github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/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  	"k8s.io/test-infra/prow/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:          "cla/linuxfoundation status pending has no effect",
    52  			context:       "cla/linuxfoundation",
    53  			state:         "pending",
    54  			addedLabels:   nil,
    55  			removedLabels: nil,
    56  		},
    57  		{
    58  			name: "cla/linuxfoundation status success does not add/remove labels " +
    59  				"when not the head commit in a PR",
    60  			context:   "cla/linuxfoundation",
    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: "cla/linuxfoundation status failure does not add/remove labels " +
    74  				"when not the head commit in a PR",
    75  			context:   "cla/linuxfoundation",
    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:      "cla/linuxfoundation status on head commit of PR adds the cla-yes label when its state is \"success\"",
    89  			context:   "cla/linuxfoundation",
    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:      "cla/linuxfoundation status on head commit of PR does nothing when pending",
   103  			context:   "cla/linuxfoundation",
   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:      "cla/linuxfoundation status success removes \"cncf-cla: no\" label",
   117  			context:   "cla/linuxfoundation",
   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:      "cla/linuxfoundation status failure removes \"cncf-cla: yes\" label",
   131  			context:   "cla/linuxfoundation",
   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  			pullRequests[pr.Number] = &pr
   148  		}
   149  
   150  		fc := &fakegithub.FakeClient{
   151  			PullRequests:  pullRequests,
   152  			Issues:        tc.issues,
   153  			IssueComments: make(map[int][]github.IssueComment),
   154  		}
   155  		se := github.StatusEvent{
   156  			Context: tc.context,
   157  			SHA:     tc.statusSHA,
   158  			State:   tc.state,
   159  		}
   160  		if err := handle(fc, logrus.WithField("plugin", pluginName), se); err != nil {
   161  			t.Errorf("For case %s, didn't expect error from cla plugin: %v", tc.name, err)
   162  			continue
   163  		}
   164  
   165  		if !reflect.DeepEqual(fc.IssueLabelsAdded, tc.addedLabels) {
   166  			t.Errorf("Expected: %#v, Got %#v in case %s.", tc.addedLabels, fc.IssueLabelsAdded, tc.name)
   167  		}
   168  
   169  		if !reflect.DeepEqual(fc.IssueLabelsRemoved, tc.removedLabels) {
   170  			t.Errorf("Expected: %#v, Got %#v in case %s.", tc.removedLabels, fc.IssueLabelsRemoved, tc.name)
   171  		}
   172  	}
   173  }
   174  
   175  func TestCheckCLA(t *testing.T) {
   176  	var testcases = []struct {
   177  		name         string
   178  		context      string
   179  		state        string
   180  		issueState   string
   181  		SHA          string
   182  		action       string
   183  		body         string
   184  		pullRequests []github.PullRequest
   185  		hasCLAYes    bool
   186  		hasCLANo     bool
   187  
   188  		addedLabel   string
   189  		removedLabel string
   190  	}{
   191  		{
   192  			name:       "ignore non cla/linuxfoundation context",
   193  			context:    "random/context",
   194  			state:      "success",
   195  			issueState: "open",
   196  			SHA:        "sha",
   197  			action:     "created",
   198  			body:       "/check-cla",
   199  			pullRequests: []github.PullRequest{
   200  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   201  			},
   202  		},
   203  		{
   204  			name:       "ignore non open PRs",
   205  			context:    "cla/linuxfoundation",
   206  			state:      "success",
   207  			issueState: "closed",
   208  			SHA:        "sha",
   209  			action:     "created",
   210  			body:       "/check-cla",
   211  			pullRequests: []github.PullRequest{
   212  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   213  			},
   214  		},
   215  		{
   216  			name:       "ignore non /check-cla comments",
   217  			context:    "cla/linuxfoundation",
   218  			state:      "success",
   219  			issueState: "open",
   220  			SHA:        "sha",
   221  			action:     "created",
   222  			body:       "/shrug",
   223  			pullRequests: []github.PullRequest{
   224  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   225  			},
   226  		},
   227  		{
   228  			name:       "do nothing on when status state is \"pending\"",
   229  			context:    "cla/linuxfoundation",
   230  			state:      "pending",
   231  			issueState: "open",
   232  			SHA:        "sha",
   233  			action:     "created",
   234  			body:       "/shrug",
   235  			pullRequests: []github.PullRequest{
   236  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   237  			},
   238  		},
   239  		{
   240  			name:       "cla/linuxfoundation status adds the cla-yes label when its state is \"success\"",
   241  			context:    "cla/linuxfoundation",
   242  			state:      "success",
   243  			issueState: "open",
   244  			SHA:        "sha",
   245  			action:     "created",
   246  			body:       "/check-cla",
   247  			pullRequests: []github.PullRequest{
   248  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   249  			},
   250  
   251  			addedLabel: fmt.Sprintf("/#3:%s", labels.ClaYes),
   252  		},
   253  		{
   254  			name:       "cla/linuxfoundation status adds the cla-yes label and removes cla-no label when its state is \"success\"",
   255  			context:    "cla/linuxfoundation",
   256  			state:      "success",
   257  			issueState: "open",
   258  			SHA:        "sha",
   259  			action:     "created",
   260  			body:       "/check-cla",
   261  			pullRequests: []github.PullRequest{
   262  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   263  			},
   264  			hasCLANo: true,
   265  
   266  			addedLabel:   fmt.Sprintf("/#3:%s", labels.ClaYes),
   267  			removedLabel: fmt.Sprintf("/#3:%s", labels.ClaNo),
   268  		},
   269  		{
   270  			name:       "cla/linuxfoundation status adds the cla-no label when its state is \"failure\"",
   271  			context:    "cla/linuxfoundation",
   272  			state:      "failure",
   273  			issueState: "open",
   274  			SHA:        "sha",
   275  			action:     "created",
   276  			body:       "/check-cla",
   277  			pullRequests: []github.PullRequest{
   278  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   279  			},
   280  
   281  			addedLabel: fmt.Sprintf("/#3:%s", labels.ClaNo),
   282  		},
   283  		{
   284  			name:       "cla/linuxfoundation status adds the cla-no label and removes cla-yes label when its state is \"failure\"",
   285  			context:    "cla/linuxfoundation",
   286  			state:      "failure",
   287  			issueState: "open",
   288  			SHA:        "sha",
   289  			action:     "created",
   290  			body:       "/check-cla",
   291  			pullRequests: []github.PullRequest{
   292  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   293  			},
   294  			hasCLAYes: true,
   295  
   296  			addedLabel:   fmt.Sprintf("/#3:%s", labels.ClaNo),
   297  			removedLabel: fmt.Sprintf("/#3:%s", labels.ClaYes),
   298  		},
   299  		{
   300  			name:       "cla/linuxfoundation status retains the cla-yes label and removes cla-no label when its state is \"success\"",
   301  			context:    "cla/linuxfoundation",
   302  			state:      "success",
   303  			issueState: "open",
   304  			SHA:        "sha",
   305  			action:     "created",
   306  			body:       "/check-cla",
   307  			pullRequests: []github.PullRequest{
   308  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   309  			},
   310  			hasCLANo:  true,
   311  			hasCLAYes: true,
   312  
   313  			removedLabel: fmt.Sprintf("/#3:%s", labels.ClaNo),
   314  		},
   315  		{
   316  			name:       "cla/linuxfoundation status retains the cla-no label and removes cla-yes label when its state is \"failure\"",
   317  			context:    "cla/linuxfoundation",
   318  			state:      "failure",
   319  			issueState: "open",
   320  			SHA:        "sha",
   321  			action:     "created",
   322  			body:       "/check-cla",
   323  			pullRequests: []github.PullRequest{
   324  				{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   325  			},
   326  			hasCLANo:  true,
   327  			hasCLAYes: true,
   328  
   329  			removedLabel: fmt.Sprintf("/#3:%s", labels.ClaYes),
   330  		},
   331  	}
   332  	for _, tc := range testcases {
   333  		t.Run(tc.name, func(t *testing.T) {
   334  			pullRequests := make(map[int]*github.PullRequest)
   335  			for _, pr := range tc.pullRequests {
   336  				pullRequests[pr.Number] = &pr
   337  			}
   338  			fc := &fakegithub.FakeClient{
   339  				CreatedStatuses: make(map[string][]github.Status),
   340  				PullRequests:    pullRequests,
   341  			}
   342  			e := &github.GenericCommentEvent{
   343  				Action:     github.GenericCommentEventAction(tc.action),
   344  				Body:       tc.body,
   345  				Number:     3,
   346  				IssueState: tc.issueState,
   347  			}
   348  			fc.CreatedStatuses["sha"] = []github.Status{
   349  				{
   350  					State:   tc.state,
   351  					Context: tc.context,
   352  				},
   353  			}
   354  			if tc.hasCLAYes {
   355  				fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", labels.ClaYes))
   356  			}
   357  			if tc.hasCLANo {
   358  				fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", labels.ClaNo))
   359  			}
   360  			if err := handleComment(fc, logrus.WithField("plugin", pluginName), e); err != nil {
   361  				t.Errorf("For case %s, didn't expect error from cla plugin: %v", tc.name, err)
   362  			}
   363  			ok := tc.addedLabel == ""
   364  			if !ok {
   365  				for _, label := range fc.IssueLabelsAdded {
   366  					if reflect.DeepEqual(tc.addedLabel, label) {
   367  						ok = true
   368  						break
   369  					}
   370  				}
   371  			}
   372  			if !ok {
   373  				t.Errorf("Expected to add: %#v, Got %#v in case %s.", tc.addedLabel, fc.IssueLabelsAdded, tc.name)
   374  			}
   375  			ok = tc.removedLabel == ""
   376  			if !ok {
   377  				for _, label := range fc.IssueLabelsRemoved {
   378  					if reflect.DeepEqual(tc.removedLabel, label) {
   379  						ok = true
   380  						break
   381  					}
   382  				}
   383  			}
   384  			if !ok {
   385  				t.Errorf("Expected to remove: %#v, Got %#v in case %s.", tc.removedLabel, fc.IssueLabelsRemoved, tc.name)
   386  			}
   387  		})
   388  	}
   389  }