1package mapstructure
2
3import (
4	"encoding/json"
5	"io"
6	"reflect"
7	"sort"
8	"strings"
9	"testing"
10)
11
12type Basic struct {
13	Vstring     string
14	Vint        int
15	Vuint       uint
16	Vbool       bool
17	Vfloat      float64
18	Vextra      string
19	vsilent     bool
20	Vdata       interface{}
21	VjsonInt    int
22	VjsonFloat  float64
23	VjsonNumber json.Number
24}
25
26type BasicSquash struct {
27	Test Basic `mapstructure:",squash"`
28}
29
30type Embedded struct {
31	Basic
32	Vunique string
33}
34
35type EmbeddedPointer struct {
36	*Basic
37	Vunique string
38}
39
40type EmbeddedSquash struct {
41	Basic   `mapstructure:",squash"`
42	Vunique string
43}
44
45type SliceAlias []string
46
47type EmbeddedSlice struct {
48	SliceAlias `mapstructure:"slice_alias"`
49	Vunique    string
50}
51
52type ArrayAlias [2]string
53
54type EmbeddedArray struct {
55	ArrayAlias `mapstructure:"array_alias"`
56	Vunique    string
57}
58
59type SquashOnNonStructType struct {
60	InvalidSquashType int `mapstructure:",squash"`
61}
62
63type Map struct {
64	Vfoo   string
65	Vother map[string]string
66}
67
68type MapOfStruct struct {
69	Value map[string]Basic
70}
71
72type Nested struct {
73	Vfoo string
74	Vbar Basic
75}
76
77type NestedPointer struct {
78	Vfoo string
79	Vbar *Basic
80}
81
82type NilInterface struct {
83	W io.Writer
84}
85
86type Slice struct {
87	Vfoo string
88	Vbar []string
89}
90
91type SliceOfStruct struct {
92	Value []Basic
93}
94
95type Array struct {
96	Vfoo string
97	Vbar [2]string
98}
99
100type ArrayOfStruct struct {
101	Value [2]Basic
102}
103
104type Func struct {
105	Foo func() string
106}
107
108type Tagged struct {
109	Extra string `mapstructure:"bar,what,what"`
110	Value string `mapstructure:"foo"`
111}
112
113type TypeConversionResult struct {
114	IntToFloat         float32
115	IntToUint          uint
116	IntToBool          bool
117	IntToString        string
118	UintToInt          int
119	UintToFloat        float32
120	UintToBool         bool
121	UintToString       string
122	BoolToInt          int
123	BoolToUint         uint
124	BoolToFloat        float32
125	BoolToString       string
126	FloatToInt         int
127	FloatToUint        uint
128	FloatToBool        bool
129	FloatToString      string
130	SliceUint8ToString string
131	StringToSliceUint8 []byte
132	ArrayUint8ToString string
133	StringToInt        int
134	StringToUint       uint
135	StringToBool       bool
136	StringToFloat      float32
137	StringToStrSlice   []string
138	StringToIntSlice   []int
139	StringToStrArray   [1]string
140	StringToIntArray   [1]int
141	SliceToMap         map[string]interface{}
142	MapToSlice         []interface{}
143	ArrayToMap         map[string]interface{}
144	MapToArray         [1]interface{}
145}
146
147func TestBasicTypes(t *testing.T) {
148	t.Parallel()
149
150	input := map[string]interface{}{
151		"vstring":     "foo",
152		"vint":        42,
153		"Vuint":       42,
154		"vbool":       true,
155		"Vfloat":      42.42,
156		"vsilent":     true,
157		"vdata":       42,
158		"vjsonInt":    json.Number("1234"),
159		"vjsonFloat":  json.Number("1234.5"),
160		"vjsonNumber": json.Number("1234.5"),
161	}
162
163	var result Basic
164	err := Decode(input, &result)
165	if err != nil {
166		t.Errorf("got an err: %s", err.Error())
167		t.FailNow()
168	}
169
170	if result.Vstring != "foo" {
171		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
172	}
173
174	if result.Vint != 42 {
175		t.Errorf("vint value should be 42: %#v", result.Vint)
176	}
177
178	if result.Vuint != 42 {
179		t.Errorf("vuint value should be 42: %#v", result.Vuint)
180	}
181
182	if result.Vbool != true {
183		t.Errorf("vbool value should be true: %#v", result.Vbool)
184	}
185
186	if result.Vfloat != 42.42 {
187		t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat)
188	}
189
190	if result.Vextra != "" {
191		t.Errorf("vextra value should be empty: %#v", result.Vextra)
192	}
193
194	if result.vsilent != false {
195		t.Error("vsilent should not be set, it is unexported")
196	}
197
198	if result.Vdata != 42 {
199		t.Error("vdata should be valid")
200	}
201
202	if result.VjsonInt != 1234 {
203		t.Errorf("vjsonint value should be 1234: %#v", result.VjsonInt)
204	}
205
206	if result.VjsonFloat != 1234.5 {
207		t.Errorf("vjsonfloat value should be 1234.5: %#v", result.VjsonFloat)
208	}
209
210	if !reflect.DeepEqual(result.VjsonNumber, json.Number("1234.5")) {
211		t.Errorf("vjsonnumber value should be '1234.5': %T, %#v", result.VjsonNumber, result.VjsonNumber)
212	}
213}
214
215func TestBasic_IntWithFloat(t *testing.T) {
216	t.Parallel()
217
218	input := map[string]interface{}{
219		"vint": float64(42),
220	}
221
222	var result Basic
223	err := Decode(input, &result)
224	if err != nil {
225		t.Fatalf("got an err: %s", err)
226	}
227}
228
229func TestBasic_Merge(t *testing.T) {
230	t.Parallel()
231
232	input := map[string]interface{}{
233		"vint": 42,
234	}
235
236	var result Basic
237	result.Vuint = 100
238	err := Decode(input, &result)
239	if err != nil {
240		t.Fatalf("got an err: %s", err)
241	}
242
243	expected := Basic{
244		Vint:  42,
245		Vuint: 100,
246	}
247	if !reflect.DeepEqual(result, expected) {
248		t.Fatalf("bad: %#v", result)
249	}
250}
251
252// Test for issue #46.
253func TestBasic_Struct(t *testing.T) {
254	t.Parallel()
255
256	input := map[string]interface{}{
257		"vdata": map[string]interface{}{
258			"vstring": "foo",
259		},
260	}
261
262	var result, inner Basic
263	result.Vdata = &inner
264	err := Decode(input, &result)
265	if err != nil {
266		t.Fatalf("got an err: %s", err)
267	}
268	expected := Basic{
269		Vdata: &Basic{
270			Vstring: "foo",
271		},
272	}
273	if !reflect.DeepEqual(result, expected) {
274		t.Fatalf("bad: %#v", result)
275	}
276}
277
278func TestDecode_BasicSquash(t *testing.T) {
279	t.Parallel()
280
281	input := map[string]interface{}{
282		"vstring": "foo",
283	}
284
285	var result BasicSquash
286	err := Decode(input, &result)
287	if err != nil {
288		t.Fatalf("got an err: %s", err.Error())
289	}
290
291	if result.Test.Vstring != "foo" {
292		t.Errorf("vstring value should be 'foo': %#v", result.Test.Vstring)
293	}
294}
295
296func TestDecode_Embedded(t *testing.T) {
297	t.Parallel()
298
299	input := map[string]interface{}{
300		"vstring": "foo",
301		"Basic": map[string]interface{}{
302			"vstring": "innerfoo",
303		},
304		"vunique": "bar",
305	}
306
307	var result Embedded
308	err := Decode(input, &result)
309	if err != nil {
310		t.Fatalf("got an err: %s", err.Error())
311	}
312
313	if result.Vstring != "innerfoo" {
314		t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring)
315	}
316
317	if result.Vunique != "bar" {
318		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
319	}
320}
321
322func TestDecode_EmbeddedPointer(t *testing.T) {
323	t.Parallel()
324
325	input := map[string]interface{}{
326		"vstring": "foo",
327		"Basic": map[string]interface{}{
328			"vstring": "innerfoo",
329		},
330		"vunique": "bar",
331	}
332
333	var result EmbeddedPointer
334	err := Decode(input, &result)
335	if err != nil {
336		t.Fatalf("err: %s", err)
337	}
338
339	expected := EmbeddedPointer{
340		Basic: &Basic{
341			Vstring: "innerfoo",
342		},
343		Vunique: "bar",
344	}
345	if !reflect.DeepEqual(result, expected) {
346		t.Fatalf("bad: %#v", result)
347	}
348}
349
350func TestDecode_EmbeddedSlice(t *testing.T) {
351	t.Parallel()
352
353	input := map[string]interface{}{
354		"slice_alias": []string{"foo", "bar"},
355		"vunique":     "bar",
356	}
357
358	var result EmbeddedSlice
359	err := Decode(input, &result)
360	if err != nil {
361		t.Fatalf("got an err: %s", err.Error())
362	}
363
364	if !reflect.DeepEqual(result.SliceAlias, SliceAlias([]string{"foo", "bar"})) {
365		t.Errorf("slice value: %#v", result.SliceAlias)
366	}
367
368	if result.Vunique != "bar" {
369		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
370	}
371}
372
373func TestDecode_EmbeddedArray(t *testing.T) {
374	t.Parallel()
375
376	input := map[string]interface{}{
377		"array_alias": [2]string{"foo", "bar"},
378		"vunique":     "bar",
379	}
380
381	var result EmbeddedArray
382	err := Decode(input, &result)
383	if err != nil {
384		t.Fatalf("got an err: %s", err.Error())
385	}
386
387	if !reflect.DeepEqual(result.ArrayAlias, ArrayAlias([2]string{"foo", "bar"})) {
388		t.Errorf("array value: %#v", result.ArrayAlias)
389	}
390
391	if result.Vunique != "bar" {
392		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
393	}
394}
395
396func TestDecode_EmbeddedSquash(t *testing.T) {
397	t.Parallel()
398
399	input := map[string]interface{}{
400		"vstring": "foo",
401		"vunique": "bar",
402	}
403
404	var result EmbeddedSquash
405	err := Decode(input, &result)
406	if err != nil {
407		t.Fatalf("got an err: %s", err.Error())
408	}
409
410	if result.Vstring != "foo" {
411		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
412	}
413
414	if result.Vunique != "bar" {
415		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
416	}
417}
418
419func TestDecode_SquashOnNonStructType(t *testing.T) {
420	t.Parallel()
421
422	input := map[string]interface{}{
423		"InvalidSquashType": 42,
424	}
425
426	var result SquashOnNonStructType
427	err := Decode(input, &result)
428	if err == nil {
429		t.Fatal("unexpected success decoding invalid squash field type")
430	} else if !strings.Contains(err.Error(), "unsupported type for squash") {
431		t.Fatalf("unexpected error message for invalid squash field type: %s", err)
432	}
433}
434
435func TestDecode_DecodeHook(t *testing.T) {
436	t.Parallel()
437
438	input := map[string]interface{}{
439		"vint": "WHAT",
440	}
441
442	decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) {
443		if from == reflect.String && to != reflect.String {
444			return 5, nil
445		}
446
447		return v, nil
448	}
449
450	var result Basic
451	config := &DecoderConfig{
452		DecodeHook: decodeHook,
453		Result:     &result,
454	}
455
456	decoder, err := NewDecoder(config)
457	if err != nil {
458		t.Fatalf("err: %s", err)
459	}
460
461	err = decoder.Decode(input)
462	if err != nil {
463		t.Fatalf("got an err: %s", err)
464	}
465
466	if result.Vint != 5 {
467		t.Errorf("vint should be 5: %#v", result.Vint)
468	}
469}
470
471func TestDecode_DecodeHookType(t *testing.T) {
472	t.Parallel()
473
474	input := map[string]interface{}{
475		"vint": "WHAT",
476	}
477
478	decodeHook := func(from reflect.Type, to reflect.Type, v interface{}) (interface{}, error) {
479		if from.Kind() == reflect.String &&
480			to.Kind() != reflect.String {
481			return 5, nil
482		}
483
484		return v, nil
485	}
486
487	var result Basic
488	config := &DecoderConfig{
489		DecodeHook: decodeHook,
490		Result:     &result,
491	}
492
493	decoder, err := NewDecoder(config)
494	if err != nil {
495		t.Fatalf("err: %s", err)
496	}
497
498	err = decoder.Decode(input)
499	if err != nil {
500		t.Fatalf("got an err: %s", err)
501	}
502
503	if result.Vint != 5 {
504		t.Errorf("vint should be 5: %#v", result.Vint)
505	}
506}
507
508func TestDecode_Nil(t *testing.T) {
509	t.Parallel()
510
511	var input interface{}
512	result := Basic{
513		Vstring: "foo",
514	}
515
516	err := Decode(input, &result)
517	if err != nil {
518		t.Fatalf("err: %s", err)
519	}
520
521	if result.Vstring != "foo" {
522		t.Fatalf("bad: %#v", result.Vstring)
523	}
524}
525
526func TestDecode_NilInterfaceHook(t *testing.T) {
527	t.Parallel()
528
529	input := map[string]interface{}{
530		"w": "",
531	}
532
533	decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
534		if t.String() == "io.Writer" {
535			return nil, nil
536		}
537
538		return v, nil
539	}
540
541	var result NilInterface
542	config := &DecoderConfig{
543		DecodeHook: decodeHook,
544		Result:     &result,
545	}
546
547	decoder, err := NewDecoder(config)
548	if err != nil {
549		t.Fatalf("err: %s", err)
550	}
551
552	err = decoder.Decode(input)
553	if err != nil {
554		t.Fatalf("got an err: %s", err)
555	}
556
557	if result.W != nil {
558		t.Errorf("W should be nil: %#v", result.W)
559	}
560}
561
562func TestDecode_FuncHook(t *testing.T) {
563	t.Parallel()
564
565	input := map[string]interface{}{
566		"foo": "baz",
567	}
568
569	decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
570		if t.Kind() != reflect.Func {
571			return v, nil
572		}
573		val := v.(string)
574		return func() string { return val }, nil
575	}
576
577	var result Func
578	config := &DecoderConfig{
579		DecodeHook: decodeHook,
580		Result:     &result,
581	}
582
583	decoder, err := NewDecoder(config)
584	if err != nil {
585		t.Fatalf("err: %s", err)
586	}
587
588	err = decoder.Decode(input)
589	if err != nil {
590		t.Fatalf("got an err: %s", err)
591	}
592
593	if result.Foo() != "baz" {
594		t.Errorf("Foo call result should be 'baz': %s", result.Foo())
595	}
596}
597
598func TestDecode_NonStruct(t *testing.T) {
599	t.Parallel()
600
601	input := map[string]interface{}{
602		"foo": "bar",
603		"bar": "baz",
604	}
605
606	var result map[string]string
607	err := Decode(input, &result)
608	if err != nil {
609		t.Fatalf("err: %s", err)
610	}
611
612	if result["foo"] != "bar" {
613		t.Fatal("foo is not bar")
614	}
615}
616
617func TestDecode_StructMatch(t *testing.T) {
618	t.Parallel()
619
620	input := map[string]interface{}{
621		"vbar": Basic{
622			Vstring: "foo",
623		},
624	}
625
626	var result Nested
627	err := Decode(input, &result)
628	if err != nil {
629		t.Fatalf("got an err: %s", err.Error())
630	}
631
632	if result.Vbar.Vstring != "foo" {
633		t.Errorf("bad: %#v", result)
634	}
635}
636
637func TestDecode_TypeConversion(t *testing.T) {
638	input := map[string]interface{}{
639		"IntToFloat":         42,
640		"IntToUint":          42,
641		"IntToBool":          1,
642		"IntToString":        42,
643		"UintToInt":          42,
644		"UintToFloat":        42,
645		"UintToBool":         42,
646		"UintToString":       42,
647		"BoolToInt":          true,
648		"BoolToUint":         true,
649		"BoolToFloat":        true,
650		"BoolToString":       true,
651		"FloatToInt":         42.42,
652		"FloatToUint":        42.42,
653		"FloatToBool":        42.42,
654		"FloatToString":      42.42,
655		"SliceUint8ToString": []uint8("foo"),
656		"StringToSliceUint8": "foo",
657		"ArrayUint8ToString": [3]uint8{'f', 'o', 'o'},
658		"StringToInt":        "42",
659		"StringToUint":       "42",
660		"StringToBool":       "1",
661		"StringToFloat":      "42.42",
662		"StringToStrSlice":   "A",
663		"StringToIntSlice":   "42",
664		"StringToStrArray":   "A",
665		"StringToIntArray":   "42",
666		"SliceToMap":         []interface{}{},
667		"MapToSlice":         map[string]interface{}{},
668		"ArrayToMap":         []interface{}{},
669		"MapToArray":         map[string]interface{}{},
670	}
671
672	expectedResultStrict := TypeConversionResult{
673		IntToFloat:  42.0,
674		IntToUint:   42,
675		UintToInt:   42,
676		UintToFloat: 42,
677		BoolToInt:   0,
678		BoolToUint:  0,
679		BoolToFloat: 0,
680		FloatToInt:  42,
681		FloatToUint: 42,
682	}
683
684	expectedResultWeak := TypeConversionResult{
685		IntToFloat:         42.0,
686		IntToUint:          42,
687		IntToBool:          true,
688		IntToString:        "42",
689		UintToInt:          42,
690		UintToFloat:        42,
691		UintToBool:         true,
692		UintToString:       "42",
693		BoolToInt:          1,
694		BoolToUint:         1,
695		BoolToFloat:        1,
696		BoolToString:       "1",
697		FloatToInt:         42,
698		FloatToUint:        42,
699		FloatToBool:        true,
700		FloatToString:      "42.42",
701		SliceUint8ToString: "foo",
702		StringToSliceUint8: []byte("foo"),
703		ArrayUint8ToString: "foo",
704		StringToInt:        42,
705		StringToUint:       42,
706		StringToBool:       true,
707		StringToFloat:      42.42,
708		StringToStrSlice:   []string{"A"},
709		StringToIntSlice:   []int{42},
710		StringToStrArray:   [1]string{"A"},
711		StringToIntArray:   [1]int{42},
712		SliceToMap:         map[string]interface{}{},
713		MapToSlice:         []interface{}{},
714		ArrayToMap:         map[string]interface{}{},
715		MapToArray:         [1]interface{}{},
716	}
717
718	// Test strict type conversion
719	var resultStrict TypeConversionResult
720	err := Decode(input, &resultStrict)
721	if err == nil {
722		t.Errorf("should return an error")
723	}
724	if !reflect.DeepEqual(resultStrict, expectedResultStrict) {
725		t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict)
726	}
727
728	// Test weak type conversion
729	var decoder *Decoder
730	var resultWeak TypeConversionResult
731
732	config := &DecoderConfig{
733		WeaklyTypedInput: true,
734		Result:           &resultWeak,
735	}
736
737	decoder, err = NewDecoder(config)
738	if err != nil {
739		t.Fatalf("err: %s", err)
740	}
741
742	err = decoder.Decode(input)
743	if err != nil {
744		t.Fatalf("got an err: %s", err)
745	}
746
747	if !reflect.DeepEqual(resultWeak, expectedResultWeak) {
748		t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak)
749	}
750}
751
752func TestDecoder_ErrorUnused(t *testing.T) {
753	t.Parallel()
754
755	input := map[string]interface{}{
756		"vstring": "hello",
757		"foo":     "bar",
758	}
759
760	var result Basic
761	config := &DecoderConfig{
762		ErrorUnused: true,
763		Result:      &result,
764	}
765
766	decoder, err := NewDecoder(config)
767	if err != nil {
768		t.Fatalf("err: %s", err)
769	}
770
771	err = decoder.Decode(input)
772	if err == nil {
773		t.Fatal("expected error")
774	}
775}
776
777func TestMap(t *testing.T) {
778	t.Parallel()
779
780	input := map[string]interface{}{
781		"vfoo": "foo",
782		"vother": map[interface{}]interface{}{
783			"foo": "foo",
784			"bar": "bar",
785		},
786	}
787
788	var result Map
789	err := Decode(input, &result)
790	if err != nil {
791		t.Fatalf("got an error: %s", err)
792	}
793
794	if result.Vfoo != "foo" {
795		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
796	}
797
798	if result.Vother == nil {
799		t.Fatal("vother should not be nil")
800	}
801
802	if len(result.Vother) != 2 {
803		t.Error("vother should have two items")
804	}
805
806	if result.Vother["foo"] != "foo" {
807		t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"])
808	}
809
810	if result.Vother["bar"] != "bar" {
811		t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"])
812	}
813}
814
815func TestMapMerge(t *testing.T) {
816	t.Parallel()
817
818	input := map[string]interface{}{
819		"vfoo": "foo",
820		"vother": map[interface{}]interface{}{
821			"foo": "foo",
822			"bar": "bar",
823		},
824	}
825
826	var result Map
827	result.Vother = map[string]string{"hello": "world"}
828	err := Decode(input, &result)
829	if err != nil {
830		t.Fatalf("got an error: %s", err)
831	}
832
833	if result.Vfoo != "foo" {
834		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
835	}
836
837	expected := map[string]string{
838		"foo":   "foo",
839		"bar":   "bar",
840		"hello": "world",
841	}
842	if !reflect.DeepEqual(result.Vother, expected) {
843		t.Errorf("bad: %#v", result.Vother)
844	}
845}
846
847func TestMapOfStruct(t *testing.T) {
848	t.Parallel()
849
850	input := map[string]interface{}{
851		"value": map[string]interface{}{
852			"foo": map[string]string{"vstring": "one"},
853			"bar": map[string]string{"vstring": "two"},
854		},
855	}
856
857	var result MapOfStruct
858	err := Decode(input, &result)
859	if err != nil {
860		t.Fatalf("got an err: %s", err)
861	}
862
863	if result.Value == nil {
864		t.Fatal("value should not be nil")
865	}
866
867	if len(result.Value) != 2 {
868		t.Error("value should have two items")
869	}
870
871	if result.Value["foo"].Vstring != "one" {
872		t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring)
873	}
874
875	if result.Value["bar"].Vstring != "two" {
876		t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring)
877	}
878}
879
880func TestNestedType(t *testing.T) {
881	t.Parallel()
882
883	input := map[string]interface{}{
884		"vfoo": "foo",
885		"vbar": map[string]interface{}{
886			"vstring": "foo",
887			"vint":    42,
888			"vbool":   true,
889		},
890	}
891
892	var result Nested
893	err := Decode(input, &result)
894	if err != nil {
895		t.Fatalf("got an err: %s", err.Error())
896	}
897
898	if result.Vfoo != "foo" {
899		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
900	}
901
902	if result.Vbar.Vstring != "foo" {
903		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
904	}
905
906	if result.Vbar.Vint != 42 {
907		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
908	}
909
910	if result.Vbar.Vbool != true {
911		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
912	}
913
914	if result.Vbar.Vextra != "" {
915		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
916	}
917}
918
919func TestNestedTypePointer(t *testing.T) {
920	t.Parallel()
921
922	input := map[string]interface{}{
923		"vfoo": "foo",
924		"vbar": &map[string]interface{}{
925			"vstring": "foo",
926			"vint":    42,
927			"vbool":   true,
928		},
929	}
930
931	var result NestedPointer
932	err := Decode(input, &result)
933	if err != nil {
934		t.Fatalf("got an err: %s", err.Error())
935	}
936
937	if result.Vfoo != "foo" {
938		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
939	}
940
941	if result.Vbar.Vstring != "foo" {
942		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
943	}
944
945	if result.Vbar.Vint != 42 {
946		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
947	}
948
949	if result.Vbar.Vbool != true {
950		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
951	}
952
953	if result.Vbar.Vextra != "" {
954		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
955	}
956}
957
958// Test for issue #46.
959func TestNestedTypeInterface(t *testing.T) {
960	t.Parallel()
961
962	input := map[string]interface{}{
963		"vfoo": "foo",
964		"vbar": &map[string]interface{}{
965			"vstring": "foo",
966			"vint":    42,
967			"vbool":   true,
968
969			"vdata": map[string]interface{}{
970				"vstring": "bar",
971			},
972		},
973	}
974
975	var result NestedPointer
976	result.Vbar = new(Basic)
977	result.Vbar.Vdata = new(Basic)
978	err := Decode(input, &result)
979	if err != nil {
980		t.Fatalf("got an err: %s", err.Error())
981	}
982
983	if result.Vfoo != "foo" {
984		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
985	}
986
987	if result.Vbar.Vstring != "foo" {
988		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
989	}
990
991	if result.Vbar.Vint != 42 {
992		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
993	}
994
995	if result.Vbar.Vbool != true {
996		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
997	}
998
999	if result.Vbar.Vextra != "" {
1000		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
1001	}
1002
1003	if result.Vbar.Vdata.(*Basic).Vstring != "bar" {
1004		t.Errorf("vstring value should be 'bar': %#v", result.Vbar.Vdata.(*Basic).Vstring)
1005	}
1006}
1007
1008func TestSlice(t *testing.T) {
1009	t.Parallel()
1010
1011	inputStringSlice := map[string]interface{}{
1012		"vfoo": "foo",
1013		"vbar": []string{"foo", "bar", "baz"},
1014	}
1015
1016	inputStringSlicePointer := map[string]interface{}{
1017		"vfoo": "foo",
1018		"vbar": &[]string{"foo", "bar", "baz"},
1019	}
1020
1021	outputStringSlice := &Slice{
1022		"foo",
1023		[]string{"foo", "bar", "baz"},
1024	}
1025
1026	testSliceInput(t, inputStringSlice, outputStringSlice)
1027	testSliceInput(t, inputStringSlicePointer, outputStringSlice)
1028}
1029
1030func TestInvalidSlice(t *testing.T) {
1031	t.Parallel()
1032
1033	input := map[string]interface{}{
1034		"vfoo": "foo",
1035		"vbar": 42,
1036	}
1037
1038	result := Slice{}
1039	err := Decode(input, &result)
1040	if err == nil {
1041		t.Errorf("expected failure")
1042	}
1043}
1044
1045func TestSliceOfStruct(t *testing.T) {
1046	t.Parallel()
1047
1048	input := map[string]interface{}{
1049		"value": []map[string]interface{}{
1050			{"vstring": "one"},
1051			{"vstring": "two"},
1052		},
1053	}
1054
1055	var result SliceOfStruct
1056	err := Decode(input, &result)
1057	if err != nil {
1058		t.Fatalf("got unexpected error: %s", err)
1059	}
1060
1061	if len(result.Value) != 2 {
1062		t.Fatalf("expected two values, got %d", len(result.Value))
1063	}
1064
1065	if result.Value[0].Vstring != "one" {
1066		t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
1067	}
1068
1069	if result.Value[1].Vstring != "two" {
1070		t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
1071	}
1072}
1073
1074func TestSliceToMap(t *testing.T) {
1075	t.Parallel()
1076
1077	input := []map[string]interface{}{
1078		{
1079			"foo": "bar",
1080		},
1081		{
1082			"bar": "baz",
1083		},
1084	}
1085
1086	var result map[string]interface{}
1087	err := WeakDecode(input, &result)
1088	if err != nil {
1089		t.Fatalf("got an error: %s", err)
1090	}
1091
1092	expected := map[string]interface{}{
1093		"foo": "bar",
1094		"bar": "baz",
1095	}
1096	if !reflect.DeepEqual(result, expected) {
1097		t.Errorf("bad: %#v", result)
1098	}
1099}
1100
1101func TestArray(t *testing.T) {
1102	t.Parallel()
1103
1104	inputStringArray := map[string]interface{}{
1105		"vfoo": "foo",
1106		"vbar": [2]string{"foo", "bar"},
1107	}
1108
1109	inputStringArrayPointer := map[string]interface{}{
1110		"vfoo": "foo",
1111		"vbar": &[2]string{"foo", "bar"},
1112	}
1113
1114	outputStringArray := &Array{
1115		"foo",
1116		[2]string{"foo", "bar"},
1117	}
1118
1119	testArrayInput(t, inputStringArray, outputStringArray)
1120	testArrayInput(t, inputStringArrayPointer, outputStringArray)
1121}
1122
1123func TestInvalidArray(t *testing.T) {
1124	t.Parallel()
1125
1126	input := map[string]interface{}{
1127		"vfoo": "foo",
1128		"vbar": 42,
1129	}
1130
1131	result := Array{}
1132	err := Decode(input, &result)
1133	if err == nil {
1134		t.Errorf("expected failure")
1135	}
1136}
1137
1138func TestArrayOfStruct(t *testing.T) {
1139	t.Parallel()
1140
1141	input := map[string]interface{}{
1142		"value": []map[string]interface{}{
1143			{"vstring": "one"},
1144			{"vstring": "two"},
1145		},
1146	}
1147
1148	var result ArrayOfStruct
1149	err := Decode(input, &result)
1150	if err != nil {
1151		t.Fatalf("got unexpected error: %s", err)
1152	}
1153
1154	if len(result.Value) != 2 {
1155		t.Fatalf("expected two values, got %d", len(result.Value))
1156	}
1157
1158	if result.Value[0].Vstring != "one" {
1159		t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
1160	}
1161
1162	if result.Value[1].Vstring != "two" {
1163		t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
1164	}
1165}
1166
1167func TestArrayToMap(t *testing.T) {
1168	t.Parallel()
1169
1170	input := []map[string]interface{}{
1171		{
1172			"foo": "bar",
1173		},
1174		{
1175			"bar": "baz",
1176		},
1177	}
1178
1179	var result map[string]interface{}
1180	err := WeakDecode(input, &result)
1181	if err != nil {
1182		t.Fatalf("got an error: %s", err)
1183	}
1184
1185	expected := map[string]interface{}{
1186		"foo": "bar",
1187		"bar": "baz",
1188	}
1189	if !reflect.DeepEqual(result, expected) {
1190		t.Errorf("bad: %#v", result)
1191	}
1192}
1193
1194func TestMapOutputForStructuredInputs(t *testing.T) {
1195	t.Parallel()
1196
1197	tests := []struct {
1198		name    string
1199		in      interface{}
1200		target  interface{}
1201		out     interface{}
1202		wantErr bool
1203	}{
1204		{
1205			"basic struct input",
1206			&Basic{
1207				Vstring: "vstring",
1208				Vint:    2,
1209				Vuint:   3,
1210				Vbool:   true,
1211				Vfloat:  4.56,
1212				Vextra:  "vextra",
1213				vsilent: true,
1214				Vdata:   []byte("data"),
1215			},
1216			&map[string]interface{}{},
1217			&map[string]interface{}{
1218				"Vstring":     "vstring",
1219				"Vint":        2,
1220				"Vuint":       uint(3),
1221				"Vbool":       true,
1222				"Vfloat":      4.56,
1223				"Vextra":      "vextra",
1224				"Vdata":       []byte("data"),
1225				"VjsonInt":    0,
1226				"VjsonFloat":  0.0,
1227				"VjsonNumber": json.Number(""),
1228			},
1229			false,
1230		},
1231		{
1232			"embedded struct input",
1233			&Embedded{
1234				Vunique: "vunique",
1235				Basic: Basic{
1236					Vstring: "vstring",
1237					Vint:    2,
1238					Vuint:   3,
1239					Vbool:   true,
1240					Vfloat:  4.56,
1241					Vextra:  "vextra",
1242					vsilent: true,
1243					Vdata:   []byte("data"),
1244				},
1245			},
1246			&map[string]interface{}{},
1247			&map[string]interface{}{
1248				"Vunique": "vunique",
1249				"Basic": map[string]interface{}{
1250					"Vstring":     "vstring",
1251					"Vint":        2,
1252					"Vuint":       uint(3),
1253					"Vbool":       true,
1254					"Vfloat":      4.56,
1255					"Vextra":      "vextra",
1256					"Vdata":       []byte("data"),
1257					"VjsonInt":    0,
1258					"VjsonFloat":  0.0,
1259					"VjsonNumber": json.Number(""),
1260				},
1261			},
1262			false,
1263		},
1264		{
1265			"slice input - should error",
1266			[]string{"foo", "bar"},
1267			&map[string]interface{}{},
1268			&map[string]interface{}{},
1269			true,
1270		},
1271		{
1272			"struct with slice property",
1273			&Slice{
1274				Vfoo: "vfoo",
1275				Vbar: []string{"foo", "bar"},
1276			},
1277			&map[string]interface{}{},
1278			&map[string]interface{}{
1279				"Vfoo": "vfoo",
1280				"Vbar": []string{"foo", "bar"},
1281			},
1282			false,
1283		},
1284		{
1285			"struct with slice of struct property",
1286			&SliceOfStruct{
1287				Value: []Basic{
1288					Basic{
1289						Vstring: "vstring",
1290						Vint:    2,
1291						Vuint:   3,
1292						Vbool:   true,
1293						Vfloat:  4.56,
1294						Vextra:  "vextra",
1295						vsilent: true,
1296						Vdata:   []byte("data"),
1297					},
1298				},
1299			},
1300			&map[string]interface{}{},
1301			&map[string]interface{}{
1302				"Value": []Basic{
1303					Basic{
1304						Vstring: "vstring",
1305						Vint:    2,
1306						Vuint:   3,
1307						Vbool:   true,
1308						Vfloat:  4.56,
1309						Vextra:  "vextra",
1310						vsilent: true,
1311						Vdata:   []byte("data"),
1312					},
1313				},
1314			},
1315			false,
1316		},
1317		{
1318			"struct with map property",
1319			&Map{
1320				Vfoo:   "vfoo",
1321				Vother: map[string]string{"vother": "vother"},
1322			},
1323			&map[string]interface{}{},
1324			&map[string]interface{}{
1325				"Vfoo": "vfoo",
1326				"Vother": map[string]string{
1327					"vother": "vother",
1328				}},
1329			false,
1330		},
1331		{
1332			"tagged struct",
1333			&Tagged{
1334				Extra: "extra",
1335				Value: "value",
1336			},
1337			&map[string]string{},
1338			&map[string]string{
1339				"bar": "extra",
1340				"foo": "value",
1341			},
1342			false,
1343		},
1344		{
1345			"omit tag struct",
1346			&struct {
1347				Value string `mapstructure:"value"`
1348				Omit  string `mapstructure:"-"`
1349			}{
1350				Value: "value",
1351				Omit:  "omit",
1352			},
1353			&map[string]string{},
1354			&map[string]string{
1355				"value": "value",
1356			},
1357			false,
1358		},
1359		{
1360			"decode to wrong map type",
1361			&struct {
1362				Value string
1363			}{
1364				Value: "string",
1365			},
1366			&map[string]int{},
1367			&map[string]int{},
1368			true,
1369		},
1370	}
1371
1372	for _, tt := range tests {
1373		t.Run(tt.name, func(t *testing.T) {
1374			if err := Decode(tt.in, tt.target); (err != nil) != tt.wantErr {
1375				t.Fatalf("%q: TestMapOutputForStructuredInputs() unexpected error: %s", tt.name, err)
1376			}
1377
1378			if !reflect.DeepEqual(tt.out, tt.target) {
1379				t.Fatalf("%q: TestMapOutputForStructuredInputs() expected: %#v, got: %#v", tt.name, tt.out, tt.target)
1380			}
1381		})
1382	}
1383}
1384
1385func TestInvalidType(t *testing.T) {
1386	t.Parallel()
1387
1388	input := map[string]interface{}{
1389		"vstring": 42,
1390	}
1391
1392	var result Basic
1393	err := Decode(input, &result)
1394	if err == nil {
1395		t.Fatal("error should exist")
1396	}
1397
1398	derr, ok := err.(*Error)
1399	if !ok {
1400		t.Fatalf("error should be kind of Error, instead: %#v", err)
1401	}
1402
1403	if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
1404		t.Errorf("got unexpected error: %s", err)
1405	}
1406
1407	inputNegIntUint := map[string]interface{}{
1408		"vuint": -42,
1409	}
1410
1411	err = Decode(inputNegIntUint, &result)
1412	if err == nil {
1413		t.Fatal("error should exist")
1414	}
1415
1416	derr, ok = err.(*Error)
1417	if !ok {
1418		t.Fatalf("error should be kind of Error, instead: %#v", err)
1419	}
1420
1421	if derr.Errors[0] != "cannot parse 'Vuint', -42 overflows uint" {
1422		t.Errorf("got unexpected error: %s", err)
1423	}
1424
1425	inputNegFloatUint := map[string]interface{}{
1426		"vuint": -42.0,
1427	}
1428
1429	err = Decode(inputNegFloatUint, &result)
1430	if err == nil {
1431		t.Fatal("error should exist")
1432	}
1433
1434	derr, ok = err.(*Error)
1435	if !ok {
1436		t.Fatalf("error should be kind of Error, instead: %#v", err)
1437	}
1438
1439	if derr.Errors[0] != "cannot parse 'Vuint', -42.000000 overflows uint" {
1440		t.Errorf("got unexpected error: %s", err)
1441	}
1442}
1443
1444func TestDecodeMetadata(t *testing.T) {
1445	t.Parallel()
1446
1447	input := map[string]interface{}{
1448		"vfoo": "foo",
1449		"vbar": map[string]interface{}{
1450			"vstring": "foo",
1451			"Vuint":   42,
1452			"foo":     "bar",
1453		},
1454		"bar": "nil",
1455	}
1456
1457	var md Metadata
1458	var result Nested
1459
1460	err := DecodeMetadata(input, &result, &md)
1461	if err != nil {
1462		t.Fatalf("err: %s", err.Error())
1463	}
1464
1465	expectedKeys := []string{"Vbar", "Vbar.Vstring", "Vbar.Vuint", "Vfoo"}
1466	sort.Strings(md.Keys)
1467	if !reflect.DeepEqual(md.Keys, expectedKeys) {
1468		t.Fatalf("bad keys: %#v", md.Keys)
1469	}
1470
1471	expectedUnused := []string{"Vbar.foo", "bar"}
1472	if !reflect.DeepEqual(md.Unused, expectedUnused) {
1473		t.Fatalf("bad unused: %#v", md.Unused)
1474	}
1475}
1476
1477func TestMetadata(t *testing.T) {
1478	t.Parallel()
1479
1480	input := map[string]interface{}{
1481		"vfoo": "foo",
1482		"vbar": map[string]interface{}{
1483			"vstring": "foo",
1484			"Vuint":   42,
1485			"foo":     "bar",
1486		},
1487		"bar": "nil",
1488	}
1489
1490	var md Metadata
1491	var result Nested
1492	config := &DecoderConfig{
1493		Metadata: &md,
1494		Result:   &result,
1495	}
1496
1497	decoder, err := NewDecoder(config)
1498	if err != nil {
1499		t.Fatalf("err: %s", err)
1500	}
1501
1502	err = decoder.Decode(input)
1503	if err != nil {
1504		t.Fatalf("err: %s", err.Error())
1505	}
1506
1507	expectedKeys := []string{"Vbar", "Vbar.Vstring", "Vbar.Vuint", "Vfoo"}
1508	sort.Strings(md.Keys)
1509	if !reflect.DeepEqual(md.Keys, expectedKeys) {
1510		t.Fatalf("bad keys: %#v", md.Keys)
1511	}
1512
1513	expectedUnused := []string{"Vbar.foo", "bar"}
1514	if !reflect.DeepEqual(md.Unused, expectedUnused) {
1515		t.Fatalf("bad unused: %#v", md.Unused)
1516	}
1517}
1518
1519func TestMetadata_Embedded(t *testing.T) {
1520	t.Parallel()
1521
1522	input := map[string]interface{}{
1523		"vstring": "foo",
1524		"vunique": "bar",
1525	}
1526
1527	var md Metadata
1528	var result EmbeddedSquash
1529	config := &DecoderConfig{
1530		Metadata: &md,
1531		Result:   &result,
1532	}
1533
1534	decoder, err := NewDecoder(config)
1535	if err != nil {
1536		t.Fatalf("err: %s", err)
1537	}
1538
1539	err = decoder.Decode(input)
1540	if err != nil {
1541		t.Fatalf("err: %s", err.Error())
1542	}
1543
1544	expectedKeys := []string{"Vstring", "Vunique"}
1545
1546	sort.Strings(md.Keys)
1547	if !reflect.DeepEqual(md.Keys, expectedKeys) {
1548		t.Fatalf("bad keys: %#v", md.Keys)
1549	}
1550
1551	expectedUnused := []string{}
1552	if !reflect.DeepEqual(md.Unused, expectedUnused) {
1553		t.Fatalf("bad unused: %#v", md.Unused)
1554	}
1555}
1556
1557func TestNonPtrValue(t *testing.T) {
1558	t.Parallel()
1559
1560	err := Decode(map[string]interface{}{}, Basic{})
1561	if err == nil {
1562		t.Fatal("error should exist")
1563	}
1564
1565	if err.Error() != "result must be a pointer" {
1566		t.Errorf("got unexpected error: %s", err)
1567	}
1568}
1569
1570func TestTagged(t *testing.T) {
1571	t.Parallel()
1572
1573	input := map[string]interface{}{
1574		"foo": "bar",
1575		"bar": "value",
1576	}
1577
1578	var result Tagged
1579	err := Decode(input, &result)
1580	if err != nil {
1581		t.Fatalf("unexpected error: %s", err)
1582	}
1583
1584	if result.Value != "bar" {
1585		t.Errorf("value should be 'bar', got: %#v", result.Value)
1586	}
1587
1588	if result.Extra != "value" {
1589		t.Errorf("extra should be 'value', got: %#v", result.Extra)
1590	}
1591}
1592
1593func TestWeakDecode(t *testing.T) {
1594	t.Parallel()
1595
1596	input := map[string]interface{}{
1597		"foo": "4",
1598		"bar": "value",
1599	}
1600
1601	var result struct {
1602		Foo int
1603		Bar string
1604	}
1605
1606	if err := WeakDecode(input, &result); err != nil {
1607		t.Fatalf("err: %s", err)
1608	}
1609	if result.Foo != 4 {
1610		t.Fatalf("bad: %#v", result)
1611	}
1612	if result.Bar != "value" {
1613		t.Fatalf("bad: %#v", result)
1614	}
1615}
1616
1617func TestWeakDecodeMetadata(t *testing.T) {
1618	t.Parallel()
1619
1620	input := map[string]interface{}{
1621		"foo":    "4",
1622		"bar":    "value",
1623		"unused": "value",
1624	}
1625
1626	var md Metadata
1627	var result struct {
1628		Foo int
1629		Bar string
1630	}
1631
1632	if err := WeakDecodeMetadata(input, &result, &md); err != nil {
1633		t.Fatalf("err: %s", err)
1634	}
1635	if result.Foo != 4 {
1636		t.Fatalf("bad: %#v", result)
1637	}
1638	if result.Bar != "value" {
1639		t.Fatalf("bad: %#v", result)
1640	}
1641
1642	expectedKeys := []string{"Bar", "Foo"}
1643	sort.Strings(md.Keys)
1644	if !reflect.DeepEqual(md.Keys, expectedKeys) {
1645		t.Fatalf("bad keys: %#v", md.Keys)
1646	}
1647
1648	expectedUnused := []string{"unused"}
1649	if !reflect.DeepEqual(md.Unused, expectedUnused) {
1650		t.Fatalf("bad unused: %#v", md.Unused)
1651	}
1652}
1653
1654func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
1655	var result Slice
1656	err := Decode(input, &result)
1657	if err != nil {
1658		t.Fatalf("got error: %s", err)
1659	}
1660
1661	if result.Vfoo != expected.Vfoo {
1662		t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
1663	}
1664
1665	if result.Vbar == nil {
1666		t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
1667	}
1668
1669	if len(result.Vbar) != len(expected.Vbar) {
1670		t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
1671	}
1672
1673	for i, v := range result.Vbar {
1674		if v != expected.Vbar[i] {
1675			t.Errorf(
1676				"Vbar[%d] should be '%#v', got '%#v'",
1677				i, expected.Vbar[i], v)
1678		}
1679	}
1680}
1681
1682func testArrayInput(t *testing.T, input map[string]interface{}, expected *Array) {
1683	var result Array
1684	err := Decode(input, &result)
1685	if err != nil {
1686		t.Fatalf("got error: %s", err)
1687	}
1688
1689	if result.Vfoo != expected.Vfoo {
1690		t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
1691	}
1692
1693	if result.Vbar == [2]string{} {
1694		t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
1695	}
1696
1697	if len(result.Vbar) != len(expected.Vbar) {
1698		t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
1699	}
1700
1701	for i, v := range result.Vbar {
1702		if v != expected.Vbar[i] {
1703			t.Errorf(
1704				"Vbar[%d] should be '%#v', got '%#v'",
1705				i, expected.Vbar[i], v)
1706		}
1707	}
1708}
1709