synctest

package standard library
go1.24.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 4, 2025 License: BSD-3-Clause Imports: 1 Imported by: 0

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