go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/util/bqutil/bq_util_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 bqutil 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 . "github.com/smartystreets/goconvey/convey" 23 "google.golang.org/protobuf/types/known/timestamppb" 24 25 "go.chromium.org/luci/bisection/model" 26 bqpb "go.chromium.org/luci/bisection/proto/bq" 27 pb "go.chromium.org/luci/bisection/proto/v1" 28 "go.chromium.org/luci/bisection/util/testutil" 29 buildbucketpb "go.chromium.org/luci/buildbucket/proto" 30 . "go.chromium.org/luci/common/testing/assertions" 31 "go.chromium.org/luci/gae/impl/memory" 32 "go.chromium.org/luci/gae/service/datastore" 33 ) 34 35 func TestConvertTestFailureAnalysisToBqRow(t *testing.T) { 36 t.Parallel() 37 ctx := memory.Use(context.Background()) 38 testutil.UpdateIndices(ctx) 39 40 Convey("TestFailureAnalysisToBqRow", t, func() { 41 tfa := testutil.CreateTestFailureAnalysis(ctx, &testutil.TestFailureAnalysisCreationOption{ 42 ID: int64(100), 43 Project: "chromium", 44 Bucket: "ci", 45 Builder: "linux-rel", 46 StartCommitHash: "start_commit_hash", 47 EndCommitHash: "end_commit_hash", 48 FailedBuildID: 8000, 49 CreateTime: time.Unix(int64(100), 0).UTC(), 50 StartTime: time.Unix(int64(110), 0).UTC(), 51 EndTime: time.Unix(int64(120), 0).UTC(), 52 TestFailureKey: datastore.MakeKey(ctx, "TestFailure", 100), 53 Status: pb.AnalysisStatus_FOUND, 54 RunStatus: pb.AnalysisRunStatus_ENDED, 55 }) 56 // non-primary test failure. 57 testutil.CreateTestFailure(ctx, &testutil.TestFailureCreationOption{ 58 ID: int64(99), 59 Analysis: tfa, 60 TestID: "testID2", 61 StartHour: time.Unix(int64(100), 0).UTC(), 62 Ref: &pb.SourceRef{ 63 System: &pb.SourceRef_Gitiles{ 64 Gitiles: &pb.GitilesRef{ 65 Host: "chromium.googlesource.com", 66 Project: "chromium/src", 67 Ref: "ref", 68 }, 69 }, 70 }, 71 Project: "chromium", 72 Variant: map[string]string{ 73 "key2": "val2", 74 }, 75 VariantHash: "vhash2", 76 RefHash: "refhash", 77 StartPosition: 100, 78 EndPosition: 199, 79 StartFailureRate: 0, 80 EndFailureRate: 1.0, 81 IsDiverged: true, 82 }) 83 primaryTf := testutil.CreateTestFailure(ctx, &testutil.TestFailureCreationOption{ 84 ID: int64(100), 85 Analysis: tfa, 86 IsPrimary: true, 87 TestID: "testID1", 88 StartHour: time.Unix(int64(100), 0).UTC(), 89 Ref: &pb.SourceRef{ 90 System: &pb.SourceRef_Gitiles{ 91 Gitiles: &pb.GitilesRef{ 92 Host: "chromium.googlesource.com", 93 Project: "chromium/src", 94 Ref: "ref", 95 }, 96 }, 97 }, 98 Project: "chromium", 99 Variant: map[string]string{ 100 "key1": "val1", 101 }, 102 VariantHash: "vhash1", 103 RefHash: "refhash", 104 StartPosition: 100, 105 EndPosition: 199, 106 StartFailureRate: 0, 107 EndFailureRate: 1.0, 108 }) 109 nsa := testutil.CreateTestNthSectionAnalysis(ctx, &testutil.TestNthSectionAnalysisCreationOption{ 110 ID: 200, 111 ParentAnalysisKey: datastore.KeyForObj(ctx, tfa), 112 BlameList: testutil.CreateBlamelist(4), 113 Status: pb.AnalysisStatus_SUSPECTFOUND, 114 RunStatus: pb.AnalysisRunStatus_ENDED, 115 StartTime: time.Unix(int64(100), 0).UTC(), 116 EndTime: time.Unix(int64(109), 0).UTC(), 117 }) 118 culprit := testutil.CreateSuspect(ctx, &testutil.SuspectCreationOption{ 119 ID: 500, 120 ParentKey: datastore.KeyForObj(ctx, nsa), 121 CommitID: "culprit_commit_id", 122 ReviewURL: "review_url", 123 ReviewTitle: "review_title", 124 SuspectRerunKey: datastore.MakeKey(ctx, "Suspect", 3000), 125 ParentRerunKey: datastore.MakeKey(ctx, "Suspect", 3001), 126 VerificationStatus: model.SuspectVerificationStatus_ConfirmedCulprit, 127 ActionDetails: model.ActionDetails{ 128 IsRevertCreated: true, 129 RevertURL: "http://revert", 130 RevertCreateTime: time.Unix(120, 0).UTC(), 131 }, 132 }) 133 134 // Suspect verification rerun. 135 testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{ 136 ID: 3000, 137 AnalysisKey: datastore.KeyForObj(ctx, tfa), 138 CulpritKey: datastore.KeyForObj(ctx, culprit), 139 Type: model.RerunBuildType_CulpritVerification, 140 CreateTime: time.Unix(103, 0).UTC(), 141 StartTime: time.Unix(104, 0).UTC(), 142 ReportTime: time.Unix(105, 0).UTC(), 143 EndTime: time.Unix(106, 0).UTC(), 144 Status: pb.RerunStatus_RERUN_STATUS_FAILED, 145 BuildStatus: buildbucketpb.Status_SUCCESS, 146 TestResult: model.RerunTestResults{ 147 IsFinalized: true, 148 Results: []model.RerunSingleTestResult{ 149 { 150 TestFailureKey: datastore.KeyForObj(ctx, primaryTf), 151 UnexpectedCount: 1, 152 }, 153 }, 154 }, 155 GitilesCommit: &buildbucketpb.GitilesCommit{ 156 Host: "chromium.googlesource.com", 157 Project: "chromium/src", 158 Ref: "ref", 159 Id: "commit2", 160 }, 161 }) 162 163 // Parent verification rerun. 164 testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{ 165 ID: 3001, 166 AnalysisKey: datastore.KeyForObj(ctx, tfa), 167 CulpritKey: datastore.KeyForObj(ctx, culprit), 168 Type: model.RerunBuildType_CulpritVerification, 169 CreateTime: time.Unix(103, 0).UTC(), 170 StartTime: time.Unix(104, 0).UTC(), 171 ReportTime: time.Unix(105, 0).UTC(), 172 EndTime: time.Unix(106, 0).UTC(), 173 Status: pb.RerunStatus_RERUN_STATUS_PASSED, 174 BuildStatus: buildbucketpb.Status_SUCCESS, 175 TestResult: model.RerunTestResults{ 176 IsFinalized: true, 177 Results: []model.RerunSingleTestResult{ 178 { 179 TestFailureKey: datastore.KeyForObj(ctx, primaryTf), 180 ExpectedCount: 1, 181 }, 182 }, 183 }, 184 GitilesCommit: &buildbucketpb.GitilesCommit{ 185 Host: "chromium.googlesource.com", 186 Project: "chromium/src", 187 Ref: "ref", 188 Id: "commit3", 189 }, 190 }) 191 192 // Nthsection rerun1. 193 testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{ 194 ID: 2998, 195 AnalysisKey: datastore.KeyForObj(ctx, tfa), 196 NthSectionAnalysisKey: datastore.KeyForObj(ctx, nsa), 197 Type: model.RerunBuildType_NthSection, 198 CreateTime: time.Unix(103, 0).UTC(), 199 StartTime: time.Unix(104, 0).UTC(), 200 ReportTime: time.Unix(105, 0).UTC(), 201 EndTime: time.Unix(106, 0).UTC(), 202 Status: pb.RerunStatus_RERUN_STATUS_FAILED, 203 BuildStatus: buildbucketpb.Status_SUCCESS, 204 TestResult: model.RerunTestResults{ 205 IsFinalized: true, 206 Results: []model.RerunSingleTestResult{ 207 { 208 TestFailureKey: datastore.KeyForObj(ctx, primaryTf), 209 UnexpectedCount: 1, 210 }, 211 }, 212 }, 213 GitilesCommit: &buildbucketpb.GitilesCommit{ 214 Host: "chromium.googlesource.com", 215 Project: "chromium/src", 216 Ref: "ref", 217 Id: "commit2", 218 }, 219 }) 220 221 // Nthsection rerun2. 222 testutil.CreateTestSingleRerun(ctx, &testutil.TestSingleRerunCreationOption{ 223 ID: 2999, 224 AnalysisKey: datastore.KeyForObj(ctx, tfa), 225 NthSectionAnalysisKey: datastore.KeyForObj(ctx, nsa), 226 Type: model.RerunBuildType_NthSection, 227 CreateTime: time.Unix(104, 0).UTC(), 228 StartTime: time.Unix(105, 0).UTC(), 229 ReportTime: time.Unix(106, 0).UTC(), 230 EndTime: time.Unix(107, 0).UTC(), 231 Status: pb.RerunStatus_RERUN_STATUS_PASSED, 232 BuildStatus: buildbucketpb.Status_SUCCESS, 233 TestResult: model.RerunTestResults{ 234 IsFinalized: true, 235 Results: []model.RerunSingleTestResult{ 236 { 237 TestFailureKey: datastore.KeyForObj(ctx, primaryTf), 238 ExpectedCount: 1, 239 }, 240 }, 241 }, 242 GitilesCommit: &buildbucketpb.GitilesCommit{ 243 Host: "chromium.googlesource.com", 244 Project: "chromium/src", 245 Ref: "ref", 246 Id: "commit3", 247 }, 248 }) 249 250 tfa.VerifiedCulpritKey = datastore.KeyForObj(ctx, culprit) 251 So(datastore.Put(ctx, tfa), ShouldBeNil) 252 nsa.CulpritKey = datastore.KeyForObj(ctx, culprit) 253 So(datastore.Put(ctx, nsa), ShouldBeNil) 254 datastore.GetTestable(ctx).CatchupIndexes() 255 256 tfaProto, err := TestFailureAnalysisToBqRow(ctx, tfa) 257 So(err, ShouldBeNil) 258 259 pbSuspectRerun := &pb.TestSingleRerun{ 260 Bbid: 3000, 261 CreateTime: timestamppb.New(time.Unix(103, 0).UTC()), 262 StartTime: timestamppb.New(time.Unix(104, 0).UTC()), 263 ReportTime: timestamppb.New(time.Unix(105, 0).UTC()), 264 EndTime: timestamppb.New(time.Unix(106, 0).UTC()), 265 Index: "2", 266 Commit: &buildbucketpb.GitilesCommit{ 267 Host: "chromium.googlesource.com", 268 Project: "chromium/src", 269 Ref: "ref", 270 Id: "commit2", 271 }, 272 RerunResult: &pb.RerunTestResults{ 273 RerunStatus: pb.RerunStatus_RERUN_STATUS_FAILED, 274 Results: []*pb.RerunTestSingleResult{ 275 { 276 TestId: "testID1", 277 VariantHash: "vhash1", 278 UnexpectedCount: 1, 279 }, 280 }, 281 }, 282 } 283 284 pbParentRerun := &pb.TestSingleRerun{ 285 Bbid: 3001, 286 CreateTime: timestamppb.New(time.Unix(103, 0).UTC()), 287 StartTime: timestamppb.New(time.Unix(104, 0).UTC()), 288 ReportTime: timestamppb.New(time.Unix(105, 0).UTC()), 289 EndTime: timestamppb.New(time.Unix(106, 0).UTC()), 290 Index: "3", 291 Commit: &buildbucketpb.GitilesCommit{ 292 Host: "chromium.googlesource.com", 293 Project: "chromium/src", 294 Ref: "ref", 295 Id: "commit3", 296 }, 297 RerunResult: &pb.RerunTestResults{ 298 RerunStatus: pb.RerunStatus_RERUN_STATUS_PASSED, 299 Results: []*pb.RerunTestSingleResult{ 300 { 301 TestId: "testID1", 302 VariantHash: "vhash1", 303 ExpectedCount: 1, 304 }, 305 }, 306 }, 307 } 308 309 pbNthsectionRerun1 := &pb.TestSingleRerun{ 310 Bbid: 2998, 311 CreateTime: timestamppb.New(time.Unix(103, 0).UTC()), 312 StartTime: timestamppb.New(time.Unix(104, 0).UTC()), 313 ReportTime: timestamppb.New(time.Unix(105, 0).UTC()), 314 EndTime: timestamppb.New(time.Unix(106, 0).UTC()), 315 Index: "2", 316 Commit: &buildbucketpb.GitilesCommit{ 317 Host: "chromium.googlesource.com", 318 Project: "chromium/src", 319 Ref: "ref", 320 Id: "commit2", 321 }, 322 RerunResult: &pb.RerunTestResults{ 323 RerunStatus: pb.RerunStatus_RERUN_STATUS_FAILED, 324 Results: []*pb.RerunTestSingleResult{ 325 { 326 TestId: "testID1", 327 VariantHash: "vhash1", 328 UnexpectedCount: 1, 329 }, 330 }, 331 }, 332 } 333 334 pbNthsectionRerun2 := &pb.TestSingleRerun{ 335 Bbid: 2999, 336 CreateTime: timestamppb.New(time.Unix(104, 0).UTC()), 337 StartTime: timestamppb.New(time.Unix(105, 0).UTC()), 338 ReportTime: timestamppb.New(time.Unix(106, 0).UTC()), 339 EndTime: timestamppb.New(time.Unix(107, 0).UTC()), 340 Index: "3", 341 Commit: &buildbucketpb.GitilesCommit{ 342 Host: "chromium.googlesource.com", 343 Project: "chromium/src", 344 Ref: "ref", 345 Id: "commit3", 346 }, 347 RerunResult: &pb.RerunTestResults{ 348 RerunStatus: pb.RerunStatus_RERUN_STATUS_PASSED, 349 Results: []*pb.RerunTestSingleResult{ 350 { 351 TestId: "testID1", 352 VariantHash: "vhash1", 353 ExpectedCount: 1, 354 }, 355 }, 356 }, 357 } 358 359 culpritPb := &pb.TestCulprit{ 360 ReviewUrl: "review_url", 361 ReviewTitle: "review_title", 362 Commit: &buildbucketpb.GitilesCommit{ 363 Host: "chromium.googlesource.com", 364 Project: "chromium/src", 365 Ref: "ref", 366 Id: "culprit_commit_id", 367 }, 368 CulpritAction: []*pb.CulpritAction{ 369 { 370 ActionType: pb.CulpritActionType_REVERT_CL_CREATED, 371 RevertClUrl: "http://revert", 372 ActionTime: timestamppb.New(time.Unix(120, 0)), 373 }, 374 }, 375 VerificationDetails: &pb.TestSuspectVerificationDetails{ 376 Status: pb.SuspectVerificationStatus_CONFIRMED_CULPRIT, 377 SuspectRerun: pbSuspectRerun, 378 ParentRerun: pbParentRerun, 379 }, 380 } 381 382 So(tfaProto, ShouldResembleProto, &bqpb.TestAnalysisRow{ 383 Project: "chromium", 384 AnalysisId: 100, 385 Builder: &buildbucketpb.BuilderID{ 386 Project: "chromium", 387 Bucket: "ci", 388 Builder: "linux-rel", 389 }, 390 CreatedTime: timestamppb.New(time.Unix(int64(100), 0).UTC()), 391 StartTime: timestamppb.New(time.Unix(int64(110), 0).UTC()), 392 EndTime: timestamppb.New(time.Unix(int64(120), 0).UTC()), 393 Status: pb.AnalysisStatus_FOUND, 394 RunStatus: pb.AnalysisRunStatus_ENDED, 395 StartGitilesCommit: &buildbucketpb.GitilesCommit{ 396 Host: "chromium.googlesource.com", 397 Project: "chromium/src", 398 Ref: "ref", 399 Id: "start_commit_hash", 400 Position: 100, 401 }, 402 EndGitilesCommit: &buildbucketpb.GitilesCommit{ 403 Host: "chromium.googlesource.com", 404 Project: "chromium/src", 405 Ref: "ref", 406 Id: "end_commit_hash", 407 Position: 199, 408 }, 409 SampleBbid: 8000, 410 StartFailureRate: 0, 411 EndFailureRate: 1.0, 412 TestFailures: []*pb.TestFailure{ 413 { 414 TestId: "testID1", 415 VariantHash: "vhash1", 416 RefHash: "refhash", 417 Variant: &pb.Variant{ 418 Def: map[string]string{ 419 "key1": "val1", 420 }, 421 }, 422 IsPrimary: true, 423 StartHour: timestamppb.New(time.Unix(int64(100), 0).UTC()), 424 }, 425 { 426 TestId: "testID2", 427 VariantHash: "vhash2", 428 RefHash: "refhash", 429 Variant: &pb.Variant{ 430 Def: map[string]string{ 431 "key2": "val2", 432 }, 433 }, 434 IsDiverged: true, 435 StartHour: timestamppb.New(time.Unix(int64(100), 0).UTC()), 436 }, 437 }, 438 NthSectionResult: &pb.TestNthSectionAnalysisResult{ 439 Status: pb.AnalysisStatus_SUSPECTFOUND, 440 RunStatus: pb.AnalysisRunStatus_ENDED, 441 StartTime: timestamppb.New(time.Unix(int64(100), 0).UTC()), 442 EndTime: timestamppb.New(time.Unix(int64(109), 0).UTC()), 443 BlameList: testutil.CreateBlamelist(4), 444 Suspect: culpritPb, 445 Reruns: []*pb.TestSingleRerun{ 446 pbNthsectionRerun1, pbNthsectionRerun2, 447 }, 448 }, 449 Culprit: culpritPb, 450 }) 451 }) 452 }