1 package multierror
2
3 import (
4 "errors"
5 "fmt"
6 "reflect"
7 "testing"
8 )
9
10 func TestError_Impl(t *testing.T) {
11 var _ error = new(Error)
12 }
13
14 func TestErrorError_custom(t *testing.T) {
15 errors := []error{
16 errors.New("foo"),
17 errors.New("bar"),
18 }
19
20 fn := func(es []error) string {
21 return "foo"
22 }
23
24 multi := &Error{Errors: errors, ErrorFormat: fn}
25 if multi.Error() != "foo" {
26 t.Fatalf("bad: %s", multi.Error())
27 }
28 }
29
30 func TestErrorError_default(t *testing.T) {
31 expected := `2 errors occurred:
32 * foo
33 * bar
34
35 `
36
37 errors := []error{
38 errors.New("foo"),
39 errors.New("bar"),
40 }
41
42 multi := &Error{Errors: errors}
43 if multi.Error() != expected {
44 t.Fatalf("bad: %s", multi.Error())
45 }
46 }
47
48 func TestErrorErrorOrNil(t *testing.T) {
49 err := new(Error)
50 if err.ErrorOrNil() != nil {
51 t.Fatalf("bad: %#v", err.ErrorOrNil())
52 }
53
54 err.Errors = []error{errors.New("foo")}
55 if v := err.ErrorOrNil(); v == nil {
56 t.Fatal("should not be nil")
57 } else if !reflect.DeepEqual(v, err) {
58 t.Fatalf("bad: %#v", v)
59 }
60 }
61
62 func TestErrorWrappedErrors(t *testing.T) {
63 errors := []error{
64 errors.New("foo"),
65 errors.New("bar"),
66 }
67
68 multi := &Error{Errors: errors}
69 if !reflect.DeepEqual(multi.Errors, multi.WrappedErrors()) {
70 t.Fatalf("bad: %s", multi.WrappedErrors())
71 }
72
73 multi = nil
74 if err := multi.WrappedErrors(); err != nil {
75 t.Fatalf("bad: %#v", multi)
76 }
77 }
78
79 func TestErrorUnwrap(t *testing.T) {
80 t.Run("with errors", func(t *testing.T) {
81 err := &Error{Errors: []error{
82 errors.New("foo"),
83 errors.New("bar"),
84 errors.New("baz"),
85 }}
86
87 var current error = err
88 for i := 0; i < len(err.Errors); i++ {
89 current = errors.Unwrap(current)
90 if !errors.Is(current, err.Errors[i]) {
91 t.Fatal("should be next value")
92 }
93 }
94
95 if errors.Unwrap(current) != nil {
96 t.Fatal("should be nil at the end")
97 }
98 })
99
100 t.Run("with no errors", func(t *testing.T) {
101 err := &Error{Errors: nil}
102 if errors.Unwrap(err) != nil {
103 t.Fatal("should be nil")
104 }
105 })
106
107 t.Run("with nil multierror", func(t *testing.T) {
108 var err *Error
109 if errors.Unwrap(err) != nil {
110 t.Fatal("should be nil")
111 }
112 })
113 }
114
115 func TestErrorIs(t *testing.T) {
116 errBar := errors.New("bar")
117
118 t.Run("with errBar", func(t *testing.T) {
119 err := &Error{Errors: []error{
120 errors.New("foo"),
121 errBar,
122 errors.New("baz"),
123 }}
124
125 if !errors.Is(err, errBar) {
126 t.Fatal("should be true")
127 }
128 })
129
130 t.Run("with errBar wrapped by fmt.Errorf", func(t *testing.T) {
131 err := &Error{Errors: []error{
132 errors.New("foo"),
133 fmt.Errorf("errorf: %w", errBar),
134 errors.New("baz"),
135 }}
136
137 if !errors.Is(err, errBar) {
138 t.Fatal("should be true")
139 }
140 })
141
142 t.Run("without errBar", func(t *testing.T) {
143 err := &Error{Errors: []error{
144 errors.New("foo"),
145 errors.New("baz"),
146 }}
147
148 if errors.Is(err, errBar) {
149 t.Fatal("should be false")
150 }
151 })
152 }
153
154 func TestErrorAs(t *testing.T) {
155 match := &nestedError{}
156
157 t.Run("with the value", func(t *testing.T) {
158 err := &Error{Errors: []error{
159 errors.New("foo"),
160 match,
161 errors.New("baz"),
162 }}
163
164 var target *nestedError
165 if !errors.As(err, &target) {
166 t.Fatal("should be true")
167 }
168 if target == nil {
169 t.Fatal("target should not be nil")
170 }
171 })
172
173 t.Run("with the value wrapped by fmt.Errorf", func(t *testing.T) {
174 err := &Error{Errors: []error{
175 errors.New("foo"),
176 fmt.Errorf("errorf: %w", match),
177 errors.New("baz"),
178 }}
179
180 var target *nestedError
181 if !errors.As(err, &target) {
182 t.Fatal("should be true")
183 }
184 if target == nil {
185 t.Fatal("target should not be nil")
186 }
187 })
188
189 t.Run("without the value", func(t *testing.T) {
190 err := &Error{Errors: []error{
191 errors.New("foo"),
192 errors.New("baz"),
193 }}
194
195 var target *nestedError
196 if errors.As(err, &target) {
197 t.Fatal("should be false")
198 }
199 if target != nil {
200 t.Fatal("target should be nil")
201 }
202 })
203 }
204
205
206 type nestedError struct{}
207
208 func (*nestedError) Error() string { return "" }
209
View as plain text