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 (&notHasTerm{}).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":          {&notHasTerm{"test", "b"}, "test", "", false},
   311  		"valid notHasTerm no value": {&notHasTerm{"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  }