Repository: mitchellh/mapstructure (go)

Issue:
Empty key name when decoding map from struct with only omitempty flag
If a structtag only contains `,omitempty` when decoding a map from a struct, the keyName is overwritten by an empty string. I can't find whether this is defined behavior. If not, I have a PR ready to fix this.

Example:
```go
type Struct struct {
	Username string `mapstructure:",omitempty"`
}

s := Struct{
	Username: "Joe",
}
var m map[string]interface{}
mapstructure.Decode(s, &m)

// Output: map[:Joe]
// Expected output: map[Username:Joe]
fmt.Printf("%+v", m)
```

Pull request description:
Fix empty keyName when decoding struct -> map with omitempty
Fixes #238

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1012550..1c9f562 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,27 +1,6 @@
-## 1.4.4
-
-* New option `IgnoreUntaggedFields` to ignore decoding to any fields
-  without `mapstructure` (or the configured tag name) set [GH-277]
-* New option `ErrorUnset` which makes it an error if any fields
-  in a target struct are not set by the decoding process. [GH-225]
-* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240]
-* Decoding to slice from array no longer crashes [GH-265]
-* Decode nested struct pointers to map [GH-271]
-* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280]
-
-## 1.4.3
-
-* Fix cases where `json.Number` didn't decode properly [GH-261]
-
-## 1.4.2
-
-* Custom name matchers to support any sort of casing, formatting, etc. for
-  field names. [GH-250]
-* Fix possible panic in ComposeDecodeHookFunc [GH-251]
-
 ## 1.4.1
 
-* Fix regression where `*time.Time` value would be set to empty and not be sent
+* Fix regression where `*time.Time` value would be set to empty and not be sent 
   to decode hooks properly [GH-232]
 
 ## 1.4.0
diff --git a/decode_hooks.go b/decode_hooks.go
index 3a754ca..92e6f76 100644
--- a/decode_hooks.go
+++ b/decode_hooks.go
@@ -62,8 +62,7 @@ func DecodeHookExec(
 func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 	return func(f reflect.Value, t reflect.Value) (interface{}, error) {
 		var err error
-		data := f.Interface()
-
+		var data interface{}
 		newFrom := f
 		for _, f1 := range fs {
 			data, err = DecodeHookExec(f1, newFrom, t)
@@ -77,28 +76,6 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 	}
 }
 
-// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
-// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
-func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
-	return func(a, b reflect.Value) (interface{}, error) {
-		var allErrs string
-		var out interface{}
-		var err error
-
-		for _, f := range ff {
-			out, err = DecodeHookExec(f, a, b)
-			if err != nil {
-				allErrs += err.Error() + "\n"
-				continue
-			}
-
-			return out, nil
-		}
-
-		return nil, errors.New(allErrs)
-	}
-}
-
 // StringToSliceHookFunc returns a DecodeHookFunc that converts
 // string to []string by splitting on the given sep.
 func StringToSliceHookFunc(sep string) DecodeHookFunc {
diff --git a/mapstructure.go b/mapstructure.go
index 32c9fce..36d591f 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -122,7 +122,7 @@
 // field value is zero and a numeric type, the field is empty, and it won't
 // be encoded into the destination type.
 //
-//     type Source struct {
+//     type Source {
 //         Age int `mapstructure:",omitempty"`
 //     }
 //
@@ -192,7 +192,7 @@ type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface
 // source and target types.
 type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
 
-// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
+// DecodeHookFuncRaw is a DecodeHookFunc which has complete access to both the source and target
 // values.
 type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
 
@@ -215,12 +215,6 @@ type DecoderConfig struct {
 	// (extra keys).
 	ErrorUnused bool
 
-	// If ErrorUnset is true, then it is an error for there to exist
-	// fields in the result that were not set in the decoding process
-	// (extra fields). This only applies to decoding to a struct. This
-	// will affect all nested structs as well.
-	ErrorUnset bool
-
 	// ZeroFields, if set to true, will zero fields before writing them.
 	// For example, a map will be emptied before decoded values are put in
 	// it. If this is false, a map will be merged.
@@ -264,15 +258,6 @@ type DecoderConfig struct {
 	// The tag name that mapstructure reads for field names. This
 	// defaults to "mapstructure"
 	TagName string
-
-	// IgnoreUntaggedFields ignores all struct fields without explicit
-	// TagName, comparable to `mapstructure:"-"` as default behaviour.
-	IgnoreUntaggedFields bool
-
-	// MatchName is the function used to match the map key to the struct
-	// field name or tag. Defaults to `strings.EqualFold`. This can be used
-	// to implement case-sensitive tag values, support snake casing, etc.
-	MatchName func(mapKey, fieldName string) bool
 }
 
 // A Decoder takes a raw interface value and turns it into structured
@@ -294,11 +279,6 @@ type Metadata struct {
 	// Unused is a slice of keys that were found in the raw value but
 	// weren't decoded since there was no matching field in the result interface
 	Unused []string
-
-	// Unset is a slice of field names that were found in the result interface
-	// but weren't set in the decoding process since there was no matching value
-	// in the input
-	Unset []string
 }
 
 // Decode takes an input structure and uses reflection to translate it to
@@ -390,20 +370,12 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
 		if config.Metadata.Unused == nil {
 			config.Metadata.Unused = make([]string, 0)
 		}
-
-		if config.Metadata.Unset == nil {
-			config.Metadata.Unset = make([]string, 0)
-		}
 	}
 
 	if config.TagName == "" {
 		config.TagName = "mapstructure"
 	}
 
-	if config.MatchName == nil {
-		config.MatchName = strings.EqualFold
-	}
-
 	result := &Decoder{
 		config: config,
 	}
@@ -703,12 +675,16 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 		}
 	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 		jn := data.(json.Number)
