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