github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/prow/config/jobs_test.go (about) 1 /* 2 Copyright 2017 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 config 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "io/ioutil" 23 "os" 24 "regexp" 25 "strings" 26 "testing" 27 28 "flag" 29 "k8s.io/test-infra/prow/kube" 30 ) 31 32 var c *Config 33 var cj configJSON 34 var configPath = flag.String("config", "../config.yaml", "Path to prow config") 35 var jobConfigPath = flag.String("job-config", "", "Path to prow job config") 36 var configJSONPath = flag.String("config-json", "../../jobs/config.json", "Path to prow job config") 37 var podRe = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`) 38 39 type configJSON map[string]map[string]interface{} 40 41 const ( 42 testThis = "/test all" 43 retestBody = "/test all [submit-queue is verifying that this PR is safe to merge]" 44 ) 45 46 type JSONJob struct { 47 Scenario string `json:"scenario"` 48 Args []string `json:"args"` 49 } 50 51 // Consistent but meaningless order. 52 func flattenJobs(jobs []Presubmit) []Presubmit { 53 ret := jobs 54 for _, job := range jobs { 55 if len(job.RunAfterSuccess) > 0 { 56 ret = append(ret, flattenJobs(job.RunAfterSuccess)...) 57 } 58 } 59 return ret 60 } 61 62 // Returns if two brancher has overlapping branches 63 func checkOverlapBrancher(b1, b2 Brancher) bool { 64 if b1.RunsAgainstAllBranch() || b2.RunsAgainstAllBranch() { 65 return true 66 } 67 68 for _, run1 := range b1.Branches { 69 if b2.RunsAgainstBranch(run1) { 70 return true 71 } 72 } 73 74 for _, run2 := range b2.Branches { 75 if b1.RunsAgainstBranch(run2) { 76 return true 77 } 78 } 79 80 return false 81 } 82 83 func readConfigJSON(path string) (config configJSON, err error) { 84 raw, err := ioutil.ReadFile(path) 85 if err != nil { 86 return nil, err 87 } 88 config = configJSON{} 89 err = json.Unmarshal(raw, &config) 90 if err != nil { 91 return nil, err 92 } 93 return config, nil 94 } 95 96 func TestMain(m *testing.M) { 97 flag.Parse() 98 if *configPath == "" { 99 fmt.Println("--config must set") 100 os.Exit(1) 101 } 102 103 conf, err := Load(*configPath, *jobConfigPath) 104 if err != nil { 105 fmt.Printf("Could not load config: %v", err) 106 os.Exit(1) 107 } 108 c = conf 109 110 if *configJSONPath != "" { 111 cj, err = readConfigJSON(*configJSONPath) 112 if err != nil { 113 fmt.Printf("Could not load jobs config: %v", err) 114 os.Exit(1) 115 } 116 } 117 118 os.Exit(m.Run()) 119 } 120 121 // TODO(spxtr): Some of this is generic prowjob stuff and some of this is k8s- 122 // specific. Figure out which is which and split this up. 123 func TestPresubmits(t *testing.T) { 124 if len(c.Presubmits) == 0 { 125 t.Fatalf("No jobs found in presubmit.yaml.") 126 } 127 b, err := ioutil.ReadFile("../../jobs/config.json") 128 if err != nil { 129 t.Fatalf("Could not load jobs/config.json: %v", err) 130 } 131 var bootstrapConfig map[string]JSONJob 132 json.Unmarshal(b, &bootstrapConfig) 133 for _, rootJobs := range c.Presubmits { 134 jobs := flattenJobs(rootJobs) 135 for i, job := range jobs { 136 if job.Name == "" { 137 t.Errorf("Job %v needs a name.", job) 138 continue 139 } 140 if !job.SkipReport && job.Context == "" { 141 t.Errorf("Job %s needs a context.", job.Name) 142 } 143 if job.RerunCommand == "" || job.Trigger == "" { 144 t.Errorf("Job %s needs a trigger and a rerun command.", job.Name) 145 continue 146 } 147 // Check that the merge bot will run AlwaysRun jobs, otherwise it 148 // will attempt to rerun forever. 149 if job.AlwaysRun && !job.re.MatchString(testThis) { 150 t.Errorf("AlwaysRun job %s: \"%s\" does not match regex \"%v\".", job.Name, testThis, job.Trigger) 151 } 152 if job.AlwaysRun && !job.re.MatchString(retestBody) { 153 t.Errorf("AlwaysRun job %s: \"%s\" does not match regex \"%v\".", job.Name, retestBody, job.Trigger) 154 } 155 // Check that the merge bot will not run Non-AlwaysRun jobs 156 if !job.AlwaysRun && job.re.MatchString(testThis) { 157 t.Errorf("Non-AlwaysRun job %s: \"%s\" matches regex \"%v\".", job.Name, testThis, job.Trigger) 158 } 159 if !job.AlwaysRun && job.re.MatchString(retestBody) { 160 t.Errorf("Non-AlwaysRun job %s: \"%s\" matches regex \"%v\".", job.Name, retestBody, job.Trigger) 161 } 162 163 if len(job.Brancher.Branches) > 0 && len(job.Brancher.SkipBranches) > 0 { 164 t.Errorf("Job %s : Cannot have both branches and skip_branches set", job.Name) 165 } 166 // Next check that the rerun command doesn't run any other jobs. 167 for j, job2 := range jobs[i+1:] { 168 if job.Name == job2.Name { 169 // Make sure max_concurrency are the same 170 if job.MaxConcurrency != job2.MaxConcurrency { 171 t.Errorf("Jobs %s share same name but has different max_concurrency", job.Name) 172 } 173 // Make sure branches are not overlapping 174 if checkOverlapBrancher(job.Brancher, job2.Brancher) { 175 t.Errorf("Two jobs have the same name: %s, and have conflicting branches", job.Name) 176 } 177 } else { 178 if job.Context == job2.Context { 179 t.Errorf("Jobs %s and %s have the same context: %s", job.Name, job2.Name, job.Context) 180 } 181 if job2.re.MatchString(job.RerunCommand) { 182 t.Errorf("%d, %d, RerunCommand \"%s\" from job %s matches \"%v\" from job %s but shouldn't.", i, j, job.RerunCommand, job.Name, job2.Trigger, job2.Name) 183 } 184 } 185 } 186 var scenario string 187 job.Name = strings.Replace(job.Name, "pull-security-kubernetes", "pull-kubernetes", 1) 188 if j, present := bootstrapConfig[job.Name]; present { 189 scenario = fmt.Sprintf("scenarios/%s.py", j.Scenario) 190 } 191 192 // Ensure that jobs have a shell script of the same name. 193 if s, err := os.Stat(fmt.Sprintf("../../%s", scenario)); err != nil { 194 t.Errorf("Cannot find test-infra/%s for %s", scenario, job.Name) 195 } else { 196 if s.Mode()&0111 == 0 { 197 t.Errorf("Not executable: test-infra/%s (%o)", scenario, s.Mode()&0777) 198 } 199 if s.Mode()&0444 == 0 { 200 t.Errorf("Not readable: test-infra/%s (%o)", scenario, s.Mode()&0777) 201 } 202 } 203 } 204 } 205 } 206 207 func TestCommentBodyMatches(t *testing.T) { 208 var testcases = []struct { 209 repo string 210 body string 211 expectedJobs []string 212 }{ 213 { 214 "org/repo", 215 "this is a random comment", 216 []string{}, 217 }, 218 { 219 "org/repo", 220 "/ok-to-test", 221 []string{"gce", "unit"}, 222 }, 223 { 224 "org/repo", 225 "/test all", 226 []string{"gce", "unit", "gke"}, 227 }, 228 { 229 "org/repo", 230 "/test unit", 231 []string{"unit"}, 232 }, 233 { 234 "org/repo", 235 "/test federation", 236 []string{"federation"}, 237 }, 238 { 239 "org/repo2", 240 "/test all", 241 []string{"cadveapster", "after-cadveapster", "after-after-cadveapster"}, 242 }, 243 { 244 "org/repo2", 245 "/test really", 246 []string{"after-cadveapster"}, 247 }, 248 { 249 "org/repo2", 250 "/test again really", 251 []string{"after-after-cadveapster"}, 252 }, 253 { 254 "org/repo3", 255 "/test all", 256 []string{}, 257 }, 258 } 259 c := &Config{ 260 JobConfig: JobConfig{ 261 Presubmits: map[string][]Presubmit{ 262 "org/repo": { 263 { 264 Name: "gce", 265 re: regexp.MustCompile(`/test (gce|all)`), 266 AlwaysRun: true, 267 }, 268 { 269 Name: "unit", 270 re: regexp.MustCompile(`/test (unit|all)`), 271 AlwaysRun: true, 272 }, 273 { 274 Name: "gke", 275 re: regexp.MustCompile(`/test (gke|all)`), 276 AlwaysRun: false, 277 }, 278 { 279 Name: "federation", 280 re: regexp.MustCompile(`/test federation`), 281 AlwaysRun: false, 282 }, 283 }, 284 "org/repo2": { 285 { 286 Name: "cadveapster", 287 re: regexp.MustCompile(`/test all`), 288 AlwaysRun: true, 289 RunAfterSuccess: []Presubmit{ 290 { 291 Name: "after-cadveapster", 292 re: regexp.MustCompile(`/test (really|all)`), 293 AlwaysRun: true, 294 RunAfterSuccess: []Presubmit{ 295 { 296 Name: "after-after-cadveapster", 297 re: regexp.MustCompile(`/test (again really|all)`), 298 AlwaysRun: true, 299 }, 300 }, 301 }, 302 { 303 Name: "another-after-cadveapster", 304 re: regexp.MustCompile(`@k8s-bot dont test this`), 305 AlwaysRun: true, 306 }, 307 }, 308 }, 309 }, 310 }, 311 }, 312 } 313 for _, tc := range testcases { 314 actualJobs := c.MatchingPresubmits(tc.repo, tc.body, regexp.MustCompile(`/ok-to-test`).MatchString(tc.body)) 315 match := true 316 if len(actualJobs) != len(tc.expectedJobs) { 317 match = false 318 } else { 319 for _, actualJob := range actualJobs { 320 found := false 321 for _, expectedJob := range tc.expectedJobs { 322 if expectedJob == actualJob.Name { 323 found = true 324 break 325 } 326 } 327 if !found { 328 match = false 329 break 330 } 331 } 332 } 333 if !match { 334 t.Errorf("Wrong jobs for body %s. Got %v, expected %v.", tc.body, actualJobs, tc.expectedJobs) 335 } 336 } 337 } 338 339 func TestRetestPresubmits(t *testing.T) { 340 var testcases = []struct { 341 skipContexts map[string]bool 342 runContexts map[string]bool 343 expectedContexts []string 344 }{ 345 { 346 map[string]bool{}, 347 map[string]bool{}, 348 []string{"gce", "unit"}, 349 }, 350 { 351 map[string]bool{"gce": true}, 352 map[string]bool{}, 353 []string{"unit"}, 354 }, 355 { 356 map[string]bool{}, 357 map[string]bool{"federation": true, "nonexistent": true}, 358 []string{"gce", "unit", "federation"}, 359 }, 360 { 361 map[string]bool{}, 362 map[string]bool{"gke": true}, 363 []string{"gce", "unit", "gke"}, 364 }, 365 { 366 map[string]bool{"gce": true}, 367 map[string]bool{"gce": true}, // should never happen 368 []string{"unit"}, 369 }, 370 } 371 c := &Config{ 372 JobConfig: JobConfig{ 373 Presubmits: map[string][]Presubmit{ 374 "org/repo": { 375 { 376 Context: "gce", 377 AlwaysRun: true, 378 }, 379 { 380 Context: "unit", 381 AlwaysRun: true, 382 }, 383 { 384 Context: "gke", 385 AlwaysRun: false, 386 }, 387 { 388 Context: "federation", 389 AlwaysRun: false, 390 }, 391 }, 392 "org/repo2": { 393 { 394 Context: "shouldneverrun", 395 AlwaysRun: true, 396 }, 397 }, 398 }, 399 }, 400 } 401 for _, tc := range testcases { 402 actualContexts := c.RetestPresubmits("org/repo", tc.skipContexts, tc.runContexts) 403 match := true 404 if len(actualContexts) != len(tc.expectedContexts) { 405 match = false 406 } else { 407 for _, actualJob := range actualContexts { 408 found := false 409 for _, expectedContext := range tc.expectedContexts { 410 if expectedContext == actualJob.Context { 411 found = true 412 break 413 } 414 } 415 if !found { 416 match = false 417 break 418 } 419 } 420 } 421 if !match { 422 t.Errorf("Wrong contexts for skip %v run %v. Got %v, expected %v.", tc.runContexts, tc.skipContexts, actualContexts, tc.expectedContexts) 423 } 424 } 425 426 } 427 428 func TestConditionalPresubmits(t *testing.T) { 429 presubmits := []Presubmit{ 430 { 431 Name: "cross build", 432 RunIfChanged: `(Makefile|\.sh|_(windows|linux|osx|unknown)(_test)?\.go)$`, 433 }, 434 } 435 SetPresubmitRegexes(presubmits) 436 ps := presubmits[0] 437 var testcases = []struct { 438 changes []string 439 expected bool 440 }{ 441 {[]string{"some random file"}, false}, 442 {[]string{"./pkg/util/rlimit/rlimit_linux.go"}, true}, 443 {[]string{"./pkg/util/rlimit/rlimit_unknown_test.go"}, true}, 444 {[]string{"build.sh"}, true}, 445 {[]string{"build.shoo"}, false}, 446 {[]string{"Makefile"}, true}, 447 } 448 for _, tc := range testcases { 449 actual := ps.RunsAgainstChanges(tc.changes) 450 if actual != tc.expected { 451 t.Errorf("wrong RunsAgainstChanges(%#v) result. Got %v, expected %v", tc.changes, actual, tc.expected) 452 } 453 } 454 } 455 456 func TestListPresubmit(t *testing.T) { 457 c := &Config{ 458 JobConfig: JobConfig{ 459 Presubmits: map[string][]Presubmit{ 460 "r1": { 461 { 462 Name: "a", 463 RunAfterSuccess: []Presubmit{ 464 {Name: "aa"}, 465 {Name: "ab"}, 466 }, 467 }, 468 {Name: "b"}, 469 }, 470 "r2": { 471 { 472 Name: "c", 473 RunAfterSuccess: []Presubmit{ 474 {Name: "ca"}, 475 {Name: "cb"}, 476 }, 477 }, 478 {Name: "d"}, 479 }, 480 }, 481 Postsubmits: map[string][]Postsubmit{ 482 "r1": {{Name: "e"}}, 483 }, 484 Periodics: []Periodic{ 485 {Name: "f"}, 486 }, 487 }, 488 } 489 490 var testcases = []struct { 491 name string 492 expected []string 493 repos []string 494 }{ 495 { 496 "all presubmits", 497 []string{"a", "aa", "ab", "b", "c", "ca", "cb", "d"}, 498 []string{}, 499 }, 500 { 501 "r2 presubmits", 502 []string{"c", "ca", "cb", "d"}, 503 []string{"r2"}, 504 }, 505 } 506 507 for _, tc := range testcases { 508 actual := c.AllPresubmits(tc.repos) 509 if len(actual) != len(tc.expected) { 510 t.Fatalf("test %s - Wrong number of jobs. Got %v, expected %v", tc.name, actual, tc.expected) 511 } 512 for _, j1 := range tc.expected { 513 found := false 514 for _, j2 := range actual { 515 if j1 == j2.Name { 516 found = true 517 break 518 } 519 } 520 if !found { 521 t.Errorf("test %s - Did not find job %s in output", tc.name, j1) 522 } 523 } 524 } 525 } 526 527 func TestListPostsubmit(t *testing.T) { 528 c := &Config{ 529 JobConfig: JobConfig{ 530 Presubmits: map[string][]Presubmit{ 531 "r1": {{Name: "a"}}, 532 }, 533 Postsubmits: map[string][]Postsubmit{ 534 "r1": { 535 { 536 Name: "c", 537 RunAfterSuccess: []Postsubmit{ 538 {Name: "ca"}, 539 {Name: "cb"}, 540 }, 541 }, 542 {Name: "d"}, 543 }, 544 "r2": {{Name: "e"}}, 545 }, 546 Periodics: []Periodic{ 547 {Name: "f"}, 548 }, 549 }, 550 } 551 552 var testcases = []struct { 553 name string 554 expected []string 555 repos []string 556 }{ 557 { 558 "all postsubmits", 559 []string{"c", "ca", "cb", "d", "e"}, 560 []string{}, 561 }, 562 { 563 "r2 presubmits", 564 []string{"e"}, 565 []string{"r2"}, 566 }, 567 } 568 569 for _, tc := range testcases { 570 actual := c.AllPostsubmits(tc.repos) 571 if len(actual) != len(tc.expected) { 572 t.Fatalf("%s - Wrong number of jobs. Got %v, expected %v", tc.name, actual, tc.expected) 573 } 574 for _, j1 := range tc.expected { 575 found := false 576 for _, j2 := range actual { 577 if j1 == j2.Name { 578 found = true 579 break 580 } 581 } 582 if !found { 583 t.Errorf("Did not find job %s in output", j1) 584 } 585 } 586 } 587 } 588 589 func TestListPeriodic(t *testing.T) { 590 c := &Config{ 591 JobConfig: JobConfig{ 592 Presubmits: map[string][]Presubmit{ 593 "r1": {{Name: "a"}}, 594 }, 595 Postsubmits: map[string][]Postsubmit{ 596 "r1": {{Name: "b"}}, 597 }, 598 Periodics: []Periodic{ 599 { 600 Name: "c", 601 RunAfterSuccess: []Periodic{ 602 {Name: "ca"}, 603 {Name: "cb"}, 604 }, 605 }, 606 {Name: "d"}, 607 }, 608 }, 609 } 610 611 expected := []string{"c", "ca", "cb", "d"} 612 actual := c.AllPeriodics() 613 if len(actual) != len(expected) { 614 t.Fatalf("Wrong number of jobs. Got %v, expected %v", actual, expected) 615 } 616 for _, j1 := range expected { 617 found := false 618 for _, j2 := range actual { 619 if j1 == j2.Name { 620 found = true 621 break 622 } 623 } 624 if !found { 625 t.Errorf("Did not find job %s in output", j1) 626 } 627 } 628 } 629 630 func TestRunAgainstBranch(t *testing.T) { 631 jobs := []Presubmit{ 632 { 633 Name: "a", 634 Brancher: Brancher{SkipBranches: []string{"s"}}, 635 }, 636 { 637 Name: "b", 638 Brancher: Brancher{Branches: []string{"r"}}, 639 }, 640 { 641 Name: "c", 642 Brancher: Brancher{ 643 SkipBranches: []string{"s"}, 644 Branches: []string{"r"}, 645 }, 646 }, 647 { 648 Name: "d", 649 Brancher: Brancher{ 650 SkipBranches: []string{"s"}, 651 Branches: []string{"s", "r"}, 652 }, 653 }, 654 { 655 Name: "default", 656 }, 657 } 658 659 if err := SetPresubmitRegexes(jobs); err != nil { 660 t.Fatalf("could not set regexes: %v", err) 661 } 662 663 for _, job := range jobs { 664 if job.Name == "default" { 665 if !job.RunsAgainstBranch("s") { 666 t.Errorf("Job %s should run branch s", job.Name) 667 } 668 } else if job.RunsAgainstBranch("s") { 669 t.Errorf("Job %s should not run branch s", job.Name) 670 } 671 672 if !job.RunsAgainstBranch("r") { 673 t.Errorf("Job %s should run branch r", job.Name) 674 } 675 } 676 } 677 678 func TestValidPodNames(t *testing.T) { 679 for _, j := range c.AllPresubmits([]string{}) { 680 if !podRe.MatchString(j.Name) { 681 t.Errorf("Job \"%s\" must match regex \"%s\".", j.Name, podRe.String()) 682 } 683 } 684 for _, j := range c.AllPostsubmits([]string{}) { 685 if !podRe.MatchString(j.Name) { 686 t.Errorf("Job \"%s\" must match regex \"%s\".", j.Name, podRe.String()) 687 } 688 } 689 for _, j := range c.AllPeriodics() { 690 if !podRe.MatchString(j.Name) { 691 t.Errorf("Job \"%s\" must match regex \"%s\".", j.Name, podRe.String()) 692 } 693 } 694 } 695 696 func TestNoDuplicateJobs(t *testing.T) { 697 // Presubmit test is covered under TestPresubmits() above 698 699 allJobs := make(map[string]bool) 700 for _, j := range c.AllPostsubmits([]string{}) { 701 if allJobs[j.Name] { 702 t.Errorf("Found duplicate job in postsubmit: %s.", j.Name) 703 } 704 allJobs[j.Name] = true 705 } 706 707 allJobs = make(map[string]bool) 708 for _, j := range c.AllPeriodics() { 709 if allJobs[j.Name] { 710 t.Errorf("Found duplicate job in periodic %s.", j.Name) 711 } 712 allJobs[j.Name] = true 713 } 714 } 715 716 func TestMergePreset(t *testing.T) { 717 tcs := []struct { 718 name string 719 jobLabels map[string]string 720 pod *kube.PodSpec 721 presets []Preset 722 723 shouldError bool 724 numEnv int 725 numVol int 726 numVolMounts int 727 }{ 728 { 729 name: "one volume", 730 jobLabels: map[string]string{"foo": "bar"}, 731 pod: &kube.PodSpec{}, 732 presets: []Preset{ 733 { 734 Labels: map[string]string{"foo": "bar"}, 735 Volumes: []kube.Volume{{Name: "baz"}}, 736 }, 737 }, 738 numVol: 1, 739 }, 740 { 741 name: "wrong label", 742 jobLabels: map[string]string{"foo": "nope"}, 743 pod: &kube.PodSpec{}, 744 presets: []Preset{ 745 { 746 Labels: map[string]string{"foo": "bar"}, 747 Volumes: []kube.Volume{{Name: "baz"}}, 748 }, 749 }, 750 }, 751 { 752 name: "conflicting volume name", 753 jobLabels: map[string]string{"foo": "bar"}, 754 pod: &kube.PodSpec{Volumes: []kube.Volume{{Name: "baz"}}}, 755 presets: []Preset{ 756 { 757 Labels: map[string]string{"foo": "bar"}, 758 Volumes: []kube.Volume{{Name: "baz"}}, 759 }, 760 }, 761 shouldError: true, 762 }, 763 { 764 name: "non conflicting volume name", 765 jobLabels: map[string]string{"foo": "bar"}, 766 pod: &kube.PodSpec{Volumes: []kube.Volume{{Name: "baz"}}}, 767 presets: []Preset{ 768 { 769 Labels: map[string]string{"foo": "bar"}, 770 Volumes: []kube.Volume{{Name: "qux"}}, 771 }, 772 }, 773 numVol: 2, 774 }, 775 { 776 name: "one env", 777 jobLabels: map[string]string{"foo": "bar"}, 778 pod: &kube.PodSpec{Containers: []kube.Container{{}}}, 779 presets: []Preset{ 780 { 781 Labels: map[string]string{"foo": "bar"}, 782 Env: []kube.EnvVar{{Name: "baz"}}, 783 }, 784 }, 785 numEnv: 1, 786 }, 787 { 788 name: "one vm", 789 jobLabels: map[string]string{"foo": "bar"}, 790 pod: &kube.PodSpec{Containers: []kube.Container{{}}}, 791 presets: []Preset{ 792 { 793 Labels: map[string]string{"foo": "bar"}, 794 VolumeMounts: []kube.VolumeMount{{Name: "baz"}}, 795 }, 796 }, 797 numVolMounts: 1, 798 }, 799 { 800 name: "one of each", 801 jobLabels: map[string]string{"foo": "bar"}, 802 pod: &kube.PodSpec{Containers: []kube.Container{{}}}, 803 presets: []Preset{ 804 { 805 Labels: map[string]string{"foo": "bar"}, 806 Env: []kube.EnvVar{{Name: "baz"}}, 807 VolumeMounts: []kube.VolumeMount{{Name: "baz"}}, 808 Volumes: []kube.Volume{{Name: "qux"}}, 809 }, 810 }, 811 numEnv: 1, 812 numVol: 1, 813 numVolMounts: 1, 814 }, 815 { 816 name: "two vm", 817 jobLabels: map[string]string{"foo": "bar"}, 818 pod: &kube.PodSpec{Containers: []kube.Container{{}}}, 819 presets: []Preset{ 820 { 821 Labels: map[string]string{"foo": "bar"}, 822 VolumeMounts: []kube.VolumeMount{{Name: "baz"}, {Name: "foo"}}, 823 }, 824 }, 825 numVolMounts: 2, 826 }, 827 } 828 for _, tc := range tcs { 829 if err := resolvePresets("foo", tc.jobLabels, tc.pod, tc.presets); err == nil && tc.shouldError { 830 t.Errorf("For test \"%s\": expected error but got none.", tc.name) 831 } else if err != nil && !tc.shouldError { 832 t.Errorf("For test \"%s\": expected no error but got %v.", tc.name, err) 833 } 834 if tc.shouldError { 835 continue 836 } 837 if len(tc.pod.Volumes) != tc.numVol { 838 t.Errorf("For test \"%s\": wrong number of volumes. Got %d, expected %d.", tc.name, len(tc.pod.Volumes), tc.numVol) 839 } 840 for _, c := range tc.pod.Containers { 841 if len(c.VolumeMounts) != tc.numVolMounts { 842 t.Errorf("For test \"%s\": wrong number of volume mounts. Got %d, expected %d.", tc.name, len(c.VolumeMounts), tc.numVolMounts) 843 } 844 if len(c.Env) != tc.numEnv { 845 t.Errorf("For test \"%s\": wrong number of env vars. Got %d, expected %d.", tc.name, len(c.Env), tc.numEnv) 846 } 847 } 848 } 849 }