selector_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package labels
  14. import (
  15. "reflect"
  16. "strings"
  17. "testing"
  18. "k8s.io/kubernetes/pkg/selection"
  19. "k8s.io/kubernetes/pkg/util/sets"
  20. )
  21. func TestSelectorParse(t *testing.T) {
  22. testGoodStrings := []string{
  23. "x=a,y=b,z=c",
  24. "",
  25. "x!=a,y=b",
  26. "x=",
  27. "x= ",
  28. "x=,z= ",
  29. "x= ,z= ",
  30. "!x",
  31. "x>1",
  32. "x>1,z<5",
  33. }
  34. testBadStrings := []string{
  35. "x=a||y=b",
  36. "x==a==b",
  37. "!x=a",
  38. "x<a",
  39. }
  40. for _, test := range testGoodStrings {
  41. lq, err := Parse(test)
  42. if err != nil {
  43. t.Errorf("%v: error %v (%#v)\n", test, err, err)
  44. }
  45. if strings.Replace(test, " ", "", -1) != lq.String() {
  46. t.Errorf("%v restring gave: %v\n", test, lq.String())
  47. }
  48. }
  49. for _, test := range testBadStrings {
  50. _, err := Parse(test)
  51. if err == nil {
  52. t.Errorf("%v: did not get expected error\n", test)
  53. }
  54. }
  55. }
  56. func TestDeterministicParse(t *testing.T) {
  57. s1, err := Parse("x=a,a=x")
  58. s2, err2 := Parse("a=x,x=a")
  59. if err != nil || err2 != nil {
  60. t.Errorf("Unexpected parse error")
  61. }
  62. if s1.String() != s2.String() {
  63. t.Errorf("Non-deterministic parse")
  64. }
  65. }
  66. func expectMatch(t *testing.T, selector string, ls Set) {
  67. lq, err := Parse(selector)
  68. if err != nil {
  69. t.Errorf("Unable to parse %v as a selector\n", selector)
  70. return
  71. }
  72. if !lq.Matches(ls) {
  73. t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
  74. }
  75. }
  76. func expectNoMatch(t *testing.T, selector string, ls Set) {
  77. lq, err := Parse(selector)
  78. if err != nil {
  79. t.Errorf("Unable to parse %v as a selector\n", selector)
  80. return
  81. }
  82. if lq.Matches(ls) {
  83. t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
  84. }
  85. }
  86. func TestEverything(t *testing.T) {
  87. if !Everything().Matches(Set{"x": "y"}) {
  88. t.Errorf("Nil selector didn't match")
  89. }
  90. if !Everything().Empty() {
  91. t.Errorf("Everything was not empty")
  92. }
  93. }
  94. func TestSelectorMatches(t *testing.T) {
  95. expectMatch(t, "", Set{"x": "y"})
  96. expectMatch(t, "x=y", Set{"x": "y"})
  97. expectMatch(t, "x=y,z=w", Set{"x": "y", "z": "w"})
  98. expectMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "a"})
  99. expectMatch(t, "notin=in", Set{"notin": "in"}) // in and notin in exactMatch
  100. expectMatch(t, "x", Set{"x": "z"})
  101. expectMatch(t, "!x", Set{"y": "z"})
  102. expectMatch(t, "x>1", Set{"x": "2"})
  103. expectMatch(t, "x<1", Set{"x": "0"})
  104. expectNoMatch(t, "x=z", Set{})
  105. expectNoMatch(t, "x=y", Set{"x": "z"})
  106. expectNoMatch(t, "x=y,z=w", Set{"x": "w", "z": "w"})
  107. expectNoMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "w"})
  108. expectNoMatch(t, "x", Set{"y": "z"})
  109. expectNoMatch(t, "!x", Set{"x": "z"})
  110. expectNoMatch(t, "x>1", Set{"x": "0"})
  111. expectNoMatch(t, "x<1", Set{"x": "2"})
  112. labelset := Set{
  113. "foo": "bar",
  114. "baz": "blah",
  115. }
  116. expectMatch(t, "foo=bar", labelset)
  117. expectMatch(t, "baz=blah", labelset)
  118. expectMatch(t, "foo=bar,baz=blah", labelset)
  119. expectNoMatch(t, "foo=blah", labelset)
  120. expectNoMatch(t, "baz=bar", labelset)
  121. expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", labelset)
  122. }
  123. func expectMatchDirect(t *testing.T, selector, ls Set) {
  124. if !SelectorFromSet(selector).Matches(ls) {
  125. t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
  126. }
  127. }
  128. func expectNoMatchDirect(t *testing.T, selector, ls Set) {
  129. if SelectorFromSet(selector).Matches(ls) {
  130. t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
  131. }
  132. }
  133. func TestSetMatches(t *testing.T) {
  134. labelset := Set{
  135. "foo": "bar",
  136. "baz": "blah",
  137. }
  138. expectMatchDirect(t, Set{}, labelset)
  139. expectMatchDirect(t, Set{"foo": "bar"}, labelset)
  140. expectMatchDirect(t, Set{"baz": "blah"}, labelset)
  141. expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset)
  142. //TODO: bad values not handled for the moment in SelectorFromSet
  143. //expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset)
  144. //expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset)
  145. //expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset)
  146. }
  147. func TestNilMapIsValid(t *testing.T) {
  148. selector := Set(nil).AsSelector()
  149. if selector == nil {
  150. t.Errorf("Selector for nil set should be Everything")
  151. }
  152. if !selector.Empty() {
  153. t.Errorf("Selector for nil set should be Empty")
  154. }
  155. }
  156. func TestSetIsEmpty(t *testing.T) {
  157. if !(Set{}).AsSelector().Empty() {
  158. t.Errorf("Empty set should be empty")
  159. }
  160. if !(NewSelector()).Empty() {
  161. t.Errorf("Nil Selector should be empty")
  162. }
  163. }
  164. func TestLexer(t *testing.T) {
  165. testcases := []struct {
  166. s string
  167. t Token
  168. }{
  169. {"", EndOfStringToken},
  170. {",", CommaToken},
  171. {"notin", NotInToken},
  172. {"in", InToken},
  173. {"=", EqualsToken},
  174. {"==", DoubleEqualsToken},
  175. {">", GreaterThanToken},
  176. {"<", LessThanToken},
  177. //Note that Lex returns the longest valid token found
  178. {"!", DoesNotExistToken},
  179. {"!=", NotEqualsToken},
  180. {"(", OpenParToken},
  181. {")", ClosedParToken},
  182. //Non-"special" characters are considered part of an identifier
  183. {"~", IdentifierToken},
  184. {"||", IdentifierToken},
  185. }
  186. for _, v := range testcases {
  187. l := &Lexer{s: v.s, pos: 0}
  188. token, lit := l.Lex()
  189. if token != v.t {
  190. t.Errorf("Got %d it should be %d for '%s'", token, v.t, v.s)
  191. }
  192. if v.t != ErrorToken && lit != v.s {
  193. t.Errorf("Got '%s' it should be '%s'", lit, v.s)
  194. }
  195. }
  196. }
  197. func min(l, r int) (m int) {
  198. m = r
  199. if l < r {
  200. m = l
  201. }
  202. return m
  203. }
  204. func TestLexerSequence(t *testing.T) {
  205. testcases := []struct {
  206. s string
  207. t []Token
  208. }{
  209. {"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken}},
  210. {"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken}},
  211. {"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken}},
  212. {"key", []Token{IdentifierToken}},
  213. {"!key", []Token{DoesNotExistToken, IdentifierToken}},
  214. {"()", []Token{OpenParToken, ClosedParToken}},
  215. {"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken}},
  216. {"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken}},
  217. {"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken}},
  218. {"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken}},
  219. }
  220. for _, v := range testcases {
  221. var literals []string
  222. var tokens []Token
  223. l := &Lexer{s: v.s, pos: 0}
  224. for {
  225. token, lit := l.Lex()
  226. if token == EndOfStringToken {
  227. break
  228. }
  229. tokens = append(tokens, token)
  230. literals = append(literals, lit)
  231. }
  232. if len(tokens) != len(v.t) {
  233. t.Errorf("Bad number of tokens for '%s %d, %d", v.s, len(tokens), len(v.t))
  234. }
  235. for i := 0; i < min(len(tokens), len(v.t)); i++ {
  236. if tokens[i] != v.t[i] {
  237. t.Errorf("Test '%s': Mismatching in token type found '%v' it should be '%v'", v.s, tokens[i], v.t[i])
  238. }
  239. }
  240. }
  241. }
  242. func TestParserLookahead(t *testing.T) {
  243. testcases := []struct {
  244. s string
  245. t []Token
  246. }{
  247. {"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
  248. {"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
  249. {"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
  250. {"key", []Token{IdentifierToken, EndOfStringToken}},
  251. {"!key", []Token{DoesNotExistToken, IdentifierToken, EndOfStringToken}},
  252. {"()", []Token{OpenParToken, ClosedParToken, EndOfStringToken}},
  253. {"", []Token{EndOfStringToken}},
  254. {"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken, EndOfStringToken}},
  255. {"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken, EndOfStringToken}},
  256. {"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken, EndOfStringToken}},
  257. {"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken, EndOfStringToken}},
  258. }
  259. for _, v := range testcases {
  260. p := &Parser{l: &Lexer{s: v.s, pos: 0}, position: 0}
  261. p.scan()
  262. if len(p.scannedItems) != len(v.t) {
  263. t.Errorf("Expected %d items found %d", len(v.t), len(p.scannedItems))
  264. }
  265. for {
  266. token, lit := p.lookahead(KeyAndOperator)
  267. token2, lit2 := p.consume(KeyAndOperator)
  268. if token == EndOfStringToken {
  269. break
  270. }
  271. if token != token2 || lit != lit2 {
  272. t.Errorf("Bad values")
  273. }
  274. }
  275. }
  276. }
  277. func TestRequirementConstructor(t *testing.T) {
  278. requirementConstructorTests := []struct {
  279. Key string
  280. Op selection.Operator
  281. Vals sets.String
  282. Success bool
  283. }{
  284. {"x", selection.In, nil, false},
  285. {"x", selection.NotIn, sets.NewString(), false},
  286. {"x", selection.In, sets.NewString("foo"), true},
  287. {"x", selection.NotIn, sets.NewString("foo"), true},
  288. {"x", selection.Exists, nil, true},
  289. {"x", selection.DoesNotExist, nil, true},
  290. {"1foo", selection.In, sets.NewString("bar"), true},
  291. {"1234", selection.In, sets.NewString("bar"), true},
  292. {"y", selection.GreaterThan, sets.NewString("1"), true},
  293. {"z", selection.LessThan, sets.NewString("6"), true},
  294. {"foo", selection.GreaterThan, sets.NewString("bar"), false},
  295. {"barz", selection.LessThan, sets.NewString("blah"), false},
  296. {strings.Repeat("a", 254), selection.Exists, nil, false}, //breaks DNS rule that len(key) <= 253
  297. }
  298. for _, rc := range requirementConstructorTests {
  299. if _, err := NewRequirement(rc.Key, rc.Op, rc.Vals); err == nil && !rc.Success {
  300. t.Errorf("expected error with key:%#v op:%v vals:%v, got no error", rc.Key, rc.Op, rc.Vals)
  301. } else if err != nil && rc.Success {
  302. t.Errorf("expected no error with key:%#v op:%v vals:%v, got:%v", rc.Key, rc.Op, rc.Vals, err)
  303. }
  304. }
  305. }
  306. func TestToString(t *testing.T) {
  307. var req Requirement
  308. toStringTests := []struct {
  309. In *internalSelector
  310. Out string
  311. Valid bool
  312. }{
  313. {&internalSelector{
  314. getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
  315. getRequirement("y", selection.NotIn, sets.NewString("jkl"), t),
  316. getRequirement("z", selection.Exists, nil, t)},
  317. "x in (abc,def),y notin (jkl),z", true},
  318. {&internalSelector{
  319. getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
  320. getRequirement("y", selection.NotEquals, sets.NewString("jkl"), t),
  321. getRequirement("z", selection.DoesNotExist, nil, t)},
  322. "x notin (abc,def),y!=jkl,!z", true},
  323. {&internalSelector{
  324. getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
  325. req}, // adding empty req for the trailing ','
  326. "x in (abc,def),", false},
  327. {&internalSelector{
  328. getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
  329. getRequirement("y", selection.In, sets.NewString("jkl", "mno"), t),
  330. getRequirement("z", selection.NotIn, sets.NewString(""), t)},
  331. "x notin (abc),y in (jkl,mno),z notin ()", true},
  332. {&internalSelector{
  333. getRequirement("x", selection.Equals, sets.NewString("abc"), t),
  334. getRequirement("y", selection.DoubleEquals, sets.NewString("jkl"), t),
  335. getRequirement("z", selection.NotEquals, sets.NewString("a"), t),
  336. getRequirement("z", selection.Exists, nil, t)},
  337. "x=abc,y==jkl,z!=a,z", true},
  338. {&internalSelector{
  339. getRequirement("x", selection.GreaterThan, sets.NewString("2"), t),
  340. getRequirement("y", selection.LessThan, sets.NewString("8"), t),
  341. getRequirement("z", selection.Exists, nil, t)},
  342. "x>2,y<8,z", true},
  343. }
  344. for _, ts := range toStringTests {
  345. if out := ts.In.String(); out == "" && ts.Valid {
  346. t.Errorf("%#v.String() => '%v' expected no error", ts.In, out)
  347. } else if out != ts.Out {
  348. t.Errorf("%#v.String() => '%v' want '%v'", ts.In, out, ts.Out)
  349. }
  350. }
  351. }
  352. func TestRequirementSelectorMatching(t *testing.T) {
  353. var req Requirement
  354. labelSelectorMatchingTests := []struct {
  355. Set Set
  356. Sel Selector
  357. Match bool
  358. }{
  359. {Set{"x": "foo", "y": "baz"}, &internalSelector{
  360. req,
  361. }, false},
  362. {Set{"x": "foo", "y": "baz"}, &internalSelector{
  363. getRequirement("x", selection.In, sets.NewString("foo"), t),
  364. getRequirement("y", selection.NotIn, sets.NewString("alpha"), t),
  365. }, true},
  366. {Set{"x": "foo", "y": "baz"}, &internalSelector{
  367. getRequirement("x", selection.In, sets.NewString("foo"), t),
  368. getRequirement("y", selection.In, sets.NewString("alpha"), t),
  369. }, false},
  370. {Set{"y": ""}, &internalSelector{
  371. getRequirement("x", selection.NotIn, sets.NewString(""), t),
  372. getRequirement("y", selection.Exists, nil, t),
  373. }, true},
  374. {Set{"y": ""}, &internalSelector{
  375. getRequirement("x", selection.DoesNotExist, nil, t),
  376. getRequirement("y", selection.Exists, nil, t),
  377. }, true},
  378. {Set{"y": ""}, &internalSelector{
  379. getRequirement("x", selection.NotIn, sets.NewString(""), t),
  380. getRequirement("y", selection.DoesNotExist, nil, t),
  381. }, false},
  382. {Set{"y": "baz"}, &internalSelector{
  383. getRequirement("x", selection.In, sets.NewString(""), t),
  384. }, false},
  385. {Set{"z": "2"}, &internalSelector{
  386. getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
  387. }, true},
  388. {Set{"z": "v2"}, &internalSelector{
  389. getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
  390. }, false},
  391. }
  392. for _, lsm := range labelSelectorMatchingTests {
  393. if match := lsm.Sel.Matches(lsm.Set); match != lsm.Match {
  394. t.Errorf("%+v.Matches(%#v) => %v, want %v", lsm.Sel, lsm.Set, match, lsm.Match)
  395. }
  396. }
  397. }
  398. func TestSetSelectorParser(t *testing.T) {
  399. setSelectorParserTests := []struct {
  400. In string
  401. Out Selector
  402. Match bool
  403. Valid bool
  404. }{
  405. {"", NewSelector(), true, true},
  406. {"\rx", internalSelector{
  407. getRequirement("x", selection.Exists, nil, t),
  408. }, true, true},
  409. {"this-is-a-dns.domain.com/key-with-dash", internalSelector{
  410. getRequirement("this-is-a-dns.domain.com/key-with-dash", selection.Exists, nil, t),
  411. }, true, true},
  412. {"this-is-another-dns.domain.com/key-with-dash in (so,what)", internalSelector{
  413. getRequirement("this-is-another-dns.domain.com/key-with-dash", selection.In, sets.NewString("so", "what"), t),
  414. }, true, true},
  415. {"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", internalSelector{
  416. getRequirement("0.1.2.domain/99", selection.NotIn, sets.NewString("10.10.100.1", "tick.tack.clock"), t),
  417. }, true, true},
  418. {"foo in (abc)", internalSelector{
  419. getRequirement("foo", selection.In, sets.NewString("abc"), t),
  420. }, true, true},
  421. {"x notin\n (abc)", internalSelector{
  422. getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
  423. }, true, true},
  424. {"x notin \t (abc,def)", internalSelector{
  425. getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
  426. }, true, true},
  427. {"x in (abc,def)", internalSelector{
  428. getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
  429. }, true, true},
  430. {"x in (abc,)", internalSelector{
  431. getRequirement("x", selection.In, sets.NewString("abc", ""), t),
  432. }, true, true},
  433. {"x in ()", internalSelector{
  434. getRequirement("x", selection.In, sets.NewString(""), t),
  435. }, true, true},
  436. {"x notin (abc,,def),bar,z in (),w", internalSelector{
  437. getRequirement("bar", selection.Exists, nil, t),
  438. getRequirement("w", selection.Exists, nil, t),
  439. getRequirement("x", selection.NotIn, sets.NewString("abc", "", "def"), t),
  440. getRequirement("z", selection.In, sets.NewString(""), t),
  441. }, true, true},
  442. {"x,y in (a)", internalSelector{
  443. getRequirement("y", selection.In, sets.NewString("a"), t),
  444. getRequirement("x", selection.Exists, nil, t),
  445. }, false, true},
  446. {"x=a", internalSelector{
  447. getRequirement("x", selection.Equals, sets.NewString("a"), t),
  448. }, true, true},
  449. {"x>1", internalSelector{
  450. getRequirement("x", selection.GreaterThan, sets.NewString("1"), t),
  451. }, true, true},
  452. {"x<7", internalSelector{
  453. getRequirement("x", selection.LessThan, sets.NewString("7"), t),
  454. }, true, true},
  455. {"x=a,y!=b", internalSelector{
  456. getRequirement("x", selection.Equals, sets.NewString("a"), t),
  457. getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
  458. }, true, true},
  459. {"x=a,y!=b,z in (h,i,j)", internalSelector{
  460. getRequirement("x", selection.Equals, sets.NewString("a"), t),
  461. getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
  462. getRequirement("z", selection.In, sets.NewString("h", "i", "j"), t),
  463. }, true, true},
  464. {"x=a||y=b", internalSelector{}, false, false},
  465. {"x,,y", nil, true, false},
  466. {",x,y", nil, true, false},
  467. {"x nott in (y)", nil, true, false},
  468. {"x notin ( )", internalSelector{
  469. getRequirement("x", selection.NotIn, sets.NewString(""), t),
  470. }, true, true},
  471. {"x notin (, a)", internalSelector{
  472. getRequirement("x", selection.NotIn, sets.NewString("", "a"), t),
  473. }, true, true},
  474. {"a in (xyz),", nil, true, false},
  475. {"a in (xyz)b notin ()", nil, true, false},
  476. {"a ", internalSelector{
  477. getRequirement("a", selection.Exists, nil, t),
  478. }, true, true},
  479. {"a in (x,y,notin, z,in)", internalSelector{
  480. getRequirement("a", selection.In, sets.NewString("in", "notin", "x", "y", "z"), t),
  481. }, true, true}, // operator 'in' inside list of identifiers
  482. {"a in (xyz abc)", nil, false, false}, // no comma
  483. {"a notin(", nil, true, false}, // bad formed
  484. {"a (", nil, false, false}, // cpar
  485. {"(", nil, false, false}, // opar
  486. }
  487. for _, ssp := range setSelectorParserTests {
  488. if sel, err := Parse(ssp.In); err != nil && ssp.Valid {
  489. t.Errorf("Parse(%s) => %v expected no error", ssp.In, err)
  490. } else if err == nil && !ssp.Valid {
  491. t.Errorf("Parse(%s) => %+v expected error", ssp.In, sel)
  492. } else if ssp.Match && !reflect.DeepEqual(sel, ssp.Out) {
  493. t.Errorf("Parse(%s) => parse output '%#v' doesn't match '%#v' expected match", ssp.In, sel, ssp.Out)
  494. }
  495. }
  496. }
  497. func getRequirement(key string, op selection.Operator, vals sets.String, t *testing.T) Requirement {
  498. req, err := NewRequirement(key, op, vals)
  499. if err != nil {
  500. t.Errorf("NewRequirement(%v, %v, %v) resulted in error:%v", key, op, vals, err)
  501. return Requirement{}
  502. }
  503. return *req
  504. }
  505. func TestAdd(t *testing.T) {
  506. testCases := []struct {
  507. name string
  508. sel Selector
  509. key string
  510. operator selection.Operator
  511. values []string
  512. refSelector Selector
  513. }{
  514. {
  515. "keyInOperator",
  516. internalSelector{},
  517. "key",
  518. selection.In,
  519. []string{"value"},
  520. internalSelector{Requirement{"key", selection.In, sets.NewString("value")}},
  521. },
  522. {
  523. "keyEqualsOperator",
  524. internalSelector{Requirement{"key", selection.In, sets.NewString("value")}},
  525. "key2",
  526. selection.Equals,
  527. []string{"value2"},
  528. internalSelector{
  529. Requirement{"key", selection.In, sets.NewString("value")},
  530. Requirement{"key2", selection.Equals, sets.NewString("value2")},
  531. },
  532. },
  533. }
  534. for _, ts := range testCases {
  535. req, err := NewRequirement(ts.key, ts.operator, sets.NewString(ts.values...))
  536. if err != nil {
  537. t.Errorf("%s - Unable to create labels.Requirement", ts.name)
  538. }
  539. ts.sel = ts.sel.Add(*req)
  540. if !reflect.DeepEqual(ts.sel, ts.refSelector) {
  541. t.Errorf("%s - Expected %v found %v", ts.name, ts.refSelector, ts.sel)
  542. }
  543. }
  544. }