github.com/vmware/govmomi@v0.51.0/object/option_value_list_test.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package object_test 6 7 import ( 8 "fmt" 9 "strings" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 14 "github.com/vmware/govmomi/object" 15 "github.com/vmware/govmomi/vim25/types" 16 ) 17 18 type nillableOptionValue struct{} 19 20 func (ov nillableOptionValue) GetOptionValue() *types.OptionValue { 21 return nil 22 } 23 24 func TestOptionValueList(t *testing.T) { 25 const ( 26 sza = "a" 27 szb = "b" 28 szc = "c" 29 szd = "d" 30 sze = "e" 31 sz1 = "1" 32 sz2 = "2" 33 sz3 = "3" 34 sz4 = "4" 35 sz5 = "5" 36 i32_1 = int32(1) 37 u64_2 = uint64(2) 38 f32_3 = float32(3) 39 f64_4 = float64(4) 40 b_5 = byte(5) //nolint:revive,stylecheck 41 ) 42 43 var ( 44 psz1 = &[]string{sz1}[0] 45 pu64_2 = &[]uint64{u64_2}[0] 46 pf32_3 = &[]float32{f32_3}[0] 47 pb_5 = &[]byte{b_5}[0] //nolint:revive,stylecheck 48 ) 49 50 t.Run("OptionValueListFromMap", func(t *testing.T) { 51 52 t.Run("a nil map should return nil", func(t *testing.T) { 53 assert.Nil(t, object.OptionValueListFromMap[any](nil)) 54 }) 55 56 t.Run("a map with string values should return OptionValues", func(t *testing.T) { 57 assert.ElementsMatch( 58 t, 59 object.OptionValueListFromMap(map[string]string{ 60 szc: sz3, 61 sza: sz1, 62 szb: sz2, 63 }), 64 []types.BaseOptionValue{ 65 &types.OptionValue{Key: szb, Value: sz2}, 66 &types.OptionValue{Key: sza, Value: sz1}, 67 &types.OptionValue{Key: szc, Value: sz3}, 68 }, 69 ) 70 }) 71 72 t.Run("a map with values of varying numeric types should return OptionValues", func(t *testing.T) { 73 assert.ElementsMatch( 74 t, 75 object.OptionValueListFromMap(map[string]any{ 76 szc: f32_3, 77 sza: i32_1, 78 szb: u64_2, 79 }), 80 []types.BaseOptionValue{ 81 &types.OptionValue{Key: szb, Value: u64_2}, 82 &types.OptionValue{Key: sza, Value: i32_1}, 83 &types.OptionValue{Key: szc, Value: f32_3}, 84 }, 85 ) 86 }) 87 88 t.Run("a map with pointer values should return OptionValues", func(t *testing.T) { 89 assert.ElementsMatch( 90 t, 91 object.OptionValueListFromMap(map[string]any{ 92 szc: pf32_3, 93 sza: psz1, 94 szb: pu64_2, 95 }), 96 []types.BaseOptionValue{ 97 &types.OptionValue{Key: szb, Value: pu64_2}, 98 &types.OptionValue{Key: sza, Value: psz1}, 99 &types.OptionValue{Key: szc, Value: pf32_3}, 100 }, 101 ) 102 }) 103 }) 104 105 t.Run("IsTrueOrFalse", func(t *testing.T) { 106 107 type testCase struct { 108 name string 109 left object.OptionValueList 110 key string 111 ok bool 112 } 113 114 addBoolTestCases := func(b, ok bool) []testCase { 115 return []testCase{ 116 { 117 name: fmt.Sprintf("a key with %v should return %v", b, ok), 118 left: object.OptionValueList{ 119 &types.OptionValue{Key: sza, Value: b}, 120 }, 121 key: sza, 122 ok: ok, 123 }, 124 { 125 name: fmt.Sprintf("a key with %v should return %v", !b, !ok), 126 left: object.OptionValueList{ 127 &types.OptionValue{Key: sza, Value: !b}, 128 }, 129 key: sza, 130 ok: !ok, 131 }, 132 } 133 } 134 135 addNumericalTestCases := func(i int, ok bool) []testCase { 136 return []testCase{ 137 { 138 name: fmt.Sprintf("a key with byte(%v) should return %v", i, ok), 139 left: object.OptionValueList{ 140 &types.OptionValue{Key: sza, Value: byte(i)}, 141 }, 142 key: sza, 143 ok: ok, 144 }, 145 { 146 name: fmt.Sprintf("a key with uint(%v) should return %v", i, ok), 147 left: object.OptionValueList{ 148 &types.OptionValue{Key: sza, Value: uint(i)}, 149 }, 150 key: sza, 151 ok: ok, 152 }, 153 { 154 name: fmt.Sprintf("a key with uint8(%v) should return %v", i, ok), 155 left: object.OptionValueList{ 156 &types.OptionValue{Key: sza, Value: uint8(i)}, 157 }, 158 key: sza, 159 ok: ok, 160 }, 161 { 162 name: fmt.Sprintf("a key with uint16(%v) should return %v", i, ok), 163 left: object.OptionValueList{ 164 &types.OptionValue{Key: sza, Value: uint16(i)}, 165 }, 166 key: sza, 167 ok: ok, 168 }, 169 { 170 name: fmt.Sprintf("a key with uint32(%v) should return %v", i, ok), 171 left: object.OptionValueList{ 172 &types.OptionValue{Key: sza, Value: uint32(i)}, 173 }, 174 key: sza, 175 ok: ok, 176 }, 177 { 178 name: fmt.Sprintf("a key with uint64(%v) should return %v", i, ok), 179 left: object.OptionValueList{ 180 &types.OptionValue{Key: sza, Value: uint64(i)}, 181 }, 182 key: sza, 183 ok: ok, 184 }, 185 186 { 187 name: fmt.Sprintf("a key with int(%v) should return %v", i, ok), 188 left: object.OptionValueList{ 189 &types.OptionValue{Key: sza, Value: int(i)}, 190 }, 191 key: sza, 192 ok: ok, 193 }, 194 { 195 name: fmt.Sprintf("a key with int8(%v) should return %v", i, ok), 196 left: object.OptionValueList{ 197 &types.OptionValue{Key: sza, Value: int8(i)}, 198 }, 199 key: sza, 200 ok: ok, 201 }, 202 { 203 name: fmt.Sprintf("a key with int16(%v) should return %v", i, ok), 204 left: object.OptionValueList{ 205 &types.OptionValue{Key: sza, Value: int16(i)}, 206 }, 207 key: sza, 208 ok: ok, 209 }, 210 { 211 name: fmt.Sprintf("a key with int32(%v) should return %v", i, ok), 212 left: object.OptionValueList{ 213 &types.OptionValue{Key: sza, Value: int32(i)}, 214 }, 215 key: sza, 216 ok: ok, 217 }, 218 { 219 name: fmt.Sprintf("a key with int64(%v) should return %v", i, ok), 220 left: object.OptionValueList{ 221 &types.OptionValue{Key: sza, Value: int64(i)}, 222 }, 223 key: sza, 224 ok: ok, 225 }, 226 227 { 228 name: fmt.Sprintf("a key with float32(%v) should return %v", i, ok), 229 left: object.OptionValueList{ 230 &types.OptionValue{Key: sza, Value: float32(i)}, 231 }, 232 key: sza, 233 ok: ok, 234 }, 235 { 236 name: fmt.Sprintf("a key with float64(%v) should return %v", i, ok), 237 left: object.OptionValueList{ 238 &types.OptionValue{Key: sza, Value: float64(i)}, 239 }, 240 key: sza, 241 ok: ok, 242 }, 243 } 244 } 245 246 addTestCasesForPermutedString := func(s string, ok bool) []testCase { 247 var testCases []testCase 248 for _, s := range permuteByCase(s) { 249 testCases = append(testCases, testCase{ 250 name: fmt.Sprintf("a key with %q should return %v", s, ok), 251 left: object.OptionValueList{ 252 &types.OptionValue{Key: sza, Value: s}, 253 }, 254 key: sza, 255 ok: ok, 256 }) 257 } 258 return testCases 259 } 260 261 addTestCasesForPermutedStrings := func(ok bool, args ...string) []testCase { 262 var testCases []testCase 263 for i := range args { 264 testCases = append(testCases, addTestCasesForPermutedString(args[i], ok)...) 265 } 266 return testCases 267 } 268 269 baseTestCases := []testCase{ 270 { 271 name: "a nil receiver should not panic and return false", 272 left: nil, 273 key: "", 274 ok: false, 275 }, 276 { 277 name: "a non-existent key should return false", 278 left: object.OptionValueList{}, 279 key: "", 280 ok: false, 281 }, 282 } 283 284 runTests := func(t *testing.T, expected bool) { 285 testCases := append([]testCase{}, baseTestCases...) 286 287 for i := range baseTestCases { 288 tc := testCases[i] 289 t.Run(tc.name, func(t *testing.T) { 290 var ok bool 291 if expected { 292 assert.NotPanics(t, func() { ok = tc.left.IsTrue(tc.key) }) 293 assert.Equal(t, tc.ok, ok) 294 } else { 295 assert.NotPanics(t, func() { ok = tc.left.IsFalse(tc.key) }) 296 assert.Equal(t, tc.ok, ok) 297 } 298 }) 299 } 300 301 testCases = append([]testCase{}, addBoolTestCases(true, expected)...) 302 testCases = append(testCases, addNumericalTestCases(0, !expected)...) 303 testCases = append(testCases, addNumericalTestCases(1, expected)...) 304 testCases = append(testCases, addTestCasesForPermutedStrings(expected, "", "1", "on", "t", "true", "y", "yes")...) 305 testCases = append(testCases, addTestCasesForPermutedStrings(!expected, "0", "f", "false", "n", "no", "off")...) 306 307 for i := range testCases { 308 tc := testCases[i] 309 t.Run(tc.name, func(t *testing.T) { 310 var ok bool 311 if expected { 312 assert.NotPanics(t, func() { ok = tc.left.IsTrue(tc.key) }) 313 assert.Equal(t, tc.ok, ok) 314 assert.NotPanics(t, func() { ok = tc.left.IsFalse(tc.key) }) 315 assert.Equal(t, !tc.ok, ok) 316 } else { 317 assert.NotPanics(t, func() { ok = tc.left.IsTrue(tc.key) }) 318 assert.Equal(t, !tc.ok, ok) 319 assert.NotPanics(t, func() { ok = tc.left.IsFalse(tc.key) }) 320 assert.Equal(t, tc.ok, ok) 321 } 322 323 }) 324 } 325 } 326 327 t.Run("IsTrue", func(t *testing.T) { runTests(t, true) }) 328 t.Run("IsFalse", func(t *testing.T) { runTests(t, false) }) 329 330 }) 331 332 t.Run("Get", func(t *testing.T) { 333 testCases := []struct { 334 name string 335 left object.OptionValueList 336 key string 337 out any 338 ok bool 339 }{ 340 { 341 name: "a nil receiver should not panic and return nil, false", 342 left: nil, 343 key: "", 344 out: nil, 345 ok: false, 346 }, 347 { 348 name: "a non-existent key should return nil, false", 349 left: object.OptionValueList{}, 350 key: "", 351 out: nil, 352 ok: false, 353 }, 354 { 355 name: "an existing key should return its value, true", 356 left: object.OptionValueList{ 357 &types.OptionValue{Key: sza, Value: sz1}, 358 }, 359 key: sza, 360 out: sz1, 361 ok: true, 362 }, 363 { 364 name: "an existing key should return its value, true when data includes a nillable types.BaseOptionValue", 365 left: object.OptionValueList{ 366 nillableOptionValue{}, 367 &types.OptionValue{Key: sza, Value: sz1}, 368 }, 369 key: sza, 370 out: sz1, 371 ok: true, 372 }, 373 } 374 375 for i := range testCases { 376 tc := testCases[i] 377 t.Run(tc.name, func(t *testing.T) { 378 var ( 379 out any 380 ok bool 381 ) 382 assert.NotPanics(t, func() { out, ok = tc.left.Get(tc.key) }) 383 assert.Equal(t, tc.out, out) 384 assert.Equal(t, tc.ok, ok) 385 }) 386 } 387 }) 388 389 t.Run("GetString", func(t *testing.T) { 390 testCases := []struct { 391 name string 392 left object.OptionValueList 393 key string 394 out string 395 ok bool 396 }{ 397 { 398 name: "a nil receiver should not panic and return \"\", false", 399 left: nil, 400 key: "", 401 out: "", 402 ok: false, 403 }, 404 { 405 name: "a non-existent key should return \"\", false", 406 left: object.OptionValueList{}, 407 key: "", 408 out: "", 409 ok: false, 410 }, 411 { 412 name: "an existing key for a string value should return its string value, true", 413 left: object.OptionValueList{ 414 &types.OptionValue{Key: sza, Value: sz1}, 415 }, 416 key: sza, 417 out: sz1, 418 ok: true, 419 }, 420 { 421 name: "an existing key for a *string value that is not nil should return its string value, true", 422 left: object.OptionValueList{ 423 &types.OptionValue{Key: sza, Value: psz1}, 424 }, 425 key: sza, 426 out: sz1, 427 ok: true, 428 }, 429 { 430 name: "an existing key for a *string value that is nil should return \"\", true", 431 left: object.OptionValueList{ 432 &types.OptionValue{Key: sza, Value: (*string)(nil)}, 433 }, 434 key: sza, 435 out: "", 436 ok: true, 437 }, 438 { 439 name: "an existing key for an int32 value should return its string value, true", 440 left: object.OptionValueList{ 441 &types.OptionValue{Key: sza, Value: i32_1}, 442 }, 443 key: sza, 444 out: sz1, 445 ok: true, 446 }, 447 { 448 name: "an existing key for a *uint64 value that is not nil should return its string value, true", 449 left: object.OptionValueList{ 450 &types.OptionValue{Key: sza, Value: pu64_2}, 451 }, 452 key: sza, 453 out: sz2, 454 ok: true, 455 }, 456 { 457 name: "an existing key for a *uint64 value that is nil should return \"\", true", 458 left: object.OptionValueList{ 459 &types.OptionValue{Key: sza, Value: (*uint64)(nil)}, 460 }, 461 key: sza, 462 out: "", 463 ok: true, 464 }, 465 { 466 name: "an existing key for a string value should return its string value, true when data includes a nillable types.BaseOptionValue", 467 left: object.OptionValueList{ 468 nillableOptionValue{}, 469 &types.OptionValue{Key: sza, Value: sz1}, 470 }, 471 key: sza, 472 out: sz1, 473 ok: true, 474 }, 475 } 476 477 for i := range testCases { 478 tc := testCases[i] 479 t.Run(tc.name, func(t *testing.T) { 480 var ( 481 out string 482 ok bool 483 ) 484 assert.NotPanics(t, func() { out, ok = tc.left.GetString(tc.key) }) 485 assert.Equal(t, tc.out, out) 486 assert.Equal(t, tc.ok, ok) 487 }) 488 } 489 }) 490 491 t.Run("Map", func(t *testing.T) { 492 testCases := []struct { 493 name string 494 left object.OptionValueList 495 out map[string]any 496 }{ 497 { 498 name: "a nil receiver should not panic and return nil", 499 left: nil, 500 out: nil, 501 }, 502 { 503 name: "data with homogeneous values should return a map", 504 left: object.OptionValueList{ 505 &types.OptionValue{Key: sza, Value: sz1}, 506 }, 507 out: map[string]any{ 508 sza: sz1, 509 }, 510 }, 511 { 512 name: "data with heterogeneous values should return a map", 513 left: object.OptionValueList{ 514 &types.OptionValue{Key: sza, Value: sz1}, 515 &types.OptionValue{Key: szb, Value: u64_2}, 516 &types.OptionValue{Key: szc, Value: pf32_3}, 517 }, 518 out: map[string]any{ 519 sza: sz1, 520 szb: u64_2, 521 szc: pf32_3, 522 }, 523 }, 524 { 525 name: "data with just a nillable types.BaseOptionValue should return nil", 526 left: object.OptionValueList{ 527 nillableOptionValue{}, 528 }, 529 out: nil, 530 }, 531 } 532 533 for i := range testCases { 534 tc := testCases[i] 535 t.Run(tc.name, func(t *testing.T) { 536 var out map[string]any 537 assert.NotPanics(t, func() { out = tc.left.Map() }) 538 assert.Equal(t, tc.out, out) 539 }) 540 } 541 }) 542 543 t.Run("StringMap", func(t *testing.T) { 544 testCases := []struct { 545 name string 546 left object.OptionValueList 547 out map[string]string 548 }{ 549 { 550 name: "a nil receiver should not panic and return nil", 551 left: nil, 552 out: nil, 553 }, 554 { 555 name: "data with homogeneous values should return a map", 556 left: object.OptionValueList{ 557 &types.OptionValue{Key: sza, Value: sz1}, 558 }, 559 out: map[string]string{ 560 sza: sz1, 561 }, 562 }, 563 { 564 name: "data with heterogeneous values should return a map", 565 left: object.OptionValueList{ 566 &types.OptionValue{Key: sza, Value: sz1}, 567 &types.OptionValue{Key: szb, Value: u64_2}, 568 &types.OptionValue{Key: szc, Value: pf32_3}, 569 }, 570 out: map[string]string{ 571 sza: sz1, 572 szb: sz2, 573 szc: sz3, 574 }, 575 }, 576 { 577 name: "data with just a nillable types.BaseOptionValue should return nil", 578 left: object.OptionValueList{ 579 nillableOptionValue{}, 580 }, 581 out: nil, 582 }, 583 } 584 585 for i := range testCases { 586 tc := testCases[i] 587 t.Run(tc.name, func(t *testing.T) { 588 var out map[string]string 589 assert.NotPanics(t, func() { out = tc.left.StringMap() }) 590 assert.Equal(t, tc.out, out) 591 }) 592 } 593 }) 594 595 t.Run("Additions", func(t *testing.T) { 596 testCases := []struct { 597 name string 598 left object.OptionValueList 599 right object.OptionValueList 600 out object.OptionValueList 601 }{ 602 { 603 name: "a nil receiver and nil input should not panic and return nil", 604 left: nil, 605 right: nil, 606 out: nil, 607 }, 608 { 609 name: "a nil receiver and non-nil input should not panic and return the diff", 610 left: nil, 611 right: object.OptionValueList{ 612 &types.OptionValue{Key: szb, Value: ""}, 613 &types.OptionValue{Key: szd, Value: f64_4}, 614 &types.OptionValue{Key: sze, Value: pb_5}, 615 }, 616 out: object.OptionValueList{ 617 &types.OptionValue{Key: szb, Value: ""}, 618 &types.OptionValue{Key: szd, Value: f64_4}, 619 &types.OptionValue{Key: sze, Value: pb_5}, 620 }, 621 }, 622 { 623 name: "a non-nil receiver and nil input should return nil", 624 left: object.OptionValueList{ 625 &types.OptionValue{Key: sza, Value: sz1}, 626 &types.OptionValue{Key: szb, Value: sz2}, 627 &types.OptionValue{Key: szc, Value: sz3}, 628 }, 629 right: nil, 630 out: nil, 631 }, 632 { 633 name: "a non-nil receiver and non-nil input should return the diff", 634 left: object.OptionValueList{ 635 &types.OptionValue{Key: sza, Value: sz1}, 636 &types.OptionValue{Key: szb, Value: sz2}, 637 &types.OptionValue{Key: szc, Value: sz3}, 638 }, 639 right: object.OptionValueList{ 640 &types.OptionValue{Key: szb, Value: ""}, 641 &types.OptionValue{Key: szd, Value: f64_4}, 642 &types.OptionValue{Key: sze, Value: pb_5}, 643 }, 644 out: object.OptionValueList{ 645 &types.OptionValue{Key: szd, Value: f64_4}, 646 &types.OptionValue{Key: sze, Value: pb_5}, 647 }, 648 }, 649 } 650 651 for i := range testCases { 652 tc := testCases[i] 653 t.Run(tc.name, func(t *testing.T) { 654 var out object.OptionValueList 655 assert.NotPanics(t, func() { out = tc.left.Additions(tc.right...) }) 656 assert.Equal(t, tc.out, out) 657 }) 658 } 659 }) 660 661 t.Run("Diff", func(t *testing.T) { 662 testCases := []struct { 663 name string 664 left object.OptionValueList 665 right object.OptionValueList 666 out object.OptionValueList 667 }{ 668 { 669 name: "a nil receiver and nil input should not panic and return nil", 670 left: nil, 671 right: nil, 672 out: nil, 673 }, 674 { 675 name: "a nil receiver and non-nil input should not panic and return the diff", 676 left: nil, 677 right: object.OptionValueList{ 678 &types.OptionValue{Key: szb, Value: ""}, 679 &types.OptionValue{Key: szd, Value: f64_4}, 680 &types.OptionValue{Key: sze, Value: pb_5}, 681 }, 682 out: object.OptionValueList{ 683 &types.OptionValue{Key: szb, Value: ""}, 684 &types.OptionValue{Key: szd, Value: f64_4}, 685 &types.OptionValue{Key: sze, Value: pb_5}, 686 }, 687 }, 688 { 689 name: "a non-nil receiver and nil input should return nil", 690 left: object.OptionValueList{ 691 &types.OptionValue{Key: sza, Value: sz1}, 692 &types.OptionValue{Key: szb, Value: sz2}, 693 &types.OptionValue{Key: szc, Value: sz3}, 694 }, 695 right: nil, 696 out: nil, 697 }, 698 { 699 name: "a non-nil receiver and non-nil input should return the diff", 700 left: object.OptionValueList{ 701 &types.OptionValue{Key: sza, Value: sz1}, 702 &types.OptionValue{Key: szb, Value: sz2}, 703 &types.OptionValue{Key: szc, Value: sz3}, 704 }, 705 right: object.OptionValueList{ 706 &types.OptionValue{Key: szb, Value: ""}, 707 &types.OptionValue{Key: szd, Value: f64_4}, 708 &types.OptionValue{Key: sze, Value: pb_5}, 709 }, 710 out: object.OptionValueList{ 711 &types.OptionValue{Key: szb, Value: ""}, 712 &types.OptionValue{Key: szd, Value: f64_4}, 713 &types.OptionValue{Key: sze, Value: pb_5}, 714 }, 715 }, 716 } 717 718 for i := range testCases { 719 tc := testCases[i] 720 t.Run(tc.name, func(t *testing.T) { 721 var out object.OptionValueList 722 assert.NotPanics(t, func() { out = tc.left.Diff(tc.right...) }) 723 assert.Equal(t, tc.out, out) 724 }) 725 } 726 }) 727 728 t.Run("Join", func(t *testing.T) { 729 testCases := []struct { 730 name string 731 left object.OptionValueList 732 right object.OptionValueList 733 out object.OptionValueList 734 }{ 735 { 736 name: "a nil receiver and nil input should not panic and return nil", 737 left: nil, 738 right: nil, 739 out: nil, 740 }, 741 { 742 name: "a nil receiver and non-nil input should not panic and return the joined data", 743 left: nil, 744 right: object.OptionValueList{ 745 &types.OptionValue{Key: szb, Value: ""}, 746 &types.OptionValue{Key: szd, Value: f64_4}, 747 &types.OptionValue{Key: sze, Value: pb_5}, 748 }, 749 out: object.OptionValueList{ 750 &types.OptionValue{Key: szb, Value: ""}, 751 &types.OptionValue{Key: szd, Value: f64_4}, 752 &types.OptionValue{Key: sze, Value: pb_5}, 753 }, 754 }, 755 { 756 name: "a non-nil receiver and nil input should return the joined data", 757 left: object.OptionValueList{ 758 &types.OptionValue{Key: sza, Value: sz1}, 759 &types.OptionValue{Key: szb, Value: sz2}, 760 &types.OptionValue{Key: szc, Value: sz3}, 761 }, 762 right: nil, 763 out: object.OptionValueList{ 764 &types.OptionValue{Key: sza, Value: sz1}, 765 &types.OptionValue{Key: szb, Value: sz2}, 766 &types.OptionValue{Key: szc, Value: sz3}, 767 }, 768 }, 769 { 770 name: "a non-nil receiver and non-nil input should return the joined data", 771 left: object.OptionValueList{ 772 &types.OptionValue{Key: sza, Value: sz1}, 773 &types.OptionValue{Key: szb, Value: sz2}, 774 &types.OptionValue{Key: szc, Value: sz3}, 775 }, 776 right: object.OptionValueList{ 777 &types.OptionValue{Key: szb, Value: ""}, 778 &types.OptionValue{Key: szd, Value: f64_4}, 779 &types.OptionValue{Key: sze, Value: pb_5}, 780 }, 781 out: object.OptionValueList{ 782 &types.OptionValue{Key: sza, Value: sz1}, 783 &types.OptionValue{Key: szb, Value: sz2}, 784 &types.OptionValue{Key: szc, Value: sz3}, 785 &types.OptionValue{Key: szd, Value: f64_4}, 786 &types.OptionValue{Key: sze, Value: pb_5}, 787 }, 788 }, 789 { 790 name: "a non-nil receiver and non-nil input, flipping left and right, should return the joined data", 791 left: object.OptionValueList{ 792 &types.OptionValue{Key: szb, Value: ""}, 793 &types.OptionValue{Key: szd, Value: f64_4}, 794 &types.OptionValue{Key: sze, Value: pb_5}, 795 }, 796 right: object.OptionValueList{ 797 &types.OptionValue{Key: sza, Value: sz1}, 798 &types.OptionValue{Key: szb, Value: sz2}, 799 &types.OptionValue{Key: szc, Value: sz3}, 800 }, 801 out: object.OptionValueList{ 802 &types.OptionValue{Key: szb, Value: ""}, 803 &types.OptionValue{Key: szd, Value: f64_4}, 804 &types.OptionValue{Key: sze, Value: pb_5}, 805 &types.OptionValue{Key: sza, Value: sz1}, 806 &types.OptionValue{Key: szc, Value: sz3}, 807 }, 808 }, 809 } 810 811 for i := range testCases { 812 tc := testCases[i] 813 t.Run(tc.name, func(t *testing.T) { 814 var out object.OptionValueList 815 assert.NotPanics(t, func() { out = tc.left.Join(tc.right...) }) 816 assert.Equal(t, tc.out, out) 817 }) 818 } 819 }) 820 } 821 822 func permuteByCase(s string) []string { 823 if len(s) == 0 { 824 return []string{s} 825 } 826 827 if len(s) == 1 { 828 lc := strings.ToLower(s) 829 uc := strings.ToUpper(s) 830 if lc == uc { 831 return []string{s} 832 } 833 return []string{lc, uc} 834 } 835 836 var p []string 837 for _, i := range permuteByCase(s[0:1]) { 838 for _, j := range permuteByCase(s[1:]) { 839 p = append(p, fmt.Sprintf("%s%s", i, j)) 840 } 841 } 842 843 return p 844 }