Skip to content

Commit

Permalink
Merge 40fde52 into 61b46f8
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex committed Mar 20, 2017
2 parents 61b46f8 + 40fde52 commit dd35fe6
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 13 deletions.
22 changes: 14 additions & 8 deletions config/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"strconv"

"github.com/go-validator/validator"
"github.com/pkg/errors"
)

type fieldInfo struct {
Expand Down Expand Up @@ -206,6 +207,10 @@ func addSeparator(key string) string {
return key
}

func addKeyToError(key string, err error) error {
return errors.Wrap(err, fmt.Sprintf("for key %q", key))
}

type decoder struct {
*Value
m map[interface{}]struct{}
Expand Down Expand Up @@ -236,12 +241,12 @@ func (d *decoder) scalar(childKey string, value reflect.Value, def string) error
// to convert to primitive,try converting the value as a struct value
if ret, err := convertValue(val, value.Type()); ret != nil {
if err != nil {
return err
return addKeyToError(childKey, err)
}

value.Set(reflect.ValueOf(ret))
} else {
return convertValueFromStruct(val, &value)
return addKeyToError(childKey, convertValueFromStruct(val, &value))
}
}

Expand Down Expand Up @@ -342,7 +347,8 @@ func (d *decoder) mapping(childKey string, value reflect.Value, def string) erro
for key := range v {
subKey := fmt.Sprintf("%v", key)
if subKey == "" {
return fmt.Errorf("empty key leads to ambiguity for path: %q", childKey)
// We can confuse an empty map key with a root element.
return addKeyToError(childKey, errors.New("empty map key is ambigious"))
}

itemValue := reflect.New(valueType.Elem()).Elem()
Expand Down Expand Up @@ -375,7 +381,7 @@ func (d *decoder) iface(key string, value reflect.Value, def string) error {
return nil
}

return fmt.Errorf("%q doesn't implement %q", src.Type(), value.Type())
return addKeyToError(key, fmt.Errorf("%q doesn't implement %q", src.Type(), value.Type()))
}

// Sets value to an object type.
Expand Down Expand Up @@ -426,7 +432,7 @@ func (d *decoder) valueStruct(key string, target interface{}) error {
}
}

return validator.Validate(target)
return addKeyToError(key, validator.Validate(target))
}

// If there is no value with name - leave it nil, otherwise allocate memory and set the value.
Expand Down Expand Up @@ -466,12 +472,12 @@ func (d *decoder) textUnmarshaller(key string, value reflect.Value, str string)

// Value has to have a pointer receiver to be able to modify itself with TextUnmarshaller
if !value.CanAddr() {
return fmt.Errorf("can't use TextUnmarshaller because %q is not addressable", key)
return addKeyToError(key, errors.New("can't use TextUnmarshaller because value is not addressable"))
}

switch t := value.Addr().Interface().(type) {
case encoding.TextUnmarshaler:
return t.UnmarshalText([]byte(str))
return addKeyToError(key, t.UnmarshalText([]byte(str)))
}

return nil
Expand Down Expand Up @@ -504,7 +510,7 @@ func (d *decoder) checkCycles(value reflect.Value) error {
// Dispatch un-marshalling functions based on the value type.
func (d *decoder) unmarshal(name string, value reflect.Value, def string) error {
if err := d.checkCycles(value); err != nil {
return err
return addKeyToError(name, err)
}

switch value.Kind() {
Expand Down
8 changes: 7 additions & 1 deletion config/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func TestUnsignedNumericDecodingNegatives(t *testing.T) {
t.Run(fmt.Sprintf("%q convert negative", to), func(t *testing.T) {
err := f(p)
require.Error(t, err)
assert.Contains(t, fmt.Sprintf("can't convert \"-1\" to unsigned integer type %q", to), err.Error())
assert.Contains(t, err.Error(), fmt.Sprintf("can't convert \"-1\" to unsigned integer type %q", to))
})
}
}
Expand Down Expand Up @@ -542,3 +542,9 @@ func TestBoolParsing(t *testing.T) {
require.NoError(t, p.Get(Root).Populate(&alias))
assert.Equal(t, boolAlias(true), alias)
}

func TestAddKeyToErrorReturnsNilForNilErrors(t *testing.T) {
t.Parallel()

assert.NoError(t, addKeyToError("key", nil))
}
3 changes: 2 additions & 1 deletion config/static_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,6 @@ func TestPopulateForNestedMaps(t *testing.T) {
var m map[string]map[string]string
err := p.Get("a").Populate(&m)
require.Error(t, err)
assert.Contains(t, err.Error(), `empty key leads to ambiguity for path: "a."`)
assert.Contains(t, err.Error(), `empty map key is ambigious`)
assert.Contains(t, err.Error(), `a.`)
}
9 changes: 6 additions & 3 deletions config/yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ func TestNilYAMLProviderSetDefaultTagValue(t *testing.T) {
}{}

p := NewYAMLProviderFromBytes(nil)
p.Get("hello").Populate(&data)
require.NoError(t, p.Get("hello").Populate(&data))

assert.Equal(t, 10, data.ID0)
assert.Equal(t, "string", data.ID1)
Expand Down Expand Up @@ -578,7 +578,10 @@ func TestLoops(t *testing.T) {
require.Equal(t, b, a)

p := testProvider{}
assert.Contains(t, p.Get(Root).Populate(&b).Error(), "cycles")
err := p.Get(Root).Populate(&b)
require.Error(t, err)
assert.Contains(t, err.Error(), "cycles")
assert.Contains(t, err.Error(), `for key "A.A"`)
}

func TestInternalFieldsAreNotSet(t *testing.T) {
Expand Down Expand Up @@ -730,7 +733,7 @@ func TestGrumpyUnmarshallerChannelFunction(t *testing.T) {
var r S
p := NewYAMLProviderFromBytes(src)
e := p.Get(Root).Populate(&r)
require.EqualError(t, e, message)
require.Contains(t, e.Error(), message)
}

chanError := []byte(`
Expand Down

0 comments on commit dd35fe6

Please sign in to comment.