diff --git a/error.go b/error.go index e75b1de..71a9a53 100644 --- a/error.go +++ b/error.go @@ -112,6 +112,33 @@ func (e ErrorObject) Error() string { return res.String() } +// Is checks if this error matches the supplied error. +// If err is not an ErrorObject, it always returns false. +// It returns true if Code() and Message() are the same. +// If err.Params() is non-nil, we also check that all the params match. +// This way, we can check an error against a sentinel error, such as ErrLengthTooLong. +func (e ErrorObject) Is(err error) bool { + eo, ok := err.(ErrorObject) + if !ok { + return false + } + + if e.message != eo.message || e.code != eo.code { + return false + } + + if len(eo.params) == 0 { + return true + } + + for k, v := range e.params { + if eo.params[k] != v { + return false + } + } + return true +} + // Error returns the error string of Errors. func (es Errors) Error() string { if len(es) == 0 { diff --git a/error_test.go b/error_test.go index e0985c5..afc86e2 100644 --- a/error_test.go +++ b/error_test.go @@ -115,6 +115,31 @@ func TestErrorObject_Params(t *testing.T) { assert.Equal(t, err.Params(), p) } +func TestErrorObject_Is(t *testing.T) { + err := ErrLengthOutOfRange.(ErrorObject) + err = err.SetParams(map[string]interface{}{"mix": 3, "max": 6}).(ErrorObject) + + assert.True(t, err.Is(ErrLengthOutOfRange)) + assert.True(t, errors.Is(err, ErrLengthOutOfRange)) + + err2 := ErrLengthOutOfRange.(ErrorObject) + err2 = err2.SetParams(map[string]interface{}{"min": 3, "max": 9}).(ErrorObject) + + assert.False(t, err2.Is(err)) + assert.False(t, errors.Is(err2, err)) + + assert.False(t, err.Is(errors.New(err.message))) + + err3 := ErrorObject{code: err.code, message: "hello"} + assert.False(t, err.Is(err3)) + + err4 := ErrorObject{code: "test_error", message: err.message} + assert.False(t, err.Is(err4)) + + err5 := ErrorObject{code: err.code, message: err.message, params: err.params} + assert.True(t, err.Is(err5)) +} + func TestErrorObject_AddParam2(t *testing.T) { p := map[string]interface{}{"key": "val"} err := NewError("code", "A").(ErrorObject)