From 3f9145b684f9c032a8d21043f561ff8a8423160f Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 7 Jan 2025 14:29:23 -0800 Subject: [PATCH] testing/synctest: add some examples For #67434 Change-Id: Iebcfc2559a62405fea7e3ceff8cf6c2f50b61def Reviewed-on: https://go-review.googlesource.com/c/go/+/641176 Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Auto-Submit: Damien Neil --- src/testing/synctest/context_example_test.go | 78 ++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/testing/synctest/context_example_test.go diff --git a/src/testing/synctest/context_example_test.go b/src/testing/synctest/context_example_test.go new file mode 100644 index 00000000000000..5f7205e50e4c42 --- /dev/null +++ b/src/testing/synctest/context_example_test.go @@ -0,0 +1,78 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.synctest + +package synctest_test + +import ( + "context" + "fmt" + "testing/synctest" + "time" +) + +// 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. +func Example_contextAfterFunc() { + 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 + }) +} + +// 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. +func Example_contextWithTimeout() { + 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() = + // after timeout: ctx.Err() = context deadline exceeded + }) +}