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