mirror of
https://github.com/syncthing/syncthing.git
synced 2024-11-17 10:58:49 -07:00
281 lines
7.1 KiB
Go
281 lines
7.1 KiB
Go
|
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))
|
||
|
})
|
||
|
})
|
||
|
})
|