Documentation
¶
Overview ¶
Package synctest provides support for testing concurrent code.
This package only exists when using Go compiled with GOEXPERIMENT=synctest. It is experimental, and not subject to the Go 1 compatibility promise.
Example (ContextAfterFunc) ¶
This example demonstrates testing the context.AfterFunc function.
AfterFunc registers a function to execute in a new goroutine after a context is canceled.
The test verifies that the function is not run before the context is canceled, and is run after the context is canceled.
package main import ( "context" "fmt" "testing/synctest" ) func main() { synctest.Run(func() { // Create a context.Context which can be canceled. ctx, cancel := context.WithCancel(context.Background()) // context.AfterFunc registers a function to be called // when a context is canceled. afterFuncCalled := false context.AfterFunc(ctx, func() { afterFuncCalled = true }) // The context has not been canceled, so the AfterFunc is not called. synctest.Wait() fmt.Printf("before context is canceled: afterFuncCalled=%v\n", afterFuncCalled) // Cancel the context and wait for the AfterFunc to finish executing. // Verify that the AfterFunc ran. cancel() synctest.Wait() fmt.Printf("after context is canceled: afterFuncCalled=%v\n", afterFuncCalled) }) }
Output: before context is canceled: afterFuncCalled=false after context is canceled: afterFuncCalled=true
Example (ContextWithTimeout) ¶
This example demonstrates testing the context.WithTimeout function.
WithTimeout creates a context which is canceled after a timeout.
The test verifies that the context is not canceled before the timeout expires, and is canceled after the timeout expires.
package main import ( "context" "fmt" "testing/synctest" "time" ) func main() { synctest.Run(func() { // Create a context.Context which is canceled after a timeout. const timeout = 5 * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() // Wait just less than the timeout. time.Sleep(timeout - time.Nanosecond) synctest.Wait() fmt.Printf("before timeout: ctx.Err() = %v\n", ctx.Err()) // Wait the rest of the way until the timeout. time.Sleep(time.Nanosecond) synctest.Wait() fmt.Printf("after timeout: ctx.Err() = %v\n", ctx.Err()) }) }
Output: before timeout: ctx.Err() = <nil> after timeout: ctx.Err() = context deadline exceeded
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Run ¶
func Run(f func())
Run executes f in a new goroutine.
The new goroutine and any goroutines transitively started by it form an isolated "bubble". Run waits for all goroutines in the bubble to exit before returning.
Goroutines in the bubble use a synthetic time implementation. The initial time is midnight UTC 2000-01-01.
Time advances when every goroutine in the bubble is blocked. For example, a call to time.Sleep will block until all other goroutines are blocked and return after the bubble's clock has advanced. See Wait for the specific definition of blocked.
If every goroutine is blocked and there are no timers scheduled, Run panics.
Channels, time.Timers, and time.Tickers created within the bubble are associated with it. Operating on a bubbled channel, timer, or ticker from outside the bubble panics.
func Wait ¶
func Wait()
Wait blocks until every goroutine within the current bubble, other than the current goroutine, is durably blocked. It panics if called from a non-bubbled goroutine, or if two goroutines in the same bubble call Wait at the same time.
A goroutine is durably blocked if can only be unblocked by another goroutine in its bubble. The following operations durably block a goroutine:
- a send or receive on a channel from within the bubble
- a select statement where every case is a channel within the bubble
- sync.Cond.Wait
- time.Sleep
A goroutine executing a system call or waiting for an external event such as a network operation is not durably blocked. For example, a goroutine blocked reading from an network connection is not durably blocked even if no data is currently available on the connection, because it may be unblocked by data written from outside the bubble or may be in the process of receiving data from a kernel network buffer.
A goroutine is not durably blocked when blocked on a send or receive on a channel that was not created within its bubble, because it may be unblocked by a channel receive or send from outside its bubble.
Types ¶
This section is empty.