1// +build go1.13
2
3package errors
4
5import (
6	stderrors "errors"
7	"fmt"
8	"reflect"
9	"testing"
10)
11
12func TestErrorChainCompat(t *testing.T) {
13	err := stderrors.New("error that gets wrapped")
14	wrapped := Wrap(err, "wrapped up")
15	if !stderrors.Is(wrapped, err) {
16		t.Errorf("Wrap does not support Go 1.13 error chains")
17	}
18}
19
20func TestIs(t *testing.T) {
21	err := New("test")
22
23	type args struct {
24		err    error
25		target error
26	}
27	tests := []struct {
28		name string
29		args args
30		want bool
31	}{
32		{
33			name: "with stack",
34			args: args{
35				err:    WithStack(err),
36				target: err,
37			},
38			want: true,
39		},
40		{
41			name: "with message",
42			args: args{
43				err:    WithMessage(err, "test"),
44				target: err,
45			},
46			want: true,
47		},
48		{
49			name: "with message format",
50			args: args{
51				err:    WithMessagef(err, "%s", "test"),
52				target: err,
53			},
54			want: true,
55		},
56		{
57			name: "std errors compatibility",
58			args: args{
59				err:    fmt.Errorf("wrap it: %w", err),
60				target: err,
61			},
62			want: true,
63		},
64	}
65	for _, tt := range tests {
66		t.Run(tt.name, func(t *testing.T) {
67			if got := Is(tt.args.err, tt.args.target); got != tt.want {
68				t.Errorf("Is() = %v, want %v", got, tt.want)
69			}
70		})
71	}
72}
73
74type customErr struct {
75	msg string
76}
77
78func (c customErr) Error() string { return c.msg }
79
80func TestAs(t *testing.T) {
81	var err = customErr{msg: "test message"}
82
83	type args struct {
84		err    error
85		target interface{}
86	}
87	tests := []struct {
88		name string
89		args args
90		want bool
91	}{
92		{
93			name: "with stack",
94			args: args{
95				err:    WithStack(err),
96				target: new(customErr),
97			},
98			want: true,
99		},
100		{
101			name: "with message",
102			args: args{
103				err:    WithMessage(err, "test"),
104				target: new(customErr),
105			},
106			want: true,
107		},
108		{
109			name: "with message format",
110			args: args{
111				err:    WithMessagef(err, "%s", "test"),
112				target: new(customErr),
113			},
114			want: true,
115		},
116		{
117			name: "std errors compatibility",
118			args: args{
119				err:    fmt.Errorf("wrap it: %w", err),
120				target: new(customErr),
121			},
122			want: true,
123		},
124	}
125	for _, tt := range tests {
126		t.Run(tt.name, func(t *testing.T) {
127			if got := As(tt.args.err, tt.args.target); got != tt.want {
128				t.Errorf("As() = %v, want %v", got, tt.want)
129			}
130
131			ce := tt.args.target.(*customErr)
132			if !reflect.DeepEqual(err, *ce) {
133				t.Errorf("set target error failed, target error is %v", *ce)
134			}
135		})
136	}
137}
138
139func TestUnwrap(t *testing.T) {
140	err := New("test")
141
142	type args struct {
143		err error
144	}
145	tests := []struct {
146		name string
147		args args
148		want error
149	}{
150		{
151			name: "with stack",
152			args: args{err: WithStack(err)},
153			want: err,
154		},
155		{
156			name: "with message",
157			args: args{err: WithMessage(err, "test")},
158			want: err,
159		},
160		{
161			name: "with message format",
162			args: args{err: WithMessagef(err, "%s", "test")},
163			want: err,
164		},
165		{
166			name: "std errors compatibility",
167			args: args{err: fmt.Errorf("wrap: %w", err)},
168			want: err,
169		},
170	}
171	for _, tt := range tests {
172		t.Run(tt.name, func(t *testing.T) {
173			if err := Unwrap(tt.args.err); !reflect.DeepEqual(err, tt.want) {
174				t.Errorf("Unwrap() error = %v, want %v", err, tt.want)
175			}
176		})
177	}
178}
179