github.com/onsi/gomega@v1.32.0/matchers/receive_matcher_test.go (about) 1 package matchers_test 2 3 import ( 4 "time" 5 6 . "github.com/onsi/ginkgo/v2" 7 . "github.com/onsi/gomega" 8 . "github.com/onsi/gomega/matchers" 9 ) 10 11 type kungFuActor interface { 12 DrunkenMaster() bool 13 } 14 15 type jackie struct { 16 name string 17 } 18 19 func (j *jackie) DrunkenMaster() bool { 20 return true 21 } 22 23 type someError struct{ s string } 24 25 func (e *someError) Error() string { return e.s } 26 27 var _ = Describe("ReceiveMatcher", func() { 28 Context("with no argument", func() { 29 Context("for a buffered channel", func() { 30 It("should succeed", func() { 31 channel := make(chan bool, 1) 32 33 Expect(channel).ShouldNot(Receive()) 34 35 channel <- true 36 37 Expect(channel).Should(Receive()) 38 }) 39 }) 40 41 Context("for an unbuffered channel", func() { 42 It("should succeed (eventually)", func() { 43 channel := make(chan bool) 44 45 Expect(channel).ShouldNot(Receive()) 46 47 go func() { 48 time.Sleep(10 * time.Millisecond) 49 channel <- true 50 }() 51 52 Eventually(channel).Should(Receive()) 53 }) 54 }) 55 }) 56 57 Context("with a pointer argument", func() { 58 Context("of the correct type", func() { 59 When("the channel has an interface type", func() { 60 It("should write the value received on the channel to the pointer", func() { 61 channel := make(chan error, 1) 62 63 var value *someError 64 65 Ω(channel).ShouldNot(Receive(&value)) 66 Ω(value).Should(BeZero()) 67 68 channel <- &someError{"boooom!"} 69 70 Ω(channel).Should(Receive(&value)) 71 Ω(value).Should(MatchError("boooom!")) 72 }) 73 }) 74 }) 75 76 Context("of the correct type", func() { 77 It("should write the value received on the channel to the pointer", func() { 78 channel := make(chan int, 1) 79 80 var value int 81 82 Expect(channel).ShouldNot(Receive(&value)) 83 Expect(value).Should(BeZero()) 84 85 channel <- 17 86 87 Expect(channel).Should(Receive(&value)) 88 Expect(value).Should(Equal(17)) 89 }) 90 }) 91 92 Context("to various types of objects", func() { 93 It("should work", func() { 94 //channels of strings 95 stringChan := make(chan string, 1) 96 stringChan <- "foo" 97 98 var s string 99 Expect(stringChan).Should(Receive(&s)) 100 Expect(s).Should(Equal("foo")) 101 102 //channels of slices 103 sliceChan := make(chan []bool, 1) 104 sliceChan <- []bool{true, true, false} 105 106 var sl []bool 107 Expect(sliceChan).Should(Receive(&sl)) 108 Expect(sl).Should(Equal([]bool{true, true, false})) 109 110 //channels of channels 111 chanChan := make(chan chan bool, 1) 112 c := make(chan bool) 113 chanChan <- c 114 115 var receivedC chan bool 116 Expect(chanChan).Should(Receive(&receivedC)) 117 Expect(receivedC).Should(Equal(c)) 118 119 //channels of interfaces 120 jackieChan := make(chan kungFuActor, 1) 121 aJackie := &jackie{name: "Jackie Chan"} 122 jackieChan <- aJackie 123 124 var theJackie kungFuActor 125 Expect(jackieChan).Should(Receive(&theJackie)) 126 Expect(theJackie).Should(Equal(aJackie)) 127 }) 128 }) 129 130 Context("of the wrong type", func() { 131 It("should error", func() { 132 channel := make(chan int, 1) 133 channel <- 10 134 135 var incorrectType bool 136 137 success, err := (&ReceiveMatcher{Arg: &incorrectType}).Match(channel) 138 Expect(success).Should(BeFalse()) 139 Expect(err).Should(HaveOccurred()) 140 141 var notAPointer int 142 success, err = (&ReceiveMatcher{Arg: notAPointer}).Match(channel) 143 Expect(success).Should(BeFalse()) 144 Expect(err).Should(HaveOccurred()) 145 }) 146 }) 147 }) 148 149 Context("with a matcher", func() { 150 It("should defer to the underlying matcher", func() { 151 intChannel := make(chan int, 1) 152 intChannel <- 3 153 Expect(intChannel).Should(Receive(Equal(3))) 154 155 intChannel <- 2 156 Expect(intChannel).ShouldNot(Receive(Equal(3))) 157 158 stringChannel := make(chan []string, 1) 159 stringChannel <- []string{"foo", "bar", "baz"} 160 Expect(stringChannel).Should(Receive(ContainElement(ContainSubstring("fo")))) 161 162 stringChannel <- []string{"foo", "bar", "baz"} 163 Expect(stringChannel).ShouldNot(Receive(ContainElement(ContainSubstring("archipelago")))) 164 }) 165 166 It("should defer to the underlying matcher for the message", func() { 167 matcher := Receive(Equal(3)) 168 channel := make(chan int, 1) 169 channel <- 2 170 matcher.Match(channel) 171 Expect(matcher.FailureMessage(channel)).Should(MatchRegexp(`Expected\s+<int>: 2\s+to equal\s+<int>: 3`)) 172 173 channel <- 3 174 matcher.Match(channel) 175 Expect(matcher.NegatedFailureMessage(channel)).Should(MatchRegexp(`Expected\s+<int>: 3\s+not to equal\s+<int>: 3`)) 176 }) 177 178 It("should work just fine with Eventually", func() { 179 stringChannel := make(chan string) 180 181 go func() { 182 time.Sleep(5 * time.Millisecond) 183 stringChannel <- "A" 184 time.Sleep(5 * time.Millisecond) 185 stringChannel <- "B" 186 }() 187 188 Eventually(stringChannel).Should(Receive(Equal("B"))) 189 }) 190 191 Context("if the matcher errors", func() { 192 It("should error", func() { 193 channel := make(chan int, 1) 194 channel <- 3 195 success, err := (&ReceiveMatcher{Arg: ContainSubstring("three")}).Match(channel) 196 Expect(success).Should(BeFalse()) 197 Expect(err).Should(HaveOccurred()) 198 }) 199 }) 200 201 Context("if nothing is received", func() { 202 It("should fail", func() { 203 channel := make(chan int, 1) 204 success, err := (&ReceiveMatcher{Arg: Equal(1)}).Match(channel) 205 Expect(success).Should(BeFalse()) 206 Expect(err).ShouldNot(HaveOccurred()) 207 }) 208 }) 209 }) 210 211 Context("When actual is a *closed* channel", func() { 212 Context("for a buffered channel", func() { 213 It("should work until it hits the end of the buffer", func() { 214 channel := make(chan bool, 1) 215 channel <- true 216 217 close(channel) 218 219 Expect(channel).Should(Receive()) 220 Expect(channel).ShouldNot(Receive()) 221 }) 222 }) 223 224 Context("for an unbuffered channel", func() { 225 It("should always fail", func() { 226 channel := make(chan bool) 227 close(channel) 228 229 Expect(channel).ShouldNot(Receive()) 230 }) 231 }) 232 }) 233 234 Context("When actual is a send-only channel", func() { 235 It("should error", func() { 236 channel := make(chan bool) 237 238 var writerChannel chan<- bool 239 writerChannel = channel 240 241 success, err := (&ReceiveMatcher{}).Match(writerChannel) 242 Expect(success).Should(BeFalse()) 243 Expect(err).Should(HaveOccurred()) 244 }) 245 }) 246 247 When("acutal is a non-channel", func() { 248 It("should error", func() { 249 var nilChannel chan bool 250 251 success, err := (&ReceiveMatcher{}).Match(nilChannel) 252 Expect(success).Should(BeFalse()) 253 Expect(err).Should(HaveOccurred()) 254 255 success, err = (&ReceiveMatcher{}).Match(nil) 256 Expect(success).Should(BeFalse()) 257 Expect(err).Should(HaveOccurred()) 258 259 success, err = (&ReceiveMatcher{}).Match(3) 260 Expect(success).Should(BeFalse()) 261 Expect(err).Should(HaveOccurred()) 262 }) 263 }) 264 265 Describe("when used with eventually and a custom matcher", func() { 266 It("should return the matcher's error when a failing value is received on the channel, instead of the must receive something failure", func() { 267 failures := InterceptGomegaFailures(func() { 268 c := make(chan string) 269 Eventually(c, 0.01).Should(Receive(Equal("hello"))) 270 }) 271 Expect(failures[0]).Should(ContainSubstring("When passed a matcher, ReceiveMatcher's channel *must* receive something.")) 272 273 failures = InterceptGomegaFailures(func() { 274 c := make(chan string, 1) 275 c <- "hi" 276 Eventually(c, 0.01).Should(Receive(Equal("hello"))) 277 }) 278 Expect(failures[0]).Should(ContainSubstring("<string>: hello")) 279 }) 280 }) 281 282 Describe("Bailing early", func() { 283 It("should bail early when passed a closed channel", func() { 284 c := make(chan bool) 285 close(c) 286 287 t := time.Now() 288 failures := InterceptGomegaFailures(func() { 289 Eventually(c).Should(Receive()) 290 }) 291 Expect(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond)) 292 Expect(failures).Should(HaveLen(1)) 293 }) 294 295 It("should bail early when passed a non-channel", func() { 296 t := time.Now() 297 failures := InterceptGomegaFailures(func() { 298 Eventually(3).Should(Receive()) 299 }) 300 Expect(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond)) 301 Expect(failures).Should(HaveLen(1)) 302 }) 303 }) 304 })