sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/resultstore/payload_test.go (about) 1 /* 2 Copyright 2023 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 resultstore 18 19 import ( 20 "testing" 21 "time" 22 23 "github.com/GoogleCloudPlatform/testgrid/metadata" 24 "github.com/google/go-cmp/cmp" 25 "google.golang.org/genproto/googleapis/devtools/resultstore/v2" 26 "google.golang.org/protobuf/testing/protocmp" 27 "google.golang.org/protobuf/types/known/durationpb" 28 "google.golang.org/protobuf/types/known/timestamppb" 29 corev1 "k8s.io/api/core/v1" 30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 v1 "sigs.k8s.io/prow/pkg/apis/prowjobs/v1" 32 "sigs.k8s.io/prow/pkg/kube" 33 ) 34 35 func TestInvocationID(t *testing.T) { 36 for _, tc := range []struct { 37 desc string 38 payload Payload 39 want string 40 wantErr bool 41 }{ 42 { 43 desc: "success", 44 payload: Payload{ 45 Job: &v1.ProwJob{ 46 ObjectMeta: metav1.ObjectMeta{ 47 Name: "job-name", 48 }, 49 }, 50 }, 51 want: "job-name", 52 }, 53 { 54 desc: "nil job", 55 payload: Payload{}, 56 wantErr: true, 57 }, 58 } { 59 t.Run(tc.desc, func(t *testing.T) { 60 got, err := tc.payload.InvocationID() 61 if err != nil { 62 if tc.wantErr { 63 t.Logf("got expected error: %v", err) 64 return 65 } 66 t.Fatal("got unexpected error") 67 } 68 if tc.wantErr { 69 t.Fatal("want error, got nil") 70 } 71 if got != tc.want { 72 t.Errorf("InvocationID got %v, want %v", got, tc.want) 73 } 74 }) 75 } 76 } 77 78 func int64Pointer(v int64) *int64 { 79 return &v 80 } 81 82 func TestInvocation(t *testing.T) { 83 for _, tc := range []struct { 84 desc string 85 payload *Payload 86 want *resultstore.Invocation 87 wantErr bool 88 }{ 89 { 90 desc: "complete", 91 payload: &Payload{ 92 Job: &v1.ProwJob{ 93 ObjectMeta: metav1.ObjectMeta{ 94 Name: "job-name", 95 Labels: map[string]string{ 96 kube.ProwJobTypeLabel: "job-type-label", 97 kube.RepoLabel: "repo-label", 98 kube.PullLabel: "pull-label", 99 kube.GerritPatchset: "gerrit-patchset-label", 100 kube.ProwBuildIDLabel: "build-id-label", 101 kube.ProwJobAnnotation: "job-label", 102 }, 103 }, 104 Spec: v1.ProwJobSpec{ 105 Job: "spec-job", 106 PodSpec: &corev1.PodSpec{ 107 Containers: []corev1.Container{ 108 { 109 Name: "container-1", 110 Args: []string{"arg-1", "arg-2"}, 111 Command: []string{"command"}, 112 Env: []corev1.EnvVar{ 113 { 114 Name: "env1", 115 Value: "env1-value", 116 }, 117 }, 118 }, 119 }, 120 }, 121 }, 122 Status: v1.ProwJobStatus{ 123 StartTime: metav1.Time{ 124 Time: time.Unix(100, 0), 125 }, 126 CompletionTime: &metav1.Time{ 127 Time: time.Unix(300, 0), 128 }, 129 State: v1.SuccessState, 130 URL: "https://prow/url", 131 BuildID: "build-id", 132 }, 133 }, 134 Started: &metadata.Started{ 135 Timestamp: 150, 136 RepoCommit: "repo-commit", 137 Repos: map[string]string{ 138 "https://started-review.repo": "started-branch", 139 }, 140 }, 141 Finished: &metadata.Finished{ 142 Timestamp: int64Pointer(250), 143 }, 144 ProjectID: "project-id", 145 }, 146 want: &resultstore.Invocation{ 147 InvocationAttributes: &resultstore.InvocationAttributes{ 148 ProjectId: "project-id", 149 Labels: []string{ 150 "prow", 151 }, 152 Description: "job-type-label for repo-label/pull-label/gerrit-patchset-label/build-id-label/job-label", 153 }, 154 Properties: []*resultstore.Property{ 155 { 156 Key: "Instance", 157 Value: "build-id", 158 }, 159 { 160 Key: "Job", 161 Value: "spec-job", 162 }, 163 { 164 Key: "Prow_Dashboard_URL", 165 Value: "https://prow/url", 166 }, 167 { 168 Key: "Env", 169 Value: "env1=env1-value", 170 }, 171 { 172 Key: "Commit", 173 Value: "repo-commit", 174 }, 175 { 176 Key: "Branch", 177 Value: "started-branch", 178 }, 179 { 180 Key: "Repo", 181 Value: "https://started.repo", 182 }, 183 }, 184 StatusAttributes: &resultstore.StatusAttributes{ 185 Status: resultstore.Status_PASSED, 186 }, 187 Timing: &resultstore.Timing{ 188 StartTime: ×tamppb.Timestamp{ 189 Seconds: 100, 190 }, 191 Duration: &durationpb.Duration{ 192 Seconds: 200, 193 }, 194 }, 195 WorkspaceInfo: &resultstore.WorkspaceInfo{ 196 CommandLines: []*resultstore.CommandLine{ 197 { 198 Label: "original", 199 Tool: "command", 200 Args: []string{"arg-1", "arg-2"}, 201 }, 202 }, 203 }, 204 }, 205 }, 206 { 207 desc: "completiontime started finished nil", 208 payload: &Payload{ 209 Job: &v1.ProwJob{ 210 ObjectMeta: metav1.ObjectMeta{ 211 Name: "job-name", 212 Labels: map[string]string{ 213 kube.ProwJobTypeLabel: "job-type-label", 214 kube.RepoLabel: "repo-label", 215 kube.ProwBuildIDLabel: "build-id-label", 216 kube.ProwJobAnnotation: "job-label", 217 }, 218 }, 219 Spec: v1.ProwJobSpec{ 220 Job: "spec-job", 221 PodSpec: &corev1.PodSpec{ 222 Containers: []corev1.Container{ 223 { 224 Name: "container-1", 225 Args: []string{"arg-1", "arg-2"}, 226 Command: []string{"command"}, 227 Env: []corev1.EnvVar{ 228 { 229 Name: "env1", 230 Value: "env1-value", 231 }, 232 { 233 Name: "env2", 234 Value: "env2-value", 235 }, 236 }, 237 }, 238 }, 239 }, 240 }, 241 Status: v1.ProwJobStatus{ 242 StartTime: metav1.Time{ 243 Time: time.Unix(100, 0), 244 }, 245 CompletionTime: nil, 246 State: v1.SuccessState, 247 URL: "https://prow/url", 248 BuildID: "build-id", 249 }, 250 }, 251 Started: nil, 252 Finished: nil, 253 ProjectID: "project-id", 254 }, 255 want: &resultstore.Invocation{ 256 InvocationAttributes: &resultstore.InvocationAttributes{ 257 ProjectId: "project-id", 258 Labels: []string{ 259 "prow", 260 }, 261 Description: "job-type-label for repo-label/build-id-label/job-label", 262 }, 263 Properties: []*resultstore.Property{ 264 { 265 Key: "Instance", 266 Value: "build-id", 267 }, 268 { 269 Key: "Job", 270 Value: "spec-job", 271 }, 272 { 273 Key: "Prow_Dashboard_URL", 274 Value: "https://prow/url", 275 }, 276 { 277 Key: "Env", 278 Value: "env1=env1-value", 279 }, 280 { 281 Key: "Env", 282 Value: "env2=env2-value", 283 }, 284 }, 285 StatusAttributes: &resultstore.StatusAttributes{ 286 Status: resultstore.Status_PASSED, 287 }, 288 Timing: &resultstore.Timing{ 289 StartTime: ×tamppb.Timestamp{ 290 Seconds: 100, 291 }, 292 Duration: &durationpb.Duration{ 293 Seconds: 0, 294 }, 295 }, 296 WorkspaceInfo: &resultstore.WorkspaceInfo{ 297 CommandLines: []*resultstore.CommandLine{ 298 { 299 Label: "original", 300 Tool: "command", 301 Args: []string{"arg-1", "arg-2"}, 302 }, 303 }, 304 }, 305 }, 306 }, 307 { 308 desc: "job nil", 309 payload: &Payload{}, 310 wantErr: true, 311 }, 312 } { 313 t.Run(tc.desc, func(t *testing.T) { 314 got, err := tc.payload.Invocation() 315 if err != nil { 316 if tc.wantErr { 317 t.Logf("got expected error: %v", err) 318 return 319 } 320 t.Fatalf("got unexpected error: %v", err) 321 } 322 if tc.wantErr { 323 t.Fatal("wanted error, got nil") 324 } 325 if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { 326 t.Errorf("invocation differs (-want +got):\n%s", diff) 327 } 328 }) 329 } 330 } 331 332 func TestInvocationTiming(t *testing.T) { 333 for _, tc := range []struct { 334 desc string 335 job *v1.ProwJob 336 want *resultstore.Timing 337 }{ 338 { 339 desc: "success", 340 job: &v1.ProwJob{ 341 Status: v1.ProwJobStatus{ 342 StartTime: metav1.Time{ 343 Time: time.Unix(100, 0), 344 }, 345 CompletionTime: &metav1.Time{ 346 Time: time.Unix(300, 0), 347 }, 348 }, 349 }, 350 want: &resultstore.Timing{ 351 StartTime: ×tamppb.Timestamp{ 352 Seconds: 100, 353 }, 354 Duration: &durationpb.Duration{ 355 Seconds: 200, 356 }, 357 }, 358 }, 359 { 360 desc: "completion nil", 361 job: &v1.ProwJob{ 362 Status: v1.ProwJobStatus{ 363 StartTime: metav1.Time{ 364 Time: time.Unix(100, 0), 365 }, 366 CompletionTime: nil, 367 }, 368 }, 369 want: &resultstore.Timing{ 370 StartTime: ×tamppb.Timestamp{ 371 Seconds: 100, 372 }, 373 Duration: &durationpb.Duration{ 374 Seconds: 0, 375 }, 376 }, 377 }, 378 { 379 desc: "job nil", 380 job: nil, 381 want: nil, 382 }, 383 } { 384 t.Run(tc.desc, func(t *testing.T) { 385 got := invocationTiming(tc.job) 386 if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { 387 t.Errorf("timing differs (-want +got):\n%s", diff) 388 } 389 }) 390 } 391 } 392 393 func TestInvocationProperties(t *testing.T) { 394 for _, tc := range []struct { 395 desc string 396 job *v1.ProwJob 397 started *metadata.Started 398 want []*resultstore.Property 399 }{ 400 { 401 desc: "success", 402 job: &v1.ProwJob{ 403 Spec: v1.ProwJobSpec{ 404 Job: "spec-job", 405 PodSpec: &corev1.PodSpec{ 406 Containers: []corev1.Container{ 407 { 408 Name: "container-1", 409 Args: []string{"arg-1", "arg-2"}, 410 Command: []string{"command"}, 411 Env: []corev1.EnvVar{ 412 { 413 Name: "env1", 414 Value: "env1-value", 415 }, 416 }, 417 }, 418 }, 419 }, 420 }, 421 Status: v1.ProwJobStatus{ 422 URL: "https://prow/url", 423 BuildID: "build-id", 424 }, 425 }, 426 started: &metadata.Started{ 427 Timestamp: 150, 428 RepoCommit: "repo-commit", 429 Repos: map[string]string{ 430 "https://started.repo": "started-branch", 431 }, 432 }, 433 want: []*resultstore.Property{ 434 { 435 Key: "Instance", 436 Value: "build-id", 437 }, 438 { 439 Key: "Job", 440 Value: "spec-job", 441 }, 442 { 443 Key: "Prow_Dashboard_URL", 444 Value: "https://prow/url", 445 }, 446 { 447 Key: "Env", 448 Value: "env1=env1-value", 449 }, 450 { 451 Key: "Commit", 452 Value: "repo-commit", 453 }, 454 { 455 Key: "Branch", 456 Value: "started-branch", 457 }, 458 { 459 Key: "Repo", 460 Value: "https://started.repo", 461 }, 462 }, 463 }, 464 { 465 desc: "job nil", 466 job: nil, 467 started: &metadata.Started{ 468 Timestamp: 150, 469 RepoCommit: "repo-commit", 470 Repos: map[string]string{ 471 "https://started.repo": "started-branch", 472 }, 473 }, 474 want: []*resultstore.Property{ 475 { 476 Key: "Commit", 477 Value: "repo-commit", 478 }, 479 { 480 Key: "Branch", 481 Value: "started-branch", 482 }, 483 { 484 Key: "Repo", 485 Value: "https://started.repo", 486 }, 487 }, 488 }, 489 } { 490 t.Run(tc.desc, func(t *testing.T) { 491 got := invocationProperties(tc.job, tc.started) 492 if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { 493 t.Errorf("properties differ (-want +got):\n%s", diff) 494 } 495 }) 496 } 497 } 498 499 func TestStartedProperties(t *testing.T) { 500 for _, tc := range []struct { 501 desc string 502 started *metadata.Started 503 want []*resultstore.Property 504 }{ 505 { 506 desc: "single repo", 507 started: &metadata.Started{ 508 Timestamp: 150, 509 RepoCommit: "repo-commit", 510 Repos: map[string]string{ 511 "https://repo1.com": "branch1", 512 }, 513 }, 514 want: []*resultstore.Property{ 515 { 516 Key: "Commit", 517 Value: "repo-commit", 518 }, 519 { 520 Key: "Branch", 521 Value: "branch1", 522 }, 523 { 524 Key: "Repo", 525 Value: "https://repo1.com", 526 }, 527 }, 528 }, 529 { 530 desc: "multi repo", 531 started: &metadata.Started{ 532 Timestamp: 150, 533 RepoCommit: "repo-commit", 534 Repos: map[string]string{ 535 "repo/two": "branch2", 536 "https://repo1-review.com": "branch1", 537 }, 538 }, 539 want: []*resultstore.Property{ 540 { 541 Key: "Commit", 542 Value: "repo-commit", 543 }, 544 { 545 Key: "Branch", 546 Value: "branch1", 547 }, 548 { 549 Key: "Branch", 550 Value: "branch2", 551 }, 552 { 553 Key: "Repo", 554 Value: "https://repo1.com", 555 }, 556 { 557 Key: "Repo", 558 Value: "repo/two", 559 }, 560 }, 561 }, 562 { 563 desc: "non gerrit", 564 started: &metadata.Started{ 565 Timestamp: 150, 566 RepoCommit: "repo-commit", 567 Repos: map[string]string{ 568 "https://repo1.other-review.com": "branch1", 569 }, 570 }, 571 want: []*resultstore.Property{ 572 { 573 Key: "Commit", 574 Value: "repo-commit", 575 }, 576 { 577 Key: "Branch", 578 Value: "branch1", 579 }, 580 { 581 Key: "Repo", 582 Value: "https://repo1.other-review.com", 583 }, 584 }, 585 }, 586 { 587 desc: "nil", 588 started: nil, 589 want: nil, 590 }, 591 } { 592 t.Run(tc.desc, func(t *testing.T) { 593 got := startedProperties(tc.started) 594 if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { 595 t.Errorf("properties differ (-want +got):\n%s", diff) 596 } 597 }) 598 } 599 } 600 601 func TestPodSpecProperties(t *testing.T) { 602 for _, tc := range []struct { 603 desc string 604 podSpec *corev1.PodSpec 605 want []*resultstore.Property 606 }{ 607 { 608 desc: "success", 609 podSpec: &corev1.PodSpec{ 610 Containers: []corev1.Container{ 611 { 612 Name: "container-1", 613 Args: []string{"arg-1", "arg-2"}, 614 Command: []string{"command"}, 615 Env: []corev1.EnvVar{ 616 { 617 Name: "env1", 618 Value: "env1-value", 619 }, 620 { 621 Name: "env2", 622 Value: "env2-value", 623 }, 624 { 625 Name: "", 626 Value: "skip empty Name", 627 }, 628 }, 629 }, 630 { 631 Name: "container-2", 632 Args: []string{"arg-3", "arg-4"}, 633 Command: []string{"command2"}, 634 Env: []corev1.EnvVar{ 635 { 636 Name: "env1", 637 Value: "env1-value", 638 }, 639 { 640 Name: "env3", 641 Value: "env3-value", 642 }, 643 }, 644 }, 645 }, 646 }, 647 want: []*resultstore.Property{ 648 { 649 Key: "Env", 650 Value: "env1=env1-value", 651 }, 652 { 653 Key: "Env", 654 Value: "env2=env2-value", 655 }, 656 { 657 Key: "Env", 658 Value: "env3=env3-value", 659 }, 660 }, 661 }, 662 { 663 desc: "nil podspec", 664 podSpec: nil, 665 want: nil, 666 }, 667 } { 668 t.Run(tc.desc, func(t *testing.T) { 669 got := podSpecProperties(tc.podSpec) 670 if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { 671 t.Errorf("properties differ (-want +got):\n%s", diff) 672 } 673 }) 674 } 675 } 676 677 func TestStatusAttributes(t *testing.T) { 678 for _, tc := range []struct { 679 prowState v1.ProwJobState 680 want resultstore.Status 681 }{ 682 { 683 prowState: v1.SuccessState, 684 want: resultstore.Status_PASSED, 685 }, 686 { 687 prowState: v1.FailureState, 688 want: resultstore.Status_FAILED, 689 }, 690 { 691 prowState: v1.AbortedState, 692 want: resultstore.Status_CANCELLED, 693 }, 694 { 695 prowState: v1.ErrorState, 696 want: resultstore.Status_INCOMPLETE, 697 }, 698 { 699 prowState: v1.PendingState, 700 want: resultstore.Status_TOOL_FAILED, 701 }, 702 } { 703 t.Run(string(tc.prowState), func(t *testing.T) { 704 job := &v1.ProwJob{ 705 Status: v1.ProwJobStatus{ 706 State: tc.prowState, 707 }, 708 } 709 want := &resultstore.StatusAttributes{ 710 Status: tc.want, 711 } 712 if diff := cmp.Diff(want, invocationStatusAttributes(job), protocmp.Transform()); diff != "" { 713 t.Errorf("invocationStatusAttributes differs (-want +got):\n%s", diff) 714 } 715 716 }) 717 } 718 } 719 720 func TestDefaultconfiguration(t *testing.T) { 721 p := &Payload{} 722 got := p.DefaultConfiguration() 723 want := &resultstore.Configuration{ 724 Id: &resultstore.Configuration_Id{ 725 ConfigurationId: "default", 726 }, 727 } 728 if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" { 729 t.Errorf("defaultConfiguration differs (-want +got):\n%s", diff) 730 } 731 } 732 733 func TestOverallTarget(t *testing.T) { 734 for _, tc := range []struct { 735 desc string 736 payload *Payload 737 want *resultstore.Target 738 }{ 739 { 740 desc: "success", 741 payload: &Payload{ 742 Job: &v1.ProwJob{ 743 Spec: v1.ProwJobSpec{ 744 Job: "spec-job", 745 }, 746 }, 747 }, 748 want: &resultstore.Target{ 749 Id: &resultstore.Target_Id{ 750 TargetId: "spec-job", 751 }, 752 TargetAttributes: &resultstore.TargetAttributes{ 753 Type: resultstore.TargetType_TEST, 754 }, 755 Visible: true, 756 }, 757 }, 758 { 759 desc: "nil job", 760 payload: &Payload{}, 761 want: &resultstore.Target{ 762 Id: &resultstore.Target_Id{ 763 TargetId: "Unknown", 764 }, 765 TargetAttributes: &resultstore.TargetAttributes{ 766 Type: resultstore.TargetType_TEST, 767 }, 768 Visible: true, 769 }, 770 }, 771 } { 772 t.Run(tc.desc, func(t *testing.T) { 773 if diff := cmp.Diff(tc.want, tc.payload.OverallTarget(), protocmp.Transform()); diff != "" { 774 t.Errorf("overallTarget differs (-want +got):\n%s", diff) 775 } 776 }) 777 } 778 } 779 780 func TestConfiguredTarget(t *testing.T) { 781 for _, tc := range []struct { 782 desc string 783 payload *Payload 784 want *resultstore.ConfiguredTarget 785 }{ 786 { 787 desc: "success", 788 payload: &Payload{ 789 Job: &v1.ProwJob{ 790 Spec: v1.ProwJobSpec{ 791 Job: "spec-job", 792 }, 793 Status: v1.ProwJobStatus{ 794 State: v1.SuccessState, 795 }, 796 }, 797 Started: &metadata.Started{ 798 Timestamp: 150, 799 RepoCommit: "repo-commit", 800 Repos: map[string]string{ 801 "repo-key": "repo-value", 802 }, 803 }, 804 Finished: &metadata.Finished{ 805 Timestamp: int64Pointer(250), 806 }, 807 }, 808 want: &resultstore.ConfiguredTarget{ 809 Id: &resultstore.ConfiguredTarget_Id{ 810 TargetId: "spec-job", 811 ConfigurationId: "default", 812 }, 813 StatusAttributes: &resultstore.StatusAttributes{ 814 Status: resultstore.Status_PASSED, 815 }, 816 Timing: &resultstore.Timing{ 817 StartTime: ×tamppb.Timestamp{ 818 Seconds: 150, 819 }, 820 Duration: &durationpb.Duration{ 821 Seconds: 100, 822 }, 823 }, 824 }, 825 }, 826 { 827 desc: "nil job", 828 payload: &Payload{}, 829 want: &resultstore.ConfiguredTarget{ 830 Id: &resultstore.ConfiguredTarget_Id{ 831 TargetId: "Unknown", 832 ConfigurationId: "default", 833 }, 834 StatusAttributes: &resultstore.StatusAttributes{ 835 Status: resultstore.Status_TOOL_FAILED, 836 }, 837 }, 838 }, 839 } { 840 t.Run(tc.desc, func(t *testing.T) { 841 if diff := cmp.Diff(tc.want, tc.payload.ConfiguredTarget(), protocmp.Transform()); diff != "" { 842 t.Errorf("configuredTarget differs (-want +got):\n%s", diff) 843 } 844 }) 845 } 846 } 847 848 func TestOverallAction(t *testing.T) { 849 for _, tc := range []struct { 850 desc string 851 payload *Payload 852 want *resultstore.Action 853 }{ 854 { 855 desc: "success", 856 payload: &Payload{ 857 Job: &v1.ProwJob{ 858 Spec: v1.ProwJobSpec{ 859 Job: "spec-job", 860 }, 861 Status: v1.ProwJobStatus{ 862 State: v1.SuccessState, 863 }, 864 }, 865 Started: &metadata.Started{ 866 Timestamp: 150, 867 RepoCommit: "repo-commit", 868 Repos: map[string]string{ 869 "repo-key": "repo-value", 870 }, 871 }, 872 Finished: &metadata.Finished{ 873 Timestamp: int64Pointer(250), 874 }, 875 }, 876 want: &resultstore.Action{ 877 Id: &resultstore.Action_Id{ 878 TargetId: "spec-job", 879 ConfigurationId: "default", 880 ActionId: "overall", 881 }, 882 StatusAttributes: &resultstore.StatusAttributes{ 883 Status: resultstore.Status_PASSED, 884 }, 885 ActionType: &resultstore.Action_TestAction{}, 886 Timing: &resultstore.Timing{ 887 StartTime: ×tamppb.Timestamp{ 888 Seconds: 150, 889 }, 890 Duration: &durationpb.Duration{ 891 Seconds: 100, 892 }, 893 }, 894 }, 895 }, 896 { 897 desc: "started nil", 898 payload: &Payload{ 899 Job: &v1.ProwJob{ 900 Spec: v1.ProwJobSpec{ 901 Job: "spec-job", 902 }, 903 Status: v1.ProwJobStatus{ 904 State: v1.ErrorState, 905 }, 906 }, 907 Finished: &metadata.Finished{ 908 Timestamp: int64Pointer(250), 909 }, 910 }, 911 want: &resultstore.Action{ 912 Id: &resultstore.Action_Id{ 913 TargetId: "spec-job", 914 ConfigurationId: "default", 915 ActionId: "overall", 916 }, 917 StatusAttributes: &resultstore.StatusAttributes{ 918 Status: resultstore.Status_INCOMPLETE, 919 }, 920 ActionType: &resultstore.Action_TestAction{}, 921 }, 922 }, 923 { 924 desc: "finished nil use completion time", 925 payload: &Payload{ 926 Job: &v1.ProwJob{ 927 Spec: v1.ProwJobSpec{ 928 Job: "spec-job", 929 }, 930 Status: v1.ProwJobStatus{ 931 State: v1.FailureState, 932 CompletionTime: &metav1.Time{ 933 Time: time.Unix(250, 0), 934 }, 935 }, 936 }, 937 Started: &metadata.Started{ 938 Timestamp: 150, 939 RepoCommit: "repo-commit", 940 Repos: map[string]string{ 941 "repo-key": "repo-value", 942 }, 943 }, 944 }, 945 want: &resultstore.Action{ 946 Id: &resultstore.Action_Id{ 947 TargetId: "spec-job", 948 ConfigurationId: "default", 949 ActionId: "overall", 950 }, 951 StatusAttributes: &resultstore.StatusAttributes{ 952 Status: resultstore.Status_FAILED, 953 }, 954 ActionType: &resultstore.Action_TestAction{}, 955 Timing: &resultstore.Timing{ 956 StartTime: ×tamppb.Timestamp{ 957 Seconds: 150, 958 }, 959 Duration: &durationpb.Duration{ 960 Seconds: 100, 961 }, 962 }, 963 }, 964 }, 965 { 966 desc: "finished and job completion time nil", 967 payload: &Payload{ 968 Job: &v1.ProwJob{ 969 Spec: v1.ProwJobSpec{ 970 Job: "spec-job", 971 }, 972 Status: v1.ProwJobStatus{ 973 CompletionTime: nil, 974 }, 975 }, 976 Started: &metadata.Started{ 977 Timestamp: 150, 978 RepoCommit: "repo-commit", 979 Repos: map[string]string{ 980 "repo-key": "repo-value", 981 }, 982 }, 983 }, 984 want: &resultstore.Action{ 985 Id: &resultstore.Action_Id{ 986 TargetId: "spec-job", 987 ConfigurationId: "default", 988 ActionId: "overall", 989 }, 990 StatusAttributes: &resultstore.StatusAttributes{ 991 Status: resultstore.Status_TOOL_FAILED, 992 }, 993 ActionType: &resultstore.Action_TestAction{}, 994 }, 995 }, 996 { 997 desc: "job nil", 998 payload: &Payload{ 999 Started: &metadata.Started{ 1000 Timestamp: 150, 1001 RepoCommit: "repo-commit", 1002 Repos: map[string]string{ 1003 "repo-key": "repo-value", 1004 }, 1005 }, 1006 Finished: &metadata.Finished{ 1007 Timestamp: int64Pointer(250), 1008 }, 1009 }, 1010 want: &resultstore.Action{ 1011 Id: &resultstore.Action_Id{ 1012 TargetId: "Unknown", 1013 ConfigurationId: "default", 1014 ActionId: "overall", 1015 }, 1016 StatusAttributes: &resultstore.StatusAttributes{ 1017 Status: resultstore.Status_TOOL_FAILED, 1018 }, 1019 ActionType: &resultstore.Action_TestAction{}, 1020 Timing: &resultstore.Timing{ 1021 StartTime: ×tamppb.Timestamp{ 1022 Seconds: 150, 1023 }, 1024 Duration: &durationpb.Duration{ 1025 Seconds: 100, 1026 }, 1027 }, 1028 }, 1029 }, 1030 } { 1031 t.Run(tc.desc, func(t *testing.T) { 1032 if diff := cmp.Diff(tc.want, tc.payload.OverallAction(), protocmp.Transform()); diff != "" { 1033 t.Errorf("overallAction differs (-want +got):\n%s", diff) 1034 } 1035 }) 1036 } 1037 }