628 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			628 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
package mapstructure
 | 
						|
 | 
						|
import (
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// GH-1, GH-10, GH-96
 | 
						|
func TestDecode_NilValue(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
 | 
						|
	tests := []struct {
 | 
						|
		name       string
 | 
						|
		in         interface{}
 | 
						|
		target     interface{}
 | 
						|
		out        interface{}
 | 
						|
		metaKeys   []string
 | 
						|
		metaUnused []string
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			"all nil",
 | 
						|
			&map[string]interface{}{
 | 
						|
				"vfoo":   nil,
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "", Vother: nil},
 | 
						|
			[]string{"Vfoo", "Vother"},
 | 
						|
			[]string{},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"partial nil",
 | 
						|
			&map[string]interface{}{
 | 
						|
				"vfoo":   "baz",
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "baz", Vother: nil},
 | 
						|
			[]string{"Vfoo", "Vother"},
 | 
						|
			[]string{},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"partial decode",
 | 
						|
			&map[string]interface{}{
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "foo", Vother: nil},
 | 
						|
			[]string{"Vother"},
 | 
						|
			[]string{},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"unused values",
 | 
						|
			&map[string]interface{}{
 | 
						|
				"vbar":   "bar",
 | 
						|
				"vfoo":   nil,
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "", Vother: nil},
 | 
						|
			[]string{"Vfoo", "Vother"},
 | 
						|
			[]string{"vbar"},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"map interface all nil",
 | 
						|
			&map[interface{}]interface{}{
 | 
						|
				"vfoo":   nil,
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "", Vother: nil},
 | 
						|
			[]string{"Vfoo", "Vother"},
 | 
						|
			[]string{},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"map interface partial nil",
 | 
						|
			&map[interface{}]interface{}{
 | 
						|
				"vfoo":   "baz",
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "baz", Vother: nil},
 | 
						|
			[]string{"Vfoo", "Vother"},
 | 
						|
			[]string{},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"map interface partial decode",
 | 
						|
			&map[interface{}]interface{}{
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "foo", Vother: nil},
 | 
						|
			[]string{"Vother"},
 | 
						|
			[]string{},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"map interface unused values",
 | 
						|
			&map[interface{}]interface{}{
 | 
						|
				"vbar":   "bar",
 | 
						|
				"vfoo":   nil,
 | 
						|
				"vother": nil,
 | 
						|
			},
 | 
						|
			&Map{Vfoo: "foo", Vother: map[string]string{"foo": "bar"}},
 | 
						|
			&Map{Vfoo: "", Vother: nil},
 | 
						|
			[]string{"Vfoo", "Vother"},
 | 
						|
			[]string{"vbar"},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tc := range tests {
 | 
						|
		t.Run(tc.name, func(t *testing.T) {
 | 
						|
			config := &DecoderConfig{
 | 
						|
				Metadata:   new(Metadata),
 | 
						|
				Result:     tc.target,
 | 
						|
				ZeroFields: true,
 | 
						|
			}
 | 
						|
 | 
						|
			decoder, err := NewDecoder(config)
 | 
						|
			if err != nil {
 | 
						|
				t.Fatalf("should not error: %s", err)
 | 
						|
			}
 | 
						|
 | 
						|
			err = decoder.Decode(tc.in)
 | 
						|
			if err != nil {
 | 
						|
				t.Fatalf("should not error: %s", err)
 | 
						|
			}
 | 
						|
 | 
						|
			if !reflect.DeepEqual(tc.out, tc.target) {
 | 
						|
				t.Fatalf("%q: TestDecode_NilValue() expected: %#v, got: %#v", tc.name, tc.out, tc.target)
 | 
						|
			}
 | 
						|
 | 
						|
			if !reflect.DeepEqual(tc.metaKeys, config.Metadata.Keys) {
 | 
						|
				t.Fatalf("%q: Metadata.Keys mismatch expected: %#v, got: %#v", tc.name, tc.metaKeys, config.Metadata.Keys)
 | 
						|
			}
 | 
						|
 | 
						|
			if !reflect.DeepEqual(tc.metaUnused, config.Metadata.Unused) {
 | 
						|
				t.Fatalf("%q: Metadata.Unused mismatch expected: %#v, got: %#v", tc.name, tc.metaUnused, config.Metadata.Unused)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// #48
 | 
						|
func TestNestedTypePointerWithDefaults(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
 | 
						|
	input := map[string]interface{}{
 | 
						|
		"vfoo": "foo",
 | 
						|
		"vbar": map[string]interface{}{
 | 
						|
			"vstring": "foo",
 | 
						|
			"vint":    42,
 | 
						|
			"vbool":   true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	result := NestedPointer{
 | 
						|
		Vbar: &Basic{
 | 
						|
			Vuint: 42,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	err := Decode(input, &result)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("got an jderr: %s", err.Error())
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vfoo != "foo" {
 | 
						|
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vstring != "foo" {
 | 
						|
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vint != 42 {
 | 
						|
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vbool != true {
 | 
						|
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vextra != "" {
 | 
						|
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
 | 
						|
	}
 | 
						|
 | 
						|
	// this is the error
 | 
						|
	if result.Vbar.Vuint != 42 {
 | 
						|
		t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
type NestedSlice struct {
 | 
						|
	Vfoo   string
 | 
						|
	Vbars  []Basic
 | 
						|
	Vempty []Basic
 | 
						|
}
 | 
						|
 | 
						|
// #48
 | 
						|
func TestNestedTypeSliceWithDefaults(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
 | 
						|
	input := map[string]interface{}{
 | 
						|
		"vfoo": "foo",
 | 
						|
		"vbars": []map[string]interface{}{
 | 
						|
			{"vstring": "foo", "vint": 42, "vbool": true},
 | 
						|
			{"vint": 42, "vbool": true},
 | 
						|
		},
 | 
						|
		"vempty": []map[string]interface{}{
 | 
						|
			{"vstring": "foo", "vint": 42, "vbool": true},
 | 
						|
			{"vint": 42, "vbool": true},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	result := NestedSlice{
 | 
						|
		Vbars: []Basic{
 | 
						|
			{Vuint: 42},
 | 
						|
			{Vstring: "foo"},
 | 
						|
		},
 | 
						|
	}
 | 
						|
	err := Decode(input, &result)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("got an jderr: %s", err.Error())
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vfoo != "foo" {
 | 
						|
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbars[0].Vstring != "foo" {
 | 
						|
		t.Errorf("vstring value should be 'foo': %#v", result.Vbars[0].Vstring)
 | 
						|
	}
 | 
						|
	// this is the error
 | 
						|
	if result.Vbars[0].Vuint != 42 {
 | 
						|
		t.Errorf("vuint value should be 42: %#v", result.Vbars[0].Vuint)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// #48 workaround
 | 
						|
func TestNestedTypeWithDefaults(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
 | 
						|
	input := map[string]interface{}{
 | 
						|
		"vfoo": "foo",
 | 
						|
		"vbar": map[string]interface{}{
 | 
						|
			"vstring": "foo",
 | 
						|
			"vint":    42,
 | 
						|
			"vbool":   true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	result := Nested{
 | 
						|
		Vbar: Basic{
 | 
						|
			Vuint: 42,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	err := Decode(input, &result)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("got an jderr: %s", err.Error())
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vfoo != "foo" {
 | 
						|
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vstring != "foo" {
 | 
						|
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vint != 42 {
 | 
						|
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vbool != true {
 | 
						|
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
 | 
						|
	}
 | 
						|
 | 
						|
	if result.Vbar.Vextra != "" {
 | 
						|
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
 | 
						|
	}
 | 
						|
 | 
						|
	// this is the error
 | 
						|
	if result.Vbar.Vuint != 42 {
 | 
						|
		t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// #67 panic() on extending slices (decodeSlice with disabled ZeroValues)
 | 
						|
func TestDecodeSliceToEmptySliceWOZeroing(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
 | 
						|
	type TestStruct struct {
 | 
						|
		Vfoo []string
 | 
						|
	}
 | 
						|
 | 
						|
	decode := func(m interface{}, rawVal interface{}) error {
 | 
						|
		config := &DecoderConfig{
 | 
						|
			Metadata:   nil,
 | 
						|
			Result:     rawVal,
 | 
						|
			ZeroFields: false,
 | 
						|
		}
 | 
						|
 | 
						|
		decoder, err := NewDecoder(config)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		return decoder.Decode(m)
 | 
						|
	}
 | 
						|
 | 
						|
	{
 | 
						|
		input := map[string]interface{}{
 | 
						|
			"vfoo": []string{"1"},
 | 
						|
		}
 | 
						|
 | 
						|
		result := &TestStruct{}
 | 
						|
 | 
						|
		err := decode(input, &result)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("got an jderr: %s", err.Error())
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	{
 | 
						|
		input := map[string]interface{}{
 | 
						|
			"vfoo": []string{"1"},
 | 
						|
		}
 | 
						|
 | 
						|
		result := &TestStruct{
 | 
						|
			Vfoo: []string{},
 | 
						|
		}
 | 
						|
 | 
						|
		err := decode(input, &result)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("got an jderr: %s", err.Error())
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	{
 | 
						|
		input := map[string]interface{}{
 | 
						|
			"vfoo": []string{"2", "3"},
 | 
						|
		}
 | 
						|
 | 
						|
		result := &TestStruct{
 | 
						|
			Vfoo: []string{"1"},
 | 
						|
		}
 | 
						|
 | 
						|
		err := decode(input, &result)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("got an jderr: %s", err.Error())
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// #70
 | 
						|
func TestNextSquashMapstructure(t *testing.T) {
 | 
						|
	data := &struct {
 | 
						|
		Level1 struct {
 | 
						|
			Level2 struct {
 | 
						|
				Foo string
 | 
						|
			} `mapstructure:",squash"`
 | 
						|
		} `mapstructure:",squash"`
 | 
						|
	}{}
 | 
						|
	err := Decode(map[interface{}]interface{}{"foo": "baz"}, &data)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("should not error: %s", err)
 | 
						|
	}
 | 
						|
	if data.Level1.Level2.Foo != "baz" {
 | 
						|
		t.Fatal("value should be baz")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type ImplementsInterfacePointerReceiver struct {
 | 
						|
	Name string
 | 
						|
}
 | 
						|
 | 
						|
func (i *ImplementsInterfacePointerReceiver) DoStuff() {}
 | 
						|
 | 
						|
type ImplementsInterfaceValueReceiver string
 | 
						|
 | 
						|
func (i ImplementsInterfaceValueReceiver) DoStuff() {}
 | 
						|
 | 
						|
// GH-140 Type error when using DecodeHook to decode into interface
 | 
						|
func TestDecode_DecodeHookInterface(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
 | 
						|
	type Interface interface {
 | 
						|
		DoStuff()
 | 
						|
	}
 | 
						|
	type DecodeIntoInterface struct {
 | 
						|
		Test Interface
 | 
						|
	}
 | 
						|
 | 
						|
	testData := map[string]string{"test": "test"}
 | 
						|
 | 
						|
	stringToPointerInterfaceDecodeHook := func(from, to reflect.Type, data interface{}) (interface{}, error) {
 | 
						|
		if from.Kind() != reflect.String {
 | 
						|
			return data, nil
 | 
						|
		}
 | 
						|
 | 
						|
		if to != reflect.TypeOf((*Interface)(nil)).Elem() {
 | 
						|
			return data, nil
 | 
						|
		}
 | 
						|
		// Ensure interface is satisfied
 | 
						|
		var impl Interface = &ImplementsInterfacePointerReceiver{data.(string)}
 | 
						|
		return impl, nil
 | 
						|
	}
 | 
						|
 | 
						|
	stringToValueInterfaceDecodeHook := func(from, to reflect.Type, data interface{}) (interface{}, error) {
 | 
						|
		if from.Kind() != reflect.String {
 | 
						|
			return data, nil
 | 
						|
		}
 | 
						|
 | 
						|
		if to != reflect.TypeOf((*Interface)(nil)).Elem() {
 | 
						|
			return data, nil
 | 
						|
		}
 | 
						|
		// Ensure interface is satisfied
 | 
						|
		var impl Interface = ImplementsInterfaceValueReceiver(data.(string))
 | 
						|
		return impl, nil
 | 
						|
	}
 | 
						|
 | 
						|
	{
 | 
						|
		decodeInto := new(DecodeIntoInterface)
 | 
						|
 | 
						|
		decoder, _ := NewDecoder(&DecoderConfig{
 | 
						|
			DecodeHook: stringToPointerInterfaceDecodeHook,
 | 
						|
			Result:     decodeInto,
 | 
						|
		})
 | 
						|
 | 
						|
		err := decoder.Decode(testData)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("Decode returned error: %s", err)
 | 
						|
		}
 | 
						|
 | 
						|
		expected := &ImplementsInterfacePointerReceiver{"test"}
 | 
						|
		if !reflect.DeepEqual(decodeInto.Test, expected) {
 | 
						|
			t.Fatalf("expected: %#v (%T), got: %#v (%T)", decodeInto.Test, decodeInto.Test, expected, expected)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	{
 | 
						|
		decodeInto := new(DecodeIntoInterface)
 | 
						|
 | 
						|
		decoder, _ := NewDecoder(&DecoderConfig{
 | 
						|
			DecodeHook: stringToValueInterfaceDecodeHook,
 | 
						|
			Result:     decodeInto,
 | 
						|
		})
 | 
						|
 | 
						|
		err := decoder.Decode(testData)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("Decode returned error: %s", err)
 | 
						|
		}
 | 
						|
 | 
						|
		expected := ImplementsInterfaceValueReceiver("test")
 | 
						|
		if !reflect.DeepEqual(decodeInto.Test, expected) {
 | 
						|
			t.Fatalf("expected: %#v (%T), got: %#v (%T)", decodeInto.Test, decodeInto.Test, expected, expected)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// #103 Check for data type before trying to access its composants prevent a panic error
 | 
						|
// in decodeSlice
 | 
						|
func TestDecodeBadDataTypeInSlice(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
 | 
						|
	input := map[string]interface{}{
 | 
						|
		"Toto": "titi",
 | 
						|
	}
 | 
						|
	result := []struct {
 | 
						|
		Toto string
 | 
						|
	}{}
 | 
						|
 | 
						|
	if err := Decode(input, &result); err == nil {
 | 
						|
		t.Error("An error was expected, got nil")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// #202 Ensure that intermediate maps in the struct -> struct decode process are settable
 | 
						|
// and not just the elements within them.
 | 
						|
func TestDecodeIntermediateMapsSettable(t *testing.T) {
 | 
						|
	type Timestamp struct {
 | 
						|
		Seconds int64
 | 
						|
		Nanos   int32
 | 
						|
	}
 | 
						|
 | 
						|
	type TsWrapper struct {
 | 
						|
		Timestamp *Timestamp
 | 
						|
	}
 | 
						|
 | 
						|
	type TimeWrapper struct {
 | 
						|
		Timestamp time.Time
 | 
						|
	}
 | 
						|
 | 
						|
	input := TimeWrapper{
 | 
						|
		Timestamp: time.Unix(123456789, 987654),
 | 
						|
	}
 | 
						|
 | 
						|
	expected := TsWrapper{
 | 
						|
		Timestamp: &Timestamp{
 | 
						|
			Seconds: 123456789,
 | 
						|
			Nanos:   987654,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	timePtrType := reflect.TypeOf((*time.Time)(nil))
 | 
						|
	mapStrInfType := reflect.TypeOf((map[string]interface{})(nil))
 | 
						|
 | 
						|
	var actual TsWrapper
 | 
						|
	decoder, err := NewDecoder(&DecoderConfig{
 | 
						|
		Result: &actual,
 | 
						|
		DecodeHook: func(from, to reflect.Type, data interface{}) (interface{}, error) {
 | 
						|
			if from == timePtrType && to == mapStrInfType {
 | 
						|
				ts := data.(*time.Time)
 | 
						|
				nanos := ts.UnixNano()
 | 
						|
 | 
						|
				seconds := nanos / 1000000000
 | 
						|
				nanos = nanos % 1000000000
 | 
						|
 | 
						|
				return &map[string]interface{}{
 | 
						|
					"Seconds": seconds,
 | 
						|
					"Nanos":   int32(nanos),
 | 
						|
				}, nil
 | 
						|
			}
 | 
						|
			return data, nil
 | 
						|
		},
 | 
						|
	})
 | 
						|
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("failed to create decoder: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := decoder.Decode(&input); err != nil {
 | 
						|
		t.Fatalf("failed to decode input: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if !reflect.DeepEqual(expected, actual) {
 | 
						|
		t.Fatalf("expected: %#[1]v (%[1]T), got: %#[2]v (%[2]T)", expected, actual)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// GH-206: decodeInt throws an error for an empty string
 | 
						|
func TestDecode_weakEmptyStringToInt(t *testing.T) {
 | 
						|
	input := map[string]interface{}{
 | 
						|
		"StringToInt":   "",
 | 
						|
		"StringToUint":  "",
 | 
						|
		"StringToBool":  "",
 | 
						|
		"StringToFloat": "",
 | 
						|
	}
 | 
						|
 | 
						|
	expectedResultWeak := TypeConversionResult{
 | 
						|
		StringToInt:   0,
 | 
						|
		StringToUint:  0,
 | 
						|
		StringToBool:  false,
 | 
						|
		StringToFloat: 0,
 | 
						|
	}
 | 
						|
 | 
						|
	// Test weak type conversion
 | 
						|
	var resultWeak TypeConversionResult
 | 
						|
	err := WeakDecode(input, &resultWeak)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("got an jderr: %s", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if !reflect.DeepEqual(resultWeak, expectedResultWeak) {
 | 
						|
		t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// GH-228: Squash cause *time.Time set to zero
 | 
						|
func TestMapSquash(t *testing.T) {
 | 
						|
	type AA struct {
 | 
						|
		T *time.Time
 | 
						|
	}
 | 
						|
	type A struct {
 | 
						|
		AA
 | 
						|
	}
 | 
						|
 | 
						|
	v := time.Now()
 | 
						|
	in := &AA{
 | 
						|
		T: &v,
 | 
						|
	}
 | 
						|
	out := &A{}
 | 
						|
	d, err := NewDecoder(&DecoderConfig{
 | 
						|
		Squash: true,
 | 
						|
		Result: out,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		t.Fatalf("jderr: %s", err)
 | 
						|
	}
 | 
						|
	if err := d.Decode(in); err != nil {
 | 
						|
		t.Fatalf("jderr: %s", err)
 | 
						|
	}
 | 
						|
 | 
						|
	// these failed
 | 
						|
	if !v.Equal(*out.T) {
 | 
						|
		t.Fatal("expected equal")
 | 
						|
	}
 | 
						|
	if out.T.IsZero() {
 | 
						|
		t.Fatal("expected false")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// GH-238: Empty key name when decoding map from struct with only omitempty flag
 | 
						|
func TestMapOmitEmptyWithEmptyFieldnameInTag(t *testing.T) {
 | 
						|
	type Struct struct {
 | 
						|
		Username string `mapstructure:",omitempty"`
 | 
						|
		Age      int    `mapstructure:",omitempty"`
 | 
						|
	}
 | 
						|
 | 
						|
	s := Struct{
 | 
						|
		Username: "Joe",
 | 
						|
	}
 | 
						|
	var m map[string]interface{}
 | 
						|
 | 
						|
	if err := Decode(s, &m); err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if len(m) != 1 {
 | 
						|
		t.Fatalf("fail: %#v", m)
 | 
						|
	}
 | 
						|
	if m["Username"] != "Joe" {
 | 
						|
		t.Fatalf("fail: %#v", m)
 | 
						|
	}
 | 
						|
}
 |