1package gbytes_test
2
3import (
4	"time"
5
6	. "github.com/onsi/gomega/gbytes"
7
8	. "github.com/onsi/ginkgo"
9	. "github.com/onsi/gomega"
10)
11
12type speaker struct {
13	buffer *Buffer
14}
15
16func (s *speaker) Buffer() *Buffer {
17	return s.buffer
18}
19
20var _ = Describe("SayMatcher", func() {
21	var buffer *Buffer
22
23	BeforeEach(func() {
24		buffer = NewBuffer()
25		buffer.Write([]byte("abc"))
26	})
27
28	Context("when actual is not a gexec Buffer, or a BufferProvider", func() {
29		It("should error", func() {
30			failures := InterceptGomegaFailures(func() {
31				Expect("foo").Should(Say("foo"))
32			})
33			Expect(failures[0]).Should(ContainSubstring("*gbytes.Buffer"))
34		})
35	})
36
37	Context("when a match is found", func() {
38		It("should succeed", func() {
39			Expect(buffer).Should(Say("abc"))
40		})
41
42		It("should support printf-like formatting", func() {
43			Expect(buffer).Should(Say("a%sc", "b"))
44		})
45
46		It("should match literal %", func() {
47			buffer.Write([]byte("%"))
48			Expect(buffer).Should(Say("abc%"))
49		})
50
51		It("should use a regular expression", func() {
52			Expect(buffer).Should(Say("a.c"))
53		})
54
55		It("should fastforward the buffer", func() {
56			buffer.Write([]byte("def"))
57			Expect(buffer).Should(Say("abcd"))
58			Expect(buffer).Should(Say("ef"))
59			Expect(buffer).ShouldNot(Say("[a-z]"))
60		})
61	})
62
63	Context("when no match is found", func() {
64		It("should not error", func() {
65			Expect(buffer).ShouldNot(Say("def"))
66		})
67
68		Context("when the buffer is closed", func() {
69			BeforeEach(func() {
70				buffer.Close()
71			})
72
73			It("should abort an eventually", func() {
74				t := time.Now()
75				failures := InterceptGomegaFailures(func() {
76					Eventually(buffer).Should(Say("def"))
77				})
78				Eventually(buffer).ShouldNot(Say("def"))
79				Expect(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
80				Expect(failures).Should(HaveLen(1))
81
82				t = time.Now()
83				Eventually(buffer).Should(Say("abc"))
84				Expect(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
85			})
86
87			It("should abort a consistently", func() {
88				t := time.Now()
89				Consistently(buffer, 2.0).ShouldNot(Say("def"))
90				Expect(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
91			})
92
93			It("should not error with a synchronous matcher", func() {
94				Expect(buffer).ShouldNot(Say("def"))
95				Expect(buffer).Should(Say("abc"))
96			})
97		})
98	})
99
100	Context("when a positive match fails", func() {
101		It("should report where it got stuck", func() {
102			Expect(buffer).Should(Say("abc"))
103			buffer.Write([]byte("def"))
104			failures := InterceptGomegaFailures(func() {
105				Expect(buffer).Should(Say("abc"))
106			})
107			Expect(failures[0]).Should(ContainSubstring("Got stuck at:"))
108			Expect(failures[0]).Should(ContainSubstring("def"))
109		})
110	})
111
112	Context("when a negative match fails", func() {
113		It("should report where it got stuck", func() {
114			failures := InterceptGomegaFailures(func() {
115				Expect(buffer).ShouldNot(Say("abc"))
116			})
117			Expect(failures[0]).Should(ContainSubstring("Saw:"))
118			Expect(failures[0]).Should(ContainSubstring("Which matches the unexpected:"))
119			Expect(failures[0]).Should(ContainSubstring("abc"))
120		})
121	})
122
123	Context("when a match is not found", func() {
124		It("should not fastforward the buffer", func() {
125			Expect(buffer).ShouldNot(Say("def"))
126			Expect(buffer).Should(Say("abc"))
127		})
128	})
129
130	Context("a nice real-life example", func() {
131		It("should behave well", func() {
132			Expect(buffer).Should(Say("abc"))
133			go func() {
134				time.Sleep(10 * time.Millisecond)
135				buffer.Write([]byte("def"))
136			}()
137			Expect(buffer).ShouldNot(Say("def"))
138			Eventually(buffer).Should(Say("def"))
139		})
140	})
141
142	Context("when actual is a BufferProvider", func() {
143		It("should use actual's buffer", func() {
144			s := &speaker{
145				buffer: NewBuffer(),
146			}
147
148			Expect(s).ShouldNot(Say("abc"))
149
150			s.Buffer().Write([]byte("abc"))
151			Expect(s).Should(Say("abc"))
152		})
153
154		It("should abort an eventually", func() {
155			s := &speaker{
156				buffer: NewBuffer(),
157			}
158
159			s.buffer.Close()
160
161			t := time.Now()
162			failures := InterceptGomegaFailures(func() {
163				Eventually(s).Should(Say("def"))
164			})
165			Expect(failures).Should(HaveLen(1))
166			Expect(time.Since(t)).Should(BeNumerically("<", 500*time.Millisecond))
167		})
168	})
169})
170