syncthing/vendor/github.com/onsi/gomega/matchers/receive_matcher_test.go

281 lines
7.1 KiB
Go
Raw Normal View History

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