sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/size/size_test.go (about) 1 /* 2 Copyright 2016 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 size 18 19 import ( 20 "testing" 21 22 "github.com/sirupsen/logrus" 23 24 "sigs.k8s.io/prow/pkg/config" 25 "sigs.k8s.io/prow/pkg/github" 26 "sigs.k8s.io/prow/pkg/plugins" 27 ) 28 29 type ghc struct { 30 *testing.T 31 labels map[github.Label]bool 32 files map[string][]byte 33 prChanges []github.PullRequestChange 34 35 addLabelErr, removeLabelErr, getIssueLabelsErr, 36 getFileErr, getPullRequestChangesErr error 37 } 38 39 func (c *ghc) AddLabel(_, _ string, _ int, label string) error { 40 c.T.Logf("AddLabel: %s", label) 41 c.labels[github.Label{Name: label}] = true 42 43 return c.addLabelErr 44 } 45 46 func (c *ghc) RemoveLabel(_, _ string, _ int, label string) error { 47 c.T.Logf("RemoveLabel: %s", label) 48 for k := range c.labels { 49 if k.Name == label { 50 delete(c.labels, k) 51 } 52 } 53 54 return c.removeLabelErr 55 } 56 57 func (c *ghc) GetIssueLabels(_, _ string, _ int) (ls []github.Label, err error) { 58 c.T.Log("GetIssueLabels") 59 for k, ok := range c.labels { 60 if ok { 61 ls = append(ls, k) 62 } 63 } 64 65 err = c.getIssueLabelsErr 66 return 67 } 68 69 func (c *ghc) GetFile(_, _, path, _ string) ([]byte, error) { 70 c.T.Logf("GetFile: %s", path) 71 return c.files[path], c.getFileErr 72 } 73 74 func (c *ghc) GetPullRequestChanges(_, _ string, _ int) ([]github.PullRequestChange, error) { 75 c.T.Log("GetPullRequestChanges") 76 return c.prChanges, c.getPullRequestChangesErr 77 } 78 79 func TestSizesOrDefault(t *testing.T) { 80 for _, c := range []struct { 81 input plugins.Size 82 expected plugins.Size 83 }{ 84 { 85 input: defaultSizes, 86 expected: defaultSizes, 87 }, 88 { 89 input: plugins.Size{ 90 S: 12, 91 M: 15, 92 L: 17, 93 Xl: 21, 94 Xxl: 51, 95 }, 96 expected: plugins.Size{ 97 S: 12, 98 M: 15, 99 L: 17, 100 Xl: 21, 101 Xxl: 51, 102 }, 103 }, 104 { 105 input: plugins.Size{}, 106 expected: defaultSizes, 107 }, 108 } { 109 if c.expected != sizesOrDefault(c.input) { 110 t.Fatalf("Unexpected sizes from sizesOrDefault - expected %+v but got %+v", c.expected, sizesOrDefault(c.input)) 111 } 112 } 113 } 114 115 func TestHandlePR(t *testing.T) { 116 cases := []struct { 117 name string 118 client *ghc 119 event github.PullRequestEvent 120 err error 121 sizes plugins.Size 122 finalLabels []github.Label 123 }{ 124 { 125 name: "simple size/S, no .generated_files", 126 client: &ghc{ 127 labels: map[github.Label]bool{}, 128 getFileErr: &github.FileNotFound{}, 129 prChanges: []github.PullRequestChange{ 130 { 131 SHA: "abcd", 132 Filename: "foobar", 133 Additions: 10, 134 Deletions: 10, 135 Changes: 20, 136 }, 137 { 138 SHA: "abcd", 139 Filename: "barfoo", 140 Additions: 3, 141 Deletions: 4, 142 Changes: 7, 143 }, 144 }, 145 }, 146 event: github.PullRequestEvent{ 147 Action: github.PullRequestActionOpened, 148 Number: 101, 149 PullRequest: github.PullRequest{ 150 Number: 101, 151 Base: github.PullRequestBranch{ 152 SHA: "abcd", 153 Repo: github.Repo{ 154 Owner: github.User{ 155 Login: "kubernetes", 156 }, 157 Name: "kubernetes", 158 }, 159 }, 160 }, 161 }, 162 finalLabels: []github.Label{ 163 {Name: "size/S"}, 164 }, 165 sizes: defaultSizes, 166 }, 167 { 168 name: "simple size/M, with .generated_files", 169 client: &ghc{ 170 labels: map[github.Label]bool{}, 171 files: map[string][]byte{ 172 ".generated_files": []byte(` 173 file-name foobar 174 175 path-prefix generated 176 `), 177 }, 178 prChanges: []github.PullRequestChange{ 179 { 180 SHA: "abcd", 181 Filename: "foobar", 182 Additions: 10, 183 Deletions: 10, 184 Changes: 20, 185 }, 186 { 187 SHA: "abcd", 188 Filename: "barfoo", 189 Additions: 50, 190 Deletions: 0, 191 Changes: 50, 192 }, 193 { 194 SHA: "abcd", 195 Filename: "generated/what.txt", 196 Additions: 30, 197 Deletions: 0, 198 Changes: 30, 199 }, 200 { 201 SHA: "abcd", 202 Filename: "generated/my/file.txt", 203 Additions: 300, 204 Deletions: 0, 205 Changes: 300, 206 }, 207 }, 208 }, 209 event: github.PullRequestEvent{ 210 Action: github.PullRequestActionOpened, 211 Number: 101, 212 PullRequest: github.PullRequest{ 213 Number: 101, 214 Base: github.PullRequestBranch{ 215 SHA: "abcd", 216 Repo: github.Repo{ 217 Owner: github.User{ 218 Login: "kubernetes", 219 }, 220 Name: "kubernetes", 221 }, 222 }, 223 }, 224 }, 225 finalLabels: []github.Label{ 226 {Name: "size/M"}, 227 }, 228 sizes: defaultSizes, 229 }, 230 { 231 name: "simple size/M, with .gitattributes", 232 client: &ghc{ 233 labels: map[github.Label]bool{}, 234 files: map[string][]byte{ 235 ".gitattributes": []byte(` 236 # comments 237 foobar linguist-generated=true 238 generated/**/*.txt linguist-generated=true 239 `), 240 }, 241 prChanges: []github.PullRequestChange{ 242 { 243 SHA: "abcd", 244 Filename: "foobar", 245 Additions: 10, 246 Deletions: 10, 247 Changes: 20, 248 }, 249 { 250 SHA: "abcd", 251 Filename: "barfoo", 252 Additions: 50, 253 Deletions: 0, 254 Changes: 50, 255 }, 256 { 257 SHA: "abcd", 258 Filename: "generated/what.txt", 259 Additions: 30, 260 Deletions: 0, 261 Changes: 30, 262 }, 263 { 264 SHA: "abcd", 265 Filename: "generated/my/file.txt", 266 Additions: 300, 267 Deletions: 0, 268 Changes: 300, 269 }, 270 }, 271 }, 272 event: github.PullRequestEvent{ 273 Action: github.PullRequestActionOpened, 274 Number: 101, 275 PullRequest: github.PullRequest{ 276 Number: 101, 277 Base: github.PullRequestBranch{ 278 SHA: "abcd", 279 Repo: github.Repo{ 280 Owner: github.User{ 281 Login: "kubernetes", 282 }, 283 Name: "kubernetes", 284 }, 285 }, 286 }, 287 }, 288 finalLabels: []github.Label{ 289 {Name: "size/M"}, 290 }, 291 sizes: defaultSizes, 292 }, 293 { 294 name: "simple size/XS, with .generated_files and paths-from-repo", 295 client: &ghc{ 296 labels: map[github.Label]bool{}, 297 files: map[string][]byte{ 298 ".generated_files": []byte(` 299 # Comments 300 file-name foobar 301 302 path-prefix generated 303 304 paths-from-repo docs/.generated_docs 305 `), 306 "docs/.generated_docs": []byte(` 307 # Comments work 308 309 # And empty lines don't matter 310 foobar 311 mypath1 312 mypath2 313 mydir/mypath3 314 `), 315 }, 316 prChanges: []github.PullRequestChange{ 317 { 318 SHA: "abcd", 319 Filename: "foobar", 320 Additions: 10, 321 Deletions: 10, 322 Changes: 20, 323 }, 324 { // Notice "barfoo" is the only relevant change. 325 SHA: "abcd", 326 Filename: "barfoo", 327 Additions: 5, 328 Deletions: 0, 329 Changes: 5, 330 }, 331 { 332 SHA: "abcd", 333 Filename: "generated/what.txt", 334 Additions: 30, 335 Deletions: 0, 336 Changes: 30, 337 }, 338 { 339 SHA: "abcd", 340 Filename: "generated/my/file.txt", 341 Additions: 300, 342 Deletions: 0, 343 Changes: 300, 344 }, 345 { 346 SHA: "abcd", 347 Filename: "mypath1", 348 Additions: 300, 349 Deletions: 0, 350 Changes: 300, 351 }, 352 { 353 SHA: "abcd", 354 Filename: "mydir/mypath3", 355 Additions: 300, 356 Deletions: 0, 357 Changes: 300, 358 }, 359 }, 360 }, 361 event: github.PullRequestEvent{ 362 Action: github.PullRequestActionOpened, 363 Number: 101, 364 PullRequest: github.PullRequest{ 365 Number: 101, 366 Base: github.PullRequestBranch{ 367 SHA: "abcd", 368 Repo: github.Repo{ 369 Owner: github.User{ 370 Login: "kubernetes", 371 }, 372 Name: "kubernetes", 373 }, 374 }, 375 }, 376 }, 377 finalLabels: []github.Label{ 378 {Name: "size/XS"}, 379 }, 380 sizes: defaultSizes, 381 }, 382 { 383 name: "pr closed event", 384 client: &ghc{}, 385 event: github.PullRequestEvent{ 386 Action: github.PullRequestActionClosed, 387 }, 388 finalLabels: []github.Label{}, 389 sizes: defaultSizes, 390 }, 391 { 392 name: "XS -> S transition", 393 client: &ghc{ 394 labels: map[github.Label]bool{ 395 {Name: "irrelevant"}: true, 396 {Name: "size/XS"}: true, 397 }, 398 files: map[string][]byte{ 399 ".generated_files": []byte(` 400 # Comments 401 file-name foobar 402 403 path-prefix generated 404 405 paths-from-repo docs/.generated_docs 406 `), 407 "docs/.generated_docs": []byte(` 408 # Comments work 409 410 # And empty lines don't matter 411 foobar 412 mypath1 413 mypath2 414 mydir/mypath3 415 `), 416 }, 417 prChanges: []github.PullRequestChange{ 418 { 419 SHA: "abcd", 420 Filename: "foobar", 421 Additions: 10, 422 Deletions: 10, 423 Changes: 20, 424 }, 425 { // Notice "barfoo" is the only relevant change. 426 SHA: "abcd", 427 Filename: "barfoo", 428 Additions: 5, 429 Deletions: 0, 430 Changes: 5, 431 }, 432 { 433 SHA: "abcd", 434 Filename: "generated/what.txt", 435 Additions: 30, 436 Deletions: 0, 437 Changes: 30, 438 }, 439 { 440 SHA: "abcd", 441 Filename: "generated/my/file.txt", 442 Additions: 300, 443 Deletions: 0, 444 Changes: 300, 445 }, 446 { 447 SHA: "abcd", 448 Filename: "mypath1", 449 Additions: 300, 450 Deletions: 0, 451 Changes: 300, 452 }, 453 { 454 SHA: "abcd", 455 Filename: "mydir/mypath3", 456 Additions: 300, 457 Deletions: 0, 458 Changes: 300, 459 }, 460 }, 461 }, 462 event: github.PullRequestEvent{ 463 Action: github.PullRequestActionOpened, 464 Number: 101, 465 PullRequest: github.PullRequest{ 466 Number: 101, 467 Base: github.PullRequestBranch{ 468 SHA: "abcd", 469 Repo: github.Repo{ 470 Owner: github.User{ 471 Login: "kubernetes", 472 }, 473 Name: "kubernetes", 474 }, 475 }, 476 }, 477 }, 478 finalLabels: []github.Label{ 479 {Name: "irrelevant"}, 480 {Name: "size/XS"}, 481 }, 482 sizes: defaultSizes, 483 }, 484 { 485 name: "pull request reopened", 486 client: &ghc{ 487 labels: map[github.Label]bool{}, 488 getFileErr: &github.FileNotFound{}, 489 prChanges: []github.PullRequestChange{ 490 { 491 SHA: "abcd", 492 Filename: "foobar", 493 Additions: 10, 494 Deletions: 10, 495 Changes: 20, 496 }, 497 { 498 SHA: "abcd", 499 Filename: "barfoo", 500 Additions: 3, 501 Deletions: 4, 502 Changes: 7, 503 }, 504 }, 505 }, 506 event: github.PullRequestEvent{ 507 Action: github.PullRequestActionReopened, 508 Number: 101, 509 PullRequest: github.PullRequest{ 510 Number: 101, 511 Base: github.PullRequestBranch{ 512 SHA: "abcd", 513 Repo: github.Repo{ 514 Owner: github.User{ 515 Login: "kubernetes", 516 }, 517 Name: "kubernetes", 518 }, 519 }, 520 }, 521 }, 522 finalLabels: []github.Label{ 523 {Name: "size/S"}, 524 }, 525 sizes: defaultSizes, 526 }, 527 { 528 name: "pull request edited", 529 client: &ghc{ 530 labels: map[github.Label]bool{}, 531 getFileErr: &github.FileNotFound{}, 532 prChanges: []github.PullRequestChange{ 533 { 534 SHA: "abcd", 535 Filename: "foobar", 536 Additions: 30, 537 Deletions: 40, 538 Changes: 70, 539 }, 540 }, 541 }, 542 event: github.PullRequestEvent{ 543 Action: github.PullRequestActionEdited, 544 Number: 101, 545 PullRequest: github.PullRequest{ 546 Number: 101, 547 Base: github.PullRequestBranch{ 548 SHA: "abcd", 549 Repo: github.Repo{ 550 Owner: github.User{ 551 Login: "kubernetes", 552 }, 553 Name: "kubernetes", 554 }, 555 }, 556 }, 557 }, 558 finalLabels: []github.Label{ 559 {Name: "size/M"}, 560 }, 561 sizes: defaultSizes, 562 }, 563 { 564 name: "different label constraints", 565 client: &ghc{ 566 labels: map[github.Label]bool{}, 567 getFileErr: &github.FileNotFound{}, 568 prChanges: []github.PullRequestChange{ 569 { 570 SHA: "abcd", 571 Filename: "foobar", 572 Additions: 10, 573 Deletions: 10, 574 Changes: 20, 575 }, 576 { 577 SHA: "abcd", 578 Filename: "barfoo", 579 Additions: 3, 580 Deletions: 4, 581 Changes: 7, 582 }, 583 }, 584 }, 585 event: github.PullRequestEvent{ 586 Action: github.PullRequestActionOpened, 587 Number: 101, 588 PullRequest: github.PullRequest{ 589 Number: 101, 590 Base: github.PullRequestBranch{ 591 SHA: "abcd", 592 Repo: github.Repo{ 593 Owner: github.User{ 594 Login: "kubernetes", 595 }, 596 Name: "kubernetes", 597 }, 598 }, 599 }, 600 }, 601 finalLabels: []github.Label{ 602 {Name: "size/XXL"}, 603 }, 604 sizes: plugins.Size{ 605 S: 0, 606 M: 1, 607 L: 2, 608 Xl: 3, 609 Xxl: 4, 610 }, 611 }, 612 } 613 614 for _, c := range cases { 615 t.Run(c.name, func(t *testing.T) { 616 if c.client == nil { 617 t.Fatalf("case can not have nil github client") 618 } 619 620 // Set up test logging. 621 c.client.T = t 622 623 err := handlePR(c.client, c.sizes, logrus.NewEntry(logrus.New()), c.event) 624 625 if err != nil && c.err == nil { 626 t.Fatalf("handlePR error: %v", err) 627 } 628 629 if err == nil && c.err != nil { 630 t.Fatalf("handlePR wanted error %v, got nil", err) 631 } 632 633 if got, want := err, c.err; got != nil && got.Error() != want.Error() { 634 t.Fatalf("handlePR errors mismatch: got %v, want %v", got, want) 635 } 636 637 if got, want := len(c.client.labels), len(c.finalLabels); got != want { 638 t.Logf("github client labels: got %v; want %v", c.client.labels, c.finalLabels) 639 t.Fatalf("finalLabels count mismatch: got %d, want %d", got, want) 640 } 641 642 for _, l := range c.finalLabels { 643 if !c.client.labels[l] { 644 t.Fatalf("github client labels missing %v", l) 645 } 646 } 647 }) 648 } 649 } 650 651 func TestHelpProvider(t *testing.T) { 652 enabledRepos := []config.OrgRepo{ 653 {Org: "org1", Repo: "repo"}, 654 {Org: "org2", Repo: "repo"}, 655 } 656 cases := []struct { 657 name string 658 config *plugins.Configuration 659 enabledRepos []config.OrgRepo 660 err bool 661 }{ 662 { 663 name: "Empty config", 664 config: &plugins.Configuration{}, 665 enabledRepos: enabledRepos, 666 }, 667 { 668 name: "Empty sizes", 669 config: &plugins.Configuration{ 670 Size: plugins.Size{}, 671 }, 672 enabledRepos: enabledRepos, 673 }, 674 { 675 name: "Sizes specified", 676 config: &plugins.Configuration{ 677 Size: plugins.Size{ 678 S: 12, 679 M: 15, 680 L: 17, 681 Xl: 21, 682 Xxl: 51, 683 }, 684 }, 685 enabledRepos: enabledRepos, 686 }, 687 } 688 for _, c := range cases { 689 t.Run(c.name, func(t *testing.T) { 690 _, err := helpProvider(c.config, c.enabledRepos) 691 if err != nil && !c.err { 692 t.Fatalf("helpProvider error: %v", err) 693 } 694 }) 695 } 696 }