diff --git a/error.go b/error.go index e744e71..a156de1 100644 --- a/error.go +++ b/error.go @@ -138,8 +138,17 @@ func withPossibleCause(ce *commonError) *commonError { func (ce *commonError) StackTrace() *StackTrace { return ce.stack } +// Unwrap returns the next error in the error chain. It returns nil if there +// is not a next error. func (ce *commonError) Unwrap() error { return ce.cause } +func (ce *commonError) Is(target error) bool { + if m, ok := ce.error.(Msg); ok { + return m.Is(target) + } + return false +} + func (ce *commonError) As(target interface{}) bool { if t, ok := target.(*commonError); ok { *t = *ce diff --git a/error_test.go b/error_test.go index 8bddb39..fc47b5b 100644 --- a/error_test.go +++ b/error_test.go @@ -120,15 +120,16 @@ func TestMsg(t *testing.T) { func TestMsg_Is(t *testing.T) { t.Run("true", func(t *testing.T) { - msg := Msg("some err") + m := Msg("some err") tests := map[string]error{ "Msg": Msg("some err"), - "*Msg": &msg, + "*Msg": &m, } - for a, err := range tests { + for a, msg := range tests { for b, target := range tests { t.Run(a+"/"+b, func(t *testing.T) { - assert.ErrorIs(t, err, target) + assert.ErrorIs(t, msg, target) + assert.ErrorIs(t, New(msg), target) }) } } diff --git a/kind.go b/kind.go index 537bca5..b0e8be9 100644 --- a/kind.go +++ b/kind.go @@ -20,6 +20,12 @@ const UnknownKind Kind = "" // It is recommended to define each Kind as a constant. type Kind string +// Kindf formats according to a format specifier using fmt.Sprintf, and returns +// the resulting string as Kind. +func Kindf(format string, args ...interface{}) Kind { + return Kind(fmt.Sprintf(format, args...)) +} + func (k Kind) Is(target error) bool { switch t := target.(type) { case Kind: diff --git a/kind_test.go b/kind_test.go index b32021a..7b42083 100644 --- a/kind_test.go +++ b/kind_test.go @@ -17,6 +17,19 @@ func TestKind(t *testing.T) { assert.Equal(t, kind.String(), kind.Error()) } +func TestKindf(t *testing.T) { + tests := map[string][]interface{}{ + "no args": nil, + "some %s": {"string"}, + "%s %s": {"foo", "bar"}, + } + for f, a := range tests { + t.Run(f, func(t *testing.T) { + assert.Equal(t, Kind(fmt.Sprintf(f, a...)), Kindf(f, a...)) + }) + } +} + func TestKind_Is(t *testing.T) { t.Run("true", func(t *testing.T) { kind := Kind("foobar")