-		i, err := strconv.ParseUint(string(jn), 0, 64)
+		i, err := jn.Int64()
 		if err != nil {
 			return fmt.Errorf(
 				"error decoding json.Number into %s: %s", name, err)
 		}
-		val.SetUint(i)
+		if i < 0 && !d.config.WeaklyTypedInput {
+			return fmt.Errorf("cannot parse '%s', %d overflows uint",
+				name, i)
+		}
+		val.SetUint(uint64(i))
 	default:
 		return fmt.Errorf(
 			"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
@@ -925,15 +901,9 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 		tagValue := f.Tag.Get(d.config.TagName)
 		keyName := f.Name
 
-		if tagValue == "" && d.config.IgnoreUntaggedFields {
-			continue
-		}
-
 		// If Squash is set in the config, we squash the field down.
 		squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous
 
-		v = dereferencePtrToStructIfNeeded(v, d.config.TagName)
-
 		// Determine the name of the key in the map
 		if index := strings.Index(tagValue, ","); index != -1 {
 			if tagValue[:index] == "-" {
@@ -945,7 +915,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 			}
 
 			// If "squash" is specified in the tag, we squash the field down.
-			squash = squash || strings.Index(tagValue[index+1:], "squash") != -1
+			squash = !squash && strings.Index(tagValue[index+1:], "squash") != -1
 			if squash {
 				// When squashing, the embedded type can be a pointer to a struct.
 				if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
@@ -957,7 +927,9 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
 					return fmt.Errorf("cannot squash non-struct type '%s'", v.Type())
 				}
 			}
-			keyName = tagValue[:index]
+			if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" {
+				keyName = keyNameTagValue
+			}
 		} else if len(tagValue) > 0 {
 			if tagValue == "-" {
 				continue
@@ -1113,7 +1085,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 	}
 
 	// If the input value is nil, then don't allocate since empty != nil
-	if dataValKind != reflect.Array && dataVal.IsNil() {
+	if dataVal.IsNil() {
 		return nil
 	}
 
@@ -1275,7 +1247,6 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
 	}
 
-	targetValKeysUnused := make(map[interface{}]struct{})
 	errors := make([]string, 0)
 
 	// This slice will keep track of all the structs we'll be decoding.
@@ -1371,7 +1342,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 					continue
 				}
 
-				if d.config.MatchName(mK, fieldName) {
+				if strings.EqualFold(mK, fieldName) {
 					rawMapKey = dataValKey
 					rawMapVal = dataVal.MapIndex(dataValKey)
 					break
@@ -1380,8 +1351,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 
 			if !rawMapVal.IsValid() {
 				// There was no matching key in the map for the value in
-				// the struct. Remember it for potential errors and metadata.
-				targetValKeysUnused[fieldName] = struct{}{}
+				// the struct. Just ignore.
 				continue
 			}
 		}
@@ -1441,17 +1411,6 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 		errors = appendErrors(errors, err)
 	}
 
