go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/culpritverification/test_failure_verify_culprit_test.go (about) 1 // Copyright 2023 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package culpritverification performs culprit verification for test failures. 16 package culpritverification 17 18 import ( 19 "context" 20 "encoding/json" 21 "testing" 22 "time" 23 24 "github.com/golang/mock/gomock" 25 . "github.com/smartystreets/goconvey/convey" 26 "go.chromium.org/luci/bisection/internal/buildbucket" 27 "go.chromium.org/luci/bisection/internal/config" 28 "go.chromium.org/luci/bisection/internal/gitiles" 29 "go.chromium.org/luci/bisection/model" 30 configpb "go.chromium.org/luci/bisection/proto/config" 31 pb "go.chromium.org/luci/bisection/proto/v1" 32 tpb "go.chromium.org/luci/bisection/task/proto" 33 "go.chromium.org/luci/bisection/util/testutil" 34 bbpb "go.chromium.org/luci/buildbucket/proto" 35 "go.chromium.org/luci/common/clock" 36 "go.chromium.org/luci/common/clock/testclock" 37 . "go.chromium.org/luci/common/testing/assertions" 38 "go.chromium.org/luci/gae/impl/memory" 39 "go.chromium.org/luci/gae/service/datastore" 40 ) 41 42 func TestProcessTestFailureTask(t *testing.T) { 43 t.Parallel() 44 c := context.Background() 45 cl := testclock.New(testclock.TestTimeUTC) 46 c = clock.Set(c, cl) 47 48 // Setup mock for buildbucket 49 ctl := gomock.NewController(t) 50 defer ctl.Finish() 51 mc := buildbucket.NewMockedClient(c, ctl) 52 c = mc.Ctx 53 build1 := buildbucket.MockScheduleBuild(mc, 123, "3425") 54 build2 := buildbucket.MockScheduleBuild(mc, 456, "3424") 55 buildbucket.MockGetBuild(mc) 56 57 Convey("process test failure task", t, func() { 58 c = memory.Use(c) 59 testutil.UpdateIndices(c) 60 61 // Setup config. 62 projectCfg := config.CreatePlaceholderProjectConfig() 63 cfg := map[string]*configpb.ProjectConfig{"chromium": projectCfg} 64 So(config.SetTestProjectConfig(c, cfg), ShouldBeNil) 65 66 Convey("trigger rerun", func() { 67 tfa := testutil.CreateTestFailureAnalysis(c, nil) 68 nsa := testutil.CreateTestNthSectionAnalysis(c, &testutil.TestNthSectionAnalysisCreationOption{ 69 ParentAnalysisKey: datastore.KeyForObj(c, tfa), 70 }) 71 suspect := testutil.CreateSuspect(c, &testutil.SuspectCreationOption{ 72 ParentKey: datastore.KeyForObj(c, nsa), 73 CommitID: "3425", 74 }) 75 tf := testutil.CreateTestFailure(c, &testutil.TestFailureCreationOption{IsPrimary: true, Analysis: tfa}) 76 gitilesResponse := model.ChangeLogResponse{ 77 Log: []*model.ChangeLog{ 78 { 79 Commit: "3424", 80 }, 81 }, 82 } 83 gitilesResponseStr, _ := json.Marshal(gitilesResponse) 84 c = gitiles.MockedGitilesClientContext(c, map[string]string{ 85 "https://chromium.googlesource.com/chromium/src/+log/3425~2..3425^": string(gitilesResponseStr), 86 }) 87 task := &tpb.TestFailureCulpritVerificationTask{ 88 AnalysisId: tfa.ID, 89 } 90 91 err := processTestFailureTask(c, task) 92 So(err, ShouldBeNil) 93 datastore.GetTestable(c).CatchupIndexes() 94 // Check suspect updated. 95 So(datastore.Get(c, suspect), ShouldBeNil) 96 So(suspect.VerificationStatus, ShouldEqual, model.SuspectVerificationStatus_UnderVerification) 97 // Check rerun saved. 98 suspectRerun := &model.TestSingleRerun{ 99 ID: suspect.SuspectRerunBuild.IntID(), 100 } 101 err = datastore.Get(c, suspectRerun) 102 So(err, ShouldBeNil) 103 expectedRerun := &model.TestSingleRerun{ 104 ID: build1.Id, 105 LUCIBuild: model.LUCIBuild{ 106 BuildID: build1.Id, 107 Project: build1.Builder.Project, 108 Bucket: build1.Builder.Bucket, 109 Builder: build1.Builder.Builder, 110 GitilesCommit: build1.Input.GitilesCommit, 111 CreateTime: build1.CreateTime.AsTime(), 112 EndTime: time.Time{}, 113 StartTime: build1.StartTime.AsTime(), 114 Status: bbpb.Status_STARTED, 115 }, 116 Type: model.RerunBuildType_CulpritVerification, 117 AnalysisKey: datastore.KeyForObj(c, tfa), 118 CulpritKey: datastore.KeyForObj(c, suspect), 119 TestResults: model.RerunTestResults{ 120 IsFinalized: false, 121 Results: []model.RerunSingleTestResult{{ 122 TestFailureKey: datastore.KeyForObj(c, tf), 123 }}, 124 }, 125 Dimensions: &pb.Dimensions{}, 126 Status: pb.RerunStatus_RERUN_STATUS_IN_PROGRESS, 127 } 128 So(suspectRerun, ShouldResembleProto, expectedRerun) 129 parentRerun := &model.TestSingleRerun{ 130 ID: suspect.ParentRerunBuild.IntID(), 131 } 132 err = datastore.Get(c, parentRerun) 133 So(err, ShouldBeNil) 134 expectedRerun.ID = build2.Id 135 expectedRerun.LUCIBuild.BuildID = build2.Id 136 expectedRerun.LUCIBuild.GitilesCommit = build2.Input.GitilesCommit 137 So(parentRerun, ShouldResembleProto, expectedRerun) 138 }) 139 }) 140 141 }