sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/jenkins/jenkins_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 jenkins
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"net/http"
    23  	"net/http/httptest"
    24  	"reflect"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/sirupsen/logrus"
    29  
    30  	prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1"
    31  )
    32  
    33  // getRequestedJob is attempting to determine if this is a job-specific
    34  // request in a pretty hacky way.
    35  func getRequestedJob(path string) string {
    36  	parts := strings.Split(path, "/")
    37  	jobIndex := -1
    38  	for i, part := range parts {
    39  		if part == "job" {
    40  			// This is a job-specific request. Record the index.
    41  			jobIndex = i + 1
    42  			break
    43  		}
    44  	}
    45  	// If this is not a job-specific request, fail for now. Eventually we
    46  	// are going to proxy queue requests.
    47  	if jobIndex == -1 {
    48  		return ""
    49  	}
    50  	// Sanity check
    51  	if jobIndex+1 > len(parts) {
    52  		return ""
    53  	}
    54  	return parts[jobIndex]
    55  }
    56  
    57  func testWrapper(t *testing.T, jobs []string, builds map[string][]Build, status *int) http.HandlerFunc {
    58  	var paths []string
    59  	for _, job := range jobs {
    60  		paths = append(paths, fmt.Sprintf("/job/%s/api/json", job))
    61  	}
    62  
    63  	return func(w http.ResponseWriter, r *http.Request) {
    64  		t.Logf("test request to %q", r.URL.Path)
    65  
    66  		if r.Method != http.MethodGet {
    67  			t.Errorf("Bad method: %s", r.Method)
    68  			return
    69  		}
    70  		if r.URL.Path == "/queue/api/json" {
    71  			fmt.Fprint(w, `{"items": [
    72  				{
    73  					"actions": [
    74  						{
    75  							"parameters": [
    76  								{
    77  									"name": "BUILD_ID",
    78  									"value": "queued-int"
    79  								},
    80  								{
    81  									"name": "PROW_JOB_ID",
    82  									"value": "queued_pj_id"
    83  								}
    84  							]
    85  						}
    86  					],
    87  					"task": {
    88  						"name": "PR-763"
    89  					}
    90  				}
    91  			]}`)
    92  			return
    93  		}
    94  		var found bool
    95  		for _, path := range paths {
    96  			if r.URL.Path == path {
    97  				found = true
    98  			}
    99  		}
   100  		if !found {
   101  			w.WriteHeader(404)
   102  			return
   103  		}
   104  		if status != nil {
   105  			w.WriteHeader(*status)
   106  			return
   107  		}
   108  		requestedJob := getRequestedJob(r.URL.Path)
   109  		data, err := json.Marshal(builds[requestedJob])
   110  		if err != nil {
   111  			t.Errorf("unexpected error while marshaling builds: %v", err)
   112  			return
   113  		}
   114  		fmt.Fprintf(w, `{"builds": %s}`, string(data))
   115  	}
   116  }
   117  
   118  func strP(str string) *string {
   119  	return &str
   120  }
   121  
   122  func intP(i int) *int {
   123  	return &i
   124  }
   125  
   126  func TestListBuilds(t *testing.T) {
   127  	tests := []struct {
   128  		name string
   129  
   130  		existingJobs  []string
   131  		requestedJobs []BuildQueryParams
   132  		builds        map[string][]Build
   133  		status        *int
   134  
   135  		expectedResults map[string]Build
   136  		expectedErr     error
   137  	}{
   138  		{
   139  			name: "missing job does not block",
   140  
   141  			existingJobs:  []string{"unit", "integration"},
   142  			requestedJobs: []BuildQueryParams{{JobName: "unit", ProwJobID: "unitpj"}, {JobName: "unit", ProwJobID: "queued_pj_id"}, {JobName: "integration", ProwJobID: "integrationpj"}, {JobName: "e2e", ProwJobID: "e2epj"}},
   143  			builds: map[string][]Build{
   144  				"unit": {
   145  					{Number: 1, Result: strP(success), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "first"}, {Name: prowJobID, Value: "first"}}}}},
   146  					{Number: 2, Result: strP(failure), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "second"}, {Name: prowJobID, Value: "second"}}}}},
   147  					{Number: 3, Result: strP(failure), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "third"}, {Name: prowJobID, Value: "third"}}}}},
   148  					{Number: 4, Result: strP(unstable), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "fourth"}, {Name: prowJobID, Value: "fourth"}}}}},
   149  				},
   150  				"integration": {
   151  					{Number: 1, Result: strP(failure), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "first-int"}, {Name: prowJobID, Value: "first-int"}}}}},
   152  					{Number: 2, Result: strP(success), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "second-int"}, {Name: prowJobID, Value: "second-int"}}}}},
   153  				},
   154  			},
   155  
   156  			expectedResults: map[string]Build{
   157  				"first":      {Number: 1, Result: strP(success), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "first"}, {Name: prowJobID, Value: "first"}}}}},
   158  				"second":     {Number: 2, Result: strP(failure), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "second"}, {Name: prowJobID, Value: "second"}}}}},
   159  				"third":      {Number: 3, Result: strP(failure), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "third"}, {Name: prowJobID, Value: "third"}}}}},
   160  				"fourth":     {Number: 4, Result: strP(unstable), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "fourth"}, {Name: prowJobID, Value: "fourth"}}}}},
   161  				"first-int":  {Number: 1, Result: strP(failure), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "first-int"}, {Name: prowJobID, Value: "first-int"}}}}},
   162  				"second-int": {Number: 2, Result: strP(success), Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "second-int"}, {Name: prowJobID, Value: "second-int"}}}}},
   163  				// queued_pj_id is returned from the testWrapper
   164  				"queued_pj_id": {Number: 0, Result: nil, Actions: []Action{{Parameters: []Parameter{{Name: statusBuildID, Value: "queued-int"}, {Name: prowJobID, Value: "queued_pj_id"}}}}, enqueued: true, Task: struct {
   165  					Name string `json:"name"`
   166  				}{Name: "PR-763"}},
   167  			},
   168  		},
   169  		{
   170  			name: "bad error",
   171  
   172  			existingJobs:  []string{"unit"},
   173  			requestedJobs: []BuildQueryParams{{JobName: "unit", ProwJobID: "prowjobidhere"}},
   174  			status:        intP(502),
   175  
   176  			expectedErr: fmt.Errorf("cannot list builds for job \"unit\": %w", fmt.Errorf("response not 2XX: %s", "502 Bad Gateway")),
   177  		},
   178  	}
   179  
   180  	for _, test := range tests {
   181  		t.Logf("scenario %q", test.name)
   182  
   183  		ts := httptest.NewServer(testWrapper(t, test.existingJobs, test.builds, test.status))
   184  		defer ts.Close()
   185  
   186  		jc := Client{
   187  			logger:  logrus.WithField("client", "jenkins"),
   188  			client:  ts.Client(),
   189  			baseURL: ts.URL,
   190  		}
   191  
   192  		builds, err := jc.ListBuilds(test.requestedJobs)
   193  		if !reflect.DeepEqual(err, test.expectedErr) {
   194  			t.Errorf("unexpected error: %v, expected: %v", err, test.expectedErr)
   195  		}
   196  		for expectedJob, expectedBuild := range test.expectedResults {
   197  			gotBuild, exists := builds[expectedJob]
   198  			if !exists {
   199  				t.Errorf("expected job %q, got %v", expectedJob, builds)
   200  				continue
   201  			}
   202  			if !reflect.DeepEqual(expectedBuild, gotBuild) {
   203  				t.Errorf("expected build:\n%+v\ngot:\n%+v", expectedBuild, gotBuild)
   204  			}
   205  		}
   206  	}
   207  }
   208  
   209  func TestBuildCreate(t *testing.T) {
   210  	testCases := []struct {
   211  		name        string
   212  		input       *prowapi.ProwJobSpec
   213  		expectError bool
   214  		statusCode  int
   215  		output      []string
   216  	}{
   217  		{
   218  			name: "GitHub Branch Source based PR job",
   219  			input: &prowapi.ProwJobSpec{
   220  				Agent: "jenkins",
   221  				Job:   "my-jenkins-job-name",
   222  				JenkinsSpec: &prowapi.JenkinsSpec{
   223  					GitHubBranchSourceJob: true,
   224  				},
   225  				Refs: &prowapi.Refs{
   226  					BaseRef: "master",
   227  					BaseSHA: "deadbeef",
   228  					Pulls: []prowapi.Pull{
   229  						{
   230  							Number: 123,
   231  							SHA:    "abcd1234",
   232  						},
   233  					},
   234  				},
   235  			},
   236  			statusCode: 201,
   237  			output: []string{
   238  				"/job/my-jenkins-job-name/view/change-requests/job/PR-123/api/json",
   239  				"/job/my-jenkins-job-name/view/change-requests/job/PR-123/build",
   240  				"/job/my-jenkins-job-name/view/change-requests/job/PR-123/api/json",
   241  				"/job/my-jenkins-job-name/view/change-requests/job/PR-123/5/stop",
   242  				"/job/my-jenkins-job-name/view/change-requests/job/PR-123/buildWithParameters",
   243  			},
   244  		},
   245  		{
   246  			name: "GitHub Branch Source based branch job",
   247  			input: &prowapi.ProwJobSpec{
   248  				Agent: "jenkins",
   249  				Type:  prowapi.PostsubmitJob,
   250  				Job:   "my-jenkins-job-name",
   251  				JenkinsSpec: &prowapi.JenkinsSpec{
   252  					GitHubBranchSourceJob: true,
   253  				},
   254  				Refs: &prowapi.Refs{
   255  					BaseRef: "master",
   256  					BaseSHA: "deadbeef",
   257  				},
   258  			},
   259  			statusCode: 201,
   260  			output: []string{
   261  				"/job/my-jenkins-job-name/job/master/api/json",
   262  				"/job/my-jenkins-job-name/job/master/build",
   263  				"/job/my-jenkins-job-name/job/master/api/json",
   264  				"/job/my-jenkins-job-name/job/master/5/stop",
   265  				"/job/my-jenkins-job-name/job/master/buildWithParameters",
   266  			},
   267  		},
   268  		{
   269  			name: "Static Jenkins job",
   270  			input: &prowapi.ProwJobSpec{
   271  				Agent: "jenkins",
   272  				Job:   "my-k8s-job-name",
   273  				Refs: &prowapi.Refs{
   274  					BaseRef: "master",
   275  					BaseSHA: "deadbeef",
   276  					Pulls: []prowapi.Pull{
   277  						{
   278  							Number: 123,
   279  							SHA:    "abcd1234",
   280  						},
   281  					},
   282  				},
   283  			},
   284  			statusCode: 201,
   285  			output: []string{
   286  				"/job/my-k8s-job-name/api/json",
   287  				"/job/my-k8s-job-name/build",
   288  				"/job/my-k8s-job-name/api/json",
   289  				"/job/my-k8s-job-name/5/stop",
   290  				"/job/my-k8s-job-name/buildWithParameters",
   291  			},
   292  		},
   293  		{
   294  			name: "Non-404 error getting Jenkins job",
   295  			input: &prowapi.ProwJobSpec{
   296  				Agent: "jenkins",
   297  				Job:   "my-k8s-job-name",
   298  				Refs: &prowapi.Refs{
   299  					BaseRef: "master",
   300  					BaseSHA: "deadbeef",
   301  					Pulls: []prowapi.Pull{
   302  						{
   303  							Number: 123,
   304  							SHA:    "abcd1234",
   305  						},
   306  					},
   307  				},
   308  			},
   309  			statusCode:  500,
   310  			expectError: true,
   311  			// 5 times because Client.Get does retries on 5xx status code
   312  			output: []string{
   313  				"/job/my-k8s-job-name/api/json",
   314  				"/job/my-k8s-job-name/api/json",
   315  				"/job/my-k8s-job-name/api/json",
   316  				"/job/my-k8s-job-name/api/json",
   317  				"/job/my-k8s-job-name/api/json",
   318  			},
   319  		},
   320  	}
   321  
   322  	for _, testCase := range testCases {
   323  		t.Run(testCase.name, func(t *testing.T) {
   324  			actualPaths := []string{}
   325  
   326  			var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
   327  				actualPaths = append(actualPaths, r.URL.Path)
   328  				var response string
   329  
   330  				if len(actualPaths) < 3 {
   331  					response = `{"builds":[],"lastBuild":null,"property":[]}`
   332  				} else {
   333  					response = `{"builds":[{"_class":"org.jenkinsci.plugins.workflow.job.WorkflowRun","number":5,"url":"https://myjenkins.com/job/very-good-job/view/change-requests/job/PR-23/5/"},{"_class":"org.jenkinsci.plugins.workflow.job.WorkflowRun","number":4,"url":"https://myjenkins.com/job/very-good-job/view/change-requests/job/PR-23/4/"},{"_class":"org.jenkinsci.plugins.workflow.job.WorkflowRun","number":3,"url":"https://myjenkins.com/job/very-good-job/view/change-requests/job/PR-23/3/"},{"_class":"org.jenkinsci.plugins.workflow.job.WorkflowRun","number":2,"url":"https://myjenkins.com/job/very-good-job/view/change-requests/job/PR-23/2/"},{"_class":"org.jenkinsci.plugins.workflow.job.WorkflowRun","number":1,"url":"https://myjenkins.com/job/very-good-job/view/change-requests/job/PR-23/1/"}],"lastBuild":{"_class":"org.jenkinsci.plugins.workflow.job.WorkflowRun","number":5,"url":"https://myjenkins.com/job/very-good-job/view/change-requests/job/PR-23/5/"},"property":[{"_class":"hudson.model.ParametersDefinitionProperty","parameterDefinitions":[{"_class":"hudson.model.StringParameterDefinition","defaultParameterValue":{"_class":"hudson.model.StringParameterValue","name":"PROW_JOB_ID","value":""},"description":"Prow Job ID – set when the job is triggered by Prow","name":"PROW_JOB_ID","type":"StringParameterDefinition"}]},{"_class":"org.jenkinsci.plugins.workflow.multibranch.BranchJobProperty","branch":{}}]}`
   334  				}
   335  
   336  				w.WriteHeader(testCase.statusCode)
   337  				w.Write([]byte(response))
   338  			}
   339  
   340  			ts := httptest.NewServer(handler)
   341  			defer ts.Close()
   342  
   343  			jc := Client{
   344  				logger:  logrus.WithField("client", "jenkins"),
   345  				client:  ts.Client(),
   346  				baseURL: ts.URL,
   347  			}
   348  
   349  			buildErr := jc.BuildFromSpec(testCase.input, "buildID", "prowJobID")
   350  
   351  			if buildErr != nil && !testCase.expectError {
   352  				t.Errorf("%s: unexpected build error: %v", testCase.name, buildErr)
   353  			}
   354  
   355  			if !reflect.DeepEqual(testCase.output, actualPaths) {
   356  				t.Errorf("%s: expected path %s, got %s", testCase.name, testCase.output, actualPaths)
   357  			}
   358  		})
   359  	}
   360  }
   361  
   362  func TestGetJobName(t *testing.T) {
   363  	testCases := []struct {
   364  		name   string
   365  		input  *prowapi.ProwJobSpec
   366  		output string
   367  	}{
   368  		{
   369  			name: "GitHub Branch Source based PR job",
   370  			input: &prowapi.ProwJobSpec{
   371  				Agent: "jenkins",
   372  				Job:   "my-jenkins-job-name",
   373  				JenkinsSpec: &prowapi.JenkinsSpec{
   374  					GitHubBranchSourceJob: true,
   375  				},
   376  				Refs: &prowapi.Refs{
   377  					BaseRef: "master",
   378  					BaseSHA: "deadbeef",
   379  					Pulls: []prowapi.Pull{
   380  						{
   381  							Number: 123,
   382  							SHA:    "abcd1234",
   383  						},
   384  					},
   385  				},
   386  			},
   387  			output: "my-jenkins-job-name/view/change-requests/job/PR-123",
   388  		},
   389  		{
   390  			name: "GitHub Branch Source based PR job in folder",
   391  			input: &prowapi.ProwJobSpec{
   392  				Agent: "jenkins",
   393  				Job:   "folder1/folder2/my-jenkins-job-name",
   394  				JenkinsSpec: &prowapi.JenkinsSpec{
   395  					GitHubBranchSourceJob: true,
   396  				},
   397  				Refs: &prowapi.Refs{
   398  					BaseRef: "master",
   399  					BaseSHA: "deadbeef",
   400  					Pulls: []prowapi.Pull{
   401  						{
   402  							Number: 123,
   403  							SHA:    "abcd1234",
   404  						},
   405  					},
   406  				},
   407  			},
   408  			output: "folder1/job/folder2/job/my-jenkins-job-name/view/change-requests/job/PR-123",
   409  		},
   410  		{
   411  			name: "GitHub Branch Source based branch job",
   412  			input: &prowapi.ProwJobSpec{
   413  				Agent: "jenkins",
   414  				Type:  prowapi.PostsubmitJob,
   415  				Job:   "my-jenkins-job-name",
   416  				JenkinsSpec: &prowapi.JenkinsSpec{
   417  					GitHubBranchSourceJob: true,
   418  				},
   419  				Refs: &prowapi.Refs{
   420  					BaseRef: "master",
   421  					BaseSHA: "deadbeef",
   422  				},
   423  			},
   424  			output: "my-jenkins-job-name/job/master",
   425  		},
   426  		{
   427  			name: "GitHub Branch Source based branch job in folder",
   428  			input: &prowapi.ProwJobSpec{
   429  				Agent: "jenkins",
   430  				Type:  prowapi.PostsubmitJob,
   431  				Job:   "folder1/folder2/my-jenkins-job-name",
   432  				JenkinsSpec: &prowapi.JenkinsSpec{
   433  					GitHubBranchSourceJob: true,
   434  				},
   435  				Refs: &prowapi.Refs{
   436  					BaseRef: "master",
   437  					BaseSHA: "deadbeef",
   438  				},
   439  			},
   440  			output: "folder1/job/folder2/job/my-jenkins-job-name/job/master",
   441  		},
   442  		{
   443  			name: "Static Jenkins job",
   444  			input: &prowapi.ProwJobSpec{
   445  				Agent: "jenkins",
   446  				Job:   "my-k8s-job-name",
   447  				Refs: &prowapi.Refs{
   448  					BaseRef: "master",
   449  					BaseSHA: "deadbeef",
   450  					Pulls: []prowapi.Pull{
   451  						{
   452  							Number: 123,
   453  							SHA:    "abcd1234",
   454  						},
   455  					},
   456  				},
   457  			},
   458  			output: "my-k8s-job-name",
   459  		},
   460  		{
   461  			name: "Static Jenkins job in folder",
   462  			input: &prowapi.ProwJobSpec{
   463  				Agent: "jenkins",
   464  				Job:   "folder1/folder2/my-k8s-job-name",
   465  				Refs: &prowapi.Refs{
   466  					BaseRef: "master",
   467  					BaseSHA: "deadbeef",
   468  					Pulls: []prowapi.Pull{
   469  						{
   470  							Number: 123,
   471  							SHA:    "abcd1234",
   472  						},
   473  					},
   474  				},
   475  			},
   476  			output: "folder1/job/folder2/job/my-k8s-job-name",
   477  		},
   478  	}
   479  
   480  	for _, testCase := range testCases {
   481  		t.Run(testCase.name, func(t *testing.T) {
   482  			actualValue := getJobName(testCase.input)
   483  
   484  			if !reflect.DeepEqual(testCase.output, actualValue) {
   485  				t.Errorf("%s: expected values %s, got %s", testCase.name, testCase.output, actualValue)
   486  			}
   487  
   488  		})
   489  	}
   490  }
   491  
   492  func TestGetJobInfoPath(t *testing.T) {
   493  	testCases := []struct {
   494  		name   string
   495  		input  *prowapi.ProwJobSpec
   496  		output string
   497  	}{
   498  		{
   499  			name: "GitHub Branch Source based PR job",
   500  			input: &prowapi.ProwJobSpec{
   501  				Agent: "jenkins",
   502  				Job:   "my-jenkins-job-name",
   503  				JenkinsSpec: &prowapi.JenkinsSpec{
   504  					GitHubBranchSourceJob: true,
   505  				},
   506  				Refs: &prowapi.Refs{
   507  					BaseRef: "master",
   508  					BaseSHA: "deadbeef",
   509  					Pulls: []prowapi.Pull{
   510  						{
   511  							Number: 123,
   512  							SHA:    "abcd1234",
   513  						},
   514  					},
   515  				},
   516  			},
   517  			output: "/job/my-jenkins-job-name/view/change-requests/job/PR-123/api/json",
   518  		},
   519  		{
   520  			name: "GitHub Branch Source based branch job",
   521  			input: &prowapi.ProwJobSpec{
   522  				Agent: "jenkins",
   523  				Type:  prowapi.PostsubmitJob,
   524  				Job:   "my-jenkins-job-name",
   525  				JenkinsSpec: &prowapi.JenkinsSpec{
   526  					GitHubBranchSourceJob: true,
   527  				},
   528  				Refs: &prowapi.Refs{
   529  					BaseRef: "master",
   530  					BaseSHA: "deadbeef",
   531  				},
   532  			},
   533  			output: "/job/my-jenkins-job-name/job/master/api/json",
   534  		},
   535  		{
   536  			name: "Static Jenkins job",
   537  			input: &prowapi.ProwJobSpec{
   538  				Agent: "jenkins",
   539  				Job:   "my-k8s-job-name",
   540  				Refs: &prowapi.Refs{
   541  					BaseRef: "master",
   542  					BaseSHA: "deadbeef",
   543  					Pulls: []prowapi.Pull{
   544  						{
   545  							Number: 123,
   546  							SHA:    "abcd1234",
   547  						},
   548  					},
   549  				},
   550  			},
   551  			output: "/job/my-k8s-job-name/api/json",
   552  		},
   553  	}
   554  
   555  	for _, testCase := range testCases {
   556  		t.Run(testCase.name, func(t *testing.T) {
   557  			actualValue := getJobInfoPath(testCase.input)
   558  
   559  			if !reflect.DeepEqual(testCase.output, actualValue) {
   560  				t.Errorf("%s: expected values %s, got %s", testCase.name, testCase.output, actualValue)
   561  			}
   562  
   563  		})
   564  	}
   565  }
   566  
   567  func TestGetBuildPath(t *testing.T) {
   568  	testCases := []struct {
   569  		name   string
   570  		input  *prowapi.ProwJobSpec
   571  		output string
   572  	}{
   573  		{
   574  			name: "GitHub Branch Source based PR job",
   575  			input: &prowapi.ProwJobSpec{
   576  				Agent: "jenkins",
   577  				Job:   "my-jenkins-job-name",
   578  				JenkinsSpec: &prowapi.JenkinsSpec{
   579  					GitHubBranchSourceJob: true,
   580  				},
   581  				Refs: &prowapi.Refs{
   582  					BaseRef: "master",
   583  					BaseSHA: "deadbeef",
   584  					Pulls: []prowapi.Pull{
   585  						{
   586  							Number: 123,
   587  							SHA:    "abcd1234",
   588  						},
   589  					},
   590  				},
   591  			},
   592  			output: "/job/my-jenkins-job-name/view/change-requests/job/PR-123/build",
   593  		},
   594  		{
   595  			name: "GitHub Branch Source based branch job",
   596  			input: &prowapi.ProwJobSpec{
   597  				Agent: "jenkins",
   598  				Type:  prowapi.PostsubmitJob,
   599  				Job:   "my-jenkins-job-name",
   600  				JenkinsSpec: &prowapi.JenkinsSpec{
   601  					GitHubBranchSourceJob: true,
   602  				},
   603  				Refs: &prowapi.Refs{
   604  					BaseRef: "master",
   605  					BaseSHA: "deadbeef",
   606  				},
   607  			},
   608  			output: "/job/my-jenkins-job-name/job/master/build",
   609  		},
   610  		{
   611  			name: "Static Jenkins job",
   612  			input: &prowapi.ProwJobSpec{
   613  				Agent: "jenkins",
   614  				Job:   "my-k8s-job-name",
   615  				Refs: &prowapi.Refs{
   616  					BaseRef: "master",
   617  					BaseSHA: "deadbeef",
   618  					Pulls: []prowapi.Pull{
   619  						{
   620  							Number: 123,
   621  							SHA:    "abcd1234",
   622  						},
   623  					},
   624  				},
   625  			},
   626  			output: "/job/my-k8s-job-name/build",
   627  		},
   628  	}
   629  
   630  	for _, testCase := range testCases {
   631  		t.Run(testCase.name, func(t *testing.T) {
   632  			actualValue := getBuildPath(testCase.input)
   633  
   634  			if !reflect.DeepEqual(testCase.output, actualValue) {
   635  				t.Errorf("%s: expected values %s, got %s", testCase.name, testCase.output, actualValue)
   636  			}
   637  
   638  		})
   639  	}
   640  }
   641  
   642  func TestGetBuildWithParametersPath(t *testing.T) {
   643  	testCases := []struct {
   644  		name   string
   645  		input  *prowapi.ProwJobSpec
   646  		output string
   647  	}{
   648  		{
   649  			name: "GitHub Branch Source based PR job",
   650  			input: &prowapi.ProwJobSpec{
   651  				Agent: "jenkins",
   652  				Job:   "my-jenkins-job-name",
   653  				JenkinsSpec: &prowapi.JenkinsSpec{
   654  					GitHubBranchSourceJob: true,
   655  				},
   656  				Refs: &prowapi.Refs{
   657  					BaseRef: "master",
   658  					BaseSHA: "deadbeef",
   659  					Pulls: []prowapi.Pull{
   660  						{
   661  							Number: 123,
   662  							SHA:    "abcd1234",
   663  						},
   664  					},
   665  				},
   666  			},
   667  			output: "/job/my-jenkins-job-name/view/change-requests/job/PR-123/buildWithParameters",
   668  		},
   669  		{
   670  			name: "GitHub Branch Source based branch job",
   671  			input: &prowapi.ProwJobSpec{
   672  				Agent: "jenkins",
   673  				Type:  prowapi.PostsubmitJob,
   674  				Job:   "my-jenkins-job-name",
   675  				JenkinsSpec: &prowapi.JenkinsSpec{
   676  					GitHubBranchSourceJob: true,
   677  				},
   678  				Refs: &prowapi.Refs{
   679  					BaseRef: "master",
   680  					BaseSHA: "deadbeef",
   681  				},
   682  			},
   683  			output: "/job/my-jenkins-job-name/job/master/buildWithParameters",
   684  		},
   685  		{
   686  			name: "Static Jenkins job",
   687  			input: &prowapi.ProwJobSpec{
   688  				Agent: "jenkins",
   689  				Job:   "my-k8s-job-name",
   690  				Refs: &prowapi.Refs{
   691  					BaseRef: "master",
   692  					BaseSHA: "deadbeef",
   693  					Pulls: []prowapi.Pull{
   694  						{
   695  							Number: 123,
   696  							SHA:    "abcd1234",
   697  						},
   698  					},
   699  				},
   700  			},
   701  			output: "/job/my-k8s-job-name/buildWithParameters",
   702  		},
   703  	}
   704  
   705  	for _, testCase := range testCases {
   706  		t.Run(testCase.name, func(t *testing.T) {
   707  			actualValue := getBuildWithParametersPath(testCase.input)
   708  
   709  			if !reflect.DeepEqual(testCase.output, actualValue) {
   710  				t.Errorf("%s: expected values %s, got %s", testCase.name, testCase.output, actualValue)
   711  			}
   712  
   713  		})
   714  	}
   715  }