Skip to content

Commit

Permalink
xload: add context to decode errors (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajatprabha authored Jun 19, 2024
1 parent 1e903ad commit 25a5c40
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 7 deletions.
6 changes: 5 additions & 1 deletion xload/async.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,11 @@ func loadAndSetWithOriginal(loader Loader, meta *field) loadAndSetPointer {

if ok, err := decode(fVal, val); ok {
if err != nil {
return err
return &ErrDecode{
key: meta.key,
val: val,
err: err,
}
}

setNilStructPtr(original, fVal, isNilStructPtr)
Expand Down
20 changes: 18 additions & 2 deletions xload/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,30 @@ func (e ErrInvalidPrefixAndKey) Error() string {
// Collision can happen when two or more fields have the same full key.
type ErrCollision struct{ keys []string }

func (e *ErrCollision) Error() string {
func (e ErrCollision) Error() string {
return fmt.Sprintf("xload: key collisions detected for keys: %v", e.keys)
}

// Keys returns the collided keys.
func (e *ErrCollision) Keys() []string {
func (e ErrCollision) Keys() []string {
keysCopy := make([]string, len(e.keys))
copy(keysCopy, e.keys)

return keysCopy
}

// ErrDecode wraps the actual error that occurred during decoding value to go type.
type ErrDecode struct {
key string
val string
err error
}

// Value returns the raw value that was used to decode the key.
func (e ErrDecode) Value() string { return e.val }

func (e ErrDecode) Error() string {
return fmt.Sprintf("xload: unable to decode value for key %s: %v", e.key, e.err)
}

func (e ErrDecode) Unwrap() error { return e.err }
12 changes: 12 additions & 0 deletions xload/errors_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package xload

import (
"errors"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -47,3 +48,14 @@ func TestErrCollision(t *testing.T) {
assert.ElementsMatch(t, ks, err.Keys())
assert.Equal(t, "xload: key collisions detected for keys: [KEY_A KEY_B]", err.Error())
}

func TestErrDecodeValue(t *testing.T) {
errDecode := errors.New("decode error")
err := &ErrDecode{
key: "KEY_A",
err: errDecode,
}

assert.EqualError(t, err, "xload: unable to decode value for key KEY_A: decode error")
assert.ErrorIs(t, err, errDecode)
}
16 changes: 14 additions & 2 deletions xload/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ func doProcess(ctx context.Context, obj any, tagKey string, loader Loader) error

if ok, err := decode(fVal, val); ok {
if err != nil {
return err
return &ErrDecode{
key: meta.key,
val: val,
err: err,
}
}

setNilStructPtr(fVal)
Expand Down Expand Up @@ -262,7 +266,15 @@ func setVal(field reflect.Value, val string, meta *field) error {

dec, err := decode(field, val)
if dec || err != nil {
return err
if err != nil {
return &ErrDecode{
key: meta.key,
val: val,
err: err,
}
}

return nil
}

ty := field.Type()
Expand Down
18 changes: 16 additions & 2 deletions xload/load_struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,22 @@ func TestLoad_JSON(t *testing.T) {
input: &struct {
Plot Plot `env:"PLOT"`
}{},
wantErr: errContains(errors.New("invalid character")),
loader: MapLoader{"PLOT": `invalid`},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
errDec := new(ErrDecode)
return assert.ErrorAs(t, err, &errDec, i...) && assert.Equal(t, "invalid", errDec.Value())
},
loader: MapLoader{"PLOT": `invalid`},
},
{
name: "json: array(not-struct) invalid",
input: &struct {
Plots Plots `env:"PLOTS"`
}{},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
errDec := new(ErrDecode)
return assert.ErrorAs(t, err, &errDec, i...) && assert.Equal(t, "invalid", errDec.Value())
},
loader: MapLoader{"PLOTS": `invalid`},
},
{
name: "json: loader error",
Expand Down

0 comments on commit 25a5c40

Please sign in to comment.