github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/mapstruct/mapstruct_test.go (about)

     1  package mapstruct
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"reflect"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  type NullTime struct {
    16  	DeletedTime *time.Time
    17  }
    18  
    19  func TestNullTime(t *testing.T) {
    20  	var nullTimes []NullTime
    21  
    22  	decoder, err := NewDecoder(&Config{
    23  		Result:   &nullTimes,
    24  		Squash:   true,
    25  		WeakType: true,
    26  	})
    27  	assert.Nil(t, err)
    28  
    29  	values := []map[string]string{
    30  		{"DeletedTime": ""},
    31  	}
    32  
    33  	err = decoder.Decode(values)
    34  	assert.Nil(t, err)
    35  	assert.Nil(t, nullTimes[0].DeletedTime)
    36  }
    37  
    38  type Basic struct {
    39  	Vstring     string
    40  	Vint        int
    41  	Vint8       int8
    42  	Vint16      int16
    43  	Vint32      int32
    44  	Vint64      int64
    45  	Vuint       uint
    46  	Vbool       bool
    47  	Vfloat      float64
    48  	Vextra      string
    49  	vsilent     bool
    50  	Vdata       interface{}
    51  	VjsonInt    int
    52  	VjsonUint   uint
    53  	VjsonFloat  float64
    54  	VjsonNumber json.Number
    55  }
    56  
    57  type BasicPointer struct {
    58  	Vstring     *string
    59  	Vint        *int
    60  	Vuint       *uint
    61  	Vbool       *bool
    62  	Vfloat      *float64
    63  	Vextra      *string
    64  	vsilent     *bool // nolint:structcheck,unused
    65  	Vdata       *interface{}
    66  	VjsonInt    *int
    67  	VjsonFloat  *float64
    68  	VjsonNumber *json.Number
    69  }
    70  
    71  type BasicSquash struct {
    72  	Test Basic `mapstruct:",squash"`
    73  }
    74  
    75  type Embedded struct {
    76  	Basic
    77  	Vunique string
    78  }
    79  
    80  type EmbeddedPointer struct {
    81  	*Basic
    82  	Vunique string
    83  }
    84  
    85  type EmbeddedSquash struct {
    86  	Basic   `mapstruct:",squash"`
    87  	Vunique string
    88  }
    89  
    90  type EmbeddedPointerSquash struct {
    91  	*Basic  `mapstruct:",squash"`
    92  	Vunique string
    93  }
    94  
    95  type EmbeddedAndNamed struct {
    96  	Basic
    97  	Named   Basic
    98  	Vunique string
    99  }
   100  
   101  type SliceAlias []string
   102  
   103  type EmbeddedSlice struct {
   104  	SliceAlias `mapstruct:"slice_alias"`
   105  	Vunique    string
   106  }
   107  
   108  type ArrayAlias [2]string
   109  
   110  type EmbeddedArray struct {
   111  	ArrayAlias `mapstruct:"array_alias"`
   112  	Vunique    string
   113  }
   114  
   115  type SquashOnNonStructType struct {
   116  	InvalidSquashType int `mapstruct:",squash"`
   117  }
   118  
   119  type Map struct {
   120  	Vfoo   string
   121  	Vother map[string]string
   122  }
   123  
   124  type MapOfStruct struct {
   125  	Value map[string]Basic
   126  }
   127  
   128  type Nested struct {
   129  	Vfoo string
   130  	Vbar Basic
   131  }
   132  
   133  type NestedPointer struct {
   134  	Vfoo string
   135  	Vbar *Basic
   136  }
   137  
   138  type NilInterface struct {
   139  	W io.Writer
   140  }
   141  
   142  type NilPointer struct {
   143  	Value *string
   144  }
   145  
   146  type Slice struct {
   147  	Vfoo string
   148  	Vbar []string
   149  }
   150  
   151  type SliceOfAlias struct {
   152  	Vfoo string
   153  	Vbar SliceAlias
   154  }
   155  
   156  type SliceOfStruct struct {
   157  	Value []Basic
   158  }
   159  
   160  type SlicePointer struct {
   161  	Vbar *[]string
   162  }
   163  
   164  type Array struct {
   165  	Vfoo string
   166  	Vbar [2]string
   167  }
   168  
   169  type ArrayOfStruct struct {
   170  	Value [2]Basic
   171  }
   172  
   173  type Func struct {
   174  	Foo func() string
   175  }
   176  
   177  type Tagged struct {
   178  	Extra string `mapstruct:"bar,what,what"`
   179  	Value string `mapstruct:"foo"`
   180  }
   181  
   182  type Remainder struct {
   183  	A     string
   184  	Extra map[string]interface{} `mapstruct:",remain"`
   185  }
   186  
   187  type StructWithOmitEmpty struct {
   188  	VisibleStringField string                 `mapstruct:"visible-string"`
   189  	OmitStringField    string                 `mapstruct:"omittable-string,omitempty"`
   190  	VisibleIntField    int                    `mapstruct:"visible-int"`
   191  	OmitIntField       int                    `mapstruct:"omittable-int,omitempty"`
   192  	VisibleFloatField  float64                `mapstruct:"visible-float"`
   193  	OmitFloatField     float64                `mapstruct:"omittable-float,omitempty"`
   194  	VisibleSliceField  []interface{}          `mapstruct:"visible-slice"`
   195  	OmitSliceField     []interface{}          `mapstruct:"omittable-slice,omitempty"`
   196  	VisibleMapField    map[string]interface{} `mapstruct:"visible-map"`
   197  	OmitMapField       map[string]interface{} `mapstruct:"omittable-map,omitempty"`
   198  	NestedField        *Nested                `mapstruct:"visible-nested"`
   199  	OmitNestedField    *Nested                `mapstruct:"omittable-nested,omitempty"`
   200  }
   201  
   202  type TypeConversionResult struct {
   203  	IntToFloat         float32
   204  	IntToUint          uint
   205  	IntToBool          bool
   206  	IntToString        string
   207  	UintToInt          int
   208  	UintToFloat        float32
   209  	UintToBool         bool
   210  	UintToString       string
   211  	BoolToInt          int
   212  	BoolToUint         uint
   213  	BoolToFloat        float32
   214  	BoolToString       string
   215  	FloatToInt         int
   216  	FloatToUint        uint
   217  	FloatToBool        bool
   218  	FloatToString      string
   219  	SliceUint8ToString string
   220  	StringToSliceUint8 []byte
   221  	ArrayUint8ToString string
   222  	StringToInt        int
   223  	StringToUint       uint
   224  	StringToBool       bool
   225  	StringToFloat      float32
   226  	StringToStrSlice   []string
   227  	StringToIntSlice   []int
   228  	StringToStrArray   [1]string
   229  	StringToIntArray   [1]int
   230  	SliceToMap         map[string]interface{}
   231  	MapToSlice         []interface{}
   232  	ArrayToMap         map[string]interface{}
   233  	MapToArray         [1]interface{}
   234  }
   235  
   236  func TestBasicTypes(t *testing.T) {
   237  	t.Parallel()
   238  
   239  	input := map[string]interface{}{
   240  		"vstring":     "foo",
   241  		"vint":        42,
   242  		"vint8":       42,
   243  		"vint16":      42,
   244  		"vint32":      42,
   245  		"vint64":      42,
   246  		"Vuint":       42,
   247  		"vbool":       true,
   248  		"Vfloat":      42.42,
   249  		"vsilent":     true,
   250  		"vdata":       42,
   251  		"vjsonInt":    json.Number("1234"),
   252  		"vjsonUint":   json.Number("1234"),
   253  		"vjsonFloat":  json.Number("1234.5"),
   254  		"vjsonNumber": json.Number("1234.5"),
   255  	}
   256  
   257  	var result Basic
   258  	err := Decode(input, &result)
   259  	if err != nil {
   260  		t.Errorf("got an err: %s", err.Error())
   261  		t.FailNow()
   262  	}
   263  
   264  	if result.Vstring != "foo" {
   265  		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
   266  	}
   267  
   268  	if result.Vint != 42 {
   269  		t.Errorf("vint value should be 42: %#v", result.Vint)
   270  	}
   271  	if result.Vint8 != 42 {
   272  		t.Errorf("vint8 value should be 42: %#v", result.Vint)
   273  	}
   274  	if result.Vint16 != 42 {
   275  		t.Errorf("vint16 value should be 42: %#v", result.Vint)
   276  	}
   277  	if result.Vint32 != 42 {
   278  		t.Errorf("vint32 value should be 42: %#v", result.Vint)
   279  	}
   280  	if result.Vint64 != 42 {
   281  		t.Errorf("vint64 value should be 42: %#v", result.Vint)
   282  	}
   283  
   284  	if result.Vuint != 42 {
   285  		t.Errorf("vuint value should be 42: %#v", result.Vuint)
   286  	}
   287  
   288  	if result.Vbool != true {
   289  		t.Errorf("vbool value should be true: %#v", result.Vbool)
   290  	}
   291  
   292  	if result.Vfloat != 42.42 {
   293  		t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat)
   294  	}
   295  
   296  	if result.Vextra != "" {
   297  		t.Errorf("vextra value should be empty: %#v", result.Vextra)
   298  	}
   299  
   300  	if result.vsilent != false {
   301  		t.Error("vsilent should not be set, it is unexported")
   302  	}
   303  
   304  	if result.Vdata != 42 {
   305  		t.Error("vdata should be valid")
   306  	}
   307  
   308  	if result.VjsonInt != 1234 {
   309  		t.Errorf("vjsonint value should be 1234: %#v", result.VjsonInt)
   310  	}
   311  
   312  	if result.VjsonUint != 1234 {
   313  		t.Errorf("vjsonuint value should be 1234: %#v", result.VjsonUint)
   314  	}
   315  
   316  	if result.VjsonFloat != 1234.5 {
   317  		t.Errorf("vjsonfloat value should be 1234.5: %#v", result.VjsonFloat)
   318  	}
   319  
   320  	if !reflect.DeepEqual(result.VjsonNumber, json.Number("1234.5")) {
   321  		t.Errorf("vjsonnumber value should be '1234.5': %T, %#v", result.VjsonNumber, result.VjsonNumber)
   322  	}
   323  }
   324  
   325  func TestBasic_IntWithFloat(t *testing.T) {
   326  	t.Parallel()
   327  
   328  	input := map[string]interface{}{
   329  		"vint": float64(42),
   330  	}
   331  
   332  	var result Basic
   333  	err := Decode(input, &result)
   334  	if err != nil {
   335  		t.Fatalf("got an err: %s", err)
   336  	}
   337  }
   338  
   339  func TestBasic_Merge(t *testing.T) {
   340  	t.Parallel()
   341  
   342  	input := map[string]interface{}{
   343  		"vint": 42,
   344  	}
   345  
   346  	var result Basic
   347  	result.Vuint = 100
   348  	err := Decode(input, &result)
   349  	if err != nil {
   350  		t.Fatalf("got an err: %s", err)
   351  	}
   352  
   353  	expected := Basic{
   354  		Vint:  42,
   355  		Vuint: 100,
   356  	}
   357  	if !reflect.DeepEqual(result, expected) {
   358  		t.Fatalf("bad: %#v", result)
   359  	}
   360  }
   361  
   362  // Test for issue #46.
   363  func TestBasic_Struct(t *testing.T) {
   364  	t.Parallel()
   365  
   366  	input := map[string]interface{}{
   367  		"vdata": map[string]interface{}{
   368  			"vstring": "foo",
   369  		},
   370  	}
   371  
   372  	var result, inner Basic
   373  	result.Vdata = &inner
   374  	err := Decode(input, &result)
   375  	if err != nil {
   376  		t.Fatalf("got an err: %s", err)
   377  	}
   378  	expected := Basic{
   379  		Vdata: &Basic{
   380  			Vstring: "foo",
   381  		},
   382  	}
   383  	if !reflect.DeepEqual(result, expected) {
   384  		t.Fatalf("bad: %#v", result)
   385  	}
   386  }
   387  
   388  func TestBasic_interfaceStruct(t *testing.T) {
   389  	t.Parallel()
   390  
   391  	input := map[string]interface{}{
   392  		"vstring": "foo",
   393  	}
   394  
   395  	var iface interface{} = &Basic{}
   396  	err := Decode(input, &iface)
   397  	if err != nil {
   398  		t.Fatalf("got an err: %s", err)
   399  	}
   400  
   401  	expected := &Basic{
   402  		Vstring: "foo",
   403  	}
   404  	if !reflect.DeepEqual(iface, expected) {
   405  		t.Fatalf("bad: %#v", iface)
   406  	}
   407  }
   408  
   409  // Issue 187
   410  func TestBasic_interfaceStructNonPtr(t *testing.T) {
   411  	t.Parallel()
   412  
   413  	input := map[string]interface{}{
   414  		"vstring": "foo",
   415  	}
   416  
   417  	var iface interface{} = Basic{}
   418  	err := Decode(input, &iface)
   419  	if err != nil {
   420  		t.Fatalf("got an err: %s", err)
   421  	}
   422  
   423  	expected := Basic{
   424  		Vstring: "foo",
   425  	}
   426  	if !reflect.DeepEqual(iface, expected) {
   427  		t.Fatalf("bad: %#v", iface)
   428  	}
   429  }
   430  
   431  func TestDecode_BasicSquash(t *testing.T) {
   432  	t.Parallel()
   433  
   434  	input := map[string]interface{}{
   435  		"vstring": "foo",
   436  	}
   437  
   438  	var result BasicSquash
   439  	err := Decode(input, &result)
   440  	if err != nil {
   441  		t.Fatalf("got an err: %s", err.Error())
   442  	}
   443  
   444  	if result.Test.Vstring != "foo" {
   445  		t.Errorf("vstring value should be 'foo': %#v", result.Test.Vstring)
   446  	}
   447  }
   448  
   449  func TestDecodeFrom_BasicSquash(t *testing.T) {
   450  	t.Parallel()
   451  
   452  	var v interface{}
   453  	var ok bool
   454  
   455  	input := BasicSquash{
   456  		Test: Basic{
   457  			Vstring: "foo",
   458  		},
   459  	}
   460  
   461  	var result map[string]interface{}
   462  	err := Decode(input, &result)
   463  	if err != nil {
   464  		t.Fatalf("got an err: %s", err.Error())
   465  	}
   466  
   467  	if _, ok = result["Test"]; ok {
   468  		t.Error("test should not be present in map")
   469  	}
   470  
   471  	v, ok = result["Vstring"]
   472  	if !ok {
   473  		t.Error("vstring should be present in map")
   474  	} else if !reflect.DeepEqual(v, "foo") {
   475  		t.Errorf("vstring value should be 'foo': %#v", v)
   476  	}
   477  }
   478  
   479  func TestDecode_Embedded(t *testing.T) {
   480  	t.Parallel()
   481  
   482  	input := map[string]interface{}{
   483  		"vstring": "foo",
   484  		"Basic": map[string]interface{}{
   485  			"vstring": "innerfoo",
   486  		},
   487  		"vunique": "bar",
   488  	}
   489  
   490  	var result Embedded
   491  	err := Decode(input, &result)
   492  	if err != nil {
   493  		t.Fatalf("got an err: %s", err.Error())
   494  	}
   495  
   496  	if result.Vstring != "innerfoo" {
   497  		t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring)
   498  	}
   499  
   500  	if result.Vunique != "bar" {
   501  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   502  	}
   503  }
   504  
   505  func TestDecode_EmbeddedPointer(t *testing.T) {
   506  	t.Parallel()
   507  
   508  	input := map[string]interface{}{
   509  		"vstring": "foo",
   510  		"Basic": map[string]interface{}{
   511  			"vstring": "innerfoo",
   512  		},
   513  		"vunique": "bar",
   514  	}
   515  
   516  	var result EmbeddedPointer
   517  	err := Decode(input, &result)
   518  	if err != nil {
   519  		t.Fatalf("err: %s", err)
   520  	}
   521  
   522  	expected := EmbeddedPointer{
   523  		Basic: &Basic{
   524  			Vstring: "innerfoo",
   525  		},
   526  		Vunique: "bar",
   527  	}
   528  	if !reflect.DeepEqual(result, expected) {
   529  		t.Fatalf("bad: %#v", result)
   530  	}
   531  }
   532  
   533  func TestDecode_EmbeddedSlice(t *testing.T) {
   534  	t.Parallel()
   535  
   536  	input := map[string]interface{}{
   537  		"slice_alias": []string{"foo", "bar"},
   538  		"vunique":     "bar",
   539  	}
   540  
   541  	var result EmbeddedSlice
   542  	err := Decode(input, &result)
   543  	if err != nil {
   544  		t.Fatalf("got an err: %s", err.Error())
   545  	}
   546  
   547  	if !reflect.DeepEqual(result.SliceAlias, SliceAlias([]string{"foo", "bar"})) {
   548  		t.Errorf("slice value: %#v", result.SliceAlias)
   549  	}
   550  
   551  	if result.Vunique != "bar" {
   552  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   553  	}
   554  }
   555  
   556  func TestDecode_EmbeddedArray(t *testing.T) {
   557  	t.Parallel()
   558  
   559  	input := map[string]interface{}{
   560  		"array_alias": [2]string{"foo", "bar"},
   561  		"vunique":     "bar",
   562  	}
   563  
   564  	var result EmbeddedArray
   565  	err := Decode(input, &result)
   566  	if err != nil {
   567  		t.Fatalf("got an err: %s", err.Error())
   568  	}
   569  
   570  	if !reflect.DeepEqual(result.ArrayAlias, ArrayAlias([2]string{"foo", "bar"})) {
   571  		t.Errorf("array value: %#v", result.ArrayAlias)
   572  	}
   573  
   574  	if result.Vunique != "bar" {
   575  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   576  	}
   577  }
   578  
   579  func TestDecode_EmbeddedNoSquash(t *testing.T) {
   580  	t.Parallel()
   581  
   582  	input := map[string]interface{}{
   583  		"vstring": "foo",
   584  		"vunique": "bar",
   585  	}
   586  
   587  	var result Embedded
   588  	err := Decode(input, &result)
   589  	if err != nil {
   590  		t.Fatalf("got an err: %s", err.Error())
   591  	}
   592  
   593  	if result.Vstring != "" {
   594  		t.Errorf("vstring value should be empty: %#v", result.Vstring)
   595  	}
   596  
   597  	if result.Vunique != "bar" {
   598  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   599  	}
   600  }
   601  
   602  func TestDecode_EmbeddedPointerNoSquash(t *testing.T) {
   603  	t.Parallel()
   604  
   605  	input := map[string]interface{}{
   606  		"vstring": "foo",
   607  		"vunique": "bar",
   608  	}
   609  
   610  	result := EmbeddedPointer{
   611  		Basic: &Basic{},
   612  	}
   613  
   614  	err := Decode(input, &result)
   615  	if err != nil {
   616  		t.Fatalf("err: %s", err)
   617  	}
   618  
   619  	if result.Vstring != "" {
   620  		t.Errorf("vstring value should be empty: %#v", result.Vstring)
   621  	}
   622  
   623  	if result.Vunique != "bar" {
   624  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   625  	}
   626  }
   627  
   628  func TestDecode_EmbeddedSquash(t *testing.T) {
   629  	t.Parallel()
   630  
   631  	input := map[string]interface{}{
   632  		"vstring": "foo",
   633  		"vunique": "bar",
   634  	}
   635  
   636  	var result EmbeddedSquash
   637  	err := Decode(input, &result)
   638  	if err != nil {
   639  		t.Fatalf("got an err: %s", err.Error())
   640  	}
   641  
   642  	if result.Vstring != "foo" {
   643  		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
   644  	}
   645  
   646  	if result.Vunique != "bar" {
   647  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   648  	}
   649  }
   650  
   651  func TestDecodeFrom_EmbeddedSquash(t *testing.T) {
   652  	t.Parallel()
   653  
   654  	var v interface{}
   655  	var ok bool
   656  
   657  	input := EmbeddedSquash{
   658  		Basic: Basic{
   659  			Vstring: "foo",
   660  		},
   661  		Vunique: "bar",
   662  	}
   663  
   664  	var result map[string]interface{}
   665  	err := Decode(input, &result)
   666  	if err != nil {
   667  		t.Fatalf("got an err: %s", err.Error())
   668  	}
   669  
   670  	if _, ok = result["Basic"]; ok {
   671  		t.Error("basic should not be present in map")
   672  	}
   673  
   674  	v, ok = result["Vstring"]
   675  	if !ok {
   676  		t.Error("vstring should be present in map")
   677  	} else if !reflect.DeepEqual(v, "foo") {
   678  		t.Errorf("vstring value should be 'foo': %#v", v)
   679  	}
   680  
   681  	v, ok = result["Vunique"]
   682  	if !ok {
   683  		t.Error("vunique should be present in map")
   684  	} else if !reflect.DeepEqual(v, "bar") {
   685  		t.Errorf("vunique value should be 'bar': %#v", v)
   686  	}
   687  }
   688  
   689  func TestDecode_EmbeddedPointerSquash_FromStructToMap(t *testing.T) {
   690  	t.Parallel()
   691  
   692  	input := EmbeddedPointerSquash{
   693  		Basic: &Basic{
   694  			Vstring: "foo",
   695  		},
   696  		Vunique: "bar",
   697  	}
   698  
   699  	var result map[string]interface{}
   700  	err := Decode(input, &result)
   701  	if err != nil {
   702  		t.Fatalf("got an err: %s", err.Error())
   703  	}
   704  
   705  	if result["Vstring"] != "foo" {
   706  		t.Errorf("vstring value should be 'foo': %#v", result["Vstring"])
   707  	}
   708  
   709  	if result["Vunique"] != "bar" {
   710  		t.Errorf("vunique value should be 'bar': %#v", result["Vunique"])
   711  	}
   712  }
   713  
   714  func TestDecode_EmbeddedPointerSquash_FromMapToStruct(t *testing.T) {
   715  	t.Parallel()
   716  
   717  	input := map[string]interface{}{
   718  		"Vstring": "foo",
   719  		"Vunique": "bar",
   720  	}
   721  
   722  	result := EmbeddedPointerSquash{
   723  		Basic: &Basic{},
   724  	}
   725  	err := Decode(input, &result)
   726  	if err != nil {
   727  		t.Fatalf("got an err: %s", err.Error())
   728  	}
   729  
   730  	if result.Vstring != "foo" {
   731  		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
   732  	}
   733  
   734  	if result.Vunique != "bar" {
   735  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   736  	}
   737  }
   738  
   739  func TestDecode_EmbeddedSquashConfig(t *testing.T) {
   740  	t.Parallel()
   741  
   742  	input := map[string]interface{}{
   743  		"vstring": "foo",
   744  		"vunique": "bar",
   745  		"Named": map[string]interface{}{
   746  			"vstring": "baz",
   747  		},
   748  	}
   749  
   750  	var result EmbeddedAndNamed
   751  	config := &Config{
   752  		Squash: true,
   753  		Result: &result,
   754  	}
   755  
   756  	decoder, err := NewDecoder(config)
   757  	if err != nil {
   758  		t.Fatalf("err: %s", err)
   759  	}
   760  
   761  	err = decoder.Decode(input)
   762  	if err != nil {
   763  		t.Fatalf("got an err: %s", err)
   764  	}
   765  
   766  	if result.Vstring != "foo" {
   767  		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
   768  	}
   769  
   770  	if result.Vunique != "bar" {
   771  		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
   772  	}
   773  
   774  	if result.Named.Vstring != "baz" {
   775  		t.Errorf("Named.vstring value should be 'baz': %#v", result.Named.Vstring)
   776  	}
   777  }
   778  
   779  func TestDecodeFrom_EmbeddedSquashConfig(t *testing.T) {
   780  	t.Parallel()
   781  
   782  	input := EmbeddedAndNamed{
   783  		Basic:   Basic{Vstring: "foo"},
   784  		Named:   Basic{Vstring: "baz"},
   785  		Vunique: "bar",
   786  	}
   787  
   788  	result := map[string]interface{}{}
   789  	config := &Config{
   790  		Squash: true,
   791  		Result: &result,
   792  	}
   793  	decoder, err := NewDecoder(config)
   794  	if err != nil {
   795  		t.Fatalf("got an err: %s", err.Error())
   796  	}
   797  
   798  	err = decoder.Decode(input)
   799  	if err != nil {
   800  		t.Fatalf("got an err: %s", err.Error())
   801  	}
   802  
   803  	if _, ok := result["Basic"]; ok {
   804  		t.Error("basic should not be present in map")
   805  	}
   806  
   807  	v, ok := result["Vstring"]
   808  	if !ok {
   809  		t.Error("vstring should be present in map")
   810  	} else if !reflect.DeepEqual(v, "foo") {
   811  		t.Errorf("vstring value should be 'foo': %#v", v)
   812  	}
   813  
   814  	v, ok = result["Vunique"]
   815  	if !ok {
   816  		t.Error("vunique should be present in map")
   817  	} else if !reflect.DeepEqual(v, "bar") {
   818  		t.Errorf("vunique value should be 'bar': %#v", v)
   819  	}
   820  
   821  	v, ok = result["Named"]
   822  	if !ok {
   823  		t.Error("Named should be present in map")
   824  	} else {
   825  		named := v.(map[string]interface{})
   826  		v, ok := named["Vstring"]
   827  		if !ok {
   828  			t.Error("Named: vstring should be present in map")
   829  		} else if !reflect.DeepEqual(v, "baz") {
   830  			t.Errorf("Named: vstring should be 'baz': %#v", v)
   831  		}
   832  	}
   833  }
   834  
   835  func TestDecode_SquashOnNonStructType(t *testing.T) {
   836  	t.Parallel()
   837  
   838  	input := map[string]interface{}{
   839  		"InvalidSquashType": 42,
   840  	}
   841  
   842  	var result SquashOnNonStructType
   843  	err := Decode(input, &result)
   844  	if err == nil {
   845  		t.Fatal("unexpected success decoding invalid squash field type")
   846  	} else if !strings.Contains(err.Error(), "unsupported type for squash") {
   847  		t.Fatalf("unexpected error message for invalid squash field type: %s", err)
   848  	}
   849  }
   850  
   851  func TestDecode_DecodeHook(t *testing.T) {
   852  	t.Parallel()
   853  
   854  	input := map[string]interface{}{
   855  		"vint": "WHAT",
   856  	}
   857  
   858  	decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) {
   859  		if from == reflect.String && to != reflect.String {
   860  			return 5, nil
   861  		}
   862  
   863  		return v, nil
   864  	}
   865  
   866  	var result Basic
   867  	config := &Config{
   868  		Hook:   decodeHook,
   869  		Result: &result,
   870  	}
   871  
   872  	decoder, err := NewDecoder(config)
   873  	if err != nil {
   874  		t.Fatalf("err: %s", err)
   875  	}
   876  
   877  	err = decoder.Decode(input)
   878  	if err != nil {
   879  		t.Fatalf("got an err: %s", err)
   880  	}
   881  
   882  	if result.Vint != 5 {
   883  		t.Errorf("vint should be 5: %#v", result.Vint)
   884  	}
   885  }
   886  
   887  func TestDecode_DecodeHookType(t *testing.T) {
   888  	t.Parallel()
   889  
   890  	input := map[string]interface{}{
   891  		"vint": "WHAT",
   892  	}
   893  
   894  	decodeHook := func(from reflect.Type, to reflect.Type, v interface{}) (interface{}, error) {
   895  		if from.Kind() == reflect.String &&
   896  			to.Kind() != reflect.String {
   897  			return 5, nil
   898  		}
   899  
   900  		return v, nil
   901  	}
   902  
   903  	var result Basic
   904  	config := &Config{
   905  		Hook:   decodeHook,
   906  		Result: &result,
   907  	}
   908  
   909  	decoder, err := NewDecoder(config)
   910  	if err != nil {
   911  		t.Fatalf("err: %s", err)
   912  	}
   913  
   914  	err = decoder.Decode(input)
   915  	if err != nil {
   916  		t.Fatalf("got an err: %s", err)
   917  	}
   918  
   919  	if result.Vint != 5 {
   920  		t.Errorf("vint should be 5: %#v", result.Vint)
   921  	}
   922  }
   923  
   924  func TestDecode_Nil(t *testing.T) {
   925  	t.Parallel()
   926  
   927  	var input interface{}
   928  	result := Basic{
   929  		Vstring: "foo",
   930  	}
   931  
   932  	err := Decode(input, &result)
   933  	if err != nil {
   934  		t.Fatalf("err: %s", err)
   935  	}
   936  
   937  	if result.Vstring != "foo" {
   938  		t.Fatalf("bad: %#v", result.Vstring)
   939  	}
   940  }
   941  
   942  func TestDecode_NilInterfaceHook(t *testing.T) {
   943  	t.Parallel()
   944  
   945  	input := map[string]interface{}{
   946  		"w": "",
   947  	}
   948  
   949  	decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
   950  		if t.String() == "io.Writer" {
   951  			return nil, nil
   952  		}
   953  
   954  		return v, nil
   955  	}
   956  
   957  	var result NilInterface
   958  	config := &Config{
   959  		Hook:   decodeHook,
   960  		Result: &result,
   961  	}
   962  
   963  	decoder, err := NewDecoder(config)
   964  	if err != nil {
   965  		t.Fatalf("err: %s", err)
   966  	}
   967  
   968  	err = decoder.Decode(input)
   969  	if err != nil {
   970  		t.Fatalf("got an err: %s", err)
   971  	}
   972  
   973  	if result.W != nil {
   974  		t.Errorf("W should be nil: %#v", result.W)
   975  	}
   976  }
   977  
   978  func TestDecode_NilPointerHook(t *testing.T) {
   979  	t.Parallel()
   980  
   981  	input := map[string]interface{}{
   982  		"value": "",
   983  	}
   984  
   985  	decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
   986  		if typed, ok := v.(string); ok {
   987  			if typed == "" {
   988  				return nil, nil
   989  			}
   990  		}
   991  		return v, nil
   992  	}
   993  
   994  	var result NilPointer
   995  	config := &Config{
   996  		Hook:   decodeHook,
   997  		Result: &result,
   998  	}
   999  
  1000  	decoder, err := NewDecoder(config)
  1001  	if err != nil {
  1002  		t.Fatalf("err: %s", err)
  1003  	}
  1004  
  1005  	err = decoder.Decode(input)
  1006  	if err != nil {
  1007  		t.Fatalf("got an err: %s", err)
  1008  	}
  1009  
  1010  	if result.Value != nil {
  1011  		t.Errorf("W should be nil: %#v", result.Value)
  1012  	}
  1013  }
  1014  
  1015  func TestDecode_FuncHook(t *testing.T) {
  1016  	t.Parallel()
  1017  
  1018  	input := map[string]interface{}{
  1019  		"foo": "baz",
  1020  	}
  1021  
  1022  	decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
  1023  		if t.Kind() != reflect.Func {
  1024  			return v, nil
  1025  		}
  1026  		val := v.(string)
  1027  		return func() string { return val }, nil
  1028  	}
  1029  
  1030  	var result Func
  1031  	config := &Config{
  1032  		Hook:   decodeHook,
  1033  		Result: &result,
  1034  	}
  1035  
  1036  	decoder, err := NewDecoder(config)
  1037  	if err != nil {
  1038  		t.Fatalf("err: %s", err)
  1039  	}
  1040  
  1041  	err = decoder.Decode(input)
  1042  	if err != nil {
  1043  		t.Fatalf("got an err: %s", err)
  1044  	}
  1045  
  1046  	if result.Foo() != "baz" {
  1047  		t.Errorf("Foo call result should be 'baz': %s", result.Foo())
  1048  	}
  1049  }
  1050  
  1051  func TestDecode_NonStruct(t *testing.T) {
  1052  	t.Parallel()
  1053  
  1054  	input := map[string]interface{}{
  1055  		"foo": "bar",
  1056  		"bar": "baz",
  1057  	}
  1058  
  1059  	var result map[string]string
  1060  	err := Decode(input, &result)
  1061  	if err != nil {
  1062  		t.Fatalf("err: %s", err)
  1063  	}
  1064  
  1065  	if result["foo"] != "bar" {
  1066  		t.Fatal("foo is not bar")
  1067  	}
  1068  }
  1069  
  1070  func TestDecode_StructMatch(t *testing.T) {
  1071  	t.Parallel()
  1072  
  1073  	input := map[string]interface{}{
  1074  		"vbar": Basic{
  1075  			Vstring: "foo",
  1076  		},
  1077  	}
  1078  
  1079  	var result Nested
  1080  	err := Decode(input, &result)
  1081  	if err != nil {
  1082  		t.Fatalf("got an err: %s", err.Error())
  1083  	}
  1084  
  1085  	if result.Vbar.Vstring != "foo" {
  1086  		t.Errorf("bad: %#v", result)
  1087  	}
  1088  }
  1089  
  1090  func TestDecode_TypeConversion(t *testing.T) {
  1091  	input := map[string]interface{}{
  1092  		"IntToFloat":         42,
  1093  		"IntToUint":          42,
  1094  		"IntToBool":          1,
  1095  		"IntToString":        42,
  1096  		"UintToInt":          42,
  1097  		"UintToFloat":        42,
  1098  		"UintToBool":         42,
  1099  		"UintToString":       42,
  1100  		"BoolToInt":          true,
  1101  		"BoolToUint":         true,
  1102  		"BoolToFloat":        true,
  1103  		"BoolToString":       true,
  1104  		"FloatToInt":         42.42,
  1105  		"FloatToUint":        42.42,
  1106  		"FloatToBool":        42.42,
  1107  		"FloatToString":      42.42,
  1108  		"SliceUint8ToString": []uint8("foo"),
  1109  		"StringToSliceUint8": "foo",
  1110  		"ArrayUint8ToString": [3]uint8{'f', 'o', 'o'},
  1111  		"StringToInt":        "42",
  1112  		"StringToUint":       "42",
  1113  		"StringToBool":       "1",
  1114  		"StringToFloat":      "42.42",
  1115  		"StringToStrSlice":   "A",
  1116  		"StringToIntSlice":   "42",
  1117  		"StringToStrArray":   "A",
  1118  		"StringToIntArray":   "42",
  1119  		"SliceToMap":         []interface{}{},
  1120  		"MapToSlice":         map[string]interface{}{},
  1121  		"ArrayToMap":         []interface{}{},
  1122  		"MapToArray":         map[string]interface{}{},
  1123  	}
  1124  
  1125  	expectedResultStrict := TypeConversionResult{
  1126  		IntToFloat:  42.0,
  1127  		IntToUint:   42,
  1128  		UintToInt:   42,
  1129  		UintToFloat: 42,
  1130  		BoolToInt:   0,
  1131  		BoolToUint:  0,
  1132  		BoolToFloat: 0,
  1133  		FloatToInt:  42,
  1134  		FloatToUint: 42,
  1135  	}
  1136  
  1137  	expectedResultWeak := TypeConversionResult{
  1138  		IntToFloat:         42.0,
  1139  		IntToUint:          42,
  1140  		IntToBool:          true,
  1141  		IntToString:        "42",
  1142  		UintToInt:          42,
  1143  		UintToFloat:        42,
  1144  		UintToBool:         true,
  1145  		UintToString:       "42",
  1146  		BoolToInt:          1,
  1147  		BoolToUint:         1,
  1148  		BoolToFloat:        1,
  1149  		BoolToString:       "1",
  1150  		FloatToInt:         42,
  1151  		FloatToUint:        42,
  1152  		FloatToBool:        true,
  1153  		FloatToString:      "42.42",
  1154  		SliceUint8ToString: "foo",
  1155  		StringToSliceUint8: []byte("foo"),
  1156  		ArrayUint8ToString: "foo",
  1157  		StringToInt:        42,
  1158  		StringToUint:       42,
  1159  		StringToBool:       true,
  1160  		StringToFloat:      42.42,
  1161  		StringToStrSlice:   []string{"A"},
  1162  		StringToIntSlice:   []int{42},
  1163  		StringToStrArray:   [1]string{"A"},
  1164  		StringToIntArray:   [1]int{42},
  1165  		SliceToMap:         map[string]interface{}{},
  1166  		MapToSlice:         []interface{}{},
  1167  		ArrayToMap:         map[string]interface{}{},
  1168  		MapToArray:         [1]interface{}{},
  1169  	}
  1170  
  1171  	// Test strict type conversion
  1172  	var resultStrict TypeConversionResult
  1173  	err := Decode(input, &resultStrict)
  1174  	if err == nil {
  1175  		t.Errorf("should return an error")
  1176  	}
  1177  	if !reflect.DeepEqual(resultStrict, expectedResultStrict) {
  1178  		t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict)
  1179  	}
  1180  
  1181  	// Test weak type conversion
  1182  	var decoder *Decoder
  1183  	var resultWeak TypeConversionResult
  1184  
  1185  	config := &Config{
  1186  		WeakType: true,
  1187  		Result:   &resultWeak,
  1188  	}
  1189  
  1190  	decoder, err = NewDecoder(config)
  1191  	if err != nil {
  1192  		t.Fatalf("err: %s", err)
  1193  	}
  1194  
  1195  	err = decoder.Decode(input)
  1196  	if err != nil {
  1197  		t.Fatalf("got an err: %s", err)
  1198  	}
  1199  
  1200  	if !reflect.DeepEqual(resultWeak, expectedResultWeak) {
  1201  		t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak)
  1202  	}
  1203  }
  1204  
  1205  func TestDecoder_ErrorUnused(t *testing.T) {
  1206  	t.Parallel()
  1207  
  1208  	input := map[string]interface{}{
  1209  		"vstring": "hello",
  1210  		"foo":     "bar",
  1211  	}
  1212  
  1213  	var result Basic
  1214  	config := &Config{
  1215  		ErrorUnused: true,
  1216  		Result:      &result,
  1217  	}
  1218  
  1219  	decoder, err := NewDecoder(config)
  1220  	if err != nil {
  1221  		t.Fatalf("err: %s", err)
  1222  	}
  1223  
  1224  	err = decoder.Decode(input)
  1225  	if err == nil {
  1226  		t.Fatal("expected error")
  1227  	}
  1228  }
  1229  
  1230  func TestDecoder_ErrorUnused_NotSetable(t *testing.T) {
  1231  	t.Parallel()
  1232  
  1233  	// lowercase vsilent is unexported and cannot be set
  1234  	input := map[string]interface{}{
  1235  		"vsilent": "false",
  1236  	}
  1237  
  1238  	var result Basic
  1239  	config := &Config{
  1240  		ErrorUnused: true,
  1241  		Result:      &result,
  1242  	}
  1243  
  1244  	decoder, err := NewDecoder(config)
  1245  	if err != nil {
  1246  		t.Fatalf("err: %s", err)
  1247  	}
  1248  
  1249  	err = decoder.Decode(input)
  1250  	if err == nil {
  1251  		t.Fatal("expected error")
  1252  	}
  1253  }
  1254  
  1255  func TestMap(t *testing.T) {
  1256  	t.Parallel()
  1257  
  1258  	input := map[string]interface{}{
  1259  		"vfoo": "foo",
  1260  		"vother": map[interface{}]interface{}{
  1261  			"foo": "foo",
  1262  			"bar": "bar",
  1263  		},
  1264  	}
  1265  
  1266  	var result Map
  1267  	err := Decode(input, &result)
  1268  	if err != nil {
  1269  		t.Fatalf("got an error: %s", err)
  1270  	}
  1271  
  1272  	if result.Vfoo != "foo" {
  1273  		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
  1274  	}
  1275  
  1276  	if result.Vother == nil {
  1277  		t.Fatal("vother should not be nil")
  1278  	}
  1279  
  1280  	if len(result.Vother) != 2 {
  1281  		t.Error("vother should have two items")
  1282  	}
  1283  
  1284  	if result.Vother["foo"] != "foo" {
  1285  		t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"])
  1286  	}
  1287  
  1288  	if result.Vother["bar"] != "bar" {
  1289  		t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"])
  1290  	}
  1291  }
  1292  
  1293  func TestMapMerge(t *testing.T) {
  1294  	t.Parallel()
  1295  
  1296  	input := map[string]interface{}{
  1297  		"vfoo": "foo",
  1298  		"vother": map[interface{}]interface{}{
  1299  			"foo": "foo",
  1300  			"bar": "bar",
  1301  		},
  1302  	}
  1303  
  1304  	var result Map
  1305  	result.Vother = map[string]string{"hello": "world"}
  1306  	err := Decode(input, &result)
  1307  	if err != nil {
  1308  		t.Fatalf("got an error: %s", err)
  1309  	}
  1310  
  1311  	if result.Vfoo != "foo" {
  1312  		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
  1313  	}
  1314  
  1315  	expected := map[string]string{
  1316  		"foo":   "foo",
  1317  		"bar":   "bar",
  1318  		"hello": "world",
  1319  	}
  1320  	if !reflect.DeepEqual(result.Vother, expected) {
  1321  		t.Errorf("bad: %#v", result.Vother)
  1322  	}
  1323  }
  1324  
  1325  func TestMapOfStruct(t *testing.T) {
  1326  	t.Parallel()
  1327  
  1328  	input := map[string]interface{}{
  1329  		"value": map[string]interface{}{
  1330  			"foo": map[string]string{"vstring": "one"},
  1331  			"bar": map[string]string{"vstring": "two"},
  1332  		},
  1333  	}
  1334  
  1335  	var result MapOfStruct
  1336  	err := Decode(input, &result)
  1337  	if err != nil {
  1338  		t.Fatalf("got an err: %s", err)
  1339  	}
  1340  
  1341  	if result.Value == nil {
  1342  		t.Fatal("value should not be nil")
  1343  	}
  1344  
  1345  	if len(result.Value) != 2 {
  1346  		t.Error("value should have two items")
  1347  	}
  1348  
  1349  	if result.Value["foo"].Vstring != "one" {
  1350  		t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring)
  1351  	}
  1352  
  1353  	if result.Value["bar"].Vstring != "two" {
  1354  		t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring)
  1355  	}
  1356  }
  1357  
  1358  func TestNestedType(t *testing.T) {
  1359  	t.Parallel()
  1360  
  1361  	input := map[string]interface{}{
  1362  		"vfoo": "foo",
  1363  		"vbar": map[string]interface{}{
  1364  			"vstring": "foo",
  1365  			"vint":    42,
  1366  			"vbool":   true,
  1367  		},
  1368  	}
  1369  
  1370  	var result Nested
  1371  	err := Decode(input, &result)
  1372  	if err != nil {
  1373  		t.Fatalf("got an err: %s", err.Error())
  1374  	}
  1375  
  1376  	if result.Vfoo != "foo" {
  1377  		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
  1378  	}
  1379  
  1380  	if result.Vbar.Vstring != "foo" {
  1381  		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
  1382  	}
  1383  
  1384  	if result.Vbar.Vint != 42 {
  1385  		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
  1386  	}
  1387  
  1388  	if result.Vbar.Vbool != true {
  1389  		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
  1390  	}
  1391  
  1392  	if result.Vbar.Vextra != "" {
  1393  		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
  1394  	}
  1395  }
  1396  
  1397  func TestNestedTypePointer(t *testing.T) {
  1398  	t.Parallel()
  1399  
  1400  	input := map[string]interface{}{
  1401  		"vfoo": "foo",
  1402  		"vbar": &map[string]interface{}{
  1403  			"vstring": "foo",
  1404  			"vint":    42,
  1405  			"vbool":   true,
  1406  		},
  1407  	}
  1408  
  1409  	var result NestedPointer
  1410  	err := Decode(input, &result)
  1411  	if err != nil {
  1412  		t.Fatalf("got an err: %s", err.Error())
  1413  	}
  1414  
  1415  	if result.Vfoo != "foo" {
  1416  		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
  1417  	}
  1418  
  1419  	if result.Vbar.Vstring != "foo" {
  1420  		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
  1421  	}
  1422  
  1423  	if result.Vbar.Vint != 42 {
  1424  		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
  1425  	}
  1426  
  1427  	if result.Vbar.Vbool != true {
  1428  		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
  1429  	}
  1430  
  1431  	if result.Vbar.Vextra != "" {
  1432  		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
  1433  	}
  1434  }
  1435  
  1436  // Test for issue #46.
  1437  func TestNestedTypeInterface(t *testing.T) {
  1438  	t.Parallel()
  1439  
  1440  	input := map[string]interface{}{
  1441  		"vfoo": "foo",
  1442  		"vbar": &map[string]interface{}{
  1443  			"vstring": "foo",
  1444  			"vint":    42,
  1445  			"vbool":   true,
  1446  
  1447  			"vdata": map[string]interface{}{
  1448  				"vstring": "bar",
  1449  			},
  1450  		},
  1451  	}
  1452  
  1453  	var result NestedPointer
  1454  	result.Vbar = new(Basic)
  1455  	result.Vbar.Vdata = new(Basic)
  1456  	err := Decode(input, &result)
  1457  	if err != nil {
  1458  		t.Fatalf("got an err: %s", err.Error())
  1459  	}
  1460  
  1461  	if result.Vfoo != "foo" {
  1462  		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
  1463  	}
  1464  
  1465  	if result.Vbar.Vstring != "foo" {
  1466  		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
  1467  	}
  1468  
  1469  	if result.Vbar.Vint != 42 {
  1470  		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
  1471  	}
  1472  
  1473  	if result.Vbar.Vbool != true {
  1474  		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
  1475  	}
  1476  
  1477  	if result.Vbar.Vextra != "" {
  1478  		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
  1479  	}
  1480  
  1481  	if result.Vbar.Vdata.(*Basic).Vstring != "bar" {
  1482  		t.Errorf("vstring value should be 'bar': %#v", result.Vbar.Vdata.(*Basic).Vstring)
  1483  	}
  1484  }
  1485  
  1486  func TestSlice(t *testing.T) {
  1487  	t.Parallel()
  1488  
  1489  	inputStringSlice := map[string]interface{}{
  1490  		"vfoo": "foo",
  1491  		"vbar": []string{"foo", "bar", "baz"},
  1492  	}
  1493  
  1494  	inputStringSlicePointer := map[string]interface{}{
  1495  		"vfoo": "foo",
  1496  		"vbar": &[]string{"foo", "bar", "baz"},
  1497  	}
  1498  
  1499  	outputStringSlice := &Slice{
  1500  		"foo",
  1501  		[]string{"foo", "bar", "baz"},
  1502  	}
  1503  
  1504  	testSliceInput(t, inputStringSlice, outputStringSlice)
  1505  	testSliceInput(t, inputStringSlicePointer, outputStringSlice)
  1506  }
  1507  
  1508  func TestInvalidSlice(t *testing.T) {
  1509  	t.Parallel()
  1510  
  1511  	input := map[string]interface{}{
  1512  		"vfoo": "foo",
  1513  		"vbar": 42,
  1514  	}
  1515  
  1516  	result := Slice{}
  1517  	err := Decode(input, &result)
  1518  	if err == nil {
  1519  		t.Errorf("expected failure")
  1520  	}
  1521  }
  1522  
  1523  func TestSliceOfStruct(t *testing.T) {
  1524  	t.Parallel()
  1525  
  1526  	input := map[string]interface{}{
  1527  		"value": []map[string]interface{}{
  1528  			{"vstring": "one"},
  1529  			{"vstring": "two"},
  1530  		},
  1531  	}
  1532  
  1533  	var result SliceOfStruct
  1534  	err := Decode(input, &result)
  1535  	if err != nil {
  1536  		t.Fatalf("got unexpected error: %s", err)
  1537  	}
  1538  
  1539  	if len(result.Value) != 2 {
  1540  		t.Fatalf("expected two values, got %d", len(result.Value))
  1541  	}
  1542  
  1543  	if result.Value[0].Vstring != "one" {
  1544  		t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
  1545  	}
  1546  
  1547  	if result.Value[1].Vstring != "two" {
  1548  		t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
  1549  	}
  1550  }
  1551  
  1552  func TestSliceCornerCases(t *testing.T) {
  1553  	t.Parallel()
  1554  
  1555  	// Input with a map with zero values
  1556  	input := map[string]interface{}{}
  1557  	var resultWeak []Basic
  1558  
  1559  	err := Decode(input, &resultWeak, WithWeakType(true))
  1560  	if err != nil {
  1561  		t.Fatalf("got unexpected error: %s", err)
  1562  	}
  1563  
  1564  	if len(resultWeak) != 0 {
  1565  		t.Errorf("length should be 0")
  1566  	}
  1567  	// Input with more values
  1568  	input = map[string]interface{}{
  1569  		"Vstring": "foo",
  1570  	}
  1571  
  1572  	resultWeak = nil
  1573  	err = Decode(input, &resultWeak, WithWeakType(true))
  1574  	if err != nil {
  1575  		t.Fatalf("got unexpected error: %s", err)
  1576  	}
  1577  
  1578  	if resultWeak[0].Vstring != "foo" {
  1579  		t.Errorf("value does not match")
  1580  	}
  1581  }
  1582  
  1583  func TestSliceToMap(t *testing.T) {
  1584  	t.Parallel()
  1585  
  1586  	input := []map[string]interface{}{
  1587  		{
  1588  			"foo": "bar",
  1589  		},
  1590  		{
  1591  			"bar": "baz",
  1592  		},
  1593  	}
  1594  
  1595  	var result map[string]interface{}
  1596  	err := Decode(input, &result, WithWeakType(true))
  1597  	if err != nil {
  1598  		t.Fatalf("got an error: %s", err)
  1599  	}
  1600  
  1601  	expected := map[string]interface{}{
  1602  		"foo": "bar",
  1603  		"bar": "baz",
  1604  	}
  1605  	if !reflect.DeepEqual(result, expected) {
  1606  		t.Errorf("bad: %#v", result)
  1607  	}
  1608  }
  1609  
  1610  func TestArray(t *testing.T) {
  1611  	t.Parallel()
  1612  
  1613  	inputStringArray := map[string]interface{}{
  1614  		"vfoo": "foo",
  1615  		"vbar": [2]string{"foo", "bar"},
  1616  	}
  1617  
  1618  	inputStringArrayPointer := map[string]interface{}{
  1619  		"vfoo": "foo",
  1620  		"vbar": &[2]string{"foo", "bar"},
  1621  	}
  1622  
  1623  	outputStringArray := &Array{
  1624  		"foo",
  1625  		[2]string{"foo", "bar"},
  1626  	}
  1627  
  1628  	testArrayInput(t, inputStringArray, outputStringArray)
  1629  	testArrayInput(t, inputStringArrayPointer, outputStringArray)
  1630  }
  1631  
  1632  func TestInvalidArray(t *testing.T) {
  1633  	t.Parallel()
  1634  
  1635  	input := map[string]interface{}{
  1636  		"vfoo": "foo",
  1637  		"vbar": 42,
  1638  	}
  1639  
  1640  	result := Array{}
  1641  	err := Decode(input, &result)
  1642  	if err == nil {
  1643  		t.Errorf("expected failure")
  1644  	}
  1645  }
  1646  
  1647  func TestArrayOfStruct(t *testing.T) {
  1648  	t.Parallel()
  1649  
  1650  	input := map[string]interface{}{
  1651  		"value": []map[string]interface{}{
  1652  			{"vstring": "one"},
  1653  			{"vstring": "two"},
  1654  		},
  1655  	}
  1656  
  1657  	var result ArrayOfStruct
  1658  	err := Decode(input, &result)
  1659  	if err != nil {
  1660  		t.Fatalf("got unexpected error: %s", err)
  1661  	}
  1662  
  1663  	if len(result.Value) != 2 {
  1664  		t.Fatalf("expected two values, got %d", len(result.Value))
  1665  	}
  1666  
  1667  	if result.Value[0].Vstring != "one" {
  1668  		t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
  1669  	}
  1670  
  1671  	if result.Value[1].Vstring != "two" {
  1672  		t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
  1673  	}
  1674  }
  1675  
  1676  func TestArrayToMap(t *testing.T) {
  1677  	t.Parallel()
  1678  
  1679  	input := []map[string]interface{}{
  1680  		{
  1681  			"foo": "bar",
  1682  		},
  1683  		{
  1684  			"bar": "baz",
  1685  		},
  1686  	}
  1687  
  1688  	var result map[string]interface{}
  1689  	err := Decode(input, &result, WithWeakType(true))
  1690  	if err != nil {
  1691  		t.Fatalf("got an error: %s", err)
  1692  	}
  1693  
  1694  	expected := map[string]interface{}{
  1695  		"foo": "bar",
  1696  		"bar": "baz",
  1697  	}
  1698  	if !reflect.DeepEqual(result, expected) {
  1699  		t.Errorf("bad: %#v", result)
  1700  	}
  1701  }
  1702  
  1703  func TestDecodeTable(t *testing.T) {
  1704  	t.Parallel()
  1705  
  1706  	// We need to make new types so that we don't get the short-circuit
  1707  	// copy functionality. We want to test the deep copying functionality.
  1708  	type BasicCopy Basic
  1709  	type NestedPointerCopy NestedPointer
  1710  	type MapCopy Map
  1711  
  1712  	tests := []struct {
  1713  		name    string
  1714  		in      interface{}
  1715  		target  interface{}
  1716  		out     interface{}
  1717  		wantErr bool
  1718  	}{
  1719  		{
  1720  			"basic struct input",
  1721  			&Basic{
  1722  				Vstring: "vstring",
  1723  				Vint:    2,
  1724  				Vint8:   2,
  1725  				Vint16:  2,
  1726  				Vint32:  2,
  1727  				Vint64:  2,
  1728  				Vuint:   3,
  1729  				Vbool:   true,
  1730  				Vfloat:  4.56,
  1731  				Vextra:  "vextra",
  1732  				vsilent: true,
  1733  				Vdata:   []byte("data"),
  1734  			},
  1735  			&map[string]interface{}{},
  1736  			&map[string]interface{}{
  1737  				"Vstring":     "vstring",
  1738  				"Vint":        2,
  1739  				"Vint8":       int8(2),
  1740  				"Vint16":      int16(2),
  1741  				"Vint32":      int32(2),
  1742  				"Vint64":      int64(2),
  1743  				"Vuint":       uint(3),
  1744  				"Vbool":       true,
  1745  				"Vfloat":      4.56,
  1746  				"Vextra":      "vextra",
  1747  				"Vdata":       []byte("data"),
  1748  				"VjsonInt":    0,
  1749  				"VjsonUint":   uint(0),
  1750  				"VjsonFloat":  0.0,
  1751  				"VjsonNumber": json.Number(""),
  1752  			},
  1753  			false,
  1754  		},
  1755  		{
  1756  			"embedded struct input",
  1757  			&Embedded{
  1758  				Vunique: "vunique",
  1759  				Basic: Basic{
  1760  					Vstring: "vstring",
  1761  					Vint:    2,
  1762  					Vint8:   2,
  1763  					Vint16:  2,
  1764  					Vint32:  2,
  1765  					Vint64:  2,
  1766  					Vuint:   3,
  1767  					Vbool:   true,
  1768  					Vfloat:  4.56,
  1769  					Vextra:  "vextra",
  1770  					vsilent: true,
  1771  					Vdata:   []byte("data"),
  1772  				},
  1773  			},
  1774  			&map[string]interface{}{},
  1775  			&map[string]interface{}{
  1776  				"Vunique": "vunique",
  1777  				"Basic": map[string]interface{}{
  1778  					"Vstring":     "vstring",
  1779  					"Vint":        2,
  1780  					"Vint8":       int8(2),
  1781  					"Vint16":      int16(2),
  1782  					"Vint32":      int32(2),
  1783  					"Vint64":      int64(2),
  1784  					"Vuint":       uint(3),
  1785  					"Vbool":       true,
  1786  					"Vfloat":      4.56,
  1787  					"Vextra":      "vextra",
  1788  					"Vdata":       []byte("data"),
  1789  					"VjsonInt":    0,
  1790  					"VjsonUint":   uint(0),
  1791  					"VjsonFloat":  0.0,
  1792  					"VjsonNumber": json.Number(""),
  1793  				},
  1794  			},
  1795  			false,
  1796  		},
  1797  		{
  1798  			"struct => struct",
  1799  			&Basic{
  1800  				Vstring: "vstring",
  1801  				Vint:    2,
  1802  				Vuint:   3,
  1803  				Vbool:   true,
  1804  				Vfloat:  4.56,
  1805  				Vextra:  "vextra",
  1806  				Vdata:   []byte("data"),
  1807  				vsilent: true,
  1808  			},
  1809  			&BasicCopy{},
  1810  			&BasicCopy{
  1811  				Vstring: "vstring",
  1812  				Vint:    2,
  1813  				Vuint:   3,
  1814  				Vbool:   true,
  1815  				Vfloat:  4.56,
  1816  				Vextra:  "vextra",
  1817  				Vdata:   []byte("data"),
  1818  			},
  1819  			false,
  1820  		},
  1821  		{
  1822  			"struct => struct with pointers",
  1823  			&NestedPointer{
  1824  				Vfoo: "hello",
  1825  				Vbar: nil,
  1826  			},
  1827  			&NestedPointerCopy{},
  1828  			&NestedPointerCopy{
  1829  				Vfoo: "hello",
  1830  			},
  1831  			false,
  1832  		},
  1833  		{
  1834  			"basic pointer to non-pointer",
  1835  			&BasicPointer{
  1836  				Vstring: stringPtr("vstring"),
  1837  				Vint:    intPtr(2),
  1838  				Vuint:   uintPtr(3),
  1839  				Vbool:   boolPtr(true),
  1840  				Vfloat:  floatPtr(4.56),
  1841  				Vdata:   interfacePtr([]byte("data")),
  1842  			},
  1843  			&Basic{},
  1844  			&Basic{
  1845  				Vstring: "vstring",
  1846  				Vint:    2,
  1847  				Vuint:   3,
  1848  				Vbool:   true,
  1849  				Vfloat:  4.56,
  1850  				Vdata:   []byte("data"),
  1851  			},
  1852  			false,
  1853  		},
  1854  		{
  1855  			"slice non-pointer to pointer",
  1856  			&Slice{},
  1857  			&SlicePointer{},
  1858  			&SlicePointer{},
  1859  			false,
  1860  		},
  1861  		{
  1862  			"slice non-pointer to pointer, zero field",
  1863  			&Slice{},
  1864  			&SlicePointer{
  1865  				Vbar: &[]string{"yo"},
  1866  			},
  1867  			&SlicePointer{},
  1868  			false,
  1869  		},
  1870  		{
  1871  			"slice to slice alias",
  1872  			&Slice{},
  1873  			&SliceOfAlias{},
  1874  			&SliceOfAlias{},
  1875  			false,
  1876  		},
  1877  		{
  1878  			"nil map to map",
  1879  			&Map{},
  1880  			&MapCopy{},
  1881  			&MapCopy{},
  1882  			false,
  1883  		},
  1884  		{
  1885  			"nil map to non-empty map",
  1886  			&Map{},
  1887  			&MapCopy{Vother: map[string]string{"foo": "bar"}},
  1888  			&MapCopy{},
  1889  			false,
  1890  		},
  1891  
  1892  		{
  1893  			"slice input - should error",
  1894  			[]string{"foo", "bar"},
  1895  			&map[string]interface{}{},
  1896  			&map[string]interface{}{},
  1897  			true,
  1898  		},
  1899  		{
  1900  			"struct with slice property",
  1901  			&Slice{
  1902  				Vfoo: "vfoo",
  1903  				Vbar: []string{"foo", "bar"},
  1904  			},
  1905  			&map[string]interface{}{},
  1906  			&map[string]interface{}{
  1907  				"Vfoo": "vfoo",
  1908  				"Vbar": []string{"foo", "bar"},
  1909  			},
  1910  			false,
  1911  		},
  1912  		{
  1913  			"struct with empty slice",
  1914  			&map[string]interface{}{
  1915  				"Vbar": []string{},
  1916  			},
  1917  			&Slice{},
  1918  			&Slice{
  1919  				Vbar: []string{},
  1920  			},
  1921  			false,
  1922  		},
  1923  		{
  1924  			"struct with slice of struct property",
  1925  			&SliceOfStruct{
  1926  				Value: []Basic{
  1927  					{
  1928  						Vstring: "vstring",
  1929  						Vint:    2,
  1930  						Vuint:   3,
  1931  						Vbool:   true,
  1932  						Vfloat:  4.56,
  1933  						Vextra:  "vextra",
  1934  						vsilent: true,
  1935  						Vdata:   []byte("data"),
  1936  					},
  1937  				},
  1938  			},
  1939  			&map[string]interface{}{},
  1940  			&map[string]interface{}{
  1941  				"Value": []Basic{
  1942  					{
  1943  						Vstring: "vstring",
  1944  						Vint:    2,
  1945  						Vuint:   3,
  1946  						Vbool:   true,
  1947  						Vfloat:  4.56,
  1948  						Vextra:  "vextra",
  1949  						vsilent: true,
  1950  						Vdata:   []byte("data"),
  1951  					},
  1952  				},
  1953  			},
  1954  			false,
  1955  		},
  1956  		{
  1957  			"struct with map property",
  1958  			&Map{
  1959  				Vfoo:   "vfoo",
  1960  				Vother: map[string]string{"vother": "vother"},
  1961  			},
  1962  			&map[string]interface{}{},
  1963  			&map[string]interface{}{
  1964  				"Vfoo": "vfoo",
  1965  				"Vother": map[string]string{
  1966  					"vother": "vother",
  1967  				},
  1968  			},
  1969  			false,
  1970  		},
  1971  		{
  1972  			"tagged struct",
  1973  			&Tagged{
  1974  				Extra: "extra",
  1975  				Value: "value",
  1976  			},
  1977  			&map[string]string{},
  1978  			&map[string]string{
  1979  				"bar": "extra",
  1980  				"foo": "value",
  1981  			},
  1982  			false,
  1983  		},
  1984  		{
  1985  			"omit tag struct",
  1986  			&struct {
  1987  				Value string `mapstruct:"value"`
  1988  				Omit  string `mapstruct:"-"`
  1989  			}{
  1990  				Value: "value",
  1991  				Omit:  "omit",
  1992  			},
  1993  			&map[string]string{},
  1994  			&map[string]string{
  1995  				"value": "value",
  1996  			},
  1997  			false,
  1998  		},
  1999  		{
  2000  			"decode to wrong map type",
  2001  			&struct {
  2002  				Value string
  2003  			}{
  2004  				Value: "string",
  2005  			},
  2006  			&map[string]int{},
  2007  			&map[string]int{},
  2008  			true,
  2009  		},
  2010  		{
  2011  			"remainder",
  2012  			map[string]interface{}{
  2013  				"A": "hello",
  2014  				"B": "goodbye",
  2015  				"C": "yo",
  2016  			},
  2017  			&Remainder{},
  2018  			&Remainder{
  2019  				A: "hello",
  2020  				Extra: map[string]interface{}{
  2021  					"B": "goodbye",
  2022  					"C": "yo",
  2023  				},
  2024  			},
  2025  			false,
  2026  		},
  2027  		{
  2028  			"remainder with no extra",
  2029  			map[string]interface{}{
  2030  				"A": "hello",
  2031  			},
  2032  			&Remainder{},
  2033  			&Remainder{
  2034  				A:     "hello",
  2035  				Extra: nil,
  2036  			},
  2037  			false,
  2038  		},
  2039  		{
  2040  			"struct with omitempty tag return non-empty values",
  2041  			&struct {
  2042  				VisibleField interface{} `mapstruct:"visible"`
  2043  				OmitField    interface{} `mapstruct:"omittable,omitempty"`
  2044  			}{
  2045  				VisibleField: nil,
  2046  				OmitField:    "string",
  2047  			},
  2048  			&map[string]interface{}{},
  2049  			&map[string]interface{}{"visible": nil, "omittable": "string"},
  2050  			false,
  2051  		},
  2052  		{
  2053  			"struct with omitempty tag ignore empty values",
  2054  			&struct {
  2055  				VisibleField interface{} `mapstruct:"visible"`
  2056  				OmitField    interface{} `mapstruct:"omittable,omitempty"`
  2057  			}{
  2058  				VisibleField: nil,
  2059  				OmitField:    nil,
  2060  			},
  2061  			&map[string]interface{}{},
  2062  			&map[string]interface{}{"visible": nil},
  2063  			false,
  2064  		},
  2065  	}
  2066  
  2067  	for _, tt := range tests {
  2068  		t.Run(tt.name, func(t *testing.T) {
  2069  			if err := Decode(tt.in, tt.target); (err != nil) != tt.wantErr {
  2070  				t.Fatalf("%q: TestMapOutputForStructuredInputs() unexpected error: %s", tt.name, err)
  2071  			}
  2072  
  2073  			if !reflect.DeepEqual(tt.out, tt.target) {
  2074  				t.Fatalf("%q: TestMapOutputForStructuredInputs() expected: %#v, got: %#v", tt.name, tt.out, tt.target)
  2075  			}
  2076  		})
  2077  	}
  2078  }
  2079  
  2080  func TestInvalidType(t *testing.T) {
  2081  	t.Parallel()
  2082  
  2083  	input := map[string]interface{}{
  2084  		"vstring": 42,
  2085  	}
  2086  
  2087  	var result Basic
  2088  	err := Decode(input, &result)
  2089  	if err == nil {
  2090  		t.Fatal("error should exist")
  2091  	}
  2092  
  2093  	derr, ok := err.(*Error)
  2094  	if !ok {
  2095  		t.Fatalf("error should be kind of Error, instead: %#v", err)
  2096  	}
  2097  
  2098  	if derr.Errors[0] !=
  2099  		"'Vstring' expected type 'string', got unconvertible type 'int', value: '42'" {
  2100  		t.Errorf("got unexpected error: %s", err)
  2101  	}
  2102  
  2103  	inputNegIntUint := map[string]interface{}{
  2104  		"vuint": -42,
  2105  	}
  2106  
  2107  	err = Decode(inputNegIntUint, &result)
  2108  	if err == nil {
  2109  		t.Fatal("error should exist")
  2110  	}
  2111  
  2112  	derr, ok = err.(*Error)
  2113  	if !ok {
  2114  		t.Fatalf("error should be kind of Error, instead: %#v", err)
  2115  	}
  2116  
  2117  	if derr.Errors[0] != "cannot parse 'Vuint', -42 overflows uint" {
  2118  		t.Errorf("got unexpected error: %s", err)
  2119  	}
  2120  
  2121  	inputNegFloatUint := map[string]interface{}{
  2122  		"vuint": -42.0,
  2123  	}
  2124  
  2125  	err = Decode(inputNegFloatUint, &result)
  2126  	if err == nil {
  2127  		t.Fatal("error should exist")
  2128  	}
  2129  
  2130  	derr, ok = err.(*Error)
  2131  	if !ok {
  2132  		t.Fatalf("error should be kind of Error, instead: %#v", err)
  2133  	}
  2134  
  2135  	if derr.Errors[0] != "cannot parse 'Vuint', -42.000000 overflows uint" {
  2136  		t.Errorf("got unexpected error: %s", err)
  2137  	}
  2138  }
  2139  
  2140  func TestDecodeMetadata(t *testing.T) {
  2141  	t.Parallel()
  2142  
  2143  	input := map[string]interface{}{
  2144  		"vfoo": "foo",
  2145  		"vbar": map[string]interface{}{
  2146  			"vstring": "foo",
  2147  			"Vuint":   42,
  2148  			"vsilent": "false",
  2149  			"foo":     "bar",
  2150  		},
  2151  		"bar": "nil",
  2152  	}
  2153  
  2154  	var md Metadata
  2155  	var result Nested
  2156  
  2157  	err := Decode(input, &result, WithMetadata(&md))
  2158  	if err != nil {
  2159  		t.Fatalf("err: %s", err.Error())
  2160  	}
  2161  
  2162  	expectedKeys := []string{"Vbar", "Vbar.Vstring", "Vbar.Vuint", "Vfoo"}
  2163  	sort.Strings(md.Keys)
  2164  	if !reflect.DeepEqual(md.Keys, expectedKeys) {
  2165  		t.Fatalf("bad keys: %#v", md.Keys)
  2166  	}
  2167  
  2168  	expectedUnused := []string{"Vbar.foo", "Vbar.vsilent", "bar"}
  2169  	sort.Strings(md.Unused)
  2170  	if !reflect.DeepEqual(md.Unused, expectedUnused) {
  2171  		t.Fatalf("bad unused: %#v", md.Unused)
  2172  	}
  2173  }
  2174  
  2175  func TestMetadata(t *testing.T) {
  2176  	t.Parallel()
  2177  
  2178  	type testResult struct {
  2179  		Vfoo string
  2180  		Vbar BasicPointer
  2181  	}
  2182  
  2183  	input := map[string]interface{}{
  2184  		"vfoo": "foo",
  2185  		"vbar": map[string]interface{}{
  2186  			"vstring": "foo",
  2187  			"Vuint":   42,
  2188  			"vsilent": "false",
  2189  			"foo":     "bar",
  2190  		},
  2191  		"bar": "nil",
  2192  	}
  2193  
  2194  	var md Metadata
  2195  	var result testResult
  2196  	config := &Config{
  2197  		Metadata: &md,
  2198  		Result:   &result,
  2199  	}
  2200  
  2201  	decoder, err := NewDecoder(config)
  2202  	if err != nil {
  2203  		t.Fatalf("err: %s", err)
  2204  	}
  2205  
  2206  	err = decoder.Decode(input)
  2207  	if err != nil {
  2208  		t.Fatalf("err: %s", err.Error())
  2209  	}
  2210  
  2211  	expectedKeys := []string{"Vbar", "Vbar.Vstring", "Vbar.Vuint", "Vfoo"}
  2212  	sort.Strings(md.Keys)
  2213  	if !reflect.DeepEqual(md.Keys, expectedKeys) {
  2214  		t.Fatalf("bad keys: %#v", md.Keys)
  2215  	}
  2216  
  2217  	expectedUnused := []string{"Vbar.foo", "Vbar.vsilent", "bar"}
  2218  	sort.Strings(md.Unused)
  2219  	if !reflect.DeepEqual(md.Unused, expectedUnused) {
  2220  		t.Fatalf("bad unused: %#v", md.Unused)
  2221  	}
  2222  }
  2223  
  2224  func TestMetadata_Embedded(t *testing.T) {
  2225  	t.Parallel()
  2226  
  2227  	input := map[string]interface{}{
  2228  		"vstring": "foo",
  2229  		"vunique": "bar",
  2230  	}
  2231  
  2232  	var md Metadata
  2233  	var result EmbeddedSquash
  2234  	config := &Config{
  2235  		Metadata: &md,
  2236  		Result:   &result,
  2237  	}
  2238  
  2239  	decoder, err := NewDecoder(config)
  2240  	if err != nil {
  2241  		t.Fatalf("err: %s", err)
  2242  	}
  2243  
  2244  	err = decoder.Decode(input)
  2245  	if err != nil {
  2246  		t.Fatalf("err: %s", err.Error())
  2247  	}
  2248  
  2249  	expectedKeys := []string{"Vstring", "Vunique"}
  2250  
  2251  	sort.Strings(md.Keys)
  2252  	if !reflect.DeepEqual(md.Keys, expectedKeys) {
  2253  		t.Fatalf("bad keys: %#v", md.Keys)
  2254  	}
  2255  
  2256  	expectedUnused := []string{}
  2257  	if !reflect.DeepEqual(md.Unused, expectedUnused) {
  2258  		t.Fatalf("bad unused: %#v", md.Unused)
  2259  	}
  2260  }
  2261  
  2262  func TestNonPtrValue(t *testing.T) {
  2263  	t.Parallel()
  2264  
  2265  	err := Decode(map[string]interface{}{}, Basic{})
  2266  	if err == nil {
  2267  		t.Fatal("error should exist")
  2268  	}
  2269  
  2270  	if err.Error() != "result must be a pointer" {
  2271  		t.Errorf("got unexpected error: %s", err)
  2272  	}
  2273  }
  2274  
  2275  func TestTagged(t *testing.T) {
  2276  	t.Parallel()
  2277  
  2278  	input := map[string]interface{}{
  2279  		"foo": "bar",
  2280  		"bar": "value",
  2281  	}
  2282  
  2283  	var result Tagged
  2284  	err := Decode(input, &result)
  2285  	if err != nil {
  2286  		t.Fatalf("unexpected error: %s", err)
  2287  	}
  2288  
  2289  	if result.Value != "bar" {
  2290  		t.Errorf("value should be 'bar', got: %#v", result.Value)
  2291  	}
  2292  
  2293  	if result.Extra != "value" {
  2294  		t.Errorf("extra should be 'value', got: %#v", result.Extra)
  2295  	}
  2296  }
  2297  
  2298  func TestWeakDecode(t *testing.T) {
  2299  	t.Parallel()
  2300  
  2301  	input := map[string]interface{}{
  2302  		"foo": "4",
  2303  		"bar": "value",
  2304  	}
  2305  
  2306  	var result struct {
  2307  		Foo int
  2308  		Bar string
  2309  	}
  2310  
  2311  	if err := Decode(input, &result, WithWeakType(true)); err != nil {
  2312  		t.Fatalf("err: %s", err)
  2313  	}
  2314  	if result.Foo != 4 {
  2315  		t.Fatalf("bad: %#v", result)
  2316  	}
  2317  	if result.Bar != "value" {
  2318  		t.Fatalf("bad: %#v", result)
  2319  	}
  2320  }
  2321  
  2322  func TestWeakDecodeMetadata(t *testing.T) {
  2323  	t.Parallel()
  2324  
  2325  	input := map[string]interface{}{
  2326  		"foo":        "4",
  2327  		"bar":        "value",
  2328  		"unused":     "value",
  2329  		"unexported": "value",
  2330  	}
  2331  
  2332  	var md Metadata
  2333  	var result struct {
  2334  		Foo        int
  2335  		Bar        string
  2336  		unexported string
  2337  	}
  2338  
  2339  	if err := Decode(input, &result, WithWeakType(true), WithMetadata(&md)); err != nil {
  2340  		t.Fatalf("err: %s", err)
  2341  	}
  2342  	if result.Foo != 4 {
  2343  		t.Fatalf("bad: %#v", result)
  2344  	}
  2345  	if result.Bar != "value" {
  2346  		t.Fatalf("bad: %#v", result)
  2347  	}
  2348  
  2349  	expectedKeys := []string{"Bar", "Foo"}
  2350  	sort.Strings(md.Keys)
  2351  	if !reflect.DeepEqual(md.Keys, expectedKeys) {
  2352  		t.Fatalf("bad keys: %#v", md.Keys)
  2353  	}
  2354  
  2355  	expectedUnused := []string{"unexported", "unused"}
  2356  	sort.Strings(md.Unused)
  2357  	if !reflect.DeepEqual(md.Unused, expectedUnused) {
  2358  		t.Fatalf("bad unused: %#v", md.Unused)
  2359  	}
  2360  }
  2361  
  2362  func TestDecode_StructTaggedWithOmitempty_OmitEmptyValues(t *testing.T) {
  2363  	t.Parallel()
  2364  
  2365  	input := &StructWithOmitEmpty{}
  2366  
  2367  	var emptySlice []interface{}
  2368  	var emptyMap map[string]interface{}
  2369  	var emptyNested *Nested
  2370  	expected := &map[string]interface{}{
  2371  		"visible-string": "",
  2372  		"visible-int":    0,
  2373  		"visible-float":  0.0,
  2374  		"visible-slice":  emptySlice,
  2375  		"visible-map":    emptyMap,
  2376  		"visible-nested": emptyNested,
  2377  	}
  2378  
  2379  	actual := &map[string]interface{}{}
  2380  	_ = Decode(input, actual)
  2381  
  2382  	if !reflect.DeepEqual(actual, expected) {
  2383  		t.Fatalf("Decode() expected: %#v, got: %#v", expected, actual)
  2384  	}
  2385  }
  2386  
  2387  func TestDecode_StructTaggedWithOmitempty_KeepNonEmptyValues(t *testing.T) {
  2388  	t.Parallel()
  2389  
  2390  	input := &StructWithOmitEmpty{
  2391  		VisibleStringField: "",
  2392  		OmitStringField:    "string",
  2393  		VisibleIntField:    0,
  2394  		OmitIntField:       1,
  2395  		VisibleFloatField:  0.0,
  2396  		OmitFloatField:     1.0,
  2397  		VisibleSliceField:  nil,
  2398  		OmitSliceField:     []interface{}{1},
  2399  		VisibleMapField:    nil,
  2400  		OmitMapField:       map[string]interface{}{"k": "v"},
  2401  		NestedField:        nil,
  2402  		OmitNestedField:    &Nested{},
  2403  	}
  2404  
  2405  	var emptySlice []interface{}
  2406  	var emptyMap map[string]interface{}
  2407  	var emptyNested *Nested
  2408  	expected := &map[string]interface{}{
  2409  		"visible-string":   "",
  2410  		"omittable-string": "string",
  2411  		"visible-int":      0,
  2412  		"omittable-int":    1,
  2413  		"visible-float":    0.0,
  2414  		"omittable-float":  1.0,
  2415  		"visible-slice":    emptySlice,
  2416  		"omittable-slice":  []interface{}{1},
  2417  		"visible-map":      emptyMap,
  2418  		"omittable-map":    map[string]interface{}{"k": "v"},
  2419  		"visible-nested":   emptyNested,
  2420  		"omittable-nested": &Nested{},
  2421  	}
  2422  
  2423  	actual := &map[string]interface{}{}
  2424  	_ = Decode(input, actual)
  2425  
  2426  	if !reflect.DeepEqual(actual, expected) {
  2427  		t.Fatalf("Decode() expected: %#v, got: %#v", expected, actual)
  2428  	}
  2429  }
  2430  
  2431  func TestDecode_mapToStruct(t *testing.T) {
  2432  	type Target struct {
  2433  		String    string
  2434  		StringPtr *string
  2435  	}
  2436  
  2437  	expected := Target{
  2438  		String: "hello",
  2439  	}
  2440  
  2441  	var target Target
  2442  	err := Decode(map[string]interface{}{
  2443  		"string":    "hello",
  2444  		"StringPtr": "goodbye",
  2445  	}, &target)
  2446  	if err != nil {
  2447  		t.Fatalf("got error: %s", err)
  2448  	}
  2449  
  2450  	// Pointers fail reflect test so do those manually
  2451  	if target.StringPtr == nil || *target.StringPtr != "goodbye" {
  2452  		t.Fatalf("bad: %#v", target)
  2453  	}
  2454  	target.StringPtr = nil
  2455  
  2456  	if !reflect.DeepEqual(target, expected) {
  2457  		t.Fatalf("bad: %#v", target)
  2458  	}
  2459  }
  2460  
  2461  func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
  2462  	var result Slice
  2463  	err := Decode(input, &result)
  2464  	if err != nil {
  2465  		t.Fatalf("got error: %s", err)
  2466  	}
  2467  
  2468  	if result.Vfoo != expected.Vfoo {
  2469  		t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
  2470  	}
  2471  
  2472  	if result.Vbar == nil {
  2473  		t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
  2474  	}
  2475  
  2476  	if len(result.Vbar) != len(expected.Vbar) {
  2477  		t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
  2478  	}
  2479  
  2480  	for i, v := range result.Vbar {
  2481  		if v != expected.Vbar[i] {
  2482  			t.Errorf(
  2483  				"Vbar[%d] should be '%#v', got '%#v'",
  2484  				i, expected.Vbar[i], v)
  2485  		}
  2486  	}
  2487  }
  2488  
  2489  func testArrayInput(t *testing.T, input map[string]interface{}, expected *Array) {
  2490  	var result Array
  2491  	err := Decode(input, &result)
  2492  	if err != nil {
  2493  		t.Fatalf("got error: %s", err)
  2494  	}
  2495  
  2496  	if result.Vfoo != expected.Vfoo {
  2497  		t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
  2498  	}
  2499  
  2500  	if result.Vbar == [2]string{} {
  2501  		t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
  2502  	}
  2503  
  2504  	if len(result.Vbar) != len(expected.Vbar) {
  2505  		t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
  2506  	}
  2507  
  2508  	for i, v := range result.Vbar {
  2509  		if v != expected.Vbar[i] {
  2510  			t.Errorf(
  2511  				"Vbar[%d] should be '%#v', got '%#v'",
  2512  				i, expected.Vbar[i], v)
  2513  		}
  2514  	}
  2515  }
  2516  
  2517  func stringPtr(v string) *string              { return &v }
  2518  func intPtr(v int) *int                       { return &v }
  2519  func uintPtr(v uint) *uint                    { return &v }
  2520  func boolPtr(v bool) *bool                    { return &v }
  2521  func floatPtr(v float64) *float64             { return &v }
  2522  func interfacePtr(v interface{}) *interface{} { return &v }