sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/size/size_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 size
    18  
    19  import (
    20  	"testing"
    21  
    22  	"github.com/sirupsen/logrus"
    23  
    24  	"sigs.k8s.io/prow/pkg/config"
    25  	"sigs.k8s.io/prow/pkg/github"
    26  	"sigs.k8s.io/prow/pkg/plugins"
    27  )
    28  
    29  type ghc struct {
    30  	*testing.T
    31  	labels    map[github.Label]bool
    32  	files     map[string][]byte
    33  	prChanges []github.PullRequestChange
    34  
    35  	addLabelErr, removeLabelErr, getIssueLabelsErr,
    36  	getFileErr, getPullRequestChangesErr error
    37  }
    38  
    39  func (c *ghc) AddLabel(_, _ string, _ int, label string) error {
    40  	c.T.Logf("AddLabel: %s", label)
    41  	c.labels[github.Label{Name: label}] = true
    42  
    43  	return c.addLabelErr
    44  }
    45  
    46  func (c *ghc) RemoveLabel(_, _ string, _ int, label string) error {
    47  	c.T.Logf("RemoveLabel: %s", label)
    48  	for k := range c.labels {
    49  		if k.Name == label {
    50  			delete(c.labels, k)
    51  		}
    52  	}
    53  
    54  	return c.removeLabelErr
    55  }
    56  
    57  func (c *ghc) GetIssueLabels(_, _ string, _ int) (ls []github.Label, err error) {
    58  	c.T.Log("GetIssueLabels")
    59  	for k, ok := range c.labels {
    60  		if ok {
    61  			ls = append(ls, k)
    62  		}
    63  	}
    64  
    65  	err = c.getIssueLabelsErr
    66  	return
    67  }
    68  
    69  func (c *ghc) GetFile(_, _, path, _ string) ([]byte, error) {
    70  	c.T.Logf("GetFile: %s", path)
    71  	return c.files[path], c.getFileErr
    72  }
    73  
    74  func (c *ghc) GetPullRequestChanges(_, _ string, _ int) ([]github.PullRequestChange, error) {
    75  	c.T.Log("GetPullRequestChanges")
    76  	return c.prChanges, c.getPullRequestChangesErr
    77  }
    78  
    79  func TestSizesOrDefault(t *testing.T) {
    80  	for _, c := range []struct {
    81  		input    plugins.Size
    82  		expected plugins.Size
    83  	}{
    84  		{
    85  			input:    defaultSizes,
    86  			expected: defaultSizes,
    87  		},
    88  		{
    89  			input: plugins.Size{
    90  				S:   12,
    91  				M:   15,
    92  				L:   17,
    93  				Xl:  21,
    94  				Xxl: 51,
    95  			},
    96  			expected: plugins.Size{
    97  				S:   12,
    98  				M:   15,
    99  				L:   17,
   100  				Xl:  21,
   101  				Xxl: 51,
   102  			},
   103  		},
   104  		{
   105  			input:    plugins.Size{},
   106  			expected: defaultSizes,
   107  		},
   108  	} {
   109  		if c.expected != sizesOrDefault(c.input) {
   110  			t.Fatalf("Unexpected sizes from sizesOrDefault - expected %+v but got %+v", c.expected, sizesOrDefault(c.input))
   111  		}
   112  	}
   113  }
   114  
   115  func TestHandlePR(t *testing.T) {
   116  	cases := []struct {
   117  		name        string
   118  		client      *ghc
   119  		event       github.PullRequestEvent
   120  		err         error
   121  		sizes       plugins.Size
   122  		finalLabels []github.Label
   123  	}{
   124  		{
   125  			name: "simple size/S, no .generated_files",
   126  			client: &ghc{
   127  				labels:     map[github.Label]bool{},
   128  				getFileErr: &github.FileNotFound{},
   129  				prChanges: []github.PullRequestChange{
   130  					{
   131  						SHA:       "abcd",
   132  						Filename:  "foobar",
   133  						Additions: 10,
   134  						Deletions: 10,
   135  						Changes:   20,
   136  					},
   137  					{
   138  						SHA:       "abcd",
   139  						Filename:  "barfoo",
   140  						Additions: 3,
   141  						Deletions: 4,
   142  						Changes:   7,
   143  					},
   144  				},
   145  			},
   146  			event: github.PullRequestEvent{
   147  				Action: github.PullRequestActionOpened,
   148  				Number: 101,
   149  				PullRequest: github.PullRequest{
   150  					Number: 101,
   151  					Base: github.PullRequestBranch{
   152  						SHA: "abcd",
   153  						Repo: github.Repo{
   154  							Owner: github.User{
   155  								Login: "kubernetes",
   156  							},
   157  							Name: "kubernetes",
   158  						},
   159  					},
   160  				},
   161  			},
   162  			finalLabels: []github.Label{
   163  				{Name: "size/S"},
   164  			},
   165  			sizes: defaultSizes,
   166  		},
   167  		{
   168  			name: "simple size/M, with .generated_files",
   169  			client: &ghc{
   170  				labels: map[github.Label]bool{},
   171  				files: map[string][]byte{
   172  					".generated_files": []byte(`
   173  						file-name foobar
   174  
   175  						path-prefix generated
   176  					`),
   177  				},
   178  				prChanges: []github.PullRequestChange{
   179  					{
   180  						SHA:       "abcd",
   181  						Filename:  "foobar",
   182  						Additions: 10,
   183  						Deletions: 10,
   184  						Changes:   20,
   185  					},
   186  					{
   187  						SHA:       "abcd",
   188  						Filename:  "barfoo",
   189  						Additions: 50,
   190  						Deletions: 0,
   191  						Changes:   50,
   192  					},
   193  					{
   194  						SHA:       "abcd",
   195  						Filename:  "generated/what.txt",
   196  						Additions: 30,
   197  						Deletions: 0,
   198  						Changes:   30,
   199  					},
   200  					{
   201  						SHA:       "abcd",
   202  						Filename:  "generated/my/file.txt",
   203  						Additions: 300,
   204  						Deletions: 0,
   205  						Changes:   300,
   206  					},
   207  				},
   208  			},
   209  			event: github.PullRequestEvent{
   210  				Action: github.PullRequestActionOpened,
   211  				Number: 101,
   212  				PullRequest: github.PullRequest{
   213  					Number: 101,
   214  					Base: github.PullRequestBranch{
   215  						SHA: "abcd",
   216  						Repo: github.Repo{
   217  							Owner: github.User{
   218  								Login: "kubernetes",
   219  							},
   220  							Name: "kubernetes",
   221  						},
   222  					},
   223  				},
   224  			},
   225  			finalLabels: []github.Label{
   226  				{Name: "size/M"},
   227  			},
   228  			sizes: defaultSizes,
   229  		},
   230  		{
   231  			name: "simple size/M, with .gitattributes",
   232  			client: &ghc{
   233  				labels: map[github.Label]bool{},
   234  				files: map[string][]byte{
   235  					".gitattributes": []byte(`
   236  						# comments
   237  						foobar linguist-generated=true
   238  						generated/**/*.txt linguist-generated=true
   239  					`),
   240  				},
   241  				prChanges: []github.PullRequestChange{
   242  					{
   243  						SHA:       "abcd",
   244  						Filename:  "foobar",
   245  						Additions: 10,
   246  						Deletions: 10,
   247  						Changes:   20,
   248  					},
   249  					{
   250  						SHA:       "abcd",
   251  						Filename:  "barfoo",
   252  						Additions: 50,
   253  						Deletions: 0,
   254  						Changes:   50,
   255  					},
   256  					{
   257  						SHA:       "abcd",
   258  						Filename:  "generated/what.txt",
   259  						Additions: 30,
   260  						Deletions: 0,
   261  						Changes:   30,
   262  					},
   263  					{
   264  						SHA:       "abcd",
   265  						Filename:  "generated/my/file.txt",
   266  						Additions: 300,
   267  						Deletions: 0,
   268  						Changes:   300,
   269  					},
   270  				},
   271  			},
   272  			event: github.PullRequestEvent{
   273  				Action: github.PullRequestActionOpened,
   274  				Number: 101,
   275  				PullRequest: github.PullRequest{
   276  					Number: 101,
   277  					Base: github.PullRequestBranch{
   278  						SHA: "abcd",
   279  						Repo: github.Repo{
   280  							Owner: github.User{
   281  								Login: "kubernetes",
   282  							},
   283  							Name: "kubernetes",
   284  						},
   285  					},
   286  				},
   287  			},
   288  			finalLabels: []github.Label{
   289  				{Name: "size/M"},
   290  			},
   291  			sizes: defaultSizes,
   292  		},
   293  		{
   294  			name: "simple size/XS, with .generated_files and paths-from-repo",
   295  			client: &ghc{
   296  				labels: map[github.Label]bool{},
   297  				files: map[string][]byte{
   298  					".generated_files": []byte(`
   299  						# Comments
   300  						file-name foobar
   301  
   302  						path-prefix generated
   303  
   304  						paths-from-repo docs/.generated_docs
   305  					`),
   306  					"docs/.generated_docs": []byte(`
   307  					# Comments work
   308  
   309  					# And empty lines don't matter
   310  					foobar
   311  					mypath1
   312  					mypath2
   313  					mydir/mypath3
   314  					`),
   315  				},
   316  				prChanges: []github.PullRequestChange{
   317  					{
   318  						SHA:       "abcd",
   319  						Filename:  "foobar",
   320  						Additions: 10,
   321  						Deletions: 10,
   322  						Changes:   20,
   323  					},
   324  					{ // Notice "barfoo" is the only relevant change.
   325  						SHA:       "abcd",
   326  						Filename:  "barfoo",
   327  						Additions: 5,
   328  						Deletions: 0,
   329  						Changes:   5,
   330  					},
   331  					{
   332  						SHA:       "abcd",
   333  						Filename:  "generated/what.txt",
   334  						Additions: 30,
   335  						Deletions: 0,
   336  						Changes:   30,
   337  					},
   338  					{
   339  						SHA:       "abcd",
   340  						Filename:  "generated/my/file.txt",
   341  						Additions: 300,
   342  						Deletions: 0,
   343  						Changes:   300,
   344  					},
   345  					{
   346  						SHA:       "abcd",
   347  						Filename:  "mypath1",
   348  						Additions: 300,
   349  						Deletions: 0,
   350  						Changes:   300,
   351  					},
   352  					{
   353  						SHA:       "abcd",
   354  						Filename:  "mydir/mypath3",
   355  						Additions: 300,
   356  						Deletions: 0,
   357  						Changes:   300,
   358  					},
   359  				},
   360  			},
   361  			event: github.PullRequestEvent{
   362  				Action: github.PullRequestActionOpened,
   363  				Number: 101,
   364  				PullRequest: github.PullRequest{
   365  					Number: 101,
   366  					Base: github.PullRequestBranch{
   367  						SHA: "abcd",
   368  						Repo: github.Repo{
   369  							Owner: github.User{
   370  								Login: "kubernetes",
   371  							},
   372  							Name: "kubernetes",
   373  						},
   374  					},
   375  				},
   376  			},
   377  			finalLabels: []github.Label{
   378  				{Name: "size/XS"},
   379  			},
   380  			sizes: defaultSizes,
   381  		},
   382  		{
   383  			name:   "pr closed event",
   384  			client: &ghc{},
   385  			event: github.PullRequestEvent{
   386  				Action: github.PullRequestActionClosed,
   387  			},
   388  			finalLabels: []github.Label{},
   389  			sizes:       defaultSizes,
   390  		},
   391  		{
   392  			name: "XS -> S transition",
   393  			client: &ghc{
   394  				labels: map[github.Label]bool{
   395  					{Name: "irrelevant"}: true,
   396  					{Name: "size/XS"}:    true,
   397  				},
   398  				files: map[string][]byte{
   399  					".generated_files": []byte(`
   400  						# Comments
   401  						file-name foobar
   402  
   403  						path-prefix generated
   404  
   405  						paths-from-repo docs/.generated_docs
   406  					`),
   407  					"docs/.generated_docs": []byte(`
   408  					# Comments work
   409  
   410  					# And empty lines don't matter
   411  					foobar
   412  					mypath1
   413  					mypath2
   414  					mydir/mypath3
   415  					`),
   416  				},
   417  				prChanges: []github.PullRequestChange{
   418  					{
   419  						SHA:       "abcd",
   420  						Filename:  "foobar",
   421  						Additions: 10,
   422  						Deletions: 10,
   423  						Changes:   20,
   424  					},
   425  					{ // Notice "barfoo" is the only relevant change.
   426  						SHA:       "abcd",
   427  						Filename:  "barfoo",
   428  						Additions: 5,
   429  						Deletions: 0,
   430  						Changes:   5,
   431  					},
   432  					{
   433  						SHA:       "abcd",
   434  						Filename:  "generated/what.txt",
   435  						Additions: 30,
   436  						Deletions: 0,
   437  						Changes:   30,
   438  					},
   439  					{
   440  						SHA:       "abcd",
   441  						Filename:  "generated/my/file.txt",
   442  						Additions: 300,
   443  						Deletions: 0,
   444  						Changes:   300,
   445  					},
   446  					{
   447  						SHA:       "abcd",
   448  						Filename:  "mypath1",
   449  						Additions: 300,
   450  						Deletions: 0,
   451  						Changes:   300,
   452  					},
   453  					{
   454  						SHA:       "abcd",
   455  						Filename:  "mydir/mypath3",
   456  						Additions: 300,
   457  						Deletions: 0,
   458  						Changes:   300,
   459  					},
   460  				},
   461  			},
   462  			event: github.PullRequestEvent{
   463  				Action: github.PullRequestActionOpened,
   464  				Number: 101,
   465  				PullRequest: github.PullRequest{
   466  					Number: 101,
   467  					Base: github.PullRequestBranch{
   468  						SHA: "abcd",
   469  						Repo: github.Repo{
   470  							Owner: github.User{
   471  								Login: "kubernetes",
   472  							},
   473  							Name: "kubernetes",
   474  						},
   475  					},
   476  				},
   477  			},
   478  			finalLabels: []github.Label{
   479  				{Name: "irrelevant"},
   480  				{Name: "size/XS"},
   481  			},
   482  			sizes: defaultSizes,
   483  		},
   484  		{
   485  			name: "pull request reopened",
   486  			client: &ghc{
   487  				labels:     map[github.Label]bool{},
   488  				getFileErr: &github.FileNotFound{},
   489  				prChanges: []github.PullRequestChange{
   490  					{
   491  						SHA:       "abcd",
   492  						Filename:  "foobar",
   493  						Additions: 10,
   494  						Deletions: 10,
   495  						Changes:   20,
   496  					},
   497  					{
   498  						SHA:       "abcd",
   499  						Filename:  "barfoo",
   500  						Additions: 3,
   501  						Deletions: 4,
   502  						Changes:   7,
   503  					},
   504  				},
   505  			},
   506  			event: github.PullRequestEvent{
   507  				Action: github.PullRequestActionReopened,
   508  				Number: 101,
   509  				PullRequest: github.PullRequest{
   510  					Number: 101,
   511  					Base: github.PullRequestBranch{
   512  						SHA: "abcd",
   513  						Repo: github.Repo{
   514  							Owner: github.User{
   515  								Login: "kubernetes",
   516  							},
   517  							Name: "kubernetes",
   518  						},
   519  					},
   520  				},
   521  			},
   522  			finalLabels: []github.Label{
   523  				{Name: "size/S"},
   524  			},
   525  			sizes: defaultSizes,
   526  		},
   527  		{
   528  			name: "pull request edited",
   529  			client: &ghc{
   530  				labels:     map[github.Label]bool{},
   531  				getFileErr: &github.FileNotFound{},
   532  				prChanges: []github.PullRequestChange{
   533  					{
   534  						SHA:       "abcd",
   535  						Filename:  "foobar",
   536  						Additions: 30,
   537  						Deletions: 40,
   538  						Changes:   70,
   539  					},
   540  				},
   541  			},
   542  			event: github.PullRequestEvent{
   543  				Action: github.PullRequestActionEdited,
   544  				Number: 101,
   545  				PullRequest: github.PullRequest{
   546  					Number: 101,
   547  					Base: github.PullRequestBranch{
   548  						SHA: "abcd",
   549  						Repo: github.Repo{
   550  							Owner: github.User{
   551  								Login: "kubernetes",
   552  							},
   553  							Name: "kubernetes",
   554  						},
   555  					},
   556  				},
   557  			},
   558  			finalLabels: []github.Label{
   559  				{Name: "size/M"},
   560  			},
   561  			sizes: defaultSizes,
   562  		},
   563  		{
   564  			name: "different label constraints",
   565  			client: &ghc{
   566  				labels:     map[github.Label]bool{},
   567  				getFileErr: &github.FileNotFound{},
   568  				prChanges: []github.PullRequestChange{
   569  					{
   570  						SHA:       "abcd",
   571  						Filename:  "foobar",
   572  						Additions: 10,
   573  						Deletions: 10,
   574  						Changes:   20,
   575  					},
   576  					{
   577  						SHA:       "abcd",
   578  						Filename:  "barfoo",
   579  						Additions: 3,
   580  						Deletions: 4,
   581  						Changes:   7,
   582  					},
   583  				},
   584  			},
   585  			event: github.PullRequestEvent{
   586  				Action: github.PullRequestActionOpened,
   587  				Number: 101,
   588  				PullRequest: github.PullRequest{
   589  					Number: 101,
   590  					Base: github.PullRequestBranch{
   591  						SHA: "abcd",
   592  						Repo: github.Repo{
   593  							Owner: github.User{
   594  								Login: "kubernetes",
   595  							},
   596  							Name: "kubernetes",
   597  						},
   598  					},
   599  				},
   600  			},
   601  			finalLabels: []github.Label{
   602  				{Name: "size/XXL"},
   603  			},
   604  			sizes: plugins.Size{
   605  				S:   0,
   606  				M:   1,
   607  				L:   2,
   608  				Xl:  3,
   609  				Xxl: 4,
   610  			},
   611  		},
   612  	}
   613  
   614  	for _, c := range cases {
   615  		t.Run(c.name, func(t *testing.T) {
   616  			if c.client == nil {
   617  				t.Fatalf("case can not have nil github client")
   618  			}
   619  
   620  			// Set up test logging.
   621  			c.client.T = t
   622  
   623  			err := handlePR(c.client, c.sizes, logrus.NewEntry(logrus.New()), c.event)
   624  
   625  			if err != nil && c.err == nil {
   626  				t.Fatalf("handlePR error: %v", err)
   627  			}
   628  
   629  			if err == nil && c.err != nil {
   630  				t.Fatalf("handlePR wanted error %v, got nil", err)
   631  			}
   632  
   633  			if got, want := err, c.err; got != nil && got.Error() != want.Error() {
   634  				t.Fatalf("handlePR errors mismatch: got %v, want %v", got, want)
   635  			}
   636  
   637  			if got, want := len(c.client.labels), len(c.finalLabels); got != want {
   638  				t.Logf("github client labels: got %v; want %v", c.client.labels, c.finalLabels)
   639  				t.Fatalf("finalLabels count mismatch: got %d, want %d", got, want)
   640  			}
   641  
   642  			for _, l := range c.finalLabels {
   643  				if !c.client.labels[l] {
   644  					t.Fatalf("github client labels missing %v", l)
   645  				}
   646  			}
   647  		})
   648  	}
   649  }
   650  
   651  func TestHelpProvider(t *testing.T) {
   652  	enabledRepos := []config.OrgRepo{
   653  		{Org: "org1", Repo: "repo"},
   654  		{Org: "org2", Repo: "repo"},
   655  	}
   656  	cases := []struct {
   657  		name         string
   658  		config       *plugins.Configuration
   659  		enabledRepos []config.OrgRepo
   660  		err          bool
   661  	}{
   662  		{
   663  			name:         "Empty config",
   664  			config:       &plugins.Configuration{},
   665  			enabledRepos: enabledRepos,
   666  		},
   667  		{
   668  			name: "Empty sizes",
   669  			config: &plugins.Configuration{
   670  				Size: plugins.Size{},
   671  			},
   672  			enabledRepos: enabledRepos,
   673  		},
   674  		{
   675  			name: "Sizes specified",
   676  			config: &plugins.Configuration{
   677  				Size: plugins.Size{
   678  					S:   12,
   679  					M:   15,
   680  					L:   17,
   681  					Xl:  21,
   682  					Xxl: 51,
   683  				},
   684  			},
   685  			enabledRepos: enabledRepos,
   686  		},
   687  	}
   688  	for _, c := range cases {
   689  		t.Run(c.name, func(t *testing.T) {
   690  			_, err := helpProvider(c.config, c.enabledRepos)
   691  			if err != nil && !c.err {
   692  				t.Fatalf("helpProvider error: %v", err)
   693  			}
   694  		})
   695  	}
   696  }