k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/experiment/gerrit-onboarder/onboarder_test.go (about) 1 /* 2 Copyright 2021 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 main 18 19 import ( 20 "regexp" 21 "strings" 22 "testing" 23 24 "github.com/google/go-cmp/cmp" 25 "github.com/google/go-cmp/cmp/cmpopts" 26 ) 27 28 func TestMapToGroups(t *testing.T) { 29 cases := []struct { 30 name string 31 groupsMap map[string]string 32 groupsString string 33 orderedIDs []string 34 }{ 35 { 36 name: "empty map", 37 groupsMap: map[string]string{}, 38 groupsString: "# UUID\tGroup Name\n", 39 orderedIDs: []string{}, 40 }, 41 { 42 name: "all uuids same size", 43 groupsMap: map[string]string{ 44 "123456": "Test Project 1", 45 "567890": "Test Project 2", 46 }, 47 groupsString: "# UUID\tGroup Name\n123456\tTest Project 1\n567890\tTest Project 2\n", 48 orderedIDs: []string{"123456", "567890"}, 49 }, 50 { 51 name: "different sized uuid", 52 groupsMap: map[string]string{ 53 "1234": "Test Project 1", 54 "123456789": "Test Project 2", 55 }, 56 groupsString: "# UUID \tGroup Name\n1234 \tTest Project 1\n123456789\tTest Project 2\n", 57 orderedIDs: []string{"1234", "123456789"}, 58 }, 59 { 60 name: "Keeps comments", 61 groupsMap: map[string]string{ 62 "1234": "Test Project 1", 63 "123456789": "Test Project 2", 64 }, 65 groupsString: "# UUID \tGroup Name\n#\n1234 \tTest Project 1\n123456789\tTest Project 2\n", 66 orderedIDs: []string{"#", "1234", "123456789"}, 67 }, 68 } 69 70 for _, tc := range cases { 71 t.Run(tc.name, func(t *testing.T) { 72 if diff := cmp.Diff(tc.groupsString, mapToGroups(tc.groupsMap, tc.orderedIDs)); diff != "" { 73 t.Errorf("mapToGroup returned unexpected value (-want +got):\n%s", diff) 74 } 75 }) 76 } 77 78 } 79 80 func TestGroupsToMap(t *testing.T) { 81 cases := []struct { 82 name string 83 groupsMap map[string]string 84 groupsString string 85 orderedIDs []string 86 }{ 87 { 88 name: "empty groups", 89 groupsMap: map[string]string{}, 90 groupsString: "# UUID\tGroup Name\n", 91 orderedIDs: []string{}, 92 }, 93 { 94 name: "all uuids same size", 95 groupsMap: map[string]string{ 96 "123456": "Test Project 1", 97 "567890": "Test Project 2", 98 }, 99 groupsString: "# UUID\tGroup Name\n123456\tTest Project 1\n567890\tTest Project 2\n", 100 orderedIDs: []string{"123456", "567890"}, 101 }, 102 { 103 name: "different sized uuid", 104 groupsMap: map[string]string{ 105 "1234": "Test Project 1", 106 "123456789": "Test Project 2", 107 }, 108 groupsString: "# UUID \tGroup Name\n1234 \tTest Project 1\n123456789\tTest Project 2\n", 109 orderedIDs: []string{"1234", "123456789"}, 110 }, 111 { 112 name: "keeps comments", 113 groupsMap: map[string]string{ 114 "1234": "Test Project 1", 115 "123456789": "Test Project 2", 116 }, 117 groupsString: "# UUID \tGroup Name\n#\n1234 \tTest Project 1\n123456789\tTest Project 2\n", 118 orderedIDs: []string{"#", "1234", "123456789"}, 119 }, 120 } 121 122 for _, tc := range cases { 123 t.Run(tc.name, func(t *testing.T) { 124 groupsMap, orderedKeys := groupsToMap(tc.groupsString) 125 if diff := cmp.Diff(tc.groupsMap, groupsMap, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" { 126 t.Errorf("groupsToMap returned unexpected map value(-want +got):\n%s", diff) 127 } 128 129 if diff := cmp.Diff(tc.orderedIDs, orderedKeys); diff != "" { 130 t.Errorf("groupsToMap returned unexpected ordered keys value (-want +got):\n%s", diff) 131 } 132 }) 133 } 134 } 135 136 func TestConfigToMap(t *testing.T) { 137 cases := []struct { 138 name string 139 configMap map[string][]string 140 configString string 141 orderedIDs []string 142 }{ 143 { 144 name: "empty config", 145 configMap: map[string][]string{}, 146 configString: "", 147 orderedIDs: []string{}, 148 }, 149 { 150 name: "one section", 151 configMap: map[string][]string{"[access]": {"\towner = group Test Group"}}, 152 configString: "[access]\n\towner = group Test Group", 153 orderedIDs: []string{"[access]"}, 154 }, 155 { 156 name: "multiple sections and lines", 157 configMap: map[string][]string{"[access]": {"\towner = group Test Group", "\towner = group Test Group 2"}, "[access \"refs/*\"]": {"\tread = group Test Group 3"}}, 158 configString: "[access]\n\towner = group Test Group\n\towner = group Test Group 2\n[access \"refs/*\"]\n\tread = group Test Group 3", 159 orderedIDs: []string{"[access]", "[access \"refs/*\"]"}, 160 }, 161 { 162 name: "empty line end of file", 163 configString: "[access]\n\towner=group Test Group\n", 164 configMap: map[string][]string{"[access]": {"\towner=group Test Group"}}, 165 orderedIDs: []string{"[access]"}, 166 }, 167 } 168 for _, tc := range cases { 169 t.Run(tc.name, func(t *testing.T) { 170 configMap, orderedKeys := configToMap(tc.configString) 171 if diff := cmp.Diff(tc.configMap, configMap, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" { 172 t.Errorf("configToMap returned unexpected map value(-want +got):\n%s", diff) 173 } 174 if diff := cmp.Diff(tc.orderedIDs, orderedKeys, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" { 175 t.Errorf("configToMap returned unexpected ordredKeys value(-want +got):\n%s", diff) 176 } 177 }) 178 } 179 } 180 181 func TestMapToConfig(t *testing.T) { 182 cases := []struct { 183 name string 184 configMap map[string][]string 185 configString string 186 orderedIDs []string 187 }{ 188 { 189 name: "empty config", 190 configMap: map[string][]string{}, 191 configString: "", 192 orderedIDs: []string{}, 193 }, 194 { 195 name: "one section", 196 configMap: map[string][]string{"[access]": {"\towner = group Test Group"}}, 197 configString: "[access]\n\towner = group Test Group\n", 198 orderedIDs: []string{"[access]"}, 199 }, 200 { 201 name: "multiple sections and lines", 202 configMap: map[string][]string{"[access]": {"\towner = group Test Group", "\towner = group Test Group 2"}, "[access \"refs/*\"]": {"\tread = group Test Group 3"}}, 203 configString: "[access]\n\towner = group Test Group\n\towner = group Test Group 2\n[access \"refs/*\"]\n\tread = group Test Group 3\n", 204 orderedIDs: []string{"[access]", "[access \"refs/*\"]"}, 205 }, 206 } 207 for _, tc := range cases { 208 t.Run(tc.name, func(t *testing.T) { 209 config := mapToConfig(tc.configMap, tc.orderedIDs) 210 if diff := cmp.Diff(tc.configString, config); diff != "" { 211 t.Errorf("mapToConfig returned unexpected value(-want +got):\n%s", diff) 212 } 213 }) 214 } 215 } 216 217 func TestEnsureUUID(t *testing.T) { 218 cases := []struct { 219 name string 220 id string 221 group string 222 groupsString string 223 expectedString string 224 err bool 225 }{ 226 { 227 name: "already exists", 228 id: "123456", 229 group: "Test Project 1", 230 groupsString: "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n", 231 expectedString: "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n", 232 err: false, 233 }, 234 { 235 name: "add new ID with new spacing", 236 id: "123456789", 237 group: "Test Project 3", 238 groupsString: "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n", 239 expectedString: "# UUID \tGroup Name\n#\n123456 \tTest Project 1\n567890 \tTest Project 2\n123456789\tTest Project 3\n", 240 err: false, 241 }, 242 { 243 name: "conflicting ID", 244 id: "123456", 245 group: "Test Project 3", 246 groupsString: "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n", 247 expectedString: "", 248 err: true, 249 }, 250 { 251 name: "conflicting groupName", 252 id: "12345678", 253 group: "Test Project 1", 254 groupsString: "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n", 255 expectedString: "", 256 err: true, 257 }, 258 } 259 for _, tc := range cases { 260 t.Run(tc.name, func(t *testing.T) { 261 res, err := ensureUUID(tc.groupsString, tc.id, tc.group) 262 if err != nil && !tc.err { 263 t.Errorf("expected no error but got %v", err) 264 } 265 if err == nil && tc.err { 266 t.Error("expected error but got none") 267 } 268 if diff := cmp.Diff(tc.expectedString, res); diff != "" { 269 t.Errorf("ensureUUID returned unexpected value (-want +got):\n%s", diff) 270 } 271 }) 272 } 273 } 274 275 func TestGetInheritedRepo(t *testing.T) { 276 cases := []struct { 277 name string 278 configMap map[string][]string 279 expected string 280 }{ 281 { 282 name: "no inheritance", 283 configMap: map[string][]string{"[access]": {"\towner = group Test Group"}}, 284 expected: "", 285 }, 286 { 287 name: "inherits", 288 configMap: map[string][]string{"[access]": {"\towner = group Test Group", "/tinheritFrom = All-Projects"}}, 289 expected: "All-Projects", 290 }, 291 } 292 for _, tc := range cases { 293 t.Run(tc.name, func(t *testing.T) { 294 res := getInheritedRepo(tc.configMap) 295 if diff := cmp.Diff(tc.expected, res); diff != "" { 296 t.Errorf("getInheritedRepo returned unexpected value(-want +got):\n%s", diff) 297 } 298 }) 299 } 300 301 } 302 303 func TestLineInMatchingHeaderFunc(t *testing.T) { 304 sampleConfig := map[string][]string{ 305 "[access]": {"\towner = group Test Group 2", "\towner = group Test Group 3"}, 306 "[access \"refs/*\"]": {"\tread = group Test Group 1"}, 307 "[access \"refs/for/master\"]": {"\tread = group Test Group 4"}, 308 } 309 cases := []struct { 310 name string 311 configMap map[string][]string 312 line string 313 expected bool 314 regex *regexp.Regexp 315 }{ 316 { 317 name: "empty config", 318 configMap: map[string][]string{}, 319 line: "owner = group Test Group", 320 expected: false, 321 regex: accessRefsRegex, 322 }, 323 { 324 name: "line in config", 325 configMap: sampleConfig, 326 line: "read = group Test Group 1", 327 expected: true, 328 regex: accessRefsRegex, 329 }, 330 { 331 name: "line not under header", 332 configMap: sampleConfig, 333 line: "owner = group Test Group 2", 334 expected: false, 335 regex: accessRefsRegex, 336 }, 337 { 338 name: "header more complicated", 339 configMap: sampleConfig, 340 line: "read = group Test Group 4", 341 expected: true, 342 regex: accessRefsRegex, 343 }, 344 } 345 for _, tc := range cases { 346 t.Run(tc.name, func(t *testing.T) { 347 resFunc := lineInMatchingHeaderFunc(tc.regex, tc.line) 348 res := resFunc(tc.configMap) 349 if diff := cmp.Diff(tc.expected, res); diff != "" { 350 t.Errorf("lineInMatchingHeaderFunc returned unexpected value(-want +got):\n%s", diff) 351 } 352 }) 353 } 354 } 355 356 func TestLabelExists(t *testing.T) { 357 cases := []struct { 358 name string 359 configMap map[string][]string 360 expected bool 361 }{ 362 { 363 name: "empty config", 364 configMap: map[string][]string{}, 365 expected: false, 366 }, 367 { 368 name: "header not in config", 369 configMap: map[string][]string{"[access]": {"\towner = group Test Group"}}, 370 expected: false, 371 }, 372 { 373 name: "header in config", 374 configMap: map[string][]string{labelHeader: {"\towner = group Test Group"}}, 375 expected: true, 376 }, 377 } 378 for _, tc := range cases { 379 t.Run(tc.name, func(t *testing.T) { 380 // labelExists always returns nil error 381 res := labelExists(tc.configMap) 382 if diff := cmp.Diff(tc.expected, res); diff != "" { 383 t.Errorf("lineInConfig returned unexpected value(-want +got):\n%s", diff) 384 } 385 }) 386 } 387 } 388 389 func TestLabelAccessExistsFunc(t *testing.T) { 390 cases := []struct { 391 name string 392 configMap map[string][]string 393 groupName string 394 expected bool 395 }{ 396 { 397 name: "empty config", 398 configMap: map[string][]string{}, 399 groupName: "Test Group", 400 expected: false, 401 }, 402 { 403 name: "line in config", 404 configMap: map[string][]string{"[access]": {"\tlabel-Verified = -1..+1 group Test Group"}}, 405 groupName: "Test Group", 406 expected: true, 407 }, 408 { 409 name: "different values in config", 410 configMap: map[string][]string{"[access]": {"\tlabel-Verified = -2..+2 group Test Group"}}, 411 groupName: "Test Group", 412 expected: true, 413 }, 414 { 415 name: "Different group", 416 configMap: map[string][]string{"[access]": {"\tlabel-Verified = -1..+1 group Not Test Group"}}, 417 groupName: "Test Group", 418 expected: false, 419 }, 420 } 421 for _, tc := range cases { 422 t.Run(tc.name, func(t *testing.T) { 423 resFunc := labelAccessExistsFunc(tc.groupName) 424 res := resFunc(tc.configMap) 425 if diff := cmp.Diff(tc.expected, res); diff != "" { 426 t.Errorf("lineInConfig returned unexpected value(-want +got):\n%s", diff) 427 } 428 }) 429 } 430 } 431 432 func TestAddSection(t *testing.T) { 433 cases := []struct { 434 name string 435 configMap map[string][]string 436 orderedIDs []string 437 header string 438 adding []string 439 expectedMap map[string][]string 440 expectedIDs []string 441 }{ 442 { 443 name: "empty config", 444 configMap: map[string][]string{}, 445 orderedIDs: []string{}, 446 header: "[access]", 447 adding: []string{"test1", "test2"}, 448 expectedMap: map[string][]string{"[access]": {"\ttest1", "\ttest2"}}, 449 expectedIDs: []string{"[access]"}, 450 }, 451 { 452 name: "add to already existing section", 453 configMap: map[string][]string{"[access]": {"\towner = group Test Group"}}, 454 orderedIDs: []string{"[access]"}, 455 header: "[access]", 456 adding: []string{"test1", "test2"}, 457 expectedMap: map[string][]string{"[access]": {"\towner = group Test Group", "\ttest1", "\ttest2"}}, 458 expectedIDs: []string{"[access]"}, 459 }, 460 { 461 name: "add to already existing section", 462 configMap: map[string][]string{"[access]": {"\towner = group Test Group"}}, 463 orderedIDs: []string{"[access]"}, 464 header: "[test]", 465 adding: []string{"test1", "test2"}, 466 expectedMap: map[string][]string{"[access]": {"\towner = group Test Group"}, "[test]": {"\ttest1", "\ttest2"}}, 467 expectedIDs: []string{"[access]", "[test]"}, 468 }, 469 } 470 for _, tc := range cases { 471 t.Run(tc.name, func(t *testing.T) { 472 configMap, orderedKeys := addSection(tc.header, tc.configMap, tc.orderedIDs, tc.adding) 473 if diff := cmp.Diff(tc.expectedMap, configMap, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" { 474 t.Errorf("configToMap returned unexpected map value(-want +got):\n%s", diff) 475 } 476 if diff := cmp.Diff(tc.expectedIDs, orderedKeys, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" { 477 t.Errorf("configToMap returned unexpected ordredKeys value(-want +got):\n%s", diff) 478 } 479 }) 480 } 481 } 482 483 func TestGetRepoClonedName(t *testing.T) { 484 cases := []struct { 485 name string 486 repo string 487 expected string 488 }{ 489 { 490 name: "No slashes", 491 repo: "test-infra", 492 expected: "test-infra", 493 }, 494 { 495 name: "empty", 496 repo: "", 497 expected: "", 498 }, 499 { 500 name: "one slash", 501 repo: "testing/test-infra", 502 expected: "test-infra", 503 }, 504 { 505 name: "multiple slashes", 506 repo: "testing/two/test-infra", 507 expected: "test-infra", 508 }, 509 } 510 for _, tc := range cases { 511 t.Run(tc.name, func(t *testing.T) { 512 workdir := getRepoClonedName(tc.repo) 513 if diff := cmp.Diff(workdir, tc.expected); diff != "" { 514 t.Errorf("configToMap returned unexpected map value(-want +got):\n%s", diff) 515 } 516 }) 517 } 518 }