initial commit
[govpp.git] / vendor / github.com / onsi / gomega / matchers / be_sent_matcher.go
1 package matchers
2
3 import (
4         "fmt"
5         "reflect"
6
7         "github.com/onsi/gomega/format"
8 )
9
10 type BeSentMatcher struct {
11         Arg           interface{}
12         channelClosed bool
13 }
14
15 func (matcher *BeSentMatcher) Match(actual interface{}) (success bool, err error) {
16         if !isChan(actual) {
17                 return false, fmt.Errorf("BeSent expects a channel.  Got:\n%s", format.Object(actual, 1))
18         }
19
20         channelType := reflect.TypeOf(actual)
21         channelValue := reflect.ValueOf(actual)
22
23         if channelType.ChanDir() == reflect.RecvDir {
24                 return false, fmt.Errorf("BeSent matcher cannot be passed a receive-only channel.  Got:\n%s", format.Object(actual, 1))
25         }
26
27         argType := reflect.TypeOf(matcher.Arg)
28         assignable := argType.AssignableTo(channelType.Elem())
29
30         if !assignable {
31                 return false, fmt.Errorf("Cannot pass:\n%s to the channel:\n%s\nThe types don't match.", format.Object(matcher.Arg, 1), format.Object(actual, 1))
32         }
33
34         argValue := reflect.ValueOf(matcher.Arg)
35
36         defer func() {
37                 if e := recover(); e != nil {
38                         success = false
39                         err = fmt.Errorf("Cannot send to a closed channel")
40                         matcher.channelClosed = true
41                 }
42         }()
43
44         winnerIndex, _, _ := reflect.Select([]reflect.SelectCase{
45                 reflect.SelectCase{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue},
46                 reflect.SelectCase{Dir: reflect.SelectDefault},
47         })
48
49         var didSend bool
50         if winnerIndex == 0 {
51                 didSend = true
52         }
53
54         return didSend, nil
55 }
56
57 func (matcher *BeSentMatcher) FailureMessage(actual interface{}) (message string) {
58         return format.Message(actual, "to send:", matcher.Arg)
59 }
60
61 func (matcher *BeSentMatcher) NegatedFailureMessage(actual interface{}) (message string) {
62         return format.Message(actual, "not to send:", matcher.Arg)
63 }
64
65 func (matcher *BeSentMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
66         if !isChan(actual) {
67                 return false
68         }
69
70         return !matcher.channelClosed
71 }