sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/cmd/generic-autobumper/bumper/bumper_test.go (about)

     1  /*
     2  Copyright 2019 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 bumper
    18  
    19  import (
    20  	"os"
    21  	"path"
    22  	"path/filepath"
    23  	"strings"
    24  	"testing"
    25  
    26  	"sigs.k8s.io/prow/pkg/config/secret"
    27  )
    28  
    29  func TestValidateOptions(t *testing.T) {
    30  	emptyStr := ""
    31  	trueVar := true
    32  	cases := []struct {
    33  		name                string
    34  		githubToken         *string
    35  		githubOrg           *string
    36  		githubRepo          *string
    37  		gerrit              *bool
    38  		gerritAuthor        *string
    39  		gerritPRIdentifier  *string
    40  		gerritHostRepo      *string
    41  		gerritCookieFile    *string
    42  		remoteName          *string
    43  		skipPullRequest     *bool
    44  		signoff             *bool
    45  		err                 bool
    46  		upstreamBaseChanged bool
    47  	}{
    48  		{
    49  			name: "Everything correct",
    50  			err:  false,
    51  		},
    52  		{
    53  			name:        "GitHubToken must not be empty when SkipPullRequest is false",
    54  			githubToken: &emptyStr,
    55  			err:         true,
    56  		},
    57  		{
    58  			name:       "remoteName must not be empty when SkipPullRequest is false",
    59  			remoteName: &emptyStr,
    60  			err:        true,
    61  		},
    62  		{
    63  			name:      "GitHubOrg cannot be empty when SkipPullRequest is false",
    64  			githubOrg: &emptyStr,
    65  			err:       true,
    66  		},
    67  		{
    68  			name:       "GitHubRepo cannot be empty when SkipPullRequest is false",
    69  			githubRepo: &emptyStr,
    70  			err:        true,
    71  		},
    72  		{
    73  			name:         "gerritAuthor cannot be empty when SkipPullRequest is false and gerrit is true",
    74  			gerrit:       &trueVar,
    75  			gerritAuthor: &emptyStr,
    76  			err:          true,
    77  		},
    78  		{
    79  			name:           "gerritHostRepo cannot be empty when SkipPullRequest is false and gerrit is true",
    80  			gerrit:         &trueVar,
    81  			gerritHostRepo: &emptyStr,
    82  			err:            true,
    83  		},
    84  		{
    85  			name:             "gerritCookieFile cannot be empty when SkipPullRequest is false and gerrit is true",
    86  			gerrit:           &trueVar,
    87  			gerritCookieFile: &emptyStr,
    88  			err:              true,
    89  		},
    90  		{
    91  			name:               "gerritCommitId cannot be empty when SkipPullRequest is false and gerrit is true",
    92  			gerrit:             &trueVar,
    93  			gerritPRIdentifier: &emptyStr,
    94  			err:                true,
    95  		},
    96  	}
    97  	for _, tc := range cases {
    98  		t.Run(tc.name, func(t *testing.T) {
    99  			gerrit := &Gerrit{
   100  				Author:               "whatever-author",
   101  				CookieFile:           "whatever cookie file",
   102  				AutobumpPRIdentifier: "whatever-commit-id",
   103  				HostRepo:             "whatever-host-repo",
   104  			}
   105  			defaultOption := &Options{
   106  				GitHubOrg:       "whatever-org",
   107  				GitHubRepo:      "whatever-repo",
   108  				GitHubLogin:     "whatever-login",
   109  				GitHubToken:     "whatever-token",
   110  				GitName:         "whatever-name",
   111  				GitEmail:        "whatever-email",
   112  				Gerrit:          nil,
   113  				RemoteName:      "whatever-name",
   114  				SkipPullRequest: false,
   115  				Signoff:         false,
   116  			}
   117  
   118  			if tc.skipPullRequest != nil {
   119  				defaultOption.SkipPullRequest = *tc.skipPullRequest
   120  			}
   121  			if tc.signoff != nil {
   122  				defaultOption.Signoff = *tc.signoff
   123  			}
   124  			if tc.githubToken != nil {
   125  				defaultOption.GitHubToken = *tc.githubToken
   126  			}
   127  			if tc.remoteName != nil {
   128  				defaultOption.RemoteName = *tc.remoteName
   129  			}
   130  			if tc.githubOrg != nil {
   131  				defaultOption.GitHubOrg = *tc.githubOrg
   132  			}
   133  			if tc.githubRepo != nil {
   134  				defaultOption.GitHubRepo = *tc.githubRepo
   135  			}
   136  			if tc.gerrit != nil {
   137  				defaultOption.Gerrit = gerrit
   138  			}
   139  			if tc.gerritAuthor != nil {
   140  				defaultOption.Gerrit.Author = *tc.gerritAuthor
   141  			}
   142  			if tc.gerritPRIdentifier != nil {
   143  				defaultOption.Gerrit.AutobumpPRIdentifier = *tc.gerritPRIdentifier
   144  			}
   145  			if tc.gerritCookieFile != nil {
   146  				defaultOption.Gerrit.CookieFile = *tc.gerritCookieFile
   147  			}
   148  			if tc.gerritHostRepo != nil {
   149  				defaultOption.Gerrit.HostRepo = *tc.gerritHostRepo
   150  			}
   151  
   152  			err := validateOptions(defaultOption)
   153  			t.Logf("err is: %v", err)
   154  			if err == nil && tc.err {
   155  				t.Errorf("Expected to get an error for %#v but got nil", defaultOption)
   156  			}
   157  			if err != nil && !tc.err {
   158  				t.Errorf("Expected to not get an error for %#v but got %v", defaultOption, err)
   159  			}
   160  		})
   161  	}
   162  }
   163  
   164  type fakeWriter struct {
   165  	results []byte
   166  }
   167  
   168  func (w *fakeWriter) Write(content []byte) (n int, err error) {
   169  	w.results = append(w.results, content...)
   170  	return len(content), nil
   171  }
   172  
   173  func writeToFile(t *testing.T, path, content string) {
   174  	if err := os.WriteFile(path, []byte(content), 0644); err != nil {
   175  		t.Errorf("write file %s dir with error '%v'", path, err)
   176  	}
   177  }
   178  
   179  func TestCallWithWriter(t *testing.T) {
   180  	dir := t.TempDir()
   181  
   182  	file1 := filepath.Join(dir, "secret1")
   183  	file2 := filepath.Join(dir, "secret2")
   184  
   185  	writeToFile(t, file1, "abc")
   186  	writeToFile(t, file2, "xyz")
   187  
   188  	if err := secret.Add(file1, file2); err != nil {
   189  		t.Errorf("failed to start secrets agent; %v", err)
   190  	}
   191  
   192  	var fakeOut fakeWriter
   193  	var fakeErr fakeWriter
   194  
   195  	stdout := HideSecretsWriter{Delegate: &fakeOut, Censor: secret.Censor}
   196  	stderr := HideSecretsWriter{Delegate: &fakeErr, Censor: secret.Censor}
   197  
   198  	testCases := []struct {
   199  		description string
   200  		command     string
   201  		args        []string
   202  		expectedOut string
   203  		expectedErr string
   204  	}{
   205  		{
   206  			description: "no secret in stdout are working well",
   207  			command:     "echo",
   208  			args:        []string{"-n", "aaa: 123"},
   209  			expectedOut: "aaa: 123",
   210  		},
   211  		{
   212  			description: "secret in stdout are censored",
   213  			command:     "echo",
   214  			args:        []string{"-n", "abc: 123"},
   215  			expectedOut: "XXX: 123",
   216  		},
   217  		{
   218  			description: "secret in stderr are censored",
   219  			command:     "ls",
   220  			args:        []string{"/tmp/file-not-exist/abc/xyz/file-not-exist"},
   221  			expectedErr: "/tmp/file-not-exist/XXX/XXX/file-not-exist",
   222  		},
   223  		{
   224  			description: "no secret in stderr are working well",
   225  			command:     "ls",
   226  			args:        []string{"/tmp/file-not-exist/aaa/file-not-exist"},
   227  			expectedErr: "/tmp/file-not-exist/aaa/file-not-exist",
   228  		},
   229  	}
   230  
   231  	for _, tc := range testCases {
   232  		t.Run(tc.description, func(t *testing.T) {
   233  			fakeOut.results = []byte{}
   234  			fakeErr.results = []byte{}
   235  			_ = Call(stdout, stderr, tc.command, tc.args)
   236  			if full, want := string(fakeOut.results), tc.expectedOut; !strings.Contains(full, want) {
   237  				t.Errorf("stdout does not contain %q, got %q", full, want)
   238  			}
   239  			if full, want := string(fakeErr.results), tc.expectedErr; !strings.Contains(full, want) {
   240  				t.Errorf("stderr does not contain %q, got %q", full, want)
   241  			}
   242  		})
   243  	}
   244  }
   245  
   246  func TestGetAssignment(t *testing.T) {
   247  	cases := []struct {
   248  		description          string
   249  		assignTo             string
   250  		oncallURL            string
   251  		oncallGroup          string
   252  		oncallServerResponse string
   253  		expectResKeyword     string
   254  	}{
   255  		{
   256  			description:      "AssignTo takes precedence over oncall setings",
   257  			assignTo:         "some-user",
   258  			expectResKeyword: "/cc @some-user",
   259  		},
   260  		{
   261  			description:      "No assign to",
   262  			assignTo:         "",
   263  			expectResKeyword: "",
   264  		},
   265  	}
   266  
   267  	for _, tc := range cases {
   268  		t.Run(tc.description, func(t *testing.T) {
   269  			res := getAssignment(tc.assignTo)
   270  			if !strings.Contains(res, tc.expectResKeyword) {
   271  				t.Errorf("Expect the result %q contains keyword %q but it does not", res, tc.expectResKeyword)
   272  			}
   273  		})
   274  	}
   275  }
   276  
   277  func TestCDToRootDir(t *testing.T) {
   278  	tmpDir := t.TempDir()
   279  	for dir, fps := range map[string][]string{
   280  		"testdata/dir": {"extra-file"},
   281  	} {
   282  		if err := os.MkdirAll(path.Join(tmpDir, dir), 0755); err != nil {
   283  			t.Fatalf("Faile creating dir %q: %v", dir, err)
   284  		}
   285  		for _, f := range fps {
   286  			if _, err := os.Create(path.Join(tmpDir, dir, f)); err != nil {
   287  				t.Fatalf("Faile creating file %q: %v", f, err)
   288  			}
   289  		}
   290  	}
   291  
   292  	envName := "BUILD_WORKSPACE_DIRECTORY"
   293  
   294  	cases := []struct {
   295  		description       string
   296  		buildWorkspaceDir string
   297  		expectedResDir    string
   298  		expectError       bool
   299  	}{
   300  		// This test case does not work when running with Bazel.
   301  		{
   302  			description:       "BUILD_WORKSPACE_DIRECTORY is a valid directory",
   303  			buildWorkspaceDir: path.Join(tmpDir, "testdata/dir"),
   304  			expectedResDir:    "testdata/dir",
   305  			expectError:       false,
   306  		},
   307  		{
   308  			description:       "BUILD_WORKSPACE_DIRECTORY is an invalid directory",
   309  			buildWorkspaceDir: "whatever-dir",
   310  			expectedResDir:    "",
   311  			expectError:       true,
   312  		},
   313  	}
   314  
   315  	for _, tc := range cases {
   316  		t.Run(tc.description, func(t *testing.T) {
   317  			curtDir, _ := os.Getwd()
   318  			curtBuildWorkspaceDir := os.Getenv(envName)
   319  			defer os.Chdir(curtDir)
   320  			defer os.Setenv(envName, curtBuildWorkspaceDir)
   321  
   322  			os.Setenv(envName, tc.buildWorkspaceDir)
   323  			err := cdToRootDir()
   324  			if tc.expectError && err == nil {
   325  				t.Errorf("Expected to get an error but the result is nil")
   326  			}
   327  			if !tc.expectError && err != nil {
   328  				t.Errorf("Expected to not get an error but got one: %v", err)
   329  			}
   330  
   331  			if !tc.expectError {
   332  				afterDir, _ := os.Getwd()
   333  				if !strings.HasSuffix(afterDir, tc.expectedResDir) {
   334  					t.Errorf("Expected to switch to %q but was switched to: %q", tc.expectedResDir, afterDir)
   335  				}
   336  			}
   337  		})
   338  	}
   339  }