initial commit
[govpp.git] / vendor / github.com / onsi / gomega / matchers / with_transform.go
1 package matchers
2
3 import (
4         "fmt"
5         "reflect"
6
7         "github.com/onsi/gomega/internal/oraclematcher"
8         "github.com/onsi/gomega/types"
9 )
10
11 type WithTransformMatcher struct {
12         // input
13         Transform interface{} // must be a function of one parameter that returns one value
14         Matcher   types.GomegaMatcher
15
16         // cached value
17         transformArgType reflect.Type
18
19         // state
20         transformedValue interface{}
21 }
22
23 func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) *WithTransformMatcher {
24         if transform == nil {
25                 panic("transform function cannot be nil")
26         }
27         txType := reflect.TypeOf(transform)
28         if txType.NumIn() != 1 {
29                 panic("transform function must have 1 argument")
30         }
31         if txType.NumOut() != 1 {
32                 panic("transform function must have 1 return value")
33         }
34
35         return &WithTransformMatcher{
36                 Transform:        transform,
37                 Matcher:          matcher,
38                 transformArgType: reflect.TypeOf(transform).In(0),
39         }
40 }
41
42 func (m *WithTransformMatcher) Match(actual interface{}) (bool, error) {
43         // return error if actual's type is incompatible with Transform function's argument type
44         actualType := reflect.TypeOf(actual)
45         if !actualType.AssignableTo(m.transformArgType) {
46                 return false, fmt.Errorf("Transform function expects '%s' but we have '%s'", m.transformArgType, actualType)
47         }
48
49         // call the Transform function with `actual`
50         fn := reflect.ValueOf(m.Transform)
51         result := fn.Call([]reflect.Value{reflect.ValueOf(actual)})
52         m.transformedValue = result[0].Interface() // expect exactly one value
53
54         return m.Matcher.Match(m.transformedValue)
55 }
56
57 func (m *WithTransformMatcher) FailureMessage(_ interface{}) (message string) {
58         return m.Matcher.FailureMessage(m.transformedValue)
59 }
60
61 func (m *WithTransformMatcher) NegatedFailureMessage(_ interface{}) (message string) {
62         return m.Matcher.NegatedFailureMessage(m.transformedValue)
63 }
64
65 func (m *WithTransformMatcher) MatchMayChangeInTheFuture(_ interface{}) bool {
66         // TODO: Maybe this should always just return true? (Only an issue for non-deterministic transformers.)
67         //
68         // Querying the next matcher is fine if the transformer always will return the same value.
69         // But if the transformer is non-deterministic and returns a different value each time, then there
70         // is no point in querying the next matcher, since it can only comment on the last transformed value.
71         return oraclematcher.MatchMayChangeInTheFuture(m.Matcher, m.transformedValue)
72 }