From 67c2acd75aaaaa724386acdf1cd629f20ebaecde Mon Sep 17 00:00:00 2001 From: Ferenc Fabian Date: Wed, 8 Jan 2020 19:41:10 +0100 Subject: [PATCH] Merge PR #5484: Add errors.Is support to the wrappedError --- types/errors/errors.go | 28 +++++++++++++++++++++ types/errors/errors_test.go | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/types/errors/errors.go b/types/errors/errors.go index 49624f7847..3179aed263 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -263,6 +263,34 @@ func (e *wrappedError) Cause() error { return e.parent } +// Is reports whether any error in e's chain matches a target. +func (e *wrappedError) Is(target error) bool { + if target == nil { + return e == target + } + + w := e.Cause() + + for { + if w == target { + return true + } + + x, ok := w.(causer) + if ok { + w = x.Cause() + } + if x == nil { + return false + } + } +} + +// Unwrap implements the built-in errors.Unwrap +func (e *wrappedError) Unwrap() error { + return e.parent +} + // Recover captures a panic and stop its propagation. If panic happens it is // transformed into a ErrPanic instance and assigned to given error. Call this // function using defer in order to work as expected. diff --git a/types/errors/errors_test.go b/types/errors/errors_test.go index a669ee150f..f6e6e8cd7f 100644 --- a/types/errors/errors_test.go +++ b/types/errors/errors_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/pkg/errors" ) @@ -158,3 +160,51 @@ func TestWrapEmpty(t *testing.T) { t.Fatal(err) } } + +func TestWrappedIs(t *testing.T) { + err := Wrap(ErrTxTooLarge, "context") + require.True(t, stdlib.Is(err, ErrTxTooLarge)) + + err = Wrap(err, "more context") + require.True(t, stdlib.Is(err, ErrTxTooLarge)) + + err = Wrap(err, "even more context") + require.True(t, stdlib.Is(err, ErrTxTooLarge)) + + err = Wrap(ErrInsufficientFee, "...") + require.False(t, stdlib.Is(err, ErrTxTooLarge)) +} + +func TestWrappedIsMultiple(t *testing.T) { + var errTest = errors.New("test error") + var errTest2 = errors.New("test error 2") + err := Wrap(errTest2, Wrap(errTest, "some random description").Error()) + require.True(t, stdlib.Is(err, errTest2)) +} + +func TestWrappedIsFail(t *testing.T) { + var errTest = errors.New("test error") + var errTest2 = errors.New("test error 2") + err := Wrap(errTest2, Wrap(errTest, "some random description").Error()) + require.False(t, stdlib.Is(err, errTest)) +} + +func TestWrappedUnwrap(t *testing.T) { + var errTest = errors.New("test error") + err := Wrap(errTest, "some random description") + require.Equal(t, errTest, stdlib.Unwrap(err)) +} + +func TestWrappedUnwrapMultiple(t *testing.T) { + var errTest = errors.New("test error") + var errTest2 = errors.New("test error 2") + err := Wrap(errTest2, Wrap(errTest, "some random description").Error()) + require.Equal(t, errTest2, stdlib.Unwrap(err)) +} + +func TestWrappedUnwrapFail(t *testing.T) { + var errTest = errors.New("test error") + var errTest2 = errors.New("test error 2") + err := Wrap(errTest2, Wrap(errTest, "some random description").Error()) + require.NotEqual(t, errTest, stdlib.Unwrap(err)) +}