| package matchers_test | 
 |  | 
 | import ( | 
 | 	"time" | 
 |  | 
 | 	. "github.com/onsi/ginkgo" | 
 | 	. "github.com/onsi/gomega" | 
 | 	. "github.com/onsi/gomega/matchers" | 
 | ) | 
 |  | 
 | type kungFuActor interface { | 
 | 	DrunkenMaster() bool | 
 | } | 
 |  | 
 | type jackie struct { | 
 | 	name string | 
 | } | 
 |  | 
 | func (j *jackie) DrunkenMaster() bool { | 
 | 	return true | 
 | } | 
 |  | 
 | var _ = Describe("ReceiveMatcher", func() { | 
 | 	Context("with no argument", func() { | 
 | 		Context("for a buffered channel", func() { | 
 | 			It("should succeed", func() { | 
 | 				channel := make(chan bool, 1) | 
 |  | 
 | 				Ω(channel).ShouldNot(Receive()) | 
 |  | 
 | 				channel <- true | 
 |  | 
 | 				Ω(channel).Should(Receive()) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("for an unbuffered channel", func() { | 
 | 			It("should succeed (eventually)", func() { | 
 | 				channel := make(chan bool) | 
 |  | 
 | 				Ω(channel).ShouldNot(Receive()) | 
 |  | 
 | 				go func() { | 
 | 					time.Sleep(10 * time.Millisecond) | 
 | 					channel <- true | 
 | 				}() | 
 |  | 
 | 				Eventually(channel).Should(Receive()) | 
 | 			}) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Context("with a pointer argument", func() { | 
 | 		Context("of the correct type", func() { | 
 | 			It("should write the value received on the channel to the pointer", func() { | 
 | 				channel := make(chan int, 1) | 
 |  | 
 | 				var value int | 
 |  | 
 | 				Ω(channel).ShouldNot(Receive(&value)) | 
 | 				Ω(value).Should(BeZero()) | 
 |  | 
 | 				channel <- 17 | 
 |  | 
 | 				Ω(channel).Should(Receive(&value)) | 
 | 				Ω(value).Should(Equal(17)) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("to various types of objects", func() { | 
 | 			It("should work", func() { | 
 | 				//channels of strings | 
 | 				stringChan := make(chan string, 1) | 
 | 				stringChan <- "foo" | 
 |  | 
 | 				var s string | 
 | 				Ω(stringChan).Should(Receive(&s)) | 
 | 				Ω(s).Should(Equal("foo")) | 
 |  | 
 | 				//channels of slices | 
 | 				sliceChan := make(chan []bool, 1) | 
 | 				sliceChan <- []bool{true, true, false} | 
 |  | 
 | 				var sl []bool | 
 | 				Ω(sliceChan).Should(Receive(&sl)) | 
 | 				Ω(sl).Should(Equal([]bool{true, true, false})) | 
 |  | 
 | 				//channels of channels | 
 | 				chanChan := make(chan chan bool, 1) | 
 | 				c := make(chan bool) | 
 | 				chanChan <- c | 
 |  | 
 | 				var receivedC chan bool | 
 | 				Ω(chanChan).Should(Receive(&receivedC)) | 
 | 				Ω(receivedC).Should(Equal(c)) | 
 |  | 
 | 				//channels of interfaces | 
 | 				jackieChan := make(chan kungFuActor, 1) | 
 | 				aJackie := &jackie{name: "Jackie Chan"} | 
 | 				jackieChan <- aJackie | 
 |  | 
 | 				var theJackie kungFuActor | 
 | 				Ω(jackieChan).Should(Receive(&theJackie)) | 
 | 				Ω(theJackie).Should(Equal(aJackie)) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("of the wrong type", func() { | 
 | 			It("should error", func() { | 
 | 				channel := make(chan int) | 
 | 				var incorrectType bool | 
 |  | 
 | 				success, err := (&ReceiveMatcher{Arg: &incorrectType}).Match(channel) | 
 | 				Ω(success).Should(BeFalse()) | 
 | 				Ω(err).Should(HaveOccurred()) | 
 |  | 
 | 				var notAPointer int | 
 | 				success, err = (&ReceiveMatcher{Arg: notAPointer}).Match(channel) | 
 | 				Ω(success).Should(BeFalse()) | 
 | 				Ω(err).Should(HaveOccurred()) | 
 | 			}) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Context("with a matcher", func() { | 
 | 		It("should defer to the underlying matcher", func() { | 
 | 			intChannel := make(chan int, 1) | 
 | 			intChannel <- 3 | 
 | 			Ω(intChannel).Should(Receive(Equal(3))) | 
 |  | 
 | 			intChannel <- 2 | 
 | 			Ω(intChannel).ShouldNot(Receive(Equal(3))) | 
 |  | 
 | 			stringChannel := make(chan []string, 1) | 
 | 			stringChannel <- []string{"foo", "bar", "baz"} | 
 | 			Ω(stringChannel).Should(Receive(ContainElement(ContainSubstring("fo")))) | 
 |  | 
 | 			stringChannel <- []string{"foo", "bar", "baz"} | 
 | 			Ω(stringChannel).ShouldNot(Receive(ContainElement(ContainSubstring("archipelago")))) | 
 | 		}) | 
 |  | 
 | 		It("should defer to the underlying matcher for the message", func() { | 
 | 			matcher := Receive(Equal(3)) | 
 | 			channel := make(chan int, 1) | 
 | 			channel <- 2 | 
 | 			matcher.Match(channel) | 
 | 			Ω(matcher.FailureMessage(channel)).Should(MatchRegexp(`Expected\s+<int>: 2\s+to equal\s+<int>: 3`)) | 
 |  | 
 | 			channel <- 3 | 
 | 			matcher.Match(channel) | 
 | 			Ω(matcher.NegatedFailureMessage(channel)).Should(MatchRegexp(`Expected\s+<int>: 3\s+not to equal\s+<int>: 3`)) | 
 | 		}) | 
 |  | 
 | 		It("should work just fine with Eventually", func() { | 
 | 			stringChannel := make(chan string) | 
 |  | 
 | 			go func() { | 
 | 				time.Sleep(5 * time.Millisecond) | 
 | 				stringChannel <- "A" | 
 | 				time.Sleep(5 * time.Millisecond) | 
 | 				stringChannel <- "B" | 
 | 			}() | 
 |  | 
 | 			Eventually(stringChannel).Should(Receive(Equal("B"))) | 
 | 		}) | 
 |  | 
 | 		Context("if the matcher errors", func() { | 
 | 			It("should error", func() { | 
 | 				channel := make(chan int, 1) | 
 | 				channel <- 3 | 
 | 				success, err := (&ReceiveMatcher{Arg: ContainSubstring("three")}).Match(channel) | 
 | 				Ω(success).Should(BeFalse()) | 
 | 				Ω(err).Should(HaveOccurred()) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("if nothing is received", func() { | 
 | 			It("should fail", func() { | 
 | 				channel := make(chan int, 1) | 
 | 				success, err := (&ReceiveMatcher{Arg: Equal(1)}).Match(channel) | 
 | 				Ω(success).Should(BeFalse()) | 
 | 				Ω(err).ShouldNot(HaveOccurred()) | 
 | 			}) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Context("When actual is a *closed* channel", func() { | 
 | 		Context("for a buffered channel", func() { | 
 | 			It("should work until it hits the end of the buffer", func() { | 
 | 				channel := make(chan bool, 1) | 
 | 				channel <- true | 
 |  | 
 | 				close(channel) | 
 |  | 
 | 				Ω(channel).Should(Receive()) | 
 | 				Ω(channel).ShouldNot(Receive()) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("for an unbuffered channel", func() { | 
 | 			It("should always fail", func() { | 
 | 				channel := make(chan bool) | 
 | 				close(channel) | 
 |  | 
 | 				Ω(channel).ShouldNot(Receive()) | 
 | 			}) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Context("When actual is a send-only channel", func() { | 
 | 		It("should error", func() { | 
 | 			channel := make(chan bool) | 
 |  | 
 | 			var writerChannel chan<- bool | 
 | 			writerChannel = channel | 
 |  | 
 | 			success, err := (&ReceiveMatcher{}).Match(writerChannel) | 
 | 			Ω(success).Should(BeFalse()) | 
 | 			Ω(err).Should(HaveOccurred()) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Context("when acutal is a non-channel", func() { | 
 | 		It("should error", func() { | 
 | 			var nilChannel chan bool | 
 |  | 
 | 			success, err := (&ReceiveMatcher{}).Match(nilChannel) | 
 | 			Ω(success).Should(BeFalse()) | 
 | 			Ω(err).Should(HaveOccurred()) | 
 |  | 
 | 			success, err = (&ReceiveMatcher{}).Match(nil) | 
 | 			Ω(success).Should(BeFalse()) | 
 | 			Ω(err).Should(HaveOccurred()) | 
 |  | 
 | 			success, err = (&ReceiveMatcher{}).Match(3) | 
 | 			Ω(success).Should(BeFalse()) | 
 | 			Ω(err).Should(HaveOccurred()) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Describe("when used with eventually and a custom matcher", func() { | 
 | 		It("should return the matcher's error when a failing value is received on the channel, instead of the must receive something failure", func() { | 
 | 			failures := InterceptGomegaFailures(func() { | 
 | 				c := make(chan string, 0) | 
 | 				Eventually(c, 0.01).Should(Receive(Equal("hello"))) | 
 | 			}) | 
 | 			Ω(failures[0]).Should(ContainSubstring("When passed a matcher, ReceiveMatcher's channel *must* receive something.")) | 
 |  | 
 | 			failures = InterceptGomegaFailures(func() { | 
 | 				c := make(chan string, 1) | 
 | 				c <- "hi" | 
 | 				Eventually(c, 0.01).Should(Receive(Equal("hello"))) | 
 | 			}) | 
 | 			Ω(failures[0]).Should(ContainSubstring("<string>: hello")) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Describe("Bailing early", func() { | 
 | 		It("should bail early when passed a closed channel", func() { | 
 | 			c := make(chan bool) | 
 | 			close(c) | 
 |  | 
 | 			t := time.Now() | 
 | 			failures := InterceptGomegaFailures(func() { | 
 | 				Eventually(c).Should(Receive()) | 
 | 			}) | 
 | 			Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond)) | 
 | 			Ω(failures).Should(HaveLen(1)) | 
 | 		}) | 
 |  | 
 | 		It("should bail early when passed a non-channel", func() { | 
 | 			t := time.Now() | 
 | 			failures := InterceptGomegaFailures(func() { | 
 | 				Eventually(3).Should(Receive()) | 
 | 			}) | 
 | 			Ω(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond)) | 
 | 			Ω(failures).Should(HaveLen(1)) | 
 | 		}) | 
 | 	}) | 
 | }) |