diff --git a/error.go b/error.go index 03d67d4..7aee285 100644 --- a/error.go +++ b/error.go @@ -62,10 +62,6 @@ func GetError(err error) (Err *Error) { return custom } - if unwrapped := errors.Unwrap(err); unwrapped != nil { - return GetError(unwrapped) - } - return &Error{msg: err.Error(), cause: err} } @@ -97,6 +93,12 @@ func Cause(err error) error { // Format is implement the fmt.Formatter for Error. func (e *Error) Format(state fmt.State, verb rune) { + if len(e.fields) == 0 { + fmt.Fprint(state, e.Error()) + + return + } + switch verb { case 'v': if state.Flag('+') { diff --git a/error_test.go b/error_test.go index cf51b98..3a816dc 100644 --- a/error_test.go +++ b/error_test.go @@ -1,82 +1,177 @@ package errors_test import ( + stdErrors "errors" + "fmt" "testing" "github.com/mrsoftware/errors" + "github.com/stretchr/testify/assert" ) -func TestMy(t *testing.T) { - stValue := struct { - Username string - Password string - }{Username: "mrsoftware", Password: "kanman"} - err := errors.New("my error", errors.String("myString", "string value"), errors.Reflect("user", stValue)) +func TestNew(t *testing.T) { + t.Parallel() - // t.Logf("%q", err) - // t.Logf("%s", err) - // t.Logf("%v", err) - t.Logf("%+s", err) + msg := "some message" - t.Fail() + err := errors.New(msg) + assert.Equal(t, msg, err.Error()) } -// -// func TestNew(t *testing.T) { -// msg := "some message" -// -// err := errors.New(msg) -// assert.Equal(t, msg, err.Error()) -// } -// -// func TestGetError(t *testing.T) { -// var ( -// msg = "some message" -// fields = []errors.Field{{}} -// ) -// -// err := errors.New(msg, fields...) -// assert.Equal(t, fields, errors.GetFields(err)) -// } -// -// func TestGetErrorNotCompatible(t *testing.T) { -// var ( -// msg = "some message" -// fields = []errors.Field{{}} -// ) -// mainErr := errors.New(msg, fields...) -// err := fmt.Errorf("msg", mainErr) -// assert.Equal(t, mainErr, errors.GetError(err)) -// } -// -// func TestWrap(t *testing.T) { -// msg := "some message" -// cErr := stdErr.New("cause") -// -// err := errors.Wrap(cErr, msg) -// assert.Equal(t, "some message: cause", err.Error()) -// } -// -// func TestWrapf(t *testing.T) { -// format := "some message id: %d" -// cErr := stdErr.New("cause") -// -// err := errors.Wrapf(cErr, format, 10) -// assert.Equal(t, "some message id: 10: cause", err.Error()) -// } -// -// func TestErrorf(t *testing.T) { -// format := "some message id: %d" -// -// err := errors.Errorf(format, 10) -// assert.Equal(t, "some message id: 10", err.Error()) -// } -// -// func TestErrorfWithFields(t *testing.T) { -// format := "some message id: %d" -// fields := []errors.Field{{}} -// -// err := errors.ErrorfWithFields(format, []interface{}{10}, fields...) -// assert.Equal(t, "some message id: 10", err.Error()) -// assert.Equal(t, fields, errors.GetFields(err)) -// } +func TestGetError(t *testing.T) { + t.Parallel() + + t.Run("compatible error", func(t *testing.T) { + t.Parallel() + + var ( + msg = "some message" + fields = []errors.Field{{}} + ) + + err := errors.New(msg, fields...) + assert.Equal(t, fields, errors.GetFields(err)) + }) + + t.Run("not compatible wrapper error", func(t *testing.T) { + t.Parallel() + + var ( + msg = "some message" + ) + mainErr := errors.New(msg) + err := fmt.Errorf("msg: %w", mainErr) + assert.Equal(t, mainErr, errors.GetError(err)) + }) + + t.Run("not compatible error", func(t *testing.T) { + t.Parallel() + + var ( + msg = "some message" + ) + + err := stdErrors.New(msg) + willCreateErr := errors.Wrap(err, msg) + assert.Equal(t, willCreateErr, errors.GetError(err)) + }) +} + +func TestWrap(t *testing.T) { + t.Parallel() + + msg := "some message" + cErr := stdErrors.New("cause") + + err := errors.Wrap(cErr, msg) + assert.Equal(t, "some message: cause", err.Error()) +} + +func TestWrapf(t *testing.T) { + t.Parallel() + + format := "some message id: %d" + cErr := stdErrors.New("cause") + + err := errors.Wrapf(cErr, format, 10) + assert.Equal(t, "some message id: 10: cause", err.Error()) +} + +func TestErrorf(t *testing.T) { + t.Parallel() + + format := "some message id: %d" + + err := errors.Errorf(format, 10) + assert.Equal(t, "some message id: 10", err.Error()) +} + +func TestErrorfWithFields(t *testing.T) { + t.Parallel() + + format := "some message id: %d" + fields := []errors.Field{{}} + + err := errors.ErrorfWithFields(format, []interface{}{10}, fields...) + assert.Equal(t, "some message id: 10", err.Error()) + assert.Equal(t, fields, errors.GetFields(err)) +} + +func TestCause(t *testing.T) { + t.Parallel() + + t.Run("error with no cause", func(t *testing.T) { + err := stdErrors.New("cause") + + assert.Equal(t, err, errors.Cause(err)) + }) + + t.Run("error support causer", func(t *testing.T) { + cause := stdErrors.New("cause") + err := errors.Wrap(cause, "wrapper") + + assert.Equal(t, cause, errors.Cause(err)) + }) + + t.Run("error support causer", func(t *testing.T) { + cause := errors.New("cause") + err := errors.Wrap(cause, "wrapper") + + assert.Equal(t, cause, errors.Cause(err)) + }) +} + +func TestError_Format(t *testing.T) { + t.Parallel() + + t.Run("format any this with no field", func(t *testing.T) { + err := errors.New("some error") + + assert.Equal(t, "some error", fmt.Sprint(err)) + }) + + t.Run("format q", func(t *testing.T) { + err := errors.New("some error", errors.String("username", "mrsoftware")) + + assert.Equal(t, "\"some error\": [\"mrsoftware\"]", fmt.Sprintf("%q", err)) + }) + + t.Run("format s", func(t *testing.T) { + err := errors.New("some error", errors.String("username", "mrsoftware")) + + assert.Equal(t, "some error: [[username: mrsoftware]]", fmt.Sprintf("%s", err)) + }) + + t.Run("format v", func(t *testing.T) { + err := errors.New("some error", errors.String("username", "mrsoftware")) + + assert.Equal(t, "some error: [{Key: username, Value: mrsoftware}]", fmt.Sprintf("%v", err)) + }) + + t.Run("format +v", func(t *testing.T) { + err := errors.New("some error", errors.String("username", "mrsoftware")) + + assert.Equal(t, "some error: [{Key: username, Type: String, Value: mrsoftware}]", fmt.Sprintf("%+v", err)) + }) + + t.Run("format #v", func(t *testing.T) { + err := errors.New("some error", errors.String("username", "mrsoftware")) + + assert.Equal(t, "some error: []errors.Field{{username: \"mrsoftware\"}}", fmt.Sprintf("%#v", err)) + }) +} + +func TestAddFields(t *testing.T) { + t.Parallel() + + t.Run("err is not custom, expect wrap it with custom and add field", func(t *testing.T) { + err := stdErrors.New("standard error") + + field := errors.String("code", "value") + expect := errors.Wrap(err, err.Error(), field) + + withField := errors.AddFields(err, field) + + assert.Equal(t, expect, withField) + }) +}