github.com/mailgun/holster/v4@v4.20.0/errors/errors_test.go (about) 1 package errors 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestNew(t *testing.T) { 13 tests := []struct { 14 err string 15 want error 16 }{ 17 {"", fmt.Errorf("")}, 18 {"foo", fmt.Errorf("foo")}, 19 {"foo", New("foo")}, 20 {"string with format specifiers: %v", errors.New("string with format specifiers: %v")}, 21 } 22 23 for _, tt := range tests { 24 got := New(tt.err) 25 if got.Error() != tt.want.Error() { 26 t.Errorf("New.Error(): got: %q, want %q", got, tt.want) 27 } 28 } 29 } 30 31 func TestWrapNil(t *testing.T) { 32 got := Wrap(nil, "no error") 33 if got != nil { 34 t.Errorf("Wrap(nil, \"no error\"): got %#v, expected nil", got) 35 } 36 } 37 38 func TestWrap(t *testing.T) { 39 tests := []struct { 40 err error 41 message string 42 want string 43 }{ 44 {io.EOF, "read error", "read error: EOF"}, 45 {Wrap(io.EOF, "read error"), "client error", "client error: read error: EOF"}, 46 } 47 48 for _, tt := range tests { 49 got := Wrap(tt.err, tt.message).Error() 50 if got != tt.want { 51 t.Errorf("Wrap(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) 52 } 53 } 54 } 55 56 type nilError struct{} 57 58 func (nilError) Error() string { return "nil error" } 59 60 func TestCause(t *testing.T) { 61 x := New("error") 62 tests := []struct { 63 err error 64 want error 65 }{{ 66 // nil error is nil 67 err: nil, 68 want: nil, 69 }, { 70 // explicit nil error is nil 71 err: error(nil), 72 want: nil, 73 }, { 74 // typed nil is nil 75 err: (*nilError)(nil), 76 want: (*nilError)(nil), 77 }, { 78 // uncaused error is unaffected 79 err: io.EOF, 80 want: io.EOF, 81 }, { 82 // caused error returns cause 83 err: Wrap(io.EOF, "ignored"), 84 want: io.EOF, 85 }, { 86 err: x, // return from errors.New 87 want: x, 88 }, { 89 WithMessage(nil, "whoops"), 90 nil, 91 }, { 92 WithMessage(io.EOF, "whoops"), 93 io.EOF, 94 }, { 95 WithStack(nil), 96 nil, 97 }, { 98 WithStack(io.EOF), 99 io.EOF, 100 }} 101 102 for i, tt := range tests { 103 got := Cause(tt.err) 104 require.ErrorIsf(t, tt.want, got, "test %d: got %#v, want %#v", i+1, got, tt.want) 105 } 106 } 107 108 func TestWrapfNil(t *testing.T) { 109 got := Wrapf(nil, "no error") 110 if got != nil { 111 t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got) 112 } 113 } 114 115 func TestWrapf(t *testing.T) { 116 tests := []struct { 117 err error 118 message string 119 want string 120 }{ 121 {io.EOF, "read error", "read error: EOF"}, 122 {Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"}, 123 {Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"}, 124 } 125 126 for _, tt := range tests { 127 got := Wrapf(tt.err, tt.message).Error() 128 if got != tt.want { 129 t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) 130 } 131 } 132 } 133 134 func TestErrorf(t *testing.T) { 135 tests := []struct { 136 err error 137 want string 138 }{ 139 {Errorf("read error without format specifiers"), "read error without format specifiers"}, 140 {Errorf("read error with %d format specifier", 1), "read error with 1 format specifier"}, 141 } 142 143 for _, tt := range tests { 144 got := tt.err.Error() 145 if got != tt.want { 146 t.Errorf("Errorf(%v): got: %q, want %q", tt.err, got, tt.want) 147 } 148 } 149 } 150 151 func TestWithStackNil(t *testing.T) { 152 got := WithStack(nil) 153 if got != nil { 154 t.Errorf("WithStack(nil): got %#v, expected nil", got) 155 } 156 } 157 158 func TestWithStack(t *testing.T) { 159 tests := []struct { 160 err error 161 want string 162 }{ 163 {io.EOF, "EOF"}, 164 {WithStack(io.EOF), "EOF"}, 165 } 166 167 for _, tt := range tests { 168 got := WithStack(tt.err).Error() 169 if got != tt.want { 170 t.Errorf("WithStack(%v): got: %v, want %v", tt.err, got, tt.want) 171 } 172 } 173 } 174 175 func TestWithMessageNil(t *testing.T) { 176 got := WithMessage(nil, "no error") 177 if got != nil { 178 t.Errorf("WithMessage(nil, \"no error\"): got %#v, expected nil", got) 179 } 180 } 181 182 func TestWithMessage(t *testing.T) { 183 tests := []struct { 184 err error 185 message string 186 want string 187 }{ 188 {io.EOF, "read error", "read error: EOF"}, 189 {WithMessage(io.EOF, "read error"), "client error", "client error: read error: EOF"}, 190 } 191 192 for _, tt := range tests { 193 got := WithMessage(tt.err, tt.message).Error() 194 if got != tt.want { 195 t.Errorf("WithMessage(%v, %q): got: %q, want %q", tt.err, tt.message, got, tt.want) 196 } 197 } 198 } 199 200 // errors.New, etc values are not expected to be compared by value 201 // but the change in errors#27 made them incomparable. Assert that 202 // various kinds of errors have a functional equality operator, even 203 // if the result of that equality is always false. 204 func TestErrorEquality(t *testing.T) { 205 vals := []error{ 206 nil, 207 io.EOF, 208 errors.New("EOF"), 209 New("EOF"), 210 Errorf("EOF"), 211 Wrap(io.EOF, "EOF"), 212 Wrapf(io.EOF, "EOF%d", 2), 213 WithMessage(nil, "whoops"), 214 WithMessage(io.EOF, "whoops"), 215 WithStack(io.EOF), 216 WithStack(nil), 217 } 218 219 for i := range vals { 220 for j := range vals { 221 _ = vals[i] == vals[j] // mustn't panic 222 } 223 } 224 }