1
15
16 package strvals
17
18 import (
19 "fmt"
20 "testing"
21
22 "sigs.k8s.io/yaml"
23 )
24
25 func TestParseLiteral(t *testing.T) {
26 cases := []struct {
27 str string
28 expect map[string]interface{}
29 err bool
30 }{
31 {
32 str: "name",
33 err: true,
34 },
35 {
36 str: "name=",
37 expect: map[string]interface{}{"name": ""},
38 },
39 {
40 str: "name=value",
41 expect: map[string]interface{}{"name": "value"},
42 err: false,
43 },
44 {
45 str: "long_int_string=1234567890",
46 expect: map[string]interface{}{"long_int_string": "1234567890"},
47 err: false,
48 },
49 {
50 str: "boolean=true",
51 expect: map[string]interface{}{"boolean": "true"},
52 err: false,
53 },
54 {
55 str: "is_null=null",
56 expect: map[string]interface{}{"is_null": "null"},
57 err: false,
58 },
59 {
60 str: "zero=0",
61 expect: map[string]interface{}{"zero": "0"},
62 err: false,
63 },
64 {
65 str: "name1=null,name2=value2",
66 expect: map[string]interface{}{"name1": "null,name2=value2"},
67 err: false,
68 },
69 {
70 str: "name1=value,,,tail",
71 expect: map[string]interface{}{"name1": "value,,,tail"},
72 err: false,
73 },
74 {
75 str: "leading_zeros=00009",
76 expect: map[string]interface{}{"leading_zeros": "00009"},
77 err: false,
78 },
79 {
80 str: "name=one two three",
81 expect: map[string]interface{}{"name": "one two three"},
82 err: false,
83 },
84 {
85 str: "outer.inner=value",
86 expect: map[string]interface{}{"outer": map[string]interface{}{"inner": "value"}},
87 err: false,
88 },
89 {
90 str: "outer.middle.inner=value",
91 expect: map[string]interface{}{"outer": map[string]interface{}{"middle": map[string]interface{}{"inner": "value"}}},
92 err: false,
93 },
94 {
95 str: "name1.name2",
96 err: true,
97 },
98 {
99 str: "name1.name2=",
100 expect: map[string]interface{}{"name1": map[string]interface{}{"name2": ""}},
101 err: false,
102 },
103 {
104 str: "name1.=name2",
105 err: true,
106 },
107 {
108 str: "name1.,name2",
109 err: true,
110 },
111 {
112 str: "name1={value1,value2}",
113 expect: map[string]interface{}{"name1": "{value1,value2}"},
114 },
115
116
117 {
118 str: "list[0]=foo",
119 expect: map[string]interface{}{"list": []string{"foo"}},
120 err: false,
121 },
122 {
123 str: "list[0].foo=bar",
124 expect: map[string]interface{}{
125 "list": []interface{}{
126 map[string]interface{}{"foo": "bar"},
127 },
128 },
129 err: false,
130 },
131 {
132 str: "list[-30].hello=world",
133 err: true,
134 },
135 {
136 str: "list[3]=bar",
137 expect: map[string]interface{}{"list": []interface{}{nil, nil, nil, "bar"}},
138 err: false,
139 },
140 {
141 str: "illegal[0]name.foo=bar",
142 err: true,
143 },
144 {
145 str: "noval[0]",
146 expect: map[string]interface{}{"noval": []interface{}{}},
147 err: false,
148 },
149 {
150 str: "noval[0]=",
151 expect: map[string]interface{}{"noval": []interface{}{""}},
152 err: false,
153 },
154 {
155 str: "nested[0][0]=1",
156 expect: map[string]interface{}{"nested": []interface{}{[]interface{}{"1"}}},
157 err: false,
158 },
159 {
160 str: "nested[1][1]=1",
161 expect: map[string]interface{}{"nested": []interface{}{nil, []interface{}{nil, "1"}}},
162 err: false,
163 },
164 {
165 str: "name1.name2[0].foo=bar",
166 expect: map[string]interface{}{
167 "name1": map[string]interface{}{
168 "name2": []map[string]interface{}{{"foo": "bar"}},
169 },
170 },
171 },
172 {
173 str: "name1.name2[1].foo=bar",
174 expect: map[string]interface{}{
175 "name1": map[string]interface{}{
176 "name2": []map[string]interface{}{nil, {"foo": "bar"}},
177 },
178 },
179 },
180 {
181 str: "name1.name2[1].foo=bar",
182 expect: map[string]interface{}{
183 "name1": map[string]interface{}{
184 "name2": []map[string]interface{}{nil, {"foo": "bar"}},
185 },
186 },
187 },
188 {
189 str: "]={}].",
190 expect: map[string]interface{}{"]": "{}]."},
191 err: false,
192 },
193
194
195 {
196 str: "name=val,val",
197 expect: map[string]interface{}{"name": "val,val"},
198 err: false,
199 },
200 {
201 str: "name=val.val",
202 expect: map[string]interface{}{"name": "val.val"},
203 err: false,
204 },
205 {
206 str: "name=val=val",
207 expect: map[string]interface{}{"name": "val=val"},
208 err: false,
209 },
210 {
211 str: "name=val$val",
212 expect: map[string]interface{}{"name": "val$val"},
213 err: false,
214 },
215 {
216 str: "name=(value",
217 expect: map[string]interface{}{"name": "(value"},
218 err: false,
219 },
220 {
221 str: "name=value)",
222 expect: map[string]interface{}{"name": "value)"},
223 err: false,
224 },
225 {
226 str: "name=(value)",
227 expect: map[string]interface{}{"name": "(value)"},
228 err: false,
229 },
230 {
231 str: "name={value",
232 expect: map[string]interface{}{"name": "{value"},
233 err: false,
234 },
235 {
236 str: "name=value}",
237 expect: map[string]interface{}{"name": "value}"},
238 err: false,
239 },
240 {
241 str: "name={value}",
242 expect: map[string]interface{}{"name": "{value}"},
243 err: false,
244 },
245 {
246 str: "name={value1,value2}",
247 expect: map[string]interface{}{"name": "{value1,value2}"},
248 err: false,
249 },
250 {
251 str: `name=val\val`,
252 expect: map[string]interface{}{"name": `val\val`},
253 err: false,
254 },
255 {
256 str: `name=val\\val`,
257 expect: map[string]interface{}{"name": `val\\val`},
258 err: false,
259 },
260 {
261 str: `name=val\\\val`,
262 expect: map[string]interface{}{"name": `val\\\val`},
263 err: false,
264 },
265 {
266 str: `name={val,.?*v\0a!l)some`,
267 expect: map[string]interface{}{"name": `{val,.?*v\0a!l)some`},
268 err: false,
269 },
270 {
271 str: `name=em%GT)tqUDqz,i-\h+Mbqs-!:.m\\rE=mkbM#rR}@{-k@`,
272 expect: map[string]interface{}{"name": `em%GT)tqUDqz,i-\h+Mbqs-!:.m\\rE=mkbM#rR}@{-k@`},
273 },
274 }
275
276 for _, tt := range cases {
277 got, err := ParseLiteral(tt.str)
278 if err != nil {
279 if !tt.err {
280 t.Fatalf("%s: %s", tt.str, err)
281 }
282 continue
283 }
284
285 if tt.err {
286 t.Errorf("%s: Expected error. Got nil", tt.str)
287 }
288
289 y1, err := yaml.Marshal(tt.expect)
290 if err != nil {
291 t.Fatal(err)
292 }
293
294 y2, err := yaml.Marshal(got)
295 if err != nil {
296 t.Fatalf("Error serializing parsed value: %s", err)
297 }
298
299 if string(y1) != string(y2) {
300 t.Errorf("%s: Expected:\n%s\nGot:\n%s", tt.str, y1, y2)
301 }
302 }
303 }
304
305 func TestParseLiteralInto(t *testing.T) {
306 tests := []struct {
307 input string
308 input2 string
309 got map[string]interface{}
310 expect map[string]interface{}
311 err bool
312 }{
313 {
314 input: "outer.inner1=value1,outer.inner3=value3,outer.inner4=4",
315 got: map[string]interface{}{
316 "outer": map[string]interface{}{
317 "inner1": "overwrite",
318 "inner2": "value2",
319 },
320 },
321 expect: map[string]interface{}{
322 "outer": map[string]interface{}{
323 "inner1": "value1,outer.inner3=value3,outer.inner4=4",
324 "inner2": "value2",
325 }},
326 err: false,
327 },
328 {
329 input: "listOuter[0][0].type=listValue",
330 input2: "listOuter[0][0].status=alive",
331 got: map[string]interface{}{},
332 expect: map[string]interface{}{
333 "listOuter": [][]interface{}{{map[string]string{
334 "type": "listValue",
335 "status": "alive",
336 }}},
337 },
338 err: false,
339 },
340 {
341 input: "listOuter[0][0].type=listValue",
342 input2: "listOuter[1][0].status=alive",
343 got: map[string]interface{}{},
344 expect: map[string]interface{}{
345 "listOuter": [][]interface{}{
346 {
347 map[string]string{"type": "listValue"},
348 },
349 {
350 map[string]string{"status": "alive"},
351 },
352 },
353 },
354 err: false,
355 },
356 {
357 input: "listOuter[0][1][0].type=listValue",
358 input2: "listOuter[0][0][1].status=alive",
359 got: map[string]interface{}{
360 "listOuter": []interface{}{
361 []interface{}{
362 []interface{}{
363 map[string]string{"exited": "old"},
364 },
365 },
366 },
367 },
368 expect: map[string]interface{}{
369 "listOuter": [][][]interface{}{
370 {
371 {
372 map[string]string{"exited": "old"},
373 map[string]string{"status": "alive"},
374 },
375 {
376 map[string]string{"type": "listValue"},
377 },
378 },
379 },
380 },
381 err: false,
382 },
383 }
384
385 for _, tt := range tests {
386 if err := ParseLiteralInto(tt.input, tt.got); err != nil {
387 t.Fatal(err)
388 }
389 if tt.err {
390 t.Errorf("%s: Expected error. Got nil", tt.input)
391 }
392
393 if tt.input2 != "" {
394 if err := ParseLiteralInto(tt.input2, tt.got); err != nil {
395 t.Fatal(err)
396 }
397 if tt.err {
398 t.Errorf("%s: Expected error. Got nil", tt.input2)
399 }
400 }
401
402 y1, err := yaml.Marshal(tt.expect)
403 if err != nil {
404 t.Fatal(err)
405 }
406
407 y2, err := yaml.Marshal(tt.got)
408 if err != nil {
409 t.Fatalf("Error serializing parsed value: %s", err)
410 }
411
412 if string(y1) != string(y2) {
413 t.Errorf("%s: Expected:\n%s\nGot:\n%s", tt.input, y1, y2)
414 }
415 }
416 }
417
418 func TestParseLiteralNestedLevels(t *testing.T) {
419 var keyMultipleNestedLevels string
420
421 for i := 1; i <= MaxNestedNameLevel+2; i++ {
422 tmpStr := fmt.Sprintf("name%d", i)
423 if i <= MaxNestedNameLevel+1 {
424 tmpStr = tmpStr + "."
425 }
426 keyMultipleNestedLevels += tmpStr
427 }
428
429 tests := []struct {
430 str string
431 expect map[string]interface{}
432 err bool
433 errStr string
434 }{
435 {
436 "outer.middle.inner=value",
437 map[string]interface{}{"outer": map[string]interface{}{"middle": map[string]interface{}{"inner": "value"}}},
438 false,
439 "",
440 },
441 {
442 str: keyMultipleNestedLevels + "=value",
443 err: true,
444 errStr: fmt.Sprintf("value name nested level is greater than maximum supported nested level of %d", MaxNestedNameLevel),
445 },
446 }
447
448 for _, tt := range tests {
449 got, err := ParseLiteral(tt.str)
450 if err != nil {
451 if tt.err {
452 if tt.errStr != "" {
453 if err.Error() != tt.errStr {
454 t.Errorf("Expected error: %s. Got error: %s", tt.errStr, err.Error())
455 }
456 }
457 continue
458 }
459 t.Fatalf("%s: %s", tt.str, err)
460 }
461
462 if tt.err {
463 t.Errorf("%s: Expected error. Got nil", tt.str)
464 }
465
466 y1, err := yaml.Marshal(tt.expect)
467 if err != nil {
468 t.Fatal(err)
469 }
470
471 y2, err := yaml.Marshal(got)
472 if err != nil {
473 t.Fatalf("Error serializing parsed value: %s", err)
474 }
475
476 if string(y1) != string(y2) {
477 t.Errorf("%s: Expected:\n%s\nGot:\n%s", tt.str, y1, y2)
478 }
479 }
480 }
481
View as plain text