arnaucube
arnaucube/mirror-to-giteaPublic Self-hosted repository
mirror-to-gitea/vendor/github.com/onsi/gomega/matchers/be_sent_matcher.go
vendor/github.com/onsi/gomega/matchers/be_sent_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 BeSentMatcher struct {
13	Arg           interface{}
14	channelClosed bool
15}
16
17func (matcher *BeSentMatcher) Match(actual interface{}) (success bool, err error) {
18	if !isChan(actual) {
19		return false, fmt.Errorf("BeSent expects a channel.  Got:\n%s", format.Object(actual, 1))
20	}
21
22	channelType := reflect.TypeOf(actual)
23	channelValue := reflect.ValueOf(actual)
24
25	if channelType.ChanDir() == reflect.RecvDir {
26		return false, fmt.Errorf("BeSent matcher cannot be passed a receive-only channel.  Got:\n%s", format.Object(actual, 1))
27	}
28
29	argType := reflect.TypeOf(matcher.Arg)
30	assignable := argType.AssignableTo(channelType.Elem())
31
32	if !assignable {
33		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))
34	}
35
36	argValue := reflect.ValueOf(matcher.Arg)
37
38	defer func() {
39		if e := recover(); e != nil {
40			success = false
41			err = fmt.Errorf("Cannot send to a closed channel")
42			matcher.channelClosed = true
43		}
44	}()
45
46	winnerIndex, _, _ := reflect.Select([]reflect.SelectCase{
47		{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue},
48		{Dir: reflect.SelectDefault},
49	})
50
51	var didSend bool
52	if winnerIndex == 0 {
53		didSend = true
54	}
55
56	return didSend, nil
57}
58
59func (matcher *BeSentMatcher) FailureMessage(actual interface{}) (message string) {
60	return format.Message(actual, "to send:", matcher.Arg)
61}
62
63func (matcher *BeSentMatcher) NegatedFailureMessage(actual interface{}) (message string) {
64	return format.Message(actual, "not to send:", matcher.Arg)
65}
66
67func (matcher *BeSentMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
68	if !isChan(actual) {
69		return false
70	}
71
72	return !matcher.channelClosed
73}