|  | 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)) | 
|  | }) | 
|  | }) | 
|  | }) |