go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/model/model_test.go (about) 1 // Copyright 2022 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 model 16 17 import ( 18 "context" 19 "testing" 20 21 pb "go.chromium.org/luci/bisection/proto/v1" 22 23 . "github.com/smartystreets/goconvey/convey" 24 buildbucketpb "go.chromium.org/luci/buildbucket/proto" 25 "go.chromium.org/luci/common/clock" 26 "go.chromium.org/luci/common/clock/testclock" 27 . "go.chromium.org/luci/common/testing/assertions" 28 "go.chromium.org/luci/gae/impl/memory" 29 "go.chromium.org/luci/gae/service/datastore" 30 ) 31 32 func TestDatastoreModel(t *testing.T) { 33 t.Parallel() 34 35 Convey("Datastore Model", t, func() { 36 c := memory.Use(context.Background()) 37 cl := testclock.New(testclock.TestTimeUTC) 38 c = clock.Set(c, cl) 39 40 Convey("Can create datastore models", func() { 41 failed_build := &LuciFailedBuild{ 42 Id: 88128398584903, 43 LuciBuild: LuciBuild{ 44 BuildId: 88128398584903, 45 Project: "chromium", 46 Bucket: "ci", 47 Builder: "android", 48 BuildNumber: 123, 49 Status: buildbucketpb.Status_FAILURE, 50 StartTime: cl.Now(), 51 EndTime: cl.Now(), 52 CreateTime: cl.Now(), 53 }, 54 BuildFailureType: pb.BuildFailureType_COMPILE, 55 } 56 So(datastore.Put(c, failed_build), ShouldBeNil) 57 58 compile_failure := &CompileFailure{ 59 Build: datastore.KeyForObj(c, failed_build), 60 OutputTargets: []string{"abc.xyx"}, 61 Rule: "CXX", 62 Dependencies: []string{"dep"}, 63 } 64 So(datastore.Put(c, compile_failure), ShouldBeNil) 65 66 compile_failure_analysis := &CompileFailureAnalysis{ 67 CompileFailure: datastore.KeyForObj(c, compile_failure), 68 CreateTime: cl.Now(), 69 StartTime: cl.Now(), 70 EndTime: cl.Now(), 71 Status: pb.AnalysisStatus_FOUND, 72 FirstFailedBuildId: 88000998778, 73 LastPassedBuildId: 873929392903, 74 InitialRegressionRange: &pb.RegressionRange{ 75 LastPassed: &buildbucketpb.GitilesCommit{ 76 Host: "host", 77 Project: "proj", 78 Ref: "ref", 79 Id: "id1", 80 }, 81 FirstFailed: &buildbucketpb.GitilesCommit{ 82 Host: "host", 83 Project: "proj", 84 Ref: "ref", 85 Id: "id2", 86 }, 87 NumberOfRevisions: 10, 88 }, 89 } 90 So(datastore.Put(c, compile_failure_analysis), ShouldBeNil) 91 92 heuristic_analysis := &CompileHeuristicAnalysis{ 93 ParentAnalysis: datastore.KeyForObj(c, compile_failure_analysis), 94 StartTime: cl.Now(), 95 EndTime: cl.Now(), 96 Status: pb.AnalysisStatus_CREATED, 97 } 98 So(datastore.Put(c, heuristic_analysis), ShouldBeNil) 99 100 nthsection_analysis := &CompileNthSectionAnalysis{ 101 ParentAnalysis: datastore.KeyForObj(c, compile_failure_analysis), 102 StartTime: cl.Now(), 103 EndTime: cl.Now(), 104 Status: pb.AnalysisStatus_CREATED, 105 BlameList: &pb.BlameList{ 106 Commits: []*pb.BlameListSingleCommit{ 107 { 108 Commit: "12345", 109 ReviewUrl: "https://this/is/review/url/1", 110 ReviewTitle: "commit 1", 111 }, 112 { 113 Commit: "12346", 114 ReviewUrl: "https://this/is/review/url/2", 115 ReviewTitle: "commit 2", 116 }, 117 }, 118 }, 119 } 120 So(datastore.Put(c, nthsection_analysis), ShouldBeNil) 121 122 suspect := &Suspect{ 123 ParentAnalysis: datastore.KeyForObj(c, compile_failure_analysis), 124 GitilesCommit: buildbucketpb.GitilesCommit{ 125 Project: "my project", 126 Host: "host", 127 Ref: "ref", 128 Id: "id", 129 Position: 3433, 130 }, 131 ReviewUrl: "http://review-url.com", 132 ReviewTitle: "Added new functionality", 133 Score: 100, 134 Justification: "The CL touch the file abc.cc, and it is in the log", 135 } 136 So(datastore.Put(c, suspect), ShouldBeNil) 137 138 rerun_build := &CompileRerunBuild{ 139 LuciBuild: LuciBuild{ 140 BuildId: 88128398584903, 141 Project: "chromium", 142 Bucket: "ci", 143 Builder: "android", 144 BuildNumber: 123, 145 Status: buildbucketpb.Status_SUCCESS, 146 StartTime: cl.Now(), 147 EndTime: cl.Now(), 148 CreateTime: cl.Now(), 149 }, 150 } 151 So(datastore.Put(c, rerun_build), ShouldBeNil) 152 }) 153 154 Convey("Can create TestSingleRerun models", func() { 155 tf1 := &TestFailure{ 156 ID: 100, 157 } 158 tf2 := &TestFailure{ 159 ID: 101, 160 } 161 tfa := &TestFailureAnalysis{ 162 ID: 1000, 163 } 164 So(datastore.Put(c, tf1), ShouldBeNil) 165 So(datastore.Put(c, tf2), ShouldBeNil) 166 So(datastore.Put(c, tfa), ShouldBeNil) 167 datastore.GetTestable(c).CatchupIndexes() 168 singleRerun := &TestSingleRerun{ 169 AnalysisKey: datastore.KeyForObj(c, tfa), 170 LUCIBuild: LUCIBuild{ 171 BuildID: 12345, 172 GitilesCommit: &buildbucketpb.GitilesCommit{ 173 Host: "host", 174 Project: "proj", 175 Id: "id", 176 }, 177 }, 178 Dimensions: &pb.Dimensions{ 179 Dimensions: []*pb.Dimension{ 180 { 181 Key: "k", 182 Value: "v", 183 }, 184 }, 185 }, 186 Type: RerunBuildType_NthSection, 187 TestResults: RerunTestResults{ 188 IsFinalized: true, 189 Results: []RerunSingleTestResult{ 190 { 191 TestFailureKey: datastore.KeyForObj(c, tf1), 192 ExpectedCount: 1, 193 }, 194 { 195 TestFailureKey: datastore.KeyForObj(c, tf2), 196 UnexpectedCount: 1, 197 }, 198 }, 199 }, 200 Status: pb.RerunStatus_RERUN_STATUS_PASSED, 201 } 202 So(datastore.Put(c, singleRerun), ShouldBeNil) 203 datastore.GetTestable(c).CatchupIndexes() 204 q := datastore.NewQuery("TestSingleRerun").Eq("analysis_key", datastore.KeyForObj(c, tfa)) 205 reruns := []*TestSingleRerun{} 206 So(datastore.GetAll(c, q, &reruns), ShouldBeNil) 207 So(len(reruns), ShouldEqual, 1) 208 So(reruns[0], ShouldResembleProto, singleRerun) 209 }) 210 }) 211 } 212 213 func TestTestFailureBundle(t *testing.T) { 214 t.Parallel() 215 216 Convey("Test failure bundle", t, func() { 217 bundle := &TestFailureBundle{} 218 219 tf1 := &TestFailure{ 220 ID: 100, 221 IsDiverged: true, 222 } 223 tf2 := &TestFailure{ 224 ID: 101, 225 IsPrimary: true, 226 } 227 err := bundle.Add([]*TestFailure{ 228 tf1, 229 tf2, 230 }) 231 So(err, ShouldBeNil) 232 So(bundle.Primary(), ShouldResemble, tf2) 233 So(len(bundle.Others()), ShouldEqual, 1) 234 So(bundle.Others()[0], ShouldResemble, tf1) 235 So(len(bundle.All()), ShouldEqual, 2) 236 237 tf3 := &TestFailure{ 238 ID: 102, 239 IsPrimary: true, 240 } 241 err = bundle.Add([]*TestFailure{ 242 tf3, 243 }) 244 So(err, ShouldNotBeNil) 245 246 tf4 := &TestFailure{ 247 ID: 103, 248 } 249 err = bundle.Add([]*TestFailure{ 250 tf4, 251 }) 252 So(err, ShouldBeNil) 253 nonDiverged := bundle.NonDiverged() 254 So(len(nonDiverged), ShouldEqual, 2) 255 So(nonDiverged[0].ID, ShouldEqual, 101) 256 So(nonDiverged[1].ID, ShouldEqual, 103) 257 }) 258 }