-	if d.config.ErrorUnset && len(targetValKeysUnused) > 0 {
-		keys := make([]string, 0, len(targetValKeysUnused))
-		for rawKey := range targetValKeysUnused {
-			keys = append(keys, rawKey.(string))
-		}
-		sort.Strings(keys)
-
-		err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", "))
-		errors = appendErrors(errors, err)
-	}
-
 	if len(errors) > 0 {
 		return &Error{errors}
 	}
@@ -1466,14 +1425,6 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
 
 			d.config.Metadata.Unused = append(d.config.Metadata.Unused, key)
 		}
-		for rawKey := range targetValKeysUnused {
-			key := rawKey.(string)
-			if name != "" {
-				key = name + "." + key
-			}
-
-			d.config.Metadata.Unset = append(d.config.Metadata.Unset, key)
-		}
 	}
 
 	return nil
@@ -1511,28 +1462,3 @@ func getKind(val reflect.Value) reflect.Kind {
 		return kind
 	}
 }
-
-func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool {
-	for i := 0; i < typ.NumField(); i++ {
-		f := typ.Field(i)
-		if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields
-			return true
-		}
-		if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside
-			return true
-		}
-	}
-	return false
-}
-
-func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value {
-	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
-		return v
-	}
-	deref := v.Elem()
-	derefT := deref.Type()
-	if isStructTypeConvertibleToMap(derefT, true, tagName) {
-		return deref
-	}
-	return v
-}


Test patch:
diff --git a/decode_hooks_test.go b/decode_hooks_test.go
index bf02952..b3165bc 100644
--- a/decode_hooks_test.go
+++ b/decode_hooks_test.go
@@ -84,126 +84,6 @@ func TestComposeDecodeHookFunc_kinds(t *testing.T) {
 	}
 }
 
