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 }