OSDN Git Service

versoin1.1.9 (#594)
[bytom/vapor.git] / vendor / github.com / mitchellh / mapstructure / mapstructure_test.go
1 package mapstructure
2
3 import (
4         "encoding/json"
5         "io"
6         "reflect"
7         "sort"
8         "strings"
9         "testing"
10 )
11
12 type 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
26 type BasicSquash struct {
27         Test Basic `mapstructure:",squash"`
28 }
29
30 type Embedded struct {
31         Basic
32         Vunique string
33 }
34
35 type EmbeddedPointer struct {
36         *Basic
37         Vunique string
38 }
39
40 type EmbeddedSquash struct {
41         Basic   `mapstructure:",squash"`
42         Vunique string
43 }
44
45 type SliceAlias []string
46
47 type EmbeddedSlice struct {
48         SliceAlias `mapstructure:"slice_alias"`
49         Vunique    string
50 }
51
52 type SquashOnNonStructType struct {
53         InvalidSquashType int `mapstructure:",squash"`
54 }
55
56 type Map struct {
57         Vfoo   string
58         Vother map[string]string
59 }
60
61 type MapOfStruct struct {
62         Value map[string]Basic
63 }
64
65 type Nested struct {
66         Vfoo string
67         Vbar Basic
68 }
69
70 type NestedPointer struct {
71         Vfoo string
72         Vbar *Basic
73 }
74
75 type NilInterface struct {
76         W io.Writer
77 }
78
79 type Slice struct {
80         Vfoo string
81         Vbar []string
82 }
83
84 type SliceOfStruct struct {
85         Value []Basic
86 }
87
88 type Func struct {
89         Foo func() string
90 }
91
92 type Tagged struct {
93         Extra string `mapstructure:"bar,what,what"`
94         Value string `mapstructure:"foo"`
95 }
96
97 type TypeConversionResult struct {
98         IntToFloat         float32
99         IntToUint          uint
100         IntToBool          bool
101         IntToString        string
102         UintToInt          int
103         UintToFloat        float32
104         UintToBool         bool
105         UintToString       string
106         BoolToInt          int
107         BoolToUint         uint
108         BoolToFloat        float32
109         BoolToString       string
110         FloatToInt         int
111         FloatToUint        uint
112         FloatToBool        bool
113         FloatToString      string
114         SliceUint8ToString string
115         StringToInt        int
116         StringToUint       uint
117         StringToBool       bool
118         StringToFloat      float32
119         StringToStrSlice   []string
120         StringToIntSlice   []int
121         SliceToMap         map[string]interface{}
122         MapToSlice         []interface{}
123 }
124
125 func TestBasicTypes(t *testing.T) {
126         t.Parallel()
127
128         input := map[string]interface{}{
129                 "vstring":     "foo",
130                 "vint":        42,
131                 "Vuint":       42,
132                 "vbool":       true,
133                 "Vfloat":      42.42,
134                 "vsilent":     true,
135                 "vdata":       42,
136                 "vjsonInt":    json.Number("1234"),
137                 "vjsonFloat":  json.Number("1234.5"),
138                 "vjsonNumber": json.Number("1234.5"),
139         }
140
141         var result Basic
142         err := Decode(input, &result)
143         if err != nil {
144                 t.Errorf("got an err: %s", err.Error())
145                 t.FailNow()
146         }
147
148         if result.Vstring != "foo" {
149                 t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
150         }
151
152         if result.Vint != 42 {
153                 t.Errorf("vint value should be 42: %#v", result.Vint)
154         }
155
156         if result.Vuint != 42 {
157                 t.Errorf("vuint value should be 42: %#v", result.Vuint)
158         }
159
160         if result.Vbool != true {
161                 t.Errorf("vbool value should be true: %#v", result.Vbool)
162         }
163
164         if result.Vfloat != 42.42 {
165                 t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat)
166         }
167
168         if result.Vextra != "" {
169                 t.Errorf("vextra value should be empty: %#v", result.Vextra)
170         }
171
172         if result.vsilent != false {
173                 t.Error("vsilent should not be set, it is unexported")
174         }
175
176         if result.Vdata != 42 {
177                 t.Error("vdata should be valid")
178         }
179
180         if result.VjsonInt != 1234 {
181                 t.Errorf("vjsonint value should be 1234: %#v", result.VjsonInt)
182         }
183
184         if result.VjsonFloat != 1234.5 {
185                 t.Errorf("vjsonfloat value should be 1234.5: %#v", result.VjsonFloat)
186         }
187
188         if !reflect.DeepEqual(result.VjsonNumber, json.Number("1234.5")) {
189                 t.Errorf("vjsonnumber value should be '1234.5': %T, %#v", result.VjsonNumber, result.VjsonNumber)
190         }
191 }
192
193 func TestBasic_IntWithFloat(t *testing.T) {
194         t.Parallel()
195
196         input := map[string]interface{}{
197                 "vint": float64(42),
198         }
199
200         var result Basic
201         err := Decode(input, &result)
202         if err != nil {
203                 t.Fatalf("got an err: %s", err)
204         }
205 }
206
207 func TestBasic_Merge(t *testing.T) {
208         t.Parallel()
209
210         input := map[string]interface{}{
211                 "vint": 42,
212         }
213
214         var result Basic
215         result.Vuint = 100
216         err := Decode(input, &result)
217         if err != nil {
218                 t.Fatalf("got an err: %s", err)
219         }
220
221         expected := Basic{
222                 Vint:  42,
223                 Vuint: 100,
224         }
225         if !reflect.DeepEqual(result, expected) {
226                 t.Fatalf("bad: %#v", result)
227         }
228 }
229
230 func TestDecode_BasicSquash(t *testing.T) {
231         t.Parallel()
232
233         input := map[string]interface{}{
234                 "vstring": "foo",
235         }
236
237         var result BasicSquash
238         err := Decode(input, &result)
239         if err != nil {
240                 t.Fatalf("got an err: %s", err.Error())
241         }
242
243         if result.Test.Vstring != "foo" {
244                 t.Errorf("vstring value should be 'foo': %#v", result.Test.Vstring)
245         }
246 }
247
248 func TestDecode_Embedded(t *testing.T) {
249         t.Parallel()
250
251         input := map[string]interface{}{
252                 "vstring": "foo",
253                 "Basic": map[string]interface{}{
254                         "vstring": "innerfoo",
255                 },
256                 "vunique": "bar",
257         }
258
259         var result Embedded
260         err := Decode(input, &result)
261         if err != nil {
262                 t.Fatalf("got an err: %s", err.Error())
263         }
264
265         if result.Vstring != "innerfoo" {
266                 t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring)
267         }
268
269         if result.Vunique != "bar" {
270                 t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
271         }
272 }
273
274 func TestDecode_EmbeddedPointer(t *testing.T) {
275         t.Parallel()
276
277         input := map[string]interface{}{
278                 "vstring": "foo",
279                 "Basic": map[string]interface{}{
280                         "vstring": "innerfoo",
281                 },
282                 "vunique": "bar",
283         }
284
285         var result EmbeddedPointer
286         err := Decode(input, &result)
287         if err != nil {
288                 t.Fatalf("err: %s", err)
289         }
290
291         expected := EmbeddedPointer{
292                 Basic: &Basic{
293                         Vstring: "innerfoo",
294                 },
295                 Vunique: "bar",
296         }
297         if !reflect.DeepEqual(result, expected) {
298                 t.Fatalf("bad: %#v", result)
299         }
300 }
301
302 func TestDecode_EmbeddedSlice(t *testing.T) {
303         t.Parallel()
304
305         input := map[string]interface{}{
306                 "slice_alias": []string{"foo", "bar"},
307                 "vunique":     "bar",
308         }
309
310         var result EmbeddedSlice
311         err := Decode(input, &result)
312         if err != nil {
313                 t.Fatalf("got an err: %s", err.Error())
314         }
315
316         if !reflect.DeepEqual(result.SliceAlias, SliceAlias([]string{"foo", "bar"})) {
317                 t.Errorf("slice value: %#v", result.SliceAlias)
318         }
319
320         if result.Vunique != "bar" {
321                 t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
322         }
323 }
324
325 func TestDecode_EmbeddedSquash(t *testing.T) {
326         t.Parallel()
327
328         input := map[string]interface{}{
329                 "vstring": "foo",
330                 "vunique": "bar",
331         }
332
333         var result EmbeddedSquash
334         err := Decode(input, &result)
335         if err != nil {
336                 t.Fatalf("got an err: %s", err.Error())
337         }
338
339         if result.Vstring != "foo" {
340                 t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
341         }
342
343         if result.Vunique != "bar" {
344                 t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
345         }
346 }
347
348 func TestDecode_SquashOnNonStructType(t *testing.T) {
349         t.Parallel()
350
351         input := map[string]interface{}{
352                 "InvalidSquashType": 42,
353         }
354
355         var result SquashOnNonStructType
356         err := Decode(input, &result)
357         if err == nil {
358                 t.Fatal("unexpected success decoding invalid squash field type")
359         } else if !strings.Contains(err.Error(), "unsupported type for squash") {
360                 t.Fatalf("unexpected error message for invalid squash field type: %s", err)
361         }
362 }
363
364 func TestDecode_DecodeHook(t *testing.T) {
365         t.Parallel()
366
367         input := map[string]interface{}{
368                 "vint": "WHAT",
369         }
370
371         decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) {
372                 if from == reflect.String && to != reflect.String {
373                         return 5, nil
374                 }
375
376                 return v, nil
377         }
378
379         var result Basic
380         config := &DecoderConfig{
381                 DecodeHook: decodeHook,
382                 Result:     &result,
383         }
384
385         decoder, err := NewDecoder(config)
386         if err != nil {
387                 t.Fatalf("err: %s", err)
388         }
389
390         err = decoder.Decode(input)
391         if err != nil {
392                 t.Fatalf("got an err: %s", err)
393         }
394
395         if result.Vint != 5 {
396                 t.Errorf("vint should be 5: %#v", result.Vint)
397         }
398 }
399
400 func TestDecode_DecodeHookType(t *testing.T) {
401         t.Parallel()
402
403         input := map[string]interface{}{
404                 "vint": "WHAT",
405         }
406
407         decodeHook := func(from reflect.Type, to reflect.Type, v interface{}) (interface{}, error) {
408                 if from.Kind() == reflect.String &&
409                         to.Kind() != reflect.String {
410                         return 5, nil
411                 }
412
413                 return v, nil
414         }
415
416         var result Basic
417         config := &DecoderConfig{
418                 DecodeHook: decodeHook,
419                 Result:     &result,
420         }
421
422         decoder, err := NewDecoder(config)
423         if err != nil {
424                 t.Fatalf("err: %s", err)
425         }
426
427         err = decoder.Decode(input)
428         if err != nil {
429                 t.Fatalf("got an err: %s", err)
430         }
431
432         if result.Vint != 5 {
433                 t.Errorf("vint should be 5: %#v", result.Vint)
434         }
435 }
436
437 func TestDecode_Nil(t *testing.T) {
438         t.Parallel()
439
440         var input interface{}
441         result := Basic{
442                 Vstring: "foo",
443         }
444
445         err := Decode(input, &result)
446         if err != nil {
447                 t.Fatalf("err: %s", err)
448         }
449
450         if result.Vstring != "foo" {
451                 t.Fatalf("bad: %#v", result.Vstring)
452         }
453 }
454
455 func TestDecode_NilInterfaceHook(t *testing.T) {
456         t.Parallel()
457
458         input := map[string]interface{}{
459                 "w": "",
460         }
461
462         decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
463                 if t.String() == "io.Writer" {
464                         return nil, nil
465                 }
466
467                 return v, nil
468         }
469
470         var result NilInterface
471         config := &DecoderConfig{
472                 DecodeHook: decodeHook,
473                 Result:     &result,
474         }
475
476         decoder, err := NewDecoder(config)
477         if err != nil {
478                 t.Fatalf("err: %s", err)
479         }
480
481         err = decoder.Decode(input)
482         if err != nil {
483                 t.Fatalf("got an err: %s", err)
484         }
485
486         if result.W != nil {
487                 t.Errorf("W should be nil: %#v", result.W)
488         }
489 }
490
491 func TestDecode_FuncHook(t *testing.T) {
492         t.Parallel()
493
494         input := map[string]interface{}{
495                 "foo": "baz",
496         }
497
498         decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
499                 if t.Kind() != reflect.Func {
500                         return v, nil
501                 }
502                 val := v.(string)
503                 return func() string { return val }, nil
504         }
505
506         var result Func
507         config := &DecoderConfig{
508                 DecodeHook: decodeHook,
509                 Result:     &result,
510         }
511
512         decoder, err := NewDecoder(config)
513         if err != nil {
514                 t.Fatalf("err: %s", err)
515         }
516
517         err = decoder.Decode(input)
518         if err != nil {
519                 t.Fatalf("got an err: %s", err)
520         }
521
522         if result.Foo() != "baz" {
523                 t.Errorf("Foo call result should be 'baz': %s", result.Foo())
524         }
525 }
526
527 func TestDecode_NonStruct(t *testing.T) {
528         t.Parallel()
529
530         input := map[string]interface{}{
531                 "foo": "bar",
532                 "bar": "baz",
533         }
534
535         var result map[string]string
536         err := Decode(input, &result)
537         if err != nil {
538                 t.Fatalf("err: %s", err)
539         }
540
541         if result["foo"] != "bar" {
542                 t.Fatal("foo is not bar")
543         }
544 }
545
546 func TestDecode_StructMatch(t *testing.T) {
547         t.Parallel()
548
549         input := map[string]interface{}{
550                 "vbar": Basic{
551                         Vstring: "foo",
552                 },
553         }
554
555         var result Nested
556         err := Decode(input, &result)
557         if err != nil {
558                 t.Fatalf("got an err: %s", err.Error())
559         }
560
561         if result.Vbar.Vstring != "foo" {
562                 t.Errorf("bad: %#v", result)
563         }
564 }
565
566 func TestDecode_TypeConversion(t *testing.T) {
567         input := map[string]interface{}{
568                 "IntToFloat":         42,
569                 "IntToUint":          42,
570                 "IntToBool":          1,
571                 "IntToString":        42,
572                 "UintToInt":          42,
573                 "UintToFloat":        42,
574                 "UintToBool":         42,
575                 "UintToString":       42,
576                 "BoolToInt":          true,
577                 "BoolToUint":         true,
578                 "BoolToFloat":        true,
579                 "BoolToString":       true,
580                 "FloatToInt":         42.42,
581                 "FloatToUint":        42.42,
582                 "FloatToBool":        42.42,
583                 "FloatToString":      42.42,
584                 "SliceUint8ToString": []uint8("foo"),
585                 "StringToInt":        "42",
586                 "StringToUint":       "42",
587                 "StringToBool":       "1",
588                 "StringToFloat":      "42.42",
589                 "StringToStrSlice":   "A",
590                 "StringToIntSlice":   "42",
591                 "SliceToMap":         []interface{}{},
592                 "MapToSlice":         map[string]interface{}{},
593         }
594
595         expectedResultStrict := TypeConversionResult{
596                 IntToFloat:  42.0,
597                 IntToUint:   42,
598                 UintToInt:   42,
599                 UintToFloat: 42,
600                 BoolToInt:   0,
601                 BoolToUint:  0,
602                 BoolToFloat: 0,
603                 FloatToInt:  42,
604                 FloatToUint: 42,
605         }
606
607         expectedResultWeak := TypeConversionResult{
608                 IntToFloat:         42.0,
609                 IntToUint:          42,
610                 IntToBool:          true,
611                 IntToString:        "42",
612                 UintToInt:          42,
613                 UintToFloat:        42,
614                 UintToBool:         true,
615                 UintToString:       "42",
616                 BoolToInt:          1,
617                 BoolToUint:         1,
618                 BoolToFloat:        1,
619                 BoolToString:       "1",
620                 FloatToInt:         42,
621                 FloatToUint:        42,
622                 FloatToBool:        true,
623                 FloatToString:      "42.42",
624                 SliceUint8ToString: "foo",
625                 StringToInt:        42,
626                 StringToUint:       42,
627                 StringToBool:       true,
628                 StringToFloat:      42.42,
629                 StringToStrSlice:   []string{"A"},
630                 StringToIntSlice:   []int{42},
631                 SliceToMap:         map[string]interface{}{},
632                 MapToSlice:         []interface{}{},
633         }
634
635         // Test strict type conversion
636         var resultStrict TypeConversionResult
637         err := Decode(input, &resultStrict)
638         if err == nil {
639                 t.Errorf("should return an error")
640         }
641         if !reflect.DeepEqual(resultStrict, expectedResultStrict) {
642                 t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict)
643         }
644
645         // Test weak type conversion
646         var decoder *Decoder
647         var resultWeak TypeConversionResult
648
649         config := &DecoderConfig{
650                 WeaklyTypedInput: true,
651                 Result:           &resultWeak,
652         }
653
654         decoder, err = NewDecoder(config)
655         if err != nil {
656                 t.Fatalf("err: %s", err)
657         }
658
659         err = decoder.Decode(input)
660         if err != nil {
661                 t.Fatalf("got an err: %s", err)
662         }
663
664         if !reflect.DeepEqual(resultWeak, expectedResultWeak) {
665                 t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak)
666         }
667 }
668
669 func TestDecoder_ErrorUnused(t *testing.T) {
670         t.Parallel()
671
672         input := map[string]interface{}{
673                 "vstring": "hello",
674                 "foo":     "bar",
675         }
676
677         var result Basic
678         config := &DecoderConfig{
679                 ErrorUnused: true,
680                 Result:      &result,
681         }
682
683         decoder, err := NewDecoder(config)
684         if err != nil {
685                 t.Fatalf("err: %s", err)
686         }
687
688         err = decoder.Decode(input)
689         if err == nil {
690                 t.Fatal("expected error")
691         }
692 }
693
694 func TestMap(t *testing.T) {
695         t.Parallel()
696
697         input := map[string]interface{}{
698                 "vfoo": "foo",
699                 "vother": map[interface{}]interface{}{
700                         "foo": "foo",
701                         "bar": "bar",
702                 },
703         }
704
705         var result Map
706         err := Decode(input, &result)
707         if err != nil {
708                 t.Fatalf("got an error: %s", err)
709         }
710
711         if result.Vfoo != "foo" {
712                 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
713         }
714
715         if result.Vother == nil {
716                 t.Fatal("vother should not be nil")
717         }
718
719         if len(result.Vother) != 2 {
720                 t.Error("vother should have two items")
721         }
722
723         if result.Vother["foo"] != "foo" {
724                 t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"])
725         }
726
727         if result.Vother["bar"] != "bar" {
728                 t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"])
729         }
730 }
731
732 func TestMapMerge(t *testing.T) {
733         t.Parallel()
734
735         input := map[string]interface{}{
736                 "vfoo": "foo",
737                 "vother": map[interface{}]interface{}{
738                         "foo": "foo",
739                         "bar": "bar",
740                 },
741         }
742
743         var result Map
744         result.Vother = map[string]string{"hello": "world"}
745         err := Decode(input, &result)
746         if err != nil {
747                 t.Fatalf("got an error: %s", err)
748         }
749
750         if result.Vfoo != "foo" {
751                 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
752         }
753
754         expected := map[string]string{
755                 "foo":   "foo",
756                 "bar":   "bar",
757                 "hello": "world",
758         }
759         if !reflect.DeepEqual(result.Vother, expected) {
760                 t.Errorf("bad: %#v", result.Vother)
761         }
762 }
763
764 func TestMapOfStruct(t *testing.T) {
765         t.Parallel()
766
767         input := map[string]interface{}{
768                 "value": map[string]interface{}{
769                         "foo": map[string]string{"vstring": "one"},
770                         "bar": map[string]string{"vstring": "two"},
771                 },
772         }
773
774         var result MapOfStruct
775         err := Decode(input, &result)
776         if err != nil {
777                 t.Fatalf("got an err: %s", err)
778         }
779
780         if result.Value == nil {
781                 t.Fatal("value should not be nil")
782         }
783
784         if len(result.Value) != 2 {
785                 t.Error("value should have two items")
786         }
787
788         if result.Value["foo"].Vstring != "one" {
789                 t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring)
790         }
791
792         if result.Value["bar"].Vstring != "two" {
793                 t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring)
794         }
795 }
796
797 func TestNestedType(t *testing.T) {
798         t.Parallel()
799
800         input := map[string]interface{}{
801                 "vfoo": "foo",
802                 "vbar": map[string]interface{}{
803                         "vstring": "foo",
804                         "vint":    42,
805                         "vbool":   true,
806                 },
807         }
808
809         var result Nested
810         err := Decode(input, &result)
811         if err != nil {
812                 t.Fatalf("got an err: %s", err.Error())
813         }
814
815         if result.Vfoo != "foo" {
816                 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
817         }
818
819         if result.Vbar.Vstring != "foo" {
820                 t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
821         }
822
823         if result.Vbar.Vint != 42 {
824                 t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
825         }
826
827         if result.Vbar.Vbool != true {
828                 t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
829         }
830
831         if result.Vbar.Vextra != "" {
832                 t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
833         }
834 }
835
836 func TestNestedTypePointer(t *testing.T) {
837         t.Parallel()
838
839         input := map[string]interface{}{
840                 "vfoo": "foo",
841                 "vbar": &map[string]interface{}{
842                         "vstring": "foo",
843                         "vint":    42,
844                         "vbool":   true,
845                 },
846         }
847
848         var result NestedPointer
849         err := Decode(input, &result)
850         if err != nil {
851                 t.Fatalf("got an err: %s", err.Error())
852         }
853
854         if result.Vfoo != "foo" {
855                 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
856         }
857
858         if result.Vbar.Vstring != "foo" {
859                 t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
860         }
861
862         if result.Vbar.Vint != 42 {
863                 t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
864         }
865
866         if result.Vbar.Vbool != true {
867                 t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
868         }
869
870         if result.Vbar.Vextra != "" {
871                 t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
872         }
873 }
874
875 func TestSlice(t *testing.T) {
876         t.Parallel()
877
878         inputStringSlice := map[string]interface{}{
879                 "vfoo": "foo",
880                 "vbar": []string{"foo", "bar", "baz"},
881         }
882
883         inputStringSlicePointer := map[string]interface{}{
884                 "vfoo": "foo",
885                 "vbar": &[]string{"foo", "bar", "baz"},
886         }
887
888         outputStringSlice := &Slice{
889                 "foo",
890                 []string{"foo", "bar", "baz"},
891         }
892
893         testSliceInput(t, inputStringSlice, outputStringSlice)
894         testSliceInput(t, inputStringSlicePointer, outputStringSlice)
895 }
896
897 func TestInvalidSlice(t *testing.T) {
898         t.Parallel()
899
900         input := map[string]interface{}{
901                 "vfoo": "foo",
902                 "vbar": 42,
903         }
904
905         result := Slice{}
906         err := Decode(input, &result)
907         if err == nil {
908                 t.Errorf("expected failure")
909         }
910 }
911
912 func TestSliceOfStruct(t *testing.T) {
913         t.Parallel()
914
915         input := map[string]interface{}{
916                 "value": []map[string]interface{}{
917                         {"vstring": "one"},
918                         {"vstring": "two"},
919                 },
920         }
921
922         var result SliceOfStruct
923         err := Decode(input, &result)
924         if err != nil {
925                 t.Fatalf("got unexpected error: %s", err)
926         }
927
928         if len(result.Value) != 2 {
929                 t.Fatalf("expected two values, got %d", len(result.Value))
930         }
931
932         if result.Value[0].Vstring != "one" {
933                 t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
934         }
935
936         if result.Value[1].Vstring != "two" {
937                 t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
938         }
939 }
940
941 func TestSliceToMap(t *testing.T) {
942         t.Parallel()
943
944         input := []map[string]interface{}{
945                 {
946                         "foo": "bar",
947                 },
948                 {
949                         "bar": "baz",
950                 },
951         }
952
953         var result map[string]interface{}
954         err := WeakDecode(input, &result)
955         if err != nil {
956                 t.Fatalf("got an error: %s", err)
957         }
958
959         expected := map[string]interface{}{
960                 "foo": "bar",
961                 "bar": "baz",
962         }
963         if !reflect.DeepEqual(result, expected) {
964                 t.Errorf("bad: %#v", result)
965         }
966 }
967
968 func TestInvalidType(t *testing.T) {
969         t.Parallel()
970
971         input := map[string]interface{}{
972                 "vstring": 42,
973         }
974
975         var result Basic
976         err := Decode(input, &result)
977         if err == nil {
978                 t.Fatal("error should exist")
979         }
980
981         derr, ok := err.(*Error)
982         if !ok {
983                 t.Fatalf("error should be kind of Error, instead: %#v", err)
984         }
985
986         if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
987                 t.Errorf("got unexpected error: %s", err)
988         }
989
990         inputNegIntUint := map[string]interface{}{
991                 "vuint": -42,
992         }
993
994         err = Decode(inputNegIntUint, &result)
995         if err == nil {
996                 t.Fatal("error should exist")
997         }
998
999         derr, ok = err.(*Error)
1000         if !ok {
1001                 t.Fatalf("error should be kind of Error, instead: %#v", err)
1002         }
1003
1004         if derr.Errors[0] != "cannot parse 'Vuint', -42 overflows uint" {
1005                 t.Errorf("got unexpected error: %s", err)
1006         }
1007
1008         inputNegFloatUint := map[string]interface{}{
1009                 "vuint": -42.0,
1010         }
1011
1012         err = Decode(inputNegFloatUint, &result)
1013         if err == nil {
1014                 t.Fatal("error should exist")
1015         }
1016
1017         derr, ok = err.(*Error)
1018         if !ok {
1019                 t.Fatalf("error should be kind of Error, instead: %#v", err)
1020         }
1021
1022         if derr.Errors[0] != "cannot parse 'Vuint', -42.000000 overflows uint" {
1023                 t.Errorf("got unexpected error: %s", err)
1024         }
1025 }
1026
1027 func TestMetadata(t *testing.T) {
1028         t.Parallel()
1029
1030         input := map[string]interface{}{
1031                 "vfoo": "foo",
1032                 "vbar": map[string]interface{}{
1033                         "vstring": "foo",
1034                         "Vuint":   42,
1035                         "foo":     "bar",
1036                 },
1037                 "bar": "nil",
1038         }
1039
1040         var md Metadata
1041         var result Nested
1042         config := &DecoderConfig{
1043                 Metadata: &md,
1044                 Result:   &result,
1045         }
1046
1047         decoder, err := NewDecoder(config)
1048         if err != nil {
1049                 t.Fatalf("err: %s", err)
1050         }
1051
1052         err = decoder.Decode(input)
1053         if err != nil {
1054                 t.Fatalf("err: %s", err.Error())
1055         }
1056
1057         expectedKeys := []string{"Vbar", "Vbar.Vstring", "Vbar.Vuint", "Vfoo"}
1058         sort.Strings(md.Keys)
1059         if !reflect.DeepEqual(md.Keys, expectedKeys) {
1060                 t.Fatalf("bad keys: %#v", md.Keys)
1061         }
1062
1063         expectedUnused := []string{"Vbar.foo", "bar"}
1064         if !reflect.DeepEqual(md.Unused, expectedUnused) {
1065                 t.Fatalf("bad unused: %#v", md.Unused)
1066         }
1067 }
1068
1069 func TestMetadata_Embedded(t *testing.T) {
1070         t.Parallel()
1071
1072         input := map[string]interface{}{
1073                 "vstring": "foo",
1074                 "vunique": "bar",
1075         }
1076
1077         var md Metadata
1078         var result EmbeddedSquash
1079         config := &DecoderConfig{
1080                 Metadata: &md,
1081                 Result:   &result,
1082         }
1083
1084         decoder, err := NewDecoder(config)
1085         if err != nil {
1086                 t.Fatalf("err: %s", err)
1087         }
1088
1089         err = decoder.Decode(input)
1090         if err != nil {
1091                 t.Fatalf("err: %s", err.Error())
1092         }
1093
1094         expectedKeys := []string{"Vstring", "Vunique"}
1095
1096         sort.Strings(md.Keys)
1097         if !reflect.DeepEqual(md.Keys, expectedKeys) {
1098                 t.Fatalf("bad keys: %#v", md.Keys)
1099         }
1100
1101         expectedUnused := []string{}
1102         if !reflect.DeepEqual(md.Unused, expectedUnused) {
1103                 t.Fatalf("bad unused: %#v", md.Unused)
1104         }
1105 }
1106
1107 func TestNonPtrValue(t *testing.T) {
1108         t.Parallel()
1109
1110         err := Decode(map[string]interface{}{}, Basic{})
1111         if err == nil {
1112                 t.Fatal("error should exist")
1113         }
1114
1115         if err.Error() != "result must be a pointer" {
1116                 t.Errorf("got unexpected error: %s", err)
1117         }
1118 }
1119
1120 func TestTagged(t *testing.T) {
1121         t.Parallel()
1122
1123         input := map[string]interface{}{
1124                 "foo": "bar",
1125                 "bar": "value",
1126         }
1127
1128         var result Tagged
1129         err := Decode(input, &result)
1130         if err != nil {
1131                 t.Fatalf("unexpected error: %s", err)
1132         }
1133
1134         if result.Value != "bar" {
1135                 t.Errorf("value should be 'bar', got: %#v", result.Value)
1136         }
1137
1138         if result.Extra != "value" {
1139                 t.Errorf("extra should be 'value', got: %#v", result.Extra)
1140         }
1141 }
1142
1143 func TestWeakDecode(t *testing.T) {
1144         t.Parallel()
1145
1146         input := map[string]interface{}{
1147                 "foo": "4",
1148                 "bar": "value",
1149         }
1150
1151         var result struct {
1152                 Foo int
1153                 Bar string
1154         }
1155
1156         if err := WeakDecode(input, &result); err != nil {
1157                 t.Fatalf("err: %s", err)
1158         }
1159         if result.Foo != 4 {
1160                 t.Fatalf("bad: %#v", result)
1161         }
1162         if result.Bar != "value" {
1163                 t.Fatalf("bad: %#v", result)
1164         }
1165 }
1166
1167 func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
1168         var result Slice
1169         err := Decode(input, &result)
1170         if err != nil {
1171                 t.Fatalf("got error: %s", err)
1172         }
1173
1174         if result.Vfoo != expected.Vfoo {
1175                 t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
1176         }
1177
1178         if result.Vbar == nil {
1179                 t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
1180         }
1181
1182         if len(result.Vbar) != len(expected.Vbar) {
1183                 t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
1184         }
1185
1186         for i, v := range result.Vbar {
1187                 if v != expected.Vbar[i] {
1188                         t.Errorf(
1189                                 "Vbar[%d] should be '%#v', got '%#v'",
1190                                 i, expected.Vbar[i], v)
1191                 }
1192         }
1193 }