github.com/abayer/test-infra@v0.0.5/prow/cmd/build/controller_test.go (about) 1 /* 2 Copyright 2018 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 main 18 19 import ( 20 "errors" 21 "fmt" 22 "reflect" 23 "testing" 24 "time" 25 26 prowjobv1 "k8s.io/test-infra/prow/apis/prowjobs/v1" 27 28 buildv1alpha1 "github.com/knative/build/pkg/apis/build/v1alpha1" 29 corev1 "k8s.io/api/core/v1" 30 apierrors "k8s.io/apimachinery/pkg/api/errors" 31 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 ) 33 34 const ( 35 errorGetProwJob = "error-get-prowjob" 36 errorGetBuild = "error-get-build" 37 errorDeleteBuild = "error-delete-build" 38 errorCreateBuild = "error-create-build" 39 errorUpdateBuild = "error-update-build" 40 errorUpdateProwJob = "error-update-prowjob" 41 ) 42 43 type fakeReconciler struct { 44 jobs map[string]prowjobv1.ProwJob 45 builds map[string]buildv1alpha1.Build 46 nows metav1.Time 47 } 48 49 func key(namespace, name string) string { 50 if namespace == "" { 51 return name 52 } 53 return namespace + "/" + name 54 } 55 56 func (r *fakeReconciler) now() metav1.Time { 57 fmt.Println(r.nows) 58 return r.nows 59 } 60 61 func (r *fakeReconciler) getProwJob(namespace, name string) (*prowjobv1.ProwJob, error) { 62 if namespace == errorGetProwJob { 63 return nil, errors.New("injected create build error") 64 } 65 k := key(namespace, name) 66 pj, present := r.jobs[k] 67 if !present { 68 return nil, apierrors.NewNotFound(prowjobv1.Resource("ProwJob"), name) 69 } 70 return &pj, nil 71 } 72 func (r *fakeReconciler) getBuild(namespace, name string) (*buildv1alpha1.Build, error) { 73 if namespace == errorGetBuild { 74 return nil, errors.New("injected create build error") 75 } 76 k := key(namespace, name) 77 b, present := r.builds[k] 78 if !present { 79 return nil, apierrors.NewNotFound(buildv1alpha1.Resource("Build"), name) 80 } 81 return &b, nil 82 } 83 func (r *fakeReconciler) deleteBuild(namespace, name string) error { 84 if namespace == errorDeleteBuild { 85 return errors.New("injected create build error") 86 } 87 k := key(namespace, name) 88 if _, present := r.builds[k]; !present { 89 return apierrors.NewNotFound(buildv1alpha1.Resource("Build"), name) 90 } 91 delete(r.builds, k) 92 return nil 93 } 94 95 func (r *fakeReconciler) createBuild(namespace string, b *buildv1alpha1.Build) (*buildv1alpha1.Build, error) { 96 if b == nil { 97 return nil, errors.New("nil build") 98 } 99 if namespace == errorCreateBuild { 100 return nil, errors.New("injected create build error") 101 } 102 k := key(namespace, b.Name) 103 if _, alreadyExists := r.builds[k]; alreadyExists { 104 return nil, apierrors.NewAlreadyExists(prowjobv1.Resource("ProwJob"), b.Name) 105 } 106 r.builds[k] = *b 107 return b, nil 108 } 109 110 func (r *fakeReconciler) updateBuild(namespace string, b *buildv1alpha1.Build) (*buildv1alpha1.Build, error) { 111 if b == nil { 112 return nil, errors.New("nil build") 113 } 114 if namespace == errorUpdateBuild { 115 return nil, errors.New("injected update prowjob error") 116 } 117 k := key(namespace, b.Name) 118 b.Generation++ // For some reason this is always changing. 119 if _, present := r.builds[k]; !present { 120 return nil, apierrors.NewNotFound(buildv1alpha1.Resource("Build"), b.Name) 121 } 122 r.builds[k] = *b 123 return b, nil 124 } 125 126 func (r *fakeReconciler) updateProwJob(namespace string, pj *prowjobv1.ProwJob) (*prowjobv1.ProwJob, error) { 127 if pj == nil { 128 return nil, errors.New("nil prowjob") 129 } 130 if namespace == errorUpdateProwJob { 131 return nil, errors.New("injected update prowjob error") 132 } 133 k := key(namespace, pj.Name) 134 if _, present := r.jobs[k]; !present { 135 return nil, apierrors.NewNotFound(prowjobv1.Resource("ProwJob"), pj.Name) 136 } 137 r.jobs[k] = *pj 138 return pj, nil 139 } 140 141 func TestReconcile(t *testing.T) { 142 now := metav1.Now() 143 buildSpec := buildv1alpha1.BuildSpec{} 144 noJobChange := func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) prowjobv1.ProwJob { 145 return pj 146 } 147 noBuildChange := func(_ prowjobv1.ProwJob, b buildv1alpha1.Build) buildv1alpha1.Build { 148 return b 149 } 150 cases := []struct { 151 name string 152 namespace string 153 observedJob *prowjobv1.ProwJob 154 observedBuild *buildv1alpha1.Build 155 expectedJob func(prowjobv1.ProwJob, buildv1alpha1.Build) prowjobv1.ProwJob 156 expectedBuild func(prowjobv1.ProwJob, buildv1alpha1.Build) buildv1alpha1.Build 157 err bool 158 }{ 159 { 160 name: "new prow job creates build", 161 observedJob: &prowjobv1.ProwJob{ 162 Spec: prowjobv1.ProwJobSpec{ 163 Agent: prowjobv1.BuildAgent, 164 BuildSpec: &buildSpec, 165 }, 166 }, 167 expectedJob: func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) prowjobv1.ProwJob { 168 pj.Status = prowjobv1.ProwJobStatus{ 169 StartTime: now, 170 State: prowjobv1.TriggeredState, 171 Description: descScheduling, 172 } 173 return pj 174 }, 175 expectedBuild: func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) buildv1alpha1.Build { 176 b, err := makeBuild(pj) 177 if err != nil { 178 panic(err) 179 } 180 return *b 181 }, 182 }, 183 { 184 name: "do not create build for failed prowjob", 185 observedJob: &prowjobv1.ProwJob{ 186 Spec: prowjobv1.ProwJobSpec{ 187 Agent: prowjobv1.BuildAgent, 188 BuildSpec: &buildSpec, 189 }, 190 Status: prowjobv1.ProwJobStatus{ 191 State: prowjobv1.FailureState, 192 }, 193 }, 194 expectedJob: noJobChange, 195 }, 196 { 197 name: "do not create build for successful prowjob", 198 observedJob: &prowjobv1.ProwJob{ 199 Spec: prowjobv1.ProwJobSpec{ 200 Agent: prowjobv1.BuildAgent, 201 BuildSpec: &buildSpec, 202 }, 203 Status: prowjobv1.ProwJobStatus{ 204 State: prowjobv1.SuccessState, 205 }, 206 }, 207 expectedJob: noJobChange, 208 }, 209 { 210 name: "do not create build for aborted prowjob", 211 observedJob: &prowjobv1.ProwJob{ 212 Spec: prowjobv1.ProwJobSpec{ 213 Agent: prowjobv1.BuildAgent, 214 BuildSpec: &buildSpec, 215 }, 216 Status: prowjobv1.ProwJobStatus{ 217 State: prowjobv1.AbortedState, 218 }, 219 }, 220 expectedJob: noJobChange, 221 }, 222 { 223 name: "delete build after deleting prowjob", 224 observedBuild: func() *buildv1alpha1.Build { 225 pj := prowjobv1.ProwJob{} 226 pj.Spec.BuildSpec = &buildv1alpha1.BuildSpec{} 227 b, err := makeBuild(pj) 228 if err != nil { 229 panic(err) 230 } 231 return b 232 }(), 233 }, 234 { 235 name: "only delete builds created by controller", 236 observedBuild: func() *buildv1alpha1.Build { 237 pj := prowjobv1.ProwJob{} 238 pj.Spec.BuildSpec = &buildv1alpha1.BuildSpec{} 239 b, err := makeBuild(pj) 240 if err != nil { 241 panic(err) 242 } 243 b.OwnerReferences = nil 244 return b 245 }(), 246 expectedBuild: noBuildChange, 247 }, 248 { 249 name: "update build if spec changes", 250 observedJob: &prowjobv1.ProwJob{ 251 Spec: prowjobv1.ProwJobSpec{ 252 Agent: prowjobv1.BuildAgent, 253 BuildSpec: &buildv1alpha1.BuildSpec{ 254 ServiceAccountName: "robot", 255 }, 256 }, 257 Status: prowjobv1.ProwJobStatus{ 258 State: prowjobv1.PendingState, 259 Description: "fancy", 260 }, 261 }, 262 observedBuild: func() *buildv1alpha1.Build { 263 pj := prowjobv1.ProwJob{} 264 pj.Spec.Agent = prowjobv1.BuildAgent 265 pj.Spec.BuildSpec = &buildSpec 266 b, err := makeBuild(pj) 267 if err != nil { 268 panic(err) 269 } 270 return b 271 }(), 272 expectedJob: func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) prowjobv1.ProwJob { 273 pj.Status = prowjobv1.ProwJobStatus{ 274 StartTime: now, 275 State: prowjobv1.TriggeredState, 276 Description: descScheduling, 277 } 278 return pj 279 }, 280 expectedBuild: func(pj prowjobv1.ProwJob, b buildv1alpha1.Build) buildv1alpha1.Build { 281 b.Spec = *pj.Spec.BuildSpec 282 b.Generation++ 283 return b 284 }, 285 }, 286 { 287 name: "prowjob goes pending when build starts", 288 observedJob: &prowjobv1.ProwJob{ 289 Spec: prowjobv1.ProwJobSpec{ 290 Agent: prowjobv1.BuildAgent, 291 BuildSpec: &buildSpec, 292 }, 293 Status: prowjobv1.ProwJobStatus{ 294 State: prowjobv1.TriggeredState, 295 Description: "fancy", 296 }, 297 }, 298 observedBuild: func() *buildv1alpha1.Build { 299 pj := prowjobv1.ProwJob{} 300 pj.Spec.Agent = prowjobv1.BuildAgent 301 pj.Spec.BuildSpec = &buildSpec 302 b, err := makeBuild(pj) 303 if err != nil { 304 panic(err) 305 } 306 b.Status.SetCondition(&buildv1alpha1.BuildCondition{ 307 Type: buildv1alpha1.BuildSucceeded, 308 Message: "hello", 309 }) 310 b.Status.StartTime = now 311 return b 312 }(), 313 expectedJob: func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) prowjobv1.ProwJob { 314 pj.Status = prowjobv1.ProwJobStatus{ 315 StartTime: now, 316 State: prowjobv1.PendingState, 317 Description: "hello", 318 } 319 return pj 320 }, 321 expectedBuild: noBuildChange, 322 }, 323 { 324 name: "prowjob succeeds when build succeeds", 325 observedJob: &prowjobv1.ProwJob{ 326 Spec: prowjobv1.ProwJobSpec{ 327 Agent: prowjobv1.BuildAgent, 328 BuildSpec: &buildSpec, 329 }, 330 Status: prowjobv1.ProwJobStatus{ 331 State: prowjobv1.PendingState, 332 Description: "fancy", 333 }, 334 }, 335 observedBuild: func() *buildv1alpha1.Build { 336 pj := prowjobv1.ProwJob{} 337 pj.Spec.Agent = prowjobv1.BuildAgent 338 pj.Spec.BuildSpec = &buildSpec 339 b, err := makeBuild(pj) 340 if err != nil { 341 panic(err) 342 } 343 b.Status.SetCondition(&buildv1alpha1.BuildCondition{ 344 Type: buildv1alpha1.BuildSucceeded, 345 Status: corev1.ConditionTrue, 346 Message: "hello", 347 }) 348 b.Status.CompletionTime = now 349 b.Status.StartTime = now 350 return b 351 }(), 352 expectedJob: func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) prowjobv1.ProwJob { 353 pj.Status = prowjobv1.ProwJobStatus{ 354 StartTime: now, 355 CompletionTime: &now, 356 State: prowjobv1.SuccessState, 357 Description: "hello", 358 } 359 return pj 360 }, 361 expectedBuild: noBuildChange, 362 }, 363 { 364 name: "prowjob fails when build fails", 365 observedJob: &prowjobv1.ProwJob{ 366 Spec: prowjobv1.ProwJobSpec{ 367 Agent: prowjobv1.BuildAgent, 368 BuildSpec: &buildSpec, 369 }, 370 Status: prowjobv1.ProwJobStatus{ 371 State: prowjobv1.PendingState, 372 Description: "fancy", 373 }, 374 }, 375 observedBuild: func() *buildv1alpha1.Build { 376 pj := prowjobv1.ProwJob{} 377 pj.Spec.Agent = prowjobv1.BuildAgent 378 pj.Spec.BuildSpec = &buildSpec 379 b, err := makeBuild(pj) 380 if err != nil { 381 panic(err) 382 } 383 b.Status.SetCondition(&buildv1alpha1.BuildCondition{ 384 Type: buildv1alpha1.BuildSucceeded, 385 Status: corev1.ConditionFalse, 386 Message: "hello", 387 }) 388 b.Status.StartTime = now 389 b.Status.CompletionTime = now 390 return b 391 }(), 392 expectedJob: func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) prowjobv1.ProwJob { 393 pj.Status = prowjobv1.ProwJobStatus{ 394 StartTime: now, 395 CompletionTime: &now, 396 State: prowjobv1.FailureState, 397 Description: "hello", 398 } 399 return pj 400 }, 401 expectedBuild: noBuildChange, 402 }, 403 { 404 name: "error when we cannot get prowjob", 405 namespace: errorGetProwJob, 406 err: true, 407 observedJob: &prowjobv1.ProwJob{ 408 Spec: prowjobv1.ProwJobSpec{ 409 Agent: prowjobv1.BuildAgent, 410 BuildSpec: &buildSpec, 411 }, 412 Status: prowjobv1.ProwJobStatus{ 413 State: prowjobv1.PendingState, 414 Description: "fancy", 415 }, 416 }, 417 }, 418 { 419 name: "error when we cannot get build", 420 namespace: errorGetBuild, 421 err: true, 422 observedBuild: func() *buildv1alpha1.Build { 423 pj := prowjobv1.ProwJob{} 424 pj.Spec.Agent = prowjobv1.BuildAgent 425 pj.Spec.BuildSpec = &buildSpec 426 b, err := makeBuild(pj) 427 if err != nil { 428 panic(err) 429 } 430 b.Status.SetCondition(&buildv1alpha1.BuildCondition{ 431 Type: buildv1alpha1.BuildSucceeded, 432 Status: corev1.ConditionTrue, 433 Message: "hello", 434 }) 435 b.Status.CompletionTime = now 436 b.Status.StartTime = now 437 return b 438 }(), 439 }, 440 { 441 name: "error when we cannot delete build", 442 namespace: errorDeleteBuild, 443 err: true, 444 observedBuild: func() *buildv1alpha1.Build { 445 pj := prowjobv1.ProwJob{} 446 pj.Spec.BuildSpec = &buildv1alpha1.BuildSpec{} 447 b, err := makeBuild(pj) 448 if err != nil { 449 panic(err) 450 } 451 return b 452 }(), 453 }, 454 { 455 name: "error when we cannot create build", 456 namespace: errorCreateBuild, 457 err: true, 458 observedJob: &prowjobv1.ProwJob{ 459 Spec: prowjobv1.ProwJobSpec{ 460 Agent: prowjobv1.BuildAgent, 461 BuildSpec: &buildSpec, 462 }, 463 }, 464 expectedJob: func(pj prowjobv1.ProwJob, _ buildv1alpha1.Build) prowjobv1.ProwJob { 465 pj.Status = prowjobv1.ProwJobStatus{ 466 StartTime: now, 467 State: prowjobv1.TriggeredState, 468 Description: descScheduling, 469 } 470 return pj 471 }, 472 }, 473 { 474 name: "error when buildspec is nil", 475 err: true, 476 observedJob: &prowjobv1.ProwJob{ 477 Spec: prowjobv1.ProwJobSpec{ 478 Agent: prowjobv1.BuildAgent, 479 BuildSpec: nil, 480 }, 481 Status: prowjobv1.ProwJobStatus{ 482 State: prowjobv1.TriggeredState, 483 }, 484 }, 485 }, 486 { 487 name: "error when we cannot update prowjob", 488 namespace: errorUpdateProwJob, 489 err: true, 490 observedJob: &prowjobv1.ProwJob{ 491 Spec: prowjobv1.ProwJobSpec{ 492 Agent: prowjobv1.BuildAgent, 493 BuildSpec: &buildSpec, 494 }, 495 Status: prowjobv1.ProwJobStatus{ 496 State: prowjobv1.PendingState, 497 Description: "fancy", 498 }, 499 }, 500 observedBuild: func() *buildv1alpha1.Build { 501 pj := prowjobv1.ProwJob{} 502 pj.Spec.Agent = prowjobv1.BuildAgent 503 pj.Spec.BuildSpec = &buildSpec 504 b, err := makeBuild(pj) 505 if err != nil { 506 panic(err) 507 } 508 b.Status.SetCondition(&buildv1alpha1.BuildCondition{ 509 Type: buildv1alpha1.BuildSucceeded, 510 Status: corev1.ConditionTrue, 511 Message: "hello", 512 }) 513 b.Status.CompletionTime = now 514 b.Status.StartTime = now 515 return b 516 }(), 517 }, 518 { 519 name: "error when we cannot update build", 520 namespace: errorUpdateBuild, 521 err: true, 522 observedJob: &prowjobv1.ProwJob{ 523 Spec: prowjobv1.ProwJobSpec{ 524 Agent: prowjobv1.BuildAgent, 525 BuildSpec: &buildv1alpha1.BuildSpec{ 526 ServiceAccountName: "robot", 527 }, 528 }, 529 Status: prowjobv1.ProwJobStatus{ 530 State: prowjobv1.PendingState, 531 Description: "fancy", 532 }, 533 }, 534 observedBuild: func() *buildv1alpha1.Build { 535 pj := prowjobv1.ProwJob{} 536 pj.Spec.Agent = prowjobv1.BuildAgent 537 pj.Spec.BuildSpec = &buildSpec 538 b, err := makeBuild(pj) 539 if err != nil { 540 panic(err) 541 } 542 return b 543 }(), 544 }, 545 } 546 547 for _, tc := range cases { 548 t.Run(tc.name, func(t *testing.T) { 549 const name = "the-object-name" 550 k := key(tc.namespace, name) 551 r := &fakeReconciler{ 552 jobs: map[string]prowjobv1.ProwJob{}, 553 builds: map[string]buildv1alpha1.Build{}, 554 nows: now, 555 } 556 if j := tc.observedJob; j != nil { 557 j.Name = name 558 r.jobs[k] = *j 559 } 560 if b := tc.observedBuild; b != nil { 561 b.Name = name 562 r.builds[k] = *b 563 } 564 expectedJobs := map[string]prowjobv1.ProwJob{} 565 if j := tc.expectedJob; j != nil { 566 expectedJobs[k] = j(r.jobs[k], r.builds[k]) 567 } 568 expectedBuilds := map[string]buildv1alpha1.Build{} 569 if b := tc.expectedBuild; b != nil { 570 expectedBuilds[k] = b(r.jobs[k], r.builds[k]) 571 } 572 err := reconcile(r, k) 573 switch { 574 case err != nil: 575 if !tc.err { 576 t.Errorf("unexpected error: %v", err) 577 } 578 case tc.err: 579 t.Error("failed to receive expected error") 580 case !reflect.DeepEqual(r.jobs, expectedJobs): 581 t.Errorf("prowjobs do not match: %#v != %#v %t", r.jobs, expectedJobs, r.jobs[k].Status.StartTime == expectedJobs[k].Status.StartTime) 582 case !reflect.DeepEqual(r.builds, expectedBuilds): 583 t.Errorf("builds do not match: %#v != %#v", r.builds, expectedBuilds) 584 } 585 }) 586 } 587 588 } 589 590 func TestMakeBuild(t *testing.T) { 591 if _, err := makeBuild(prowjobv1.ProwJob{}); err == nil { 592 t.Error("failed to receive expected error") 593 } 594 pj := prowjobv1.ProwJob{} 595 pj.Name = "world" 596 pj.Namespace = "hello" 597 pj.Spec.BuildSpec = &buildv1alpha1.BuildSpec{} 598 switch b, err := makeBuild(pj); { 599 case err != nil: 600 t.Errorf("unexpected error: %v", err) 601 case !reflect.DeepEqual(b.Spec, *pj.Spec.BuildSpec): 602 t.Errorf("buildspecs do not match %#v != expected %#v", b.Spec, pj.Spec.BuildSpec) 603 case len(b.OwnerReferences) == 0: 604 t.Error("failed to find owner references") 605 } 606 } 607 608 func TestDescription(t *testing.T) { 609 cases := []struct { 610 name string 611 message string 612 reason string 613 fallback string 614 expected string 615 }{ 616 { 617 name: "prefer message over reason or fallback", 618 message: "hello", 619 reason: "world", 620 fallback: "doh", 621 expected: "hello", 622 }, 623 { 624 name: "prefer reason over fallback", 625 reason: "world", 626 fallback: "other", 627 expected: "world", 628 }, 629 { 630 name: "use fallback if nothing else set", 631 fallback: "fancy", 632 expected: "fancy", 633 }, 634 } 635 636 for _, tc := range cases { 637 bc := buildv1alpha1.BuildCondition{ 638 Message: tc.message, 639 Reason: tc.reason, 640 } 641 if actual := description(bc, tc.fallback); actual != tc.expected { 642 t.Errorf("%s: actual %q != expected %q", tc.name, actual, tc.expected) 643 } 644 } 645 } 646 647 func TestProwJobStatus(t *testing.T) { 648 now := metav1.Now() 649 later := metav1.NewTime(now.Time.Add(1 * time.Hour)) 650 cases := []struct { 651 name string 652 input buildv1alpha1.BuildStatus 653 state prowjobv1.ProwJobState 654 desc string 655 fallback string 656 }{ 657 { 658 name: "empty conditions returns triggered/scheduling", 659 state: prowjobv1.TriggeredState, 660 desc: descScheduling, 661 }, 662 { 663 name: "truly succeeded state returns success", 664 input: buildv1alpha1.BuildStatus{ 665 Conditions: []buildv1alpha1.BuildCondition{ 666 { 667 Type: buildv1alpha1.BuildSucceeded, 668 Status: corev1.ConditionTrue, 669 Message: "fancy", 670 }, 671 }, 672 }, 673 state: prowjobv1.SuccessState, 674 desc: "fancy", 675 fallback: descSucceeded, 676 }, 677 { 678 name: "falsely succeeded state returns failure", 679 input: buildv1alpha1.BuildStatus{ 680 Conditions: []buildv1alpha1.BuildCondition{ 681 { 682 Type: buildv1alpha1.BuildSucceeded, 683 Status: corev1.ConditionFalse, 684 Message: "weird", 685 }, 686 }, 687 }, 688 state: prowjobv1.FailureState, 689 desc: "weird", 690 fallback: descFailed, 691 }, 692 { 693 name: "unstarted job returns triggered/initializing", 694 input: buildv1alpha1.BuildStatus{ 695 Conditions: []buildv1alpha1.BuildCondition{ 696 { 697 Type: buildv1alpha1.BuildSucceeded, 698 Status: corev1.ConditionUnknown, 699 Message: "hola", 700 }, 701 }, 702 }, 703 state: prowjobv1.TriggeredState, 704 desc: "hola", 705 fallback: descInitializing, 706 }, 707 { 708 name: "unfinished job returns running", 709 input: buildv1alpha1.BuildStatus{ 710 StartTime: now, 711 Conditions: []buildv1alpha1.BuildCondition{ 712 { 713 Type: buildv1alpha1.BuildSucceeded, 714 Status: corev1.ConditionUnknown, 715 Message: "hola", 716 }, 717 }, 718 }, 719 state: prowjobv1.PendingState, 720 desc: "hola", 721 fallback: descRunning, 722 }, 723 { 724 name: "expect a finished job to have a success status", 725 input: buildv1alpha1.BuildStatus{ 726 StartTime: now, 727 CompletionTime: later, 728 Conditions: []buildv1alpha1.BuildCondition{ 729 { 730 Type: buildv1alpha1.BuildSucceeded, 731 Status: corev1.ConditionUnknown, 732 Message: "hola", 733 }, 734 }, 735 }, 736 state: prowjobv1.ErrorState, 737 desc: "hola", 738 fallback: descUnknown, 739 }, 740 { 741 name: "expect a finished job to have a condition", 742 input: buildv1alpha1.BuildStatus{ 743 StartTime: now, 744 CompletionTime: later, 745 }, 746 state: prowjobv1.ErrorState, 747 desc: descMissingCondition, 748 }, 749 } 750 751 for _, tc := range cases { 752 if len(tc.fallback) > 0 { 753 tc.desc = tc.fallback 754 tc.fallback = "" 755 tc.name += " [fallback]" 756 cond := tc.input.Conditions[0] 757 cond.Message = "" 758 tc.input.Conditions = []buildv1alpha1.BuildCondition{cond} 759 cases = append(cases, tc) 760 } 761 } 762 763 for _, tc := range cases { 764 t.Run(tc.name, func(t *testing.T) { 765 state, desc := prowJobStatus(tc.input) 766 if state != tc.state { 767 t.Errorf("state %q != expected %q", state, tc.state) 768 } 769 if desc != tc.desc { 770 t.Errorf("description %q != expected %q", desc, tc.desc) 771 } 772 }) 773 } 774 }