blob: 6c8d99c2c5fca65c1e1787806ec3aa65bb99e98d [file] [log] [blame]
package ingestion_processors
import (
"context"
"sync"
"testing"
"time"
"go.skia.org/infra/golden/go/continuous_integration/simple_cis"
lru "github.com/hashicorp/golang-lru"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/httputils"
"go.skia.org/infra/go/paramtools"
"go.skia.org/infra/go/skerr"
"go.skia.org/infra/go/testutils"
"go.skia.org/infra/go/testutils/unittest"
"go.skia.org/infra/golden/go/clstore"
"go.skia.org/infra/golden/go/code_review"
"go.skia.org/infra/golden/go/code_review/gerrit_crs"
mock_crs "go.skia.org/infra/golden/go/code_review/mocks"
ci "go.skia.org/infra/golden/go/continuous_integration"
mock_cis "go.skia.org/infra/golden/go/continuous_integration/mocks"
"go.skia.org/infra/golden/go/ingestion"
"go.skia.org/infra/golden/go/ingestion_processors/mocks"
dks "go.skia.org/infra/golden/go/sql/datakitchensink"
"go.skia.org/infra/golden/go/sql/schema"
"go.skia.org/infra/golden/go/sql/sqltest"
"go.skia.org/infra/golden/go/types"
)
func TestTryjobSQL_SingleCRSAndCIS_Success(t *testing.T) {
unittest.SmallTest(t)
configParams := map[string]string{
codeReviewSystemsParam: "gerrit,gerrit-internal",
gerritURLParam: "https://example-review.googlesource.com",
gerritInternalURLParam: "https://example-internal-review.googlesource.com",
continuousIntegrationSystemsParam: "buildbucket",
}
ctx := gerrit_crs.TestContext(context.Background())
p, err := TryjobSQL(ctx, nil, configParams, httputils.NewTimeoutClient(), nil)
require.NoError(t, err)
require.NotNil(t, p)
gtp, ok := p.(*goldTryjobProcessor)
require.True(t, ok)
assert.Len(t, gtp.reviewSystems, 2)
assert.Len(t, gtp.cisClients, 1)
assert.Contains(t, gtp.cisClients, buildbucketCIS)
assert.Nil(t, gtp.lookupSystem)
}
func TestTryjobSQL_SingleCRSDoubleCIS_Success(t *testing.T) {
unittest.SmallTest(t)
configParams := map[string]string{
codeReviewSystemsParam: "github",
githubRepoParam: "google/skia",
githubCredentialsPathParam: "testdata/fake_token", // this is actually a file on disk.
continuousIntegrationSystemsParam: "cirrus,buildbucket",
}
ctx := gerrit_crs.TestContext(context.Background())
p, err := TryjobSQL(ctx, nil, configParams, httputils.NewTimeoutClient(), nil)
require.NoError(t, err)
require.NotNil(t, p)
gtp, ok := p.(*goldTryjobProcessor)
require.True(t, ok)
assert.Len(t, gtp.reviewSystems, 1)
assert.Len(t, gtp.cisClients, 2)
assert.Contains(t, gtp.cisClients, cirrusCIS)
assert.Contains(t, gtp.cisClients, buildbucketCIS)
assert.Nil(t, gtp.lookupSystem)
}
func TestTryjobSQL_LookupCRS_Success(t *testing.T) {
unittest.SmallTest(t)
configParams := map[string]string{
lookupParam: "buildbucket",
codeReviewSystemsParam: "gerrit",
gerritURLParam: "https://example-review.googlesource.com",
continuousIntegrationSystemsParam: "buildbucket",
}
ctx := gerrit_crs.TestContext(context.Background())
p, err := TryjobSQL(ctx, nil, configParams, httputils.NewTimeoutClient(), nil)
require.NoError(t, err)
require.NotNil(t, p)
gtp, ok := p.(*goldTryjobProcessor)
require.True(t, ok)
assert.Len(t, gtp.reviewSystems, 1)
assert.Len(t, gtp.cisClients, 1)
assert.NotNil(t, gtp.lookupSystem)
}
func TestTryjobSQL_Process_FirstFileForCL_Success(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const clID = dks.ChangelistIDThatAttemptsToFixIOS
const psID = dks.PatchSetIDFixesIPadButNotIPhone
const tjID = dks.Tryjob01IPhoneRGB
const expectedPSOrder = 3
const squareTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"square","os":"iOS","source_type":"corners"}`
const triangleTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"triangle","os":"iOS","source_type":"corners"}`
const circleTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"circle","os":"iOS","source_type":"round"}`
const qualifiedCL = "gerrit_CL_fix_ios"
const qualifiedPS = "gerrit_PS_fixes_ipad_but_not_iphone"
const qualifiedTJ = "buildbucket_tryjob_01_iphonergb"
mcrs := &mock_crs.Client{}
mcrs.On("GetChangelist", testutils.AnyContext, clID).Return(code_review.Changelist{
SystemID: clID,
Owner: dks.UserOne,
Status: code_review.Open,
Subject: "Fix iOS",
// This time should get overwritten by the fakeIngestionTime
Updated: time.Date(2020, time.December, 5, 15, 0, 0, 0, time.UTC),
}, nil)
mcrs.On("GetPatchset", testutils.AnyContext, clID, "", expectedPSOrder).Return(code_review.Patchset{
SystemID: psID,
ChangelistID: clID,
Order: expectedPSOrder,
GitHash: "ffff111111111111111111111111111111111111",
Created: time.Date(2020, time.December, 6, 6, 0, 0, 0, time.UTC),
}, nil)
mcis := &mock_cis.Client{}
mcis.On("GetTryJob", testutils.AnyContext, tjID).Return(ci.TryJob{
SystemID: tjID,
System: dks.BuildBucketCIS,
DisplayName: "Test-iPhone-RGB",
}, nil)
// This file has data from 3 traces across 2 corpora. The data is for the patchset with order 3.
src := fakeGCSSourceFromFile(t, "from_goldctl_legacy_fields.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
db: db,
source: src,
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB)
require.NoError(t, err)
actualSourceFiles := sqltest.GetAllRows(ctx, t, db, "SourceFiles", &schema.SourceFileRow{}).([]schema.SourceFileRow)
assert.Equal(t, []schema.SourceFileRow{{
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
SourceFile: dks.Tryjob01FileIPhoneRGB,
LastIngested: fakeIngestionTime,
}}, actualSourceFiles)
actualChangelists := sqltest.GetAllRows(ctx, t, db, "Changelists", &schema.ChangelistRow{}).([]schema.ChangelistRow)
assert.Equal(t, []schema.ChangelistRow{{
ChangelistID: qualifiedCL,
System: dks.GerritCRS,
Status: schema.StatusOpen,
OwnerEmail: dks.UserOne,
Subject: "Fix iOS",
LastIngestedData: fakeIngestionTime,
}}, actualChangelists)
actualPatchsets := sqltest.GetAllRows(ctx, t, db, "Patchsets", &schema.PatchsetRow{}).([]schema.PatchsetRow)
assert.Equal(t, []schema.PatchsetRow{{
PatchsetID: qualifiedPS,
System: dks.GerritCRS,
ChangelistID: qualifiedCL,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
Created: time.Date(2020, time.December, 6, 6, 0, 0, 0, time.UTC),
}}, actualPatchsets)
actualTryjobs := sqltest.GetAllRows(ctx, t, db, "Tryjobs", &schema.TryjobRow{}).([]schema.TryjobRow)
assert.Equal(t, []schema.TryjobRow{{
TryjobID: qualifiedTJ,
System: dks.BuildBucketCIS,
ChangelistID: qualifiedCL,
PatchsetID: qualifiedPS,
DisplayName: "Test-iPhone-RGB",
LastIngestedData: fakeIngestionTime,
}}, actualTryjobs)
actualGroupings := sqltest.GetAllRows(ctx, t, db, "Groupings", &schema.GroupingRow{}).([]schema.GroupingRow)
assert.ElementsMatch(t, []schema.GroupingRow{{
GroupingID: h(circleGrouping),
Keys: map[string]string{
types.CorpusField: dks.RoundCorpus,
types.PrimaryKeyField: dks.CircleTest,
},
}, {
GroupingID: h(squareGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.SquareTest,
},
}, {
GroupingID: h(triangleGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.TriangleTest,
},
}}, actualGroupings)
actualOptions := sqltest.GetAllRows(ctx, t, db, "Options", &schema.OptionsRow{}).([]schema.OptionsRow)
assert.ElementsMatch(t, []schema.OptionsRow{{
OptionsID: h(pngOptions),
Keys: map[string]string{
"ext": "png",
},
}}, actualOptions)
actualTraces := sqltest.GetAllRows(ctx, t, db, "Traces", &schema.TraceRow{}).([]schema.TraceRow)
assert.Equal(t, []schema.TraceRow{{
TraceID: h(circleTraceKeys),
Corpus: dks.RoundCorpus,
GroupingID: h(circleGrouping),
Keys: map[string]string{
types.CorpusField: dks.RoundCorpus,
types.PrimaryKeyField: dks.CircleTest,
dks.ColorModeKey: dks.RGBColorMode,
dks.OSKey: dks.IOS,
dks.DeviceKey: dks.IPhoneDevice,
},
MatchesAnyIgnoreRule: schema.NBNull,
}, {
TraceID: h(squareTraceKeys),
Corpus: dks.CornersCorpus,
GroupingID: h(squareGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.SquareTest,
dks.ColorModeKey: dks.RGBColorMode,
dks.OSKey: dks.IOS,
dks.DeviceKey: dks.IPhoneDevice,
},
MatchesAnyIgnoreRule: schema.NBNull,
}, {
TraceID: h(triangleTraceKeys),
Corpus: dks.CornersCorpus,
GroupingID: h(triangleGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.TriangleTest,
dks.ColorModeKey: dks.RGBColorMode,
dks.OSKey: dks.IOS,
dks.DeviceKey: dks.IPhoneDevice,
},
MatchesAnyIgnoreRule: schema.NBNull,
}}, actualTraces)
actualParams := sqltest.GetAllRows(ctx, t, db, "SecondaryBranchParams", &schema.SecondaryBranchParamRow{}).([]schema.SecondaryBranchParamRow)
assert.Equal(t, []schema.SecondaryBranchParamRow{
{Key: dks.ColorModeKey, Value: dks.RGBColorMode, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: dks.DeviceKey, Value: dks.IPhoneDevice, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: "ext", Value: "png", BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.PrimaryKeyField, Value: dks.CircleTest, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.PrimaryKeyField, Value: dks.SquareTest, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.PrimaryKeyField, Value: dks.TriangleTest, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: dks.OSKey, Value: dks.IOS, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.CorpusField, Value: dks.CornersCorpus, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.CorpusField, Value: dks.RoundCorpus, BranchName: qualifiedCL, VersionName: qualifiedPS},
}, actualParams)
actualValues := sqltest.GetAllRows(ctx, t, db, "SecondaryBranchValues", &schema.SecondaryBranchValueRow{}).([]schema.SecondaryBranchValueRow)
assert.ElementsMatch(t, []schema.SecondaryBranchValueRow{{
BranchName: qualifiedCL, VersionName: qualifiedPS,
TraceID: h(squareTraceKeys),
Digest: d(dks.DigestA01Pos),
GroupingID: h(squareGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}, {
BranchName: qualifiedCL, VersionName: qualifiedPS,
TraceID: h(triangleTraceKeys),
Digest: d(dks.DigestB01Pos),
GroupingID: h(triangleGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}, {
BranchName: qualifiedCL, VersionName: qualifiedPS,
TraceID: h(circleTraceKeys),
Digest: d(dks.DigestC07Unt_CL),
GroupingID: h(circleGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}}, actualValues)
// We only write to SecondaryBranchExpectations when something is explicitly triaged.
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "SecondaryBranchExpectations", &schema.SecondaryBranchExpectationRow{}))
// Unlike the primary branch ingestion, these should be empty
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "CommitsWithData", &schema.CommitWithDataRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "TraceValues", &schema.TraceValueRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "ValuesAtHead", &schema.ValueAtHeadRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "Expectations", &schema.ExpectationRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "PrimaryBranchParams", &schema.PrimaryBranchParamRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "TiledTraceDigests", &schema.TiledTraceDigestRow{}))
}
func TestTryjobSQL_Process_UsesRubberstampCRSAndSimpleCIS_Success(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const squareTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"square","os":"iOS","source_type":"corners"}`
const triangleTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"triangle","os":"iOS","source_type":"corners"}`
const circleTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"circle","os":"iOS","source_type":"round"}`
const qualifiedCL = "gerrit_CL_fix_ios"
const qualifiedRubberstampPS = "gerrit_CL_fix_ios||3"
const qualifiedTJ = "buildbucket_tryjob_01_iphonergb"
// This file has data from 3 traces across 2 corpora. The data is for the patchset with order 3.
src := fakeGCSSourceFromFile(t, "from_goldctl_legacy_fields.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: simple_cis.New(dks.BuildBucketCIS),
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: rubberstampCRS{},
},
},
db: db,
source: src,
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB)
require.NoError(t, err)
actualChangelists := sqltest.GetAllRows(ctx, t, db, "Changelists", &schema.ChangelistRow{}).([]schema.ChangelistRow)
assert.Equal(t, []schema.ChangelistRow{{
ChangelistID: qualifiedCL,
System: dks.GerritCRS,
Status: schema.StatusOpen,
OwnerEmail: "<unknown>",
Subject: "<unknown>",
LastIngestedData: fakeIngestionTime,
}}, actualChangelists)
actualPatchsets := sqltest.GetAllRows(ctx, t, db, "Patchsets", &schema.PatchsetRow{}).([]schema.PatchsetRow)
assert.Equal(t, []schema.PatchsetRow{{
PatchsetID: qualifiedRubberstampPS,
System: dks.GerritCRS,
ChangelistID: qualifiedCL,
Order: 3,
GitHash: "<unknown>",
}}, actualPatchsets)
actualTryjobs := sqltest.GetAllRows(ctx, t, db, "Tryjobs", &schema.TryjobRow{}).([]schema.TryjobRow)
assert.Equal(t, []schema.TryjobRow{{
TryjobID: qualifiedTJ,
System: dks.BuildBucketCIS,
ChangelistID: qualifiedCL,
PatchsetID: qualifiedRubberstampPS,
DisplayName: "tryjob_01_iphonergb",
LastIngestedData: fakeIngestionTime,
}}, actualTryjobs)
actualValues := sqltest.GetAllRows(ctx, t, db, "SecondaryBranchValues", &schema.SecondaryBranchValueRow{}).([]schema.SecondaryBranchValueRow)
assert.ElementsMatch(t, []schema.SecondaryBranchValueRow{{
BranchName: qualifiedCL, VersionName: qualifiedRubberstampPS,
TraceID: h(squareTraceKeys),
Digest: d(dks.DigestA01Pos),
GroupingID: h(squareGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}, {
BranchName: qualifiedCL, VersionName: qualifiedRubberstampPS,
TraceID: h(triangleTraceKeys),
Digest: d(dks.DigestB01Pos),
GroupingID: h(triangleGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}, {
BranchName: qualifiedCL, VersionName: qualifiedRubberstampPS,
TraceID: h(circleTraceKeys),
Digest: d(dks.DigestC07Unt_CL),
GroupingID: h(circleGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}}, actualValues)
}
func TestTryjobSQL_Process_SomeDataExists_Success(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const qualifiedCL = "gerrit_CL_fix_ios"
const qualifiedPS = "gerrit_PS_fixes_ipad_but_not_iphone"
const qualifiedTJ = "buildbucket_tryjob_01_iphonergb"
const squareTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"square","os":"iOS","source_type":"corners"}`
const triangleTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"triangle","os":"iOS","source_type":"corners"}`
const circleTraceKeys = `{"color mode":"RGB","device":"iPhone12,1","name":"circle","os":"iOS","source_type":"round"}`
// Load all the tables we write to with one existing row.
existingData := schema.Tables{
Changelists: []schema.ChangelistRow{{
ChangelistID: qualifiedCL,
System: dks.GerritCRS,
Status: schema.StatusOpen,
OwnerEmail: dks.UserOne,
Subject: "Fix iOS [sentinel]",
LastIngestedData: time.Time{}, // should be updated.
}},
Patchsets: []schema.PatchsetRow{{
PatchsetID: qualifiedPS,
System: dks.GerritCRS,
ChangelistID: qualifiedCL,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
CommentedOnCL: true, // sentinel values
Created: time.Date(2021, time.March, 26, 13, 6, 3, 0, time.UTC),
}},
Tryjobs: []schema.TryjobRow{{
TryjobID: qualifiedTJ,
System: dks.BuildBucketCIS,
ChangelistID: qualifiedCL,
PatchsetID: qualifiedPS,
DisplayName: "Test-iPhone-RGB-sentinel",
LastIngestedData: time.Time{}, // should be updated.
}},
Groupings: []schema.GroupingRow{{
GroupingID: h(squareGrouping),
Keys: paramtools.Params{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.SquareTest,
},
}},
Options: []schema.OptionsRow{{
OptionsID: h(pngOptions),
Keys: map[string]string{
"ext": "png",
},
}},
Traces: []schema.TraceRow{{
TraceID: h(circleTraceKeys),
Corpus: dks.RoundCorpus,
GroupingID: h(circleGrouping),
Keys: map[string]string{
types.CorpusField: dks.RoundCorpus,
types.PrimaryKeyField: dks.CircleTest,
dks.ColorModeKey: dks.RGBColorMode,
dks.OSKey: dks.IOS,
dks.DeviceKey: dks.IPhoneDevice,
},
MatchesAnyIgnoreRule: schema.NBFalse, // should not be overwritten
}},
SecondaryBranchParams: []schema.SecondaryBranchParamRow{{
Key: dks.ColorModeKey,
Value: dks.RGBColorMode,
BranchName: qualifiedCL,
VersionName: qualifiedPS,
}},
SecondaryBranchValues: []schema.SecondaryBranchValueRow{{
BranchName: qualifiedCL, VersionName: qualifiedPS,
TraceID: h(squareTraceKeys),
Digest: d(dks.DigestA01Pos),
GroupingID: h(squareGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: "Should be overwritten",
}},
SourceFiles: []schema.SourceFileRow{{
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
SourceFile: dks.Tryjob01FileIPhoneRGB,
LastIngested: time.Date(2020, time.March, 1, 1, 1, 1, 0, time.UTC),
}},
}
require.NoError(t, sqltest.BulkInsertDataTables(ctx, db, existingData))
mcrs := &mock_crs.Client{}
mcis := &mock_cis.Client{}
// This file has data from 3 traces across 2 corpora. The data is for the patchset with order 3.
src := fakeGCSSourceFromFile(t, "from_goldctl_recent_fields.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
db: db,
source: src,
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB)
require.NoError(t, err)
actualSourceFiles := sqltest.GetAllRows(ctx, t, db, "SourceFiles", &schema.SourceFileRow{}).([]schema.SourceFileRow)
assert.Equal(t, []schema.SourceFileRow{{
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
SourceFile: dks.Tryjob01FileIPhoneRGB,
LastIngested: fakeIngestionTime,
}}, actualSourceFiles)
actualChangelists := sqltest.GetAllRows(ctx, t, db, "Changelists", &schema.ChangelistRow{}).([]schema.ChangelistRow)
assert.Equal(t, []schema.ChangelistRow{{
ChangelistID: qualifiedCL,
System: dks.GerritCRS,
Status: schema.StatusOpen,
OwnerEmail: dks.UserOne,
Subject: "Fix iOS [sentinel]",
LastIngestedData: fakeIngestionTime,
}}, actualChangelists)
actualPatchsets := sqltest.GetAllRows(ctx, t, db, "Patchsets", &schema.PatchsetRow{}).([]schema.PatchsetRow)
assert.Equal(t, []schema.PatchsetRow{{
PatchsetID: qualifiedPS,
System: dks.GerritCRS,
ChangelistID: qualifiedCL,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
CommentedOnCL: true,
Created: time.Date(2021, time.March, 26, 13, 6, 3, 0, time.UTC),
}}, actualPatchsets)
actualTryjobs := sqltest.GetAllRows(ctx, t, db, "Tryjobs", &schema.TryjobRow{}).([]schema.TryjobRow)
assert.Equal(t, []schema.TryjobRow{{
TryjobID: qualifiedTJ,
System: dks.BuildBucketCIS,
ChangelistID: qualifiedCL,
PatchsetID: qualifiedPS,
DisplayName: "Test-iPhone-RGB-sentinel",
LastIngestedData: fakeIngestionTime,
}}, actualTryjobs)
actualGroupings := sqltest.GetAllRows(ctx, t, db, "Groupings", &schema.GroupingRow{}).([]schema.GroupingRow)
assert.ElementsMatch(t, []schema.GroupingRow{{
GroupingID: h(circleGrouping),
Keys: map[string]string{
types.CorpusField: dks.RoundCorpus,
types.PrimaryKeyField: dks.CircleTest,
},
}, {
GroupingID: h(squareGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.SquareTest,
},
}, {
GroupingID: h(triangleGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.TriangleTest,
},
}}, actualGroupings)
actualOptions := sqltest.GetAllRows(ctx, t, db, "Options", &schema.OptionsRow{}).([]schema.OptionsRow)
assert.ElementsMatch(t, []schema.OptionsRow{{
OptionsID: h(pngOptions),
Keys: map[string]string{
"ext": "png",
},
}}, actualOptions)
actualTraces := sqltest.GetAllRows(ctx, t, db, "Traces", &schema.TraceRow{}).([]schema.TraceRow)
assert.Equal(t, []schema.TraceRow{{
TraceID: h(circleTraceKeys),
Corpus: dks.RoundCorpus,
GroupingID: h(circleGrouping),
Keys: map[string]string{
types.CorpusField: dks.RoundCorpus,
types.PrimaryKeyField: dks.CircleTest,
dks.ColorModeKey: dks.RGBColorMode,
dks.OSKey: dks.IOS,
dks.DeviceKey: dks.IPhoneDevice,
},
MatchesAnyIgnoreRule: schema.NBFalse, // existing status not overwritten
}, {
TraceID: h(squareTraceKeys),
Corpus: dks.CornersCorpus,
GroupingID: h(squareGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.SquareTest,
dks.ColorModeKey: dks.RGBColorMode,
dks.OSKey: dks.IOS,
dks.DeviceKey: dks.IPhoneDevice,
},
MatchesAnyIgnoreRule: schema.NBNull,
}, {
TraceID: h(triangleTraceKeys),
Corpus: dks.CornersCorpus,
GroupingID: h(triangleGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.TriangleTest,
dks.ColorModeKey: dks.RGBColorMode,
dks.OSKey: dks.IOS,
dks.DeviceKey: dks.IPhoneDevice,
},
MatchesAnyIgnoreRule: schema.NBNull,
}}, actualTraces)
actualParams := sqltest.GetAllRows(ctx, t, db, "SecondaryBranchParams", &schema.SecondaryBranchParamRow{}).([]schema.SecondaryBranchParamRow)
assert.Equal(t, []schema.SecondaryBranchParamRow{
{Key: dks.ColorModeKey, Value: dks.RGBColorMode, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: dks.DeviceKey, Value: dks.IPhoneDevice, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: "ext", Value: "png", BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.PrimaryKeyField, Value: dks.CircleTest, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.PrimaryKeyField, Value: dks.SquareTest, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.PrimaryKeyField, Value: dks.TriangleTest, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: dks.OSKey, Value: dks.IOS, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.CorpusField, Value: dks.CornersCorpus, BranchName: qualifiedCL, VersionName: qualifiedPS},
{Key: types.CorpusField, Value: dks.RoundCorpus, BranchName: qualifiedCL, VersionName: qualifiedPS},
}, actualParams)
actualValues := sqltest.GetAllRows(ctx, t, db, "SecondaryBranchValues", &schema.SecondaryBranchValueRow{}).([]schema.SecondaryBranchValueRow)
assert.ElementsMatch(t, []schema.SecondaryBranchValueRow{{
BranchName: qualifiedCL, VersionName: qualifiedPS,
TraceID: h(squareTraceKeys),
Digest: d(dks.DigestA01Pos),
GroupingID: h(squareGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}, {
BranchName: qualifiedCL, VersionName: qualifiedPS,
TraceID: h(triangleTraceKeys),
Digest: d(dks.DigestB01Pos),
GroupingID: h(triangleGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}, {
BranchName: qualifiedCL, VersionName: qualifiedPS,
TraceID: h(circleTraceKeys),
Digest: d(dks.DigestC07Unt_CL),
GroupingID: h(circleGrouping),
OptionsID: h(pngOptions),
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
TryjobID: qualifiedTJ,
}}, actualValues)
// We only write to SecondaryBranchExpectations when something is explicitly triaged.
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "SecondaryBranchExpectations", &schema.SecondaryBranchExpectationRow{}))
// Unlike the primary branch ingestion, these should be empty
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "CommitsWithData", &schema.CommitWithDataRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "TraceValues", &schema.TraceValueRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "ValuesAtHead", &schema.ValueAtHeadRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "Expectations", &schema.ExpectationRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "PrimaryBranchParams", &schema.PrimaryBranchParamRow{}))
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "TiledTraceDigests", &schema.TiledTraceDigestRow{}))
}
func TestTryjobSQL_Process_PatchsetExistsAndSuppliedByOrder_Success(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const qualifiedCL = "gerrit_CL_fix_ios"
const qualifiedPS = "gerrit_PS_fixes_ipad_but_not_iphone"
const qualifiedTJ = "buildbucket_tryjob_01_iphonergb"
// Load all the tables we write to with one existing row.
existingData := schema.Tables{
Changelists: []schema.ChangelistRow{{
ChangelistID: qualifiedCL,
System: dks.GerritCRS,
Status: schema.StatusOpen,
OwnerEmail: dks.UserOne,
Subject: "Fix iOS [sentinel]",
LastIngestedData: time.Time{}, // should be updated.
}},
Patchsets: []schema.PatchsetRow{{
PatchsetID: qualifiedPS,
System: dks.GerritCRS,
ChangelistID: qualifiedCL,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
CommentedOnCL: true, // sentinel values
Created: time.Date(2021, time.March, 26, 13, 6, 3, 0, time.UTC),
}},
}
require.NoError(t, sqltest.BulkInsertDataTables(ctx, db, existingData))
mcrs := &mock_crs.Client{}
mcis := &mock_cis.Client{}
mcis.On("GetTryJob", testutils.AnyContext, dks.Tryjob01IPhoneRGB).Return(ci.TryJob{
SystemID: dks.Tryjob01IPhoneRGB,
System: dks.BuildBucketCIS,
DisplayName: "Test-iPhone-RGB",
}, nil)
// This file has data from 3 traces across 2 corpora. The data is for the patchset with order 3.
src := fakeGCSSourceFromFile(t, "from_goldctl_patchset_order_provided.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
db: db,
source: src,
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB)
require.NoError(t, err)
actualSourceFiles := sqltest.GetAllRows(ctx, t, db, "SourceFiles", &schema.SourceFileRow{}).([]schema.SourceFileRow)
assert.Equal(t, []schema.SourceFileRow{{
SourceFileID: h(dks.Tryjob01FileIPhoneRGB),
SourceFile: dks.Tryjob01FileIPhoneRGB,
LastIngested: fakeIngestionTime,
}}, actualSourceFiles)
actualChangelists := sqltest.GetAllRows(ctx, t, db, "Changelists", &schema.ChangelistRow{}).([]schema.ChangelistRow)
assert.Equal(t, []schema.ChangelistRow{{
ChangelistID: qualifiedCL,
System: dks.GerritCRS,
Status: schema.StatusOpen,
OwnerEmail: dks.UserOne,
Subject: "Fix iOS [sentinel]",
LastIngestedData: fakeIngestionTime,
}}, actualChangelists)
actualPatchsets := sqltest.GetAllRows(ctx, t, db, "Patchsets", &schema.PatchsetRow{}).([]schema.PatchsetRow)
assert.Equal(t, []schema.PatchsetRow{{
PatchsetID: qualifiedPS,
System: dks.GerritCRS,
ChangelistID: qualifiedCL,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
CommentedOnCL: true,
Created: time.Date(2021, time.March, 26, 13, 6, 3, 0, time.UTC),
}}, actualPatchsets)
actualTryjobs := sqltest.GetAllRows(ctx, t, db, "Tryjobs", &schema.TryjobRow{}).([]schema.TryjobRow)
assert.Equal(t, []schema.TryjobRow{{
TryjobID: qualifiedTJ,
System: dks.BuildBucketCIS,
ChangelistID: qualifiedCL,
PatchsetID: qualifiedPS,
DisplayName: "Test-iPhone-RGB",
LastIngestedData: fakeIngestionTime,
}}, actualTryjobs)
}
func TestTryjobSQL_Process_UnknownCL_ReturnsNonretriableError(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
mcrs := &mock_crs.Client{}
mcrs.On("GetChangelist", testutils.AnyContext, dks.ChangelistIDThatAttemptsToFixIOS).Return(code_review.Changelist{}, code_review.ErrNotFound)
mcis := &mock_cis.Client{}
src := fakeGCSSourceFromFile(t, "from_goldctl_recent_fields.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
db: db,
source: src,
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB)
require.Error(t, err)
assert.NotEqual(t, ingestion.ErrRetryable, skerr.Unwrap(err))
assert.Contains(t, err.Error(), "not found")
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "Changelists", &schema.ChangelistRow{}))
}
func TestTryjobSQL_Process_UnknownPS_ReturnsNonretriableError(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const clID = dks.ChangelistIDThatAttemptsToFixIOS
const psID = dks.PatchSetIDFixesIPadButNotIPhone
mcrs := &mock_crs.Client{}
mcrs.On("GetChangelist", testutils.AnyContext, clID).Return(code_review.Changelist{
SystemID: clID,
Owner: dks.UserOne,
Status: code_review.Open,
Subject: "Fix iOS",
Updated: time.Date(2020, time.December, 5, 15, 0, 0, 0, time.UTC),
}, nil)
mcrs.On("GetPatchset", testutils.AnyContext, clID, psID, 0).Return(code_review.Patchset{}, code_review.ErrNotFound)
mcis := &mock_cis.Client{}
src := fakeGCSSourceFromFile(t, "from_goldctl_recent_fields.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
db: db,
source: src,
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB)
require.Error(t, err)
assert.NotEqual(t, ingestion.ErrRetryable, skerr.Unwrap(err))
assert.Contains(t, err.Error(), "not found")
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "Patchsets", &schema.PatchsetRow{}))
}
func TestTryjobSQL_Process_UnknownTryjob_ReturnsNonretriableError(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const clID = dks.ChangelistIDThatAttemptsToFixIOS
const psID = dks.PatchSetIDFixesIPadButNotIPhone
const tjID = dks.Tryjob01IPhoneRGB
mcrs := &mock_crs.Client{}
mcrs.On("GetChangelist", testutils.AnyContext, clID).Return(code_review.Changelist{
SystemID: clID,
Owner: dks.UserOne,
Status: code_review.Open,
Subject: "Fix iOS",
Updated: time.Date(2020, time.December, 5, 15, 0, 0, 0, time.UTC),
}, nil)
mcrs.On("GetPatchset", testutils.AnyContext, clID, psID, 0).Return(code_review.Patchset{
SystemID: psID,
ChangelistID: clID,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
}, nil)
mcis := &mock_cis.Client{}
mcis.On("GetTryJob", testutils.AnyContext, tjID).Return(ci.TryJob{}, ci.ErrNotFound)
src := fakeGCSSourceFromFile(t, "from_goldctl_recent_fields.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
db: db,
source: src,
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB)
require.Error(t, err)
assert.NotEqual(t, ingestion.ErrRetryable, skerr.Unwrap(err))
assert.Contains(t, err.Error(), "not found")
assert.Empty(t, sqltest.GetAllRows(ctx, t, db, "Tryjobs", &schema.TryjobRow{}))
}
func TestTryjobSQL_Process_SameFileMultipleTimesInParallel_Success(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const clID = dks.ChangelistIDThatAttemptsToFixIOS
const psID = dks.PatchSetIDFixesIPadButNotIPhone
const tjID = dks.Tryjob01IPhoneRGB
const qualifiedCL = "gerrit_CL_fix_ios"
const qualifiedPS = "gerrit_PS_fixes_ipad_but_not_iphone"
const qualifiedTJ = "buildbucket_tryjob_01_iphonergb"
ctx = overwriteNow(ctx, fakeIngestionTime)
wg := sync.WaitGroup{}
for i := 0; i < 4; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mcrs := &mock_crs.Client{}
mcrs.On("GetChangelist", testutils.AnyContext, clID).Return(code_review.Changelist{
SystemID: clID,
Owner: dks.UserOne,
Status: code_review.Open,
Subject: "Fix iOS",
// This time should get overwritten by the fakeIngestionTime
Updated: time.Date(2020, time.December, 5, 15, 0, 0, 0, time.UTC),
}, nil)
mcrs.On("GetPatchset", testutils.AnyContext, clID, psID, 0).Return(code_review.Patchset{
SystemID: psID,
ChangelistID: clID,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
}, nil)
mcis := &mock_cis.Client{}
mcis.On("GetTryJob", testutils.AnyContext, tjID).Return(ci.TryJob{
SystemID: tjID,
System: dks.BuildBucketCIS,
DisplayName: "Test-iPhone-RGB",
}, nil)
src := fakeGCSSourceFromFile(t, "from_goldctl_recent_fields.json")
gtp := initCaches(goldTryjobProcessor{
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
db: db,
source: src,
})
for j := 0; j < 10; j++ {
if err := ctx.Err(); err != nil {
return
}
if err := gtp.Process(ctx, dks.Tryjob01FileIPhoneRGB); err != nil {
assert.NoError(t, err)
return
}
}
}()
}
wg.Wait()
// spot check the data to make sure it was written
actualTryjobs := sqltest.GetAllRows(ctx, t, db, "Tryjobs", &schema.TryjobRow{}).([]schema.TryjobRow)
assert.Equal(t, []schema.TryjobRow{{
TryjobID: qualifiedTJ,
System: dks.BuildBucketCIS,
ChangelistID: qualifiedCL,
PatchsetID: qualifiedPS,
DisplayName: "Test-iPhone-RGB",
LastIngestedData: fakeIngestionTime,
}}, actualTryjobs)
actualGroupings := sqltest.GetAllRows(ctx, t, db, "Groupings", &schema.GroupingRow{}).([]schema.GroupingRow)
assert.ElementsMatch(t, []schema.GroupingRow{{
GroupingID: h(circleGrouping),
Keys: map[string]string{
types.CorpusField: dks.RoundCorpus,
types.PrimaryKeyField: dks.CircleTest,
},
}, {
GroupingID: h(squareGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.SquareTest,
},
}, {
GroupingID: h(triangleGrouping),
Keys: map[string]string{
types.CorpusField: dks.CornersCorpus,
types.PrimaryKeyField: dks.TriangleTest,
},
}}, actualGroupings)
}
func TestTryjobSQL_Process_CLPSNeedResolution_Success(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
const resolvedCRS = dks.GerritCRS
const resolvedCL = dks.ChangelistIDThatAttemptsToFixIOS
const resolvedPSOrder = 3
const expectedTryjobID = dks.Tryjob01IPhoneRGB
const expectedPSID = dks.PatchSetIDFixesIPadButNotIPhone
const qualifiedCL = "gerrit_CL_fix_ios"
const qualifiedPS = "gerrit_PS_fixes_ipad_but_not_iphone"
const qualifiedTJ = "buildbucket_tryjob_01_iphonergb"
ml := &mocks.LookupSystem{}
ml.On("Lookup", testutils.AnyContext, expectedTryjobID).Return(resolvedCRS, resolvedCL, resolvedPSOrder, nil)
mcrs := &mock_crs.Client{}
mcrs.On("GetChangelist", testutils.AnyContext, resolvedCL).Return(code_review.Changelist{
SystemID: resolvedCL,
Owner: dks.UserOne,
Status: code_review.Open,
Subject: "Fix iOS",
// This time should get overwritten by the fakeIngestionTime
Updated: time.Date(2020, time.December, 5, 15, 0, 0, 0, time.UTC),
}, nil)
mcrs.On("GetPatchset", testutils.AnyContext, resolvedCL, "", resolvedPSOrder).Return(code_review.Patchset{
SystemID: expectedPSID,
ChangelistID: resolvedCL,
Order: resolvedPSOrder,
GitHash: "ffff111111111111111111111111111111111111",
}, nil)
mcis := &mock_cis.Client{}
mcis.On("GetTryJob", testutils.AnyContext, expectedTryjobID).Return(ci.TryJob{
SystemID: expectedTryjobID,
System: dks.BuildBucketCIS,
DisplayName: "Test-iPhone-RGB",
}, nil)
src := fakeGCSSourceFromFile(t, "needs_lookup.json")
gtp := initCaches(goldTryjobProcessor{
source: src,
db: db,
lookupSystem: ml,
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
})
ctx = overwriteNow(ctx, fakeIngestionTime)
require.NoError(t, gtp.Process(ctx, "needs_lookup.json"))
// Spot check the resolved data
actualChangelists := sqltest.GetAllRows(ctx, t, db, "Changelists", &schema.ChangelistRow{}).([]schema.ChangelistRow)
assert.Equal(t, []schema.ChangelistRow{{
ChangelistID: qualifiedCL,
System: dks.GerritCRS,
Status: schema.StatusOpen,
OwnerEmail: dks.UserOne,
Subject: "Fix iOS",
LastIngestedData: fakeIngestionTime,
}}, actualChangelists)
actualPatchsets := sqltest.GetAllRows(ctx, t, db, "Patchsets", &schema.PatchsetRow{}).([]schema.PatchsetRow)
assert.Equal(t, []schema.PatchsetRow{{
PatchsetID: qualifiedPS,
System: dks.GerritCRS,
ChangelistID: qualifiedCL,
Order: 3,
GitHash: "ffff111111111111111111111111111111111111",
}}, actualPatchsets)
actualTryjobs := sqltest.GetAllRows(ctx, t, db, "Tryjobs", &schema.TryjobRow{}).([]schema.TryjobRow)
assert.Equal(t, []schema.TryjobRow{{
TryjobID: qualifiedTJ,
System: dks.BuildBucketCIS,
ChangelistID: qualifiedCL,
PatchsetID: qualifiedPS,
DisplayName: "Test-iPhone-RGB",
LastIngestedData: fakeIngestionTime,
}}, actualTryjobs)
}
func TestTryjobSQL_Process_CLPSNeedResolution_UsesCache(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
require.NoError(t, sqltest.BulkInsertDataTables(ctx, db, dks.Build()))
const resolvedCRS = dks.GerritCRS
const resolvedCL = dks.ChangelistIDThatAttemptsToFixIOS
const resolvedPSOrder = 3
const expectedTryjobID = dks.Tryjob01IPhoneRGB
ml := &mocks.LookupSystem{}
ml.On("Lookup", testutils.AnyContext, expectedTryjobID).
Return(resolvedCRS, resolvedCL, resolvedPSOrder, nil).Once() // Will fail if not cached
mcrs := &mock_crs.Client{}
mcis := &mock_cis.Client{}
src := fakeGCSSourceFromFile(t, "needs_lookup.json")
gtp := initCaches(goldTryjobProcessor{
source: src,
db: db,
lookupSystem: ml,
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
})
ctx = overwriteNow(ctx, fakeIngestionTime)
require.NoError(t, gtp.Process(ctx, "needs_lookup.json"))
require.NoError(t, gtp.Process(ctx, "needs_lookup.json"))
require.NoError(t, gtp.Process(ctx, "needs_lookup.json"))
require.NoError(t, gtp.Process(ctx, "needs_lookup.json"))
}
func TestTryjobSQL_Process_LookupSystemNotConfigured_ReturnsError(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
mcrs := &mock_crs.Client{}
mcis := &mock_cis.Client{}
src := fakeGCSSourceFromFile(t, "needs_lookup.json")
gtp := initCaches(goldTryjobProcessor{
source: src,
db: db,
reviewSystems: []clstore.ReviewSystem{
{
ID: gerritCRS,
Client: mcrs,
},
},
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, "needs_lookup.json")
require.Error(t, err)
assert.Contains(t, err.Error(), "not configured")
}
func TestTryjobSQL_Process_LookupReturnsDifferentSystem_ReturnsError(t *testing.T) {
unittest.LargeTest(t)
ctx := context.Background()
db := sqltest.NewCockroachDBForTestsWithProductionSchema(ctx, t)
ml := &mocks.LookupSystem{}
ml.On("Lookup", testutils.AnyContext, mock.Anything).Return("incorrect CRS", "whatever", 6, nil)
mcrs := &mock_crs.Client{}
mcis := &mock_cis.Client{}
src := fakeGCSSourceFromFile(t, "needs_lookup.json")
gtp := initCaches(goldTryjobProcessor{
source: src,
db: db,
lookupSystem: ml,
reviewSystems: []clstore.ReviewSystem{
{
ID: "gerrit",
Client: mcrs,
},
},
cisClients: map[string]ci.Client{
buildbucketCIS: mcis,
},
})
ctx = overwriteNow(ctx, fakeIngestionTime)
err := gtp.Process(ctx, "needs_lookup.json")
require.Error(t, err)
assert.Contains(t, err.Error(), "after lookup")
}
func initCaches(processor goldTryjobProcessor) goldTryjobProcessor {
ogCache, err := lru.New(optionsGroupingCacheSize)
if err != nil {
panic(err) // should only throw error on invalid size
}
paramsCache, err := lru.New(paramsCacheSize)
if err != nil {
panic(err) // should only throw error on invalid size
}
tCache, err := lru.New(traceCacheSize)
if err != nil {
panic(err) // should only throw error on invalid size
}
clCache, err := lru.New(clCacheSize)
if err != nil {
panic(err) // should only throw error on invalid size
}
processor.optionGroupingCache = ogCache
processor.paramsCache = paramsCache
processor.traceCache = tCache
processor.clCache = clCache
return processor
}