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