/
be_caused_by.go
63 lines (56 loc) · 1.52 KB
/
be_caused_by.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
package matchers
import (
"github.com/hashicorp/go-multierror"
"github.com/onsi/gomega/types"
"github.com/pkg/errors"
)
type BeCausedByMatcher struct {
MatchError types.GomegaMatcher
}
func (m *BeCausedByMatcher) Match(actual interface{}) (success bool, err error) {
success, err = m.MatchError.Match(actual)
if success || err != nil {
return
}
// We now need to use recursive matching for everything.
// Eventually we'll unwind and hit the normal MatchError.Match call above.
actualErr := actual.(error)
if unwrapped := unwrap(actualErr); unwrapped != actualErr && m.matchRecursive(unwrapped) {
return true, nil
}
if cause := errors.Cause(actualErr); cause != actualErr && m.matchRecursive(cause) {
return true, nil
}
if me, ok := actualErr.(*multierror.Error); ok {
for _, e := range me.Errors {
if m.matchRecursive(e) {
return true, nil
}
}
}
return false, nil
}
func (m *BeCausedByMatcher) matchRecursive(err error) bool {
if err == nil {
return false
}
m2 := &BeCausedByMatcher{MatchError: m.MatchError}
success, _ := m2.Match(err)
return success
}
func (m *BeCausedByMatcher) FailureMessage(actual interface{}) (message string) {
return m.MatchError.FailureMessage(actual)
}
func (m *BeCausedByMatcher) NegatedFailureMessage(actual interface{}) (message string) {
panic("bad idea to use a matcher like this negated, it's too specific")
}
// Copied from Go 1.13 errors.Unwrap
func unwrap(err error) error {
u, ok := err.(interface {
Unwrap() error
})
if !ok {
return nil
}
return u.Unwrap()
}