Skip to content

Commit 23e9478

Browse files
committed
add string wrap and unwrap
1 parent 27c7e85 commit 23e9478

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

string.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,30 @@ func (s String) Errorf(format string, a ...interface{}) error {
1616
}
1717
}
1818

19+
// Wrap returns nil when passed nil, otherwise it returns an error such
20+
// that [errors.Is] returns true when compared to the String error or the
21+
// passed in error. It leaves the error text unchanged.
22+
func (s String) Wrap(err error) error {
23+
if err == nil {
24+
return nil
25+
}
26+
return errorString{
27+
error: WithStack(err),
28+
s: s,
29+
}
30+
}
31+
1932
type errorString struct {
2033
error
2134
s String
2235
}
2336

37+
// Is returns true if the target matches the same underlying
38+
// String value (compared as a string)
2439
func (e errorString) Is(target error) bool {
2540
return target == e.s
2641
}
42+
43+
func (e errorString) Unwrap() error {
44+
return e.error
45+
}

string_test.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,45 @@
1-
package errors
1+
package errors_test
22

33
import (
4+
"fmt"
45
"testing"
6+
7+
"github.com/memsql/errors"
8+
"github.com/stretchr/testify/require"
59
)
610

711
func TestStringIs(t *testing.T) {
8-
const myErr String = "custom type of error"
12+
const myErr errors.String = "custom type of error"
913
ex := myErr.Errorf("%s, we have a problem", "houston")
1014
if ex.Error() != "houston, we have a problem" {
1115
t.Errorf("mismatched text, have %q", ex.Error())
1216
}
13-
if !Is(ex, myErr) {
17+
if !errors.Is(ex, myErr) {
1418
t.Errorf("exception (%T) is not myErr (%T)", ex, myErr)
1519
}
1620
}
21+
22+
func TestStringAsMarker(t *testing.T) {
23+
const signalOne errors.String = "signal one"
24+
const signalTwo errors.String = "signal two"
25+
26+
err := errors.WithStack(fmt.Errorf("a test error"))
27+
require.False(t, errors.Is(err, signalOne), "non-signaled errors are not the signal error")
28+
require.NoError(t, signalOne.Wrap(nil), "wrapped nil is nil")
29+
30+
require.True(t, errors.Is(signalOne.Wrap(err), signalOne), "wrapped errors are the signal error (Wrap)")
31+
require.False(t, errors.Is(signalTwo.Wrap(err), signalOne), "one signal error is not another (Wrap)")
32+
require.False(t, errors.Is(signalOne, signalTwo), "raw signal are not each other (Wrap)")
33+
require.True(t, errors.Is(signalOne, signalOne), "raw signal is itself (Wrap)")
34+
require.True(t, errors.Is(signalTwo.Wrap(signalOne.Wrap(err)), signalOne), "double wrapped is the signal #1 (Wrap)")
35+
require.True(t, errors.Is(signalOne.Wrap(signalTwo.Wrap(err)), signalOne), "double wrapped is the signal #2 (Wrap)")
36+
require.Equal(t, "a test error", signalOne.Wrap(signalTwo.Wrap(err)).Error(), "the string is untouched (Wrap)")
37+
38+
require.True(t, errors.Is(signalOne.Errorf("%w", err), signalOne), "wrapped errors are the signal error (Errorf)")
39+
require.False(t, errors.Is(signalTwo.Errorf("%w", err), signalOne), "one signal error is not another (Errorf)")
40+
require.False(t, errors.Is(signalOne, signalTwo), "raw signal are not each other (Errorf)")
41+
require.True(t, errors.Is(signalOne, signalOne), "raw signal is itself (Errorf)")
42+
require.True(t, errors.Is(signalTwo.Errorf("%w", signalOne.Errorf("%w", err)), signalOne), "double wrapped is the signal #1 (Errorf)")
43+
require.True(t, errors.Is(signalOne.Errorf("%w", signalTwo.Errorf("%w", err)), signalOne), "double wrapped is the signal #2 (Errorf)")
44+
require.Equal(t, "a test error", signalOne.Errorf("%w", signalTwo.Errorf("%w", err)).Error(), "the string is untouched (Errorf)")
45+
}

0 commit comments

Comments
 (0)