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