Exemple #1
0
func TestAdd(t *testing.T) {
	testCases := []struct {
		sel         Selector
		key         string
		operator    Operator
		values      []string
		refSelector Selector
	}{
		{
			LabelSelector{},
			"key",
			InOperator,
			[]string{"value"},
			LabelSelector{Requirement{"key", InOperator, util.NewStringSet("value")}},
		},
		{
			LabelSelector{Requirement{"key", InOperator, util.NewStringSet("value")}},
			"key2",
			EqualsOperator,
			[]string{"value2"},
			LabelSelector{
				Requirement{"key", InOperator, util.NewStringSet("value")},
				Requirement{"key2", EqualsOperator, util.NewStringSet("value2")},
			},
		},
	}
	for _, ts := range testCases {
		ts.sel = ts.sel.Add(ts.key, ts.operator, ts.values)
		if !reflect.DeepEqual(ts.sel, ts.refSelector) {
			t.Errorf("Expected %t found %t", ts.refSelector, ts.sel)
		}
	}
}
Exemple #2
0
func TestToString(t *testing.T) {
	var req Requirement
	toStringTests := []struct {
		In    *LabelSelector
		Out   string
		Valid bool
	}{
		{&LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t),
			getRequirement("y", NotInOperator, util.NewStringSet("jkl"), t),
			getRequirement("z", ExistsOperator, nil, t)},
			"x in (abc,def),y notin (jkl),z", true},
		{&LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t),
			req}, // adding empty req for the trailing ','
			"x in (abc,def),", false},
		{&LabelSelector{
			getRequirement("x", NotInOperator, util.NewStringSet("abc"), t),
			getRequirement("y", InOperator, util.NewStringSet("jkl", "mno"), t),
			getRequirement("z", NotInOperator, util.NewStringSet(""), t)},
			"x notin (abc),y in (jkl,mno),z notin ()", true},
		{&LabelSelector{
			getRequirement("x", EqualsOperator, util.NewStringSet("abc"), t),
			getRequirement("y", DoubleEqualsOperator, util.NewStringSet("jkl"), t),
			getRequirement("z", NotEqualsOperator, util.NewStringSet("a"), t)},
			"x=abc,y==jkl,z!=a", true},
	}
	for _, ts := range toStringTests {
		if out := ts.In.String(); out == "" && ts.Valid {
			t.Errorf("%+v.String() => '%v' expected no error", ts.In, out)
		} else if out != ts.Out {
			t.Errorf("%+v.String() => '%v' want '%v'", ts.In, out, ts.Out)
		}
	}
}
Exemple #3
0
// parseIdentifiersList parses a (possibly empty) list of
// of comma separated (possibly empty) identifiers
func (p *Parser) parseIdentifiersList() (util.StringSet, error) {
	s := util.NewStringSet()
	for {
		tok, lit := p.consume(Values)
		switch tok {
		case IdentifierToken:
			s.Insert(lit)
			tok2, lit2 := p.lookahead(Values)
			switch tok2 {
			case CommaToken:
				continue
			case ClosedParToken:
				return s, nil
			default:
				return nil, fmt.Errorf("found '%s', expected: ',' or ')'", lit2)
			}
		case CommaToken: // handled here since we can have "(,"
			if s.Len() == 0 {
				s.Insert("") // to handle (,
			}
			tok2, _ := p.lookahead(Values)
			if tok2 == ClosedParToken {
				s.Insert("") // to handle ,)  Double "" removed by StringSet
				return s, nil
			}
			if tok2 == CommaToken {
				p.consume(Values)
				s.Insert("") // to handle ,, Double "" removed by StringSet
			}
		default: // it can be operator
			return s, fmt.Errorf("found '%s', expected: ',', or identifier", lit)
		}
	}
}
Exemple #4
0
// parseExactValue parses the only value for exact match style
func (p *Parser) parseExactValue() (util.StringSet, error) {
	s := util.NewStringSet()
	tok, lit := p.consume(Values)
	if tok == IdentifierToken {
		s.Insert(lit)
		return s, nil
	}
	return nil, fmt.Errorf("found '%s', expected: identifier", lit)
}
Exemple #5
0
// Add adds a requirement to the selector. It copies the current selector returning a new one
func (lsel LabelSelector) Add(key string, operator Operator, values []string) Selector {
	var reqs []Requirement
	for _, item := range lsel {
		reqs = append(reqs, item)
	}
	if r, err := NewRequirement(key, operator, util.NewStringSet(values...)); err == nil {
		reqs = append(reqs, *r)
	}
	return LabelSelector(reqs)
}
Exemple #6
0
func TestRequirementLabelSelectorMatching(t *testing.T) {
	var req Requirement
	labelSelectorMatchingTests := []struct {
		Set   Set
		Sel   *LabelSelector
		Match bool
	}{
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{
			req,
		}, false},
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet("foo"), t),
			getRequirement("y", NotInOperator, util.NewStringSet("alpha"), t),
		}, true},
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet("foo"), t),
			getRequirement("y", InOperator, util.NewStringSet("alpha"), t),
		}, false},
		{Set{"y": ""}, &LabelSelector{
			getRequirement("x", NotInOperator, util.NewStringSet(""), t),
			getRequirement("y", ExistsOperator, nil, t),
		}, true},
		{Set{"y": "baz"}, &LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet(""), t),
		}, false},
	}
	for _, lsm := range labelSelectorMatchingTests {
		if match := lsm.Sel.Matches(lsm.Set); match != lsm.Match {
			t.Errorf("%+v.Matches(%#v) => %v, want %v", lsm.Sel, lsm.Set, match, lsm.Match)
		}
	}
}
Exemple #7
0
func TestRequirementConstructor(t *testing.T) {
	requirementConstructorTests := []struct {
		Key     string
		Op      Operator
		Vals    util.StringSet
		Success bool
	}{
		{"x", InOperator, nil, false},
		{"x", NotInOperator, util.NewStringSet(), false},
		{"x", InOperator, util.NewStringSet("foo"), true},
		{"x", NotInOperator, util.NewStringSet("foo"), true},
		{"x", ExistsOperator, nil, true},
		{"1foo", InOperator, util.NewStringSet("bar"), true},
		{"1234", InOperator, util.NewStringSet("bar"), true},
		{strings.Repeat("a", 254), ExistsOperator, nil, false}, //breaks DNS rule that len(key) <= 253
	}
	for _, rc := range requirementConstructorTests {
		if _, err := NewRequirement(rc.Key, rc.Op, rc.Vals); err == nil && !rc.Success {
			t.Errorf("expected error with key:%#v op:%v vals:%v, got no error", rc.Key, rc.Op, rc.Vals)
		} else if err != nil && rc.Success {
			t.Errorf("expected no error with key:%#v op:%v vals:%v, got:%v", rc.Key, rc.Op, rc.Vals, err)
		}
	}
}
Exemple #8
0
// SelectorFromSet returns a Selector which will match exactly the given Set. A
// nil and empty Sets are considered equivalent to Everything().
func SelectorFromSet(ls Set) Selector {
	if ls == nil {
		return LabelSelector{}
	}
	var requirements []Requirement
	for label, value := range ls {
		if r, err := NewRequirement(label, EqualsOperator, util.NewStringSet(value)); err != nil {
			//TODO: double check errors when input comes from serialization?
			return LabelSelector{}
		} else {
			requirements = append(requirements, *r)
		}
	}
	return LabelSelector(requirements)
}
Exemple #9
0
// parseValues parses the values for set based matching (x,y,z)
func (p *Parser) parseValues() (util.StringSet, error) {
	tok, lit := p.consume(Values)
	if tok != OpenParToken {
		return nil, fmt.Errorf("found '%s' expected: '('", lit)
	}
	tok, lit = p.lookahead(Values)
	switch tok {
	case IdentifierToken, CommaToken:
		s, err := p.parseIdentifiersList() // handles general cases
		if err != nil {
			return s, err
		}
		if tok, _ = p.consume(Values); tok != ClosedParToken {
			return nil, fmt.Errorf("found '%s', expected: ')'", lit)
		}
		return s, nil
	case ClosedParToken: // handles "()"
		p.consume(Values)
		return util.NewStringSet(""), nil
	default:
		return nil, fmt.Errorf("found '%s', expected: ',', ')' or identifier", lit)
	}
	return util.NewStringSet(), nil
}
Exemple #10
0
func TestSetSelectorParser(t *testing.T) {
	setSelectorParserTests := []struct {
		In    string
		Out   Selector
		Match bool
		Valid bool
	}{
		{"", LabelSelector(nil), true, true},
		{"\rx", LabelSelector{
			getRequirement("x", ExistsOperator, nil, t),
		}, true, true},
		{"this-is-a-dns.domain.com/key-with-dash", LabelSelector{
			getRequirement("this-is-a-dns.domain.com/key-with-dash", ExistsOperator, nil, t),
		}, true, true},
		{"this-is-another-dns.domain.com/key-with-dash in (so,what)", LabelSelector{
			getRequirement("this-is-another-dns.domain.com/key-with-dash", InOperator, util.NewStringSet("so", "what"), t),
		}, true, true},
		{"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", LabelSelector{
			getRequirement("0.1.2.domain/99", NotInOperator, util.NewStringSet("10.10.100.1", "tick.tack.clock"), t),
		}, true, true},
		{"foo  in	 (abc)", LabelSelector{
			getRequirement("foo", InOperator, util.NewStringSet("abc"), t),
		}, true, true},
		{"x notin\n (abc)", LabelSelector{
			getRequirement("x", NotInOperator, util.NewStringSet("abc"), t),
		}, true, true},
		{"x  notin	\t	(abc,def)", LabelSelector{
			getRequirement("x", NotInOperator, util.NewStringSet("abc", "def"), t),
		}, true, true},
		{"x in (abc,def)", LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t),
		}, true, true},
		{"x in (abc,)", LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet("abc", ""), t),
		}, true, true},
		{"x in ()", LabelSelector{
			getRequirement("x", InOperator, util.NewStringSet(""), t),
		}, true, true},
		{"x notin (abc,,def),bar,z in (),w", LabelSelector{
			getRequirement("bar", ExistsOperator, nil, t),
			getRequirement("w", ExistsOperator, nil, t),
			getRequirement("x", NotInOperator, util.NewStringSet("abc", "", "def"), t),
			getRequirement("z", InOperator, util.NewStringSet(""), t),
		}, true, true},
		{"x,y in (a)", LabelSelector{
			getRequirement("y", InOperator, util.NewStringSet("a"), t),
			getRequirement("x", ExistsOperator, nil, t),
		}, false, true},
		{"x=a", LabelSelector{
			getRequirement("x", EqualsOperator, util.NewStringSet("a"), t),
		}, true, true},
		{"x=a,y!=b", LabelSelector{
			getRequirement("x", EqualsOperator, util.NewStringSet("a"), t),
			getRequirement("y", NotEqualsOperator, util.NewStringSet("b"), t),
		}, true, true},
		{"x=a,y!=b,z in (h,i,j)", LabelSelector{
			getRequirement("x", EqualsOperator, util.NewStringSet("a"), t),
			getRequirement("y", NotEqualsOperator, util.NewStringSet("b"), t),
			getRequirement("z", InOperator, util.NewStringSet("h", "i", "j"), t),
		}, true, true},
		{"x=a||y=b", LabelSelector{}, false, false},
		{"x,,y", nil, true, false},
		{",x,y", nil, true, false},
		{"x nott in (y)", nil, true, false},
		{"x notin ( )", LabelSelector{
			getRequirement("x", NotInOperator, util.NewStringSet(""), t),
		}, true, true},
		{"x notin (, a)", LabelSelector{
			getRequirement("x", NotInOperator, util.NewStringSet("", "a"), t),
		}, true, true},
		{"a in (xyz),", nil, true, false},
		{"a in (xyz)b notin ()", nil, true, false},
		{"a ", LabelSelector{
			getRequirement("a", ExistsOperator, nil, t),
		}, true, true},
		{"a in (x,y,notin, z,in)", LabelSelector{
			getRequirement("a", InOperator, util.NewStringSet("in", "notin", "x", "y", "z"), t),
		}, true, true}, // operator 'in' inside list of identifiers
		{"a in (xyz abc)", nil, false, false}, // no comma
		{"a notin(", nil, true, false},        // bad formed
		{"a (", nil, false, false},            // cpar
		{"(", nil, false, false},              // opar
	}

	for _, ssp := range setSelectorParserTests {
		if sel, err := Parse(ssp.In); err != nil && ssp.Valid {
			t.Errorf("Parse(%s) => %v expected no error", ssp.In, err)
		} else if err == nil && !ssp.Valid {
			t.Errorf("Parse(%s) => %+v expected error", ssp.In, sel)
		} else if ssp.Match && !reflect.DeepEqual(sel, ssp.Out) {
			t.Errorf("Parse(%s) => parse output '%t' doesn't match '%t' expected match", ssp.In, sel, ssp.Out)
		}
	}
}