github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/flags/strvals/parser_test.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package strvals 19 20 import ( 21 "bytes" 22 "testing" 23 24 "sigs.k8s.io/yaml" 25 ) 26 27 func TestSetIndex(t *testing.T) { 28 tests := []struct { 29 name string 30 initial []interface{} 31 expect []interface{} 32 add int 33 val int 34 }{ 35 { 36 name: "short", 37 initial: []interface{}{0, 1}, 38 expect: []interface{}{0, 1, 2}, 39 add: 2, 40 val: 2, 41 }, 42 { 43 name: "equal", 44 initial: []interface{}{0, 1}, 45 expect: []interface{}{0, 2}, 46 add: 1, 47 val: 2, 48 }, 49 { 50 name: "long", 51 initial: []interface{}{0, 1, 2, 3, 4, 5}, 52 expect: []interface{}{0, 1, 2, 4, 4, 5}, 53 add: 3, 54 val: 4, 55 }, 56 } 57 58 for _, tt := range tests { 59 got := setIndex(tt.initial, tt.add, tt.val) 60 if len(got) != len(tt.expect) { 61 t.Fatalf("%s: Expected length %d, got %d", tt.name, len(tt.expect), len(got)) 62 } 63 64 if gg := got[tt.add].(int); gg != tt.val { 65 t.Errorf("%s, Expected value %d, got %d", tt.name, tt.val, gg) 66 } 67 } 68 } 69 70 func TestParseSet(t *testing.T) { 71 testsString := []struct { 72 str string 73 expect map[string]interface{} 74 err bool 75 }{ 76 { 77 str: "long_int_string=1234567890", 78 expect: map[string]interface{}{"long_int_string": "1234567890"}, 79 err: false, 80 }, 81 { 82 str: "boolean=true", 83 expect: map[string]interface{}{"boolean": "true"}, 84 err: false, 85 }, 86 { 87 str: "is_null=null", 88 expect: map[string]interface{}{"is_null": "null"}, 89 err: false, 90 }, 91 { 92 str: "zero=0", 93 expect: map[string]interface{}{"zero": "0"}, 94 err: false, 95 }, 96 } 97 tests := []struct { 98 str string 99 expect map[string]interface{} 100 err bool 101 }{ 102 { 103 "name1=null,f=false,t=true", 104 map[string]interface{}{"name1": nil, "f": false, "t": true}, 105 false, 106 }, 107 { 108 "name1=value1", 109 map[string]interface{}{"name1": "value1"}, 110 false, 111 }, 112 { 113 "name1=value1,name2=value2", 114 map[string]interface{}{"name1": "value1", "name2": "value2"}, 115 false, 116 }, 117 { 118 "name1=value1,name2=value2,", 119 map[string]interface{}{"name1": "value1", "name2": "value2"}, 120 false, 121 }, 122 { 123 str: "name1=value1,,,,name2=value2,", 124 err: true, 125 }, 126 { 127 str: "name1=,name2=value2", 128 expect: map[string]interface{}{"name1": "", "name2": "value2"}, 129 }, 130 { 131 str: "leading_zeros=00009", 132 expect: map[string]interface{}{"leading_zeros": "00009"}, 133 }, 134 { 135 str: "zero_int=0", 136 expect: map[string]interface{}{"zero_int": 0}, 137 }, 138 { 139 str: "long_int=1234567890", 140 expect: map[string]interface{}{"long_int": 1234567890}, 141 }, 142 { 143 str: "boolean=true", 144 expect: map[string]interface{}{"boolean": true}, 145 }, 146 { 147 str: "is_null=null", 148 expect: map[string]interface{}{"is_null": nil}, 149 err: false, 150 }, 151 { 152 str: "name1,name2=", 153 err: true, 154 }, 155 { 156 str: "name1,name2=value2", 157 err: true, 158 }, 159 { 160 str: "name1,name2=value2\\", 161 err: true, 162 }, 163 { 164 str: "name1,name2", 165 err: true, 166 }, 167 { 168 "name1=one\\,two,name2=three\\,four", 169 map[string]interface{}{"name1": "one,two", "name2": "three,four"}, 170 false, 171 }, 172 { 173 "name1=one\\=two,name2=three\\=four", 174 map[string]interface{}{"name1": "one=two", "name2": "three=four"}, 175 false, 176 }, 177 { 178 "name1=one two three,name2=three two one", 179 map[string]interface{}{"name1": "one two three", "name2": "three two one"}, 180 false, 181 }, 182 { 183 "outer.inner=value", 184 map[string]interface{}{"outer": map[string]interface{}{"inner": "value"}}, 185 false, 186 }, 187 { 188 "outer.middle.inner=value", 189 map[string]interface{}{"outer": map[string]interface{}{"middle": map[string]interface{}{"inner": "value"}}}, 190 false, 191 }, 192 { 193 "outer.inner1=value,outer.inner2=value2", 194 map[string]interface{}{"outer": map[string]interface{}{"inner1": "value", "inner2": "value2"}}, 195 false, 196 }, 197 { 198 "outer.inner1=value,outer.middle.inner=value", 199 map[string]interface{}{ 200 "outer": map[string]interface{}{ 201 "inner1": "value", 202 "middle": map[string]interface{}{ 203 "inner": "value", 204 }, 205 }, 206 }, 207 false, 208 }, 209 { 210 str: "name1.name2", 211 err: true, 212 }, 213 { 214 str: "name1.name2,name1.name3", 215 err: true, 216 }, 217 { 218 str: "name1.name2=", 219 expect: map[string]interface{}{"name1": map[string]interface{}{"name2": ""}}, 220 }, 221 { 222 str: "name1.=name2", 223 err: true, 224 }, 225 { 226 str: "name1.,name2", 227 err: true, 228 }, 229 { 230 "name1={value1,value2}", 231 map[string]interface{}{"name1": []string{"value1", "value2"}}, 232 false, 233 }, 234 { 235 "name1={value1,value2},name2={value1,value2}", 236 map[string]interface{}{ 237 "name1": []string{"value1", "value2"}, 238 "name2": []string{"value1", "value2"}, 239 }, 240 false, 241 }, 242 { 243 "name1={1021,902}", 244 map[string]interface{}{"name1": []int{1021, 902}}, 245 false, 246 }, 247 { 248 "name1.name2={value1,value2}", 249 map[string]interface{}{"name1": map[string]interface{}{"name2": []string{"value1", "value2"}}}, 250 false, 251 }, 252 { 253 str: "name1={1021,902", 254 err: true, 255 }, 256 // List support 257 { 258 str: "list[0]=foo", 259 expect: map[string]interface{}{"list": []string{"foo"}}, 260 }, 261 { 262 str: "list[0].foo=bar", 263 expect: map[string]interface{}{ 264 "list": []interface{}{ 265 map[string]interface{}{"foo": "bar"}, 266 }, 267 }, 268 }, 269 { 270 str: "list[0].foo=bar,list[0].hello=world", 271 expect: map[string]interface{}{ 272 "list": []interface{}{ 273 map[string]interface{}{"foo": "bar", "hello": "world"}, 274 }, 275 }, 276 }, 277 { 278 str: "list[0]=foo,list[1]=bar", 279 expect: map[string]interface{}{"list": []string{"foo", "bar"}}, 280 }, 281 { 282 str: "list[0]=foo,list[1]=bar,", 283 expect: map[string]interface{}{"list": []string{"foo", "bar"}}, 284 }, 285 { 286 str: "list[0]=foo,list[3]=bar", 287 expect: map[string]interface{}{"list": []interface{}{"foo", nil, nil, "bar"}}, 288 }, 289 { 290 str: "illegal[0]name.foo=bar", 291 err: true, 292 }, 293 { 294 str: "noval[0]", 295 expect: map[string]interface{}{"noval": []interface{}{}}, 296 }, 297 { 298 str: "noval[0]=", 299 expect: map[string]interface{}{"noval": []interface{}{""}}, 300 }, 301 { 302 str: "nested[0][0]=1", 303 expect: map[string]interface{}{"nested": []interface{}{[]interface{}{1}}}, 304 }, 305 { 306 str: "nested[1][1]=1", 307 expect: map[string]interface{}{"nested": []interface{}{nil, []interface{}{nil, 1}}}, 308 }, 309 { 310 str: "name1.name2[0].foo=bar,name1.name2[1].foo=bar", 311 expect: map[string]interface{}{ 312 "name1": map[string]interface{}{ 313 "name2": []map[string]interface{}{{"foo": "bar"}, {"foo": "bar"}}, 314 }, 315 }, 316 }, 317 { 318 str: "name1.name2[1].foo=bar,name1.name2[0].foo=bar", 319 expect: map[string]interface{}{ 320 "name1": map[string]interface{}{ 321 "name2": []map[string]interface{}{{"foo": "bar"}, {"foo": "bar"}}, 322 }, 323 }, 324 }, 325 { 326 str: "name1.name2[1].foo=bar", 327 expect: map[string]interface{}{ 328 "name1": map[string]interface{}{ 329 "name2": []map[string]interface{}{nil, {"foo": "bar"}}, 330 }, 331 }, 332 }, 333 } 334 335 for _, tt := range tests { 336 got, err := Parse(tt.str) 337 if err != nil { 338 if tt.err { 339 continue 340 } 341 t.Fatalf("%s: %s", tt.str, err) 342 } 343 if tt.err { 344 t.Errorf("%s: Expected error. Got nil", tt.str) 345 } 346 347 y1, err := yaml.Marshal(tt.expect) 348 if err != nil { 349 t.Fatal(err) 350 } 351 y2, err := yaml.Marshal(got) 352 if err != nil { 353 t.Fatalf("Error serializing parsed value: %s", err) 354 } 355 356 if !bytes.Equal(y1, y2) { 357 t.Errorf("%s: Expected:\n%s\nGot:\n%s", tt.str, y1, y2) 358 } 359 } 360 for _, tt := range testsString { 361 got, err := ParseString(tt.str) 362 if err != nil { 363 if tt.err { 364 continue 365 } 366 t.Fatalf("%s: %s", tt.str, err) 367 } 368 if tt.err { 369 t.Errorf("%s: Expected error. Got nil", tt.str) 370 } 371 372 y1, err := yaml.Marshal(tt.expect) 373 if err != nil { 374 t.Fatal(err) 375 } 376 y2, err := yaml.Marshal(got) 377 if err != nil { 378 t.Fatalf("Error serializing parsed value: %s", err) 379 } 380 381 if !bytes.Equal(y1, y2) { 382 t.Errorf("%s: Expected:\n%s\nGot:\n%s", tt.str, y1, y2) 383 } 384 } 385 } 386 387 func TestParseInto(t *testing.T) { 388 got := map[string]interface{}{ 389 "outer": map[string]interface{}{ 390 "inner1": "overwrite", 391 "inner2": "value2", 392 }, 393 } 394 input := "outer.inner1=value1,outer.inner3=value3,outer.inner4=4" 395 expect := map[string]interface{}{ 396 "outer": map[string]interface{}{ 397 "inner1": "value1", 398 "inner2": "value2", 399 "inner3": "value3", 400 "inner4": 4, 401 }, 402 } 403 404 if err := ParseInto(input, got); err != nil { 405 t.Fatal(err) 406 } 407 408 y1, err := yaml.Marshal(expect) 409 if err != nil { 410 t.Fatal(err) 411 } 412 y2, err := yaml.Marshal(got) 413 if err != nil { 414 t.Fatalf("Error serializing parsed value: %s", err) 415 } 416 417 if !bytes.Equal(y1, y2) { 418 t.Errorf("%s: Expected:\n%s\nGot:\n%s", input, y1, y2) 419 } 420 } 421 422 func TestParseIntoString(t *testing.T) { 423 got := map[string]interface{}{ 424 "outer": map[string]interface{}{ 425 "inner1": "overwrite", 426 "inner2": "value2", 427 }, 428 } 429 input := "outer.inner1=1,outer.inner3=3" 430 expect := map[string]interface{}{ 431 "outer": map[string]interface{}{ 432 "inner1": "1", 433 "inner2": "value2", 434 "inner3": "3", 435 }, 436 } 437 438 if err := ParseIntoString(input, got); err != nil { 439 t.Fatal(err) 440 } 441 442 y1, err := yaml.Marshal(expect) 443 if err != nil { 444 t.Fatal(err) 445 } 446 y2, err := yaml.Marshal(got) 447 if err != nil { 448 t.Fatalf("Error serializing parsed value: %s", err) 449 } 450 451 if !bytes.Equal(y1, y2) { 452 t.Errorf("%s: Expected:\n%s\nGot:\n%s", input, y1, y2) 453 } 454 } 455 456 func TestParseFile(t *testing.T) { 457 input := "name1=path1" 458 expect := map[string]interface{}{ 459 "name1": "value1", 460 } 461 rs2v := func(rs []rune) (interface{}, error) { 462 v := string(rs) 463 if v != "path1" { 464 t.Errorf("%s: runesToVal: Expected value path1, got %s", input, v) 465 return "", nil 466 } 467 return "value1", nil 468 } 469 470 got, err := ParseFile(input, rs2v) 471 if err != nil { 472 t.Fatal(err) 473 } 474 475 y1, err := yaml.Marshal(expect) 476 if err != nil { 477 t.Fatal(err) 478 } 479 y2, err := yaml.Marshal(got) 480 if err != nil { 481 t.Fatalf("Error serializing parsed value: %s", err) 482 } 483 484 if !bytes.Equal(y1, y2) { 485 t.Errorf("%s: Expected:\n%s\nGot:\n%s", input, y1, y2) 486 } 487 } 488 489 func TestParseIntoFile(t *testing.T) { 490 got := map[string]interface{}{} 491 input := "name1=path1" 492 expect := map[string]interface{}{ 493 "name1": "value1", 494 } 495 rs2v := func(rs []rune) (interface{}, error) { 496 v := string(rs) 497 if v != "path1" { 498 t.Errorf("%s: runesToVal: Expected value path1, got %s", input, v) 499 return "", nil 500 } 501 return "value1", nil 502 } 503 504 if err := ParseIntoFile(input, got, rs2v); err != nil { 505 t.Fatal(err) 506 } 507 508 y1, err := yaml.Marshal(expect) 509 if err != nil { 510 t.Fatal(err) 511 } 512 y2, err := yaml.Marshal(got) 513 if err != nil { 514 t.Fatalf("Error serializing parsed value: %s", err) 515 } 516 517 if !bytes.Equal(y1, y2) { 518 t.Errorf("%s: Expected:\n%s\nGot:\n%s", input, y1, y2) 519 } 520 } 521 522 func TestToYAML(t *testing.T) { 523 // The TestParse does the hard part. We just verify that YAML formatting is 524 // happening. 525 o, err := ToYAML("name=value") 526 if err != nil { 527 t.Fatal(err) 528 } 529 expect := "name: value" 530 if o != expect { 531 t.Errorf("Expected %q, got %q", expect, o) 532 } 533 }