arnaucube
arnaucube/mirror-to-giteaPublic Self-hosted repository
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}