mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Revert "testing: add T.Context method"
This reverts commit 26827bc2fe.
Fixes #18199
Change-Id: I42e292cb4e3d740a4fbb5d0380c6ee15ac742092
Reviewed-on: https://go-review.googlesource.com/34141
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
e12ce1e400
commit
4bf7d1e722
5 changed files with 34 additions and 96 deletions
|
|
@ -179,7 +179,7 @@ var pkgDeps = map[string][]string{
|
||||||
"runtime/trace": {"L0"},
|
"runtime/trace": {"L0"},
|
||||||
"text/tabwriter": {"L2"},
|
"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/iotest": {"L2", "log"},
|
||||||
"testing/quick": {"L2", "flag", "fmt", "reflect"},
|
"testing/quick": {"L2", "flag", "fmt", "reflect"},
|
||||||
"internal/testenv": {"L2", "OS", "flag", "testing", "syscall"},
|
"internal/testenv": {"L2", "OS", "flag", "testing", "syscall"},
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
package testing
|
package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/race"
|
"internal/race"
|
||||||
|
|
@ -128,9 +127,6 @@ func (b *B) nsPerOp() int64 {
|
||||||
|
|
||||||
// runN runs a single benchmark for the specified number of iterations.
|
// runN runs a single benchmark for the specified number of iterations.
|
||||||
func (b *B) runN(n int) {
|
func (b *B) runN(n int) {
|
||||||
b.ctx, b.cancel = context.WithCancel(b.parentContext())
|
|
||||||
defer b.cancel()
|
|
||||||
|
|
||||||
benchmarkLock.Lock()
|
benchmarkLock.Lock()
|
||||||
defer benchmarkLock.Unlock()
|
defer benchmarkLock.Unlock()
|
||||||
// Try to get a comparable environment for each run
|
// Try to get a comparable environment for each run
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
@ -278,33 +277,28 @@ func TestTRun(t *T) {
|
||||||
ok: true,
|
ok: true,
|
||||||
maxPar: 4,
|
maxPar: 4,
|
||||||
f: func(t *T) {
|
f: func(t *T) {
|
||||||
// t.Parallel doesn't work in the pseudo-T we start with:
|
t.Parallel()
|
||||||
// it leaks a goroutine.
|
for i := 0; i < 12; i++ {
|
||||||
// Call t.Run to get a real one.
|
t.Run("a", func(t *T) {
|
||||||
t.Run("X", func(t *T) {
|
t.Parallel()
|
||||||
t.Parallel()
|
time.Sleep(time.Nanosecond)
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
t.Run("a", func(t *T) {
|
t.Run("b", func(t *T) {
|
||||||
t.Parallel()
|
time.Sleep(time.Nanosecond)
|
||||||
time.Sleep(time.Nanosecond)
|
for i := 0; i < 12; i++ {
|
||||||
for i := 0; i < 12; i++ {
|
t.Run("c", func(t *T) {
|
||||||
t.Run("b", func(t *T) {
|
t.Parallel()
|
||||||
time.Sleep(time.Nanosecond)
|
time.Sleep(time.Nanosecond)
|
||||||
for i := 0; i < 12; i++ {
|
t.Run("d1", func(t *T) {})
|
||||||
t.Run("c", func(t *T) {
|
t.Run("d2", func(t *T) {})
|
||||||
t.Parallel()
|
t.Run("d3", func(t *T) {})
|
||||||
time.Sleep(time.Nanosecond)
|
t.Run("d4", func(t *T) {})
|
||||||
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",
|
desc: "skip output",
|
||||||
|
|
@ -347,7 +341,6 @@ func TestTRun(t *T) {
|
||||||
},
|
},
|
||||||
context: ctx,
|
context: ctx,
|
||||||
}
|
}
|
||||||
root.ctx, root.cancel = context.WithCancel(context.Background())
|
|
||||||
ok := root.Run(tc.desc, tc.f)
|
ok := root.Run(tc.desc, tc.f)
|
||||||
ctx.release()
|
ctx.release()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,6 @@ package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -262,14 +261,12 @@ type common struct {
|
||||||
mu sync.RWMutex // guards output, failed, and done.
|
mu sync.RWMutex // guards output, failed, and done.
|
||||||
output []byte // Output generated by test or benchmark.
|
output []byte // Output generated by test or benchmark.
|
||||||
w io.Writer // For flushToParent.
|
w io.Writer // For flushToParent.
|
||||||
ctx context.Context
|
chatty bool // A copy of the chatty flag.
|
||||||
cancel context.CancelFunc
|
ran bool // Test or benchmark (or one of its subtests) was executed.
|
||||||
chatty bool // A copy of the chatty flag.
|
failed bool // Test or benchmark has failed.
|
||||||
ran bool // Test or benchmark (or one of its subtests) was executed.
|
skipped bool // Test of benchmark has been skipped.
|
||||||
failed bool // Test or benchmark has failed.
|
finished bool // Test function has completed.
|
||||||
skipped bool // Test of benchmark has been skipped.
|
done bool // Test is finished and all subtests have completed.
|
||||||
finished bool // Test function has completed.
|
|
||||||
done bool // Test is finished and all subtests have completed.
|
|
||||||
hasSub bool
|
hasSub bool
|
||||||
raceErrors int // number of races detected during test
|
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.
|
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.
|
// Short reports whether the -test.short flag is set.
|
||||||
func Short() bool {
|
func Short() bool {
|
||||||
return *short
|
return *short
|
||||||
|
|
@ -386,7 +376,6 @@ func fmtDuration(d time.Duration) string {
|
||||||
|
|
||||||
// TB is the interface common to T and B.
|
// TB is the interface common to T and B.
|
||||||
type TB interface {
|
type TB interface {
|
||||||
Context() context.Context
|
|
||||||
Error(args ...interface{})
|
Error(args ...interface{})
|
||||||
Errorf(format string, args ...interface{})
|
Errorf(format string, args ...interface{})
|
||||||
Fail()
|
Fail()
|
||||||
|
|
@ -434,15 +423,6 @@ func (c *common) Name() string {
|
||||||
return c.name
|
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() {
|
func (c *common) setRan() {
|
||||||
if c.parent != nil {
|
if c.parent != nil {
|
||||||
c.parent.setRan()
|
c.parent.setRan()
|
||||||
|
|
@ -619,9 +599,6 @@ type InternalTest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func tRunner(t *T, fn func(t *T)) {
|
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)
|
// When this goroutine is done, either because fn(t)
|
||||||
// returned normally or because a test failure triggered
|
// returned normally or because a test failure triggered
|
||||||
// a call to runtime.Goexit, record the duration and send
|
// a call to runtime.Goexit, record the duration and send
|
||||||
|
|
|
||||||
|
|
@ -5,42 +5,14 @@
|
||||||
package testing_test
|
package testing_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"testing"
|
"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) {
|
func TestMain(m *testing.M) {
|
||||||
g0 := runtime.NumGoroutine()
|
os.Exit(m.Run())
|
||||||
|
|
||||||
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()
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue