Skip to content

coder/paralleltestctx

Repository files navigation

paralleltestctx

A Go static analysis tool that warns when contexts with a deadline are used in parallel subtests.

Problem

See our blog post for an in-depth explanation of the problem.

Usage

go run github.com/coder/paralleltestctx/cmd/paralleltestctx@latest ./...

Custom functions that produce contexts with timeouts

By default, the linter detects context.WithTimeout and context.WithDeadline as producing contexts with timeouts or deadlines. Additional functions that create a context with a deadline or timeout can be specified using the -custom-funcs flag.

go run github.com/coder/paralleltestctx/cmd/paralleltestctx@latest -custom-funcs="testutil.Context" ./...

Examples

❌ Potentially flakey test

func TestBad(t *testing.T) {
   ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
   defer cancel()
   // WARNING: do not do this!
   t.Parallel()

   uut := newUnitUnderTest()
   // Danger! Context may have timed out by this point
   writeCtx(ctx, t, uut.Input, 5)
   output := readCtx(ctx, t, uut.Output)
   if output != 25 {
      t.Errorf("expected 25 got %d", output)
   }
}

❌ Potentially flakey parallel subtest

func TestBad(t *testing.T) {
    t.Parallel()
    ctx, cancel := context.WithTimeout(context.Background(), time.Second * 5)
    t.Cleanup(cancel)
    t.Run("sub", func(t *testing.T) {
        t.Parallel()
        // Danger! Context may have timed out by this point
        doSomething(ctx) // Warning: timeout context used after t.Parallel call
    })
}

✅ Fixed test - create a new context

func TestGood(t *testing.T) {
    t.Parallel()
    ctx, cancel := context.WithTimeout(context.Background(), time.Second * 5)
    t.Cleanup(cancel)
    t.Run("sub", func(t *testing.T) {
        t.Parallel()
        // We're shadowing the parent context with a new deadline, so this is fine
        ctx, cancel := context.WithTimeout(context.Background(), time.Second * 5)
        t.Cleanup(cancel)
        doSomething(ctx)
    })
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Go linter for finding usages of contexts with timeouts in parallel subtests.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published