package sql import ( "context" "os" "testing" "time" _ "github.com/jackc/pgx/v4/stdlib" // nolint:revive necessary for db driver "gotest.tools/v3/assert" "edge-infra.dev/pkg/f8n/devinfra/testinfra/model" "edge-infra.dev/pkg/f8n/devinfra/testinfra/sql" "edge-infra.dev/pkg/f8n/devinfra/testinfra/sql/schema" "edge-infra.dev/test/f2" pg "edge-infra.dev/test/f2/x/postgres" ) var ( f f2.Framework ) const ( selectCountJobs = ` SELECT Count(*) FROM edge_jobs; ` selectCountMetadata = ` SELECT Count(*) FROM edge_job_metadatas; ` selectCountTests = ` SELECT Count(*) FROM edge_job_tests; ` deleteJob = "DELETE FROM edge_jobs WHERE number = $1 RETURNING number" ) func TestMain(m *testing.M) { f = f2.New(context.Background(), f2.WithExtensions( pg.New(), ), ) os.Exit(f.Run(m)) } func TestTestInfra(t *testing.T) { feat := f2.NewFeature("Test schema can be added"). Setup("setup schema", func(ctx f2.Context, t *testing.T) f2.Context { db := pg.FromContextT(ctx, t).DB() file, err := schema.SQL.ReadFile("schema.sql") assert.NilError(t, err) _, err = db.Exec(string(file)) assert.NilError(t, err) return ctx }).Test("db is empty", func(ctx f2.Context, t *testing.T) f2.Context { // probably worthless test but makes me feel better pg := pg.FromContextT(ctx, t) db := pg.DB() rows, err := db.QueryContext(ctx, selectCountJobs) assert.NilError(t, err) var count int for rows.Next() { err = rows.Scan(&count) assert.NilError(t, err) } assert.Equal(t, count, 0) return ctx }).Test("insert data from 48 hours ago", func(ctx f2.Context, t *testing.T) f2.Context { // add a new job which ran 48 hours ago pg := pg.FromContextT(ctx, t) db := pg.DB() dbHandle := &sql.DBHandle{DB: db} job := model.EdgeJob{ Number: "4568537873", Repos: "edge-test", Job: "verify", Workflow: "hack", Started: time.Now().AddDate(0, 0, -2), TestsRun: 15, TestsFailed: 0, } pastJobID, err := dbHandle.InsertEdgeJob(ctx, job) assert.NilError(t, err) meta := model.EdgeJobMetadata{ EdgeJob: pastJobID, Key: "a", Value: "b", } _, err = dbHandle.InsertEdgeJobMetadata(ctx, meta) assert.NilError(t, err) testCase := model.EdgeJobTest{ EdgeJob: pastJobID, Name: "test-1", Suite: "suite 1", Time: 300, Failed: true, FailureText: "failed because of reasons", } _, err = dbHandle.InsertEdgeJobTest(ctx, testCase) assert.NilError(t, err) return ctx }).Test("insert present data", func(ctx f2.Context, t *testing.T) f2.Context { // insert a job with a timestamp of now // with 3 metadata entries // and 5 tests pg := pg.FromContextT(ctx, t) db := pg.DB() dbHandle := &sql.DBHandle{DB: db} job := model.EdgeJob{ Number: "4568537872", Repos: "edge-test", Workflow: "pre", Job: "ci", Started: time.Now(), TestsRun: 14, TestsFailed: 14, } jobID, err := dbHandle.InsertEdgeJob(ctx, job) assert.NilError(t, err) t.Logf("jobID: %s \n", jobID) meta := model.EdgeJobMetadata{ EdgeJob: jobID, Key: "foo", Value: "bar", } _, err = dbHandle.InsertEdgeJobMetadata(ctx, meta) assert.NilError(t, err) meta = model.EdgeJobMetadata{ EdgeJob: jobID, Key: "boo", Value: "hoo", } _, err = dbHandle.InsertEdgeJobMetadata(ctx, meta) assert.NilError(t, err) meta = model.EdgeJobMetadata{ EdgeJob: jobID, Key: "care", Value: "bear", } _, err = dbHandle.InsertEdgeJobMetadata(ctx, meta) assert.NilError(t, err) testCase := model.EdgeJobTest{ EdgeJob: jobID, Name: "chill test", Suite: "chill suite", Time: 10, Failed: true, FailureText: "failed to keep it chill", } _, err = dbHandle.InsertEdgeJobTest(ctx, testCase) assert.NilError(t, err) testCase = model.EdgeJobTest{ EdgeJob: jobID, Name: "unchill test", Suite: "unchill suite", Time: 30, Failed: false, FailureText: "successfully kept it unchill", } _, err = dbHandle.InsertEdgeJobTest(ctx, testCase) assert.NilError(t, err) testCase = model.EdgeJobTest{ EdgeJob: jobID, Name: "test-a", Suite: "suite a", Time: 300, Failed: true, FailureText: "failed because reason: a", } _, err = dbHandle.InsertEdgeJobTest(ctx, testCase) assert.NilError(t, err) testCase = model.EdgeJobTest{ EdgeJob: jobID, Name: "test-b", Suite: "suite b", Time: 600, Failed: true, FailureText: "failed because reason: b", } _, err = dbHandle.InsertEdgeJobTest(ctx, testCase) assert.NilError(t, err) testCase = model.EdgeJobTest{ EdgeJob: jobID, Name: "test-c", Suite: "suite c", Time: 900, Failed: true, FailureText: "failed because reason: c", } _, err = dbHandle.InsertEdgeJobTest(ctx, testCase) assert.NilError(t, err) run, err := dbHandle.GetEdgeJob(ctx, "4568537872") assert.NilError(t, err) assert.Equal(t, run.Job.Number, "4568537872") assert.Equal(t, len(run.Metadata), 3) assert.Equal(t, len(run.Tests), 5) assert.Equal( t, run.Job.GCPURL, "https://console.cloud.google.com/storage/browser/edge-test-jobs/actions/edge-test/pre/4568537872/ci", "job has incorrect gcp bucket link", ) _, err = dbHandle.GetRecentEdgeJobRuns("edge-test", "pre", "ci") assert.NilError(t, err) return ctx }).Test("get todays jobs", func(ctx f2.Context, t *testing.T) f2.Context { pg := pg.FromContextT(ctx, t) db := pg.DB() dbHandle := &sql.DBHandle{DB: db} tests, err := dbHandle.GetTodaysEdgeJobs() assert.NilError(t, err) assert.Equal(t, len(tests), 1) return ctx }).Test("insert duplicate data", func(ctx f2.Context, t *testing.T) f2.Context { pg := pg.FromContextT(ctx, t) db := pg.DB() dbHandle := &sql.DBHandle{DB: db} // matches the number from present data job := model.EdgeJob{ Number: "4568537872", Repos: "edge-test", Workflow: "pre", Job: "ci", Started: time.Now(), TestsRun: 14, TestsFailed: 14, } _, err := dbHandle.InsertEdgeJob(ctx, job) assert.Error(t, err, "Value already exists in table") return ctx }).Test("cascade delete", func(ctx f2.Context, t *testing.T) f2.Context { pg := pg.FromContextT(ctx, t) db := pg.DB() // check jobs count rows, err := db.QueryContext(ctx, selectCountJobs) assert.NilError(t, err) var count int for rows.Next() { err = rows.Scan(&count) assert.NilError(t, err) } assert.Equal(t, count, 2) // check metadata count rows, err = db.QueryContext(ctx, selectCountMetadata) assert.NilError(t, err) for rows.Next() { err = rows.Scan(&count) assert.NilError(t, err) } assert.Equal(t, count, 4) // check tests count rows, err = db.QueryContext(ctx, selectCountTests) assert.NilError(t, err) for rows.Next() { err = rows.Scan(&count) assert.NilError(t, err) } assert.Equal(t, count, 6) rows, err = db.QueryContext(ctx, deleteJob, "4568537872") assert.NilError(t, err) var number string for rows.Next() { err = rows.Scan(&number) assert.NilError(t, err) } assert.Equal(t, count, 6) assert.Equal(t, number, "4568537872") // check jobs count after delete rows, err = db.QueryContext(ctx, selectCountJobs) assert.NilError(t, err) for rows.Next() { err = rows.Scan(&count) assert.NilError(t, err) } assert.Equal(t, count, 1) // check metadata count after delete rows, err = db.QueryContext(ctx, selectCountMetadata) assert.NilError(t, err) for rows.Next() { err = rows.Scan(&count) assert.NilError(t, err) } assert.Equal(t, count, 1) // check tests count after delete rows, err = db.QueryContext(ctx, selectCountTests) assert.NilError(t, err) for rows.Next() { err = rows.Scan(&count) assert.NilError(t, err) } assert.Equal(t, count, 1) return ctx }).Feature() f.Test(t, feat) }