-func TestOrComposeDecodeHookFunc(t *testing.T) {
-	f1 := func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		return data.(string) + "foo", nil
-	}
-
-	f2 := func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		return data.(string) + "bar", nil
-	}
-
-	f := OrComposeDecodeHookFunc(f1, f2)
-
-	result, err := DecodeHookExec(
-		f, reflect.ValueOf(""), reflect.ValueOf([]byte("")))
-	if err != nil {
-		t.Fatalf("bad: %s", err)
-	}
-	if result.(string) != "foo" {
-		t.Fatalf("bad: %#v", result)
-	}
-}
-
-func TestOrComposeDecodeHookFunc_correctValueIsLast(t *testing.T) {
-	f1 := func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		return nil, errors.New("f1 error")
-	}
-
-	f2 := func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		return nil, errors.New("f2 error")
-	}
-
-	f3 := func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		return data.(string) + "bar", nil
-	}
-
-	f := OrComposeDecodeHookFunc(f1, f2, f3)
-
-	result, err := DecodeHookExec(
-		f, reflect.ValueOf(""), reflect.ValueOf([]byte("")))
-	if err != nil {
-		t.Fatalf("bad: %s", err)
-	}
-	if result.(string) != "bar" {
-		t.Fatalf("bad: %#v", result)
-	}
-}
-
-func TestOrComposeDecodeHookFunc_err(t *testing.T) {
-	f1 := func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		return nil, errors.New("f1 error")
-	}
-
-	f2 := func(
-		f reflect.Kind,
-		t reflect.Kind,
-		data interface{}) (interface{}, error) {
-		return nil, errors.New("f2 error")
-	}
-
-	f := OrComposeDecodeHookFunc(f1, f2)
-
-	_, err := DecodeHookExec(
-		f, reflect.ValueOf(""), reflect.ValueOf([]byte("")))
-	if err == nil {
-		t.Fatalf("bad: should return an error")
-	}
-	if err.Error() != "f1 error\nf2 error\n" {
-		t.Fatalf("bad: %s", err)
-	}
-}
-
-func TestComposeDecodeHookFunc_safe_nofuncs(t *testing.T) {
-	f := ComposeDecodeHookFunc()
-	type myStruct2 struct {
-		MyInt int
-	}
-
-	type myStruct1 struct {
-		Blah map[string]myStruct2
-	}
-
-	src := &myStruct1{Blah: map[string]myStruct2{
-		"test": {
-			MyInt: 1,
-		},
-	}}
-
-	dst := &myStruct1{}
-	dConf := &DecoderConfig{
-		Result:      dst,
-		ErrorUnused: true,
-		DecodeHook:  f,
-	}
-	d, err := NewDecoder(dConf)
-	if err != nil {
-		t.Fatal(err)
-	}
-	err = d.Decode(src)
-	if err != nil {
-		t.Fatal(err)
-	}
-}
-
 func TestStringToSliceHookFunc(t *testing.T) {
 	f := StringToSliceHookFunc(",")
 
diff --git a/mapstructure_bugs_test.go b/mapstructure_bugs_test.go
index f063760..7477c74 100644
--- a/mapstructure_bugs_test.go
+++ b/mapstructure_bugs_test.go
@@ -1,6 +1,7 @@
 package mapstructure
 
 import (
+	"fmt"
 	"reflect"
 	"testing"
 	"time"
@@ -479,7 +480,7 @@ func TestDecodeBadDataTypeInSlice(t *testing.T) {
 
 // #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) {
+func TestDecodeIntermeidateMapsSettable(t *testing.T) {
 	type Timestamp struct {
 		Seconds int64
 		Nanos   int32
@@ -601,3 +602,25 @@ func TestMapSquash(t *testing.T) {
 		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)
+	}
+
+	expect := "map[Username:Joe]"
+	if got := fmt.Sprintf("%+v", m); expect != got {
+		t.Fatalf("expect %q, got: %s", expect, got)
+	}
+}
diff --git a/mapstructure_test.go b/mapstructure_test.go
index bef5f85..53b2d0a 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -7,7 +7,6 @@ import (
 	"sort"
 	"strings"
 	"testing"
-	"time"
 )
 
 type Basic struct {
@@ -25,7 +24,6 @@ type Basic struct {
 	Vdata       interface{}
 	VjsonInt    int
 	VjsonUint   uint
-	VjsonUint64 uint64
 	VjsonFloat  float64
 	VjsonNumber json.Number
 }
@@ -68,20 +66,6 @@ type EmbeddedPointerSquash struct {
 	Vunique string
 }
 
-type BasicMapStructure struct {
-	Vunique string     `mapstructure:"vunique"`
-	Vtime   *time.Time `mapstructure:"time"`
-}
-
-type NestedPointerWithMapstructure struct {
-	Vbar *BasicMapStructure `mapstructure:"vbar"`
-}
-
-type EmbeddedPointerSquashWithNestedMapstructure struct {
-	*NestedPointerWithMapstructure `mapstructure:",squash"`
-	Vunique                        string
-}
-
 type EmbeddedAndNamed struct {
 	Basic
 	Named   Basic
@@ -240,7 +224,6 @@ func TestBasicTypes(t *testing.T) {
 		"vdata":       42,
 		"vjsonInt":    json.Number("1234"),
 		"vjsonUint":   json.Number("1234"),
-		"vjsonUint64": json.Number("9223372036854775809"), // 2^63 + 1
 		"vjsonFloat":  json.Number("1234.5"),
 		"vjsonNumber": json.Number("1234.5"),
 	}
@@ -304,10 +287,6 @@ func TestBasicTypes(t *testing.T) {
 		t.Errorf("vjsonuint value should be 1234: %#v", result.VjsonUint)
 	}
 
-	if result.VjsonUint64 != 9223372036854775809 {
-		t.Errorf("vjsonuint64 value should be 9223372036854775809: %#v", result.VjsonUint64)
-	}
-
 	if result.VjsonFloat != 1234.5 {
 		t.Errorf("vjsonfloat value should be 1234.5: %#v", result.VjsonFloat)
 	}
@@ -571,21 +550,6 @@ func TestDecode_EmbeddedArray(t *testing.T) {
 	}
 }
 
-func TestDecode_decodeSliceWithArray(t *testing.T) {
-	t.Parallel()
-
-	var result []int
-	input := [1]int{1}
-	expected := []int{1}
-	if err := Decode(input, &result); err != nil {
-		t.Fatalf("got an err: %s", err.Error())
-	}
-
-	if !reflect.DeepEqual(expected, result) {
-		t.Errorf("wanted %+v, got %+v", expected, result)
-	}
-}
-
 func TestDecode_EmbeddedNoSquash(t *testing.T) {
 	t.Parallel()
 
@@ -746,74 +710,6 @@ func TestDecode_EmbeddedPointerSquash_FromMapToStruct(t *testing.T) {
 	}
 }
 
-func TestDecode_EmbeddedPointerSquashWithNestedMapstructure_FromStructToMap(t *testing.T) {
-	t.Parallel()
-
-	vTime := time.Now()
-
-	input := EmbeddedPointerSquashWithNestedMapstructure{
-		NestedPointerWithMapstructure: &NestedPointerWithMapstructure{
-			Vbar: &BasicMapStructure{
-				Vunique: "bar",
-				Vtime:   &vTime,
-			},
-		},
-		Vunique: "foo",
-	}
-
-	var result map[string]interface{}
-	err := Decode(input, &result)
-	if err != nil {
-		t.Fatalf("got an err: %s", err.Error())
-	}
-	expected := map[string]interface{}{
-		"vbar": map[string]interface{}{
-			"vunique": "bar",
-			"time":    &vTime,
-		},
-		"Vunique": "foo",
-	}
-
-	if !reflect.DeepEqual(result, expected) {
-		t.Errorf("result should be %#v: got %#v", expected, result)
-	}
-}
-
-func TestDecode_EmbeddedPointerSquashWithNestedMapstructure_FromMapToStruct(t *testing.T) {
-	t.Parallel()
-
-	vTime := time.Now()
-
-	input := map[string]interface{}{
-		"vbar": map[string]interface{}{
-			"vunique": "bar",
-			"time":    &vTime,
-		},
-		"Vunique": "foo",
-	}
-
-	result := EmbeddedPointerSquashWithNestedMapstructure{
-		NestedPointerWithMapstructure: &NestedPointerWithMapstructure{},
-	}
-	err := Decode(input, &result)
-	if err != nil {
-		t.Fatalf("got an err: %s", err.Error())
-	}
-	expected := EmbeddedPointerSquashWithNestedMapstructure{
-		NestedPointerWithMapstructure: &NestedPointerWithMapstructure{
-			Vbar: &BasicMapStructure{
-				Vunique: "bar",
-				Vtime:   &vTime,
-			},
-		},
-		Vunique: "foo",
-	}
-
-	if !reflect.DeepEqual(result, expected) {
-		t.Errorf("result should be %#v: got %#v", expected, result)
-	}
-}
-
 func TestDecode_EmbeddedSquashConfig(t *testing.T) {
 	t.Parallel()
 
@@ -910,53 +806,6 @@ func TestDecodeFrom_EmbeddedSquashConfig(t *testing.T) {
 	}
 }
 
-func TestDecodeFrom_EmbeddedSquashConfig_WithTags(t *testing.T) {
-	t.Parallel()
-
-	var v interface{}
-	var ok bool
-
-	input := EmbeddedSquash{
-		Basic: Basic{
-			Vstring: "foo",
-		},
-		Vunique: "bar",
-	}
-
-	result := map[string]interface{}{}
-	config := &DecoderConfig{
-		Squash: true,
-		Result: &result,
-	}
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		t.Fatalf("got an err: %s", err.Error())
-	}
-
-	err = decoder.Decode(input)
-	if err != nil {
-		t.Fatalf("got an err: %s", err.Error())
-	}
-
-	if _, ok = result["Basic"]; ok {
-		t.Error("basic should not be present in map")
-	}
-
-	v, ok = result["Vstring"]
-	if !ok {
-		t.Error("vstring should be present in map")
-	} else if !reflect.DeepEqual(v, "foo") {
-		t.Errorf("vstring value should be 'foo': %#v", v)
-	}
-
-	v, ok = result["Vunique"]
-	if !ok {
-		t.Error("vunique should be present in map")
-	} else if !reflect.DeepEqual(v, "bar") {
-		t.Errorf("vunique value should be 'bar': %#v", v)
-	}
-}
-
 func TestDecode_SquashOnNonStructType(t *testing.T) {
 	t.Parallel()
 
@@ -1376,30 +1225,6 @@ func TestDecoder_ErrorUnused_NotSetable(t *testing.T) {
 		t.Fatal("expected error")
 	}
 }
-func TestDecoder_ErrorUnset(t *testing.T) {
-	t.Parallel()
-
-	input := map[string]interface{}{
-		"vstring": "hello",
-		"foo":     "bar",
-	}
-
-	var result Basic
-	config := &DecoderConfig{
-		ErrorUnset: true,
-		Result:     &result,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		t.Fatalf("err: %s", err)
-	}
-
-	err = decoder.Decode(input)
-	if err == nil {
-		t.Fatal("expected error")
-	}
-}
 
 func TestMap(t *testing.T) {
 	t.Parallel()
@@ -1896,7 +1721,6 @@ func TestDecodeTable(t *testing.T) {
 				"Vdata":       []byte("data"),
 				"VjsonInt":    0,
 				"VjsonUint":   uint(0),
-				"VjsonUint64": uint64(0),
 				"VjsonFloat":  0.0,
 				"VjsonNumber": json.Number(""),
 			},
@@ -1938,7 +1762,6 @@ func TestDecodeTable(t *testing.T) {
 					"Vdata":       []byte("data"),
 					"VjsonInt":    0,
 					"VjsonUint":   uint(0),
-					"VjsonUint64": uint64(0),
 					"VjsonFloat":  0.0,
 					"VjsonNumber": json.Number(""),
 				},
@@ -2369,14 +2192,6 @@ func TestMetadata(t *testing.T) {
 	if !reflect.DeepEqual(md.Unused, expectedUnused) {
 		t.Fatalf("bad unused: %#v", md.Unused)
 	}
-
-	expectedUnset := []string{
-		"Vbar.Vbool", "Vbar.Vdata", "Vbar.Vextra", "Vbar.Vfloat", "Vbar.Vint",
-		"Vbar.VjsonFloat", "Vbar.VjsonInt", "Vbar.VjsonNumber"}
-	sort.Strings(md.Unset)
-	if !reflect.DeepEqual(md.Unset, expectedUnset) {
-		t.Fatalf("bad unset: %#v", md.Unset)
-	}
 }
 
 func TestMetadata_Embedded(t *testing.T) {
@@ -2616,89 +2431,6 @@ func TestDecode_mapToStruct(t *testing.T) {
 	}
 }
 
-func TestDecoder_MatchName(t *testing.T) {
-	t.Parallel()
-
-	type Target struct {
-		FirstMatch  string `mapstructure:"first_match"`
-		SecondMatch string
-		NoMatch     string `mapstructure:"no_match"`
-	}
-
-	input := map[string]interface{}{
-		"first_match": "foo",
-		"SecondMatch": "bar",
-		"NO_MATCH":    "baz",
-	}
-
-	expected := Target{
-		FirstMatch:  "foo",
-		SecondMatch: "bar",
-	}
-
-	var actual Target
-	config := &DecoderConfig{
-		Result: &actual,
-		MatchName: func(mapKey, fieldName string) bool {
-			return mapKey == fieldName
-		},
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		t.Fatalf("err: %s", err)
-	}
-
-	err = decoder.Decode(input)
-	if err != nil {
-		t.Fatalf("err: %s", err)
-	}
-
-	if !reflect.DeepEqual(expected, actual) {
-		t.Fatalf("Decode() expected: %#v, got: %#v", expected, actual)
-	}
-}
-
-func TestDecoder_IgnoreUntaggedFields(t *testing.T) {
-	type Input struct {
-		UntaggedNumber int
-		TaggedNumber   int `mapstructure:"tagged_number"`
-		UntaggedString string
-		TaggedString   string `mapstructure:"tagged_string"`
-	}
-	input := &Input{
-		UntaggedNumber: 31,
-		TaggedNumber:   42,
-		UntaggedString: "hidden",
-		TaggedString:   "visible",
-	}
-
-	actual := make(map[string]interface{})
-	config := &DecoderConfig{
-		Result:               &actual,
-		IgnoreUntaggedFields: true,
-	}
-
-	decoder, err := NewDecoder(config)
-	if err != nil {
-		t.Fatalf("err: %s", err)
-	}
-
-	err = decoder.Decode(input)
-	if err != nil {
-		t.Fatalf("err: %s", err)
-	}
-
-	expected := map[string]interface{}{
-		"tagged_number": 42,
-		"tagged_string": "visible",
-	}
-
-	if !reflect.DeepEqual(expected, actual) {
-		t.Fatalf("Decode() expected: %#v\ngot: %#v", expected, actual)
-	}
-}
-
 func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
 	var result Slice
 	err := Decode(input, &result)