go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/util/testutil/testutil.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 testutil contains utility functions for test. 16 package testutil 17 18 import ( 19 "context" 20 "fmt" 21 "time" 22 23 . "github.com/smartystreets/goconvey/convey" 24 "google.golang.org/protobuf/types/known/timestamppb" 25 26 "go.chromium.org/luci/bisection/model" 27 pb "go.chromium.org/luci/bisection/proto/v1" 28 bbpb "go.chromium.org/luci/buildbucket/proto" 29 "go.chromium.org/luci/gae/service/datastore" 30 ) 31 32 func CreateBlamelist(nCommits int) *pb.BlameList { 33 blamelist := &pb.BlameList{} 34 for i := 0; i < nCommits; i++ { 35 blamelist.Commits = append(blamelist.Commits, &pb.BlameListSingleCommit{ 36 Commit: fmt.Sprintf("commit%d", i), 37 CommitTime: timestamppb.New(time.Unix(int64(i+1000), 0)), 38 }) 39 } 40 blamelist.LastPassCommit = &pb.BlameListSingleCommit{ 41 Commit: fmt.Sprintf("commit%d", nCommits), 42 } 43 return blamelist 44 } 45 46 func CreateLUCIFailedBuild(c context.Context, id int64, project string) *model.LuciFailedBuild { 47 fb := &model.LuciFailedBuild{ 48 Id: id, 49 LuciBuild: model.LuciBuild{ 50 Project: project, 51 }, 52 SheriffRotations: []string{"chromium"}, 53 } 54 So(datastore.Put(c, fb), ShouldBeNil) 55 datastore.GetTestable(c).CatchupIndexes() 56 return fb 57 } 58 59 func CreateCompileFailure(c context.Context, fb *model.LuciFailedBuild) *model.CompileFailure { 60 cf := &model.CompileFailure{ 61 Id: fb.Id, 62 Build: datastore.KeyForObj(c, fb), 63 } 64 So(datastore.Put(c, cf), ShouldBeNil) 65 datastore.GetTestable(c).CatchupIndexes() 66 return cf 67 } 68 69 func CreateCompileFailureAnalysis(c context.Context, id int64, cf *model.CompileFailure) *model.CompileFailureAnalysis { 70 cfa := &model.CompileFailureAnalysis{ 71 Id: id, 72 CompileFailure: datastore.KeyForObj(c, cf), 73 } 74 So(datastore.Put(c, cfa), ShouldBeNil) 75 datastore.GetTestable(c).CatchupIndexes() 76 return cfa 77 } 78 79 func CreateCompileFailureAnalysisAnalysisChain(c context.Context, bbid int64, project string, analysisID int64) (*model.LuciFailedBuild, *model.CompileFailure, *model.CompileFailureAnalysis) { 80 fb := CreateLUCIFailedBuild(c, bbid, project) 81 cf := CreateCompileFailure(c, fb) 82 cfa := CreateCompileFailureAnalysis(c, analysisID, cf) 83 return fb, cf, cfa 84 } 85 86 func CreateHeuristicAnalysis(c context.Context, cfa *model.CompileFailureAnalysis) *model.CompileHeuristicAnalysis { 87 ha := &model.CompileHeuristicAnalysis{ 88 ParentAnalysis: datastore.KeyForObj(c, cfa), 89 } 90 So(datastore.Put(c, ha), ShouldBeNil) 91 datastore.GetTestable(c).CatchupIndexes() 92 return ha 93 } 94 95 func CreateNthSectionAnalysis(c context.Context, cfa *model.CompileFailureAnalysis) *model.CompileNthSectionAnalysis { 96 nsa := &model.CompileNthSectionAnalysis{ 97 ParentAnalysis: datastore.KeyForObj(c, cfa), 98 } 99 So(datastore.Put(c, nsa), ShouldBeNil) 100 datastore.GetTestable(c).CatchupIndexes() 101 return nsa 102 } 103 104 func CreateHeuristicSuspect(c context.Context, ha *model.CompileHeuristicAnalysis, status model.SuspectVerificationStatus) *model.Suspect { 105 suspect := &model.Suspect{ 106 ParentAnalysis: datastore.KeyForObj(c, ha), 107 Type: model.SuspectType_Heuristic, 108 VerificationStatus: status, 109 } 110 So(datastore.Put(c, suspect), ShouldBeNil) 111 datastore.GetTestable(c).CatchupIndexes() 112 return suspect 113 } 114 115 func CreateNthSectionSuspect(c context.Context, nsa *model.CompileNthSectionAnalysis) *model.Suspect { 116 suspect := &model.Suspect{ 117 ParentAnalysis: datastore.KeyForObj(c, nsa), 118 Type: model.SuspectType_NthSection, 119 } 120 So(datastore.Put(c, suspect), ShouldBeNil) 121 datastore.GetTestable(c).CatchupIndexes() 122 return suspect 123 } 124 125 type TestFailureCreationOption struct { 126 ID int64 127 Project string 128 Variant map[string]string 129 IsPrimary bool 130 Analysis *model.TestFailureAnalysis 131 Ref *pb.SourceRef 132 TestID string 133 VariantHash string 134 StartHour time.Time 135 RefHash string 136 StartPosition int64 137 EndPosition int64 138 StartFailureRate float64 139 EndFailureRate float64 140 IsDiverged bool 141 } 142 143 func CreateTestFailure(ctx context.Context, option *TestFailureCreationOption) *model.TestFailure { 144 id := int64(100) 145 project := "chromium" 146 variant := map[string]string{} 147 isPrimary := false 148 var analysisKey *datastore.Key = nil 149 var ref *pb.SourceRef = nil 150 var testID = "" 151 var variantHash = "" 152 var startHour time.Time 153 var refHash = "" 154 var startPosition int64 155 var endPosition int64 156 var startFailureRate float64 157 var endFailureRate float64 158 var isDiverged bool 159 160 if option != nil { 161 if option.ID != 0 { 162 id = option.ID 163 } 164 if option.Project != "" { 165 project = option.Project 166 } 167 if option.Analysis != nil { 168 analysisKey = datastore.KeyForObj(ctx, option.Analysis) 169 } 170 variant = option.Variant 171 isPrimary = option.IsPrimary 172 ref = option.Ref 173 testID = option.TestID 174 variantHash = option.VariantHash 175 startHour = option.StartHour 176 refHash = option.RefHash 177 startPosition = option.StartPosition 178 endPosition = option.EndPosition 179 startFailureRate = option.StartFailureRate 180 endFailureRate = option.EndFailureRate 181 isDiverged = option.IsDiverged 182 } 183 184 tf := &model.TestFailure{ 185 ID: id, 186 Project: project, 187 Variant: &pb.Variant{ 188 Def: variant, 189 }, 190 IsPrimary: isPrimary, 191 AnalysisKey: analysisKey, 192 Ref: ref, 193 TestID: testID, 194 VariantHash: variantHash, 195 StartHour: startHour, 196 RefHash: refHash, 197 RegressionStartPosition: startPosition, 198 RegressionEndPosition: endPosition, 199 StartPositionFailureRate: startFailureRate, 200 EndPositionFailureRate: endFailureRate, 201 IsDiverged: isDiverged, 202 } 203 204 So(datastore.Put(ctx, tf), ShouldBeNil) 205 datastore.GetTestable(ctx).CatchupIndexes() 206 return tf 207 } 208 209 type TestFailureAnalysisCreationOption struct { 210 ID int64 211 Project string 212 Bucket string 213 Builder string 214 TestFailureKey *datastore.Key 215 StartCommitHash string 216 EndCommitHash string 217 FailedBuildID int64 218 Priority int32 219 Status pb.AnalysisStatus 220 RunStatus pb.AnalysisRunStatus 221 CreateTime time.Time 222 StartTime time.Time 223 EndTime time.Time 224 VerifiedCulpritKey *datastore.Key 225 } 226 227 func CreateTestFailureAnalysis(ctx context.Context, option *TestFailureAnalysisCreationOption) *model.TestFailureAnalysis { 228 id := int64(1000) 229 project := "chromium" 230 bucket := "bucket" 231 builder := "builder" 232 var tfKey *datastore.Key = nil 233 startCommitHash := "" 234 endCommitHash := "" 235 failedBuildID := int64(8000) 236 var priority int32 237 var status pb.AnalysisStatus 238 var runStatus pb.AnalysisRunStatus 239 var createTime time.Time 240 var startTime time.Time 241 var endTime time.Time 242 var verifiedCulpritKey *datastore.Key = nil 243 244 if option != nil { 245 if option.ID != 0 { 246 id = option.ID 247 } 248 if option.Project != "" { 249 project = option.Project 250 } 251 if option.Bucket != "" { 252 bucket = option.Bucket 253 } 254 if option.Builder != "" { 255 builder = option.Builder 256 } 257 if option.StartCommitHash != "" { 258 startCommitHash = option.StartCommitHash 259 } 260 if option.EndCommitHash != "" { 261 endCommitHash = option.EndCommitHash 262 } 263 if option.FailedBuildID != 0 { 264 failedBuildID = option.FailedBuildID 265 } 266 priority = option.Priority 267 tfKey = option.TestFailureKey 268 status = option.Status 269 runStatus = option.RunStatus 270 createTime = option.CreateTime 271 startTime = option.StartTime 272 endTime = option.EndTime 273 verifiedCulpritKey = option.VerifiedCulpritKey 274 } 275 276 tfa := &model.TestFailureAnalysis{ 277 ID: id, 278 Project: project, 279 Bucket: bucket, 280 Builder: builder, 281 TestFailure: tfKey, 282 StartCommitHash: startCommitHash, 283 EndCommitHash: endCommitHash, 284 FailedBuildID: failedBuildID, 285 Priority: int32(priority), 286 Status: status, 287 RunStatus: runStatus, 288 CreateTime: createTime, 289 StartTime: startTime, 290 EndTime: endTime, 291 VerifiedCulpritKey: verifiedCulpritKey, 292 } 293 So(datastore.Put(ctx, tfa), ShouldBeNil) 294 datastore.GetTestable(ctx).CatchupIndexes() 295 return tfa 296 } 297 298 type TestSingleRerunCreationOption struct { 299 ID int64 300 Status pb.RerunStatus 301 AnalysisKey *datastore.Key 302 Type model.RerunBuildType 303 TestResult model.RerunTestResults 304 NthSectionAnalysisKey *datastore.Key 305 CulpritKey *datastore.Key 306 CreateTime time.Time 307 StartTime time.Time 308 ReportTime time.Time 309 EndTime time.Time 310 BuildStatus bbpb.Status 311 GitilesCommit *bbpb.GitilesCommit 312 } 313 314 func CreateTestSingleRerun(ctx context.Context, option *TestSingleRerunCreationOption) *model.TestSingleRerun { 315 id := int64(1000) 316 status := pb.RerunStatus_RERUN_STATUS_UNSPECIFIED 317 var analysisKey *datastore.Key 318 var rerunType model.RerunBuildType 319 testresult := model.RerunTestResults{} 320 var nthSectionAnalysisKey *datastore.Key 321 var culpritKey *datastore.Key 322 var startTime time.Time 323 var createTime time.Time 324 var reportTime time.Time 325 var endTime time.Time 326 var buildStatus bbpb.Status 327 var gitilesCommit *bbpb.GitilesCommit 328 329 if option != nil { 330 if option.ID != 0 { 331 id = option.ID 332 } 333 status = option.Status 334 analysisKey = option.AnalysisKey 335 rerunType = option.Type 336 testresult = option.TestResult 337 nthSectionAnalysisKey = option.NthSectionAnalysisKey 338 culpritKey = option.CulpritKey 339 startTime = option.StartTime 340 createTime = option.CreateTime 341 reportTime = option.ReportTime 342 endTime = option.EndTime 343 buildStatus = option.BuildStatus 344 gitilesCommit = option.GitilesCommit 345 } 346 rerun := &model.TestSingleRerun{ 347 ID: id, 348 Status: status, 349 AnalysisKey: analysisKey, 350 Type: rerunType, 351 TestResults: testresult, 352 NthSectionAnalysisKey: nthSectionAnalysisKey, 353 CulpritKey: culpritKey, 354 ReportTime: reportTime, 355 LUCIBuild: model.LUCIBuild{ 356 CreateTime: createTime, 357 StartTime: startTime, 358 EndTime: endTime, 359 Status: buildStatus, 360 GitilesCommit: gitilesCommit, 361 }, 362 } 363 So(datastore.Put(ctx, rerun), ShouldBeNil) 364 datastore.GetTestable(ctx).CatchupIndexes() 365 return rerun 366 } 367 368 type TestNthSectionAnalysisCreationOption struct { 369 ID int64 370 ParentAnalysisKey *datastore.Key 371 BlameList *pb.BlameList 372 Status pb.AnalysisStatus 373 RunStatus pb.AnalysisRunStatus 374 StartTime time.Time 375 EndTime time.Time 376 CulpritKey *datastore.Key 377 } 378 379 func CreateTestNthSectionAnalysis(ctx context.Context, option *TestNthSectionAnalysisCreationOption) *model.TestNthSectionAnalysis { 380 id := int64(1000) 381 var parentAnalysis *datastore.Key = nil 382 var blameList *pb.BlameList 383 var status pb.AnalysisStatus 384 var runStatus pb.AnalysisRunStatus 385 var startTime time.Time 386 var endTime time.Time 387 var culpritKey *datastore.Key 388 389 if option != nil { 390 if option.ID != 0 { 391 id = option.ID 392 } 393 parentAnalysis = option.ParentAnalysisKey 394 blameList = option.BlameList 395 status = option.Status 396 runStatus = option.RunStatus 397 startTime = option.StartTime 398 endTime = option.EndTime 399 culpritKey = option.CulpritKey 400 } 401 nsa := &model.TestNthSectionAnalysis{ 402 ID: id, 403 ParentAnalysisKey: parentAnalysis, 404 BlameList: blameList, 405 Status: status, 406 RunStatus: runStatus, 407 StartTime: startTime, 408 EndTime: endTime, 409 CulpritKey: culpritKey, 410 } 411 So(datastore.Put(ctx, nsa), ShouldBeNil) 412 datastore.GetTestable(ctx).CatchupIndexes() 413 return nsa 414 } 415 416 type SuspectCreationOption struct { 417 ID int64 418 ParentKey *datastore.Key 419 CommitID string 420 ReviewURL string 421 ReviewTitle string 422 SuspectRerunKey *datastore.Key 423 ParentRerunKey *datastore.Key 424 VerificationStatus model.SuspectVerificationStatus 425 ActionDetails model.ActionDetails 426 AnalysisType pb.AnalysisType 427 } 428 429 func CreateSuspect(ctx context.Context, option *SuspectCreationOption) *model.Suspect { 430 var parentKey *datastore.Key 431 id := int64(500) 432 commitID := "1" 433 reviewURL := "" 434 reviewTitle := "" 435 var suspectRerunKey *datastore.Key 436 var parentRerunKey *datastore.Key 437 var verificationStatus model.SuspectVerificationStatus 438 var actionDetails model.ActionDetails 439 var analysisType pb.AnalysisType 440 441 if option != nil { 442 if option.ID != 0 { 443 id = option.ID 444 } 445 if option.CommitID != "" { 446 commitID = option.CommitID 447 } 448 parentKey = option.ParentKey 449 reviewURL = option.ReviewURL 450 reviewTitle = option.ReviewTitle 451 suspectRerunKey = option.SuspectRerunKey 452 parentRerunKey = option.ParentRerunKey 453 verificationStatus = option.VerificationStatus 454 actionDetails = option.ActionDetails 455 analysisType = option.AnalysisType 456 } 457 suspect := &model.Suspect{ 458 Id: id, 459 ParentAnalysis: parentKey, 460 GitilesCommit: bbpb.GitilesCommit{ 461 Host: "chromium.googlesource.com", 462 Project: "chromium/src", 463 Ref: "ref", 464 Id: commitID, 465 }, 466 ReviewUrl: reviewURL, 467 ReviewTitle: reviewTitle, 468 SuspectRerunBuild: suspectRerunKey, 469 ParentRerunBuild: parentRerunKey, 470 VerificationStatus: verificationStatus, 471 ActionDetails: actionDetails, 472 AnalysisType: analysisType, 473 } 474 So(datastore.Put(ctx, suspect), ShouldBeNil) 475 datastore.GetTestable(ctx).CatchupIndexes() 476 return suspect 477 } 478 479 func UpdateIndices(c context.Context) { 480 datastore.GetTestable(c).AddIndexes( 481 &datastore.IndexDefinition{ 482 Kind: "SingleRerun", 483 SortBy: []datastore.IndexColumn{ 484 { 485 Property: "analysis", 486 }, 487 { 488 Property: "start_time", 489 }, 490 }, 491 }, 492 &datastore.IndexDefinition{ 493 Kind: "Suspect", 494 SortBy: []datastore.IndexColumn{ 495 { 496 Property: "analysis_type", 497 }, 498 { 499 Property: "is_revert_created", 500 }, 501 { 502 Property: "revert_create_time", 503 }, 504 }, 505 }, 506 &datastore.IndexDefinition{ 507 Kind: "Suspect", 508 SortBy: []datastore.IndexColumn{ 509 { 510 Property: "is_revert_committed", 511 }, 512 { 513 Property: "revert_commit_time", 514 }, 515 }, 516 }, 517 &datastore.IndexDefinition{ 518 Kind: "SingleRerun", 519 SortBy: []datastore.IndexColumn{ 520 { 521 Property: "rerun_build", 522 }, 523 { 524 Property: "start_time", 525 }, 526 }, 527 }, 528 &datastore.IndexDefinition{ 529 Kind: "SingleRerun", 530 SortBy: []datastore.IndexColumn{ 531 { 532 Property: "Status", 533 }, 534 { 535 Property: "create_time", 536 }, 537 }, 538 }, 539 &datastore.IndexDefinition{ 540 Kind: "LuciFailedBuild", 541 SortBy: []datastore.IndexColumn{ 542 { 543 Property: "project", 544 }, 545 { 546 Property: "bucket", 547 }, 548 { 549 Property: "builder", 550 }, 551 { 552 Property: "end_time", 553 Descending: true, 554 }, 555 }, 556 }, 557 &datastore.IndexDefinition{ 558 Kind: "TestSingleRerun", 559 SortBy: []datastore.IndexColumn{ 560 { 561 Property: "nthsection_analysis_key", 562 }, 563 { 564 Property: "luci_build.create_time", 565 }, 566 }, 567 }, 568 &datastore.IndexDefinition{ 569 Kind: "CompileRerunBuild", 570 SortBy: []datastore.IndexColumn{ 571 { 572 Property: "project", 573 }, 574 { 575 Property: "status", 576 }, 577 { 578 Property: "create_time", 579 }, 580 }, 581 }, 582 &datastore.IndexDefinition{ 583 Kind: "TestSingleRerun", 584 SortBy: []datastore.IndexColumn{ 585 { 586 Property: "luci_build.project", 587 }, 588 { 589 Property: "luci_build.status", 590 }, 591 { 592 Property: "luci_build.create_time", 593 }, 594 }, 595 }, 596 &datastore.IndexDefinition{ 597 Kind: "TestSingleRerun", 598 SortBy: []datastore.IndexColumn{ 599 { 600 Property: "status", 601 }, 602 { 603 Property: "luci_build.create_time", 604 }, 605 }, 606 }, 607 &datastore.IndexDefinition{ 608 Kind: "TestFailureAnalysis", 609 SortBy: []datastore.IndexColumn{ 610 { 611 Property: "project", 612 }, 613 { 614 Property: "create_time", 615 }, 616 }, 617 }, 618 &datastore.IndexDefinition{ 619 Kind: "TestFailureAnalysis", 620 SortBy: []datastore.IndexColumn{ 621 { 622 Property: "project", 623 }, 624 { 625 Property: "create_time", 626 Descending: true, 627 }, 628 }, 629 }, 630 ) 631 datastore.GetTestable(c).CatchupIndexes() 632 }