github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/cmd/checkconfig/main_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 main
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	"k8s.io/apimachinery/pkg/util/diff"
    24  	"k8s.io/apimachinery/pkg/util/sets"
    25  )
    26  
    27  func TestEnsureValidConfiguration(t *testing.T) {
    28  	var testCases = []struct {
    29  		name                                    string
    30  		tideSubSet, tideSuperSet, pluginsSubSet *orgRepoConfig
    31  		expectedErr                             bool
    32  	}{
    33  		{
    34  			name:          "nothing enabled makes no error",
    35  			tideSubSet:    newOrgRepoConfig(nil, nil),
    36  			tideSuperSet:  newOrgRepoConfig(nil, nil),
    37  			pluginsSubSet: newOrgRepoConfig(nil, nil),
    38  			expectedErr:   false,
    39  		},
    40  		{
    41  			name:          "plugin enabled on org without tide makes no error",
    42  			tideSubSet:    newOrgRepoConfig(nil, nil),
    43  			tideSuperSet:  newOrgRepoConfig(nil, nil),
    44  			pluginsSubSet: newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    45  			expectedErr:   false,
    46  		},
    47  		{
    48  			name:          "plugin enabled on repo without tide makes no error",
    49  			tideSubSet:    newOrgRepoConfig(nil, nil),
    50  			tideSuperSet:  newOrgRepoConfig(nil, nil),
    51  			pluginsSubSet: newOrgRepoConfig(nil, sets.NewString("org/repo")),
    52  			expectedErr:   false,
    53  		},
    54  		{
    55  			name:          "plugin enabled on repo with tide on repo makes no error",
    56  			tideSubSet:    newOrgRepoConfig(nil, sets.NewString("org/repo")),
    57  			tideSuperSet:  newOrgRepoConfig(nil, sets.NewString("org/repo")),
    58  			pluginsSubSet: newOrgRepoConfig(nil, sets.NewString("org/repo")),
    59  			expectedErr:   false,
    60  		},
    61  		{
    62  			name:          "plugin enabled on repo with tide on org makes error",
    63  			tideSubSet:    newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    64  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    65  			pluginsSubSet: newOrgRepoConfig(nil, sets.NewString("org/repo")),
    66  			expectedErr:   true,
    67  		},
    68  		{
    69  			name:          "plugin enabled on org with tide on repo makes no error",
    70  			tideSubSet:    newOrgRepoConfig(nil, sets.NewString("org/repo")),
    71  			tideSuperSet:  newOrgRepoConfig(nil, sets.NewString("org/repo")),
    72  			pluginsSubSet: newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    73  			expectedErr:   false,
    74  		},
    75  		{
    76  			name:          "plugin enabled on org with tide on org makes no error",
    77  			tideSubSet:    newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    78  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    79  			pluginsSubSet: newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    80  			expectedErr:   false,
    81  		},
    82  		{
    83  			name:          "tide enabled on org without plugin makes error",
    84  			tideSubSet:    newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    85  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
    86  			pluginsSubSet: newOrgRepoConfig(nil, nil),
    87  			expectedErr:   true,
    88  		},
    89  		{
    90  			name:          "tide enabled on repo without plugin makes error",
    91  			tideSubSet:    newOrgRepoConfig(nil, sets.NewString("org/repo")),
    92  			tideSuperSet:  newOrgRepoConfig(nil, sets.NewString("org/repo")),
    93  			pluginsSubSet: newOrgRepoConfig(nil, nil),
    94  			expectedErr:   true,
    95  		},
    96  		{
    97  			name:          "plugin enabled on org with any tide record but no specific tide requirement makes error",
    98  			tideSubSet:    newOrgRepoConfig(nil, nil),
    99  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
   100  			pluginsSubSet: newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
   101  			expectedErr:   true,
   102  		},
   103  		{
   104  			name:          "plugin enabled on repo with any tide record but no specific tide requirement makes error",
   105  			tideSubSet:    newOrgRepoConfig(nil, nil),
   106  			tideSuperSet:  newOrgRepoConfig(nil, sets.NewString("org/repo")),
   107  			pluginsSubSet: newOrgRepoConfig(nil, sets.NewString("org/repo")),
   108  			expectedErr:   true,
   109  		},
   110  		{
   111  			name:          "any tide org record but no specific tide requirement or plugin makes no error",
   112  			tideSubSet:    newOrgRepoConfig(nil, nil),
   113  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
   114  			pluginsSubSet: newOrgRepoConfig(nil, nil),
   115  			expectedErr:   false,
   116  		},
   117  		{
   118  			name:          "any tide repo record but no specific tide requirement or plugin makes no error",
   119  			tideSubSet:    newOrgRepoConfig(nil, nil),
   120  			tideSuperSet:  newOrgRepoConfig(nil, sets.NewString("org/repo")),
   121  			pluginsSubSet: newOrgRepoConfig(nil, nil),
   122  			expectedErr:   false,
   123  		},
   124  		{
   125  			name:          "irrelevant repo exception in tide superset doesn't stop missing req error",
   126  			tideSubSet:    newOrgRepoConfig(nil, nil),
   127  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, nil),
   128  			pluginsSubSet: newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
   129  			expectedErr:   true,
   130  		},
   131  		{
   132  			name:          "repo exception in tide superset (no missing req error)",
   133  			tideSubSet:    newOrgRepoConfig(nil, nil),
   134  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, nil),
   135  			pluginsSubSet: newOrgRepoConfig(nil, sets.NewString("org/repo")),
   136  			expectedErr:   false,
   137  		},
   138  		{
   139  			name:          "repo exception in tide subset (new missing req error)",
   140  			tideSubSet:    newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, nil),
   141  			tideSuperSet:  newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
   142  			pluginsSubSet: newOrgRepoConfig(map[string]sets.String{"org": nil}, nil),
   143  			expectedErr:   true,
   144  		},
   145  	}
   146  
   147  	for _, testCase := range testCases {
   148  		t.Run(testCase.name, func(t *testing.T) {
   149  			err := ensureValidConfiguration("plugin", "label", "verb", testCase.tideSubSet, testCase.tideSuperSet, testCase.pluginsSubSet)
   150  			if testCase.expectedErr && err == nil {
   151  				t.Errorf("%s: expected an error but got none", testCase.name)
   152  			}
   153  			if !testCase.expectedErr && err != nil {
   154  				t.Errorf("%s: expected no error but got one: %v", testCase.name, err)
   155  			}
   156  		})
   157  	}
   158  }
   159  
   160  func TestOrgRepoDifference(t *testing.T) {
   161  	testCases := []struct {
   162  		name           string
   163  		a, b, expected *orgRepoConfig
   164  	}{
   165  		{
   166  			name:     "subtract nil",
   167  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   168  			b:        newOrgRepoConfig(map[string]sets.String{}, sets.NewString()),
   169  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   170  		},
   171  		{
   172  			name:     "no overlap",
   173  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   174  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil}, sets.NewString("3/1")),
   175  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   176  		},
   177  		{
   178  			name:     "subtract self",
   179  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   180  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   181  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString()),
   182  		},
   183  		{
   184  			name:     "subtract superset",
   185  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   186  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo"), "org2": nil}, sets.NewString("4/1", "4/2", "5/1")),
   187  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString()),
   188  		},
   189  		{
   190  			name:     "remove org with org",
   191  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/foo")}, sets.NewString("4/1", "4/2")),
   192  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/foo"), "2": nil}, sets.NewString("3/1")),
   193  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString("4/1", "4/2")),
   194  		},
   195  		{
   196  			name:     "shrink org with org",
   197  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   198  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/foo"), "2": nil}, sets.NewString("3/1")),
   199  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString("org/foo", "4/1", "4/2")),
   200  		},
   201  		{
   202  			name:     "shrink org with repo",
   203  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   204  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil}, sets.NewString("org/foo", "3/1")),
   205  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/foo")}, sets.NewString("4/1", "4/2")),
   206  		},
   207  		{
   208  			name:     "remove repo with org",
   209  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2", "4/3", "5/1")),
   210  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil, "4": sets.NewString("4/2")}, sets.NewString("3/1")),
   211  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/2", "5/1")),
   212  		},
   213  		{
   214  			name:     "remove repo with repo",
   215  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2", "4/3", "5/1")),
   216  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil}, sets.NewString("3/1", "4/2", "4/3")),
   217  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "5/1")),
   218  		},
   219  	}
   220  
   221  	for _, tc := range testCases {
   222  		t.Run(tc.name, func(t *testing.T) {
   223  			got := tc.a.difference(tc.b)
   224  			if !reflect.DeepEqual(got, tc.expected) {
   225  				t.Errorf("expected config: %#v, but got config: %#v", tc.expected, got)
   226  			}
   227  		})
   228  	}
   229  }
   230  
   231  func TestOrgRepoIntersection(t *testing.T) {
   232  	testCases := []struct {
   233  		name           string
   234  		a, b, expected *orgRepoConfig
   235  	}{
   236  		{
   237  			name:     "intersect empty",
   238  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   239  			b:        newOrgRepoConfig(map[string]sets.String{}, sets.NewString()),
   240  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString()),
   241  		},
   242  		{
   243  			name:     "no overlap",
   244  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   245  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil}, sets.NewString("3/1")),
   246  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString()),
   247  		},
   248  		{
   249  			name:     "intersect self",
   250  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   251  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   252  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   253  		},
   254  		{
   255  			name:     "intersect superset",
   256  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   257  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo"), "org2": nil}, sets.NewString("4/1", "4/2", "5/1")),
   258  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   259  		},
   260  		{
   261  			name:     "remove org",
   262  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/foo")}, sets.NewString("4/1", "4/2")),
   263  			b:        newOrgRepoConfig(map[string]sets.String{"org2": sets.NewString("org2/repo1")}, sets.NewString("4/1", "4/2", "5/1")),
   264  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString("4/1", "4/2")),
   265  		},
   266  		{
   267  			name:     "shrink org with org",
   268  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/bar")}, sets.NewString("4/1", "4/2")),
   269  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/foo"), "2": nil}, sets.NewString("3/1")),
   270  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/foo", "org/bar")}, sets.NewString()),
   271  		},
   272  		{
   273  			name:     "shrink org with repo",
   274  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   275  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil}, sets.NewString("org/repo", "org/foo", "3/1", "4/1")),
   276  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString("org/foo", "4/1")),
   277  		},
   278  		{
   279  			name:     "remove repo with org",
   280  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2", "4/3", "5/1")),
   281  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil, "4": sets.NewString("4/2")}, sets.NewString("3/1")),
   282  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString("4/1", "4/3")),
   283  		},
   284  		{
   285  			name:     "remove repo with repo",
   286  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2", "4/3", "5/1")),
   287  			b:        newOrgRepoConfig(map[string]sets.String{"2": nil}, sets.NewString("3/1", "4/2", "4/3")),
   288  			expected: newOrgRepoConfig(map[string]sets.String{}, sets.NewString("4/2", "4/3")),
   289  		},
   290  	}
   291  
   292  	for _, tc := range testCases {
   293  		t.Run(tc.name, func(t *testing.T) {
   294  			got := tc.a.intersection(tc.b)
   295  			if !reflect.DeepEqual(got, tc.expected) {
   296  				t.Errorf("expected config: %#v, but got config: %#v", tc.expected, got)
   297  			}
   298  		})
   299  	}
   300  }
   301  
   302  func TestOrgRepoUnion(t *testing.T) {
   303  	testCases := []struct {
   304  		name           string
   305  		a, b, expected *orgRepoConfig
   306  	}{
   307  		{
   308  			name:     "second set empty, get first set back",
   309  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   310  			b:        newOrgRepoConfig(map[string]sets.String{}, sets.NewString()),
   311  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   312  		},
   313  		{
   314  			name:     "no overlap, simple union",
   315  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   316  			b:        newOrgRepoConfig(map[string]sets.String{"2": sets.NewString()}, sets.NewString("3/1")),
   317  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo"), "2": sets.NewString()}, sets.NewString("4/1", "4/2", "3/1")),
   318  		},
   319  		{
   320  			name:     "union self, get self back",
   321  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   322  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   323  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   324  		},
   325  		{
   326  			name:     "union superset, get superset back",
   327  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString("4/1", "4/2")),
   328  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo"), "org2": sets.NewString()}, sets.NewString("4/1", "4/2", "5/1")),
   329  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo"), "org2": sets.NewString()}, sets.NewString("4/1", "4/2", "5/1")),
   330  		},
   331  		{
   332  			name:     "keep only common blacklist items for an org",
   333  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/bar")}, sets.NewString()),
   334  			b:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo", "org/foo")}, sets.NewString()),
   335  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString()),
   336  		},
   337  		{
   338  			name:     "remove items from an org blacklist if they're in a repo whitelist",
   339  			a:        newOrgRepoConfig(map[string]sets.String{"org": sets.NewString("org/repo")}, sets.NewString()),
   340  			b:        newOrgRepoConfig(map[string]sets.String{}, sets.NewString("org/repo")),
   341  			expected: newOrgRepoConfig(map[string]sets.String{"org": sets.NewString()}, sets.NewString()),
   342  		},
   343  		{
   344  			name:     "remove repos when they're covered by an org whitelist",
   345  			a:        newOrgRepoConfig(map[string]sets.String{}, sets.NewString("4/1", "4/2", "4/3")),
   346  			b:        newOrgRepoConfig(map[string]sets.String{"4": sets.NewString("4/2")}, sets.NewString()),
   347  			expected: newOrgRepoConfig(map[string]sets.String{"4": sets.NewString()}, sets.NewString()),
   348  		},
   349  	}
   350  
   351  	for _, tc := range testCases {
   352  		t.Run(tc.name, func(t *testing.T) {
   353  			got := tc.a.union(tc.b)
   354  			if !reflect.DeepEqual(got, tc.expected) {
   355  				t.Errorf("%s: did not get expected config:\n%v", tc.name, diff.ObjectGoPrintDiff(tc.expected, got))
   356  			}
   357  		})
   358  	}
   359  }