1/* 2Gomega is the Ginkgo BDD-style testing framework's preferred matcher library. 3 4The godoc documentation describes Gomega's API. More comprehensive documentation (with examples!) is available at http://onsi.github.io/gomega/ 5 6Gomega on Github: http://github.com/onsi/gomega 7 8Learn more about Ginkgo online: http://onsi.github.io/ginkgo 9 10Ginkgo on Github: http://github.com/onsi/ginkgo 11 12Gomega is MIT-Licensed 13*/ 14package gomega 15 16import ( 17 "fmt" 18 "reflect" 19 "time" 20 21 "github.com/onsi/gomega/internal/assertion" 22 "github.com/onsi/gomega/internal/asyncassertion" 23 "github.com/onsi/gomega/internal/testingtsupport" 24 "github.com/onsi/gomega/types" 25) 26 27const GOMEGA_VERSION = "1.4.3" 28 29const nilFailHandlerPanic = `You are trying to make an assertion, but Gomega's fail handler is nil. 30If you're using Ginkgo then you probably forgot to put your assertion in an It(). 31Alternatively, you may have forgotten to register a fail handler with RegisterFailHandler() or RegisterTestingT(). 32Depending on your vendoring solution you may be inadvertently importing gomega and subpackages (e.g. ghhtp, gexec,...) from different locations. 33` 34 35var globalFailWrapper *types.GomegaFailWrapper 36 37var defaultEventuallyTimeout = time.Second 38var defaultEventuallyPollingInterval = 10 * time.Millisecond 39var defaultConsistentlyDuration = 100 * time.Millisecond 40var defaultConsistentlyPollingInterval = 10 * time.Millisecond 41 42//RegisterFailHandler connects Ginkgo to Gomega. When a matcher fails 43//the fail handler passed into RegisterFailHandler is called. 44func RegisterFailHandler(handler types.GomegaFailHandler) { 45 if handler == nil { 46 globalFailWrapper = nil 47 return 48 } 49 50 globalFailWrapper = &types.GomegaFailWrapper{ 51 Fail: handler, 52 TWithHelper: testingtsupport.EmptyTWithHelper{}, 53 } 54} 55 56func RegisterFailHandlerWithT(t types.TWithHelper, handler types.GomegaFailHandler) { 57 if handler == nil { 58 globalFailWrapper = nil 59 return 60 } 61 62 globalFailWrapper = &types.GomegaFailWrapper{ 63 Fail: handler, 64 TWithHelper: t, 65 } 66} 67 68//RegisterTestingT connects Gomega to Golang's XUnit style 69//Testing.T tests. It is now deprecated and you should use NewGomegaWithT() instead. 70// 71//Legacy Documentation: 72// 73//You'll need to call this at the top of each XUnit style test: 74// 75// func TestFarmHasCow(t *testing.T) { 76// RegisterTestingT(t) 77// 78// f := farm.New([]string{"Cow", "Horse"}) 79// Expect(f.HasCow()).To(BeTrue(), "Farm should have cow") 80// } 81// 82// Note that this *testing.T is registered *globally* by Gomega (this is why you don't have to 83// pass `t` down to the matcher itself). This means that you cannot run the XUnit style tests 84// in parallel as the global fail handler cannot point to more than one testing.T at a time. 85// 86// NewGomegaWithT() does not have this limitation 87// 88// (As an aside: Ginkgo gets around this limitation by running parallel tests in different *processes*). 89func RegisterTestingT(t types.GomegaTestingT) { 90 tWithHelper, hasHelper := t.(types.TWithHelper) 91 if !hasHelper { 92 RegisterFailHandler(testingtsupport.BuildTestingTGomegaFailWrapper(t).Fail) 93 return 94 } 95 RegisterFailHandlerWithT(tWithHelper, testingtsupport.BuildTestingTGomegaFailWrapper(t).Fail) 96} 97 98//InterceptGomegaHandlers runs a given callback and returns an array of 99//failure messages generated by any Gomega assertions within the callback. 100// 101//This is accomplished by temporarily replacing the *global* fail handler 102//with a fail handler that simply annotates failures. The original fail handler 103//is reset when InterceptGomegaFailures returns. 104// 105//This is most useful when testing custom matchers, but can also be used to check 106//on a value using a Gomega assertion without causing a test failure. 107func InterceptGomegaFailures(f func()) []string { 108 originalHandler := globalFailWrapper.Fail 109 failures := []string{} 110 RegisterFailHandler(func(message string, callerSkip ...int) { 111 failures = append(failures, message) 112 }) 113 f() 114 RegisterFailHandler(originalHandler) 115 return failures 116} 117 118//Ω wraps an actual value allowing assertions to be made on it: 119// Ω("foo").Should(Equal("foo")) 120// 121//If Ω is passed more than one argument it will pass the *first* argument to the matcher. 122//All subsequent arguments will be required to be nil/zero. 123// 124//This is convenient if you want to make an assertion on a method/function that returns 125//a value and an error - a common patter in Go. 126// 127//For example, given a function with signature: 128// func MyAmazingThing() (int, error) 129// 130//Then: 131// Ω(MyAmazingThing()).Should(Equal(3)) 132//Will succeed only if `MyAmazingThing()` returns `(3, nil)` 133// 134//Ω and Expect are identical 135func Ω(actual interface{}, extra ...interface{}) GomegaAssertion { 136 return ExpectWithOffset(0, actual, extra...) 137} 138 139//Expect wraps an actual value allowing assertions to be made on it: 140// Expect("foo").To(Equal("foo")) 141// 142//If Expect is passed more than one argument it will pass the *first* argument to the matcher. 143//All subsequent arguments will be required to be nil/zero. 144// 145//This is convenient if you want to make an assertion on a method/function that returns 146//a value and an error - a common patter in Go. 147// 148//For example, given a function with signature: 149// func MyAmazingThing() (int, error) 150// 151//Then: 152// Expect(MyAmazingThing()).Should(Equal(3)) 153//Will succeed only if `MyAmazingThing()` returns `(3, nil)` 154// 155//Expect and Ω are identical 156func Expect(actual interface{}, extra ...interface{}) GomegaAssertion { 157 return ExpectWithOffset(0, actual, extra...) 158} 159 160//ExpectWithOffset wraps an actual value allowing assertions to be made on it: 161// ExpectWithOffset(1, "foo").To(Equal("foo")) 162// 163//Unlike `Expect` and `Ω`, `ExpectWithOffset` takes an additional integer argument 164//this is used to modify the call-stack offset when computing line numbers. 165// 166//This is most useful in helper functions that make assertions. If you want Gomega's 167//error message to refer to the calling line in the test (as opposed to the line in the helper function) 168//set the first argument of `ExpectWithOffset` appropriately. 169func ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) GomegaAssertion { 170 if globalFailWrapper == nil { 171 panic(nilFailHandlerPanic) 172 } 173 return assertion.New(actual, globalFailWrapper, offset, extra...) 174} 175 176//Eventually wraps an actual value allowing assertions to be made on it. 177//The assertion is tried periodically until it passes or a timeout occurs. 178// 179//Both the timeout and polling interval are configurable as optional arguments: 180//The first optional argument is the timeout 181//The second optional argument is the polling interval 182// 183//Both intervals can either be specified as time.Duration, parsable duration strings or as floats/integers. In the 184//last case they are interpreted as seconds. 185// 186//If Eventually is passed an actual that is a function taking no arguments and returning at least one value, 187//then Eventually will call the function periodically and try the matcher against the function's first return value. 188// 189//Example: 190// 191// Eventually(func() int { 192// return thingImPolling.Count() 193// }).Should(BeNumerically(">=", 17)) 194// 195//Note that this example could be rewritten: 196// 197// Eventually(thingImPolling.Count).Should(BeNumerically(">=", 17)) 198// 199//If the function returns more than one value, then Eventually will pass the first value to the matcher and 200//assert that all other values are nil/zero. 201//This allows you to pass Eventually a function that returns a value and an error - a common pattern in Go. 202// 203//For example, consider a method that returns a value and an error: 204// func FetchFromDB() (string, error) 205// 206//Then 207// Eventually(FetchFromDB).Should(Equal("hasselhoff")) 208// 209//Will pass only if the the returned error is nil and the returned string passes the matcher. 210// 211//Eventually's default timeout is 1 second, and its default polling interval is 10ms 212func Eventually(actual interface{}, intervals ...interface{}) GomegaAsyncAssertion { 213 return EventuallyWithOffset(0, actual, intervals...) 214} 215 216//EventuallyWithOffset operates like Eventually but takes an additional 217//initial argument to indicate an offset in the call stack. This is useful when building helper 218//functions that contain matchers. To learn more, read about `ExpectWithOffset`. 219func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) GomegaAsyncAssertion { 220 if globalFailWrapper == nil { 221 panic(nilFailHandlerPanic) 222 } 223 timeoutInterval := defaultEventuallyTimeout 224 pollingInterval := defaultEventuallyPollingInterval 225 if len(intervals) > 0 { 226 timeoutInterval = toDuration(intervals[0]) 227 } 228 if len(intervals) > 1 { 229 pollingInterval = toDuration(intervals[1]) 230 } 231 return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, globalFailWrapper, timeoutInterval, pollingInterval, offset) 232} 233 234//Consistently wraps an actual value allowing assertions to be made on it. 235//The assertion is tried periodically and is required to pass for a period of time. 236// 237//Both the total time and polling interval are configurable as optional arguments: 238//The first optional argument is the duration that Consistently will run for 239//The second optional argument is the polling interval 240// 241//Both intervals can either be specified as time.Duration, parsable duration strings or as floats/integers. In the 242//last case they are interpreted as seconds. 243// 244//If Consistently is passed an actual that is a function taking no arguments and returning at least one value, 245//then Consistently will call the function periodically and try the matcher against the function's first return value. 246// 247//If the function returns more than one value, then Consistently will pass the first value to the matcher and 248//assert that all other values are nil/zero. 249//This allows you to pass Consistently a function that returns a value and an error - a common pattern in Go. 250// 251//Consistently is useful in cases where you want to assert that something *does not happen* over a period of tiem. 252//For example, you want to assert that a goroutine does *not* send data down a channel. In this case, you could: 253// 254// Consistently(channel).ShouldNot(Receive()) 255// 256//Consistently's default duration is 100ms, and its default polling interval is 10ms 257func Consistently(actual interface{}, intervals ...interface{}) GomegaAsyncAssertion { 258 return ConsistentlyWithOffset(0, actual, intervals...) 259} 260 261//ConsistentlyWithOffset operates like Consistnetly but takes an additional 262//initial argument to indicate an offset in the call stack. This is useful when building helper 263//functions that contain matchers. To learn more, read about `ExpectWithOffset`. 264func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) GomegaAsyncAssertion { 265 if globalFailWrapper == nil { 266 panic(nilFailHandlerPanic) 267 } 268 timeoutInterval := defaultConsistentlyDuration 269 pollingInterval := defaultConsistentlyPollingInterval 270 if len(intervals) > 0 { 271 timeoutInterval = toDuration(intervals[0]) 272 } 273 if len(intervals) > 1 { 274 pollingInterval = toDuration(intervals[1]) 275 } 276 return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, globalFailWrapper, timeoutInterval, pollingInterval, offset) 277} 278 279//Set the default timeout duration for Eventually. Eventually will repeatedly poll your condition until it succeeds, or until this timeout elapses. 280func SetDefaultEventuallyTimeout(t time.Duration) { 281 defaultEventuallyTimeout = t 282} 283 284//Set the default polling interval for Eventually. 285func SetDefaultEventuallyPollingInterval(t time.Duration) { 286 defaultEventuallyPollingInterval = t 287} 288 289//Set the default duration for Consistently. Consistently will verify that your condition is satsified for this long. 290func SetDefaultConsistentlyDuration(t time.Duration) { 291 defaultConsistentlyDuration = t 292} 293 294//Set the default polling interval for Consistently. 295func SetDefaultConsistentlyPollingInterval(t time.Duration) { 296 defaultConsistentlyPollingInterval = t 297} 298 299//GomegaAsyncAssertion is returned by Eventually and Consistently and polls the actual value passed into Eventually against 300//the matcher passed to the Should and ShouldNot methods. 301// 302//Both Should and ShouldNot take a variadic optionalDescription argument. This is passed on to 303//fmt.Sprintf() and is used to annotate failure messages. This allows you to make your failure messages more 304//descriptive 305// 306//Both Should and ShouldNot return a boolean that is true if the assertion passed and false if it failed. 307// 308//Example: 309// 310// Eventually(myChannel).Should(Receive(), "Something should have come down the pipe.") 311// Consistently(myChannel).ShouldNot(Receive(), "Nothing should have come down the pipe.") 312type GomegaAsyncAssertion interface { 313 Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool 314 ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool 315} 316 317//GomegaAssertion is returned by Ω and Expect and compares the actual value to the matcher 318//passed to the Should/ShouldNot and To/ToNot/NotTo methods. 319// 320//Typically Should/ShouldNot are used with Ω and To/ToNot/NotTo are used with Expect 321//though this is not enforced. 322// 323//All methods take a variadic optionalDescription argument. This is passed on to fmt.Sprintf() 324//and is used to annotate failure messages. 325// 326//All methods return a bool that is true if hte assertion passed and false if it failed. 327// 328//Example: 329// 330// Ω(farm.HasCow()).Should(BeTrue(), "Farm %v should have a cow", farm) 331type GomegaAssertion interface { 332 Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool 333 ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool 334 335 To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool 336 ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool 337 NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool 338} 339 340//OmegaMatcher is deprecated in favor of the better-named and better-organized types.GomegaMatcher but sticks around to support existing code that uses it 341type OmegaMatcher types.GomegaMatcher 342 343//GomegaWithT wraps a *testing.T and provides `Expect`, `Eventually`, and `Consistently` methods. This allows you to leverage 344//Gomega's rich ecosystem of matchers in standard `testing` test suites. 345// 346//Use `NewGomegaWithT` to instantiate a `GomegaWithT` 347type GomegaWithT struct { 348 t types.GomegaTestingT 349} 350 351//NewGomegaWithT takes a *testing.T and returngs a `GomegaWithT` allowing you to use `Expect`, `Eventually`, and `Consistently` along with 352//Gomega's rich ecosystem of matchers in standard `testing` test suits. 353// 354// func TestFarmHasCow(t *testing.T) { 355// g := GomegaWithT(t) 356// 357// f := farm.New([]string{"Cow", "Horse"}) 358// g.Expect(f.HasCow()).To(BeTrue(), "Farm should have cow") 359// } 360func NewGomegaWithT(t types.GomegaTestingT) *GomegaWithT { 361 return &GomegaWithT{ 362 t: t, 363 } 364} 365 366//See documentation for Expect 367func (g *GomegaWithT) Expect(actual interface{}, extra ...interface{}) GomegaAssertion { 368 return assertion.New(actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), 0, extra...) 369} 370 371//See documentation for Eventually 372func (g *GomegaWithT) Eventually(actual interface{}, intervals ...interface{}) GomegaAsyncAssertion { 373 timeoutInterval := defaultEventuallyTimeout 374 pollingInterval := defaultEventuallyPollingInterval 375 if len(intervals) > 0 { 376 timeoutInterval = toDuration(intervals[0]) 377 } 378 if len(intervals) > 1 { 379 pollingInterval = toDuration(intervals[1]) 380 } 381 return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, 0) 382} 383 384//See documentation for Consistently 385func (g *GomegaWithT) Consistently(actual interface{}, intervals ...interface{}) GomegaAsyncAssertion { 386 timeoutInterval := defaultConsistentlyDuration 387 pollingInterval := defaultConsistentlyPollingInterval 388 if len(intervals) > 0 { 389 timeoutInterval = toDuration(intervals[0]) 390 } 391 if len(intervals) > 1 { 392 pollingInterval = toDuration(intervals[1]) 393 } 394 return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, 0) 395} 396 397func toDuration(input interface{}) time.Duration { 398 duration, ok := input.(time.Duration) 399 if ok { 400 return duration 401 } 402 403 value := reflect.ValueOf(input) 404 kind := reflect.TypeOf(input).Kind() 405 406 if reflect.Int <= kind && kind <= reflect.Int64 { 407 return time.Duration(value.Int()) * time.Second 408 } else if reflect.Uint <= kind && kind <= reflect.Uint64 { 409 return time.Duration(value.Uint()) * time.Second 410 } else if reflect.Float32 <= kind && kind <= reflect.Float64 { 411 return time.Duration(value.Float() * float64(time.Second)) 412 } else if reflect.String == kind { 413 duration, err := time.ParseDuration(value.String()) 414 if err != nil { 415 panic(fmt.Sprintf("%#v is not a valid parsable duration string.", input)) 416 } 417 return duration 418 } 419 420 panic(fmt.Sprintf("%v is not a valid interval. Must be time.Duration, parsable duration string or a number.", input)) 421} 422