mirror-to-gitea/vendor/github.com/onsi/gomega/matchers/satisfy_matcher.go
vendor/github.com/onsi/gomega/matchers/satisfy_matcher.goRaw
1package matchers
2
3import (
4 "fmt"
5 "reflect"
6
7 "github.com/onsi/gomega/format"
8)
9
10type SatisfyMatcher struct {
11 Predicate interface{}
12
13 // cached type
14 predicateArgType reflect.Type
15}
16
17func NewSatisfyMatcher(predicate interface{}) *SatisfyMatcher {
18 if predicate == nil {
19 panic("predicate cannot be nil")
20 }
21 predicateType := reflect.TypeOf(predicate)
22 if predicateType.Kind() != reflect.Func {
23 panic("predicate must be a function")
24 }
25 if predicateType.NumIn() != 1 {
26 panic("predicate must have 1 argument")
27 }
28 if predicateType.NumOut() != 1 || predicateType.Out(0).Kind() != reflect.Bool {
29 panic("predicate must return bool")
30 }
31
32 return &SatisfyMatcher{
33 Predicate: predicate,
34 predicateArgType: predicateType.In(0),
35 }
36}
37
38func (m *SatisfyMatcher) Match(actual interface{}) (success bool, err error) {
39 // prepare a parameter to pass to the predicate
40 var param reflect.Value
41 if actual != nil && reflect.TypeOf(actual).AssignableTo(m.predicateArgType) {
42 // The dynamic type of actual is compatible with the predicate argument.
43 param = reflect.ValueOf(actual)
44
45 } else if actual == nil && m.predicateArgType.Kind() == reflect.Interface {
46 // The dynamic type of actual is unknown, so there's no way to make its
47 // reflect.Value. Create a nil of the predicate argument, which is known.
48 param = reflect.Zero(m.predicateArgType)
49
50 } else {
51 return false, fmt.Errorf("predicate expects '%s' but we have '%T'", m.predicateArgType, actual)
52 }
53
54 // call the predicate with `actual`
55 fn := reflect.ValueOf(m.Predicate)
56 result := fn.Call([]reflect.Value{param})
57 return result[0].Bool(), nil
58}
59
60func (m *SatisfyMatcher) FailureMessage(actual interface{}) (message string) {
61 return format.Message(actual, "to satisfy predicate", m.Predicate)
62}
63
64func (m *SatisfyMatcher) NegatedFailureMessage(actual interface{}) (message string) {
65 return format.Message(actual, "to not satisfy predicate", m.Predicate)
66}