1package structs 2 3import ( 4 "fmt" 5 "reflect" 6 "testing" 7 "time" 8) 9 10func TestMapNonStruct(t *testing.T) { 11 foo := []string{"foo"} 12 13 defer func() { 14 err := recover() 15 if err == nil { 16 t.Error("Passing a non struct into Map should panic") 17 } 18 }() 19 20 // this should panic. We are going to recover and and test it 21 _ = Map(foo) 22} 23 24func TestStructIndexes(t *testing.T) { 25 type C struct { 26 something int 27 Props map[string]interface{} 28 } 29 30 defer func() { 31 err := recover() 32 if err != nil { 33 fmt.Printf("err %+v\n", err) 34 t.Error("Using mixed indexes should not panic") 35 } 36 }() 37 38 // They should not panic 39 _ = Map(&C{}) 40 _ = Fields(&C{}) 41 _ = Values(&C{}) 42 _ = IsZero(&C{}) 43 _ = HasZero(&C{}) 44} 45 46func TestMap(t *testing.T) { 47 var T = struct { 48 A string 49 B int 50 C bool 51 }{ 52 A: "a-value", 53 B: 2, 54 C: true, 55 } 56 57 a := Map(T) 58 59 if typ := reflect.TypeOf(a).Kind(); typ != reflect.Map { 60 t.Errorf("Map should return a map type, got: %v", typ) 61 } 62 63 // we have three fields 64 if len(a) != 3 { 65 t.Errorf("Map should return a map of len 3, got: %d", len(a)) 66 } 67 68 inMap := func(val interface{}) bool { 69 for _, v := range a { 70 if reflect.DeepEqual(v, val) { 71 return true 72 } 73 } 74 75 return false 76 } 77 78 for _, val := range []interface{}{"a-value", 2, true} { 79 if !inMap(val) { 80 t.Errorf("Map should have the value %v", val) 81 } 82 } 83 84} 85 86func TestMap_Tag(t *testing.T) { 87 var T = struct { 88 A string `structs:"x"` 89 B int `structs:"y"` 90 C bool `structs:"z"` 91 }{ 92 A: "a-value", 93 B: 2, 94 C: true, 95 } 96 97 a := Map(T) 98 99 inMap := func(key interface{}) bool { 100 for k := range a { 101 if reflect.DeepEqual(k, key) { 102 return true 103 } 104 } 105 return false 106 } 107 108 for _, key := range []string{"x", "y", "z"} { 109 if !inMap(key) { 110 t.Errorf("Map should have the key %v", key) 111 } 112 } 113 114} 115 116func TestMap_CustomTag(t *testing.T) { 117 var T = struct { 118 A string `json:"x"` 119 B int `json:"y"` 120 C bool `json:"z"` 121 D struct { 122 E string `json:"jkl"` 123 } `json:"nested"` 124 }{ 125 A: "a-value", 126 B: 2, 127 C: true, 128 } 129 T.D.E = "e-value" 130 131 s := New(T) 132 s.TagName = "json" 133 134 a := s.Map() 135 136 inMap := func(key interface{}) bool { 137 for k := range a { 138 if reflect.DeepEqual(k, key) { 139 return true 140 } 141 } 142 return false 143 } 144 145 for _, key := range []string{"x", "y", "z"} { 146 if !inMap(key) { 147 t.Errorf("Map should have the key %v", key) 148 } 149 } 150 151 nested, ok := a["nested"].(map[string]interface{}) 152 if !ok { 153 t.Fatalf("Map should contain the D field that is tagged as 'nested'") 154 } 155 156 e, ok := nested["jkl"].(string) 157 if !ok { 158 t.Fatalf("Map should contain the D.E field that is tagged as 'jkl'") 159 } 160 161 if e != "e-value" { 162 t.Errorf("D.E field should be equal to 'e-value', got: '%v'", e) 163 } 164 165} 166 167func TestMap_MultipleCustomTag(t *testing.T) { 168 var A = struct { 169 X string `aa:"ax"` 170 }{"a_value"} 171 172 aStruct := New(A) 173 aStruct.TagName = "aa" 174 175 var B = struct { 176 X string `bb:"bx"` 177 }{"b_value"} 178 179 bStruct := New(B) 180 bStruct.TagName = "bb" 181 182 a, b := aStruct.Map(), bStruct.Map() 183 if !reflect.DeepEqual(a, map[string]interface{}{"ax": "a_value"}) { 184 t.Error("Map should have field ax with value a_value") 185 } 186 187 if !reflect.DeepEqual(b, map[string]interface{}{"bx": "b_value"}) { 188 t.Error("Map should have field bx with value b_value") 189 } 190} 191 192func TestMap_OmitEmpty(t *testing.T) { 193 type A struct { 194 Name string 195 Value string `structs:",omitempty"` 196 Time time.Time `structs:",omitempty"` 197 } 198 a := A{} 199 200 m := Map(a) 201 202 _, ok := m["Value"].(map[string]interface{}) 203 if ok { 204 t.Error("Map should not contain the Value field that is tagged as omitempty") 205 } 206 207 _, ok = m["Time"].(map[string]interface{}) 208 if ok { 209 t.Error("Map should not contain the Time field that is tagged as omitempty") 210 } 211} 212 213func TestMap_OmitNested(t *testing.T) { 214 type A struct { 215 Name string 216 Value string 217 Time time.Time `structs:",omitnested"` 218 } 219 a := A{Time: time.Now()} 220 221 type B struct { 222 Desc string 223 A A 224 } 225 b := &B{A: a} 226 227 m := Map(b) 228 229 in, ok := m["A"].(map[string]interface{}) 230 if !ok { 231 t.Error("Map nested structs is not available in the map") 232 } 233 234 // should not happen 235 if _, ok := in["Time"].(map[string]interface{}); ok { 236 t.Error("Map nested struct should omit recursiving parsing of Time") 237 } 238 239 if _, ok := in["Time"].(time.Time); !ok { 240 t.Error("Map nested struct should stop parsing of Time at is current value") 241 } 242} 243 244func TestMap_Nested(t *testing.T) { 245 type A struct { 246 Name string 247 } 248 a := &A{Name: "example"} 249 250 type B struct { 251 A *A 252 } 253 b := &B{A: a} 254 255 m := Map(b) 256 257 if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { 258 t.Errorf("Map should return a map type, got: %v", typ) 259 } 260 261 in, ok := m["A"].(map[string]interface{}) 262 if !ok { 263 t.Error("Map nested structs is not available in the map") 264 } 265 266 if name := in["Name"].(string); name != "example" { 267 t.Errorf("Map nested struct's name field should give example, got: %s", name) 268 } 269} 270 271func TestMap_NestedMapWithStructValues(t *testing.T) { 272 type A struct { 273 Name string 274 } 275 276 type B struct { 277 A map[string]*A 278 } 279 280 a := &A{Name: "example"} 281 282 b := &B{ 283 A: map[string]*A{ 284 "example_key": a, 285 }, 286 } 287 288 m := Map(b) 289 290 if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { 291 t.Errorf("Map should return a map type, got: %v", typ) 292 } 293 294 in, ok := m["A"].(map[string]interface{}) 295 if !ok { 296 t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["A"]) 297 } 298 299 example := in["example_key"].(map[string]interface{}) 300 if name := example["Name"].(string); name != "example" { 301 t.Errorf("Map nested struct's name field should give example, got: %s", name) 302 } 303} 304 305func TestMap_NestedMapWithStringValues(t *testing.T) { 306 type B struct { 307 Foo map[string]string 308 } 309 310 type A struct { 311 B *B 312 } 313 314 b := &B{ 315 Foo: map[string]string{ 316 "example_key": "example", 317 }, 318 } 319 320 a := &A{B: b} 321 322 m := Map(a) 323 324 if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { 325 t.Errorf("Map should return a map type, got: %v", typ) 326 } 327 328 in, ok := m["B"].(map[string]interface{}) 329 if !ok { 330 t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"]) 331 } 332 333 foo := in["Foo"].(map[string]string) 334 if name := foo["example_key"]; name != "example" { 335 t.Errorf("Map nested struct's name field should give example, got: %s", name) 336 } 337} 338func TestMap_NestedMapWithInterfaceValues(t *testing.T) { 339 type B struct { 340 Foo map[string]interface{} 341 } 342 343 type A struct { 344 B *B 345 } 346 347 b := &B{ 348 Foo: map[string]interface{}{ 349 "example_key": "example", 350 }, 351 } 352 353 a := &A{B: b} 354 355 m := Map(a) 356 357 if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { 358 t.Errorf("Map should return a map type, got: %v", typ) 359 } 360 361 in, ok := m["B"].(map[string]interface{}) 362 if !ok { 363 t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"]) 364 } 365 366 foo := in["Foo"].(map[string]interface{}) 367 if name := foo["example_key"]; name != "example" { 368 t.Errorf("Map nested struct's name field should give example, got: %s", name) 369 } 370} 371 372func TestMap_NestedMapWithSliceIntValues(t *testing.T) { 373 type B struct { 374 Foo map[string][]int 375 } 376 377 type A struct { 378 B *B 379 } 380 381 b := &B{ 382 Foo: map[string][]int{ 383 "example_key": {80}, 384 }, 385 } 386 387 a := &A{B: b} 388 389 m := Map(a) 390 391 if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { 392 t.Errorf("Map should return a map type, got: %v", typ) 393 } 394 395 in, ok := m["B"].(map[string]interface{}) 396 if !ok { 397 t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"]) 398 } 399 400 foo := in["Foo"].(map[string][]int) 401 if name := foo["example_key"]; name[0] != 80 { 402 t.Errorf("Map nested struct's name field should give example, got: %v", name) 403 } 404} 405 406func TestMap_NestedMapWithSliceStructValues(t *testing.T) { 407 type address struct { 408 Country string `structs:"country"` 409 } 410 411 type B struct { 412 Foo map[string][]address 413 } 414 415 type A struct { 416 B *B 417 } 418 419 b := &B{ 420 Foo: map[string][]address{ 421 "example_key": { 422 {Country: "Turkey"}, 423 }, 424 }, 425 } 426 427 a := &A{B: b} 428 m := Map(a) 429 430 if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { 431 t.Errorf("Map should return a map type, got: %v", typ) 432 } 433 434 in, ok := m["B"].(map[string]interface{}) 435 if !ok { 436 t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"]) 437 } 438 439 foo := in["Foo"].(map[string]interface{}) 440 441 addresses := foo["example_key"].([]interface{}) 442 443 addr, ok := addresses[0].(map[string]interface{}) 444 if !ok { 445 t.Errorf("Nested type of map should be of type map[string]interface{}, have %T", m["B"]) 446 } 447 448 if _, exists := addr["country"]; !exists { 449 t.Errorf("Expecting country, but found Country") 450 } 451} 452 453func TestMap_NestedSliceWithStructValues(t *testing.T) { 454 type address struct { 455 Country string `structs:"customCountryName"` 456 } 457 458 type person struct { 459 Name string `structs:"name"` 460 Addresses []address `structs:"addresses"` 461 } 462 463 p := person{ 464 Name: "test", 465 Addresses: []address{ 466 {Country: "England"}, 467 {Country: "Italy"}, 468 }, 469 } 470 mp := Map(p) 471 472 mpAddresses := mp["addresses"].([]interface{}) 473 if _, exists := mpAddresses[0].(map[string]interface{})["Country"]; exists { 474 t.Errorf("Expecting customCountryName, but found Country") 475 } 476 477 if _, exists := mpAddresses[0].(map[string]interface{})["customCountryName"]; !exists { 478 t.Errorf("customCountryName key not found") 479 } 480} 481 482func TestMap_NestedSliceWithPointerOfStructValues(t *testing.T) { 483 type address struct { 484 Country string `structs:"customCountryName"` 485 } 486 487 type person struct { 488 Name string `structs:"name"` 489 Addresses []*address `structs:"addresses"` 490 } 491 492 p := person{ 493 Name: "test", 494 Addresses: []*address{ 495 {Country: "England"}, 496 {Country: "Italy"}, 497 }, 498 } 499 mp := Map(p) 500 501 mpAddresses := mp["addresses"].([]interface{}) 502 if _, exists := mpAddresses[0].(map[string]interface{})["Country"]; exists { 503 t.Errorf("Expecting customCountryName, but found Country") 504 } 505 506 if _, exists := mpAddresses[0].(map[string]interface{})["customCountryName"]; !exists { 507 t.Errorf("customCountryName key not found") 508 } 509} 510 511func TestMap_NestedSliceWithIntValues(t *testing.T) { 512 type person struct { 513 Name string `structs:"name"` 514 Ports []int `structs:"ports"` 515 } 516 517 p := person{ 518 Name: "test", 519 Ports: []int{80}, 520 } 521 m := Map(p) 522 523 ports, ok := m["ports"].([]int) 524 if !ok { 525 t.Errorf("Nested type of map should be of type []int, have %T", m["ports"]) 526 } 527 528 if ports[0] != 80 { 529 t.Errorf("Map nested struct's ports field should give 80, got: %v", ports) 530 } 531} 532 533func TestMap_Anonymous(t *testing.T) { 534 type A struct { 535 Name string 536 } 537 a := &A{Name: "example"} 538 539 type B struct { 540 *A 541 } 542 b := &B{} 543 b.A = a 544 545 m := Map(b) 546 547 if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { 548 t.Errorf("Map should return a map type, got: %v", typ) 549 } 550 551 in, ok := m["A"].(map[string]interface{}) 552 if !ok { 553 t.Error("Embedded structs is not available in the map") 554 } 555 556 if name := in["Name"].(string); name != "example" { 557 t.Errorf("Embedded A struct's Name field should give example, got: %s", name) 558 } 559} 560 561func TestMap_Flatnested(t *testing.T) { 562 type A struct { 563 Name string 564 } 565 a := A{Name: "example"} 566 567 type B struct { 568 A `structs:",flatten"` 569 C int 570 } 571 b := &B{C: 123} 572 b.A = a 573 574 m := Map(b) 575 576 _, ok := m["A"].(map[string]interface{}) 577 if ok { 578 t.Error("Embedded A struct with tag flatten has to be flat in the map") 579 } 580 581 expectedMap := map[string]interface{}{"Name": "example", "C": 123} 582 if !reflect.DeepEqual(m, expectedMap) { 583 t.Errorf("The exprected map %+v does't correspond to %+v", expectedMap, m) 584 } 585 586} 587 588func TestMap_FlatnestedOverwrite(t *testing.T) { 589 type A struct { 590 Name string 591 } 592 a := A{Name: "example"} 593 594 type B struct { 595 A `structs:",flatten"` 596 Name string 597 C int 598 } 599 b := &B{C: 123, Name: "bName"} 600 b.A = a 601 602 m := Map(b) 603 604 _, ok := m["A"].(map[string]interface{}) 605 if ok { 606 t.Error("Embedded A struct with tag flatten has to be flat in the map") 607 } 608 609 expectedMap := map[string]interface{}{"Name": "bName", "C": 123} 610 if !reflect.DeepEqual(m, expectedMap) { 611 t.Errorf("The exprected map %+v does't correspond to %+v", expectedMap, m) 612 } 613} 614 615func TestMap_TimeField(t *testing.T) { 616 type A struct { 617 CreatedAt time.Time 618 } 619 620 a := &A{CreatedAt: time.Now().UTC()} 621 m := Map(a) 622 623 _, ok := m["CreatedAt"].(time.Time) 624 if !ok { 625 t.Error("Time field must be final") 626 } 627} 628 629func TestFillMap(t *testing.T) { 630 var T = struct { 631 A string 632 B int 633 C bool 634 }{ 635 A: "a-value", 636 B: 2, 637 C: true, 638 } 639 640 a := make(map[string]interface{}, 0) 641 FillMap(T, a) 642 643 // we have three fields 644 if len(a) != 3 { 645 t.Errorf("FillMap should fill a map of len 3, got: %d", len(a)) 646 } 647 648 inMap := func(val interface{}) bool { 649 for _, v := range a { 650 if reflect.DeepEqual(v, val) { 651 return true 652 } 653 } 654 655 return false 656 } 657 658 for _, val := range []interface{}{"a-value", 2, true} { 659 if !inMap(val) { 660 t.Errorf("FillMap should have the value %v", val) 661 } 662 } 663} 664 665func TestFillMap_Nil(t *testing.T) { 666 var T = struct { 667 A string 668 B int 669 C bool 670 }{ 671 A: "a-value", 672 B: 2, 673 C: true, 674 } 675 676 defer func() { 677 err := recover() 678 if err != nil { 679 t.Error("FillMap should not panic if a nil map is passed") 680 } 681 }() 682 683 // nil should no 684 FillMap(T, nil) 685} 686func TestStruct(t *testing.T) { 687 var T = struct{}{} 688 689 if !IsStruct(T) { 690 t.Errorf("T should be a struct, got: %T", T) 691 } 692 693 if !IsStruct(&T) { 694 t.Errorf("T should be a struct, got: %T", T) 695 } 696 697} 698 699func TestValues(t *testing.T) { 700 var T = struct { 701 A string 702 B int 703 C bool 704 }{ 705 A: "a-value", 706 B: 2, 707 C: true, 708 } 709 710 s := Values(T) 711 712 if typ := reflect.TypeOf(s).Kind(); typ != reflect.Slice { 713 t.Errorf("Values should return a slice type, got: %v", typ) 714 } 715 716 inSlice := func(val interface{}) bool { 717 for _, v := range s { 718 if reflect.DeepEqual(v, val) { 719 return true 720 } 721 } 722 return false 723 } 724 725 for _, val := range []interface{}{"a-value", 2, true} { 726 if !inSlice(val) { 727 t.Errorf("Values should have the value %v", val) 728 } 729 } 730} 731 732func TestValues_OmitEmpty(t *testing.T) { 733 type A struct { 734 Name string 735 Value int `structs:",omitempty"` 736 } 737 738 a := A{Name: "example"} 739 s := Values(a) 740 741 if len(s) != 1 { 742 t.Errorf("Values of omitted empty fields should be not counted") 743 } 744 745 if s[0].(string) != "example" { 746 t.Errorf("Values of omitted empty fields should left the value example") 747 } 748} 749 750func TestValues_OmitNested(t *testing.T) { 751 type A struct { 752 Name string 753 Value int 754 } 755 756 a := A{ 757 Name: "example", 758 Value: 123, 759 } 760 761 type B struct { 762 A A `structs:",omitnested"` 763 C int 764 } 765 b := &B{A: a, C: 123} 766 767 s := Values(b) 768 769 if len(s) != 2 { 770 t.Errorf("Values of omitted nested struct should be not counted") 771 } 772 773 inSlice := func(val interface{}) bool { 774 for _, v := range s { 775 if reflect.DeepEqual(v, val) { 776 return true 777 } 778 } 779 return false 780 } 781 782 for _, val := range []interface{}{123, a} { 783 if !inSlice(val) { 784 t.Errorf("Values should have the value %v", val) 785 } 786 } 787} 788 789func TestValues_Nested(t *testing.T) { 790 type A struct { 791 Name string 792 } 793 a := A{Name: "example"} 794 795 type B struct { 796 A A 797 C int 798 } 799 b := &B{A: a, C: 123} 800 801 s := Values(b) 802 803 inSlice := func(val interface{}) bool { 804 for _, v := range s { 805 if reflect.DeepEqual(v, val) { 806 return true 807 } 808 } 809 return false 810 } 811 812 for _, val := range []interface{}{"example", 123} { 813 if !inSlice(val) { 814 t.Errorf("Values should have the value %v", val) 815 } 816 } 817} 818 819func TestValues_Anonymous(t *testing.T) { 820 type A struct { 821 Name string 822 } 823 a := A{Name: "example"} 824 825 type B struct { 826 A 827 C int 828 } 829 b := &B{C: 123} 830 b.A = a 831 832 s := Values(b) 833 834 inSlice := func(val interface{}) bool { 835 for _, v := range s { 836 if reflect.DeepEqual(v, val) { 837 return true 838 } 839 } 840 return false 841 } 842 843 for _, val := range []interface{}{"example", 123} { 844 if !inSlice(val) { 845 t.Errorf("Values should have the value %v", val) 846 } 847 } 848} 849 850func TestNames(t *testing.T) { 851 var T = struct { 852 A string 853 B int 854 C bool 855 }{ 856 A: "a-value", 857 B: 2, 858 C: true, 859 } 860 861 s := Names(T) 862 863 if len(s) != 3 { 864 t.Errorf("Names should return a slice of len 3, got: %d", len(s)) 865 } 866 867 inSlice := func(val string) bool { 868 for _, v := range s { 869 if reflect.DeepEqual(v, val) { 870 return true 871 } 872 } 873 return false 874 } 875 876 for _, val := range []string{"A", "B", "C"} { 877 if !inSlice(val) { 878 t.Errorf("Names should have the value %v", val) 879 } 880 } 881} 882 883func TestFields(t *testing.T) { 884 var T = struct { 885 A string 886 B int 887 C bool 888 }{ 889 A: "a-value", 890 B: 2, 891 C: true, 892 } 893 894 s := Fields(T) 895 896 if len(s) != 3 { 897 t.Errorf("Fields should return a slice of len 3, got: %d", len(s)) 898 } 899 900 inSlice := func(val string) bool { 901 for _, v := range s { 902 if reflect.DeepEqual(v.Name(), val) { 903 return true 904 } 905 } 906 return false 907 } 908 909 for _, val := range []string{"A", "B", "C"} { 910 if !inSlice(val) { 911 t.Errorf("Fields should have the value %v", val) 912 } 913 } 914} 915 916func TestFields_OmitNested(t *testing.T) { 917 type A struct { 918 Name string 919 Enabled bool 920 } 921 a := A{Name: "example"} 922 923 type B struct { 924 A A 925 C int 926 Value string `structs:"-"` 927 Number int 928 } 929 b := &B{A: a, C: 123} 930 931 s := Fields(b) 932 933 if len(s) != 3 { 934 t.Errorf("Fields should omit nested struct. Expecting 2 got: %d", len(s)) 935 } 936 937 inSlice := func(val interface{}) bool { 938 for _, v := range s { 939 if reflect.DeepEqual(v.Name(), val) { 940 return true 941 } 942 } 943 return false 944 } 945 946 for _, val := range []interface{}{"A", "C"} { 947 if !inSlice(val) { 948 t.Errorf("Fields should have the value %v", val) 949 } 950 } 951} 952 953func TestFields_Anonymous(t *testing.T) { 954 type A struct { 955 Name string 956 } 957 a := A{Name: "example"} 958 959 type B struct { 960 A 961 C int 962 } 963 b := &B{C: 123} 964 b.A = a 965 966 s := Fields(b) 967 968 inSlice := func(val interface{}) bool { 969 for _, v := range s { 970 if reflect.DeepEqual(v.Name(), val) { 971 return true 972 } 973 } 974 return false 975 } 976 977 for _, val := range []interface{}{"A", "C"} { 978 if !inSlice(val) { 979 t.Errorf("Fields should have the value %v", val) 980 } 981 } 982} 983 984func TestIsZero(t *testing.T) { 985 var T = struct { 986 A string 987 B int 988 C bool `structs:"-"` 989 D []string 990 }{} 991 992 ok := IsZero(T) 993 if !ok { 994 t.Error("IsZero should return true because none of the fields are initialized.") 995 } 996 997 var X = struct { 998 A string 999 F *bool 1000 }{ 1001 A: "a-value", 1002 } 1003 1004 ok = IsZero(X) 1005 if ok { 1006 t.Error("IsZero should return false because A is initialized") 1007 } 1008 1009 var Y = struct { 1010 A string 1011 B int 1012 }{ 1013 A: "a-value", 1014 B: 123, 1015 } 1016 1017 ok = IsZero(Y) 1018 if ok { 1019 t.Error("IsZero should return false because A and B is initialized") 1020 } 1021} 1022 1023func TestIsZero_OmitNested(t *testing.T) { 1024 type A struct { 1025 Name string 1026 D string 1027 } 1028 a := A{Name: "example"} 1029 1030 type B struct { 1031 A A `structs:",omitnested"` 1032 C int 1033 } 1034 b := &B{A: a, C: 123} 1035 1036 ok := IsZero(b) 1037 if ok { 1038 t.Error("IsZero should return false because A, B and C are initialized") 1039 } 1040 1041 aZero := A{} 1042 bZero := &B{A: aZero} 1043 1044 ok = IsZero(bZero) 1045 if !ok { 1046 t.Error("IsZero should return true because neither A nor B is initialized") 1047 } 1048 1049} 1050 1051func TestIsZero_Nested(t *testing.T) { 1052 type A struct { 1053 Name string 1054 D string 1055 } 1056 a := A{Name: "example"} 1057 1058 type B struct { 1059 A A 1060 C int 1061 } 1062 b := &B{A: a, C: 123} 1063 1064 ok := IsZero(b) 1065 if ok { 1066 t.Error("IsZero should return false because A, B and C are initialized") 1067 } 1068 1069 aZero := A{} 1070 bZero := &B{A: aZero} 1071 1072 ok = IsZero(bZero) 1073 if !ok { 1074 t.Error("IsZero should return true because neither A nor B is initialized") 1075 } 1076 1077} 1078 1079func TestIsZero_Anonymous(t *testing.T) { 1080 type A struct { 1081 Name string 1082 D string 1083 } 1084 a := A{Name: "example"} 1085 1086 type B struct { 1087 A 1088 C int 1089 } 1090 b := &B{C: 123} 1091 b.A = a 1092 1093 ok := IsZero(b) 1094 if ok { 1095 t.Error("IsZero should return false because A, B and C are initialized") 1096 } 1097 1098 aZero := A{} 1099 bZero := &B{} 1100 bZero.A = aZero 1101 1102 ok = IsZero(bZero) 1103 if !ok { 1104 t.Error("IsZero should return true because neither A nor B is initialized") 1105 } 1106} 1107 1108func TestHasZero(t *testing.T) { 1109 var T = struct { 1110 A string 1111 B int 1112 C bool `structs:"-"` 1113 D []string 1114 }{ 1115 A: "a-value", 1116 B: 2, 1117 } 1118 1119 ok := HasZero(T) 1120 if !ok { 1121 t.Error("HasZero should return true because A and B are initialized.") 1122 } 1123 1124 var X = struct { 1125 A string 1126 F *bool 1127 }{ 1128 A: "a-value", 1129 } 1130 1131 ok = HasZero(X) 1132 if !ok { 1133 t.Error("HasZero should return true because A is initialized") 1134 } 1135 1136 var Y = struct { 1137 A string 1138 B int 1139 }{ 1140 A: "a-value", 1141 B: 123, 1142 } 1143 1144 ok = HasZero(Y) 1145 if ok { 1146 t.Error("HasZero should return false because A and B is initialized") 1147 } 1148} 1149 1150func TestHasZero_OmitNested(t *testing.T) { 1151 type A struct { 1152 Name string 1153 D string 1154 } 1155 a := A{Name: "example"} 1156 1157 type B struct { 1158 A A `structs:",omitnested"` 1159 C int 1160 } 1161 b := &B{A: a, C: 123} 1162 1163 // Because the Field A inside B is omitted HasZero should return false 1164 // because it will stop iterating deeper andnot going to lookup for D 1165 ok := HasZero(b) 1166 if ok { 1167 t.Error("HasZero should return false because A and C are initialized") 1168 } 1169} 1170 1171func TestHasZero_Nested(t *testing.T) { 1172 type A struct { 1173 Name string 1174 D string 1175 } 1176 a := A{Name: "example"} 1177 1178 type B struct { 1179 A A 1180 C int 1181 } 1182 b := &B{A: a, C: 123} 1183 1184 ok := HasZero(b) 1185 if !ok { 1186 t.Error("HasZero should return true because D is not initialized") 1187 } 1188} 1189 1190func TestHasZero_Anonymous(t *testing.T) { 1191 type A struct { 1192 Name string 1193 D string 1194 } 1195 a := A{Name: "example"} 1196 1197 type B struct { 1198 A 1199 C int 1200 } 1201 b := &B{C: 123} 1202 b.A = a 1203 1204 ok := HasZero(b) 1205 if !ok { 1206 t.Error("HasZero should return false because D is not initialized") 1207 } 1208} 1209 1210func TestName(t *testing.T) { 1211 type Foo struct { 1212 A string 1213 B bool 1214 } 1215 f := &Foo{} 1216 1217 n := Name(f) 1218 if n != "Foo" { 1219 t.Errorf("Name should return Foo, got: %s", n) 1220 } 1221 1222 unnamed := struct{ Name string }{Name: "Cihangir"} 1223 m := Name(unnamed) 1224 if m != "" { 1225 t.Errorf("Name should return empty string for unnamed struct, got: %s", n) 1226 } 1227 1228 defer func() { 1229 err := recover() 1230 if err == nil { 1231 t.Error("Name should panic if a non struct is passed") 1232 } 1233 }() 1234 1235 Name([]string{}) 1236} 1237 1238func TestNestedNilPointer(t *testing.T) { 1239 type Collar struct { 1240 Engraving string 1241 } 1242 1243 type Dog struct { 1244 Name string 1245 Collar *Collar 1246 } 1247 1248 type Person struct { 1249 Name string 1250 Dog *Dog 1251 } 1252 1253 person := &Person{ 1254 Name: "John", 1255 } 1256 1257 personWithDog := &Person{ 1258 Name: "Ron", 1259 Dog: &Dog{ 1260 Name: "Rover", 1261 }, 1262 } 1263 1264 personWithDogWithCollar := &Person{ 1265 Name: "Kon", 1266 Dog: &Dog{ 1267 Name: "Ruffles", 1268 Collar: &Collar{ 1269 Engraving: "If lost, call Kon", 1270 }, 1271 }, 1272 } 1273 1274 defer func() { 1275 err := recover() 1276 if err != nil { 1277 fmt.Printf("err %+v\n", err) 1278 t.Error("Internal nil pointer should not panic") 1279 } 1280 }() 1281 1282 _ = Map(person) // Panics 1283 _ = Map(personWithDog) // Panics 1284 _ = Map(personWithDogWithCollar) // Doesn't panic 1285} 1286 1287func TestSetValueOnNestedField(t *testing.T) { 1288 type Base struct { 1289 ID int 1290 } 1291 1292 type User struct { 1293 Base 1294 Name string 1295 } 1296 1297 u := User{} 1298 s := New(&u) 1299 f := s.Field("Base").Field("ID") 1300 err := f.Set(10) 1301 if err != nil { 1302 t.Errorf("Error %v", err) 1303 } 1304 if f.Value().(int) != 10 { 1305 t.Errorf("Value should be equal to 10, got %v", f.Value()) 1306 } 1307} 1308 1309type Person struct { 1310 Name string 1311 Age int 1312} 1313 1314func (p *Person) String() string { 1315 return fmt.Sprintf("%s(%d)", p.Name, p.Age) 1316} 1317 1318func TestTagWithStringOption(t *testing.T) { 1319 1320 type Address struct { 1321 Country string `json:"country"` 1322 Person *Person `json:"person,string"` 1323 } 1324 1325 person := &Person{ 1326 Name: "John", 1327 Age: 23, 1328 } 1329 1330 address := &Address{ 1331 Country: "EU", 1332 Person: person, 1333 } 1334 1335 defer func() { 1336 err := recover() 1337 if err != nil { 1338 fmt.Printf("err %+v\n", err) 1339 t.Error("Internal nil pointer should not panic") 1340 } 1341 }() 1342 1343 s := New(address) 1344 1345 s.TagName = "json" 1346 m := s.Map() 1347 1348 if m["person"] != person.String() { 1349 t.Errorf("Value for field person should be %s, got: %s", person.String(), m["person"]) 1350 } 1351 1352 vs := s.Values() 1353 if vs[1] != person.String() { 1354 t.Errorf("Value for 2nd field (person) should be %T, got: %T", person.String(), vs[1]) 1355 } 1356} 1357 1358type Animal struct { 1359 Name string 1360 Age int 1361} 1362 1363type Dog struct { 1364 Animal *Animal `json:"animal,string"` 1365} 1366 1367func TestNonStringerTagWithStringOption(t *testing.T) { 1368 a := &Animal{ 1369 Name: "Fluff", 1370 Age: 4, 1371 } 1372 1373 d := &Dog{ 1374 Animal: a, 1375 } 1376 1377 defer func() { 1378 err := recover() 1379 if err != nil { 1380 fmt.Printf("err %+v\n", err) 1381 t.Error("Internal nil pointer should not panic") 1382 } 1383 }() 1384 1385 s := New(d) 1386 1387 s.TagName = "json" 1388 m := s.Map() 1389 1390 if _, exists := m["animal"]; exists { 1391 t.Errorf("Value for field Animal should not exist") 1392 } 1393} 1394 1395func TestMap_InterfaceValue(t *testing.T) { 1396 type TestStruct struct { 1397 A interface{} 1398 } 1399 1400 expected := []byte("test value") 1401 1402 a := TestStruct{A: expected} 1403 s := Map(a) 1404 if !reflect.DeepEqual(s["A"], expected) { 1405 t.Errorf("Value does not match expected: %q != %q", s["A"], expected) 1406 } 1407} 1408 1409func TestPointer2Pointer(t *testing.T) { 1410 defer func() { 1411 err := recover() 1412 if err != nil { 1413 fmt.Printf("err %+v\n", err) 1414 t.Error("Internal nil pointer should not panic") 1415 } 1416 }() 1417 a := &Animal{ 1418 Name: "Fluff", 1419 Age: 4, 1420 } 1421 _ = Map(&a) 1422 1423 b := &a 1424 _ = Map(&b) 1425 1426 c := &b 1427 _ = Map(&c) 1428} 1429 1430func TestMap_InterfaceTypeWithMapValue(t *testing.T) { 1431 type A struct { 1432 Name string `structs:"name"` 1433 IP string `structs:"ip"` 1434 Query string `structs:"query"` 1435 Payload interface{} `structs:"payload"` 1436 } 1437 1438 a := A{ 1439 Name: "test", 1440 IP: "127.0.0.1", 1441 Query: "", 1442 Payload: map[string]string{"test_param": "test_param"}, 1443 } 1444 1445 defer func() { 1446 err := recover() 1447 if err != nil { 1448 t.Error("Converting Map with an interface{} type with map value should not panic") 1449 } 1450 }() 1451 1452 _ = Map(a) 1453} 1454