github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/labels/selector_test.go (about)

     1  /*
     2  Copyright 2014 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 labels
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/google/go-cmp/cmp/cmpopts"
    27  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/selection"
    28  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/sets"
    29  	"github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/validation/field"
    30  )
    31  
    32  var (
    33  	ignoreDetail = cmpopts.IgnoreFields(field.Error{}, "Detail")
    34  )
    35  
    36  func TestSelectorParse(t *testing.T) {
    37  	testGoodStrings := []string{
    38  		"x=a,y=b,z=c",
    39  		"",
    40  		"x!=a,y=b",
    41  		"x=",
    42  		"x= ",
    43  		"x=,z= ",
    44  		"x= ,z= ",
    45  		"!x",
    46  		"x>1",
    47  		"x>1,z<5",
    48  	}
    49  	testBadStrings := []string{
    50  		"x=a||y=b",
    51  		"x==a==b",
    52  		"!x=a",
    53  		"x<a",
    54  	}
    55  	for _, test := range testGoodStrings {
    56  		lq, err := Parse(test)
    57  		if err != nil {
    58  			t.Errorf("%v: error %v (%#v)\n", test, err, err)
    59  		}
    60  		if strings.Replace(test, " ", "", -1) != lq.String() {
    61  			t.Errorf("%v restring gave: %v\n", test, lq.String())
    62  		}
    63  	}
    64  	for _, test := range testBadStrings {
    65  		_, err := Parse(test)
    66  		if err == nil {
    67  			t.Errorf("%v: did not get expected error\n", test)
    68  		}
    69  	}
    70  }
    71  
    72  func TestDeterministicParse(t *testing.T) {
    73  	s1, err := Parse("x=a,a=x")
    74  	s2, err2 := Parse("a=x,x=a")
    75  	if err != nil || err2 != nil {
    76  		t.Errorf("Unexpected parse error")
    77  	}
    78  	if s1.String() != s2.String() {
    79  		t.Errorf("Non-deterministic parse")
    80  	}
    81  }
    82  
    83  func expectMatch(t *testing.T, selector string, ls Set) {
    84  	lq, err := Parse(selector)
    85  	if err != nil {
    86  		t.Errorf("Unable to parse %v as a selector\n", selector)
    87  		return
    88  	}
    89  	if !lq.Matches(ls) {
    90  		t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
    91  	}
    92  }
    93  
    94  func expectNoMatch(t *testing.T, selector string, ls Set) {
    95  	lq, err := Parse(selector)
    96  	if err != nil {
    97  		t.Errorf("Unable to parse %v as a selector\n", selector)
    98  		return
    99  	}
   100  	if lq.Matches(ls) {
   101  		t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
   102  	}
   103  }
   104  
   105  func TestEverything(t *testing.T) {
   106  	if !Everything().Matches(Set{"x": "y"}) {
   107  		t.Errorf("Nil selector didn't match")
   108  	}
   109  	if !Everything().Empty() {
   110  		t.Errorf("Everything was not empty")
   111  	}
   112  }
   113  
   114  func TestSelectorMatches(t *testing.T) {
   115  	expectMatch(t, "", Set{"x": "y"})
   116  	expectMatch(t, "x=y", Set{"x": "y"})
   117  	expectMatch(t, "x=y,z=w", Set{"x": "y", "z": "w"})
   118  	expectMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "a"})
   119  	expectMatch(t, "notin=in", Set{"notin": "in"}) // in and notin in exactMatch
   120  	expectMatch(t, "x", Set{"x": "z"})
   121  	expectMatch(t, "!x", Set{"y": "z"})
   122  	expectMatch(t, "x>1", Set{"x": "2"})
   123  	expectMatch(t, "x<1", Set{"x": "0"})
   124  	expectNoMatch(t, "x=z", Set{})
   125  	expectNoMatch(t, "x=y", Set{"x": "z"})
   126  	expectNoMatch(t, "x=y,z=w", Set{"x": "w", "z": "w"})
   127  	expectNoMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "w"})
   128  	expectNoMatch(t, "x", Set{"y": "z"})
   129  	expectNoMatch(t, "!x", Set{"x": "z"})
   130  	expectNoMatch(t, "x>1", Set{"x": "0"})
   131  	expectNoMatch(t, "x<1", Set{"x": "2"})
   132  
   133  	labelset := Set{
   134  		"foo": "bar",
   135  		"baz": "blah",
   136  	}
   137  	expectMatch(t, "foo=bar", labelset)
   138  	expectMatch(t, "baz=blah", labelset)
   139  	expectMatch(t, "foo=bar,baz=blah", labelset)
   140  	expectNoMatch(t, "foo=blah", labelset)
   141  	expectNoMatch(t, "baz=bar", labelset)
   142  	expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", labelset)
   143  }
   144  
   145  func expectMatchDirect(t *testing.T, selector, ls Set) {
   146  	if !SelectorFromSet(selector).Matches(ls) {
   147  		t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
   148  	}
   149  }
   150  
   151  //nolint:staticcheck,unused //iccheck // U1000 currently commented out in TODO of TestSetMatches
   152  func expectNoMatchDirect(t *testing.T, selector, ls Set) {
   153  	if SelectorFromSet(selector).Matches(ls) {
   154  		t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
   155  	}
   156  }
   157  
   158  func TestSetMatches(t *testing.T) {
   159  	labelset := Set{
   160  		"foo": "bar",
   161  		"baz": "blah",
   162  	}
   163  	expectMatchDirect(t, Set{}, labelset)
   164  	expectMatchDirect(t, Set{"foo": "bar"}, labelset)
   165  	expectMatchDirect(t, Set{"baz": "blah"}, labelset)
   166  	expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset)
   167  
   168  	//TODO: bad values not handled for the moment in SelectorFromSet
   169  	//expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset)
   170  	//expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset)
   171  	//expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset)
   172  }
   173  
   174  func TestNilMapIsValid(t *testing.T) {
   175  	selector := Set(nil).AsSelector()
   176  	if selector == nil {
   177  		t.Errorf("Selector for nil set should be Everything")
   178  	}
   179  	if !selector.Empty() {
   180  		t.Errorf("Selector for nil set should be Empty")
   181  	}
   182  }
   183  
   184  func TestSetIsEmpty(t *testing.T) {
   185  	if !(Set{}).AsSelector().Empty() {
   186  		t.Errorf("Empty set should be empty")
   187  	}
   188  	if !(NewSelector()).Empty() {
   189  		t.Errorf("Nil Selector should be empty")
   190  	}
   191  }
   192  
   193  func TestLexer(t *testing.T) {
   194  	testcases := []struct {
   195  		s string
   196  		t Token
   197  	}{
   198  		{"", EndOfStringToken},
   199  		{",", CommaToken},
   200  		{"notin", NotInToken},
   201  		{"in", InToken},
   202  		{"=", EqualsToken},
   203  		{"==", DoubleEqualsToken},
   204  		{">", GreaterThanToken},
   205  		{"<", LessThanToken},
   206  		//Note that Lex returns the longest valid token found
   207  		{"!", DoesNotExistToken},
   208  		{"!=", NotEqualsToken},
   209  		{"(", OpenParToken},
   210  		{")", ClosedParToken},
   211  		//Non-"special" characters are considered part of an identifier
   212  		{"~", IdentifierToken},
   213  		{"||", IdentifierToken},
   214  	}
   215  	for _, v := range testcases {
   216  		l := &Lexer{s: v.s, pos: 0}
   217  		token, lit := l.Lex()
   218  		if token != v.t {
   219  			t.Errorf("Got %d it should be %d for '%s'", token, v.t, v.s)
   220  		}
   221  		if v.t != ErrorToken && lit != v.s {
   222  			t.Errorf("Got '%s' it should be '%s'", lit, v.s)
   223  		}
   224  	}
   225  }
   226  
   227  func min(l, r int) (m int) {
   228  	m = r
   229  	if l < r {
   230  		m = l
   231  	}
   232  	return m
   233  }
   234  
   235  func TestLexerSequence(t *testing.T) {
   236  	testcases := []struct {
   237  		s string
   238  		t []Token
   239  	}{
   240  		{"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken}},
   241  		{"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken}},
   242  		{"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken}},
   243  		{"key", []Token{IdentifierToken}},
   244  		{"!key", []Token{DoesNotExistToken, IdentifierToken}},
   245  		{"()", []Token{OpenParToken, ClosedParToken}},
   246  		{"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken}},
   247  		{"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken}},
   248  		{"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken}},
   249  		{"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken}},
   250  	}
   251  	for _, v := range testcases {
   252  		var tokens []Token
   253  		l := &Lexer{s: v.s, pos: 0}
   254  		for {
   255  			token, _ := l.Lex()
   256  			if token == EndOfStringToken {
   257  				break
   258  			}
   259  			tokens = append(tokens, token)
   260  		}
   261  		if len(tokens) != len(v.t) {
   262  			t.Errorf("Bad number of tokens for '%s %d, %d", v.s, len(tokens), len(v.t))
   263  		}
   264  		for i := 0; i < min(len(tokens), len(v.t)); i++ {
   265  			if tokens[i] != v.t[i] {
   266  				t.Errorf("Test '%s': Mismatching in token type found '%v' it should be '%v'", v.s, tokens[i], v.t[i])
   267  			}
   268  		}
   269  	}
   270  }
   271  func TestParserLookahead(t *testing.T) {
   272  	testcases := []struct {
   273  		s string
   274  		t []Token
   275  	}{
   276  		{"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
   277  		{"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
   278  		{"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
   279  		{"key", []Token{IdentifierToken, EndOfStringToken}},
   280  		{"!key", []Token{DoesNotExistToken, IdentifierToken, EndOfStringToken}},
   281  		{"()", []Token{OpenParToken, ClosedParToken, EndOfStringToken}},
   282  		{"", []Token{EndOfStringToken}},
   283  		{"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken, EndOfStringToken}},
   284  		{"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken, EndOfStringToken}},
   285  		{"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken, EndOfStringToken}},
   286  		{"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken, EndOfStringToken}},
   287  	}
   288  	for _, v := range testcases {
   289  		p := &Parser{l: &Lexer{s: v.s, pos: 0}, position: 0}
   290  		p.scan()
   291  		if len(p.scannedItems) != len(v.t) {
   292  			t.Errorf("Expected %d items found %d", len(v.t), len(p.scannedItems))
   293  		}
   294  		for {
   295  			token, lit := p.lookahead(KeyAndOperator)
   296  
   297  			token2, lit2 := p.consume(KeyAndOperator)
   298  			if token == EndOfStringToken {
   299  				break
   300  			}
   301  			if token != token2 || lit != lit2 {
   302  				t.Errorf("Bad values")
   303  			}
   304  		}
   305  	}
   306  }
   307  
   308  func TestParseOperator(t *testing.T) {
   309  	testcases := []struct {
   310  		token         string
   311  		expectedError error
   312  	}{
   313  		{"in", nil},
   314  		{"=", nil},
   315  		{"==", nil},
   316  		{">", nil},
   317  		{"<", nil},
   318  		{"notin", nil},
   319  		{"!=", nil},
   320  		{"!", fmt.Errorf("found '%s', expected: %v", selection.DoesNotExist, strings.Join(binaryOperators, ", "))},
   321  		{"exists", fmt.Errorf("found '%s', expected: %v", selection.Exists, strings.Join(binaryOperators, ", "))},
   322  		{"(", fmt.Errorf("found '%s', expected: %v", "(", strings.Join(binaryOperators, ", "))},
   323  	}
   324  	for _, testcase := range testcases {
   325  		p := &Parser{l: &Lexer{s: testcase.token, pos: 0}, position: 0}
   326  		p.scan()
   327  
   328  		_, err := p.parseOperator()
   329  		if ok := reflect.DeepEqual(testcase.expectedError, err); !ok {
   330  			t.Errorf("\nexpect err [%v], \nactual err [%v]", testcase.expectedError, err)
   331  		}
   332  	}
   333  }
   334  
   335  func TestRequirementConstructor(t *testing.T) {
   336  	requirementConstructorTests := []struct {
   337  		Key     string
   338  		Op      selection.Operator
   339  		Vals    sets.String
   340  		WantErr field.ErrorList
   341  	}{
   342  		{
   343  			Key: "x1",
   344  			Op:  selection.In,
   345  			WantErr: field.ErrorList{
   346  				&field.Error{
   347  					Type:     field.ErrorTypeInvalid,
   348  					Field:    "values",
   349  					BadValue: []string{},
   350  				},
   351  			},
   352  		},
   353  		{
   354  			Key:  "x2",
   355  			Op:   selection.NotIn,
   356  			Vals: sets.NewString(),
   357  			WantErr: field.ErrorList{
   358  				&field.Error{
   359  					Type:     field.ErrorTypeInvalid,
   360  					Field:    "values",
   361  					BadValue: []string{},
   362  				},
   363  			},
   364  		},
   365  		{
   366  			Key:  "x3",
   367  			Op:   selection.In,
   368  			Vals: sets.NewString("foo"),
   369  		},
   370  		{
   371  			Key:  "x4",
   372  			Op:   selection.NotIn,
   373  			Vals: sets.NewString("foo"),
   374  		},
   375  		{
   376  			Key:  "x5",
   377  			Op:   selection.Equals,
   378  			Vals: sets.NewString("foo", "bar"),
   379  			WantErr: field.ErrorList{
   380  				&field.Error{
   381  					Type:     field.ErrorTypeInvalid,
   382  					Field:    "values",
   383  					BadValue: []string{"bar", "foo"},
   384  				},
   385  			},
   386  		},
   387  		{
   388  			Key: "x6",
   389  			Op:  selection.Exists,
   390  		},
   391  		{
   392  			Key: "x7",
   393  			Op:  selection.DoesNotExist,
   394  		},
   395  		{
   396  			Key:  "x8",
   397  			Op:   selection.Exists,
   398  			Vals: sets.NewString("foo"),
   399  			WantErr: field.ErrorList{
   400  				&field.Error{
   401  					Type:     field.ErrorTypeInvalid,
   402  					Field:    "values",
   403  					BadValue: []string{"foo"},
   404  				},
   405  			},
   406  		},
   407  		{
   408  			Key:  "x9",
   409  			Op:   selection.In,
   410  			Vals: sets.NewString("bar"),
   411  		},
   412  		{
   413  			Key:  "x10",
   414  			Op:   selection.In,
   415  			Vals: sets.NewString("bar"),
   416  		},
   417  		{
   418  			Key:  "x11",
   419  			Op:   selection.GreaterThan,
   420  			Vals: sets.NewString("1"),
   421  		},
   422  		{
   423  			Key:  "x12",
   424  			Op:   selection.LessThan,
   425  			Vals: sets.NewString("6"),
   426  		},
   427  		{
   428  			Key: "x13",
   429  			Op:  selection.GreaterThan,
   430  			WantErr: field.ErrorList{
   431  				&field.Error{
   432  					Type:     field.ErrorTypeInvalid,
   433  					Field:    "values",
   434  					BadValue: []string{},
   435  				},
   436  			},
   437  		},
   438  		{
   439  			Key:  "x14",
   440  			Op:   selection.GreaterThan,
   441  			Vals: sets.NewString("bar"),
   442  			WantErr: field.ErrorList{
   443  				&field.Error{
   444  					Type:     field.ErrorTypeInvalid,
   445  					Field:    "values[0]",
   446  					BadValue: "bar",
   447  				},
   448  			},
   449  		},
   450  		{
   451  			Key:  "x15",
   452  			Op:   selection.LessThan,
   453  			Vals: sets.NewString("bar"),
   454  			WantErr: field.ErrorList{
   455  				&field.Error{
   456  					Type:     field.ErrorTypeInvalid,
   457  					Field:    "values[0]",
   458  					BadValue: "bar",
   459  				},
   460  			},
   461  		},
   462  		{
   463  			Key: strings.Repeat("a", 254), //breaks DNS rule that len(key) <= 253
   464  			Op:  selection.Exists,
   465  			WantErr: field.ErrorList{
   466  				&field.Error{
   467  					Type:     field.ErrorTypeInvalid,
   468  					Field:    "key",
   469  					BadValue: strings.Repeat("a", 254),
   470  				},
   471  			},
   472  		},
   473  		{
   474  			Key:  "x16",
   475  			Op:   selection.Equals,
   476  			Vals: sets.NewString(strings.Repeat("a", 254)),
   477  			WantErr: field.ErrorList{
   478  				&field.Error{
   479  					Type:     field.ErrorTypeInvalid,
   480  					Field:    "values[0][x16]",
   481  					BadValue: strings.Repeat("a", 254),
   482  				},
   483  			},
   484  		},
   485  		{
   486  			Key:  "x17",
   487  			Op:   selection.Equals,
   488  			Vals: sets.NewString("a b"),
   489  			WantErr: field.ErrorList{
   490  				&field.Error{
   491  					Type:     field.ErrorTypeInvalid,
   492  					Field:    "values[0][x17]",
   493  					BadValue: "a b",
   494  				},
   495  			},
   496  		},
   497  		{
   498  			Key: "x18",
   499  			Op:  "unsupportedOp",
   500  			WantErr: field.ErrorList{
   501  				&field.Error{
   502  					Type:     field.ErrorTypeNotSupported,
   503  					Field:    "operator",
   504  					BadValue: selection.Operator("unsupportedOp"),
   505  				},
   506  			},
   507  		},
   508  	}
   509  	for _, rc := range requirementConstructorTests {
   510  		_, err := NewRequirement(rc.Key, rc.Op, rc.Vals.List())
   511  		if diff := cmp.Diff(rc.WantErr.ToAggregate(), err, ignoreDetail); diff != "" {
   512  			t.Errorf("NewRequirement test %v returned unexpected error (-want,+got):\n%s", rc.Key, diff)
   513  		}
   514  	}
   515  }
   516  
   517  func TestToString(t *testing.T) {
   518  	var req Requirement
   519  	toStringTests := []struct {
   520  		In    *internalSelector
   521  		Out   string
   522  		Valid bool
   523  	}{
   524  
   525  		{&internalSelector{
   526  			getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
   527  			getRequirement("y", selection.NotIn, sets.NewString("jkl"), t),
   528  			getRequirement("z", selection.Exists, nil, t)},
   529  			"x in (abc,def),y notin (jkl),z", true},
   530  		{&internalSelector{
   531  			getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
   532  			getRequirement("y", selection.NotEquals, sets.NewString("jkl"), t),
   533  			getRequirement("z", selection.DoesNotExist, nil, t)},
   534  			"x notin (abc,def),y!=jkl,!z", true},
   535  		{&internalSelector{
   536  			getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
   537  			req}, // adding empty req for the trailing ','
   538  			"x in (abc,def),", false},
   539  		{&internalSelector{
   540  			getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
   541  			getRequirement("y", selection.In, sets.NewString("jkl", "mno"), t),
   542  			getRequirement("z", selection.NotIn, sets.NewString(""), t)},
   543  			"x notin (abc),y in (jkl,mno),z notin ()", true},
   544  		{&internalSelector{
   545  			getRequirement("x", selection.Equals, sets.NewString("abc"), t),
   546  			getRequirement("y", selection.DoubleEquals, sets.NewString("jkl"), t),
   547  			getRequirement("z", selection.NotEquals, sets.NewString("a"), t),
   548  			getRequirement("z", selection.Exists, nil, t)},
   549  			"x=abc,y==jkl,z!=a,z", true},
   550  		{&internalSelector{
   551  			getRequirement("x", selection.GreaterThan, sets.NewString("2"), t),
   552  			getRequirement("y", selection.LessThan, sets.NewString("8"), t),
   553  			getRequirement("z", selection.Exists, nil, t)},
   554  			"x>2,y<8,z", true},
   555  	}
   556  	for _, ts := range toStringTests {
   557  		if out := ts.In.String(); out == "" && ts.Valid {
   558  			t.Errorf("%#v.String() => '%v' expected no error", ts.In, out)
   559  		} else if out != ts.Out {
   560  			t.Errorf("%#v.String() => '%v' want '%v'", ts.In, out, ts.Out)
   561  		}
   562  	}
   563  }
   564  
   565  func TestRequirementSelectorMatching(t *testing.T) {
   566  	var req Requirement
   567  	labelSelectorMatchingTests := []struct {
   568  		Set   Set
   569  		Sel   Selector
   570  		Match bool
   571  	}{
   572  		{Set{"x": "foo", "y": "baz"}, &internalSelector{
   573  			req,
   574  		}, false},
   575  		{Set{"x": "foo", "y": "baz"}, &internalSelector{
   576  			getRequirement("x", selection.In, sets.NewString("foo"), t),
   577  			getRequirement("y", selection.NotIn, sets.NewString("alpha"), t),
   578  		}, true},
   579  		{Set{"x": "foo", "y": "baz"}, &internalSelector{
   580  			getRequirement("x", selection.In, sets.NewString("foo"), t),
   581  			getRequirement("y", selection.In, sets.NewString("alpha"), t),
   582  		}, false},
   583  		{Set{"y": ""}, &internalSelector{
   584  			getRequirement("x", selection.NotIn, sets.NewString(""), t),
   585  			getRequirement("y", selection.Exists, nil, t),
   586  		}, true},
   587  		{Set{"y": ""}, &internalSelector{
   588  			getRequirement("x", selection.DoesNotExist, nil, t),
   589  			getRequirement("y", selection.Exists, nil, t),
   590  		}, true},
   591  		{Set{"y": ""}, &internalSelector{
   592  			getRequirement("x", selection.NotIn, sets.NewString(""), t),
   593  			getRequirement("y", selection.DoesNotExist, nil, t),
   594  		}, false},
   595  		{Set{"y": "baz"}, &internalSelector{
   596  			getRequirement("x", selection.In, sets.NewString(""), t),
   597  		}, false},
   598  		{Set{"z": "2"}, &internalSelector{
   599  			getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
   600  		}, true},
   601  		{Set{"z": "v2"}, &internalSelector{
   602  			getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
   603  		}, false},
   604  	}
   605  	for _, lsm := range labelSelectorMatchingTests {
   606  		if match := lsm.Sel.Matches(lsm.Set); match != lsm.Match {
   607  			t.Errorf("%+v.Matches(%#v) => %v, want %v", lsm.Sel, lsm.Set, match, lsm.Match)
   608  		}
   609  	}
   610  }
   611  
   612  func TestSetSelectorParser(t *testing.T) {
   613  	setSelectorParserTests := []struct {
   614  		In    string
   615  		Out   Selector
   616  		Match bool
   617  		Valid bool
   618  	}{
   619  		{"", NewSelector(), true, true},
   620  		{"\rx", internalSelector{
   621  			getRequirement("x", selection.Exists, nil, t),
   622  		}, true, true},
   623  		{"this-is-a-dns.domain.com/key-with-dash", internalSelector{
   624  			getRequirement("this-is-a-dns.domain.com/key-with-dash", selection.Exists, nil, t),
   625  		}, true, true},
   626  		{"this-is-another-dns.domain.com/key-with-dash in (so,what)", internalSelector{
   627  			getRequirement("this-is-another-dns.domain.com/key-with-dash", selection.In, sets.NewString("so", "what"), t),
   628  		}, true, true},
   629  		{"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", internalSelector{
   630  			getRequirement("0.1.2.domain/99", selection.NotIn, sets.NewString("10.10.100.1", "tick.tack.clock"), t),
   631  		}, true, true},
   632  		{"foo  in	 (abc)", internalSelector{
   633  			getRequirement("foo", selection.In, sets.NewString("abc"), t),
   634  		}, true, true},
   635  		{"x notin\n (abc)", internalSelector{
   636  			getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
   637  		}, true, true},
   638  		{"x  notin	\t	(abc,def)", internalSelector{
   639  			getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
   640  		}, true, true},
   641  		{"x in (abc,def)", internalSelector{
   642  			getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
   643  		}, true, true},
   644  		{"x in (abc,)", internalSelector{
   645  			getRequirement("x", selection.In, sets.NewString("abc", ""), t),
   646  		}, true, true},
   647  		{"x in ()", internalSelector{
   648  			getRequirement("x", selection.In, sets.NewString(""), t),
   649  		}, true, true},
   650  		{"x notin (abc,,def),bar,z in (),w", internalSelector{
   651  			getRequirement("bar", selection.Exists, nil, t),
   652  			getRequirement("w", selection.Exists, nil, t),
   653  			getRequirement("x", selection.NotIn, sets.NewString("abc", "", "def"), t),
   654  			getRequirement("z", selection.In, sets.NewString(""), t),
   655  		}, true, true},
   656  		{"x,y in (a)", internalSelector{
   657  			getRequirement("y", selection.In, sets.NewString("a"), t),
   658  			getRequirement("x", selection.Exists, nil, t),
   659  		}, false, true},
   660  		{"x=a", internalSelector{
   661  			getRequirement("x", selection.Equals, sets.NewString("a"), t),
   662  		}, true, true},
   663  		{"x>1", internalSelector{
   664  			getRequirement("x", selection.GreaterThan, sets.NewString("1"), t),
   665  		}, true, true},
   666  		{"x<7", internalSelector{
   667  			getRequirement("x", selection.LessThan, sets.NewString("7"), t),
   668  		}, true, true},
   669  		{"x=a,y!=b", internalSelector{
   670  			getRequirement("x", selection.Equals, sets.NewString("a"), t),
   671  			getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
   672  		}, true, true},
   673  		{"x=a,y!=b,z in (h,i,j)", internalSelector{
   674  			getRequirement("x", selection.Equals, sets.NewString("a"), t),
   675  			getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
   676  			getRequirement("z", selection.In, sets.NewString("h", "i", "j"), t),
   677  		}, true, true},
   678  		{"x=a||y=b", internalSelector{}, false, false},
   679  		{"x,,y", nil, true, false},
   680  		{",x,y", nil, true, false},
   681  		{"x nott in (y)", nil, true, false},
   682  		{"x notin ( )", internalSelector{
   683  			getRequirement("x", selection.NotIn, sets.NewString(""), t),
   684  		}, true, true},
   685  		{"x notin (, a)", internalSelector{
   686  			getRequirement("x", selection.NotIn, sets.NewString("", "a"), t),
   687  		}, true, true},
   688  		{"a in (xyz),", nil, true, false},
   689  		{"a in (xyz)b notin ()", nil, true, false},
   690  		{"a ", internalSelector{
   691  			getRequirement("a", selection.Exists, nil, t),
   692  		}, true, true},
   693  		{"a in (x,y,notin, z,in)", internalSelector{
   694  			getRequirement("a", selection.In, sets.NewString("in", "notin", "x", "y", "z"), t),
   695  		}, true, true}, // operator 'in' inside list of identifiers
   696  		{"a in (xyz abc)", nil, false, false}, // no comma
   697  		{"a notin(", nil, true, false},        // bad formed
   698  		{"a (", nil, false, false},            // cpar
   699  		{"(", nil, false, false},              // opar
   700  	}
   701  
   702  	for _, ssp := range setSelectorParserTests {
   703  		if sel, err := Parse(ssp.In); err != nil && ssp.Valid {
   704  			t.Errorf("Parse(%s) => %v expected no error", ssp.In, err)
   705  		} else if err == nil && !ssp.Valid {
   706  			t.Errorf("Parse(%s) => %+v expected error", ssp.In, sel)
   707  		} else if ssp.Match && !reflect.DeepEqual(sel, ssp.Out) {
   708  			t.Errorf("Parse(%s) => parse output '%#v' doesn't match '%#v' expected match", ssp.In, sel, ssp.Out)
   709  		}
   710  	}
   711  }
   712  
   713  func getRequirement(key string, op selection.Operator, vals sets.String, t *testing.T) Requirement {
   714  	req, err := NewRequirement(key, op, vals.List())
   715  	if err != nil {
   716  		t.Errorf("NewRequirement(%v, %v, %v) resulted in error:%v", key, op, vals, err)
   717  		return Requirement{}
   718  	}
   719  	return *req
   720  }
   721  
   722  func TestAdd(t *testing.T) {
   723  	testCases := []struct {
   724  		name        string
   725  		sel         Selector
   726  		key         string
   727  		operator    selection.Operator
   728  		values      []string
   729  		refSelector Selector
   730  	}{
   731  		{
   732  			"keyInOperator",
   733  			internalSelector{},
   734  			"key",
   735  			selection.In,
   736  			[]string{"value"},
   737  			internalSelector{Requirement{"key", selection.In, []string{"value"}}},
   738  		},
   739  		{
   740  			"keyEqualsOperator",
   741  			internalSelector{Requirement{"key", selection.In, []string{"value"}}},
   742  			"key2",
   743  			selection.Equals,
   744  			[]string{"value2"},
   745  			internalSelector{
   746  				Requirement{"key", selection.In, []string{"value"}},
   747  				Requirement{"key2", selection.Equals, []string{"value2"}},
   748  			},
   749  		},
   750  	}
   751  	for _, ts := range testCases {
   752  		req, err := NewRequirement(ts.key, ts.operator, ts.values)
   753  		if err != nil {
   754  			t.Errorf("%s - Unable to create labels.Requirement", ts.name)
   755  		}
   756  		ts.sel = ts.sel.Add(*req)
   757  		if !reflect.DeepEqual(ts.sel, ts.refSelector) {
   758  			t.Errorf("%s - Expected %v found %v", ts.name, ts.refSelector, ts.sel)
   759  		}
   760  	}
   761  }
   762  
   763  func TestSafeSort(t *testing.T) {
   764  	tests := []struct {
   765  		name   string
   766  		in     []string
   767  		inCopy []string
   768  		want   []string
   769  	}{
   770  		{
   771  			name:   "nil strings",
   772  			in:     nil,
   773  			inCopy: nil,
   774  			want:   nil,
   775  		},
   776  		{
   777  			name:   "ordered strings",
   778  			in:     []string{"bar", "foo"},
   779  			inCopy: []string{"bar", "foo"},
   780  			want:   []string{"bar", "foo"},
   781  		},
   782  		{
   783  			name:   "unordered strings",
   784  			in:     []string{"foo", "bar"},
   785  			inCopy: []string{"foo", "bar"},
   786  			want:   []string{"bar", "foo"},
   787  		},
   788  		{
   789  			name:   "duplicated strings",
   790  			in:     []string{"foo", "bar", "foo", "bar"},
   791  			inCopy: []string{"foo", "bar", "foo", "bar"},
   792  			want:   []string{"bar", "bar", "foo", "foo"},
   793  		},
   794  	}
   795  	for _, tt := range tests {
   796  		t.Run(tt.name, func(t *testing.T) {
   797  			if got := safeSort(tt.in); !reflect.DeepEqual(got, tt.want) {
   798  				t.Errorf("safeSort() = %v, want %v", got, tt.want)
   799  			}
   800  			if !reflect.DeepEqual(tt.in, tt.inCopy) {
   801  				t.Errorf("after safeSort(), input = %v, want %v", tt.in, tt.inCopy)
   802  			}
   803  		})
   804  	}
   805  }
   806  
   807  func BenchmarkSelectorFromValidatedSet(b *testing.B) {
   808  	set := map[string]string{
   809  		"foo": "foo",
   810  		"bar": "bar",
   811  	}
   812  
   813  	for i := 0; i < b.N; i++ {
   814  		if SelectorFromValidatedSet(set).Empty() {
   815  			b.Errorf("Unexpected selector")
   816  		}
   817  	}
   818  }
   819  
   820  func TestRequiresExactMatch(t *testing.T) {
   821  	testCases := []struct {
   822  		name          string
   823  		sel           Selector
   824  		label         string
   825  		expectedFound bool
   826  		expectedValue string
   827  	}{
   828  		{
   829  			name:          "keyInOperatorExactMatch",
   830  			sel:           internalSelector{Requirement{"key", selection.In, []string{"value"}}},
   831  			label:         "key",
   832  			expectedFound: true,
   833  			expectedValue: "value",
   834  		},
   835  		{
   836  			name:          "keyInOperatorNotExactMatch",
   837  			sel:           internalSelector{Requirement{"key", selection.In, []string{"value", "value2"}}},
   838  			label:         "key",
   839  			expectedFound: false,
   840  			expectedValue: "",
   841  		},
   842  		{
   843  			name: "keyInOperatorNotExactMatch",
   844  			sel: internalSelector{
   845  				Requirement{"key", selection.In, []string{"value", "value1"}},
   846  				Requirement{"key2", selection.In, []string{"value2"}},
   847  			},
   848  			label:         "key2",
   849  			expectedFound: true,
   850  			expectedValue: "value2",
   851  		},
   852  		{
   853  			name:          "keyEqualOperatorExactMatch",
   854  			sel:           internalSelector{Requirement{"key", selection.Equals, []string{"value"}}},
   855  			label:         "key",
   856  			expectedFound: true,
   857  			expectedValue: "value",
   858  		},
   859  		{
   860  			name:          "keyDoubleEqualOperatorExactMatch",
   861  			sel:           internalSelector{Requirement{"key", selection.DoubleEquals, []string{"value"}}},
   862  			label:         "key",
   863  			expectedFound: true,
   864  			expectedValue: "value",
   865  		},
   866  		{
   867  			name:          "keyNotEqualOperatorExactMatch",
   868  			sel:           internalSelector{Requirement{"key", selection.NotEquals, []string{"value"}}},
   869  			label:         "key",
   870  			expectedFound: false,
   871  			expectedValue: "",
   872  		},
   873  		{
   874  			name: "keyEqualOperatorExactMatchFirst",
   875  			sel: internalSelector{
   876  				Requirement{"key", selection.In, []string{"value"}},
   877  				Requirement{"key2", selection.In, []string{"value2"}},
   878  			},
   879  			label:         "key",
   880  			expectedFound: true,
   881  			expectedValue: "value",
   882  		},
   883  	}
   884  	for _, ts := range testCases {
   885  		t.Run(ts.name, func(t *testing.T) {
   886  			value, found := ts.sel.RequiresExactMatch(ts.label)
   887  			if found != ts.expectedFound {
   888  				t.Errorf("Expected match %v, found %v", ts.expectedFound, found)
   889  			}
   890  			if found && value != ts.expectedValue {
   891  				t.Errorf("Expected value %v, found %v", ts.expectedValue, value)
   892  			}
   893  
   894  		})
   895  	}
   896  }
   897  
   898  func TestValidatedSelectorFromSet(t *testing.T) {
   899  	tests := []struct {
   900  		name             string
   901  		input            Set
   902  		expectedSelector internalSelector
   903  		expectedError    field.ErrorList
   904  	}{
   905  		{
   906  			name:  "Simple Set, no error",
   907  			input: Set{"key": "val"},
   908  			expectedSelector: internalSelector{
   909  				Requirement{
   910  					key:       "key",
   911  					operator:  selection.Equals,
   912  					strValues: []string{"val"},
   913  				},
   914  			},
   915  		},
   916  		{
   917  			name:  "Invalid Set, value too long",
   918  			input: Set{"Key": "axahm2EJ8Phiephe2eixohbee9eGeiyees1thuozi1xoh0GiuH3diewi8iem7Nui"},
   919  			expectedError: field.ErrorList{
   920  				&field.Error{
   921  					Type:     field.ErrorTypeInvalid,
   922  					Field:    "values[0][Key]",
   923  					BadValue: "axahm2EJ8Phiephe2eixohbee9eGeiyees1thuozi1xoh0GiuH3diewi8iem7Nui",
   924  				},
   925  			},
   926  		},
   927  	}
   928  
   929  	for _, tc := range tests {
   930  		selector, err := ValidatedSelectorFromSet(tc.input)
   931  		if diff := cmp.Diff(tc.expectedError.ToAggregate(), err, ignoreDetail); diff != "" {
   932  			t.Errorf("ValidatedSelectorFromSet %#v returned unexpected error (-want,+got):\n%s", tc.name, diff)
   933  		}
   934  		if err == nil {
   935  			if diff := cmp.Diff(tc.expectedSelector, selector); diff != "" {
   936  				t.Errorf("ValidatedSelectorFromSet %#v returned unexpected selector (-want,+got):\n%s", tc.name, diff)
   937  			}
   938  		}
   939  	}
   940  }
   941  
   942  func BenchmarkRequirementString(b *testing.B) {
   943  	r := Requirement{
   944  		key:      "environment",
   945  		operator: selection.NotIn,
   946  		strValues: []string{
   947  			"dev",
   948  		},
   949  	}
   950  
   951  	b.ReportAllocs()
   952  	b.ResetTimer()
   953  	for i := 0; i < b.N; i++ {
   954  		if r.String() != "environment notin (dev)" {
   955  			b.Errorf("Unexpected Requirement string")
   956  		}
   957  	}
   958  }
   959  
   960  func TestRequirementEqual(t *testing.T) {
   961  	tests := []struct {
   962  		name string
   963  		x, y *Requirement
   964  		want bool
   965  	}{
   966  		{
   967  			name: "same requirements should be equal",
   968  			x: &Requirement{
   969  				key:       "key",
   970  				operator:  selection.Equals,
   971  				strValues: []string{"foo", "bar"},
   972  			},
   973  			y: &Requirement{
   974  				key:       "key",
   975  				operator:  selection.Equals,
   976  				strValues: []string{"foo", "bar"},
   977  			},
   978  			want: true,
   979  		},
   980  		{
   981  			name: "requirements with different keys should not be equal",
   982  			x: &Requirement{
   983  				key:       "key1",
   984  				operator:  selection.Equals,
   985  				strValues: []string{"foo", "bar"},
   986  			},
   987  			y: &Requirement{
   988  				key:       "key2",
   989  				operator:  selection.Equals,
   990  				strValues: []string{"foo", "bar"},
   991  			},
   992  			want: false,
   993  		},
   994  		{
   995  			name: "requirements with different operators should not be equal",
   996  			x: &Requirement{
   997  				key:       "key",
   998  				operator:  selection.Equals,
   999  				strValues: []string{"foo", "bar"},
  1000  			},
  1001  			y: &Requirement{
  1002  				key:       "key",
  1003  				operator:  selection.In,
  1004  				strValues: []string{"foo", "bar"},
  1005  			},
  1006  			want: false,
  1007  		},
  1008  		{
  1009  			name: "requirements with different values should not be equal",
  1010  			x: &Requirement{
  1011  				key:       "key",
  1012  				operator:  selection.Equals,
  1013  				strValues: []string{"foo", "bar"},
  1014  			},
  1015  			y: &Requirement{
  1016  				key:       "key",
  1017  				operator:  selection.Equals,
  1018  				strValues: []string{"foobar"},
  1019  			},
  1020  			want: false,
  1021  		},
  1022  	}
  1023  	for _, tt := range tests {
  1024  		t.Run(tt.name, func(t *testing.T) {
  1025  			if got := cmp.Equal(tt.x, tt.y); got != tt.want {
  1026  				t.Errorf("cmp.Equal() = %v, want %v", got, tt.want)
  1027  			}
  1028  		})
  1029  	}
  1030  }