sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/tide/gerrit_test.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package tide 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "strconv" 24 "testing" 25 "time" 26 27 "github.com/andygrunwald/go-gerrit" 28 "github.com/google/go-cmp/cmp" 29 githubql "github.com/shurcooL/githubv4" 30 "github.com/sirupsen/logrus" 31 prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1" 32 "sigs.k8s.io/prow/pkg/config" 33 "sigs.k8s.io/prow/pkg/git/types" 34 "sigs.k8s.io/prow/pkg/kube" 35 "sigs.k8s.io/prow/pkg/tide/blockers" 36 37 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 38 fakectrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" 39 ) 40 41 var _ gerritClient = (*fakeGerritClient)(nil) 42 43 type fakeGerritClient struct { 44 // map{org: map{project: []changes}} 45 changes map[string]map[string][]gerrit.ChangeInfo 46 } 47 48 func newFakeGerritClient() *fakeGerritClient { 49 return &fakeGerritClient{ 50 changes: make(map[string]map[string][]gerrit.ChangeInfo), 51 } 52 } 53 54 func (f *fakeGerritClient) QueryChangesForProject(instance, project string, lastUpdate time.Time, rateLimit int, addtionalFilters ...string) ([]gerrit.ChangeInfo, error) { 55 if f.changes == nil || f.changes[instance] == nil || f.changes[instance][project] == nil { 56 return nil, errors.New("queries project doesn't exist") 57 } 58 59 return f.changes[instance][project], nil 60 } 61 62 func (f *fakeGerritClient) GetChange(instance, id string, addtionalFields ...string) (*gerrit.ChangeInfo, error) { 63 if f.changes == nil || f.changes[instance] == nil { 64 return nil, errors.New("instance not exist") 65 } 66 for _, prs := range f.changes[instance] { 67 for _, pr := range prs { 68 if pr.ID == id { 69 return &pr, nil 70 } 71 } 72 } 73 return nil, errors.New("change not exist") 74 } 75 76 func (f *fakeGerritClient) GetBranchRevision(instance, project, branch string) (string, error) { 77 return "abc", nil 78 } 79 80 func (f *fakeGerritClient) SubmitChange(instance, id string, wait bool) (*gerrit.ChangeInfo, error) { 81 return f.GetChange(instance, id) 82 } 83 84 func (f *fakeGerritClient) SetReview(instance, id, revision, message string, _ map[string]string) error { 85 change, err := f.GetChange(instance, id) 86 if err != nil { 87 return fmt.Errorf("change not found: %v", err) 88 } 89 revNum, err := strconv.Atoi(revision) 90 if err != nil { 91 return fmt.Errorf("failed converting revision '%s' to int: %v", revision, err) 92 } 93 change.Messages = append(change.Messages, gerrit.ChangeMessageInfo{ 94 RevisionNumber: revNum, 95 Message: message, 96 }) 97 98 return nil 99 } 100 101 func (f *fakeGerritClient) addChanges(instance, project string, changes []gerrit.ChangeInfo) { 102 if _, ok := f.changes[instance]; !ok { 103 f.changes[instance] = make(map[string][]gerrit.ChangeInfo) 104 } 105 if _, ok := f.changes[instance][project]; !ok { 106 f.changes[instance][project] = []gerrit.ChangeInfo{} 107 } 108 f.changes[instance][project] = append(f.changes[instance][project], changes...) 109 } 110 111 func TestGerritQueryParam(t *testing.T) { 112 tests := []struct { 113 name string 114 optIn bool 115 want string 116 }{ 117 { 118 name: "default", 119 optIn: false, 120 want: "status:open+-is:wip+is:submittable+-label:Prow-Auto-Submit=-1+label:Prow-Auto-Submit", 121 }, 122 { 123 name: "opt-in", 124 optIn: true, 125 want: "status:open+-is:wip+is:submittable+-label:Prow-Auto-Submit=-1", 126 }, 127 } 128 129 for _, tc := range tests { 130 tc := tc 131 t.Run(tc.name, func(t *testing.T) { 132 if want, got := tc.want, gerritQueryParam(tc.optIn); want != got { 133 t.Errorf("Wrong query param. Want: %s, got: %s", want, got) 134 } 135 }) 136 } 137 } 138 139 func TestQuery(t *testing.T) { 140 tests := []struct { 141 name string 142 queries config.GerritOrgRepoConfigs 143 prs map[string]map[string][]gerrit.ChangeInfo 144 expect map[string]CodeReviewCommon 145 wantErr bool 146 }{ 147 { 148 name: "single", 149 queries: config.GerritOrgRepoConfigs{ 150 { 151 Org: "foo1", 152 Repos: []string{"bar1"}, 153 }, 154 }, 155 prs: map[string]map[string][]gerrit.ChangeInfo{ 156 "foo1": { 157 "bar1": { 158 gerrit.ChangeInfo{ 159 Number: 1, 160 Project: "bar1", 161 }, 162 }, 163 }, 164 }, 165 expect: map[string]CodeReviewCommon{ 166 "foo1/bar1#1": *CodeReviewCommonFromGerrit(&gerrit.ChangeInfo{Number: 1, Project: "bar1"}, "foo1"), 167 }, 168 }, 169 { 170 name: "multiple", 171 queries: config.GerritOrgRepoConfigs{ 172 { 173 Org: "foo1", 174 Repos: []string{"bar1", "bar2"}, 175 }, 176 { 177 Org: "foo2", 178 Repos: []string{"bar3", "bar4"}, 179 }, 180 }, 181 prs: map[string]map[string][]gerrit.ChangeInfo{ 182 "foo1": { 183 "bar1": { 184 gerrit.ChangeInfo{ 185 Number: 1, 186 Project: "bar1", 187 }, 188 }, 189 "bar2": { 190 gerrit.ChangeInfo{ 191 Number: 2, 192 Project: "bar2", 193 }, 194 }, 195 }, 196 "foo2": { 197 "bar3": { 198 gerrit.ChangeInfo{ 199 Number: 1, 200 Project: "bar3", 201 }, 202 }, 203 "bar4": { 204 gerrit.ChangeInfo{ 205 Number: 2, 206 Project: "bar4", 207 }, 208 }, 209 }, 210 }, 211 expect: map[string]CodeReviewCommon{ 212 "foo1/bar1#1": *CodeReviewCommonFromGerrit(&gerrit.ChangeInfo{Number: 1, Project: "bar1"}, "foo1"), 213 "foo1/bar2#2": *CodeReviewCommonFromGerrit(&gerrit.ChangeInfo{Number: 2, Project: "bar2"}, "foo1"), 214 "foo2/bar3#1": *CodeReviewCommonFromGerrit(&gerrit.ChangeInfo{Number: 1, Project: "bar3"}, "foo2"), 215 "foo2/bar4#2": *CodeReviewCommonFromGerrit(&gerrit.ChangeInfo{Number: 2, Project: "bar4"}, "foo2"), 216 }, 217 }, 218 { 219 name: "not-configured", 220 queries: config.GerritOrgRepoConfigs{ 221 { 222 Org: "foo5", 223 Repos: []string{"bar1", "bar2"}, 224 }, 225 { 226 Org: "foo6", 227 Repos: []string{"bar3", "bar4"}, 228 }, 229 }, 230 prs: map[string]map[string][]gerrit.ChangeInfo{ 231 "foo1": { 232 "bar1": { 233 gerrit.ChangeInfo{ 234 Number: 1, 235 Project: "bar1", 236 }, 237 }, 238 "bar2": { 239 gerrit.ChangeInfo{ 240 Number: 2, 241 Project: "bar2", 242 }, 243 }, 244 }, 245 "foo2": { 246 "bar3": { 247 gerrit.ChangeInfo{ 248 Number: 1, 249 Project: "bar3", 250 }, 251 }, 252 "bar4": { 253 gerrit.ChangeInfo{ 254 Number: 2, 255 Project: "bar4", 256 }, 257 }, 258 }, 259 }, 260 wantErr: true, 261 }, 262 { 263 name: "no-pr", 264 queries: config.GerritOrgRepoConfigs{ 265 { 266 Org: "foo1", 267 Repos: []string{"bar1"}, 268 }, 269 }, 270 prs: map[string]map[string][]gerrit.ChangeInfo{ 271 "foo1": { 272 "bar1": {}, 273 }, 274 }, 275 expect: map[string]CodeReviewCommon{}, 276 }, 277 } 278 279 for _, tc := range tests { 280 tc := tc 281 t.Run(tc.name, func(t *testing.T) { 282 cfg := config.Config{ 283 ProwConfig: config.ProwConfig{ 284 Tide: config.Tide{ 285 Gerrit: &config.TideGerritConfig{ 286 Queries: tc.queries, 287 }, 288 }, 289 }, 290 } 291 292 fc := newGerritProvider(logrus.WithContext(context.Background()), func() *config.Config { return &cfg }, nil, nil, "", "", 0, 0) 293 fgc := newFakeGerritClient() 294 295 for instance, projs := range tc.prs { 296 for project, changes := range projs { 297 fgc.addChanges(instance, project, changes) 298 } 299 } 300 fc.gc = fgc 301 302 got, err := fc.Query() 303 if (tc.wantErr && err == nil) || (!tc.wantErr && err != nil) { 304 t.Fatalf("Error mismatch. Want: %v, got: %v", tc.wantErr, err) 305 } 306 if diff := cmp.Diff(tc.expect, got); diff != "" { 307 t.Fatalf("Query result mismatch. Want(-), got(+):\n%s", diff) 308 } 309 }) 310 } 311 } 312 313 func TestBlocker(t *testing.T) { 314 fc := &GerritProvider{} 315 want := blockers.Blockers{} 316 var wantErr error 317 got, gotErr := fc.blockers() 318 if diff := cmp.Diff(want, got); diff != "" { 319 t.Errorf("Blocker mismatch. Want(-), got(+):\n%s", diff) 320 } 321 if wantErr != gotErr { 322 t.Errorf("Error mismatch. Want: %v, got: %v", wantErr, gotErr) 323 } 324 } 325 326 func TestIsAllowedToMerge(t *testing.T) { 327 tests := []struct { 328 name string 329 mergeable string 330 want string 331 wantErr error 332 }{ 333 { 334 name: "conflict", 335 mergeable: string(githubql.MergeableStateConflicting), 336 want: "PR has a merge conflict.", 337 }, 338 { 339 name: "normal", 340 mergeable: string(githubql.MergeableStateMergeable), 341 }, 342 } 343 344 for _, tc := range tests { 345 tc := tc 346 t.Run(tc.name, func(t *testing.T) { 347 fc := &GerritProvider{} 348 got, gotErr := fc.isAllowedToMerge(&CodeReviewCommon{Mergeable: tc.mergeable}) 349 350 if diff := cmp.Diff(tc.want, got); diff != "" { 351 t.Errorf("Blocker mismatch. Want(-), got(+):\n%s", diff) 352 } 353 if tc.wantErr != gotErr { 354 t.Errorf("Error mismatch. Want: %v, got: %v", tc.wantErr, gotErr) 355 } 356 }) 357 } 358 } 359 360 func TestGetRef(t *testing.T) { 361 fgc := newFakeGerritClient() 362 fc := &GerritProvider{gc: fgc} 363 got, _ := fc.GetRef("", "", "") 364 365 want := "abc" 366 if diff := cmp.Diff(want, got); diff != "" { 367 t.Errorf("Blocker mismatch. Want(-), got(+):\n%s", diff) 368 } 369 } 370 371 func TestGerritHeadContexts(t *testing.T) { 372 tests := []struct { 373 name string 374 jobs []prowapi.ProwJob 375 want []Context 376 wantErr error 377 }{ 378 { 379 name: "normal", 380 jobs: []prowapi.ProwJob{ 381 { 382 ObjectMeta: metav1.ObjectMeta{ 383 Name: "not-important-1", 384 Namespace: "prowjobs", 385 Labels: map[string]string{ 386 kube.GerritRevision: "abc123", 387 kube.ProwJobTypeLabel: string(prowapi.PresubmitJob), 388 kube.OrgLabel: "foo1", 389 kube.RepoLabel: "bar1", 390 kube.PullLabel: "1", 391 }, 392 }, 393 Spec: prowapi.ProwJobSpec{ 394 Type: prowapi.PresubmitJob, 395 Job: "job-1", 396 Context: "job-1", 397 Refs: &prowapi.Refs{ 398 BaseSHA: "def123", 399 }, 400 }, 401 Status: prowapi.ProwJobStatus{ 402 State: prowapi.SuccessState, 403 Description: "desc", 404 }, 405 }, 406 }, 407 want: []Context{ 408 { 409 Context: "job-1", 410 Description: "desc\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\xe2\x80\x81\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001\u2001 BaseSHA:def123", 411 State: "success", 412 }, 413 }, 414 }, 415 { 416 name: "periodic", 417 jobs: []prowapi.ProwJob{ 418 { 419 ObjectMeta: metav1.ObjectMeta{ 420 Name: "not-important-1", 421 Namespace: "prowjobs", 422 Labels: map[string]string{ 423 kube.GerritRevision: "abc123", 424 kube.ProwJobTypeLabel: string(prowapi.PeriodicJob), 425 kube.OrgLabel: "foo1", 426 kube.RepoLabel: "bar1", 427 kube.PullLabel: "1", 428 }, 429 }, 430 Spec: prowapi.ProwJobSpec{ 431 Type: prowapi.PeriodicJob, 432 Job: "job-1", 433 Context: "job-1", 434 Refs: &prowapi.Refs{ 435 BaseSHA: "def123", 436 }, 437 }, 438 Status: prowapi.ProwJobStatus{ 439 State: prowapi.SuccessState, 440 Description: "desc", 441 }, 442 }, 443 }, 444 }, 445 { 446 name: "wrong-org", 447 jobs: []prowapi.ProwJob{ 448 { 449 ObjectMeta: metav1.ObjectMeta{ 450 Name: "not-important-1", 451 Namespace: "prowjobs", 452 Labels: map[string]string{ 453 kube.GerritRevision: "abc123", 454 kube.ProwJobTypeLabel: string(prowapi.PresubmitJob), 455 kube.OrgLabel: "foo2", 456 kube.RepoLabel: "bar1", 457 kube.PullLabel: "1", 458 }, 459 }, 460 Spec: prowapi.ProwJobSpec{ 461 Type: prowapi.PresubmitJob, 462 Job: "job-1", 463 Context: "job-1", 464 Refs: &prowapi.Refs{ 465 BaseSHA: "def123", 466 }, 467 }, 468 Status: prowapi.ProwJobStatus{ 469 State: prowapi.SuccessState, 470 Description: "desc", 471 }, 472 }, 473 }, 474 }, 475 { 476 name: "wrong-repo", 477 jobs: []prowapi.ProwJob{ 478 { 479 ObjectMeta: metav1.ObjectMeta{ 480 Name: "not-important-1", 481 Namespace: "prowjobs", 482 Labels: map[string]string{ 483 kube.GerritRevision: "abc123", 484 kube.ProwJobTypeLabel: string(prowapi.PresubmitJob), 485 kube.OrgLabel: "foo1", 486 kube.RepoLabel: "bar2", 487 kube.PullLabel: "1", 488 }, 489 }, 490 Spec: prowapi.ProwJobSpec{ 491 Type: prowapi.PresubmitJob, 492 Job: "job-1", 493 Context: "job-1", 494 Refs: &prowapi.Refs{ 495 BaseSHA: "def123", 496 }, 497 }, 498 Status: prowapi.ProwJobStatus{ 499 State: prowapi.SuccessState, 500 Description: "desc", 501 }, 502 }, 503 }, 504 }, 505 { 506 name: "wrong-revision", 507 jobs: []prowapi.ProwJob{ 508 { 509 ObjectMeta: metav1.ObjectMeta{ 510 Name: "not-important-1", 511 Namespace: "prowjobs", 512 Labels: map[string]string{ 513 kube.GerritRevision: "abc456", 514 kube.ProwJobTypeLabel: string(prowapi.PresubmitJob), 515 kube.OrgLabel: "foo1", 516 kube.RepoLabel: "bar1", 517 kube.PullLabel: "1", 518 }, 519 }, 520 Spec: prowapi.ProwJobSpec{ 521 Type: prowapi.PresubmitJob, 522 Job: "job-1", 523 Context: "job-1", 524 Refs: &prowapi.Refs{ 525 BaseSHA: "def123", 526 }, 527 }, 528 Status: prowapi.ProwJobStatus{ 529 State: prowapi.SuccessState, 530 Description: "desc", 531 }, 532 }, 533 }, 534 }, 535 { 536 name: "wrong-pull", 537 jobs: []prowapi.ProwJob{ 538 { 539 ObjectMeta: metav1.ObjectMeta{ 540 Name: "not-important-1", 541 Namespace: "prowjobs", 542 Labels: map[string]string{ 543 kube.GerritRevision: "abc123", 544 kube.ProwJobTypeLabel: string(prowapi.PresubmitJob), 545 kube.OrgLabel: "foo1", 546 kube.RepoLabel: "bar1", 547 kube.PullLabel: "2", 548 }, 549 }, 550 Spec: prowapi.ProwJobSpec{ 551 Type: prowapi.PresubmitJob, 552 Job: "job-1", 553 Context: "job-1", 554 Refs: &prowapi.Refs{ 555 BaseSHA: "def123", 556 }, 557 }, 558 Status: prowapi.ProwJobStatus{ 559 State: prowapi.SuccessState, 560 Description: "desc", 561 }, 562 }, 563 }, 564 }, 565 } 566 567 for _, tc := range tests { 568 tc := tc 569 t.Run(tc.name, func(t *testing.T) { 570 builder := fakectrlruntimeclient.NewClientBuilder() 571 for i := range tc.jobs { 572 job := tc.jobs[i] 573 complete := metav1.NewTime(time.Now().Add(-time.Millisecond)) 574 if job.Status.State != prowapi.PendingState && job.Status.State != prowapi.TriggeredState { 575 job.Status.CompletionTime = &complete 576 } 577 578 builder.WithRuntimeObjects(&job) 579 } 580 581 fpjc := builder.Build() 582 fc := &GerritProvider{pjclientset: fpjc} 583 584 got, gotErr := fc.headContexts(&CodeReviewCommon{ 585 HeadRefOID: "abc123", 586 Org: "foo1", 587 Repo: "bar1", 588 Number: 1, 589 }) 590 591 if diff := cmp.Diff(tc.want, got); diff != "" { 592 t.Errorf("Blocker mismatch. Want(-), got(+):\n%s", diff) 593 } 594 if tc.wantErr != gotErr { 595 t.Errorf("Error mismatch. Want: %v, got: %v", tc.wantErr, gotErr) 596 } 597 }) 598 } 599 } 600 601 func TestMergePR(t *testing.T) { 602 tests := []struct { 603 name string 604 subpool subpool 605 clientChanges map[string]map[string][]gerrit.ChangeInfo 606 prs []gerrit.ChangeInfo 607 wantErr error 608 }{ 609 { 610 name: "single", 611 subpool: subpool{ 612 org: "org", 613 repo: "repo", 614 }, 615 clientChanges: map[string]map[string][]gerrit.ChangeInfo{ 616 "org": { 617 "repo": { 618 { 619 ID: "abc123", 620 }, 621 }, 622 }, 623 }, 624 prs: []gerrit.ChangeInfo{ 625 { 626 ID: "abc123", 627 }, 628 }, 629 wantErr: nil, 630 }, 631 { 632 name: "multiple", 633 subpool: subpool{ 634 org: "org", 635 repo: "repo", 636 }, 637 clientChanges: map[string]map[string][]gerrit.ChangeInfo{ 638 "org": { 639 "repo": { 640 { 641 ID: "abc123", 642 }, 643 { 644 ID: "def456", 645 }, 646 }, 647 }, 648 }, 649 prs: []gerrit.ChangeInfo{ 650 { 651 ID: "abc123", 652 }, 653 { 654 ID: "def456", 655 }, 656 }, 657 wantErr: nil, 658 }, 659 { 660 name: "single-error", 661 subpool: subpool{ 662 org: "org", 663 repo: "repo", 664 }, 665 // Empty changes results in SubmitChange error. 666 clientChanges: map[string]map[string][]gerrit.ChangeInfo{}, 667 prs: []gerrit.ChangeInfo{ 668 { 669 ID: "abc123", 670 }, 671 }, 672 wantErr: errors.New("failed submitting change 'org' from org 'abc123': instance not exist"), 673 }, 674 { 675 name: "multiple-error", 676 subpool: subpool{ 677 org: "org", 678 repo: "repo", 679 }, 680 // Empty changes results in SubmitChange error. 681 clientChanges: map[string]map[string][]gerrit.ChangeInfo{}, 682 prs: []gerrit.ChangeInfo{ 683 { 684 ID: "abc123", 685 }, 686 { 687 ID: "def456", 688 }, 689 }, 690 wantErr: errors.New("[failed submitting change 'org' from org 'abc123': instance not exist, failed submitting change 'org' from org 'def456': instance not exist]"), 691 }, 692 { 693 name: "partial-error", 694 subpool: subpool{ 695 org: "org", 696 repo: "repo", 697 }, 698 clientChanges: map[string]map[string][]gerrit.ChangeInfo{ 699 "org": { 700 "repo": { 701 { 702 ID: "abc123", 703 }, 704 }, 705 }, 706 }, 707 prs: []gerrit.ChangeInfo{ 708 { 709 ID: "abc123", 710 }, 711 { 712 ID: "def456", 713 }, 714 }, 715 wantErr: errors.New("failed submitting change 'org' from org 'def456': change not exist"), 716 }, 717 } 718 719 for _, tc := range tests { 720 tc := tc 721 t.Run(tc.name, func(t *testing.T) { 722 fgc := newFakeGerritClient() 723 fgc.changes = tc.clientChanges 724 cfg := config.Config{ 725 ProwConfig: config.ProwConfig{ 726 Gerrit: config.Gerrit{ 727 DeckURL: "http://foo.bar", 728 }, 729 }, 730 } 731 fc := &GerritProvider{ 732 logger: logrus.WithContext(context.Background()), 733 gc: fgc, 734 cfg: func() *config.Config { return &cfg }, 735 } 736 737 var prsToMerge []CodeReviewCommon 738 for _, pr := range tc.prs { 739 prsToMerge = append(prsToMerge, *CodeReviewCommonFromGerrit(&pr, tc.subpool.org)) 740 } 741 742 _, gotErr := fc.mergePRs(tc.subpool, prsToMerge, nil) 743 if tc.wantErr == nil { 744 if gotErr != nil { 745 t.Fatalf("Error mismatch. Want nil, got: %v", gotErr) 746 } 747 return 748 } 749 if gotErr == nil { 750 t.Fatalf("Error mismatch. Want %v, got nil", tc.wantErr) 751 } 752 if tc.wantErr.Error() != gotErr.Error() { 753 t.Fatalf("Error not matching. Want: %v, got: %v", tc.wantErr, gotErr) 754 } 755 }) 756 } 757 } 758 759 func TestGetTideContextPolicy(t *testing.T) { 760 tests := []struct { 761 name string 762 pr gerrit.ChangeInfo 763 cloneURI string 764 presubmits map[string][]config.Presubmit 765 want contextChecker 766 wantErr error 767 }{ 768 { 769 name: "base", 770 pr: gerrit.ChangeInfo{ 771 Project: "bar1", 772 Branch: "main", 773 CurrentRevision: "abc123", 774 Labels: map[string]gerrit.LabelInfo{ 775 "Verified": { 776 Optional: false, 777 }, 778 }, 779 }, 780 presubmits: map[string][]config.Presubmit{ 781 "https://foo1/bar1": { 782 { 783 Reporter: config.Reporter{Context: "job-1"}, 784 JobBase: config.JobBase{ 785 Labels: map[string]string{ 786 "prow.k8s.io/gerrit-report-label": "Verified", 787 }, 788 }, 789 }, 790 }, 791 }, 792 want: &gerritContextChecker{}, 793 }, 794 { 795 name: "no-job", 796 pr: gerrit.ChangeInfo{ 797 Project: "bar1", 798 Branch: "main", 799 CurrentRevision: "abc123", 800 Labels: map[string]gerrit.LabelInfo{ 801 "Verified": { 802 Optional: false, 803 }, 804 }, 805 }, 806 presubmits: map[string][]config.Presubmit{ 807 "https://foo1/bar1": {}, 808 }, 809 want: &gerritContextChecker{}, 810 }, 811 } 812 813 for _, tc := range tests { 814 tc := tc 815 t.Run(tc.name, func(t *testing.T) { 816 cfg := config.Config{JobConfig: config.JobConfig{PresubmitsStatic: tc.presubmits}} 817 fc := &GerritProvider{cfg: func() *config.Config { return &cfg }} 818 819 got, gotErr := fc.GetTideContextPolicy("foo1", tc.pr.Project, tc.pr.Branch, nil, CodeReviewCommonFromGerrit(&tc.pr, "foo1")) 820 821 if diff := cmp.Diff(tc.want, got); diff != "" { 822 t.Errorf("Blocker mismatch. Want(-), got(+):\n%s", diff) 823 } 824 if tc.wantErr != gotErr { 825 t.Errorf("Error mismatch. Want: %v, got: %v", tc.wantErr, gotErr) 826 } 827 }) 828 } 829 } 830 831 func TestPrMergeMethod(t *testing.T) { 832 tests := []struct { 833 name string 834 pr gerrit.ChangeInfo 835 want types.PullRequestMergeType 836 }{ 837 { 838 name: "MERGE_IF_NECESSARY", 839 pr: gerrit.ChangeInfo{ 840 SubmitType: "MERGE_IF_NECESSARY", 841 }, 842 want: types.MergeIfNecessary, 843 }, 844 { 845 name: "FAST_FORWARD_ONLY", 846 pr: gerrit.ChangeInfo{ 847 SubmitType: "FAST_FORWARD_ONLY", 848 }, 849 want: types.MergeMerge, 850 }, 851 { 852 name: "REBASE_IF_NECESSARY", 853 pr: gerrit.ChangeInfo{ 854 SubmitType: "REBASE_IF_NECESSARY", 855 }, 856 want: types.MergeRebase, 857 }, 858 { 859 name: "REBASE_ALWAYS", 860 pr: gerrit.ChangeInfo{ 861 SubmitType: "REBASE_ALWAYS", 862 }, 863 want: types.MergeRebase, 864 }, 865 { 866 name: "MERGE_ALWAYS", 867 pr: gerrit.ChangeInfo{ 868 SubmitType: "MERGE_ALWAYS", 869 }, 870 want: types.MergeMerge, 871 }, 872 { 873 name: "NOT_EXIST", 874 pr: gerrit.ChangeInfo{ 875 SubmitType: "NOT_EXIST", 876 }, 877 want: types.MergeMerge, 878 }, 879 } 880 881 for _, tc := range tests { 882 tc := tc 883 t.Run(tc.name, func(t *testing.T) { 884 fc := &GerritProvider{} 885 886 got := fc.prMergeMethod(CodeReviewCommonFromGerrit(&tc.pr, "foo1")) 887 if got == nil { 888 t.Error("Multiple conflicting merge methods assigned.") 889 } else { 890 if diff := cmp.Diff(tc.want, *got); diff != "" { 891 t.Errorf("Blocker mismatch. Want(-), got(+):\n%s", diff) 892 } 893 } 894 }) 895 } 896 } 897 898 func TestJobIsRequiredByTide(t *testing.T) { 899 tests := []struct { 900 name string 901 ps *config.Presubmit 902 crc *CodeReviewCommon 903 want bool 904 }{ 905 { 906 name: "default", 907 ps: &config.Presubmit{}, 908 crc: &CodeReviewCommon{ 909 Gerrit: &gerrit.ChangeInfo{Labels: map[string]gerrit.LabelInfo{}}, 910 }, 911 }, 912 { 913 name: "run-before-merge", 914 ps: &config.Presubmit{RunBeforeMerge: true}, 915 crc: &CodeReviewCommon{ 916 Gerrit: &gerrit.ChangeInfo{Labels: map[string]gerrit.LabelInfo{}}, 917 }, 918 want: true, 919 }, 920 { 921 name: "required-label", 922 ps: &config.Presubmit{JobBase: config.JobBase{Labels: map[string]string{ 923 "prow.k8s.io/gerrit-report-label": "Verified-By-Prow", 924 }}}, 925 crc: &CodeReviewCommon{ 926 Gerrit: &gerrit.ChangeInfo{Labels: map[string]gerrit.LabelInfo{"Verified-By-Prow": {}}}, 927 }, 928 want: true, 929 }, 930 { 931 name: "optional-label", 932 ps: &config.Presubmit{JobBase: config.JobBase{Labels: map[string]string{ 933 "prow.k8s.io/gerrit-report-label": "Verified-By-Prow", 934 }}}, 935 crc: &CodeReviewCommon{ 936 Gerrit: &gerrit.ChangeInfo{Labels: map[string]gerrit.LabelInfo{"Verified-By-Prow": {Optional: true}}}, 937 }, 938 }, 939 } 940 941 for _, tc := range tests { 942 tc := tc 943 t.Run(tc.name, func(t *testing.T) { 944 fc := &GerritProvider{} 945 if want, got := tc.want, fc.jobIsRequiredByTide(tc.ps, tc.crc); want != got { 946 t.Errorf("Wrong. Want: %v, got: %v", want, got) 947 } 948 }) 949 } 950 }