| package matchers | 
 |  | 
 | import ( | 
 | 	"fmt" | 
 | 	"reflect" | 
 |  | 
 | 	"github.com/onsi/gomega/format" | 
 | ) | 
 |  | 
 | type BeSentMatcher struct { | 
 | 	Arg           interface{} | 
 | 	channelClosed bool | 
 | } | 
 |  | 
 | func (matcher *BeSentMatcher) Match(actual interface{}) (success bool, err error) { | 
 | 	if !isChan(actual) { | 
 | 		return false, fmt.Errorf("BeSent expects a channel.  Got:\n%s", format.Object(actual, 1)) | 
 | 	} | 
 |  | 
 | 	channelType := reflect.TypeOf(actual) | 
 | 	channelValue := reflect.ValueOf(actual) | 
 |  | 
 | 	if channelType.ChanDir() == reflect.RecvDir { | 
 | 		return false, fmt.Errorf("BeSent matcher cannot be passed a receive-only channel.  Got:\n%s", format.Object(actual, 1)) | 
 | 	} | 
 |  | 
 | 	argType := reflect.TypeOf(matcher.Arg) | 
 | 	assignable := argType.AssignableTo(channelType.Elem()) | 
 |  | 
 | 	if !assignable { | 
 | 		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)) | 
 | 	} | 
 |  | 
 | 	argValue := reflect.ValueOf(matcher.Arg) | 
 |  | 
 | 	defer func() { | 
 | 		if e := recover(); e != nil { | 
 | 			success = false | 
 | 			err = fmt.Errorf("Cannot send to a closed channel") | 
 | 			matcher.channelClosed = true | 
 | 		} | 
 | 	}() | 
 |  | 
 | 	winnerIndex, _, _ := reflect.Select([]reflect.SelectCase{ | 
 | 		reflect.SelectCase{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue}, | 
 | 		reflect.SelectCase{Dir: reflect.SelectDefault}, | 
 | 	}) | 
 |  | 
 | 	var didSend bool | 
 | 	if winnerIndex == 0 { | 
 | 		didSend = true | 
 | 	} | 
 |  | 
 | 	return didSend, nil | 
 | } | 
 |  | 
 | func (matcher *BeSentMatcher) FailureMessage(actual interface{}) (message string) { | 
 | 	return format.Message(actual, "to send:", matcher.Arg) | 
 | } | 
 |  | 
 | func (matcher *BeSentMatcher) NegatedFailureMessage(actual interface{}) (message string) { | 
 | 	return format.Message(actual, "not to send:", matcher.Arg) | 
 | } | 
 |  | 
 | func (matcher *BeSentMatcher) MatchMayChangeInTheFuture(actual interface{}) bool { | 
 | 	if !isChan(actual) { | 
 | 		return false | 
 | 	} | 
 |  | 
 | 	return !matcher.channelClosed | 
 | } |