| package asyncassertion_test | 
 |  | 
 | import ( | 
 | 	"errors" | 
 | 	"time" | 
 |  | 
 | 	. "github.com/onsi/ginkgo" | 
 | 	. "github.com/onsi/gomega" | 
 | 	. "github.com/onsi/gomega/internal/asyncassertion" | 
 | ) | 
 |  | 
 | var _ = Describe("Async Assertion", func() { | 
 | 	var ( | 
 | 		failureMessage string | 
 | 		callerSkip     int | 
 | 	) | 
 |  | 
 | 	var fakeFailHandler = func(message string, skip ...int) { | 
 | 		failureMessage = message | 
 | 		callerSkip = skip[0] | 
 | 	} | 
 |  | 
 | 	BeforeEach(func() { | 
 | 		failureMessage = "" | 
 | 		callerSkip = 0 | 
 | 	}) | 
 |  | 
 | 	Describe("Eventually", func() { | 
 | 		Context("the positive case", func() { | 
 | 			It("should poll the function and matcher", func() { | 
 | 				counter := 0 | 
 | 				a := New(AsyncAssertionTypeEventually, func() int { | 
 | 					counter++ | 
 | 					return counter | 
 | 				}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 				a.Should(BeNumerically("==", 5)) | 
 | 				Ω(failureMessage).Should(BeZero()) | 
 | 			}) | 
 |  | 
 | 			It("should continue when the matcher errors", func() { | 
 | 				counter := 0 | 
 | 				a := New(AsyncAssertionTypeEventually, func() interface{} { | 
 | 					counter++ | 
 | 					if counter == 5 { | 
 | 						return "not-a-number" //this should cause the matcher to error | 
 | 					} | 
 | 					return counter | 
 | 				}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 				a.Should(BeNumerically("==", 5), "My description %d", 2) | 
 |  | 
 | 				Ω(failureMessage).Should(ContainSubstring("Timed out after")) | 
 | 				Ω(failureMessage).Should(ContainSubstring("My description 2")) | 
 | 				Ω(callerSkip).Should(Equal(4)) | 
 | 			}) | 
 |  | 
 | 			It("should be able to timeout", func() { | 
 | 				counter := 0 | 
 | 				a := New(AsyncAssertionTypeEventually, func() int { | 
 | 					counter++ | 
 | 					return counter | 
 | 				}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 				a.Should(BeNumerically(">", 100), "My description %d", 2) | 
 |  | 
 | 				Ω(counter).Should(BeNumerically(">", 8)) | 
 | 				Ω(counter).Should(BeNumerically("<=", 10)) | 
 | 				Ω(failureMessage).Should(ContainSubstring("Timed out after")) | 
 | 				Ω(failureMessage).Should(MatchRegexp(`\<int\>: \d`), "Should pass the correct value to the matcher message formatter.") | 
 | 				Ω(failureMessage).Should(ContainSubstring("My description 2")) | 
 | 				Ω(callerSkip).Should(Equal(4)) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("the negative case", func() { | 
 | 			It("should poll the function and matcher", func() { | 
 | 				counter := 0 | 
 | 				a := New(AsyncAssertionTypeEventually, func() int { | 
 | 					counter += 1 | 
 | 					return counter | 
 | 				}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 				a.ShouldNot(BeNumerically("<", 3)) | 
 |  | 
 | 				Ω(counter).Should(Equal(3)) | 
 | 				Ω(failureMessage).Should(BeZero()) | 
 | 			}) | 
 |  | 
 | 			It("should timeout when the matcher errors", func() { | 
 | 				a := New(AsyncAssertionTypeEventually, func() interface{} { | 
 | 					return 0 //this should cause the matcher to error | 
 | 				}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 				a.ShouldNot(HaveLen(0), "My description %d", 2) | 
 |  | 
 | 				Ω(failureMessage).Should(ContainSubstring("Timed out after")) | 
 | 				Ω(failureMessage).Should(ContainSubstring("Error:")) | 
 | 				Ω(failureMessage).Should(ContainSubstring("My description 2")) | 
 | 				Ω(callerSkip).Should(Equal(4)) | 
 | 			}) | 
 |  | 
 | 			It("should be able to timeout", func() { | 
 | 				a := New(AsyncAssertionTypeEventually, func() int { | 
 | 					return 0 | 
 | 				}, fakeFailHandler, time.Duration(0.1*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 				a.ShouldNot(Equal(0), "My description %d", 2) | 
 |  | 
 | 				Ω(failureMessage).Should(ContainSubstring("Timed out after")) | 
 | 				Ω(failureMessage).Should(ContainSubstring("<int>: 0"), "Should pass the correct value to the matcher message formatter.") | 
 | 				Ω(failureMessage).Should(ContainSubstring("My description 2")) | 
 | 				Ω(callerSkip).Should(Equal(4)) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("with a function that returns multiple values", func() { | 
 | 			It("should eventually succeed if the additional arguments are nil", func() { | 
 | 				i := 0 | 
 | 				Eventually(func() (int, error) { | 
 | 					i++ | 
 | 					return i, nil | 
 | 				}).Should(Equal(10)) | 
 | 			}) | 
 |  | 
 | 			It("should eventually timeout if the additional arguments are not nil", func() { | 
 | 				i := 0 | 
 | 				a := New(AsyncAssertionTypeEventually, func() (int, error) { | 
 | 					i++ | 
 | 					return i, errors.New("bam") | 
 | 				}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 | 				a.Should(Equal(2)) | 
 |  | 
 | 				Ω(failureMessage).Should(ContainSubstring("Timed out after")) | 
 | 				Ω(failureMessage).Should(ContainSubstring("Error:")) | 
 | 				Ω(failureMessage).Should(ContainSubstring("bam")) | 
 | 				Ω(callerSkip).Should(Equal(4)) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("Making an assertion without a registered fail handler", func() { | 
 | 			It("should panic", func() { | 
 | 				defer func() { | 
 | 					e := recover() | 
 | 					RegisterFailHandler(Fail) | 
 | 					if e == nil { | 
 | 						Fail("expected a panic to have occured") | 
 | 					} | 
 | 				}() | 
 |  | 
 | 				RegisterFailHandler(nil) | 
 | 				c := make(chan bool, 1) | 
 | 				c <- true | 
 | 				Eventually(c).Should(Receive()) | 
 | 			}) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Describe("Consistently", func() { | 
 | 		Describe("The positive case", func() { | 
 | 			Context("when the matcher consistently passes for the duration", func() { | 
 | 				It("should pass", func() { | 
 | 					calls := 0 | 
 | 					a := New(AsyncAssertionTypeConsistently, func() string { | 
 | 						calls++ | 
 | 						return "foo" | 
 | 					}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 					a.Should(Equal("foo")) | 
 | 					Ω(calls).Should(BeNumerically(">", 8)) | 
 | 					Ω(calls).Should(BeNumerically("<=", 10)) | 
 | 					Ω(failureMessage).Should(BeZero()) | 
 | 				}) | 
 | 			}) | 
 |  | 
 | 			Context("when the matcher fails at some point", func() { | 
 | 				It("should fail", func() { | 
 | 					calls := 0 | 
 | 					a := New(AsyncAssertionTypeConsistently, func() interface{} { | 
 | 						calls++ | 
 | 						if calls > 5 { | 
 | 							return "bar" | 
 | 						} | 
 | 						return "foo" | 
 | 					}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 					a.Should(Equal("foo")) | 
 | 					Ω(failureMessage).Should(ContainSubstring("to equal")) | 
 | 					Ω(callerSkip).Should(Equal(4)) | 
 | 				}) | 
 | 			}) | 
 |  | 
 | 			Context("when the matcher errors at some point", func() { | 
 | 				It("should fail", func() { | 
 | 					calls := 0 | 
 | 					a := New(AsyncAssertionTypeConsistently, func() interface{} { | 
 | 						calls++ | 
 | 						if calls > 5 { | 
 | 							return 3 | 
 | 						} | 
 | 						return []int{1, 2, 3} | 
 | 					}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 					a.Should(HaveLen(3)) | 
 | 					Ω(failureMessage).Should(ContainSubstring("HaveLen matcher expects")) | 
 | 					Ω(callerSkip).Should(Equal(4)) | 
 | 				}) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Describe("The negative case", func() { | 
 | 			Context("when the matcher consistently passes for the duration", func() { | 
 | 				It("should pass", func() { | 
 | 					c := make(chan bool) | 
 | 					a := New(AsyncAssertionTypeConsistently, c, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 					a.ShouldNot(Receive()) | 
 | 					Ω(failureMessage).Should(BeZero()) | 
 | 				}) | 
 | 			}) | 
 |  | 
 | 			Context("when the matcher fails at some point", func() { | 
 | 				It("should fail", func() { | 
 | 					c := make(chan bool) | 
 | 					go func() { | 
 | 						time.Sleep(time.Duration(100 * time.Millisecond)) | 
 | 						c <- true | 
 | 					}() | 
 |  | 
 | 					a := New(AsyncAssertionTypeConsistently, c, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 					a.ShouldNot(Receive()) | 
 | 					Ω(failureMessage).Should(ContainSubstring("not to receive anything")) | 
 | 				}) | 
 | 			}) | 
 |  | 
 | 			Context("when the matcher errors at some point", func() { | 
 | 				It("should fail", func() { | 
 | 					calls := 0 | 
 | 					a := New(AsyncAssertionTypeConsistently, func() interface{} { | 
 | 						calls++ | 
 | 						return calls | 
 | 					}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 |  | 
 | 					a.ShouldNot(BeNumerically(">", 5)) | 
 | 					Ω(failureMessage).Should(ContainSubstring("not to be >")) | 
 | 					Ω(callerSkip).Should(Equal(4)) | 
 | 				}) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("with a function that returns multiple values", func() { | 
 | 			It("should consistently succeed if the additional arguments are nil", func() { | 
 | 				i := 2 | 
 | 				Consistently(func() (int, error) { | 
 | 					i++ | 
 | 					return i, nil | 
 | 				}).Should(BeNumerically(">=", 2)) | 
 | 			}) | 
 |  | 
 | 			It("should eventually timeout if the additional arguments are not nil", func() { | 
 | 				i := 2 | 
 | 				a := New(AsyncAssertionTypeEventually, func() (int, error) { | 
 | 					i++ | 
 | 					return i, errors.New("bam") | 
 | 				}, fakeFailHandler, time.Duration(0.2*float64(time.Second)), time.Duration(0.02*float64(time.Second)), 1) | 
 | 				a.Should(BeNumerically(">=", 2)) | 
 |  | 
 | 				Ω(failureMessage).Should(ContainSubstring("Error:")) | 
 | 				Ω(failureMessage).Should(ContainSubstring("bam")) | 
 | 				Ω(callerSkip).Should(Equal(4)) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("Making an assertion without a registered fail handler", func() { | 
 | 			It("should panic", func() { | 
 | 				defer func() { | 
 | 					e := recover() | 
 | 					RegisterFailHandler(Fail) | 
 | 					if e == nil { | 
 | 						Fail("expected a panic to have occured") | 
 | 					} | 
 | 				}() | 
 |  | 
 | 				RegisterFailHandler(nil) | 
 | 				c := make(chan bool) | 
 | 				Consistently(c).ShouldNot(Receive()) | 
 | 			}) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Context("when passed a function with the wrong # or arguments & returns", func() { | 
 | 		It("should panic", func() { | 
 | 			Ω(func() { | 
 | 				New(AsyncAssertionTypeEventually, func() {}, fakeFailHandler, 0, 0, 1) | 
 | 			}).Should(Panic()) | 
 |  | 
 | 			Ω(func() { | 
 | 				New(AsyncAssertionTypeEventually, func(a string) int { return 0 }, fakeFailHandler, 0, 0, 1) | 
 | 			}).Should(Panic()) | 
 |  | 
 | 			Ω(func() { | 
 | 				New(AsyncAssertionTypeEventually, func() int { return 0 }, fakeFailHandler, 0, 0, 1) | 
 | 			}).ShouldNot(Panic()) | 
 |  | 
 | 			Ω(func() { | 
 | 				New(AsyncAssertionTypeEventually, func() (int, error) { return 0, nil }, fakeFailHandler, 0, 0, 1) | 
 | 			}).ShouldNot(Panic()) | 
 | 		}) | 
 | 	}) | 
 |  | 
 | 	Describe("bailing early", func() { | 
 | 		Context("when actual is a value", func() { | 
 | 			It("Eventually should bail out and fail early if the matcher says to", func() { | 
 | 				c := make(chan bool) | 
 | 				close(c) | 
 |  | 
 | 				t := time.Now() | 
 | 				failures := InterceptGomegaFailures(func() { | 
 | 					Eventually(c, 0.1).Should(Receive()) | 
 | 				}) | 
 | 				Ω(time.Since(t)).Should(BeNumerically("<", 90*time.Millisecond)) | 
 |  | 
 | 				Ω(failures).Should(HaveLen(1)) | 
 | 			}) | 
 | 		}) | 
 |  | 
 | 		Context("when actual is a function", func() { | 
 | 			It("should never bail early", func() { | 
 | 				c := make(chan bool) | 
 | 				close(c) | 
 |  | 
 | 				t := time.Now() | 
 | 				failures := InterceptGomegaFailures(func() { | 
 | 					Eventually(func() chan bool { | 
 | 						return c | 
 | 					}, 0.1).Should(Receive()) | 
 | 				}) | 
 | 				Ω(time.Since(t)).Should(BeNumerically(">=", 90*time.Millisecond)) | 
 |  | 
 | 				Ω(failures).Should(HaveLen(1)) | 
 | 			}) | 
 | 		}) | 
 | 	}) | 
 | }) |