sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/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  	"errors"
    21  	"reflect"
    22  	"testing"
    23  
    24  	pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
    25  	coreapi "k8s.io/api/core/v1"
    26  	prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1"
    27  )
    28  
    29  func TestRunIfChangedPresubmits(t *testing.T) {
    30  	PresubmitsStatic := []Presubmit{
    31  		{
    32  			JobBase: JobBase{
    33  				Name: "cross build",
    34  			},
    35  			RegexpChangeMatcher: RegexpChangeMatcher{
    36  				RunIfChanged: `(Makefile|\.sh|_(windows|linux|osx|unknown)(_test)?\.go)$`,
    37  			},
    38  		},
    39  	}
    40  	SetPresubmitRegexes(PresubmitsStatic)
    41  	ps := PresubmitsStatic[0]
    42  	var testcases = []struct {
    43  		changes  []string
    44  		expected bool
    45  	}{
    46  		{[]string{"some random file"}, false},
    47  		{[]string{"./pkg/util/rlimit/rlimit_linux.go"}, true},
    48  		{[]string{"./pkg/util/rlimit/rlimit_unknown_test.go"}, true},
    49  		{[]string{"build.sh"}, true},
    50  		{[]string{"build.shoo"}, false},
    51  		{[]string{"Makefile"}, true},
    52  	}
    53  	for _, tc := range testcases {
    54  		actual := ps.RunsAgainstChanges(tc.changes)
    55  		if actual != tc.expected {
    56  			t.Errorf("wrong RunsAgainstChanges(%#v) result. Got %v, expected %v", tc.changes, actual, tc.expected)
    57  		}
    58  	}
    59  }
    60  
    61  // TestRunIfChangedPostsubmits is identical to TestRunIfChangedPresubmits.
    62  func TestRunIfChangedPostsubmits(t *testing.T) {
    63  	PostsubmitsStatic := []Postsubmit{
    64  		{
    65  			JobBase: JobBase{
    66  				Name: "cross build",
    67  			},
    68  			RegexpChangeMatcher: RegexpChangeMatcher{
    69  				RunIfChanged: `(Makefile|\.sh|_(windows|linux|osx|unknown)(_test)?\.go)$`,
    70  			},
    71  		},
    72  	}
    73  	SetPostsubmitRegexes(PostsubmitsStatic)
    74  	ps := PostsubmitsStatic[0]
    75  	var testcases = []struct {
    76  		changes  []string
    77  		expected bool
    78  	}{
    79  		{[]string{"some random file"}, false},
    80  		{[]string{"./pkg/util/rlimit/rlimit_linux.go"}, true},
    81  		{[]string{"./pkg/util/rlimit/rlimit_unknown_test.go"}, true},
    82  		{[]string{"build.sh"}, true},
    83  		{[]string{"build.shoo"}, false},
    84  		{[]string{"Makefile"}, true},
    85  	}
    86  	for _, tc := range testcases {
    87  		actual := ps.RunsAgainstChanges(tc.changes)
    88  		if actual != tc.expected {
    89  			t.Errorf("wrong RunsAgainstChanges(%#v) result. Got %v, expected %v", tc.changes, actual, tc.expected)
    90  		}
    91  	}
    92  }
    93  
    94  func TestSkipIfOnlyChangedPresubmits(t *testing.T) {
    95  	PresubmitsStatic := []Presubmit{
    96  		{
    97  			JobBase: JobBase{
    98  				Name: "cross build",
    99  			},
   100  			RegexpChangeMatcher: RegexpChangeMatcher{
   101  				// Files satisfying any of:
   102  				// - in the top-level docs/ directory
   103  				// - with .md/.adoc extensions
   104  				// - with basename README or OWNERS
   105  				SkipIfOnlyChanged: `^docs/|\.(md|adoc)$|/?(README|OWNERS)$`,
   106  			},
   107  		},
   108  	}
   109  	SetPresubmitRegexes(PresubmitsStatic)
   110  	ps := PresubmitsStatic[0]
   111  	var testcases = []struct {
   112  		changes  []string
   113  		expected bool
   114  	}{
   115  		{[]string{"some random file"}, true},
   116  		{[]string{"./pkg/util/rlimit/rlimit_linux.go"}, true},
   117  		// Skips because in docs/, even though it's a go file. Caveat emptor.
   118  		{[]string{"docs/cobragen.go"}, false},
   119  		// Our regex isn't expecting paths to start with ./
   120  		{[]string{"./docs/cobragen.go"}, true},
   121  		{[]string{"README", "README.md", "OWNERS", "path/to/something.adoc", "path/to/README"}, false},
   122  		// Any non-matching file triggers the job
   123  		{[]string{"README", "README.md", "OWNERS", "path/to/something.adoc", "path/to/README", "foo"}, true},
   124  	}
   125  	for _, tc := range testcases {
   126  		actual := ps.RunsAgainstChanges(tc.changes)
   127  		if actual != tc.expected {
   128  			t.Errorf("wrong RunsAgainstChanges(%#v) result. Got %v, expected %v", tc.changes, actual, tc.expected)
   129  		}
   130  	}
   131  }
   132  
   133  // TestSkipIfOnlyChangedPostsubmits is identical to TestSkipIfOnlyChangedPresubmits.
   134  func TestSkipIfOnlyChangedPostsubmits(t *testing.T) {
   135  	PostsubmitsStatic := []Postsubmit{
   136  		{
   137  			JobBase: JobBase{
   138  				Name: "cross build",
   139  			},
   140  			RegexpChangeMatcher: RegexpChangeMatcher{
   141  				// Files satisfying any of:
   142  				// - in the top-level docs/ directory
   143  				// - with .md/.adoc extensions
   144  				// - with basename README or OWNERS
   145  				SkipIfOnlyChanged: `^docs/|\.(md|adoc)$|/?(README|OWNERS)$`,
   146  			},
   147  		},
   148  	}
   149  	SetPostsubmitRegexes(PostsubmitsStatic)
   150  	ps := PostsubmitsStatic[0]
   151  	var testcases = []struct {
   152  		changes  []string
   153  		expected bool
   154  	}{
   155  		{[]string{"some random file"}, true},
   156  		{[]string{"./pkg/util/rlimit/rlimit_linux.go"}, true},
   157  		// Skips because in docs/, even though it's a go file. Caveat emptor.
   158  		{[]string{"docs/cobragen.go"}, false},
   159  		// Our regex isn't expecting paths to start with ./
   160  		{[]string{"./docs/cobragen.go"}, true},
   161  		{[]string{"README", "README.md", "OWNERS", "path/to/something.adoc", "path/to/README"}, false},
   162  		// Any non-matching file triggers the job
   163  		{[]string{"README", "README.md", "OWNERS", "path/to/something.adoc", "path/to/README", "foo"}, true},
   164  	}
   165  	for _, tc := range testcases {
   166  		actual := ps.RunsAgainstChanges(tc.changes)
   167  		if actual != tc.expected {
   168  			t.Errorf("wrong RunsAgainstChanges(%#v) result. Got %v, expected %v", tc.changes, actual, tc.expected)
   169  		}
   170  	}
   171  }
   172  
   173  func TestListPresubmit(t *testing.T) {
   174  	c := &Config{
   175  		JobConfig: JobConfig{
   176  			PresubmitsStatic: map[string][]Presubmit{
   177  				"r1": {
   178  					{
   179  						JobBase: JobBase{
   180  							Name: "a",
   181  						},
   182  					},
   183  					{JobBase: JobBase{Name: "b"}},
   184  				},
   185  				"r2": {
   186  					{
   187  						JobBase: JobBase{
   188  							Name: "c",
   189  						},
   190  					},
   191  					{JobBase: JobBase{Name: "d"}},
   192  				},
   193  			},
   194  			PostsubmitsStatic: map[string][]Postsubmit{
   195  				"r1": {{JobBase: JobBase{Name: "e"}}},
   196  			},
   197  			Periodics: []Periodic{
   198  				{JobBase: JobBase{Name: "f"}},
   199  			},
   200  		},
   201  	}
   202  
   203  	var testcases = []struct {
   204  		name     string
   205  		expected []string
   206  		repos    []string
   207  	}{
   208  		{
   209  			"all presubmits",
   210  			[]string{"a", "b", "c", "d"},
   211  			[]string{},
   212  		},
   213  		{
   214  			"r2 presubmits",
   215  			[]string{"c", "d"},
   216  			[]string{"r2"},
   217  		},
   218  	}
   219  
   220  	for _, tc := range testcases {
   221  		actual := c.AllStaticPresubmits(tc.repos)
   222  		if len(actual) != len(tc.expected) {
   223  			t.Fatalf("test %s - Wrong number of jobs. Got %v, expected %v", tc.name, actual, tc.expected)
   224  		}
   225  		for _, j1 := range tc.expected {
   226  			found := false
   227  			for _, j2 := range actual {
   228  				if j1 == j2.Name {
   229  					found = true
   230  					break
   231  				}
   232  			}
   233  			if !found {
   234  				t.Errorf("test %s - Did not find job %s in output", tc.name, j1)
   235  			}
   236  		}
   237  	}
   238  }
   239  
   240  func TestListPostsubmit(t *testing.T) {
   241  	c := &Config{
   242  		JobConfig: JobConfig{
   243  			PresubmitsStatic: map[string][]Presubmit{
   244  				"r1": {{JobBase: JobBase{Name: "a"}}},
   245  			},
   246  			PostsubmitsStatic: map[string][]Postsubmit{
   247  				"r1": {
   248  					{
   249  						JobBase: JobBase{
   250  							Name: "c",
   251  						},
   252  					},
   253  					{JobBase: JobBase{Name: "d"}},
   254  				},
   255  				"r2": {{JobBase: JobBase{Name: "e"}}},
   256  			},
   257  			Periodics: []Periodic{
   258  				{JobBase: JobBase{Name: "f"}},
   259  			},
   260  		},
   261  	}
   262  
   263  	var testcases = []struct {
   264  		name     string
   265  		expected []string
   266  		repos    []string
   267  	}{
   268  		{
   269  			"all postsubmits",
   270  			[]string{"c", "d", "e"},
   271  			[]string{},
   272  		},
   273  		{
   274  			"r2 presubmits",
   275  			[]string{"e"},
   276  			[]string{"r2"},
   277  		},
   278  	}
   279  
   280  	for _, tc := range testcases {
   281  		actual := c.AllStaticPostsubmits(tc.repos)
   282  		if len(actual) != len(tc.expected) {
   283  			t.Fatalf("%s - Wrong number of jobs. Got %v, expected %v", tc.name, actual, tc.expected)
   284  		}
   285  		for _, j1 := range tc.expected {
   286  			found := false
   287  			for _, j2 := range actual {
   288  				if j1 == j2.Name {
   289  					found = true
   290  					break
   291  				}
   292  			}
   293  			if !found {
   294  				t.Errorf("Did not find job %s in output", j1)
   295  			}
   296  		}
   297  	}
   298  }
   299  
   300  func TestListPeriodic(t *testing.T) {
   301  	c := &Config{
   302  		JobConfig: JobConfig{
   303  			PresubmitsStatic: map[string][]Presubmit{
   304  				"r1": {{JobBase: JobBase{Name: "a"}}},
   305  			},
   306  			PostsubmitsStatic: map[string][]Postsubmit{
   307  				"r1": {{JobBase: JobBase{Name: "b"}}},
   308  			},
   309  			Periodics: []Periodic{
   310  				{
   311  					JobBase: JobBase{
   312  						Name: "c",
   313  					},
   314  				},
   315  				{JobBase: JobBase{Name: "d"}},
   316  			},
   317  		},
   318  	}
   319  
   320  	expected := []string{"c", "d"}
   321  	actual := c.AllPeriodics()
   322  	if len(actual) != len(expected) {
   323  		t.Fatalf("Wrong number of jobs. Got %v, expected %v", actual, expected)
   324  	}
   325  	for _, j1 := range expected {
   326  		found := false
   327  		for _, j2 := range actual {
   328  			if j1 == j2.Name {
   329  				found = true
   330  				break
   331  			}
   332  		}
   333  		if !found {
   334  			t.Errorf("Did not find job %s in output", j1)
   335  		}
   336  	}
   337  }
   338  
   339  func TestRunAgainstBranch(t *testing.T) {
   340  	jobs := []Presubmit{
   341  		{
   342  			JobBase: JobBase{
   343  				Name: "a",
   344  			},
   345  			Brancher: Brancher{SkipBranches: []string{"s"}},
   346  		},
   347  		{
   348  			JobBase: JobBase{
   349  				Name: "b",
   350  			},
   351  			Brancher: Brancher{Branches: []string{"r"}},
   352  		},
   353  		{
   354  			JobBase: JobBase{
   355  				Name: "c",
   356  			},
   357  			Brancher: Brancher{
   358  				SkipBranches: []string{"s"},
   359  				Branches:     []string{"r"},
   360  			},
   361  		},
   362  		{
   363  			JobBase: JobBase{
   364  				Name: "d",
   365  			},
   366  			Brancher: Brancher{
   367  				SkipBranches: []string{"s"},
   368  				Branches:     []string{"s", "r"},
   369  			},
   370  		},
   371  		{
   372  			JobBase: JobBase{
   373  				Name: "default",
   374  			},
   375  		},
   376  	}
   377  
   378  	if err := SetPresubmitRegexes(jobs); err != nil {
   379  		t.Fatalf("could not set regexes: %v", err)
   380  	}
   381  
   382  	for _, job := range jobs {
   383  		if job.Name == "default" {
   384  			if !job.Brancher.ShouldRun("s") {
   385  				t.Errorf("Job %s should run branch s", job.Name)
   386  			}
   387  		} else if job.Brancher.ShouldRun("s") {
   388  			t.Errorf("Job %s should not run branch s", job.Name)
   389  		}
   390  
   391  		if !job.Brancher.ShouldRun("r") {
   392  			t.Errorf("Job %s should run branch r", job.Name)
   393  		}
   394  	}
   395  }
   396  
   397  func TestMergePreset(t *testing.T) {
   398  	tcs := []struct {
   399  		name      string
   400  		jobLabels map[string]string
   401  		pod       *coreapi.PodSpec
   402  		presets   []Preset
   403  
   404  		shouldError  bool
   405  		numEnv       int
   406  		numVol       int
   407  		numVolMounts int
   408  	}{
   409  		{
   410  			name:      "one volume",
   411  			jobLabels: map[string]string{"foo": "bar"},
   412  			pod:       &coreapi.PodSpec{},
   413  			presets: []Preset{
   414  				{
   415  					Labels:  map[string]string{"foo": "bar"},
   416  					Volumes: []coreapi.Volume{{Name: "baz"}},
   417  				},
   418  			},
   419  			numVol: 1,
   420  		},
   421  		{
   422  			name:      "wrong label",
   423  			jobLabels: map[string]string{"foo": "nope"},
   424  			pod:       &coreapi.PodSpec{},
   425  			presets: []Preset{
   426  				{
   427  					Labels:  map[string]string{"foo": "bar"},
   428  					Volumes: []coreapi.Volume{{Name: "baz"}},
   429  				},
   430  			},
   431  		},
   432  		{
   433  			name:      "conflicting volume name for podspec",
   434  			jobLabels: map[string]string{"foo": "bar"},
   435  			pod:       &coreapi.PodSpec{Volumes: []coreapi.Volume{{Name: "baz"}}},
   436  			presets: []Preset{
   437  				{
   438  					Labels:  map[string]string{"foo": "bar"},
   439  					Volumes: []coreapi.Volume{{Name: "baz"}},
   440  				},
   441  			},
   442  			shouldError: true,
   443  		},
   444  		{
   445  			name:      "non conflicting volume name",
   446  			jobLabels: map[string]string{"foo": "bar"},
   447  			pod:       &coreapi.PodSpec{Volumes: []coreapi.Volume{{Name: "baz"}}},
   448  			presets: []Preset{
   449  				{
   450  					Labels:  map[string]string{"foo": "bar"},
   451  					Volumes: []coreapi.Volume{{Name: "qux"}},
   452  				},
   453  			},
   454  			numVol: 2,
   455  		},
   456  		{
   457  			name:      "one env",
   458  			jobLabels: map[string]string{"foo": "bar"},
   459  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   460  			presets: []Preset{
   461  				{
   462  					Labels: map[string]string{"foo": "bar"},
   463  					Env:    []coreapi.EnvVar{{Name: "baz"}},
   464  				},
   465  			},
   466  			numEnv: 1,
   467  		},
   468  		{
   469  			name:      "conflicting env",
   470  			jobLabels: map[string]string{"foo": "bar"},
   471  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{Env: []coreapi.EnvVar{{Name: "baz"}}}}},
   472  			presets: []Preset{
   473  				{
   474  					Labels: map[string]string{"foo": "bar"},
   475  					Env:    []coreapi.EnvVar{{Name: "baz"}},
   476  				},
   477  			},
   478  			shouldError: true,
   479  		},
   480  		{
   481  			name:      "one vm",
   482  			jobLabels: map[string]string{"foo": "bar"},
   483  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   484  			presets: []Preset{
   485  				{
   486  					Labels:       map[string]string{"foo": "bar"},
   487  					VolumeMounts: []coreapi.VolumeMount{{Name: "baz"}},
   488  				},
   489  			},
   490  			numVolMounts: 1,
   491  		},
   492  		{
   493  			name:      "one of each",
   494  			jobLabels: map[string]string{"foo": "bar"},
   495  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   496  			presets: []Preset{
   497  				{
   498  					Labels:       map[string]string{"foo": "bar"},
   499  					Env:          []coreapi.EnvVar{{Name: "baz"}},
   500  					VolumeMounts: []coreapi.VolumeMount{{Name: "baz"}},
   501  					Volumes:      []coreapi.Volume{{Name: "qux"}},
   502  				},
   503  			},
   504  			numEnv:       1,
   505  			numVol:       1,
   506  			numVolMounts: 1,
   507  		},
   508  		{
   509  			name:      "two vm",
   510  			jobLabels: map[string]string{"foo": "bar"},
   511  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   512  			presets: []Preset{
   513  				{
   514  					Labels:       map[string]string{"foo": "bar"},
   515  					VolumeMounts: []coreapi.VolumeMount{{Name: "baz"}, {Name: "foo"}},
   516  				},
   517  			},
   518  			numVolMounts: 2,
   519  		},
   520  		{
   521  			name:      "default preset only",
   522  			jobLabels: map[string]string{"foo": "bar"},
   523  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   524  			presets: []Preset{
   525  				{
   526  					Env: []coreapi.EnvVar{{Name: "baz"}},
   527  				},
   528  			},
   529  			numEnv: 1,
   530  		},
   531  		{
   532  			name:      "default and matching presets",
   533  			jobLabels: map[string]string{"foo": "bar"},
   534  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   535  			presets: []Preset{
   536  				{
   537  					Env: []coreapi.EnvVar{{Name: "baz"}},
   538  				},
   539  				{
   540  					Labels:  map[string]string{"foo": "bar"},
   541  					Volumes: []coreapi.Volume{{Name: "qux"}},
   542  				},
   543  			},
   544  			numEnv: 1,
   545  			numVol: 1,
   546  		},
   547  		{
   548  			name:      "default and non-matching presets",
   549  			jobLabels: map[string]string{"foo": "bar"},
   550  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   551  			presets: []Preset{
   552  				{
   553  					Env: []coreapi.EnvVar{{Name: "baz"}},
   554  				},
   555  				{
   556  					Labels:  map[string]string{"no": "match"},
   557  					Volumes: []coreapi.Volume{{Name: "qux"}},
   558  				},
   559  			},
   560  			numEnv: 1,
   561  		},
   562  		{
   563  			name:      "multiple default presets",
   564  			jobLabels: map[string]string{"foo": "bar"},
   565  			pod:       &coreapi.PodSpec{Containers: []coreapi.Container{{}}},
   566  			presets: []Preset{
   567  				{
   568  					Env: []coreapi.EnvVar{{Name: "baz"}},
   569  				},
   570  				{
   571  					Env: []coreapi.EnvVar{{Name: "foo"}},
   572  				},
   573  				{
   574  					Volumes: []coreapi.Volume{{Name: "qux"}},
   575  				},
   576  			},
   577  			numEnv: 2,
   578  			numVol: 1,
   579  		},
   580  		{
   581  			name:      "default preset conflicts with job",
   582  			jobLabels: map[string]string{"foo": "bar"},
   583  			pod:       &coreapi.PodSpec{Volumes: []coreapi.Volume{{Name: "baz"}}},
   584  			presets: []Preset{
   585  				{
   586  					Volumes: []coreapi.Volume{{Name: "baz"}},
   587  				},
   588  			},
   589  			shouldError: true,
   590  		},
   591  	}
   592  	for _, tc := range tcs {
   593  		t.Run(tc.name, func(t *testing.T) {
   594  			if err := resolvePresets("foo", tc.jobLabels, tc.pod, tc.presets); err == nil && tc.shouldError {
   595  				t.Errorf("expected error but got none.")
   596  			} else if err != nil && !tc.shouldError {
   597  				t.Errorf("expected no error but got %v.", err)
   598  			}
   599  			if tc.shouldError {
   600  				return
   601  			}
   602  			if len(tc.pod.Volumes) != tc.numVol {
   603  				t.Errorf("wrong number of volumes for podspec. Got %d, expected %d.", len(tc.pod.Volumes), tc.numVol)
   604  			}
   605  			for _, c := range tc.pod.Containers {
   606  				if len(c.VolumeMounts) != tc.numVolMounts {
   607  					t.Errorf("wrong number of volume mounts for podspec. Got %d, expected %d.", len(c.VolumeMounts), tc.numVolMounts)
   608  				}
   609  				if len(c.Env) != tc.numEnv {
   610  					t.Errorf("wrong number of env vars for podspec. Got %d, expected %d.", len(c.Env), tc.numEnv)
   611  				}
   612  			}
   613  		})
   614  	}
   615  }
   616  
   617  func TestPresubmitShouldRun(t *testing.T) {
   618  	var testCases = []struct {
   619  		name        string
   620  		fileChanges []string
   621  		fileError   error
   622  		job         Presubmit
   623  		ref         string
   624  		forced      bool
   625  		defaults    bool
   626  
   627  		expectedRun bool
   628  		expectedErr bool
   629  	}{
   630  		{
   631  			name: "job skipped on the branch won't run",
   632  			job: Presubmit{
   633  				Brancher: Brancher{
   634  					SkipBranches: []string{"master"},
   635  				},
   636  			},
   637  			ref:         "master",
   638  			expectedRun: false,
   639  		},
   640  		{
   641  			name: "job enabled on the branch will run",
   642  			job: Presubmit{
   643  				Brancher: Brancher{
   644  					Branches: []string{"something"},
   645  				},
   646  				AlwaysRun: true,
   647  			},
   648  			ref:         "something",
   649  			expectedRun: true,
   650  		},
   651  		{
   652  			name: "job running only on other branches won't run",
   653  			job: Presubmit{
   654  				Brancher: Brancher{
   655  					Branches: []string{"master"},
   656  				},
   657  			},
   658  			ref:         "release-1.11",
   659  			expectedRun: false,
   660  		},
   661  		{
   662  			name: "job on a branch that's not skipped will run",
   663  			job: Presubmit{
   664  				Brancher: Brancher{
   665  					SkipBranches: []string{"master"},
   666  				},
   667  				AlwaysRun: true,
   668  			},
   669  			ref:         "other",
   670  			expectedRun: true,
   671  		},
   672  		{
   673  			name: "job with always_run: true should run",
   674  			job: Presubmit{
   675  				AlwaysRun: true,
   676  			},
   677  			ref:         "master",
   678  			expectedRun: true,
   679  		},
   680  		{
   681  			name: "job with always_run: false and no run_if_changed or skip_if_only_changed should not run",
   682  			job: Presubmit{
   683  				AlwaysRun:    false,
   684  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   685  				RerunCommand: "/test foo",
   686  				RegexpChangeMatcher: RegexpChangeMatcher{
   687  					RunIfChanged:      "",
   688  					SkipIfOnlyChanged: "",
   689  				},
   690  			},
   691  			ref:         "master",
   692  			expectedRun: false,
   693  		},
   694  		{
   695  			name: "job with run_if_changed but file get errors should not run",
   696  			job: Presubmit{
   697  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   698  				RerunCommand: "/test foo",
   699  				RegexpChangeMatcher: RegexpChangeMatcher{
   700  					RunIfChanged: "file",
   701  				},
   702  			},
   703  			ref:         "master",
   704  			fileError:   errors.New("oops"),
   705  			expectedRun: false,
   706  			expectedErr: true,
   707  		},
   708  		{
   709  			name: "job with skip_if_only_changed but file get errors should not run",
   710  			job: Presubmit{
   711  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   712  				RerunCommand: "/test foo",
   713  				RegexpChangeMatcher: RegexpChangeMatcher{
   714  					SkipIfOnlyChanged: "file",
   715  				},
   716  			},
   717  			ref:         "master",
   718  			fileChanges: []string{"something"},
   719  			fileError:   errors.New("oops"),
   720  			expectedRun: false,
   721  			expectedErr: true,
   722  		},
   723  		{
   724  			name: "job with run_if_changed not matching should not run",
   725  			job: Presubmit{
   726  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   727  				RerunCommand: "/test foo",
   728  				RegexpChangeMatcher: RegexpChangeMatcher{
   729  					RunIfChanged: "^file$",
   730  				},
   731  			},
   732  			ref:         "master",
   733  			fileChanges: []string{"something"},
   734  			expectedRun: false,
   735  		},
   736  		{
   737  			name: "job with skip_if_only_changed all matching should not run",
   738  			job: Presubmit{
   739  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   740  				RerunCommand: "/test foo",
   741  				RegexpChangeMatcher: RegexpChangeMatcher{
   742  					SkipIfOnlyChanged: "file$",
   743  				},
   744  			},
   745  			ref:         "master",
   746  			fileChanges: []string{"onefile", "two-file", "pkg/controller/three_file"},
   747  			expectedRun: false,
   748  		},
   749  		{
   750  			name: "job with run_if_changed not matching should run when default=true",
   751  			job: Presubmit{
   752  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   753  				RerunCommand: "/test foo",
   754  				RegexpChangeMatcher: RegexpChangeMatcher{
   755  					RunIfChanged: "^file$",
   756  				},
   757  			},
   758  			ref:         "master",
   759  			fileChanges: []string{"something"},
   760  			defaults:    true,
   761  			expectedRun: true,
   762  		},
   763  		{
   764  			name: "job with skip_if_only_changed all matching should run when default=true",
   765  			job: Presubmit{
   766  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   767  				RerunCommand: "/test foo",
   768  				RegexpChangeMatcher: RegexpChangeMatcher{
   769  					SkipIfOnlyChanged: "file$",
   770  				},
   771  			},
   772  			ref:         "master",
   773  			fileChanges: []string{"onefile", "two-file", "pkg/controller/three_file"},
   774  			defaults:    true,
   775  			expectedRun: true,
   776  		},
   777  		{
   778  			name: "job with run_if_changed matching should run",
   779  			job: Presubmit{
   780  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   781  				RerunCommand: "/test foo",
   782  				RegexpChangeMatcher: RegexpChangeMatcher{
   783  					RunIfChanged: "^file$",
   784  				},
   785  			},
   786  			ref:         "master",
   787  			fileChanges: []string{"file"},
   788  			expectedRun: true,
   789  		},
   790  		{
   791  			name: "job with skip_if_all_changed partially matching should run",
   792  			job: Presubmit{
   793  				Trigger:      `(?m)^/test (?:.*? )?foo(?: .*?)?$`,
   794  				RerunCommand: "/test foo",
   795  				RegexpChangeMatcher: RegexpChangeMatcher{
   796  					SkipIfOnlyChanged: "file$",
   797  				},
   798  			},
   799  			ref:         "master",
   800  			fileChanges: []string{"onefile", "two-file", "pkg/controller/three_file.go"},
   801  			expectedRun: true,
   802  		},
   803  	}
   804  
   805  	for _, testCase := range testCases {
   806  		t.Run(testCase.name, func(t *testing.T) {
   807  			jobs := []Presubmit{testCase.job}
   808  			if err := SetPresubmitRegexes(jobs); err != nil {
   809  				t.Fatalf("%s: failed to set presubmit regexes: %v", testCase.name, err)
   810  			}
   811  			jobShouldRun, err := jobs[0].ShouldRun(testCase.ref, func() ([]string, error) {
   812  				return testCase.fileChanges, testCase.fileError
   813  			}, testCase.forced, testCase.defaults)
   814  			if err == nil && testCase.expectedErr {
   815  				t.Errorf("%s: expected an error and got none", testCase.name)
   816  			}
   817  			if err != nil && !testCase.expectedErr {
   818  				t.Errorf("%s: expected no error but got one: %v", testCase.name, err)
   819  			}
   820  			if jobShouldRun != testCase.expectedRun {
   821  				t.Errorf("%s: did not determine if job should run correctly, expected %v but got %v", testCase.name, testCase.expectedRun, jobShouldRun)
   822  			}
   823  		})
   824  	}
   825  }
   826  
   827  func TestPostsubmitShouldRun(t *testing.T) {
   828  	true_ := true
   829  	false_ := false
   830  	var testCases = []struct {
   831  		name        string
   832  		fileChanges []string
   833  		fileError   error
   834  		job         Postsubmit
   835  		ref         string
   836  		expectedRun bool
   837  		expectedErr bool
   838  	}{
   839  		{
   840  			name: "job skipped on the branch won't run",
   841  			job: Postsubmit{
   842  				Brancher: Brancher{
   843  					SkipBranches: []string{"master"},
   844  				},
   845  			},
   846  			ref:         "master",
   847  			expectedRun: false,
   848  		},
   849  		{
   850  			name: "job enabled on the branch will run",
   851  			job: Postsubmit{
   852  				Brancher: Brancher{
   853  					Branches: []string{"something"},
   854  				},
   855  			},
   856  			ref:         "something",
   857  			expectedRun: true,
   858  		},
   859  		{
   860  			name: "job running only on other branches won't run",
   861  			job: Postsubmit{
   862  				Brancher: Brancher{
   863  					Branches: []string{"master"},
   864  				},
   865  			},
   866  			ref:         "release-1.11",
   867  			expectedRun: false,
   868  		},
   869  		{
   870  			name: "job on a branch that's not skipped will run",
   871  			job: Postsubmit{
   872  				Brancher: Brancher{
   873  					SkipBranches: []string{"master"},
   874  				},
   875  			},
   876  			ref:         "other",
   877  			expectedRun: true,
   878  		},
   879  		{
   880  			name:        "job with no run_if_changed should run",
   881  			job:         Postsubmit{},
   882  			ref:         "master",
   883  			expectedRun: true,
   884  		},
   885  		{
   886  			name: "job with run_if_changed but file get errors should not run",
   887  			job: Postsubmit{
   888  				RegexpChangeMatcher: RegexpChangeMatcher{
   889  					RunIfChanged: "file",
   890  				},
   891  			},
   892  			ref:         "master",
   893  			fileError:   errors.New("oops"),
   894  			expectedRun: false,
   895  			expectedErr: true,
   896  		},
   897  		{
   898  			name: "job with skip_if_only_changed but file get errors should not run",
   899  			job: Postsubmit{
   900  				RegexpChangeMatcher: RegexpChangeMatcher{
   901  					SkipIfOnlyChanged: "file",
   902  				},
   903  			},
   904  			ref:         "master",
   905  			fileChanges: []string{"something"},
   906  			fileError:   errors.New("oops"),
   907  			expectedRun: false,
   908  			expectedErr: true,
   909  		},
   910  		{
   911  			name: "job with run_if_changed not matching should not run",
   912  			job: Postsubmit{
   913  				RegexpChangeMatcher: RegexpChangeMatcher{
   914  					RunIfChanged: "^file$",
   915  				},
   916  			},
   917  			ref:         "master",
   918  			fileChanges: []string{"something"},
   919  			expectedRun: false,
   920  		},
   921  		{
   922  			name: "job with skip_if_only_changed all matching should not run",
   923  			job: Postsubmit{
   924  				RegexpChangeMatcher: RegexpChangeMatcher{
   925  					SkipIfOnlyChanged: "file$",
   926  				},
   927  			},
   928  			ref:         "master",
   929  			fileChanges: []string{"onefile", "two-file", "pkg/controller/three_file"},
   930  			expectedRun: false,
   931  		},
   932  		{
   933  			name: "job with run_if_changed matching should run",
   934  			job: Postsubmit{
   935  				RegexpChangeMatcher: RegexpChangeMatcher{
   936  					RunIfChanged: "^file$",
   937  				},
   938  			},
   939  			ref:         "master",
   940  			fileChanges: []string{"file"},
   941  			expectedRun: true,
   942  		},
   943  		{
   944  			name: "job with skip_if_only_changed partially matching should run",
   945  			job: Postsubmit{
   946  				RegexpChangeMatcher: RegexpChangeMatcher{
   947  					SkipIfOnlyChanged: "file$",
   948  				},
   949  			},
   950  			ref:         "master",
   951  			fileChanges: []string{"onefile", "two-file", "pkg/controller/three_file.go"},
   952  			expectedRun: true,
   953  		},
   954  		{
   955  			name: "job with run_if_changed matching (and `always_run` explicitly set to false) should run",
   956  			job: Postsubmit{
   957  				AlwaysRun: &false_,
   958  				RegexpChangeMatcher: RegexpChangeMatcher{
   959  					RunIfChanged: "^file$",
   960  				},
   961  			},
   962  			ref:         "master",
   963  			fileChanges: []string{"file"},
   964  			expectedRun: true,
   965  		},
   966  		{
   967  			name: "job with skip_if_only_changed partially matching (and `always_run` explicitly set to false) should run",
   968  			job: Postsubmit{
   969  				AlwaysRun: &false_,
   970  				RegexpChangeMatcher: RegexpChangeMatcher{
   971  					SkipIfOnlyChanged: "file$",
   972  				},
   973  			},
   974  			ref:         "master",
   975  			fileChanges: []string{"onefile", "two-file", "pkg/controller/three_file.go"},
   976  			expectedRun: true,
   977  		},
   978  		{
   979  			name: "job with `always_run` explicitly set to true will run",
   980  			job: Postsubmit{
   981  				AlwaysRun: &true_,
   982  			},
   983  			ref:         "master",
   984  			expectedRun: true,
   985  		},
   986  		{
   987  			name: "job with `always_run` explicitly set to false will not run",
   988  			job: Postsubmit{
   989  				AlwaysRun: &false_,
   990  			},
   991  			ref:         "master",
   992  			expectedRun: false,
   993  		},
   994  		{
   995  			name: "job skipped on the branch will not run, even if `always_run` set to true explicitly",
   996  			job: Postsubmit{
   997  				AlwaysRun: &true_,
   998  				Brancher: Brancher{
   999  					SkipBranches: []string{"master"},
  1000  				},
  1001  			},
  1002  			ref:         "master",
  1003  			expectedRun: false,
  1004  		},
  1005  		{
  1006  			name: "job enabled on the branch (with `always_run` explicitly set to false explicitly) will not run",
  1007  			job: Postsubmit{
  1008  				AlwaysRun: &false_,
  1009  				Brancher: Brancher{
  1010  					Branches: []string{"something"},
  1011  				},
  1012  			},
  1013  			ref:         "something",
  1014  			expectedRun: false,
  1015  		},
  1016  	}
  1017  
  1018  	for _, testCase := range testCases {
  1019  		t.Run(testCase.name, func(t *testing.T) {
  1020  			jobs := []Postsubmit{testCase.job}
  1021  			if err := SetPostsubmitRegexes(jobs); err != nil {
  1022  				t.Fatalf("%s: failed to set presubmit regexes: %v", testCase.name, err)
  1023  			}
  1024  			jobShouldRun, err := jobs[0].ShouldRun(testCase.ref, func() ([]string, error) {
  1025  				return testCase.fileChanges, testCase.fileError
  1026  			})
  1027  			if err == nil && testCase.expectedErr {
  1028  				t.Errorf("%s: expected an error and got none", testCase.name)
  1029  			}
  1030  			if err != nil && !testCase.expectedErr {
  1031  				t.Errorf("%s: expected no error but got one: %v", testCase.name, err)
  1032  			}
  1033  			if jobShouldRun != testCase.expectedRun {
  1034  				t.Errorf("%s: did not determine if job should run correctly, expected %v but got %v", testCase.name, testCase.expectedRun, jobShouldRun)
  1035  			}
  1036  		})
  1037  	}
  1038  }
  1039  
  1040  func TestUtilityConfigValidation(t *testing.T) {
  1041  	testCases := []struct {
  1042  		id    string
  1043  		valid bool
  1044  		uc    UtilityConfig
  1045  	}{
  1046  		{
  1047  			id:    "empty UtilityConfig, no error",
  1048  			valid: true,
  1049  			uc:    UtilityConfig{},
  1050  		},
  1051  		{
  1052  			id: "clone_uri is a not valid, error",
  1053  			uc: UtilityConfig{CloneURI: "://notvalidURI"},
  1054  		},
  1055  		{
  1056  			id: "one of the clone_uri is not valid, error",
  1057  			uc: UtilityConfig{
  1058  				CloneURI: "://notvalidURI",
  1059  				ExtraRefs: []prowapi.Refs{
  1060  					{
  1061  						Org:      "org1",
  1062  						Repo:     "repo1",
  1063  						BaseSHA:  "master",
  1064  						CloneURI: "https://github.com/kubernetes/test-infra.git",
  1065  					},
  1066  					{
  1067  						Org:      "org2",
  1068  						Repo:     "repo2",
  1069  						BaseSHA:  "master",
  1070  						CloneURI: "://notvalidURI",
  1071  					},
  1072  				},
  1073  			},
  1074  		},
  1075  		{
  1076  			id:    "ssh_keys specified but clone_uri is empty, no error",
  1077  			valid: true,
  1078  			uc: UtilityConfig{
  1079  				DecorationConfig: &prowapi.DecorationConfig{
  1080  					SSHKeySecrets: []string{"ssh-secret"},
  1081  				},
  1082  			},
  1083  		},
  1084  		{
  1085  			id: "ssh_keys specified but clone_uri is invalid, error",
  1086  			uc: UtilityConfig{
  1087  				CloneURI: "://notvalidURI",
  1088  				DecorationConfig: &prowapi.DecorationConfig{
  1089  					SSHKeySecrets: []string{"ssh-secret"},
  1090  				},
  1091  			},
  1092  		},
  1093  		{
  1094  			id:    "ssh_keys specified and clone_uri is valid, no error",
  1095  			valid: true,
  1096  			uc: UtilityConfig{
  1097  				CloneURI: "git@github.com:kubernetes/test-infra.git",
  1098  				DecorationConfig: &prowapi.DecorationConfig{
  1099  					SSHKeySecrets: []string{"ssh-secret"},
  1100  				},
  1101  			},
  1102  		},
  1103  		{
  1104  			id:    "ssh_keys specified and all of clone_uri are valid, no error",
  1105  			valid: true,
  1106  			uc: UtilityConfig{
  1107  				CloneURI: "git@github.com:kubernetes/test-infra.git",
  1108  				ExtraRefs: []prowapi.Refs{
  1109  					{
  1110  						Org:      "org1",
  1111  						Repo:     "repo1",
  1112  						BaseSHA:  "master",
  1113  						CloneURI: "github.com:org1/repo1.git",
  1114  					},
  1115  					{
  1116  						Org:      "org2",
  1117  						Repo:     "repo2",
  1118  						BaseSHA:  "master",
  1119  						CloneURI: "git@github.com:org2/repo2.git",
  1120  					},
  1121  				},
  1122  				DecorationConfig: &prowapi.DecorationConfig{
  1123  					SSHKeySecrets: []string{"ssh-secret"},
  1124  				},
  1125  			},
  1126  		},
  1127  		{
  1128  			id: "ssh_keys specified and one of the clone_uri is invalid, error",
  1129  			uc: UtilityConfig{
  1130  				CloneURI: "git@github.com:kubernetes/test-infra.git",
  1131  				ExtraRefs: []prowapi.Refs{
  1132  					{
  1133  						Org:      "org1",
  1134  						Repo:     "repo1",
  1135  						BaseSHA:  "master",
  1136  						CloneURI: "git@github.com:org1/repo1.git",
  1137  					},
  1138  					{
  1139  						Org:      "org2",
  1140  						Repo:     "repo2",
  1141  						BaseSHA:  "master",
  1142  						CloneURI: "://notvalidURI",
  1143  					},
  1144  				},
  1145  				DecorationConfig: &prowapi.DecorationConfig{
  1146  					SSHKeySecrets: []string{"ssh-secret"},
  1147  				},
  1148  			},
  1149  		},
  1150  		{
  1151  			id: "clone_uri contains a user and decoration config is nil, no error",
  1152  			uc: UtilityConfig{
  1153  				CloneURI: "git@github.com:kubernetes/test-infra.git",
  1154  			},
  1155  			valid: true,
  1156  		},
  1157  		{
  1158  			id: "oauth token secret provided and all clone_uri have valid http(s) a scheme, no error",
  1159  			uc: UtilityConfig{
  1160  				DecorationConfig: &prowapi.DecorationConfig{
  1161  					OauthTokenSecret: &prowapi.OauthTokenSecret{
  1162  						Name: "secret",
  1163  						Key:  "token",
  1164  					},
  1165  				},
  1166  				CloneURI: "http://github.com/kubernetes/test-infra.git",
  1167  				ExtraRefs: []prowapi.Refs{
  1168  					{
  1169  						Org:      "org1",
  1170  						Repo:     "repo1",
  1171  						BaseSHA:  "master",
  1172  						CloneURI: "https://github.com/org1/repo1.git",
  1173  					},
  1174  					{
  1175  						Org:      "org2",
  1176  						Repo:     "repo2",
  1177  						BaseSHA:  "master",
  1178  						CloneURI: "http://github.com/org1/repo1.git",
  1179  					},
  1180  				},
  1181  			},
  1182  			valid: true,
  1183  		},
  1184  		{
  1185  			id: "oauth token secret provided but clone_uri doesn't contain a scheme, error",
  1186  			uc: UtilityConfig{
  1187  				DecorationConfig: &prowapi.DecorationConfig{
  1188  					OauthTokenSecret: &prowapi.OauthTokenSecret{
  1189  						Name: "secret",
  1190  						Key:  "token",
  1191  					},
  1192  				},
  1193  				CloneURI: "github.com/kubernetes/test-infra.git",
  1194  			},
  1195  		},
  1196  		{
  1197  			id: "oauth token secret provided but one of the clone_uri doesn't contain a scheme, error",
  1198  			uc: UtilityConfig{
  1199  				DecorationConfig: &prowapi.DecorationConfig{
  1200  					OauthTokenSecret: &prowapi.OauthTokenSecret{
  1201  						Name: "secret",
  1202  						Key:  "token",
  1203  					},
  1204  				},
  1205  				CloneURI: "https://github.com/kubernetes/test-infra.git",
  1206  				ExtraRefs: []prowapi.Refs{
  1207  					{
  1208  						Org:      "org1",
  1209  						Repo:     "repo1",
  1210  						BaseSHA:  "master",
  1211  						CloneURI: "github.com/org1/repo1.git",
  1212  					},
  1213  					{
  1214  						Org:      "org2",
  1215  						Repo:     "repo2",
  1216  						BaseSHA:  "master",
  1217  						CloneURI: "http://github.com/org1/repo1.git",
  1218  					},
  1219  				},
  1220  			},
  1221  		},
  1222  		{
  1223  			id: "oauth token secret provided but clone_uri doesn't contain a http(s) scheme, error",
  1224  			uc: UtilityConfig{
  1225  				DecorationConfig: &prowapi.DecorationConfig{
  1226  					OauthTokenSecret: &prowapi.OauthTokenSecret{
  1227  						Name: "secret",
  1228  						Key:  "token",
  1229  					},
  1230  				},
  1231  				CloneURI: "ssh://github.com/kubernetes/test-infra.git",
  1232  			},
  1233  		},
  1234  		{
  1235  			id: "oauth token secret provided but one of the clone_uri doesn't contain a http(s) scheme, error",
  1236  			uc: UtilityConfig{
  1237  				DecorationConfig: &prowapi.DecorationConfig{
  1238  					OauthTokenSecret: &prowapi.OauthTokenSecret{
  1239  						Name: "secret",
  1240  						Key:  "token",
  1241  					},
  1242  				},
  1243  				CloneURI: "https://github.com/kubernetes/test-infra.git",
  1244  				ExtraRefs: []prowapi.Refs{
  1245  					{
  1246  						Org:      "org1",
  1247  						Repo:     "repo1",
  1248  						BaseSHA:  "master",
  1249  						CloneURI: "ssh://git@github.com:org1/repo1.git",
  1250  					},
  1251  					{
  1252  						Org:      "org2",
  1253  						Repo:     "repo2",
  1254  						BaseSHA:  "master",
  1255  						CloneURI: "http://github.com/org1/repo1.git",
  1256  					},
  1257  				},
  1258  			},
  1259  		},
  1260  	}
  1261  
  1262  	for _, tc := range testCases {
  1263  		t.Run(tc.id, func(t *testing.T) {
  1264  			if err := tc.uc.Validate(); err != nil && tc.valid {
  1265  				t.Fatalf("No validation error expected: %v", err)
  1266  			}
  1267  			if err := tc.uc.Validate(); err == nil && !tc.valid {
  1268  				t.Fatalf("Validation error expected: %v", err)
  1269  			}
  1270  		})
  1271  	}
  1272  }
  1273  
  1274  func TestJobBase_HasPipelineRunSpec(t *testing.T) {
  1275  	type fields struct {
  1276  		PipelineRunSpec       *pipelinev1beta1.PipelineRunSpec
  1277  		TektonPipelineRunSpec *prowapi.TektonPipelineRunSpec
  1278  	}
  1279  	tests := []struct {
  1280  		name   string
  1281  		fields fields
  1282  		want   bool
  1283  	}{{
  1284  		name: "none set",
  1285  		want: false,
  1286  	}, {
  1287  		name: "PipelineRunSpec set",
  1288  		fields: fields{
  1289  			PipelineRunSpec: &pipelinev1beta1.PipelineRunSpec{},
  1290  		},
  1291  		want: true,
  1292  	}, {
  1293  		name: "TektonPipelineRunSpec set",
  1294  		fields: fields{
  1295  			TektonPipelineRunSpec: &prowapi.TektonPipelineRunSpec{},
  1296  		},
  1297  		want: false,
  1298  	}, {
  1299  		name: "TektonPipelineRunSpec.V1VBeta1 set",
  1300  		fields: fields{
  1301  			TektonPipelineRunSpec: &prowapi.TektonPipelineRunSpec{
  1302  				V1Beta1: &pipelinev1beta1.PipelineRunSpec{},
  1303  			},
  1304  		},
  1305  		want: true,
  1306  	}, {
  1307  		name: "both set",
  1308  		fields: fields{
  1309  			PipelineRunSpec: &pipelinev1beta1.PipelineRunSpec{},
  1310  			TektonPipelineRunSpec: &prowapi.TektonPipelineRunSpec{
  1311  				V1Beta1: &pipelinev1beta1.PipelineRunSpec{},
  1312  			},
  1313  		},
  1314  		want: true,
  1315  	}}
  1316  	for _, tt := range tests {
  1317  		t.Run(tt.name, func(t *testing.T) {
  1318  			jb := JobBase{
  1319  				PipelineRunSpec:       tt.fields.PipelineRunSpec,
  1320  				TektonPipelineRunSpec: tt.fields.TektonPipelineRunSpec,
  1321  			}
  1322  			if got := jb.HasPipelineRunSpec(); got != tt.want {
  1323  				t.Errorf("JobBase.HasPipelineRunSpec() = %v, want %v", got, tt.want)
  1324  			}
  1325  		})
  1326  	}
  1327  }
  1328  
  1329  func TestJobBase_GetPipelineRunSpec(t *testing.T) {
  1330  	type fields struct {
  1331  		PipelineRunSpec       *pipelinev1beta1.PipelineRunSpec
  1332  		TektonPipelineRunSpec *prowapi.TektonPipelineRunSpec
  1333  	}
  1334  	tests := []struct {
  1335  		name    string
  1336  		fields  fields
  1337  		want    *pipelinev1beta1.PipelineRunSpec
  1338  		wantErr bool
  1339  	}{
  1340  		{
  1341  			name: "none set",
  1342  			fields: fields{
  1343  				PipelineRunSpec:       nil,
  1344  				TektonPipelineRunSpec: nil,
  1345  			},
  1346  			wantErr: true,
  1347  		},
  1348  		{
  1349  			name: "only PipelineRunSpec set",
  1350  			fields: fields{
  1351  				PipelineRunSpec: &pipelinev1beta1.PipelineRunSpec{
  1352  					ServiceAccountName: "robot",
  1353  					PipelineSpec: &pipelinev1beta1.PipelineSpec{
  1354  						Tasks: []pipelinev1beta1.PipelineTask{{Name: "implicit git resource", TaskRef: &pipelinev1beta1.TaskRef{Name: "abc"}}},
  1355  					},
  1356  				},
  1357  				TektonPipelineRunSpec: nil,
  1358  			},
  1359  			want: &pipelinev1beta1.PipelineRunSpec{
  1360  				ServiceAccountName: "robot",
  1361  				PipelineSpec: &pipelinev1beta1.PipelineSpec{
  1362  					Tasks: []pipelinev1beta1.PipelineTask{{Name: "implicit git resource", TaskRef: &pipelinev1beta1.TaskRef{Name: "abc"}}},
  1363  				},
  1364  			},
  1365  		},
  1366  		{
  1367  			name: "only TektonPipelineRunSpec set",
  1368  			fields: fields{
  1369  				PipelineRunSpec: nil,
  1370  				TektonPipelineRunSpec: &prowapi.TektonPipelineRunSpec{
  1371  					V1Beta1: &pipelinev1beta1.PipelineRunSpec{
  1372  						ServiceAccountName: "robot",
  1373  						PipelineSpec: &pipelinev1beta1.PipelineSpec{
  1374  							Tasks: []pipelinev1beta1.PipelineTask{{Name: "implicit git resource", TaskRef: &pipelinev1beta1.TaskRef{Name: "abc"}}},
  1375  						},
  1376  					},
  1377  				},
  1378  			},
  1379  			want: &pipelinev1beta1.PipelineRunSpec{
  1380  				ServiceAccountName: "robot",
  1381  				PipelineSpec: &pipelinev1beta1.PipelineSpec{
  1382  					Tasks: []pipelinev1beta1.PipelineTask{{Name: "implicit git resource", TaskRef: &pipelinev1beta1.TaskRef{Name: "abc"}}},
  1383  				},
  1384  			},
  1385  		},
  1386  		{
  1387  			name: "PipelineRunSpec and TektonPipelineRunSpec set",
  1388  			fields: fields{
  1389  				PipelineRunSpec: &pipelinev1beta1.PipelineRunSpec{
  1390  					ServiceAccountName: "robot",
  1391  					PipelineSpec: &pipelinev1beta1.PipelineSpec{
  1392  						Tasks: []pipelinev1beta1.PipelineTask{{Name: "implicit git resource", TaskRef: &pipelinev1beta1.TaskRef{Name: "abc"}}},
  1393  					},
  1394  				},
  1395  				TektonPipelineRunSpec: &prowapi.TektonPipelineRunSpec{
  1396  					V1Beta1: &pipelinev1beta1.PipelineRunSpec{
  1397  						ServiceAccountName: "robot",
  1398  						PipelineSpec: &pipelinev1beta1.PipelineSpec{
  1399  							Tasks: []pipelinev1beta1.PipelineTask{{Name: "implicit git resource", TaskRef: &pipelinev1beta1.TaskRef{Name: "def"}}},
  1400  						},
  1401  					},
  1402  				},
  1403  			},
  1404  			want: &pipelinev1beta1.PipelineRunSpec{
  1405  				ServiceAccountName: "robot",
  1406  				PipelineSpec: &pipelinev1beta1.PipelineSpec{
  1407  					Tasks: []pipelinev1beta1.PipelineTask{{Name: "implicit git resource", TaskRef: &pipelinev1beta1.TaskRef{Name: "def"}}},
  1408  				},
  1409  			},
  1410  		}}
  1411  	for _, tt := range tests {
  1412  		t.Run(tt.name, func(t *testing.T) {
  1413  			jb := JobBase{
  1414  				PipelineRunSpec:       tt.fields.PipelineRunSpec,
  1415  				TektonPipelineRunSpec: tt.fields.TektonPipelineRunSpec,
  1416  			}
  1417  			got, err := jb.GetPipelineRunSpec()
  1418  			if (err != nil) != tt.wantErr {
  1419  				t.Errorf("JobBase.GetPipelineRunSpec() error = %v, wantErr %v", err, tt.wantErr)
  1420  				return
  1421  			}
  1422  			if !reflect.DeepEqual(got, tt.want) {
  1423  				t.Errorf("JobBase.GetPipelineRunSpec() = %v, want %v", got, tt.want)
  1424  			}
  1425  		})
  1426  	}
  1427  }