initial commit
[govpp.git] / vendor / github.com / onsi / gomega / matchers / receive_matcher.go
1 package matchers
2
3 import (
4         "fmt"
5         "reflect"
6
7         "github.com/onsi/gomega/format"
8 )
9
10 type ReceiveMatcher struct {
11         Arg           interface{}
12         receivedValue reflect.Value
13         channelClosed bool
14 }
15
16 func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err error) {
17         if !isChan(actual) {
18                 return false, fmt.Errorf("ReceiveMatcher expects a channel.  Got:\n%s", format.Object(actual, 1))
19         }
20
21         channelType := reflect.TypeOf(actual)
22         channelValue := reflect.ValueOf(actual)
23
24         if channelType.ChanDir() == reflect.SendDir {
25                 return false, fmt.Errorf("ReceiveMatcher matcher cannot be passed a send-only channel.  Got:\n%s", format.Object(actual, 1))
26         }
27
28         var subMatcher omegaMatcher
29         var hasSubMatcher bool
30
31         if matcher.Arg != nil {
32                 subMatcher, hasSubMatcher = (matcher.Arg).(omegaMatcher)
33                 if !hasSubMatcher {
34                         argType := reflect.TypeOf(matcher.Arg)
35                         if argType.Kind() != reflect.Ptr {
36                                 return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s\nYou need to pass a pointer!", format.Object(actual, 1), format.Object(matcher.Arg, 1))
37                         }
38
39                         assignable := channelType.Elem().AssignableTo(argType.Elem())
40                         if !assignable {
41                                 return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(matcher.Arg, 1))
42                         }
43                 }
44         }
45
46         winnerIndex, value, open := reflect.Select([]reflect.SelectCase{
47                 reflect.SelectCase{Dir: reflect.SelectRecv, Chan: channelValue},
48                 reflect.SelectCase{Dir: reflect.SelectDefault},
49         })
50
51         var closed bool
52         var didReceive bool
53         if winnerIndex == 0 {
54                 closed = !open
55                 didReceive = open
56         }
57         matcher.channelClosed = closed
58
59         if closed {
60                 return false, nil
61         }
62
63         if hasSubMatcher {
64                 if didReceive {
65                         matcher.receivedValue = value
66                         return subMatcher.Match(matcher.receivedValue.Interface())
67                 } else {
68                         return false, nil
69                 }
70         }
71
72         if didReceive {
73                 if matcher.Arg != nil {
74                         outValue := reflect.ValueOf(matcher.Arg)
75                         reflect.Indirect(outValue).Set(value)
76                 }
77
78                 return true, nil
79         } else {
80                 return false, nil
81         }
82 }
83
84 func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message string) {
85         subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher)
86
87         closedAddendum := ""
88         if matcher.channelClosed {
89                 closedAddendum = " The channel is closed."
90         }
91
92         if hasSubMatcher {
93                 if matcher.receivedValue.IsValid() {
94                         return subMatcher.FailureMessage(matcher.receivedValue.Interface())
95                 }
96                 return "When passed a matcher, ReceiveMatcher's channel *must* receive something."
97         } else {
98                 return format.Message(actual, "to receive something."+closedAddendum)
99         }
100 }
101
102 func (matcher *ReceiveMatcher) NegatedFailureMessage(actual interface{}) (message string) {
103         subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher)
104
105         closedAddendum := ""
106         if matcher.channelClosed {
107                 closedAddendum = " The channel is closed."
108         }
109
110         if hasSubMatcher {
111                 if matcher.receivedValue.IsValid() {
112                         return subMatcher.NegatedFailureMessage(matcher.receivedValue.Interface())
113                 }
114                 return "When passed a matcher, ReceiveMatcher's channel *must* receive something."
115         } else {
116                 return format.Message(actual, "not to receive anything."+closedAddendum)
117         }
118 }
119
120 func (matcher *ReceiveMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
121         if !isChan(actual) {
122                 return false
123         }
124
125         return !matcher.channelClosed
126 }