github.com/abayer/test-infra@v0.0.5/prow/plugins/label/label_test.go (about) 1 /* 2 Copyright 2016 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 label 18 19 import ( 20 "fmt" 21 "reflect" 22 "sort" 23 "testing" 24 25 "github.com/sirupsen/logrus" 26 "k8s.io/test-infra/prow/github" 27 "k8s.io/test-infra/prow/github/fakegithub" 28 ) 29 30 const ( 31 orgMember = "Alice" 32 nonOrgMember = "Bob" 33 ) 34 35 func formatLabels(labels ...string) []string { 36 r := []string{} 37 for _, l := range labels { 38 r = append(r, fmt.Sprintf("%s/%s#%d:%s", "org", "repo", 1, l)) 39 } 40 if len(r) == 0 { 41 return nil 42 } 43 return r 44 } 45 46 func TestLabel(t *testing.T) { 47 type testCase struct { 48 name string 49 body string 50 commenter string 51 extraLabels []string 52 expectedNewLabels []string 53 expectedRemovedLabels []string 54 expectedBotComment bool 55 repoLabels []string 56 issueLabels []string 57 } 58 testcases := []testCase{ 59 { 60 name: "Irrelevant comment", 61 body: "irrelelvant", 62 expectedNewLabels: []string{}, 63 expectedRemovedLabels: []string{}, 64 repoLabels: []string{}, 65 issueLabels: []string{}, 66 commenter: orgMember, 67 }, 68 { 69 name: "Empty Area", 70 body: "/area", 71 expectedNewLabels: []string{}, 72 expectedRemovedLabels: []string{}, 73 repoLabels: []string{"area/infra"}, 74 issueLabels: []string{"area/infra"}, 75 commenter: orgMember, 76 }, 77 { 78 name: "Add Single Area Label", 79 body: "/area infra", 80 repoLabels: []string{"area/infra"}, 81 issueLabels: []string{}, 82 expectedNewLabels: formatLabels("area/infra"), 83 expectedRemovedLabels: []string{}, 84 commenter: orgMember, 85 }, 86 { 87 name: "Add Single Area Label when already present on Issue", 88 body: "/area infra", 89 repoLabels: []string{"area/infra"}, 90 issueLabels: []string{"area/infra"}, 91 expectedNewLabels: []string{}, 92 expectedRemovedLabels: []string{}, 93 commenter: orgMember, 94 }, 95 { 96 name: "Add Single Priority Label", 97 body: "/priority critical", 98 repoLabels: []string{"area/infra", "priority/critical"}, 99 issueLabels: []string{}, 100 expectedNewLabels: formatLabels("priority/critical"), 101 expectedRemovedLabels: []string{}, 102 commenter: orgMember, 103 }, 104 { 105 name: "Add Single Kind Label", 106 body: "/kind bug", 107 repoLabels: []string{"area/infra", "priority/critical", "kind/bug"}, 108 issueLabels: []string{}, 109 expectedNewLabels: formatLabels("kind/bug"), 110 expectedRemovedLabels: []string{}, 111 commenter: orgMember, 112 }, 113 { 114 name: "Add Single Triage Label", 115 body: "/triage needs-information", 116 repoLabels: []string{"area/infra", "triage/needs-information"}, 117 issueLabels: []string{"area/infra"}, 118 expectedNewLabels: formatLabels("triage/needs-information"), 119 expectedRemovedLabels: []string{}, 120 commenter: orgMember, 121 }, 122 { 123 name: "Adding Labels is Case Insensitive", 124 body: "/kind BuG", 125 repoLabels: []string{"area/infra", "priority/critical", "kind/bug"}, 126 issueLabels: []string{}, 127 expectedNewLabels: formatLabels("kind/bug"), 128 expectedRemovedLabels: []string{}, 129 commenter: orgMember, 130 }, 131 { 132 name: "Adding Labels is Case Insensitive", 133 body: "/kind bug", 134 repoLabels: []string{"area/infra", "priority/critical", "kind/BUG"}, 135 issueLabels: []string{}, 136 expectedNewLabels: formatLabels("kind/BUG"), 137 expectedRemovedLabels: []string{}, 138 commenter: orgMember, 139 }, 140 { 141 name: "Can't Add Non Existent Label", 142 body: "/priority critical", 143 repoLabels: []string{"area/infra"}, 144 issueLabels: []string{}, 145 expectedNewLabels: formatLabels(), 146 expectedRemovedLabels: []string{}, 147 commenter: orgMember, 148 }, 149 { 150 name: "Non Org Member Can't Add", 151 body: "/area infra", 152 repoLabels: []string{"area/infra", "priority/critical", "kind/bug"}, 153 issueLabels: []string{}, 154 expectedNewLabels: formatLabels("area/infra"), 155 expectedRemovedLabels: []string{}, 156 commenter: nonOrgMember, 157 }, 158 { 159 name: "Command must start at the beginning of the line", 160 body: " /area infra", 161 repoLabels: []string{"area/infra", "area/api", "priority/critical", "priority/urgent", "priority/important", "kind/bug"}, 162 issueLabels: []string{}, 163 expectedNewLabels: formatLabels(), 164 expectedRemovedLabels: []string{}, 165 commenter: orgMember, 166 }, 167 { 168 name: "Can't Add Labels Non Existing Labels", 169 body: "/area lgtm", 170 repoLabels: []string{"area/infra", "area/api", "priority/critical"}, 171 issueLabels: []string{}, 172 expectedNewLabels: formatLabels(), 173 expectedRemovedLabels: []string{}, 174 commenter: orgMember, 175 }, 176 { 177 name: "Add Multiple Area Labels", 178 body: "/area api infra", 179 repoLabels: []string{"area/infra", "area/api", "priority/critical", "priority/urgent"}, 180 issueLabels: []string{}, 181 expectedNewLabels: formatLabels("area/api", "area/infra"), 182 expectedRemovedLabels: []string{}, 183 commenter: orgMember, 184 }, 185 { 186 name: "Add Multiple Area Labels one already present on Issue", 187 body: "/area api infra", 188 repoLabels: []string{"area/infra", "area/api", "priority/critical", "priority/urgent"}, 189 issueLabels: []string{"area/api"}, 190 expectedNewLabels: formatLabels("area/infra"), 191 expectedRemovedLabels: []string{}, 192 commenter: orgMember, 193 }, 194 { 195 name: "Add Multiple Priority Labels", 196 body: "/priority critical important", 197 repoLabels: []string{"priority/critical", "priority/important"}, 198 issueLabels: []string{}, 199 expectedNewLabels: formatLabels("priority/critical", "priority/important"), 200 expectedRemovedLabels: []string{}, 201 commenter: orgMember, 202 }, 203 { 204 name: "Label Prefix Must Match Command (Area-Priority Mismatch)", 205 body: "/area urgent", 206 repoLabels: []string{"area/infra", "area/api", "priority/critical", "priority/urgent"}, 207 issueLabels: []string{}, 208 expectedNewLabels: formatLabels(), 209 expectedRemovedLabels: []string{}, 210 commenter: orgMember, 211 }, 212 { 213 name: "Label Prefix Must Match Command (Priority-Area Mismatch)", 214 body: "/priority infra", 215 repoLabels: []string{"area/infra", "area/api", "priority/critical", "priority/urgent"}, 216 issueLabels: []string{}, 217 expectedNewLabels: formatLabels(), 218 expectedRemovedLabels: []string{}, 219 commenter: orgMember, 220 }, 221 { 222 name: "Add Multiple Area Labels (Some Valid)", 223 body: "/area lgtm infra", 224 repoLabels: []string{"area/infra", "area/api"}, 225 issueLabels: []string{}, 226 expectedNewLabels: formatLabels("area/infra"), 227 expectedRemovedLabels: []string{}, 228 commenter: orgMember, 229 }, 230 { 231 name: "Add Multiple Committee Labels (Some Valid)", 232 body: "/committee steering calamity", 233 repoLabels: []string{"committee/conduct", "committee/steering"}, 234 issueLabels: []string{}, 235 expectedNewLabels: formatLabels("committee/steering"), 236 expectedRemovedLabels: []string{}, 237 commenter: orgMember, 238 }, 239 { 240 name: "Add Multiple Types of Labels Different Lines", 241 body: "/priority urgent\n/area infra", 242 repoLabels: []string{"area/infra", "priority/urgent"}, 243 issueLabels: []string{}, 244 expectedNewLabels: formatLabels("priority/urgent", "area/infra"), 245 expectedRemovedLabels: []string{}, 246 commenter: orgMember, 247 }, 248 { 249 name: "Remove Area Label when no such Label on Repo", 250 body: "/remove-area infra", 251 repoLabels: []string{}, 252 issueLabels: []string{}, 253 expectedNewLabels: []string{}, 254 expectedRemovedLabels: []string{}, 255 commenter: orgMember, 256 expectedBotComment: true, 257 }, 258 { 259 name: "Remove Area Label when no such Label on Issue", 260 body: "/remove-area infra", 261 repoLabels: []string{"area/infra"}, 262 issueLabels: []string{}, 263 expectedNewLabels: []string{}, 264 expectedRemovedLabels: []string{}, 265 commenter: orgMember, 266 expectedBotComment: true, 267 }, 268 { 269 name: "Remove Area Label", 270 body: "/remove-area infra", 271 repoLabels: []string{"area/infra"}, 272 issueLabels: []string{"area/infra"}, 273 expectedNewLabels: []string{}, 274 expectedRemovedLabels: formatLabels("area/infra"), 275 commenter: orgMember, 276 }, 277 { 278 name: "Remove Committee Label", 279 body: "/remove-committee infinite-monkeys", 280 repoLabels: []string{"area/infra", "sig/testing", "committee/infinite-monkeys"}, 281 issueLabels: []string{"area/infra", "sig/testing", "committee/infinite-monkeys"}, 282 expectedNewLabels: []string{}, 283 expectedRemovedLabels: formatLabels("committee/infinite-monkeys"), 284 commenter: orgMember, 285 }, 286 { 287 name: "Remove Kind Label", 288 body: "/remove-kind api-server", 289 repoLabels: []string{"area/infra", "priority/high", "kind/api-server"}, 290 issueLabels: []string{"area/infra", "priority/high", "kind/api-server"}, 291 expectedNewLabels: []string{}, 292 expectedRemovedLabels: formatLabels("kind/api-server"), 293 commenter: orgMember, 294 }, 295 { 296 name: "Remove Priority Label", 297 body: "/remove-priority high", 298 repoLabels: []string{"area/infra", "priority/high"}, 299 issueLabels: []string{"area/infra", "priority/high"}, 300 expectedNewLabels: []string{}, 301 expectedRemovedLabels: formatLabels("priority/high"), 302 commenter: orgMember, 303 }, 304 { 305 name: "Remove SIG Label", 306 body: "/remove-sig testing", 307 repoLabels: []string{"area/infra", "sig/testing"}, 308 issueLabels: []string{"area/infra", "sig/testing"}, 309 expectedNewLabels: []string{}, 310 expectedRemovedLabels: formatLabels("sig/testing"), 311 commenter: orgMember, 312 }, 313 { 314 name: "Remove WG Policy", 315 body: "/remove-wg policy", 316 repoLabels: []string{"area/infra", "wg/policy"}, 317 issueLabels: []string{"area/infra", "wg/policy"}, 318 expectedNewLabels: []string{}, 319 expectedRemovedLabels: formatLabels("wg/policy"), 320 commenter: orgMember, 321 }, 322 { 323 name: "Remove Triage Label", 324 body: "/remove-triage needs-information", 325 repoLabels: []string{"area/infra", "triage/needs-information"}, 326 issueLabels: []string{"area/infra", "triage/needs-information"}, 327 expectedNewLabels: []string{}, 328 expectedRemovedLabels: formatLabels("triage/needs-information"), 329 commenter: orgMember, 330 }, 331 { 332 name: "Remove Multiple Labels", 333 body: "/remove-priority low high\n/remove-kind api-server\n/remove-area infra", 334 repoLabels: []string{"area/infra", "priority/high", "priority/low", "kind/api-server"}, 335 issueLabels: []string{"area/infra", "priority/high", "priority/low", "kind/api-server"}, 336 expectedNewLabels: []string{}, 337 expectedRemovedLabels: formatLabels("priority/low", "priority/high", "kind/api-server", "area/infra"), 338 commenter: orgMember, 339 expectedBotComment: true, 340 }, 341 { 342 name: "Add and Remove Label at the same time", 343 body: "/remove-area infra\n/area test", 344 repoLabels: []string{"area/infra", "area/test"}, 345 issueLabels: []string{"area/infra"}, 346 expectedNewLabels: formatLabels("area/test"), 347 expectedRemovedLabels: formatLabels("area/infra"), 348 commenter: orgMember, 349 }, 350 { 351 name: "Add and Remove the same Label", 352 body: "/remove-area infra\n/area infra", 353 repoLabels: []string{"area/infra"}, 354 issueLabels: []string{"area/infra"}, 355 expectedNewLabels: []string{}, 356 expectedRemovedLabels: formatLabels("area/infra"), 357 commenter: orgMember, 358 }, 359 { 360 name: "Multiple Add and Delete Labels", 361 body: "/remove-area ruby\n/remove-kind srv\n/remove-priority l m\n/area go\n/kind cli\n/priority h", 362 repoLabels: []string{"area/go", "area/ruby", "kind/cli", "kind/srv", "priority/h", "priority/m", "priority/l"}, 363 issueLabels: []string{"area/ruby", "kind/srv", "priority/l", "priority/m"}, 364 expectedNewLabels: formatLabels("area/go", "kind/cli", "priority/h"), 365 expectedRemovedLabels: formatLabels("area/ruby", "kind/srv", "priority/l", "priority/m"), 366 commenter: orgMember, 367 }, 368 { 369 name: "Do nothing with empty /label command", 370 body: "/label", 371 extraLabels: []string{"orchestrator/foo", "orchestrator/bar"}, 372 repoLabels: []string{"orchestrator/foo"}, 373 issueLabels: []string{}, 374 expectedNewLabels: []string{}, 375 expectedRemovedLabels: []string{}, 376 commenter: orgMember, 377 }, 378 { 379 name: "Do nothing with empty /remove-label command", 380 body: "/remove-label", 381 extraLabels: []string{"orchestrator/foo", "orchestrator/bar"}, 382 repoLabels: []string{"orchestrator/foo"}, 383 issueLabels: []string{}, 384 expectedNewLabels: []string{}, 385 expectedRemovedLabels: []string{}, 386 commenter: orgMember, 387 }, 388 { 389 name: "Add custom label", 390 body: "/label orchestrator/foo", 391 extraLabels: []string{"orchestrator/foo", "orchestrator/bar"}, 392 repoLabels: []string{"orchestrator/foo"}, 393 issueLabels: []string{}, 394 expectedNewLabels: formatLabels("orchestrator/foo"), 395 expectedRemovedLabels: []string{}, 396 commenter: orgMember, 397 }, 398 { 399 name: "Cannot add missing custom label", 400 body: "/label orchestrator/foo", 401 extraLabels: []string{"orchestrator/jar", "orchestrator/bar"}, 402 repoLabels: []string{"orchestrator/foo"}, 403 issueLabels: []string{}, 404 expectedNewLabels: []string{}, 405 expectedRemovedLabels: []string{}, 406 commenter: orgMember, 407 }, 408 { 409 name: "Remove custom label", 410 body: "/remove-label orchestrator/foo", 411 extraLabels: []string{"orchestrator/foo", "orchestrator/bar"}, 412 repoLabels: []string{"orchestrator/foo"}, 413 issueLabels: []string{"orchestrator/foo"}, 414 expectedNewLabels: []string{}, 415 expectedRemovedLabels: formatLabels("orchestrator/foo"), 416 commenter: orgMember, 417 }, 418 { 419 name: "Cannot remove missing custom label", 420 body: "/remove-label orchestrator/jar", 421 extraLabels: []string{"orchestrator/foo", "orchestrator/bar"}, 422 repoLabels: []string{"orchestrator/foo"}, 423 issueLabels: []string{"orchestrator/foo"}, 424 expectedNewLabels: []string{}, 425 expectedRemovedLabels: []string{}, 426 commenter: orgMember, 427 }, 428 } 429 430 for _, tc := range testcases { 431 t.Logf("Running scenario %q", tc.name) 432 sort.Strings(tc.expectedNewLabels) 433 fakeClient := &fakegithub.FakeClient{ 434 Issues: make([]github.Issue, 1), 435 IssueComments: make(map[int][]github.IssueComment), 436 ExistingLabels: tc.repoLabels, 437 OrgMembers: map[string][]string{"org": {orgMember}}, 438 LabelsAdded: []string{}, 439 LabelsRemoved: []string{}, 440 } 441 // Add initial labels 442 for _, label := range tc.issueLabels { 443 fakeClient.AddLabel("org", "repo", 1, label) 444 } 445 e := &github.GenericCommentEvent{ 446 Action: github.GenericCommentActionCreated, 447 Body: tc.body, 448 Number: 1, 449 Repo: github.Repo{Owner: github.User{Login: "org"}, Name: "repo"}, 450 User: github.User{Login: tc.commenter}, 451 } 452 err := handle(fakeClient, logrus.WithField("plugin", pluginName), tc.extraLabels, e) 453 if err != nil { 454 t.Errorf("didn't expect error from label test: %v", err) 455 continue 456 } 457 458 // Check that all the correct labels (and only the correct labels) were added. 459 expectLabels := append(formatLabels(tc.issueLabels...), tc.expectedNewLabels...) 460 if expectLabels == nil { 461 expectLabels = []string{} 462 } 463 sort.Strings(expectLabels) 464 sort.Strings(fakeClient.LabelsAdded) 465 if !reflect.DeepEqual(expectLabels, fakeClient.LabelsAdded) { 466 t.Errorf("expected the labels %q to be added, but %q were added.", expectLabels, fakeClient.LabelsAdded) 467 } 468 469 sort.Strings(tc.expectedRemovedLabels) 470 sort.Strings(fakeClient.LabelsRemoved) 471 if !reflect.DeepEqual(tc.expectedRemovedLabels, fakeClient.LabelsRemoved) { 472 t.Errorf("expected the labels %q to be removed, but %q were removed.", tc.expectedRemovedLabels, fakeClient.LabelsRemoved) 473 } 474 if len(fakeClient.IssueCommentsAdded) > 0 && !tc.expectedBotComment { 475 t.Errorf("unexpected bot comments: %#v", fakeClient.IssueCommentsAdded) 476 } 477 if len(fakeClient.IssueCommentsAdded) == 0 && tc.expectedBotComment { 478 t.Error("expected a bot comment but got none") 479 } 480 } 481 }