| package ingestion_processors |
| |
| import ( |
| "context" |
| "encoding/json" |
| "errors" |
| "testing" |
| "time" |
| |
| "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/testutils" |
| "go.skia.org/infra/go/testutils/unittest" |
| "go.skia.org/infra/golden/go/clstore" |
| mock_clstore "go.skia.org/infra/golden/go/clstore/mocks" |
| "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" |
| ingestion_mocks "go.skia.org/infra/golden/go/ingestion/mocks" |
| "go.skia.org/infra/golden/go/jsonio" |
| "go.skia.org/infra/golden/go/tjstore" |
| mock_tjstore "go.skia.org/infra/golden/go/tjstore/mocks" |
| "go.skia.org/infra/golden/go/types" |
| ) |
| |
| const ( |
| legacyGoldCtlFile = "testdata/legacy-tryjob-goldctl.json" |
| githubGoldCtlFile = "testdata/github-goldctl.json" |
| ) |
| |
| func TestGerritBuildbucketFactory(t *testing.T) { |
| unittest.LargeTest(t) // should use the emulator |
| unittest.RequiresFirestoreEmulator(t) |
| |
| config := ingestion.Config{ |
| ExtraParams: map[string]string{ |
| firestoreProjectIDParam: "should-use-emulator", |
| firestoreNamespaceParam: "testing", |
| |
| 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 := newModularTryjobProcessor(ctx, nil, config, 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) |
| } |
| |
| func TestGitHubCirrusBuildbucketFactory(t *testing.T) { |
| unittest.LargeTest(t) // should use the emulator |
| unittest.RequiresFirestoreEmulator(t) |
| |
| config := ingestion.Config{ |
| ExtraParams: map[string]string{ |
| firestoreProjectIDParam: "should-use-emulator", |
| firestoreNamespaceParam: "testing", |
| |
| 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 := newModularTryjobProcessor(ctx, nil, config, 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) |
| } |
| |
| // TestTryJobProcessFreshStartSunnyDay tests the scenario in which we see data uploaded to Gerrit |
| // for a brand new CL, PS, and TryJob. There are no ignore rules and the known digests don't contain |
| // gerritDigest. |
| func TestTryJobProcessFreshStartSunnyDay(t *testing.T) { |
| unittest.SmallTest(t) |
| mcls := makeEmptyCLStore() |
| mtjs := makeEmptyTJStore() |
| defer mcls.AssertExpectations(t) |
| defer mtjs.AssertExpectations(t) |
| |
| mcls.On("PutChangelist", testutils.AnyContext, clWithUpdatedTime(t, gerritCLID, gerritCLDate)).Return(nil).Twice() |
| mcls.On("PutPatchset", testutils.AnyContext, makeGerritPatchset()).Return(nil).Once() |
| |
| mtjs.On("PutTryJob", testutils.AnyContext, gerritCombinedID, makeGerritBuildbucketTryJob()).Return(nil).Once() |
| mtjs.On("PutResults", testutils.AnyContext, gerritCombinedID, legacyGoldCtlFile, makeTryJobResults(), anyTime).Return(nil).Once() |
| |
| gtp := goldTryjobProcessor{ |
| cisClients: makeBuildbucketCIS(), |
| reviewSystems: []clstore.ReviewSystem{ |
| { |
| ID: gerritCRS, |
| Client: makeGerritCRS(), |
| Store: mcls, |
| // URLTemplate unused here |
| }, |
| }, |
| tryJobStore: mtjs, |
| } |
| |
| fsResult, err := ingestion_mocks.MockResultFileLocationFromFile(legacyGoldCtlFile) |
| require.NoError(t, err) |
| |
| err = gtp.Process(context.Background(), fsResult) |
| require.NoError(t, err) |
| } |
| |
| // TestTryJobProcessFreshStartGitHub tests the scenario in which we see data uploaded to GitHub for |
| // a brand new CL, PS, and TryJob. The PS is derived by id, not by order. The uploaded digest |
| // was not previously seen or triaged on master and is not covered by an ignore rule, so the |
| // created Patchset object should be marked as having UntriagedDigests. |
| func TestTryJobProcessFreshStartGitHub(t *testing.T) { |
| unittest.SmallTest(t) |
| mcls := makeEmptyCLStore() |
| mtjs := makeEmptyTJStore() |
| // We want to assert that the Process calls each of PutChangelist, PutPatchset, and PutTryJob |
| // with the new, correct objects object. Further, it should call PutResults with the |
| // appropriate TryJobResults. |
| defer mcls.AssertExpectations(t) |
| defer mtjs.AssertExpectations(t) |
| |
| mcls.On("PutChangelist", testutils.AnyContext, clWithUpdatedTime(t, githubCLID, makeGitHubCirrusTryJob().Updated)).Return(nil) |
| mcls.On("PutPatchset", testutils.AnyContext, code_review.Patchset{ |
| SystemID: githubPSID, |
| ChangelistID: githubCLID, |
| Order: githubPSOrder, |
| GitHash: githubPSID, |
| }).Return(nil).Once() |
| |
| combinedID := tjstore.CombinedPSID{CL: githubCLID, PS: githubPSID, CRS: "github"} |
| mtjs.On("PutTryJob", testutils.AnyContext, combinedID, makeGitHubCirrusTryJob()).Return(nil) |
| mtjs.On("PutResults", testutils.AnyContext, combinedID, githubGoldCtlFile, makeGitHubTryJobResults(), anyTime).Return(nil) |
| |
| gtp := goldTryjobProcessor{ |
| cisClients: makeCirrusCIS(), |
| reviewSystems: []clstore.ReviewSystem{ |
| { |
| ID: githubCRS, |
| Client: makeGitHubCRS(), |
| Store: mcls, |
| // URLTemplate unused here |
| }, |
| }, |
| tryJobStore: mtjs, |
| } |
| |
| fsResult, err := ingestion_mocks.MockResultFileLocationFromFile(githubGoldCtlFile) |
| require.NoError(t, err) |
| |
| err = gtp.Process(context.Background(), fsResult) |
| require.NoError(t, err) |
| } |
| |
| // TestProcess_MultipleCIS_CorrectlyLooksUpTryJobs processes three results from different CIS |
| // (and has the CIS return an error to short-circuit the process code) and verifies that the |
| // two CIS we knew about were correctly contacted and the result with an unknown CIS was ignored. |
| func TestProcess_MultipleCIS_CorrectlyLooksUpTryJobs(t *testing.T) { |
| unittest.SmallTest(t) |
| mcls := &mock_clstore.Store{} |
| // We can return whatever here, since we plan to error out when the tryjob gets read. |
| mcls.On("GetChangelist", testutils.AnyContext, githubCLID).Return(makeChangelist(), nil) |
| mcls.On("GetPatchset", testutils.AnyContext, githubCLID, githubPSID).Return(makeGerritPatchsets()[0], nil) |
| |
| bbClient := &mock_cis.Client{} |
| bbClient.On("GetTryJob", testutils.AnyContext, mock.Anything).Return(ci.TryJob{}, errors.New("buildbucket error")).Once() |
| defer bbClient.AssertExpectations(t) // make sure GetTryJob is called exactly once. |
| |
| cirrusClient := &mock_cis.Client{} |
| cirrusClient.On("GetTryJob", testutils.AnyContext, mock.Anything).Return(ci.TryJob{}, errors.New("cirrus error")).Once() |
| defer cirrusClient.AssertExpectations(t) // make sure GetTryJob is called exactly once. |
| |
| errorfulCISClients := map[string]ci.Client{ |
| buildbucketCIS: bbClient, |
| cirrusCIS: cirrusClient, |
| } |
| |
| gtp := goldTryjobProcessor{ |
| cisClients: errorfulCISClients, |
| reviewSystems: []clstore.ReviewSystem{ |
| { |
| ID: githubCRS, |
| Store: mcls, |
| // Client, URLTemplate unused here |
| }, |
| }, |
| tryJobStore: makeEmptyTJStore(), |
| } |
| |
| err := gtp.Process(context.Background(), githubIngestionResultFromCIS(t, buildbucketCIS)) |
| require.Error(t, err) |
| assert.Contains(t, err.Error(), "buildbucket error") |
| |
| err = gtp.Process(context.Background(), githubIngestionResultFromCIS(t, cirrusCIS)) |
| require.Error(t, err) |
| assert.Contains(t, err.Error(), "cirrus error") |
| |
| err = gtp.Process(context.Background(), githubIngestionResultFromCIS(t, "unknown")) |
| require.Error(t, err) |
| assert.Equal(t, err, ingestion.IgnoreResultsFileErr) |
| } |
| |
| func githubIngestionResultFromCIS(t *testing.T, cis string) ingestion.ResultFileLocation { |
| // We provide the bare minimum to be a valid result |
| gr := jsonio.GoldResults{ |
| Key: map[string]string{ |
| types.CorpusField: "arbitrary", |
| }, |
| Results: []*jsonio.Result{ |
| { |
| Key: map[string]string{ |
| types.PrimaryKeyField: "whatever", |
| }, |
| // arbitrary, yet valid, md5 hash |
| Digest: "46eb78c9711cb79197d47f448ba51338", |
| }, |
| }, |
| // arbitrary, yet valid, sha1 (git) hash |
| GitHash: "6eb2b22a052a9913fe3b9170fc217e84def40598", |
| ChangelistID: githubCLID, |
| PatchsetID: githubPSID, |
| CodeReviewSystem: githubCRS, |
| TryJobID: "whatever", |
| ContinuousIntegrationSystem: cis, |
| } |
| b, err := json.Marshal(gr) |
| require.NoError(t, err) |
| |
| // These two fields are arbitrary and don't affect the test. |
| const name = "does not matter" |
| ts := time.Date(2020, time.January, 2, 3, 4, 5, 0, time.UTC) |
| |
| return ingestion_mocks.MockResultFileLocationWithContent(name, b, ts) |
| } |
| |
| // TestTryJobProcessCLExistsSunnyDay tests that the ingestion works when the CL already exists. |
| func TestTryJobProcessCLExistsSunnyDay(t *testing.T) { |
| unittest.SmallTest(t) |
| mcls := &mock_clstore.Store{} |
| mtjs := makeEmptyTJStore() |
| // We want to assert that the Process calls PutChangelist (with updated time), PutPatchset |
| // (with the correct new object), PutTryJob with the new TryJob object and PutResults with |
| // the appropriate TryJobResults. |
| defer mcls.AssertExpectations(t) |
| defer mtjs.AssertExpectations(t) |
| |
| mcls.On("GetChangelist", testutils.AnyContext, gerritCLID).Return(makeChangelist(), nil) |
| mcls.On("GetPatchsetByOrder", testutils.AnyContext, gerritCLID, gerritPSOrder).Return(code_review.Patchset{}, clstore.ErrNotFound) |
| mcls.On("PutPatchset", testutils.AnyContext, makeGerritPatchset()).Return(nil) |
| mcls.On("PutChangelist", testutils.AnyContext, clWithUpdatedTime(t, gerritCLID, gerritCLDate)).Return(nil) |
| |
| mtjs.On("PutTryJob", testutils.AnyContext, gerritCombinedID, makeGerritBuildbucketTryJob()).Return(nil) |
| mtjs.On("PutResults", testutils.AnyContext, gerritCombinedID, |
| legacyGoldCtlFile, makeTryJobResults(), anyTime).Return(nil) |
| |
| gtp := goldTryjobProcessor{ |
| cisClients: makeBuildbucketCIS(), |
| reviewSystems: []clstore.ReviewSystem{ |
| { |
| ID: gerritCRS, |
| Client: makeGerritCRS(), |
| Store: mcls, |
| // URLTemplate unused here |
| }, |
| }, |
| tryJobStore: mtjs, |
| } |
| |
| fsResult, err := ingestion_mocks.MockResultFileLocationFromFile(legacyGoldCtlFile) |
| require.NoError(t, err) |
| |
| err = gtp.Process(context.Background(), fsResult) |
| require.NoError(t, err) |
| } |
| |
| // TestTryJobProcessCLExistsPreviouslyAbandoned tests that the ingestion works when the |
| // CL already exists, but was marked abandoned at some point (and presumably was re-opened). |
| func TestTryJobProcessCLExistsPreviouslyAbandoned(t *testing.T) { |
| unittest.SmallTest(t) |
| mcls := &mock_clstore.Store{} |
| mtjs := makeEmptyTJStore() |
| // We want to assert that the Process calls PutChangelist (with updated time and no longer |
| // abandoned), PutPatchset with the new object, PutTryJob with the new TryJob object, |
| // and PutResults with the appropriate TryJobResults. |
| defer mcls.AssertExpectations(t) |
| defer mtjs.AssertExpectations(t) |
| |
| cl := makeChangelist() |
| cl.Status = code_review.Abandoned |
| mcls.On("GetChangelist", testutils.AnyContext, gerritCLID).Return(cl, nil) |
| mcls.On("GetPatchsetByOrder", testutils.AnyContext, gerritCLID, gerritPSOrder).Return(code_review.Patchset{}, clstore.ErrNotFound) |
| mcls.On("PutPatchset", testutils.AnyContext, makeGerritPatchset()).Return(nil) |
| mcls.On("PutChangelist", testutils.AnyContext, clWithUpdatedTime(t, gerritCLID, gerritCLDate)).Return(nil) |
| |
| mtjs.On("PutTryJob", testutils.AnyContext, gerritCombinedID, makeGerritBuildbucketTryJob()).Return(nil) |
| mtjs.On("PutResults", testutils.AnyContext, gerritCombinedID, |
| legacyGoldCtlFile, makeTryJobResults(), anyTime).Return(nil) |
| |
| gtp := goldTryjobProcessor{ |
| cisClients: makeBuildbucketCIS(), |
| reviewSystems: []clstore.ReviewSystem{ |
| { |
| ID: gerritCRS, |
| Client: makeGerritCRS(), |
| Store: mcls, |
| // URLTemplate unused here |
| }, |
| }, |
| tryJobStore: mtjs, |
| } |
| |
| fsResult, err := ingestion_mocks.MockResultFileLocationFromFile(legacyGoldCtlFile) |
| require.NoError(t, err) |
| |
| err = gtp.Process(context.Background(), fsResult) |
| require.NoError(t, err) |
| } |
| |
| // TestTryJobProcessPSExistsSunnyDay tests that the ingestion works when the |
| // CL and the PS already exists. |
| func TestTryJobProcessPSExistsSunnyDay(t *testing.T) { |
| unittest.SmallTest(t) |
| mcls := &mock_clstore.Store{} |
| mtjs := makeEmptyTJStore() |
| // We want to assert that the Process calls PutChangelist and PutPatchset (with updated times), |
| // PutTryJob with the new TryJob object, and PutResults with the appropriate TryJobResults. |
| defer mcls.AssertExpectations(t) |
| defer mtjs.AssertExpectations(t) |
| |
| mcls.On("GetChangelist", testutils.AnyContext, gerritCLID).Return(makeChangelist(), nil) |
| mcls.On("GetPatchsetByOrder", testutils.AnyContext, gerritCLID, gerritPSOrder).Return(makeGerritPatchset(), nil) |
| mcls.On("PutChangelist", testutils.AnyContext, clWithUpdatedTime(t, gerritCLID, gerritCLDate)).Return(nil) |
| mcls.On("PutPatchset", testutils.AnyContext, makeGerritPatchset()).Return(nil) |
| |
| mtjs.On("PutTryJob", testutils.AnyContext, gerritCombinedID, makeGerritBuildbucketTryJob()).Return(nil) |
| mtjs.On("PutResults", testutils.AnyContext, gerritCombinedID, |
| legacyGoldCtlFile, makeTryJobResults(), anyTime).Return(nil) |
| |
| gtp := goldTryjobProcessor{ |
| cisClients: makeBuildbucketCIS(), |
| reviewSystems: []clstore.ReviewSystem{ |
| { |
| ID: gerritCRS, |
| Store: mcls, |
| // Client, URLTemplate unused here |
| }, |
| }, |
| tryJobStore: mtjs, |
| } |
| |
| fsResult, err := ingestion_mocks.MockResultFileLocationFromFile(legacyGoldCtlFile) |
| require.NoError(t, err) |
| |
| err = gtp.Process(context.Background(), fsResult) |
| require.NoError(t, err) |
| } |
| |
| func makeEmptyCLStore() *mock_clstore.Store { |
| mcls := &mock_clstore.Store{} |
| mcls.On("GetChangelist", testutils.AnyContext, mock.Anything).Return(code_review.Changelist{}, clstore.ErrNotFound).Maybe() |
| mcls.On("GetPatchsetByOrder", testutils.AnyContext, mock.Anything, mock.Anything).Return(code_review.Patchset{}, clstore.ErrNotFound).Maybe() |
| mcls.On("GetPatchset", testutils.AnyContext, mock.Anything, mock.Anything).Return(code_review.Patchset{}, clstore.ErrNotFound).Maybe() |
| |
| return mcls |
| } |
| |
| func makeEmptyTJStore() *mock_tjstore.Store { |
| mtjs := &mock_tjstore.Store{} |
| mtjs.On("GetTryJob", testutils.AnyContext, mock.Anything, mock.Anything).Return(ci.TryJob{}, tjstore.ErrNotFound).Maybe() |
| return mtjs |
| } |
| |
| // Below is the gerrit data that belongs to legacyGoldCtlFile. It doesn't need to be a super |
| // complex example because we have tests that test parseDMResults directly. |
| const ( |
| gerritCLID = "1762193" |
| gerritPSID = "e1681c90cf6a4c3b6be2bc4b4cea59849c16a438" |
| gerritPSOrder = 2 |
| gerritTJID = "8904604368086838672" |
| ) |
| |
| var ( |
| gerritCombinedID = tjstore.CombinedPSID{CL: gerritCLID, PS: gerritPSID, CRS: gerritCRS} |
| |
| gerritCLDate = time.Date(2019, time.August, 19, 18, 17, 16, 0, time.UTC) |
| |
| anyTime = mock.MatchedBy(func(time.Time) bool { return true }) |
| ) |
| |
| // These are functions to avoid mutations causing issues for future tests/checks |
| func makeTryJobResults() []tjstore.TryJobResult { |
| return []tjstore.TryJobResult{ |
| { |
| TryjobID: gerritTJID, |
| System: buildbucketCIS, |
| Digest: "690f72c0b56ae014c8ac66e7f25c0779", |
| GroupParams: paramtools.Params{ |
| "device_id": "0x1cb3", |
| "device_string": "None", |
| "msaa": "True", |
| "vendor_id": "0x10de", |
| "vendor_string": "None", |
| }, |
| ResultParams: paramtools.Params{ |
| "name": "Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing", |
| "source_type": "chrome-gpu", |
| }, |
| Options: paramtools.Params{ |
| "ext": "png", |
| }, |
| }, |
| } |
| } |
| |
| func makeChangelist() code_review.Changelist { |
| return code_review.Changelist{ |
| SystemID: "1762193", |
| Owner: "test@example.com", |
| Status: code_review.Open, |
| Subject: "initial commit", |
| Updated: gerritCLDate, |
| } |
| } |
| |
| // clWithUpdatedTime returns a matcher that will assert the CL has properly had its Updated field |
| // updated. |
| func clWithUpdatedTime(t *testing.T, clID string, originalDate time.Time) interface{} { |
| return mock.MatchedBy(func(cl code_review.Changelist) bool { |
| assert.Equal(t, clID, cl.SystemID) |
| assert.Equal(t, code_review.Open, cl.Status) |
| // If the CL is being stored with the sentinel value, we can ignore the time check. |
| if !cl.Updated.IsZero() { |
| // Make sure the time is updated to be later than the original one (which was in November |
| // or August, depending on the testcase). Since this test was authored after 1 Dec 2019 and |
| // the Updated is set to time.Now(), we can just check that we are after then. |
| assert.True(t, cl.Updated.After(originalDate)) |
| } |
| |
| // assert messages are easier to debug than "not matched" errors, so say that we matched, |
| // but know the test will fail if any of the above asserts fail. |
| return true |
| }) |
| } |
| |
| func makeGerritPatchsets() []code_review.Patchset { |
| return []code_review.Patchset{ |
| { |
| SystemID: "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1", |
| ChangelistID: "1762193", |
| Order: 1, |
| GitHash: "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1", |
| }, |
| { |
| SystemID: gerritPSID, |
| ChangelistID: "1762193", |
| Order: gerritPSOrder, |
| GitHash: gerritPSID, |
| }, |
| { |
| SystemID: "b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2", |
| ChangelistID: "1762193", |
| Order: 3, |
| GitHash: "b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2", |
| }, |
| } |
| } |
| |
| func makeGerritPatchset() code_review.Patchset { |
| ps := makeGerritPatchsets()[1] |
| return ps |
| } |
| |
| func makeGerritBuildbucketTryJob() ci.TryJob { |
| return ci.TryJob{ |
| SystemID: gerritTJID, |
| System: buildbucketCIS, |
| DisplayName: "my-task", |
| Updated: time.Date(2019, time.August, 19, 18, 20, 10, 0, time.UTC), |
| } |
| } |
| |
| func makeBuildbucketCIS() map[string]ci.Client { |
| mcis := &mock_cis.Client{} |
| mcis.On("GetTryJob", testutils.AnyContext, gerritTJID).Return(makeGerritBuildbucketTryJob(), nil) |
| return map[string]ci.Client{ |
| buildbucketCIS: mcis, |
| } |
| } |
| |
| func makeGerritCRS() *mock_crs.Client { |
| mcrs := &mock_crs.Client{} |
| mcrs.On("GetChangelist", testutils.AnyContext, gerritCLID).Return(makeChangelist(), nil) |
| mcrs.On("GetPatchset", testutils.AnyContext, gerritCLID, mock.Anything, mock.Anything).Return(makeGerritPatchsets()[1], nil) |
| return mcrs |
| } |
| |
| // Below is the gerrit data that belongs to githubGoldCtlFile, which is based on real data. |
| const ( |
| githubCLID = "44474" |
| githubPSOrder = 1 |
| githubPSID = "fe1cad6c1a5d6dc7cea47f09efdd49f197a7f017" |
| githubTJID = "5489081055707136" |
| ) |
| |
| func makeGitHubCirrusTryJob() ci.TryJob { |
| return ci.TryJob{ |
| SystemID: githubTJID, |
| System: cirrusCIS, |
| DisplayName: "my-github-task", |
| Updated: time.Date(2019, time.November, 19, 18, 20, 10, 0, time.UTC), |
| } |
| } |
| |
| func makeGitHubTryJobResults() []tjstore.TryJobResult { |
| return []tjstore.TryJobResult{ |
| { |
| TryjobID: githubTJID, |
| System: cirrusCIS, |
| Digest: "87599f3dec5b56dc110f1b63dc747182", |
| GroupParams: paramtools.Params{ |
| "Platform": "windows", |
| }, |
| ResultParams: paramtools.Params{ |
| "name": "cupertino.date_picker_test.datetime.initial", |
| "source_type": "flutter", |
| }, |
| Options: paramtools.Params{ |
| "ext": "png", |
| }, |
| }, |
| { |
| TryjobID: githubTJID, |
| System: cirrusCIS, |
| Digest: "7d04fc1ef547a8e092495dab4294b4cd", |
| GroupParams: paramtools.Params{ |
| "Platform": "windows", |
| }, |
| ResultParams: paramtools.Params{ |
| "name": "cupertino.date_picker_test.datetime.drag", |
| "source_type": "flutter", |
| }, |
| Options: paramtools.Params{ |
| "ext": "png", |
| }, |
| }, |
| } |
| } |
| |
| func makeCirrusCIS() map[string]ci.Client { |
| mcis := &mock_cis.Client{} |
| mcis.On("GetTryJob", testutils.AnyContext, githubTJID).Return(makeGitHubCirrusTryJob(), nil) |
| return map[string]ci.Client{ |
| cirrusCIS: mcis, |
| } |
| } |
| |
| func makeGitHubCRS() *mock_crs.Client { |
| cl := code_review.Changelist{ |
| SystemID: githubCLID, |
| Owner: "test@example.com", |
| Status: code_review.Open, |
| Subject: "initial commit", |
| Updated: time.Date(2019, time.November, 19, 18, 17, 16, 0, time.UTC), |
| } |
| |
| ps := code_review.Patchset{ |
| SystemID: "fe1cad6c1a5d6dc7cea47f09efdd49f197a7f017", |
| ChangelistID: githubCLID, |
| Order: githubPSOrder, |
| GitHash: "fe1cad6c1a5d6dc7cea47f09efdd49f197a7f017", |
| } |
| mcrs := &mock_crs.Client{} |
| mcrs.On("GetChangelist", testutils.AnyContext, githubCLID).Return(cl, nil) |
| mcrs.On("GetPatchset", testutils.AnyContext, githubCLID, mock.Anything, mock.Anything).Return(ps, nil) |
| return mcrs |
| } |