“This is the 22nd day of my participation in the First Challenge 2022. For details: First Challenge 2022”

context test

The test object is the context package and the package name of the test package is context_test

Test Example Analysis

Example_test.go, showing four examples of the with-series.

func ExampleWithCancel() {
  gen := func(ctx context.Context) <-chan int {
    dst := make(chan int)
    n := 1
    go func() {
      for {
        select {
        case <-ctx.Done():
          return // returning not to leak the goroutine
        case dst <- n:
          n++
        }
      }
    }()
    return dst
  }

  ctx, cancel := context.WithCancel(context.Background())
  defer cancel() // cancel when we are finished consuming integers

  for n := range gen(ctx) {
    fmt.Println(n)
    if n == 5 {
      break
    }
  }
  // Output:
  // 1
  // 2
  // 3
  // 4
  // 5
}
Copy the code

Gen is a function that returns a channel. For is a loop that reads data from a channel until the channel is closed ().

The coroutine inside Gen is a typical closure. For range will constantly trigger reads, and gen’s for Select will constantly trigger writes. After reading the main coroutine for 5 times, the function main will end, and the function defer will be triggered. In this case, the done channel will be closed and the coroutine inside GEN will exit normally.

This example tests a context that supports cancellation signals, and the call to the cancellation function is placed in main’s defer function.

const shortDuration = 1 * time.Millisecond
func ExampleWithDeadline() {
  d := time.Now().Add(shortDuration)
  ctx, cancel := context.WithDeadline(context.Background(), d)

  // Even though ctx will be expired, it is good practice to call its
  // cancellation function in any case. Failure to do so may keep the
  // context and its parent alive longer than necessary.
  defer cancel()

  select {
  case <-time.After(1 * time.Second):
    fmt.Println("overslept")
  case <-ctx.Done():
    fmt.Println(ctx.Err())
  }

  // Output:
  // context deadline exceeded
}
Copy the code

Deadline’s example also has an active cancellation call in Main’s defer. You can actually print out whether the deadline is working as expected.

func ExampleWithTimeout() {
  ctx, cancel := context.WithTimeout(context.Background(), shortDuration)
  defer cancel()

  select {
  case <-time.After(1 * time.Second):
    fmt.Println("overslept")
  case <-ctx.Done():
    fmt.Println(ctx.Err()) // prints "context deadline exceeded"
  }

  // Output:
  // context deadline exceeded
}
Copy the code

Timeout is just a shorthand for deadline.

func ExampleWithValue() { type favContextKey string f := func(ctx context.Context, k favContextKey) { if v := ctx.Value(k); v ! = nil { fmt.Println("found value:", v) return } fmt.Println("key not found:", k) } k := favContextKey("language") ctx := context.WithValue(context.Background(), k, "Go") f(ctx, k) f(ctx, favContextKey("color")) // Output: // found value: Go // key not found: color }Copy the code

Context.withvalue and context.value () are access operations that return nil if the key is not found.

Unit testing

Context_text. go,x_test.go is the unit test, example_test.go is the example,benchmark_test.go is the benchmark, and net_test.go shows deadline’s support for NET packages.

Look first at context_text.go for the unit test.

type testingT interface {}

type otherContext struct {}
func quiescent(t testingT) time.Duration {}
func XTestBackground(t testingT) {}
func XTestTODO(t testingT) {}
func XTestWithCancel(t testingT) {}
func contains(m map[canceler]struct{}, key canceler) bool {}
func XTestParentFinishesChild(t testingT) {}
func XTestChildFinishesFirst(t testingT) {}
func testDeadline(c Context, name string, t testingT) {}
func XTestDeadline(t testingT) {}
func XTestTimeout(t testingT) {}
func XTestCanceledTimeout(t testingT) {}
func XTestValues(t testingT) {}
func XTestAllocs(t testingT, testingShort func() bool, testingAllocsPerRun func(int, func()) float64) {}
func XTestSimultaneousCancels(t testingT) {}
func XTestInterlockedCancels(t testingT) {}
func XTestLayersCancel(t testingT) {}
func XTestLayersTimeout(t testingT) {}
func XTestCancelRemoves(t testingT) {}
func XTestWithCancelCanceledParent(t testingT) {}
func XTestWithValueChecksKey(t testingT) {}
func XTestInvalidDerivedFail(t testingT) {}
func recoveredValue(fn func()) (v interface{}) {}
func XTestDeadlineExceededSupportsTimeout(t testingT) {}
type myCtx struct {}
type myDoneCtx struct {}
func (d *myDoneCtx) Done() <-chan struct{} {}
func XTestCustomContextGoroutines(t testingT) {}
Copy the code

Most of the exposed test functions have parameter types of the testingT interface, but there are no implementations of the testingT interface in this source file.

func TestBackground(t *testing.T) { XTestBackground(t) } func TestTODO(t *testing.T) { XTestTODO(t) } func TestWithCancel(t *testing.T) { XTestWithCancel(t) } func TestParentFinishesChild(t *testing.T) { XTestParentFinishesChild(t) } func TestChildFinishesFirst(t *testing.T) { XTestChildFinishesFirst(t) } func TestDeadline(t *testing.T) { XTestDeadline(t) } func TestTimeout(t *testing.T) { XTestTimeout(t) } func TestCanceledTimeout(t *testing.T) { XTestCanceledTimeout(t) } func TestValues(t *testing.T) { XTestValues(t) } func TestAllocs(t *testing.T) { XTestAllocs(t, testing.Short, testing.AllocsPerRun) } func TestSimultaneousCancels(t *testing.T) { XTestSimultaneousCancels(t) } func TestInterlockedCancels(t *testing.T) { XTestInterlockedCancels(t) } func TestLayersCancel(t *testing.T) { XTestLayersCancel(t) } func TestLayersTimeout(t *testing.T) { XTestLayersTimeout(t) } func TestCancelRemoves(t *testing.T) { XTestCancelRemoves(t) } func TestWithCancelCanceledParent(t *testing.T) { XTestWithCancelCanceledParent(t)  } func TestWithValueChecksKey(t *testing.T) { XTestWithValueChecksKey(t) } func TestInvalidDerivedFail(t *testing.T) { XTestInvalidDerivedFail(t) } func TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) } func TestCustomContextGoroutines(t *testing.T) { XTestCustomContextGoroutines(t) }Copy the code

This is the content of x_test.go, which implements the testingT interface directly using the testing.t type.

Let’s look at the testing.T implementation of the testingT interface.

type T struct { common isParallel bool context *testContext } func (t *T) Deadline() (deadline time.Time, ok bool) { deadline = t.context.deadline return deadline, ! deadline.IsZero() }Copy the code

Note that testing.t. ontext is not an implementation of context.context, and Deadline() returns the Deadline information stored in t.ontext.

Testing.t is embedded with testing.mon, and most of the method set comes from common:

Error(args ... interface{}) Errorf(format string, args ... interface{}) Fail() FailNow() Failed() bool Fatal(args ... interface{}) Fatalf(format string, args ... interface{}) Helper() Log(args ... interface{}) Logf(format string, args ... interface{}) Name() string Skip(args ... interface{}) SkipNow() Skipf(format string, args ... interface{}) Skipped() boolCopy the code

Parallel() is implemented by testing.t, which enables concurrency parameters when a test case is repeated multiple times.