diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index e6f228852b9..147eaf6aba3 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -179,7 +179,7 @@ var pkgDeps = map[string][]string{ "runtime/trace": {"L0"}, "text/tabwriter": {"L2"}, - "testing": {"L2", "context", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"}, + "testing": {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"}, "testing/iotest": {"L2", "log"}, "testing/quick": {"L2", "flag", "fmt", "reflect"}, "internal/testenv": {"L2", "OS", "flag", "testing", "syscall"}, diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index b1c6d2eff04..c033ce5fecb 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -5,7 +5,6 @@ package testing import ( - "context" "flag" "fmt" "internal/race" @@ -128,9 +127,6 @@ func (b *B) nsPerOp() int64 { // runN runs a single benchmark for the specified number of iterations. func (b *B) runN(n int) { - b.ctx, b.cancel = context.WithCancel(b.parentContext()) - defer b.cancel() - benchmarkLock.Lock() defer benchmarkLock.Unlock() // Try to get a comparable environment for each run diff --git a/src/testing/sub_test.go b/src/testing/sub_test.go index 563e8656c60..2a24aaacfd7 100644 --- a/src/testing/sub_test.go +++ b/src/testing/sub_test.go @@ -6,7 +6,6 @@ package testing import ( "bytes" - "context" "regexp" "strings" "sync/atomic" @@ -278,33 +277,28 @@ func TestTRun(t *T) { ok: true, maxPar: 4, f: func(t *T) { - // t.Parallel doesn't work in the pseudo-T we start with: - // it leaks a goroutine. - // Call t.Run to get a real one. - t.Run("X", func(t *T) { - t.Parallel() - for i := 0; i < 12; i++ { - t.Run("a", func(t *T) { - t.Parallel() - time.Sleep(time.Nanosecond) - for i := 0; i < 12; i++ { - t.Run("b", func(t *T) { - time.Sleep(time.Nanosecond) - for i := 0; i < 12; i++ { - t.Run("c", func(t *T) { - t.Parallel() - time.Sleep(time.Nanosecond) - t.Run("d1", func(t *T) {}) - t.Run("d2", func(t *T) {}) - t.Run("d3", func(t *T) {}) - t.Run("d4", func(t *T) {}) - }) - } - }) - } - }) - } - }) + t.Parallel() + for i := 0; i < 12; i++ { + t.Run("a", func(t *T) { + t.Parallel() + time.Sleep(time.Nanosecond) + for i := 0; i < 12; i++ { + t.Run("b", func(t *T) { + time.Sleep(time.Nanosecond) + for i := 0; i < 12; i++ { + t.Run("c", func(t *T) { + t.Parallel() + time.Sleep(time.Nanosecond) + t.Run("d1", func(t *T) {}) + t.Run("d2", func(t *T) {}) + t.Run("d3", func(t *T) {}) + t.Run("d4", func(t *T) {}) + }) + } + }) + } + }) + } }, }, { desc: "skip output", @@ -347,7 +341,6 @@ func TestTRun(t *T) { }, context: ctx, } - root.ctx, root.cancel = context.WithCancel(context.Background()) ok := root.Run(tc.desc, tc.f) ctx.release() diff --git a/src/testing/testing.go b/src/testing/testing.go index f08c5c6b8e2..8fb6d8373e5 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -204,7 +204,6 @@ package testing import ( "bytes" - "context" "errors" "flag" "fmt" @@ -262,14 +261,12 @@ type common struct { mu sync.RWMutex // guards output, failed, and done. output []byte // Output generated by test or benchmark. w io.Writer // For flushToParent. - ctx context.Context - cancel context.CancelFunc - chatty bool // A copy of the chatty flag. - ran bool // Test or benchmark (or one of its subtests) was executed. - failed bool // Test or benchmark has failed. - skipped bool // Test of benchmark has been skipped. - finished bool // Test function has completed. - done bool // Test is finished and all subtests have completed. + chatty bool // A copy of the chatty flag. + ran bool // Test or benchmark (or one of its subtests) was executed. + failed bool // Test or benchmark has failed. + skipped bool // Test of benchmark has been skipped. + finished bool // Test function has completed. + done bool // Test is finished and all subtests have completed. hasSub bool raceErrors int // number of races detected during test @@ -283,13 +280,6 @@ type common struct { sub []*T // Queue of subtests to be run in parallel. } -func (c *common) parentContext() context.Context { - if c == nil || c.parent == nil || c.parent.ctx == nil { - return context.Background() - } - return c.parent.ctx -} - // Short reports whether the -test.short flag is set. func Short() bool { return *short @@ -386,7 +376,6 @@ func fmtDuration(d time.Duration) string { // TB is the interface common to T and B. type TB interface { - Context() context.Context Error(args ...interface{}) Errorf(format string, args ...interface{}) Fail() @@ -434,15 +423,6 @@ func (c *common) Name() string { return c.name } -// Context returns the context for the current test or benchmark. -// The context is cancelled when the test or benchmark finishes. -// A goroutine started during a test or benchmark can wait for the -// context's Done channel to become readable as a signal that the -// test or benchmark is over, so that the goroutine can exit. -func (c *common) Context() context.Context { - return c.ctx -} - func (c *common) setRan() { if c.parent != nil { c.parent.setRan() @@ -619,9 +599,6 @@ type InternalTest struct { } func tRunner(t *T, fn func(t *T)) { - t.ctx, t.cancel = context.WithCancel(t.parentContext()) - defer t.cancel() - // When this goroutine is done, either because fn(t) // returned normally or because a test failure triggered // a call to runtime.Goexit, record the duration and send diff --git a/src/testing/testing_test.go b/src/testing/testing_test.go index 9954f9af8cd..45e44683b43 100644 --- a/src/testing/testing_test.go +++ b/src/testing/testing_test.go @@ -5,42 +5,14 @@ package testing_test import ( - "fmt" "os" - "runtime" "testing" - "time" ) +// This is exactly what a test would do without a TestMain. +// It's here only so that there is at least one package in the +// standard library with a TestMain, so that code is executed. + func TestMain(m *testing.M) { - g0 := runtime.NumGoroutine() - - code := m.Run() - if code != 0 { - os.Exit(code) - } - - // Check that there are no goroutines left behind. - t0 := time.Now() - stacks := make([]byte, 1<<20) - for { - g1 := runtime.NumGoroutine() - if g1 == g0 { - return - } - stacks = stacks[:runtime.Stack(stacks, true)] - time.Sleep(50 * time.Millisecond) - if time.Since(t0) > 2*time.Second { - fmt.Fprintf(os.Stderr, "Unexpected leftover goroutines detected: %v -> %v\n%s\n", g0, g1, stacks) - os.Exit(1) - } - } -} - -func TestContextCancel(t *testing.T) { - ctx := t.Context() - // Tests we don't leak this goroutine: - go func() { - <-ctx.Done() - }() + os.Exit(m.Run()) }