github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/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  	"sort"
    22  	"testing"
    23  
    24  	"github.com/sirupsen/logrus"
    25  	"k8s.io/test-infra/prow/github"
    26  	"k8s.io/test-infra/prow/github/fakegithub"
    27  	"k8s.io/test-infra/prow/slack/fakeslack"
    28  )
    29  
    30  const (
    31  	fakeRepoOrg  = "fakeOrg"
    32  	fakeRepoName = "fakeName"
    33  	orgMember    = "Alice"
    34  	nonOrgMember = "Bob"
    35  	prNumber     = 1
    36  )
    37  
    38  func formatLabels(labels ...string) []string {
    39  	r := []string{}
    40  	for _, l := range labels {
    41  		r = append(r, fmt.Sprintf("%s/%s#%d:%s", fakeRepoOrg, fakeRepoName, prNumber, l))
    42  	}
    43  	if len(r) == 0 {
    44  		return nil
    45  	}
    46  	return r
    47  }
    48  
    49  func getFakeRepoIssueComment(commentBody, commenter string, repoLabels, issueLabels []string) (*fakegithub.FakeClient, assignEvent) {
    50  	fakeCli := &fakegithub.FakeClient{
    51  		IssueComments:  make(map[int][]github.IssueComment),
    52  		ExistingLabels: repoLabels,
    53  		OrgMembers:     []string{orgMember},
    54  	}
    55  
    56  	startingLabels := []github.Label{}
    57  	for _, label := range issueLabels {
    58  		startingLabels = append(startingLabels, github.Label{Name: label})
    59  	}
    60  
    61  	ice := github.IssueCommentEvent{
    62  		Repo: github.Repo{
    63  			Owner: github.User{Login: fakeRepoOrg},
    64  			Name:  fakeRepoName,
    65  		},
    66  		Comment: github.IssueComment{
    67  			Body: commentBody,
    68  			User: github.User{Login: commenter},
    69  		},
    70  		Issue: github.Issue{
    71  			User:        github.User{Login: "a"},
    72  			Number:      prNumber,
    73  			PullRequest: &struct{}{},
    74  			Labels:      startingLabels,
    75  		},
    76  	}
    77  
    78  	ae := assignEvent{
    79  		body:    ice.Comment.Body,
    80  		login:   ice.Comment.User.Login,
    81  		org:     ice.Repo.Owner.Login,
    82  		repo:    ice.Repo.Name,
    83  		url:     ice.Comment.HTMLURL,
    84  		number:  ice.Issue.Number,
    85  		issue:   ice.Issue,
    86  		comment: ice.Comment,
    87  	}
    88  
    89  	return fakeCli, ae
    90  }
    91  
    92  func getFakeRepoIssue(commentBody, creator string, repoLabels, issueLabels []string) (*fakegithub.FakeClient, assignEvent) {
    93  	fakeCli := &fakegithub.FakeClient{
    94  		Issues:         make([]github.Issue, 1),
    95  		IssueComments:  make(map[int][]github.IssueComment),
    96  		ExistingLabels: repoLabels,
    97  		OrgMembers:     []string{orgMember},
    98  	}
    99  
   100  	startingLabels := []github.Label{}
   101  	for _, label := range issueLabels {
   102  		startingLabels = append(startingLabels, github.Label{Name: label})
   103  	}
   104  
   105  	ie := github.IssueEvent{
   106  		Repo: github.Repo{
   107  			Owner: github.User{Login: fakeRepoOrg},
   108  			Name:  fakeRepoName,
   109  		},
   110  		Issue: github.Issue{
   111  			User:        github.User{Login: creator},
   112  			Number:      prNumber,
   113  			PullRequest: &struct{}{},
   114  			Body:        commentBody,
   115  			Labels:      startingLabels,
   116  		},
   117  	}
   118  
   119  	ae := assignEvent{
   120  		body:   ie.Issue.Body,
   121  		login:  ie.Issue.User.Login,
   122  		org:    ie.Repo.Owner.Login,
   123  		repo:   ie.Repo.Name,
   124  		url:    ie.Issue.HTMLURL,
   125  		number: ie.Issue.Number,
   126  		issue:  ie.Issue,
   127  		comment: github.IssueComment{
   128  			Body: ie.Issue.Body,
   129  			User: ie.Issue.User,
   130  		},
   131  	}
   132  
   133  	return fakeCli, ae
   134  }
   135  
   136  func getFakeRepoPullRequest(commentBody, commenter string, repoLabels, issueLabels []string) (*fakegithub.FakeClient, assignEvent) {
   137  	fakeCli := &fakegithub.FakeClient{
   138  		PullRequests:   make(map[int]*github.PullRequest),
   139  		IssueComments:  make(map[int][]github.IssueComment),
   140  		ExistingLabels: repoLabels,
   141  		OrgMembers:     []string{orgMember},
   142  	}
   143  
   144  	startingLabels := []github.Label{}
   145  	for _, label := range issueLabels {
   146  		startingLabels = append(startingLabels, github.Label{Name: label})
   147  	}
   148  
   149  	pre := github.PullRequestEvent{
   150  		PullRequest: github.PullRequest{
   151  			User:   github.User{Login: commenter},
   152  			Number: prNumber,
   153  			Base: github.PullRequestBranch{
   154  				Repo: github.Repo{
   155  					Owner: github.User{Login: fakeRepoOrg},
   156  					Name:  fakeRepoName,
   157  				},
   158  			},
   159  			Body: commentBody,
   160  			Head: github.PullRequestBranch{
   161  				Repo: github.Repo{
   162  					Owner: github.User{Login: fakeRepoOrg},
   163  					Name:  fakeRepoName,
   164  				},
   165  			},
   166  		},
   167  		Number: prNumber,
   168  	}
   169  
   170  	ae := assignEvent{
   171  		body:   pre.PullRequest.Body,
   172  		login:  pre.PullRequest.User.Login,
   173  		org:    pre.PullRequest.Base.Repo.Owner.Login,
   174  		repo:   pre.PullRequest.Base.Repo.Name,
   175  		url:    pre.PullRequest.HTMLURL,
   176  		number: pre.Number,
   177  		issue: github.Issue{
   178  			User:   pre.PullRequest.User,
   179  			Number: pre.Number,
   180  			Body:   pre.PullRequest.Body,
   181  			Labels: startingLabels,
   182  		},
   183  		comment: github.IssueComment{
   184  			Body: pre.PullRequest.Body,
   185  			User: pre.PullRequest.User,
   186  		},
   187  	}
   188  
   189  	return fakeCli, ae
   190  }
   191  
   192  func TestLabel(t *testing.T) {
   193  	// "a" is the author, "a", "r1", and "r2" are reviewers.
   194  
   195  	type testCase struct {
   196  		name                  string
   197  		body                  string
   198  		commenter             string
   199  		expectedNewLabels     []string
   200  		expectedRemovedLabels []string
   201  		repoLabels            []string
   202  		issueLabels           []string
   203  	}
   204  	testcases := []testCase{
   205  		{
   206  			name:                  "Irrelevant comment",
   207  			body:                  "irrelelvant",
   208  			expectedNewLabels:     []string{},
   209  			expectedRemovedLabels: []string{},
   210  			repoLabels:            []string{},
   211  			issueLabels:           []string{},
   212  			commenter:             orgMember,
   213  		},
   214  		{
   215  			name:                  "Empty Area",
   216  			body:                  "/area",
   217  			expectedNewLabels:     []string{},
   218  			expectedRemovedLabels: []string{},
   219  			repoLabels:            []string{},
   220  			issueLabels:           []string{"area/infra"},
   221  			commenter:             orgMember,
   222  		},
   223  		{
   224  			name:                  "Add Single Area Label",
   225  			body:                  "/area infra",
   226  			repoLabels:            []string{"area/infra"},
   227  			issueLabels:           []string{},
   228  			expectedNewLabels:     formatLabels("area/infra"),
   229  			expectedRemovedLabels: []string{},
   230  			commenter:             orgMember,
   231  		},
   232  		{
   233  			name:                  "Add Status Approved Label",
   234  			body:                  "/status approved-for-milestone ",
   235  			repoLabels:            []string{"status/approved-for-milestone"},
   236  			issueLabels:           []string{},
   237  			expectedNewLabels:     formatLabels("status/approved-for-milestone"),
   238  			expectedRemovedLabels: []string{},
   239  			commenter:             "sig-lead",
   240  		},
   241  		{
   242  			name:                  "Add Status In Progress Label",
   243  			body:                  "/status in-progress",
   244  			repoLabels:            []string{"status/in-progress"},
   245  			issueLabels:           []string{},
   246  			expectedNewLabels:     formatLabels("status/in-progress"),
   247  			expectedRemovedLabels: []string{},
   248  			commenter:             "sig-lead",
   249  		},
   250  		{
   251  			name:                  "Add Status In Review Label",
   252  			body:                  "/status in-review",
   253  			repoLabels:            []string{"status/in-review"},
   254  			issueLabels:           []string{},
   255  			expectedNewLabels:     formatLabels("status/in-review"),
   256  			expectedRemovedLabels: []string{},
   257  			commenter:             "sig-lead",
   258  		},
   259  		{
   260  			name:                  "Non sig lead can't add status/accepted-for-milestone",
   261  			body:                  "/status accepted-for-milestone",
   262  			repoLabels:            []string{"status/accepted-for-milestone"},
   263  			issueLabels:           []string{},
   264  			expectedNewLabels:     formatLabels(),
   265  			expectedRemovedLabels: []string{},
   266  			commenter:             "invalidLead",
   267  		},
   268  		{
   269  			name:                  "Non sig lead can't add status/in-review",
   270  			body:                  "/status in-review",
   271  			repoLabels:            []string{"status/in-review"},
   272  			issueLabels:           []string{},
   273  			expectedNewLabels:     formatLabels(),
   274  			expectedRemovedLabels: []string{},
   275  			commenter:             "invalidLead",
   276  		},
   277  		{
   278  			name:                  "Invalid Status Label Attempt",
   279  			body:                  "/status not-a-real-status",
   280  			repoLabels:            []string{"status/in-review"},
   281  			issueLabels:           []string{},
   282  			expectedNewLabels:     formatLabels(),
   283  			expectedRemovedLabels: []string{},
   284  			commenter:             "sig-lead",
   285  		},
   286  		{
   287  			name:                  "Add Single Area Label when already present on Issue",
   288  			body:                  "/area infra",
   289  			repoLabels:            []string{"area/infra"},
   290  			issueLabels:           []string{"area/infra"},
   291  			expectedNewLabels:     []string{},
   292  			expectedRemovedLabels: []string{},
   293  			commenter:             orgMember,
   294  		},
   295  		{
   296  			name:                  "Add Single Priority Label",
   297  			body:                  "/priority critical",
   298  			repoLabels:            []string{"area/infra", "priority/critical"},
   299  			issueLabels:           []string{},
   300  			expectedNewLabels:     formatLabels("priority/critical"),
   301  			expectedRemovedLabels: []string{},
   302  			commenter:             orgMember,
   303  		},
   304  		{
   305  			name:                  "Add Single Kind Label",
   306  			body:                  "/kind bug",
   307  			repoLabels:            []string{"area/infra", "priority/critical", "kind/bug"},
   308  			issueLabels:           []string{},
   309  			expectedNewLabels:     formatLabels("kind/bug"),
   310  			expectedRemovedLabels: []string{},
   311  			commenter:             orgMember,
   312  		},
   313  		{
   314  			name:                  "Adding Labels is Case Insensitive",
   315  			body:                  "/kind BuG",
   316  			repoLabels:            []string{"area/infra", "priority/critical", "kind/bug"},
   317  			issueLabels:           []string{},
   318  			expectedNewLabels:     formatLabels("kind/bug"),
   319  			expectedRemovedLabels: []string{},
   320  			commenter:             orgMember,
   321  		},
   322  		{
   323  			name:                  "Adding Labels is Case Insensitive",
   324  			body:                  "/kind bug",
   325  			repoLabels:            []string{"area/infra", "priority/critical", "kind/BUG"},
   326  			issueLabels:           []string{},
   327  			expectedNewLabels:     formatLabels("kind/BUG"),
   328  			expectedRemovedLabels: []string{},
   329  			commenter:             orgMember,
   330  		},
   331  		{
   332  			name:                  "Can't Add Non Existent Label",
   333  			body:                  "/priority critical",
   334  			repoLabels:            []string{"area/infra"},
   335  			issueLabels:           []string{},
   336  			expectedNewLabels:     formatLabels(),
   337  			expectedRemovedLabels: []string{},
   338  			commenter:             orgMember,
   339  		},
   340  		{
   341  			name:                  "Non Org Member Can't Add",
   342  			body:                  "/area infra",
   343  			repoLabels:            []string{"area/infra", "priority/critical", "kind/bug"},
   344  			issueLabels:           []string{},
   345  			expectedNewLabels:     formatLabels("area/infra"),
   346  			expectedRemovedLabels: []string{},
   347  			commenter:             nonOrgMember,
   348  		},
   349  		{
   350  			name:                  "Command must start at the beginning of the line",
   351  			body:                  "  /area infra",
   352  			repoLabels:            []string{"area/infra", "area/api", "priority/critical", "priority/urgent", "priority/important", "kind/bug"},
   353  			issueLabels:           []string{},
   354  			expectedNewLabels:     formatLabels(),
   355  			expectedRemovedLabels: []string{},
   356  			commenter:             orgMember,
   357  		},
   358  		{
   359  			name:                  "Can't Add Labels Non Existing Labels",
   360  			body:                  "/area lgtm",
   361  			repoLabels:            []string{"area/infra", "area/api", "priority/critical"},
   362  			issueLabels:           []string{},
   363  			expectedNewLabels:     formatLabels(),
   364  			expectedRemovedLabels: []string{},
   365  			commenter:             orgMember,
   366  		},
   367  		{
   368  			name:                  "Add Multiple Area Labels",
   369  			body:                  "/area api infra",
   370  			repoLabels:            []string{"area/infra", "area/api", "priority/critical", "priority/urgent"},
   371  			issueLabels:           []string{},
   372  			expectedNewLabels:     formatLabels("area/api", "area/infra"),
   373  			expectedRemovedLabels: []string{},
   374  			commenter:             orgMember,
   375  		},
   376  		{
   377  			name:                  "Add Multiple Area Labels one already present on Issue",
   378  			body:                  "/area api infra",
   379  			repoLabels:            []string{"area/infra", "area/api", "priority/critical", "priority/urgent"},
   380  			issueLabels:           []string{"area/api"},
   381  			expectedNewLabels:     formatLabels("area/infra"),
   382  			expectedRemovedLabels: []string{},
   383  			commenter:             orgMember,
   384  		},
   385  		{
   386  			name:                  "Add Multiple Priority Labels",
   387  			body:                  "/priority critical important",
   388  			repoLabels:            []string{"priority/critical", "priority/important"},
   389  			issueLabels:           []string{},
   390  			expectedNewLabels:     formatLabels("priority/critical", "priority/important"),
   391  			expectedRemovedLabels: []string{},
   392  			commenter:             orgMember,
   393  		},
   394  		{
   395  			name:                  "Label Prefix Must Match Command (Area-Priority Mismatch)",
   396  			body:                  "/area urgent",
   397  			repoLabels:            []string{"area/infra", "area/api", "priority/critical", "priority/urgent"},
   398  			issueLabels:           []string{},
   399  			expectedNewLabels:     formatLabels(),
   400  			expectedRemovedLabels: []string{},
   401  			commenter:             orgMember,
   402  		},
   403  		{
   404  			name:                  "Label Prefix Must Match Command (Priority-Area Mismatch)",
   405  			body:                  "/priority infra",
   406  			repoLabels:            []string{"area/infra", "area/api", "priority/critical", "priority/urgent"},
   407  			issueLabels:           []string{},
   408  			expectedNewLabels:     formatLabels(),
   409  			expectedRemovedLabels: []string{},
   410  			commenter:             orgMember,
   411  		},
   412  		{
   413  			name:                  "Add Multiple Labels (Some Valid)",
   414  			body:                  "/area lgtm infra",
   415  			repoLabels:            []string{"area/infra", "area/api"},
   416  			issueLabels:           []string{},
   417  			expectedNewLabels:     formatLabels("area/infra"),
   418  			expectedRemovedLabels: []string{},
   419  			commenter:             orgMember,
   420  		},
   421  		{
   422  			name:                  "Add Multiple Types of Labels Different Lines",
   423  			body:                  "/priority urgent\n/area infra",
   424  			repoLabels:            []string{"area/infra", "priority/urgent"},
   425  			issueLabels:           []string{},
   426  			expectedNewLabels:     formatLabels("priority/urgent", "area/infra"),
   427  			expectedRemovedLabels: []string{},
   428  			commenter:             orgMember,
   429  		},
   430  		{
   431  			name:                  "Infer One Sig Label",
   432  			body:                  "@kubernetes/sig-node-misc",
   433  			repoLabels:            []string{"area/infra", "priority/urgent", "sig/node"},
   434  			issueLabels:           []string{},
   435  			expectedNewLabels:     formatLabels("sig/node"),
   436  			expectedRemovedLabels: []string{},
   437  			commenter:             orgMember,
   438  		},
   439  		{
   440  			name:                  "Infer Multiple Sig Labels One Line",
   441  			body:                  "@kubernetes/sig-node-misc @kubernetes/sig-api-machinery-bugs",
   442  			repoLabels:            []string{"area/infra", "priority/urgent", "sig/node", "sig/api-machinery"},
   443  			issueLabels:           []string{},
   444  			expectedNewLabels:     formatLabels("sig/node", "sig/api-machinery"),
   445  			expectedRemovedLabels: []string{},
   446  			commenter:             orgMember,
   447  		},
   448  		{
   449  			name:                  "Infer Multiple Sig Labels Different Lines",
   450  			body:                  "@kubernetes/sig-node-misc\n@kubernetes/sig-api-machinery-bugs",
   451  			repoLabels:            []string{"area/infra", "priority/urgent", "sig/node", "sig/api-machinery"},
   452  			issueLabels:           []string{},
   453  			expectedNewLabels:     formatLabels("sig/node", "sig/api-machinery"),
   454  			expectedRemovedLabels: []string{},
   455  			commenter:             orgMember,
   456  		},
   457  		{
   458  			name:                  "Infer Multiple Sig Labels Different Lines With Other Text",
   459  			body:                  "Code Comment.  Design Review\n@kubernetes/sig-node-misc\ncc @kubernetes/sig-api-machinery-bugs",
   460  			repoLabels:            []string{"area/infra", "priority/urgent", "sig/node", "sig/api-machinery"},
   461  			issueLabels:           []string{},
   462  			expectedNewLabels:     formatLabels("sig/node", "sig/api-machinery"),
   463  			expectedRemovedLabels: []string{},
   464  			commenter:             orgMember,
   465  		},
   466  		{
   467  			name:                  "Add Area, Priority Labels and CC a Sig",
   468  			body:                  "/area infra\n/priority urgent Design Review\n@kubernetes/sig-node-misc\ncc @kubernetes/sig-api-machinery-bugs",
   469  			repoLabels:            []string{"area/infra", "priority/urgent", "sig/node", "sig/api-machinery"},
   470  			issueLabels:           []string{},
   471  			expectedNewLabels:     formatLabels("area/infra", "priority/urgent", "sig/node", "sig/api-machinery"),
   472  			expectedRemovedLabels: []string{},
   473  			commenter:             orgMember,
   474  		},
   475  		{
   476  			name:                  "Add SIG Label and CC a Sig",
   477  			body:                  "/sig testing\ncc @kubernetes/sig-api-machinery-misc\n",
   478  			repoLabels:            []string{"area/infra", "sig/testing", "sig/api-machinery"},
   479  			issueLabels:           []string{},
   480  			expectedNewLabels:     formatLabels("sig/testing", "sig/api-machinery"),
   481  			expectedRemovedLabels: []string{},
   482  			commenter:             orgMember,
   483  		},
   484  		{
   485  			name:                  "Remove Area Label when no such Label on Repo",
   486  			body:                  "/remove-area infra",
   487  			repoLabels:            []string{},
   488  			issueLabels:           []string{},
   489  			expectedNewLabels:     []string{},
   490  			expectedRemovedLabels: []string{},
   491  			commenter:             orgMember,
   492  		},
   493  		{
   494  			name:                  "Remove Area Label when no such Label on Issue",
   495  			body:                  "/remove-area infra",
   496  			repoLabels:            []string{"area/infra"},
   497  			issueLabels:           []string{},
   498  			expectedNewLabels:     []string{},
   499  			expectedRemovedLabels: []string{},
   500  			commenter:             orgMember,
   501  		},
   502  		{
   503  			name:                  "Remove Area Label",
   504  			body:                  "/remove-area infra",
   505  			repoLabels:            []string{"area/infra"},
   506  			issueLabels:           []string{"area/infra"},
   507  			expectedNewLabels:     []string{},
   508  			expectedRemovedLabels: formatLabels("area/infra"),
   509  			commenter:             orgMember,
   510  		},
   511  		{
   512  			name:                  "Remove Kind Label",
   513  			body:                  "/remove-kind api-server",
   514  			repoLabels:            []string{"area/infra", "priority/high", "kind/api-server"},
   515  			issueLabels:           []string{"area/infra", "priority/high", "kind/api-server"},
   516  			expectedNewLabels:     []string{},
   517  			expectedRemovedLabels: formatLabels("kind/api-server"),
   518  			commenter:             orgMember,
   519  		},
   520  		{
   521  			name:                  "Remove Priority Label",
   522  			body:                  "/remove-priority high",
   523  			repoLabels:            []string{"area/infra", "priority/high"},
   524  			issueLabels:           []string{"area/infra", "priority/high"},
   525  			expectedNewLabels:     []string{},
   526  			expectedRemovedLabels: formatLabels("priority/high"),
   527  			commenter:             orgMember,
   528  		},
   529  		{
   530  			name:                  "Remove SIG Label",
   531  			body:                  "/remove-sig testing",
   532  			repoLabels:            []string{"area/infra", "sig/testing"},
   533  			issueLabels:           []string{"area/infra", "sig/testing"},
   534  			expectedNewLabels:     []string{},
   535  			expectedRemovedLabels: formatLabels("sig/testing"),
   536  			commenter:             orgMember,
   537  		},
   538  		{
   539  			name:                  "Remove Multiple Labels",
   540  			body:                  "/remove-priority low high\n/remove-kind api-server\n/remove-area  infra",
   541  			repoLabels:            []string{"area/infra", "priority/high", "priority/low", "kind/api-server"},
   542  			issueLabels:           []string{"area/infra", "priority/high", "priority/low", "kind/api-server"},
   543  			expectedNewLabels:     []string{},
   544  			expectedRemovedLabels: formatLabels("priority/low", "priority/high", "kind/api-server", "area/infra"),
   545  			commenter:             orgMember,
   546  		},
   547  		{
   548  			name:                  "Add and Remove Label at the same time",
   549  			body:                  "/remove-area infra\n/area test",
   550  			repoLabels:            []string{"area/infra", "area/test"},
   551  			issueLabels:           []string{"area/infra"},
   552  			expectedNewLabels:     formatLabels("area/test"),
   553  			expectedRemovedLabels: formatLabels("area/infra"),
   554  			commenter:             orgMember,
   555  		},
   556  		{
   557  			name:                  "Add and Remove the same Label",
   558  			body:                  "/remove-area infra\n/area infra",
   559  			repoLabels:            []string{"area/infra"},
   560  			issueLabels:           []string{"area/infra"},
   561  			expectedNewLabels:     []string{},
   562  			expectedRemovedLabels: formatLabels("area/infra"),
   563  			commenter:             orgMember,
   564  		},
   565  		{
   566  			name:                  "Multiple Add and Delete Labels",
   567  			body:                  "/remove-area ruby\n/remove-kind srv\n/remove-priority l m\n/area go\n/kind cli\n/priority h",
   568  			repoLabels:            []string{"area/go", "area/ruby", "kind/cli", "kind/srv", "priority/h", "priority/m", "priority/l"},
   569  			issueLabels:           []string{"area/ruby", "kind/srv", "priority/l", "priority/m"},
   570  			expectedNewLabels:     formatLabels("area/go", "kind/cli", "priority/h"),
   571  			expectedRemovedLabels: formatLabels("area/ruby", "kind/srv", "priority/l", "priority/m"),
   572  			commenter:             orgMember,
   573  		},
   574  	}
   575  
   576  	fakeRepoFunctions := []func(string, string, []string, []string) (*fakegithub.FakeClient, assignEvent){
   577  		getFakeRepoIssueComment,
   578  		getFakeRepoIssue,
   579  		getFakeRepoPullRequest,
   580  	}
   581  
   582  	for _, tc := range testcases {
   583  		sort.Strings(tc.expectedNewLabels)
   584  
   585  		for i := 0; i < len(fakeRepoFunctions); i++ {
   586  			fakeClient, ae := fakeRepoFunctions[i](tc.body, tc.commenter, tc.repoLabels, tc.issueLabels)
   587  			fakeMilestoneId := 123456
   588  			fakeSlackClient := &fakeslack.FakeClient{
   589  				SentMessages: make(map[string][]string),
   590  			}
   591  			err := handle(fakeClient, logrus.WithField("plugin", pluginName), ae, fakeSlackClient, fakeMilestoneId)
   592  			if err != nil {
   593  				t.Errorf("For case %s, didn't expect error from label test: %v", tc.name, err)
   594  				return
   595  			}
   596  
   597  			if len(tc.expectedNewLabels) != len(fakeClient.LabelsAdded) {
   598  				t.Errorf("For test %v,\n\tExpected %+v \n\tFound %+v", tc.name, tc.expectedNewLabels, fakeClient.LabelsAdded)
   599  				return
   600  			}
   601  
   602  			sort.Strings(fakeClient.LabelsAdded)
   603  
   604  			for i := range tc.expectedNewLabels {
   605  				if tc.expectedNewLabels[i] != fakeClient.LabelsAdded[i] {
   606  					t.Errorf("For test %v,\n\tExpected %+v \n\tFound %+v", tc.name, tc.expectedNewLabels, fakeClient.LabelsAdded)
   607  					break
   608  				}
   609  			}
   610  
   611  			if len(tc.expectedRemovedLabels) != len(fakeClient.LabelsRemoved) {
   612  				t.Errorf("For test %v,\n\tExpected Removed %+v \n\tFound %+v", tc.name, tc.expectedRemovedLabels, fakeClient.LabelsRemoved)
   613  				return
   614  			}
   615  
   616  			for i := range tc.expectedRemovedLabels {
   617  				if tc.expectedRemovedLabels[i] != fakeClient.LabelsRemoved[i] {
   618  					t.Errorf("For test %v,\n\tExpected %+v \n\tFound %+v", tc.name, tc.expectedRemovedLabels, fakeClient.LabelsRemoved)
   619  					break
   620  				}
   621  			}
   622  		}
   623  	}
   624  }
   625  
   626  //Make sure we are repeating sig mentions for non org members (and only non org members)
   627  func TestRepeat(t *testing.T) {
   628  
   629  	type testCase struct {
   630  		name                   string
   631  		body                   string
   632  		commenter              string
   633  		expectedRepeatedLabels []string
   634  		issueLabels            []string
   635  		repoLabels             []string
   636  	}
   637  	testcases := []testCase{
   638  		{
   639  			name: "Dont repeat when org member adds one sig label",
   640  			body: "@kubernetes/sig-node-misc",
   641  			expectedRepeatedLabels: []string{},
   642  			repoLabels:             []string{"area/infra", "priority/urgent", "sig/node"},
   643  			issueLabels:            []string{},
   644  			commenter:              orgMember,
   645  		},
   646  		{
   647  			name: "Repeat when non org adds one sig label",
   648  			body: "@kubernetes/sig-node-misc",
   649  			expectedRepeatedLabels: []string{"@kubernetes/sig-node-misc"},
   650  			repoLabels:             []string{"area/infra", "priority/urgent", "sig/node", "sig/node"},
   651  			issueLabels:            []string{},
   652  			commenter:              nonOrgMember,
   653  		},
   654  		{
   655  			name: "Don't repeat non existent labels",
   656  			body: "@kubernetes/sig-node-misc @kubernetes/sig-api-machinery-bugs",
   657  			expectedRepeatedLabels: []string{},
   658  			repoLabels:             []string{},
   659  			issueLabels:            []string{},
   660  			commenter:              nonOrgMember,
   661  		},
   662  		{
   663  			name: "Dont repeat multiple if org member",
   664  			body: "@kubernetes/sig-node-misc @kubernetes/sig-api-machinery-bugs",
   665  			expectedRepeatedLabels: []string{},
   666  			repoLabels:             []string{"sig/node", "sig/api-machinery"},
   667  			issueLabels:            []string{},
   668  			commenter:              orgMember,
   669  		},
   670  		{
   671  			name: "Repeat multiple valid labels from non org member",
   672  			body: "@kubernetes/sig-node-misc @kubernetes/sig-api-machinery-bugs",
   673  			expectedRepeatedLabels: []string{"@kubernetes/sig-node-misc", "@kubernetes/sig-api-machinery-bugs"},
   674  			repoLabels:             []string{"sig/node", "sig/api-machinery"},
   675  			issueLabels:            []string{},
   676  			commenter:              nonOrgMember,
   677  		},
   678  		{
   679  			name: "Repeat multiple valid labels with a line break from non org member.",
   680  			body: "@kubernetes/sig-node-misc\n@kubernetes/sig-api-machinery-bugs",
   681  			expectedRepeatedLabels: []string{"@kubernetes/sig-node-misc", "@kubernetes/sig-api-machinery-bugs"},
   682  			repoLabels:             []string{"sig/node", "sig/api-machinery"},
   683  			issueLabels:            []string{},
   684  			commenter:              nonOrgMember,
   685  		},
   686  		{
   687  			name: "Repeat Multiple Sig Labels Different Lines With Other Text",
   688  			body: "Code Comment.  Design Review\n@kubernetes/sig-node-misc\ncc @kubernetes/sig-api-machinery-bugs",
   689  			expectedRepeatedLabels: []string{"@kubernetes/sig-node-misc", "@kubernetes/sig-api-machinery-bugs"},
   690  			repoLabels:             []string{"area/infra", "priority/urgent", "sig/node", "sig/api-machinery"},
   691  			issueLabels:            []string{},
   692  			commenter:              nonOrgMember,
   693  		},
   694  		{
   695  			name: "Repeat when multiple label adding commands",
   696  			body: "/area infra\n/priority urgent Design Review\n@kubernetes/sig-node-misc\ncc @kubernetes/sig-api-machinery-bugs",
   697  			expectedRepeatedLabels: []string{"@kubernetes/sig-node-misc", "@kubernetes/sig-api-machinery-bugs"},
   698  			repoLabels:             []string{"area/infra", "priority/urgent", "sig/node", "sig/api-machinery"},
   699  			issueLabels:            []string{},
   700  			commenter:              nonOrgMember,
   701  		},
   702  	}
   703  
   704  	//Test that this functionality works on comments, newly opened issues and newly opened PRs
   705  	fakeRepoFunctions := []func(string, string, []string, []string) (*fakegithub.FakeClient, assignEvent){
   706  		getFakeRepoIssueComment,
   707  		getFakeRepoIssue,
   708  		getFakeRepoPullRequest,
   709  	}
   710  
   711  	for _, tc := range testcases {
   712  		sort.Strings(tc.expectedRepeatedLabels)
   713  
   714  		for i := 0; i < len(fakeRepoFunctions); i++ {
   715  			fakeClient, ae := fakeRepoFunctions[i](tc.body, tc.commenter, tc.repoLabels, tc.issueLabels)
   716  			m := map[string]string{}
   717  			for _, l := range tc.repoLabels {
   718  				m[l] = ""
   719  			}
   720  
   721  			member, _ := fakeClient.IsMember(ae.org, ae.login)
   722  			toRepeat := []string{}
   723  			if !member {
   724  				toRepeat = ae.getRepeats(sigMatcher.FindAllStringSubmatch(tc.body, -1), m)
   725  			}
   726  
   727  			sort.Strings(toRepeat)
   728  			if len(tc.expectedRepeatedLabels) != len(toRepeat) {
   729  				t.Errorf("For test %v and case %v,\n\tExpected %+v \n\tFound %+v", tc.name, i, tc.expectedRepeatedLabels, toRepeat)
   730  				continue
   731  			}
   732  
   733  			for i := range tc.expectedRepeatedLabels {
   734  				if tc.expectedRepeatedLabels[i] != toRepeat[i] {
   735  					t.Errorf("For test %v,\n\tExpected %+v \n\tFound %+v", tc.name, tc.expectedRepeatedLabels, toRepeat)
   736  					break
   737  				}
   738  			}
   739  
   740  		}
   741  	}
   742  }