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