Skip to content

Commit 4cc5e15

Browse files
committed
Satisfy errors.Is even if formatting is incorrect
1 parent 54a9448 commit 4cc5e15

File tree

2 files changed

+51
-22
lines changed

2 files changed

+51
-22
lines changed

errortypes.go

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
package errors
55

66
import (
7-
"errors"
87
stderror "errors"
98
"fmt"
10-
"strings"
119
)
1210

1311
// a ConstError is a prototype for a certain type of error
@@ -86,12 +84,17 @@ func wrapErrorWithMsg(err error, msg string) error {
8684
return fmt.Errorf("%s: %w", msg, err)
8785
}
8886

89-
func makeWrappedConstError(err error, format string, args ...interface{}) error {
90-
separator := " "
91-
if err.Error() == "" || errors.Is(err, &fmtNoop{}) {
92-
separator = ""
87+
// fmtErrWithType returns an error with the provided error type and format.
88+
func fmtErrWithType(errType ConstError, hideSuffix bool, format string, args ...interface{}) error {
89+
msg := fmt.Sprintf(format, args...)
90+
if !hideSuffix {
91+
msg += " " + errType.Error()
92+
}
93+
94+
return &errWithType{
95+
error: New(msg),
96+
errType: errType,
9397
}
94-
return fmt.Errorf(strings.Join([]string{format, "%w"}, separator), append(args, err)...)
9598
}
9699

97100
// WithType is responsible for annotating an already existing error so that it
@@ -116,7 +119,7 @@ func WithType(err error, errType ConstError) error {
116119
// interface.
117120
func Timeoutf(format string, args ...interface{}) error {
118121
return newLocationError(
119-
makeWrappedConstError(Timeout, format, args...),
122+
fmtErrWithType(Timeout, false, format, args...),
120123
1,
121124
)
122125
}
@@ -140,7 +143,7 @@ func IsTimeout(err error) bool {
140143
// Locationer interface.
141144
func NotFoundf(format string, args ...interface{}) error {
142145
return newLocationError(
143-
makeWrappedConstError(NotFound, format, args...),
146+
fmtErrWithType(NotFound, false, format, args...),
144147
1,
145148
)
146149
}
@@ -164,7 +167,7 @@ func IsNotFound(err error) bool {
164167
// Locationer interface.
165168
func UserNotFoundf(format string, args ...interface{}) error {
166169
return newLocationError(
167-
makeWrappedConstError(UserNotFound, format, args...),
170+
fmtErrWithType(UserNotFound, false, format, args...),
168171
1,
169172
)
170173
}
@@ -188,7 +191,7 @@ func IsUserNotFound(err error) bool {
188191
// the Locationer interface.
189192
func Unauthorizedf(format string, args ...interface{}) error {
190193
return newLocationError(
191-
makeWrappedConstError(Hide(Unauthorized), format, args...),
194+
fmtErrWithType(Unauthorized, true, format, args...),
192195
1,
193196
)
194197
}
@@ -212,7 +215,7 @@ func IsUnauthorized(err error) bool {
212215
// the Locationer interface.
213216
func NotImplementedf(format string, args ...interface{}) error {
214217
return newLocationError(
215-
makeWrappedConstError(NotImplemented, format, args...),
218+
fmtErrWithType(NotImplemented, false, format, args...),
216219
1,
217220
)
218221
}
@@ -236,7 +239,7 @@ func IsNotImplemented(err error) bool {
236239
// the Locationer interface.
237240
func AlreadyExistsf(format string, args ...interface{}) error {
238241
return newLocationError(
239-
makeWrappedConstError(AlreadyExists, format, args...),
242+
fmtErrWithType(AlreadyExists, false, format, args...),
240243
1,
241244
)
242245
}
@@ -260,7 +263,7 @@ func IsAlreadyExists(err error) bool {
260263
// Locationer interface.
261264
func NotSupportedf(format string, args ...interface{}) error {
262265
return newLocationError(
263-
makeWrappedConstError(NotSupported, format, args...),
266+
fmtErrWithType(NotSupported, false, format, args...),
264267
1,
265268
)
266269
}
@@ -284,7 +287,7 @@ func IsNotSupported(err error) bool {
284287
// Locationer interface.
285288
func NotValidf(format string, args ...interface{}) error {
286289
return newLocationError(
287-
makeWrappedConstError(NotValid, format, args...),
290+
fmtErrWithType(NotValid, false, format, args...),
288291
1,
289292
)
290293
}
@@ -308,7 +311,7 @@ func IsNotValid(err error) bool {
308311
// the Locationer interface.
309312
func NotProvisionedf(format string, args ...interface{}) error {
310313
return newLocationError(
311-
makeWrappedConstError(NotProvisioned, format, args...),
314+
fmtErrWithType(NotProvisioned, false, format, args...),
312315
1,
313316
)
314317
}
@@ -332,7 +335,7 @@ func IsNotProvisioned(err error) bool {
332335
// Locationer interface.
333336
func NotAssignedf(format string, args ...interface{}) error {
334337
return newLocationError(
335-
makeWrappedConstError(NotAssigned, format, args...),
338+
fmtErrWithType(NotAssigned, false, format, args...),
336339
1,
337340
)
338341
}
@@ -356,7 +359,7 @@ func IsNotAssigned(err error) bool {
356359
// Locationer interface.
357360
func BadRequestf(format string, args ...interface{}) error {
358361
return newLocationError(
359-
makeWrappedConstError(Hide(BadRequest), format, args...),
362+
fmtErrWithType(BadRequest, true, format, args...),
360363
1,
361364
)
362365
}
@@ -380,7 +383,7 @@ func IsBadRequest(err error) bool {
380383
// and the Locationer interface.
381384
func MethodNotAllowedf(format string, args ...interface{}) error {
382385
return newLocationError(
383-
makeWrappedConstError(Hide(MethodNotAllowed), format, args...),
386+
fmtErrWithType(MethodNotAllowed, true, format, args...),
384387
1,
385388
)
386389
}
@@ -404,7 +407,7 @@ func IsMethodNotAllowed(err error) bool {
404407
// Locationer interface.
405408
func Forbiddenf(format string, args ...interface{}) error {
406409
return newLocationError(
407-
makeWrappedConstError(Hide(Forbidden), format, args...),
410+
fmtErrWithType(Forbidden, true, format, args...),
408411
1,
409412
)
410413
}
@@ -428,7 +431,7 @@ func IsForbidden(err error) bool {
428431
// Is(err, QuotaLimitExceeded) and the Locationer interface.
429432
func QuotaLimitExceededf(format string, args ...interface{}) error {
430433
return newLocationError(
431-
makeWrappedConstError(Hide(QuotaLimitExceeded), format, args...),
434+
fmtErrWithType(QuotaLimitExceeded, true, format, args...),
432435
1,
433436
)
434437
}
@@ -452,7 +455,7 @@ func IsQuotaLimitExceeded(err error) bool {
452455
// and the Locationer interface.
453456
func NotYetAvailablef(format string, args ...interface{}) error {
454457
return newLocationError(
455-
makeWrappedConstError(Hide(NotYetAvailable), format, args...),
458+
fmtErrWithType(NotYetAvailable, true, format, args...),
456459
1,
457460
)
458461
}

errortypes_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,29 @@ func (*errorTypeSuite) TestWithType(c *gc.C) {
193193
c.Assert(err.Error(), gc.Equals, "yes")
194194
c.Assert(errors.Is(err, myErr2), gc.Equals, false)
195195
}
196+
197+
func (*errorTypeSuite) TestBadFormatNotEnoughArgs(c *gc.C) {
198+
errorTests := make([]errorTest, 0, len(allErrors))
199+
for _, errInfo := range allErrors {
200+
errorTests = append(errorTests, errorTest{
201+
errInfo.argsConstructor("missing arg %v"),
202+
".*",
203+
errInfo,
204+
})
205+
}
206+
207+
runErrorTests(c, errorTests, true)
208+
}
209+
210+
func (*errorTypeSuite) TestBadFormatTooManyArgs(c *gc.C) {
211+
errorTests := make([]errorTest, 0, len(allErrors))
212+
for _, errInfo := range allErrors {
213+
errorTests = append(errorTests, errorTest{
214+
errInfo.argsConstructor("extra arg %v", "foo", "bar"),
215+
".*",
216+
errInfo,
217+
})
218+
}
219+
220+
runErrorTests(c, errorTests, true)
221+
}

0 commit comments

Comments
 (0)