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 }