github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/fields/selector_test.go (about) 1 /* 2 Copyright 2015 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 fields 18 19 import ( 20 "reflect" 21 "testing" 22 ) 23 24 func TestSplitTerms(t *testing.T) { 25 testcases := map[string][]string{ 26 // Simple selectors 27 `a`: {`a`}, 28 `a=avalue`: {`a=avalue`}, 29 `a=avalue,b=bvalue`: {`a=avalue`, `b=bvalue`}, 30 `a=avalue,b==bvalue,c!=cvalue`: {`a=avalue`, `b==bvalue`, `c!=cvalue`}, 31 32 // Empty terms 33 ``: nil, 34 `a=a,`: {`a=a`, ``}, 35 `,a=a`: {``, `a=a`}, 36 37 // Escaped values 38 `k=\,,k2=v2`: {`k=\,`, `k2=v2`}, // escaped comma in value 39 `k=\\,k2=v2`: {`k=\\`, `k2=v2`}, // escaped backslash, unescaped comma 40 `k=\\\,,k2=v2`: {`k=\\\,`, `k2=v2`}, // escaped backslash and comma 41 `k=\a\b\`: {`k=\a\b\`}, // non-escape sequences 42 `k=\`: {`k=\`}, // orphan backslash 43 44 // Multi-byte 45 `함=수,목=록`: {`함=수`, `목=록`}, 46 } 47 48 for selector, expectedTerms := range testcases { 49 if terms := splitTerms(selector); !reflect.DeepEqual(terms, expectedTerms) { 50 t.Errorf("splitSelectors(`%s`): Expected\n%#v\ngot\n%#v", selector, expectedTerms, terms) 51 } 52 } 53 } 54 55 func TestSplitTerm(t *testing.T) { 56 testcases := map[string]struct { 57 lhs string 58 op string 59 rhs string 60 ok bool 61 }{ 62 // Simple terms 63 `a=value`: {lhs: `a`, op: `=`, rhs: `value`, ok: true}, 64 `b==value`: {lhs: `b`, op: `==`, rhs: `value`, ok: true}, 65 `c!=value`: {lhs: `c`, op: `!=`, rhs: `value`, ok: true}, 66 67 // Empty or invalid terms 68 ``: {lhs: ``, op: ``, rhs: ``, ok: false}, 69 `a`: {lhs: ``, op: ``, rhs: ``, ok: false}, 70 71 // Escaped values 72 `k=\,`: {lhs: `k`, op: `=`, rhs: `\,`, ok: true}, 73 `k=\=`: {lhs: `k`, op: `=`, rhs: `\=`, ok: true}, 74 `k=\\\a\b\=\,\`: {lhs: `k`, op: `=`, rhs: `\\\a\b\=\,\`, ok: true}, 75 76 // Multi-byte 77 `함=수`: {lhs: `함`, op: `=`, rhs: `수`, ok: true}, 78 } 79 80 for term, expected := range testcases { 81 lhs, op, rhs, ok := splitTerm(term) 82 if lhs != expected.lhs || op != expected.op || rhs != expected.rhs || ok != expected.ok { 83 t.Errorf( 84 "splitTerm(`%s`): Expected\n%s,%s,%s,%v\nGot\n%s,%s,%s,%v", 85 term, 86 expected.lhs, expected.op, expected.rhs, expected.ok, 87 lhs, op, rhs, ok, 88 ) 89 } 90 } 91 } 92 93 func TestEscapeValue(t *testing.T) { 94 // map values to their normalized escaped values 95 testcases := map[string]string{ 96 ``: ``, 97 `a`: `a`, 98 `=`: `\=`, 99 `,`: `\,`, 100 `\`: `\\`, 101 `\=\,\`: `\\\=\\\,\\`, 102 } 103 104 for unescapedValue, escapedValue := range testcases { 105 actualEscaped := EscapeValue(unescapedValue) 106 if actualEscaped != escapedValue { 107 t.Errorf("EscapeValue(%s): expected %s, got %s", unescapedValue, escapedValue, actualEscaped) 108 } 109 110 actualUnescaped, err := UnescapeValue(escapedValue) 111 if err != nil { 112 t.Errorf("UnescapeValue(%s): unexpected error %v", escapedValue, err) 113 } 114 if actualUnescaped != unescapedValue { 115 t.Errorf("UnescapeValue(%s): expected %s, got %s", escapedValue, unescapedValue, actualUnescaped) 116 } 117 } 118 119 // test invalid escape sequences 120 invalidTestcases := []string{ 121 `\`, // orphan slash is invalid 122 `\\\`, // orphan slash is invalid 123 `\a`, // unrecognized escape sequence is invalid 124 } 125 for _, invalidValue := range invalidTestcases { 126 _, err := UnescapeValue(invalidValue) 127 if _, ok := err.(InvalidEscapeSequence); !ok || err == nil { 128 t.Errorf("UnescapeValue(%s): expected invalid escape sequence error, got %#v", invalidValue, err) 129 } 130 } 131 } 132 133 func TestSelectorParse(t *testing.T) { 134 testGoodStrings := []string{ 135 "x=a,y=b,z=c", 136 "", 137 "x!=a,y=b", 138 `x=a||y\=b`, 139 `x=a\=\=b`, 140 } 141 testBadStrings := []string{ 142 "x=a||y=b", 143 "x==a==b", 144 "x=a,b", 145 "x in (a)", 146 "x in (a,b,c)", 147 "x", 148 } 149 for _, test := range testGoodStrings { 150 lq, err := ParseSelector(test) 151 if err != nil { 152 t.Errorf("%v: error %v (%#v)\n", test, err, err) 153 } 154 if test != lq.String() { 155 t.Errorf("%v restring gave: %v\n", test, lq.String()) 156 } 157 } 158 for _, test := range testBadStrings { 159 _, err := ParseSelector(test) 160 if err == nil { 161 t.Errorf("%v: did not get expected error\n", test) 162 } 163 } 164 } 165 166 func TestDeterministicParse(t *testing.T) { 167 s1, err := ParseSelector("x=a,a=x") 168 s2, err2 := ParseSelector("a=x,x=a") 169 if err != nil || err2 != nil { 170 t.Errorf("Unexpected parse error") 171 } 172 if s1.String() != s2.String() { 173 t.Errorf("Non-deterministic parse") 174 } 175 } 176 177 func expectMatch(t *testing.T, selector string, ls Set) { 178 lq, err := ParseSelector(selector) 179 if err != nil { 180 t.Errorf("Unable to parse %v as a selector\n", selector) 181 return 182 } 183 if !lq.Matches(ls) { 184 t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls) 185 } 186 } 187 188 func expectNoMatch(t *testing.T, selector string, ls Set) { 189 lq, err := ParseSelector(selector) 190 if err != nil { 191 t.Errorf("Unable to parse %v as a selector\n", selector) 192 return 193 } 194 if lq.Matches(ls) { 195 t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls) 196 } 197 } 198 199 func TestEverything(t *testing.T) { 200 if !Everything().Matches(Set{"x": "y"}) { 201 t.Errorf("Nil selector didn't match") 202 } 203 if !Everything().Empty() { 204 t.Errorf("Everything was not empty") 205 } 206 } 207 208 func TestSelectorMatches(t *testing.T) { 209 expectMatch(t, "", Set{"x": "y"}) 210 expectMatch(t, "x=y", Set{"x": "y"}) 211 expectMatch(t, "x=y,z=w", Set{"x": "y", "z": "w"}) 212 expectMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "a"}) 213 expectMatch(t, "notin=in", Set{"notin": "in"}) // in and notin in exactMatch 214 expectNoMatch(t, "x=y", Set{"x": "z"}) 215 expectNoMatch(t, "x=y,z=w", Set{"x": "w", "z": "w"}) 216 expectNoMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "w"}) 217 218 fieldset := Set{ 219 "foo": "bar", 220 "baz": "blah", 221 "complex": `=value\,\`, 222 } 223 expectMatch(t, "foo=bar", fieldset) 224 expectMatch(t, "baz=blah", fieldset) 225 expectMatch(t, "foo=bar,baz=blah", fieldset) 226 expectMatch(t, `foo=bar,baz=blah,complex=\=value\\\,\\`, fieldset) 227 expectNoMatch(t, "foo=blah", fieldset) 228 expectNoMatch(t, "baz=bar", fieldset) 229 expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", fieldset) 230 } 231 232 func TestOneTermEqualSelector(t *testing.T) { 233 if !OneTermEqualSelector("x", "y").Matches(Set{"x": "y"}) { 234 t.Errorf("No match when match expected.") 235 } 236 if OneTermEqualSelector("x", "y").Matches(Set{"x": "z"}) { 237 t.Errorf("Match when none expected.") 238 } 239 } 240 241 func expectMatchDirect(t *testing.T, selector, ls Set) { 242 if !SelectorFromSet(selector).Matches(ls) { 243 t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls) 244 } 245 } 246 247 func expectNoMatchDirect(t *testing.T, selector, ls Set) { 248 if SelectorFromSet(selector).Matches(ls) { 249 t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls) 250 } 251 } 252 253 func TestSetMatches(t *testing.T) { 254 labelset := Set{ 255 "foo": "bar", 256 "baz": "blah", 257 } 258 expectMatchDirect(t, Set{}, labelset) 259 expectMatchDirect(t, Set{"foo": "bar"}, labelset) 260 expectMatchDirect(t, Set{"baz": "blah"}, labelset) 261 expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset) 262 expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset) 263 expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset) 264 expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset) 265 } 266 267 func TestNilMapIsValid(t *testing.T) { 268 selector := Set(nil).AsSelector() 269 if selector == nil { 270 t.Errorf("Selector for nil set should be Everything") 271 } 272 if !selector.Empty() { 273 t.Errorf("Selector for nil set should be Empty") 274 } 275 } 276 277 func TestSetIsEmpty(t *testing.T) { 278 if !(Set{}).AsSelector().Empty() { 279 t.Errorf("Empty set should be empty") 280 } 281 if !(andTerm(nil)).Empty() { 282 t.Errorf("Nil andTerm should be empty") 283 } 284 if (&hasTerm{}).Empty() { 285 t.Errorf("hasTerm should not be empty") 286 } 287 if (¬HasTerm{}).Empty() { 288 t.Errorf("notHasTerm should not be empty") 289 } 290 if !(andTerm{andTerm{}}).Empty() { 291 t.Errorf("Nested andTerm should be empty") 292 } 293 if (andTerm{&hasTerm{"a", "b"}}).Empty() { 294 t.Errorf("Nested andTerm should not be empty") 295 } 296 } 297 298 func TestRequiresExactMatch(t *testing.T) { 299 testCases := map[string]struct { 300 S Selector 301 Label string 302 Value string 303 Found bool 304 }{ 305 "empty set": {Set{}.AsSelector(), "test", "", false}, 306 "empty hasTerm": {&hasTerm{}, "test", "", false}, 307 "skipped hasTerm": {&hasTerm{"a", "b"}, "test", "", false}, 308 "valid hasTerm": {&hasTerm{"test", "b"}, "test", "b", true}, 309 "valid hasTerm no value": {&hasTerm{"test", ""}, "test", "", true}, 310 "valid notHasTerm": {¬HasTerm{"test", "b"}, "test", "", false}, 311 "valid notHasTerm no value": {¬HasTerm{"test", ""}, "test", "", false}, 312 "nil andTerm": {andTerm(nil), "test", "", false}, 313 "empty andTerm": {andTerm{}, "test", "", false}, 314 "nested andTerm": {andTerm{andTerm{}}, "test", "", false}, 315 "nested andTerm matches": {andTerm{&hasTerm{"test", "b"}}, "test", "b", true}, 316 "andTerm with non-match": {andTerm{&hasTerm{}, &hasTerm{"test", "b"}}, "test", "b", true}, 317 } 318 for k, v := range testCases { 319 value, found := v.S.RequiresExactMatch(v.Label) 320 if value != v.Value { 321 t.Errorf("%s: expected value %s, got %s", k, v.Value, value) 322 } 323 if found != v.Found { 324 t.Errorf("%s: expected found %t, got %t", k, v.Found, found) 325 } 326 } 327 } 328 329 func TestTransform(t *testing.T) { 330 testCases := []struct { 331 name string 332 selector string 333 transform func(field, value string) (string, string, error) 334 result string 335 isEmpty bool 336 }{ 337 { 338 name: "empty selector", 339 selector: "", 340 transform: func(field, value string) (string, string, error) { return field, value, nil }, 341 result: "", 342 isEmpty: true, 343 }, 344 { 345 name: "no-op transform", 346 selector: "a=b,c=d", 347 transform: func(field, value string) (string, string, error) { return field, value, nil }, 348 result: "a=b,c=d", 349 isEmpty: false, 350 }, 351 { 352 name: "transform one field", 353 selector: "a=b,c=d", 354 transform: func(field, value string) (string, string, error) { 355 if field == "a" { 356 return "e", "f", nil 357 } 358 return field, value, nil 359 }, 360 result: "e=f,c=d", 361 isEmpty: false, 362 }, 363 { 364 name: "remove field to make empty", 365 selector: "a=b", 366 transform: func(field, value string) (string, string, error) { return "", "", nil }, 367 result: "", 368 isEmpty: true, 369 }, 370 { 371 name: "remove only one field", 372 selector: "a=b,c=d,e=f", 373 transform: func(field, value string) (string, string, error) { 374 if field == "c" { 375 return "", "", nil 376 } 377 return field, value, nil 378 }, 379 result: "a=b,e=f", 380 isEmpty: false, 381 }, 382 } 383 384 for i, tc := range testCases { 385 result, err := ParseAndTransformSelector(tc.selector, tc.transform) 386 if err != nil { 387 t.Errorf("[%d] unexpected error during Transform: %v", i, err) 388 } 389 if result.Empty() != tc.isEmpty { 390 t.Errorf("[%d] expected empty: %t, got: %t", i, tc.isEmpty, result.Empty()) 391 } 392 if result.String() != tc.result { 393 t.Errorf("[%d] unexpected result: %s", i, result.String()) 394 } 395 } 396 397 }