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