-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmatch.go
88 lines (80 loc) · 2.94 KB
/
match.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package errors
import (
"fmt"
"reflect"
)
// Match compares its two error arguments. It can be used to check for
// expected errors in tests. Both arguments must have underlying type
// *Error or Match will return false. Otherwise, it returns true iff
// every non-zero field of the template error is equal to the
// corresponding field of the error being checked. If the Err field is
// a *Error, Match recurs on that field; otherwise it compares the
// strings returned by the Error methods. Elements that are in the
// second argument but not present in the first are ignored.
//
// For example,
//
// errors.Match(errors.E(errors.WithOp("service.MakeBooking"), errors.PermissionDenied), err)
//
// tests whether err is an Error with Kind=PermissionDenied and
// Op=service.MakeBooking.
func Match(template, err error) bool {
return len(Diff(template, err)) == 0
}
// Diff compares and returns the diff between two error arguments. It
// can be used to extract the exact details of difference between
// expected and got errors in tests. It returns an empty array iff
// both arguments are of type *Error and every non-zero field of the
// template error is equal to the corresponding field of the second. If
// the Err field is a *Error, Diff recurs on that field; otherwise it
// compares the strings returned by the Error methods. Elements that are
// in the second argument but not present in the template are ignored.
//
// For example,
//
// errors.Diff(errors.E(errors.WithOp("service.MakeBooking"), errors.PermissionDenied), err)
//
// tests whether err is an Error with Kind=PermissionDenied and
// Op=service.MakeBooking.
func Diff(template, err error) []string { //nolint: gocognit
t, ok1 := template.(*Error)
e, ok2 := err.(*Error)
if !ok1 || !ok2 {
return []string{fmt.Sprintf(`template="%v"(type %[1]T); err="%v"(type %[2]T)`, template, err)}
}
var diff []string
if t.Op != "" && t.Op != e.Op {
diff = append(diff, fmt.Sprintf("Op: template=%q; err=%q", t.Op, e.Op))
}
if t.Kind != Unknown && t.Kind != e.Kind {
diff = append(diff, fmt.Sprintf("Kind: template=%q; err=%q", t.Kind, e.Kind))
}
if t.Text != "" && t.Text != e.Text {
diff = append(diff, fmt.Sprintf("Text: template=%q; err=%q", t.Text, e.Text))
}
if t.UserMsg != "" && t.UserMsg != e.UserMsg {
diff = append(diff, fmt.Sprintf("UserMsg: template=%q; err=%q", t.UserMsg, e.UserMsg))
}
if t.Data != nil && !reflect.DeepEqual(t.Data, e.Data) {
diff = append(diff, fmt.Sprintf(`Data: template="%#v"; err="%#v"`, t.Data, e.Data))
}
if t.Err == nil {
return diff
}
switch t.Err.(type) {
case *Error:
cdiff := Diff(t.Err, e.Err)
if len(cdiff) == 0 {
return diff
}
diff = append(diff, "Diff(template.Err, err.Err)=")
for _, d := range cdiff {
diff = append(diff, "\t"+d)
}
default:
if e.Err == nil || e.Err.Error() != t.Err.Error() {
diff = append(diff, fmt.Sprintf(`Err(nested): template="%v"(type %[1]T); err="%v"(type %[2]T)`, t.Err, e.Err))
}
}
return diff
}