sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/cla/cla_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 cla 18 19 import ( 20 "fmt" 21 "reflect" 22 "testing" 23 24 "github.com/sirupsen/logrus" 25 26 "sigs.k8s.io/prow/pkg/github" 27 "sigs.k8s.io/prow/pkg/github/fakegithub" 28 "sigs.k8s.io/prow/pkg/labels" 29 ) 30 31 func TestCLALabels(t *testing.T) { 32 var testcases = []struct { 33 name string 34 context string 35 state string 36 statusSHA string 37 issues []github.Issue 38 pullRequests []github.PullRequest 39 labels []string 40 addedLabels []string 41 removedLabels []string 42 }{ 43 { 44 name: "unrecognized status context has no effect", 45 context: "unknown", 46 state: "success", 47 addedLabels: nil, 48 removedLabels: nil, 49 }, 50 { 51 name: "EasyCLA status pending has no effect", 52 context: "EasyCLA", 53 state: "pending", 54 addedLabels: nil, 55 removedLabels: nil, 56 }, 57 { 58 name: "EasyCLA status success does not add/remove labels " + 59 "when not the head commit in a PR", 60 context: "EasyCLA", 61 state: "success", 62 statusSHA: "a", 63 issues: []github.Issue{ 64 {Number: 3, State: "open", Labels: []github.Label{}}, 65 }, 66 pullRequests: []github.PullRequest{ 67 {Number: 3, Head: github.PullRequestBranch{SHA: "b"}}, 68 }, 69 addedLabels: nil, 70 removedLabels: nil, 71 }, 72 { 73 name: "EasyCLA status failure does not add/remove labels " + 74 "when not the head commit in a PR", 75 context: "EasyCLA", 76 state: "failure", 77 statusSHA: "a", 78 issues: []github.Issue{ 79 {Number: 3, State: "open", Labels: []github.Label{{Name: labels.ClaYes}}}, 80 }, 81 pullRequests: []github.PullRequest{ 82 {Number: 3, Head: github.PullRequestBranch{SHA: "b"}}, 83 }, 84 addedLabels: nil, 85 removedLabels: nil, 86 }, 87 { 88 name: "EasyCLA status on head commit of PR adds the cla-yes label when its state is \"success\"", 89 context: "EasyCLA", 90 state: "success", 91 statusSHA: "a", 92 issues: []github.Issue{ 93 {Number: 3, State: "open", Labels: []github.Label{}}, 94 }, 95 pullRequests: []github.PullRequest{ 96 {Number: 3, Head: github.PullRequestBranch{SHA: "a"}}, 97 }, 98 addedLabels: []string{fmt.Sprintf("/#3:%s", labels.ClaYes)}, 99 removedLabels: nil, 100 }, 101 { 102 name: "EasyCLA status on head commit of PR does nothing when pending", 103 context: "EasyCLA", 104 state: "pending", 105 statusSHA: "a", 106 issues: []github.Issue{ 107 {Number: 3, State: "open", Labels: []github.Label{}}, 108 }, 109 pullRequests: []github.PullRequest{ 110 {Number: 3, Head: github.PullRequestBranch{SHA: "a"}}, 111 }, 112 addedLabels: nil, 113 removedLabels: nil, 114 }, 115 { 116 name: "EasyCLA status success removes \"cncf-cla: no\" label", 117 context: "EasyCLA", 118 state: "success", 119 statusSHA: "a", 120 issues: []github.Issue{ 121 {Number: 3, State: "open", Labels: []github.Label{{Name: labels.ClaNo}}}, 122 }, 123 pullRequests: []github.PullRequest{ 124 {Number: 3, Head: github.PullRequestBranch{SHA: "a"}}, 125 }, 126 addedLabels: []string{fmt.Sprintf("/#3:%s", labels.ClaYes)}, 127 removedLabels: []string{fmt.Sprintf("/#3:%s", labels.ClaNo)}, 128 }, 129 { 130 name: "EasyCLA status failure removes \"cncf-cla: yes\" label", 131 context: "EasyCLA", 132 state: "failure", 133 statusSHA: "a", 134 issues: []github.Issue{ 135 {Number: 3, State: "open", Labels: []github.Label{{Name: labels.ClaYes}}}, 136 }, 137 pullRequests: []github.PullRequest{ 138 {Number: 3, Head: github.PullRequestBranch{SHA: "a"}}, 139 }, 140 addedLabels: []string{fmt.Sprintf("/#3:%s", labels.ClaNo)}, 141 removedLabels: []string{fmt.Sprintf("/#3:%s", labels.ClaYes)}, 142 }, 143 } 144 for _, tc := range testcases { 145 pullRequests := make(map[int]*github.PullRequest) 146 for _, pr := range tc.pullRequests { 147 pr := pr 148 pullRequests[pr.Number] = &pr 149 } 150 151 issues := make(map[int]*github.Issue) 152 for _, issue := range tc.issues { 153 issue := issue 154 issues[issue.Number] = &issue 155 } 156 157 fc := fakegithub.NewFakeClient() 158 fc.PullRequests = pullRequests 159 fc.Issues = issues 160 fc.IssueComments = make(map[int][]github.IssueComment) 161 se := github.StatusEvent{ 162 Context: tc.context, 163 SHA: tc.statusSHA, 164 State: tc.state, 165 } 166 if err := handle(fc, logrus.WithField("plugin", pluginName), se); err != nil { 167 t.Errorf("For case %s, didn't expect error from cla plugin: %v", tc.name, err) 168 continue 169 } 170 171 if !reflect.DeepEqual(fc.IssueLabelsAdded, tc.addedLabels) { 172 t.Errorf("Expected: %#v, Got %#v in case %s.", tc.addedLabels, fc.IssueLabelsAdded, tc.name) 173 } 174 175 if !reflect.DeepEqual(fc.IssueLabelsRemoved, tc.removedLabels) { 176 t.Errorf("Expected: %#v, Got %#v in case %s.", tc.removedLabels, fc.IssueLabelsRemoved, tc.name) 177 } 178 } 179 } 180 181 func TestCheckCLA(t *testing.T) { 182 var testcases = []struct { 183 name string 184 context string 185 state string 186 issueState string 187 SHA string 188 action string 189 body string 190 pullRequests []github.PullRequest 191 hasCLAYes bool 192 hasCLANo bool 193 194 addedLabel string 195 removedLabel string 196 }{ 197 { 198 name: "ignore non EasyCLA context", 199 context: "random/context", 200 state: "success", 201 issueState: "open", 202 SHA: "sha", 203 action: "created", 204 body: "/check-cla", 205 pullRequests: []github.PullRequest{ 206 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 207 }, 208 }, 209 { 210 name: "ignore non open PRs", 211 context: "EasyCLA", 212 state: "success", 213 issueState: "closed", 214 SHA: "sha", 215 action: "created", 216 body: "/check-cla", 217 pullRequests: []github.PullRequest{ 218 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 219 }, 220 }, 221 { 222 name: "ignore non /check-cla comments", 223 context: "EasyCLA", 224 state: "success", 225 issueState: "open", 226 SHA: "sha", 227 action: "created", 228 body: "/shrug", 229 pullRequests: []github.PullRequest{ 230 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 231 }, 232 }, 233 { 234 name: "do nothing on when status state is \"pending\"", 235 context: "EasyCLA", 236 state: "pending", 237 issueState: "open", 238 SHA: "sha", 239 action: "created", 240 body: "/shrug", 241 pullRequests: []github.PullRequest{ 242 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 243 }, 244 }, 245 { 246 name: "EasyCLA status adds the cla-yes label when its state is \"success\"", 247 context: "EasyCLA", 248 state: "success", 249 issueState: "open", 250 SHA: "sha", 251 action: "created", 252 body: "/check-cla", 253 pullRequests: []github.PullRequest{ 254 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 255 }, 256 257 addedLabel: fmt.Sprintf("/#3:%s", labels.ClaYes), 258 }, 259 { 260 name: "EasyCLA status adds the cla-yes label and removes cla-no label when its state is \"success\"", 261 context: "EasyCLA", 262 state: "success", 263 issueState: "open", 264 SHA: "sha", 265 action: "created", 266 body: "/check-cla", 267 pullRequests: []github.PullRequest{ 268 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 269 }, 270 hasCLANo: true, 271 272 addedLabel: fmt.Sprintf("/#3:%s", labels.ClaYes), 273 removedLabel: fmt.Sprintf("/#3:%s", labels.ClaNo), 274 }, 275 { 276 name: "EasyCLA status adds the cla-no label when its state is \"failure\"", 277 context: "EasyCLA", 278 state: "failure", 279 issueState: "open", 280 SHA: "sha", 281 action: "created", 282 body: "/check-cla", 283 pullRequests: []github.PullRequest{ 284 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 285 }, 286 287 addedLabel: fmt.Sprintf("/#3:%s", labels.ClaNo), 288 }, 289 { 290 name: "EasyCLA status adds the cla-no label and removes cla-yes label when its state is \"failure\"", 291 context: "EasyCLA", 292 state: "failure", 293 issueState: "open", 294 SHA: "sha", 295 action: "created", 296 body: "/check-cla", 297 pullRequests: []github.PullRequest{ 298 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 299 }, 300 hasCLAYes: true, 301 302 addedLabel: fmt.Sprintf("/#3:%s", labels.ClaNo), 303 removedLabel: fmt.Sprintf("/#3:%s", labels.ClaYes), 304 }, 305 { 306 name: "EasyCLA status retains the cla-yes label and removes cla-no label when its state is \"success\"", 307 context: "EasyCLA", 308 state: "success", 309 issueState: "open", 310 SHA: "sha", 311 action: "created", 312 body: "/check-cla", 313 pullRequests: []github.PullRequest{ 314 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 315 }, 316 hasCLANo: true, 317 hasCLAYes: true, 318 319 removedLabel: fmt.Sprintf("/#3:%s", labels.ClaNo), 320 }, 321 { 322 name: "EasyCLA status retains the cla-no label and removes cla-yes label when its state is \"failure\"", 323 context: "EasyCLA", 324 state: "failure", 325 issueState: "open", 326 SHA: "sha", 327 action: "created", 328 body: "/check-cla", 329 pullRequests: []github.PullRequest{ 330 {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}}, 331 }, 332 hasCLANo: true, 333 hasCLAYes: true, 334 335 removedLabel: fmt.Sprintf("/#3:%s", labels.ClaYes), 336 }, 337 } 338 for _, tc := range testcases { 339 t.Run(tc.name, func(t *testing.T) { 340 pullRequests := make(map[int]*github.PullRequest) 341 for _, pr := range tc.pullRequests { 342 pr := pr 343 pullRequests[pr.Number] = &pr 344 } 345 fc := fakegithub.NewFakeClient() 346 fc.CreatedStatuses = make(map[string][]github.Status) 347 fc.PullRequests = pullRequests 348 e := &github.GenericCommentEvent{ 349 Action: github.GenericCommentEventAction(tc.action), 350 Body: tc.body, 351 Number: 3, 352 IssueState: tc.issueState, 353 } 354 fc.CombinedStatuses = map[string]*github.CombinedStatus{ 355 tc.SHA: { 356 Statuses: []github.Status{ 357 {State: tc.state, Context: tc.context}, 358 }, 359 }, 360 } 361 if tc.hasCLAYes { 362 fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", labels.ClaYes)) 363 } 364 if tc.hasCLANo { 365 fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", labels.ClaNo)) 366 } 367 if err := handleComment(fc, logrus.WithField("plugin", pluginName), e); err != nil { 368 t.Errorf("For case %s, didn't expect error from cla plugin: %v", tc.name, err) 369 } 370 ok := tc.addedLabel == "" 371 if !ok { 372 for _, label := range fc.IssueLabelsAdded { 373 if reflect.DeepEqual(tc.addedLabel, label) { 374 ok = true 375 break 376 } 377 } 378 } 379 if !ok { 380 t.Errorf("Expected to add: %#v, Got %#v in case %s.", tc.addedLabel, fc.IssueLabelsAdded, tc.name) 381 } 382 ok = tc.removedLabel == "" 383 if !ok { 384 for _, label := range fc.IssueLabelsRemoved { 385 if reflect.DeepEqual(tc.removedLabel, label) { 386 ok = true 387 break 388 } 389 } 390 } 391 if !ok { 392 t.Errorf("Expected to remove: %#v, Got %#v in case %s.", tc.removedLabel, fc.IssueLabelsRemoved, tc.name) 393 } 394 }) 395 } 396 }