github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/configs/parsing_helpers_test.go (about) 1 package configs 2 3 import ( 4 "reflect" 5 "testing" 6 7 v1 "k8s.io/api/core/v1" 8 "k8s.io/api/networking/v1beta1" 9 meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 ) 11 12 var configMap = v1.ConfigMap{ 13 ObjectMeta: meta_v1.ObjectMeta{ 14 Name: "test", 15 Namespace: "default", 16 }, 17 TypeMeta: meta_v1.TypeMeta{ 18 Kind: "ConfigMap", 19 APIVersion: "v1", 20 }, 21 } 22 var ingress = v1beta1.Ingress{ 23 ObjectMeta: meta_v1.ObjectMeta{ 24 Name: "test", 25 Namespace: "kube-system", 26 }, 27 TypeMeta: meta_v1.TypeMeta{ 28 Kind: "Ingress", 29 APIVersion: "extensions/v1beta1", 30 }, 31 } 32 33 func TestGetMapKeyAsBool(t *testing.T) { 34 configMap := configMap 35 configMap.Data = map[string]string{ 36 "key": "True", 37 } 38 39 b, exists, err := GetMapKeyAsBool(configMap.Data, "key", &configMap) 40 if !exists { 41 t.Errorf("The key 'key' must exist in the configMap") 42 } 43 if err != nil { 44 t.Errorf("Unexpected error: %v", err) 45 } 46 if b != true { 47 t.Errorf("Result should be true") 48 } 49 } 50 51 func TestGetMapKeyAsBoolNotFound(t *testing.T) { 52 configMap := configMap 53 configMap.Data = map[string]string{} 54 55 _, exists, _ := GetMapKeyAsBool(configMap.Data, "key", &configMap) 56 if exists { 57 t.Errorf("The key 'key' must not exist in the configMap") 58 } 59 } 60 61 func TestGetMapKeyAsBoolErrorMessage(t *testing.T) { 62 cfgm := configMap 63 cfgm.Data = map[string]string{ 64 "key": "string", 65 } 66 67 // Test with configmap 68 _, _, err := GetMapKeyAsBool(cfgm.Data, "key", &cfgm) 69 if err == nil { 70 t.Error("An error was expected") 71 } 72 expected := `ConfigMap default/test 'key' contains invalid bool: strconv.ParseBool: parsing "string": invalid syntax, ignoring` 73 if err.Error() != expected { 74 t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected) 75 } 76 77 // Test with ingress object 78 ingress := ingress 79 ingress.Annotations = map[string]string{ 80 "key": "other_string", 81 } 82 83 _, _, err = GetMapKeyAsBool(ingress.Annotations, "key", &ingress) 84 if err == nil { 85 t.Error("An error was expected") 86 } 87 expected = `Ingress kube-system/test 'key' contains invalid bool: strconv.ParseBool: parsing "other_string": invalid syntax, ignoring` 88 if err.Error() != expected { 89 t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected) 90 } 91 } 92 93 func TestGetMapKeyAsInt(t *testing.T) { 94 configMap := configMap 95 configMap.Data = map[string]string{ 96 "key": "123456789", 97 } 98 99 i, exists, err := GetMapKeyAsInt(configMap.Data, "key", &configMap) 100 if err != nil { 101 t.Errorf("Unexpected error: %v", err) 102 } 103 if !exists { 104 t.Errorf("The key 'key' must exist in the configMap") 105 } 106 expected := 123456789 107 if i != expected { 108 t.Errorf("Unexpected return value:\nGot: %v\nExpected: %v", i, expected) 109 } 110 } 111 112 func TestGetMapKeyAsIntNotFound(t *testing.T) { 113 configMap := configMap 114 configMap.Data = map[string]string{} 115 116 _, exists, _ := GetMapKeyAsInt(configMap.Data, "key", &configMap) 117 if exists { 118 t.Errorf("The key 'key' must not exist in the configMap") 119 } 120 } 121 122 func TestGetMapKeyAsIntErrorMessage(t *testing.T) { 123 cfgm := configMap 124 cfgm.Data = map[string]string{ 125 "key": "string", 126 } 127 128 // Test with configmap 129 _, _, err := GetMapKeyAsInt(cfgm.Data, "key", &cfgm) 130 if err == nil { 131 t.Error("An error was expected") 132 } 133 expected := `ConfigMap default/test 'key' contains invalid integer: strconv.Atoi: parsing "string": invalid syntax, ignoring` 134 if err.Error() != expected { 135 t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected) 136 } 137 138 // Test with ingress object 139 ingress := ingress 140 ingress.Annotations = map[string]string{ 141 "key": "other_string", 142 } 143 144 _, _, err = GetMapKeyAsInt(ingress.Annotations, "key", &ingress) 145 if err == nil { 146 t.Error("An error was expected") 147 } 148 expected = `Ingress kube-system/test 'key' contains invalid integer: strconv.Atoi: parsing "other_string": invalid syntax, ignoring` 149 if err.Error() != expected { 150 t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected) 151 } 152 } 153 154 func TestGetMapKeyAsInt64(t *testing.T) { 155 configMap := configMap 156 configMap.Data = map[string]string{ 157 "key": "123456789", 158 } 159 160 i, exists, err := GetMapKeyAsInt64(configMap.Data, "key", &configMap) 161 if err != nil { 162 t.Errorf("Unexpected error: %v", err) 163 } 164 if !exists { 165 t.Errorf("The key 'key' must exist in the configMap") 166 } 167 var expected int64 = 123456789 168 if i != expected { 169 t.Errorf("Unexpected return value:\nGot: %v\nExpected: %v", i, expected) 170 } 171 } 172 173 func TestGetMapKeyAsInt64NotFound(t *testing.T) { 174 configMap := configMap 175 configMap.Data = map[string]string{} 176 177 _, exists, _ := GetMapKeyAsInt64(configMap.Data, "key", &configMap) 178 if exists { 179 t.Errorf("The key 'key' must not exist in the configMap") 180 } 181 } 182 183 func TestGetMapKeyAsInt64ErrorMessage(t *testing.T) { 184 cfgm := configMap 185 cfgm.Data = map[string]string{ 186 "key": "string", 187 } 188 189 // Test with configmap 190 _, _, err := GetMapKeyAsInt64(cfgm.Data, "key", &cfgm) 191 if err == nil { 192 t.Error("An error was expected") 193 } 194 expected := `ConfigMap default/test 'key' contains invalid integer: strconv.ParseInt: parsing "string": invalid syntax, ignoring` 195 if err.Error() != expected { 196 t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected) 197 } 198 199 // Test with ingress object 200 ingress := ingress 201 ingress.Annotations = map[string]string{ 202 "key": "other_string", 203 } 204 205 _, _, err = GetMapKeyAsInt64(ingress.Annotations, "key", &ingress) 206 if err == nil { 207 t.Error("An error was expected") 208 } 209 expected = `Ingress kube-system/test 'key' contains invalid integer: strconv.ParseInt: parsing "other_string": invalid syntax, ignoring` 210 if err.Error() != expected { 211 t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected) 212 } 213 } 214 215 func TestGetMapKeyAsStringSlice(t *testing.T) { 216 configMap := configMap 217 configMap.Data = map[string]string{ 218 "key": "1.String,2.String,3.String", 219 } 220 221 slice, exists, err := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap, ",") 222 if err != nil { 223 t.Errorf("Unexpected error: %v", err) 224 } 225 if !exists { 226 t.Errorf("The key 'key' must exist in the configMap") 227 } 228 expected := []string{"1.String", "2.String", "3.String"} 229 t.Log(expected) 230 if !reflect.DeepEqual(expected, slice) { 231 t.Errorf("Unexpected return value:\nGot: %#v\nExpected: %#v", slice, expected) 232 } 233 234 } 235 236 func TestGetMapKeyAsStringSliceMultilineSnippets(t *testing.T) { 237 configMap := configMap 238 configMap.Data = map[string]string{ 239 "server-snippets": ` 240 if ($new_uri) { 241 rewrite ^ $new_uri permanent; 242 }`, 243 } 244 245 slice, exists, err := GetMapKeyAsStringSlice(configMap.Data, "server-snippets", &configMap, "\n") 246 if err != nil { 247 t.Errorf("Unexpected error: %v", err) 248 } 249 if !exists { 250 t.Errorf("The key 'server-snippets' must exist in the configMap") 251 } 252 expected := []string{"", "\t\t\tif ($new_uri) {", "\t\t\t\trewrite ^ $new_uri permanent;", "\t\t\t}"} 253 t.Log(expected) 254 if !reflect.DeepEqual(expected, slice) { 255 t.Errorf("Unexpected return value:\nGot: %#v\nExpected: %#v", slice, expected) 256 } 257 } 258 259 func TestGetMapKeyAsStringSliceNotFound(t *testing.T) { 260 configMap := configMap 261 configMap.Data = map[string]string{} 262 263 _, exists, _ := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap, ",") 264 if exists { 265 t.Errorf("The key 'key' must not exist in the configMap") 266 } 267 } 268 269 func TestParseLBMethod(t *testing.T) { 270 var testsWithValidInput = []struct { 271 input string 272 expected string 273 }{ 274 {"least_conn", "least_conn"}, 275 {"round_robin", ""}, 276 {"ip_hash", "ip_hash"}, 277 {"random", "random"}, 278 {"random two", "random two"}, 279 {"random two least_conn", "random two least_conn"}, 280 {"hash $request_id", "hash $request_id"}, 281 {"hash $request_id consistent", "hash $request_id consistent"}, 282 } 283 284 var invalidInput = []string{ 285 "", 286 "blabla", 287 "least_time header", 288 "hash123", 289 "hash $request_id conwrongspelling", 290 "random one", 291 "random two least_time=header", 292 "random two least_time=last_byte", 293 "random two ip_hash", 294 } 295 296 for _, test := range testsWithValidInput { 297 result, err := ParseLBMethod(test.input) 298 if err != nil { 299 t.Errorf("TestParseLBMethod(%q) returned an error for valid input", test.input) 300 } 301 302 if result != test.expected { 303 t.Errorf("TestParseLBMethod(%q) returned %q expected %q", test.input, result, test.expected) 304 } 305 } 306 307 for _, input := range invalidInput { 308 _, err := ParseLBMethod(input) 309 if err == nil { 310 t.Errorf("TestParseLBMethod(%q) does not return an error for invalid input", input) 311 } 312 } 313 } 314 315 func TestParseLBMethodForPlus(t *testing.T) { 316 var testsWithValidInput = []struct { 317 input string 318 expected string 319 }{ 320 {"least_conn", "least_conn"}, 321 {"round_robin", ""}, 322 {"ip_hash", "ip_hash"}, 323 {"random", "random"}, 324 {"random two", "random two"}, 325 {"random two least_conn", "random two least_conn"}, 326 {"random two least_time=header", "random two least_time=header"}, 327 {"random two least_time=last_byte", "random two least_time=last_byte"}, 328 {"hash $request_id", "hash $request_id"}, 329 {"least_time header", "least_time header"}, 330 {"least_time last_byte", "least_time last_byte"}, 331 {"least_time header inflight", "least_time header inflight"}, 332 {"least_time last_byte inflight", "least_time last_byte inflight"}, 333 } 334 335 var invalidInput = []string{ 336 "", 337 "blabla", 338 "hash123", 339 "least_time", 340 "last_byte", 341 "least_time inflight header", 342 "random one", 343 "random two ip_hash", 344 "random two least_time", 345 } 346 347 for _, test := range testsWithValidInput { 348 result, err := ParseLBMethodForPlus(test.input) 349 if err != nil { 350 t.Errorf("TestParseLBMethod(%q) returned an error for valid input", test.input) 351 } 352 353 if result != test.expected { 354 t.Errorf("TestParseLBMethod(%q) returned %q expected %q", test.input, result, test.expected) 355 } 356 } 357 358 for _, input := range invalidInput { 359 _, err := ParseLBMethodForPlus(input) 360 if err == nil { 361 t.Errorf("TestParseLBMethod(%q) does not return an error for invalid input", input) 362 } 363 } 364 } 365 366 func TestParseTime(t *testing.T) { 367 var testsWithValidInput = []struct { 368 input string 369 expected string 370 }{ 371 {"1h30m 5 100ms", "1h30m5s100ms"}, 372 {"10ms", "10ms"}, 373 {"1", "1s"}, 374 {"5m 30s", "5m30s"}, 375 {"1s", "1s"}, 376 {"100m", "100m"}, 377 {"5w", "5w"}, 378 {"15m", "15m"}, 379 {"11M", "11M"}, 380 {"3h", "3h"}, 381 {"100y", "100y"}, 382 {"600", "600s"}, 383 } 384 var invalidInput = []string{"5s 5s", "ss", "rM", "m0m", "s1s", "-5s", "", "1L", "11 11", " ", " "} 385 386 for _, test := range testsWithValidInput { 387 result, err := ParseTime(test.input) 388 if err != nil { 389 t.Errorf("TestparseTime(%q) returned an error for valid input", test.input) 390 } 391 392 if result != test.expected { 393 t.Errorf("TestparseTime(%q) returned %q expected %q", test.input, result, test.expected) 394 } 395 } 396 397 for _, test := range invalidInput { 398 result, err := ParseTime(test) 399 if err == nil { 400 t.Errorf("TestparseTime(%q) didn't return error. Returned: %q", test, result) 401 } 402 } 403 } 404 405 func TestParseOffset(t *testing.T) { 406 var testsWithValidInput = []string{"1", "2k", "2K", "3m", "3M", "4g", "4G"} 407 var invalidInput = []string{"-1", "", "blah"} 408 for _, test := range testsWithValidInput { 409 result, err := ParseOffset(test) 410 if err != nil { 411 t.Errorf("TestParseOffset(%q) returned an error for valid input", test) 412 } 413 if test != result { 414 t.Errorf("TestParseOffset(%q) returned %q expected %q", test, result, test) 415 } 416 } 417 for _, test := range invalidInput { 418 result, err := ParseOffset(test) 419 if err == nil { 420 t.Errorf("TestParseOffset(%q) didn't return error. Returned: %q", test, result) 421 } 422 } 423 } 424 425 func TestParseSize(t *testing.T) { 426 var testsWithValidInput = []string{"1", "2k", "2K", "3m", "3M"} 427 var invalidInput = []string{"-1", "", "blah", "4g", "4G"} 428 for _, test := range testsWithValidInput { 429 result, err := ParseSize(test) 430 if err != nil { 431 t.Errorf("TestParseSize(%q) returned an error for valid input", test) 432 } 433 if test != result { 434 t.Errorf("TestParseSize(%q) returned %q expected %q", test, result, test) 435 } 436 } 437 for _, test := range invalidInput { 438 result, err := ParseSize(test) 439 if err == nil { 440 t.Errorf("TestParseSize(%q) didn't return error. Returned: %q", test, result) 441 } 442 } 443 } 444 445 func TestParseProxyBuffersSpec(t *testing.T) { 446 var testsWithValidInput = []string{"1 1k", "10 24k", "2 2K", "6 3m", "128 3M"} 447 var invalidInput = []string{"-1", "-6 2k", "", "blah", "16k", "10M", "2 4g", "3 4G"} 448 for _, test := range testsWithValidInput { 449 result, err := ParseProxyBuffersSpec(test) 450 if err != nil { 451 t.Errorf("ParseProxyBuffersSpec(%q) returned an error for valid input", test) 452 } 453 if test != result { 454 t.Errorf("TestParseProxyBuffersSpec(%q) returned %q expected %q", test, result, test) 455 } 456 } 457 for _, test := range invalidInput { 458 result, err := ParseProxyBuffersSpec(test) 459 if err == nil { 460 t.Errorf("TestParseProxyBuffersSpec(%q) didn't return error. Returned: %q", test, result) 461 } 462 } 463 } 464 465 func TestVerifyThresholds(t *testing.T) { 466 validInput := []string{ 467 "high=3 low=1", 468 "high=12 low=2", 469 "high=100 low=3", 470 "high=12 low=10", 471 "high=100 low=11", 472 "low=1 high=3", 473 "low=2 high=12", 474 "low=3 high=100", 475 "low=10 high=12", 476 "low=11 high=100", 477 } 478 invalidInput := []string{ 479 "high=101 low=10", 480 "high=101 low=999", 481 "high=1 high=1", 482 "low=1 low=20", 483 "low=", 484 "high=12", 485 "a string", 486 } 487 for _, input := range validInput { 488 if !VerifyAppProtectThresholds(input) { 489 t.Errorf("VerifyAppProtectThresholds(%s) returned false,expected true", input) 490 } 491 } 492 for _, input := range invalidInput { 493 if VerifyAppProtectThresholds(input) { 494 t.Errorf("VerifyAppProtectThresholds(%s) returned true,expected false", input) 495 } 496 } 497 } 498 499 func TestParseBool(t *testing.T) { 500 var testsWithValidInput = []struct { 501 input string 502 expected bool 503 }{ 504 {"0", false}, 505 {"1", true}, 506 {"true", true}, 507 {"false", false}, 508 } 509 510 var invalidInput = []string{ 511 "", 512 "blablah", 513 "-100", 514 "-1", 515 } 516 517 for _, test := range testsWithValidInput { 518 result, err := ParseBool(test.input) 519 if err != nil { 520 t.Errorf("TestParseBool(%q) returned an error for valid input", test.input) 521 } 522 523 if result != test.expected { 524 t.Errorf("TestParseBool(%q) returned %t expected %t", test.input, result, test.expected) 525 } 526 } 527 528 for _, input := range invalidInput { 529 _, err := ParseBool(input) 530 if err == nil { 531 t.Errorf("TestParseBool(%q) does not return an error for invalid input", input) 532 } 533 } 534 } 535 536 func TestParseInt(t *testing.T) { 537 var testsWithValidInput = []struct { 538 input string 539 expected int 540 }{ 541 {"0", 0}, 542 {"1", 1}, 543 {"-100", -100}, 544 {"123456789", 123456789}, 545 } 546 547 var invalidInput = []string{ 548 "", 549 "blablah", 550 "10000000000000000000000000000000000000000000000000000000000000000", 551 "1,000", 552 } 553 554 for _, test := range testsWithValidInput { 555 result, err := ParseInt(test.input) 556 if err != nil { 557 t.Errorf("TestParseInt(%q) returned an error for valid input", test.input) 558 } 559 560 if result != test.expected { 561 t.Errorf("TestParseInt(%q) returned %d expected %d", test.input, result, test.expected) 562 } 563 } 564 565 for _, input := range invalidInput { 566 _, err := ParseInt(input) 567 if err == nil { 568 t.Errorf("TestParseInt(%q) does not return an error for invalid input", input) 569 } 570 } 571 } 572 573 func TestParseInt64(t *testing.T) { 574 var testsWithValidInput = []struct { 575 input string 576 expected int64 577 }{ 578 {"0", 0}, 579 {"1", 1}, 580 {"-100", -100}, 581 {"123456789", 123456789}, 582 } 583 584 var invalidInput = []string{ 585 "", 586 "blablah", 587 "10000000000000000000000000000000000000000000000000000000000000000", 588 "1,000", 589 } 590 591 for _, test := range testsWithValidInput { 592 result, err := ParseInt64(test.input) 593 if err != nil { 594 t.Errorf("TestParseInt64(%q) returned an error for valid input", test.input) 595 } 596 597 if result != test.expected { 598 t.Errorf("TestParseInt64(%q) returned %d expected %d", test.input, result, test.expected) 599 } 600 } 601 602 for _, input := range invalidInput { 603 _, err := ParseInt64(input) 604 if err == nil { 605 t.Errorf("TestParseInt64(%q) does not return an error for invalid input", input) 606 } 607 } 608 } 609 610 func TestParseUint64(t *testing.T) { 611 var testsWithValidInput = []struct { 612 input string 613 expected uint64 614 }{ 615 {"0", 0}, 616 {"1", 1}, 617 {"100", 100}, 618 {"123456789", 123456789}, 619 } 620 621 var invalidInput = []string{ 622 "", 623 "blablah", 624 "10000000000000000000000000000000000000000000000000000000000000000", 625 "1,000", 626 "-1023", 627 } 628 629 for _, test := range testsWithValidInput { 630 result, err := ParseUint64(test.input) 631 if err != nil { 632 t.Errorf("TestParseUint64(%q) returned an error for valid input", test.input) 633 } 634 635 if result != test.expected { 636 t.Errorf("TestParseUint64(%q) returned %d expected %d", test.input, result, test.expected) 637 } 638 } 639 640 for _, input := range invalidInput { 641 _, err := ParseUint64(input) 642 if err == nil { 643 t.Errorf("TestParseUint64(%q) does not return an error for invalid input", input) 644 } 645 } 646 }