sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/owners-label/owners-label_test.go (about)

     1  /*
     2  Copyright 2018 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 ownerslabel
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"sort"
    23  	"testing"
    24  
    25  	"github.com/sirupsen/logrus"
    26  
    27  	"k8s.io/apimachinery/pkg/util/sets"
    28  	"sigs.k8s.io/prow/pkg/github"
    29  	"sigs.k8s.io/prow/pkg/github/fakegithub"
    30  	"sigs.k8s.io/prow/pkg/labels"
    31  )
    32  
    33  func formatLabels(labels ...string) []string {
    34  	r := []string{}
    35  	for _, l := range labels {
    36  		r = append(r, fmt.Sprintf("%s/%s#%d:%s", "org", "repo", 1, l))
    37  	}
    38  	if len(r) == 0 {
    39  		return nil
    40  	}
    41  	return r
    42  }
    43  
    44  type fakeOwnersClient struct {
    45  	labels map[string]sets.Set[string]
    46  }
    47  
    48  func (foc *fakeOwnersClient) FindLabelsForFile(path string) sets.Set[string] {
    49  	return foc.labels[path]
    50  }
    51  
    52  // TestHandle tests that the handle function requests reviews from the correct number of unique users.
    53  func TestHandle(t *testing.T) {
    54  	foc := &fakeOwnersClient{
    55  		labels: map[string]sets.Set[string]{
    56  			"a.go": sets.New[string](labels.LGTM, labels.Approved, "kind/docs"),
    57  			"b.go": sets.New[string](labels.LGTM),
    58  			"c.go": sets.New[string](labels.LGTM, "dnm/frozen-docs"),
    59  			"d.sh": sets.New[string]("dnm/bash"),
    60  			"e.sh": sets.New[string]("dnm/bash"),
    61  		},
    62  	}
    63  
    64  	type testCase struct {
    65  		name              string
    66  		filesChanged      []string
    67  		expectedNewLabels []string
    68  		repoLabels        []string
    69  		issueLabels       []string
    70  	}
    71  	testcases := []testCase{
    72  		{
    73  			name:              "no labels",
    74  			filesChanged:      []string{"other.go", "something.go"},
    75  			expectedNewLabels: []string{},
    76  			repoLabels:        []string{},
    77  			issueLabels:       []string{},
    78  		},
    79  		{
    80  			name:              "1 file 1 label",
    81  			filesChanged:      []string{"b.go"},
    82  			expectedNewLabels: formatLabels(labels.LGTM),
    83  			repoLabels:        []string{labels.LGTM},
    84  			issueLabels:       []string{},
    85  		},
    86  		{
    87  			name:              "1 file 3 labels",
    88  			filesChanged:      []string{"a.go"},
    89  			expectedNewLabels: formatLabels(labels.LGTM, labels.Approved, "kind/docs"),
    90  			repoLabels:        []string{labels.LGTM, labels.Approved, "kind/docs"},
    91  			issueLabels:       []string{},
    92  		},
    93  		{
    94  			name:              "2 files no overlap",
    95  			filesChanged:      []string{"c.go", "d.sh"},
    96  			expectedNewLabels: formatLabels(labels.LGTM, "dnm/frozen-docs", "dnm/bash"),
    97  			repoLabels:        []string{labels.LGTM, "dnm/frozen-docs", "dnm/bash"},
    98  			issueLabels:       []string{},
    99  		},
   100  		{
   101  			name:              "2 files partial overlap",
   102  			filesChanged:      []string{"a.go", "b.go"},
   103  			expectedNewLabels: formatLabels(labels.LGTM, labels.Approved, "kind/docs"),
   104  			repoLabels:        []string{labels.LGTM, labels.Approved, "kind/docs"},
   105  			issueLabels:       []string{},
   106  		},
   107  		{
   108  			name:              "2 files complete overlap",
   109  			filesChanged:      []string{"d.sh", "e.sh"},
   110  			expectedNewLabels: formatLabels("dnm/bash"),
   111  			repoLabels:        []string{"dnm/bash"},
   112  			issueLabels:       []string{},
   113  		},
   114  		{
   115  			name:              "3 files partial overlap",
   116  			filesChanged:      []string{"a.go", "b.go", "c.go"},
   117  			expectedNewLabels: formatLabels(labels.LGTM, labels.Approved, "kind/docs", "dnm/frozen-docs"),
   118  			repoLabels:        []string{labels.LGTM, labels.Approved, "kind/docs", "dnm/frozen-docs"},
   119  			issueLabels:       []string{},
   120  		},
   121  		{
   122  			name:              "no labels to add, initial unrelated label",
   123  			filesChanged:      []string{"other.go", "something.go"},
   124  			expectedNewLabels: []string{},
   125  			repoLabels:        []string{labels.LGTM},
   126  			issueLabels:       []string{labels.LGTM},
   127  		},
   128  		{
   129  			name:              "1 file 1 label, already present",
   130  			filesChanged:      []string{"b.go"},
   131  			expectedNewLabels: []string{},
   132  			repoLabels:        []string{labels.LGTM},
   133  			issueLabels:       []string{labels.LGTM},
   134  		},
   135  		{
   136  			name:              "1 file 1 label, doesn't exist on the repo",
   137  			filesChanged:      []string{"b.go"},
   138  			expectedNewLabels: []string{},
   139  			repoLabels:        []string{labels.Approved},
   140  			issueLabels:       []string{},
   141  		},
   142  		{
   143  			name:              "2 files no overlap, 1 label already present",
   144  			filesChanged:      []string{"c.go", "d.sh"},
   145  			expectedNewLabels: formatLabels(labels.LGTM, "dnm/frozen-docs"),
   146  			repoLabels:        []string{"dnm/bash", labels.Approved, labels.LGTM, "dnm/frozen-docs"},
   147  			issueLabels:       []string{"dnm/bash", labels.Approved},
   148  		},
   149  		{
   150  			name:              "2 files complete overlap, label already present",
   151  			filesChanged:      []string{"d.sh", "e.sh"},
   152  			expectedNewLabels: []string{},
   153  			repoLabels:        []string{"dnm/bash"},
   154  			issueLabels:       []string{"dnm/bash"},
   155  		},
   156  	}
   157  
   158  	for _, tc := range testcases {
   159  		basicPR := github.PullRequest{
   160  			Number: 1,
   161  			Base: github.PullRequestBranch{
   162  				Repo: github.Repo{
   163  					Owner: github.User{
   164  						Login: "org",
   165  					},
   166  					Name: "repo",
   167  				},
   168  			},
   169  			User: github.User{
   170  				Login: "user",
   171  			},
   172  		}
   173  
   174  		t.Logf("Running scenario %q", tc.name)
   175  		sort.Strings(tc.expectedNewLabels)
   176  		changes := make([]github.PullRequestChange, 0, len(tc.filesChanged))
   177  		for _, name := range tc.filesChanged {
   178  			changes = append(changes, github.PullRequestChange{Filename: name})
   179  		}
   180  		fghc := fakegithub.NewFakeClient()
   181  		fghc.PullRequests = map[int]*github.PullRequest{
   182  			basicPR.Number: &basicPR,
   183  		}
   184  		fghc.PullRequestChanges = map[int][]github.PullRequestChange{
   185  			basicPR.Number: changes,
   186  		}
   187  		fghc.RepoLabelsExisting = tc.repoLabels
   188  		fghc.IssueLabelsAdded = []string{}
   189  		// Add initial labels
   190  		for _, label := range tc.issueLabels {
   191  			fghc.AddLabel(basicPR.Base.Repo.Owner.Login, basicPR.Base.Repo.Name, basicPR.Number, label)
   192  		}
   193  		pre := &github.PullRequestEvent{
   194  			Action:      github.PullRequestActionOpened,
   195  			Number:      basicPR.Number,
   196  			PullRequest: basicPR,
   197  			Repo:        basicPR.Base.Repo,
   198  		}
   199  
   200  		err := handle(fghc, foc, logrus.WithField("plugin", PluginName), pre)
   201  		if err != nil {
   202  			t.Errorf("[%s] unexpected error from handle: %v", tc.name, err)
   203  			continue
   204  		}
   205  
   206  		// Check that all the correct labels (and only the correct labels) were added.
   207  		expectLabels := append(formatLabels(tc.issueLabels...), tc.expectedNewLabels...)
   208  		if expectLabels == nil {
   209  			expectLabels = []string{}
   210  		}
   211  		sort.Strings(expectLabels)
   212  		sort.Strings(fghc.IssueLabelsAdded)
   213  		if !reflect.DeepEqual(expectLabels, fghc.IssueLabelsAdded) {
   214  			t.Errorf("expected the labels %q to be added, but %q were added.", expectLabels, fghc.IssueLabelsAdded)
   215  		}
   216  
   217  	}
   218  }