diff --git a/src/context/benchmark_test.go b/src/context/benchmark_test.go new file mode 100644 index 0000000000..b79232704e --- /dev/null +++ b/src/context/benchmark_test.go @@ -0,0 +1,44 @@ +// Copyright 2014 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. + +package context_test + +import ( + . "context" + "fmt" + "testing" +) + +func BenchmarkContextCancelTree(b *testing.B) { + depths := []int{1, 10, 100, 1000} + for _, d := range depths { + b.Run(fmt.Sprintf("depth=%d", d), func(b *testing.B) { + b.Run("Root=Background", func(b *testing.B) { + for i := 0; i < b.N; i++ { + buildContextTree(Background(), d) + } + }) + b.Run("Root=OpenCanceler", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ctx, cancel := WithCancel(Background()) + buildContextTree(ctx, d) + cancel() + } + }) + b.Run("Root=ClosedCanceler", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ctx, cancel := WithCancel(Background()) + cancel() + buildContextTree(ctx, d) + } + }) + }) + } +} + +func buildContextTree(root Context, depth int) { + for d := 0; d < depth; d++ { + root, _ = WithCancel(root) + } +} diff --git a/src/context/context_test.go b/src/context/context_test.go index d305db50dc..2d604a04d3 100644 --- a/src/context/context_test.go +++ b/src/context/context_test.go @@ -10,10 +10,26 @@ import ( "runtime" "strings" "sync" - "testing" "time" ) +type testingT interface { + Error(args ...interface{}) + Errorf(format string, args ...interface{}) + Fail() + FailNow() + Failed() bool + Fatal(args ...interface{}) + Fatalf(format string, args ...interface{}) + Log(args ...interface{}) + Logf(format string, args ...interface{}) + Name() string + Skip(args ...interface{}) + SkipNow() + Skipf(format string, args ...interface{}) + Skipped() bool +} + // otherContext is a Context that's not one of the types defined in context.go. // This lets us test code paths that differ based on the underlying type of the // Context. @@ -21,7 +37,7 @@ type otherContext struct { Context } -func TestBackground(t *testing.T) { +func XTestBackground(t testingT) { c := Background() if c == nil { t.Fatalf("Background returned nil") @@ -36,7 +52,7 @@ func TestBackground(t *testing.T) { } } -func TestTODO(t *testing.T) { +func XTestTODO(t testingT) { c := TODO() if c == nil { t.Fatalf("TODO returned nil") @@ -51,7 +67,7 @@ func TestTODO(t *testing.T) { } } -func TestWithCancel(t *testing.T) { +func XTestWithCancel(t testingT) { c1, cancel := WithCancel(Background()) if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want { @@ -97,7 +113,7 @@ func contains(m map[canceler]struct{}, key canceler) bool { return ret } -func TestParentFinishesChild(t *testing.T) { +func XTestParentFinishesChild(t testingT) { // Context tree: // parent -> cancelChild // parent -> valueChild -> timerChild @@ -174,7 +190,7 @@ func TestParentFinishesChild(t *testing.T) { } } -func TestChildFinishesFirst(t *testing.T) { +func XTestChildFinishesFirst(t testingT) { cancelable, stop := WithCancel(Background()) defer stop() for _, parent := range []Context{Background(), cancelable} { @@ -234,7 +250,7 @@ func TestChildFinishesFirst(t *testing.T) { } } -func testDeadline(c Context, name string, failAfter time.Duration, t *testing.T) { +func testDeadline(c Context, name string, failAfter time.Duration, t testingT) { select { case <-time.After(failAfter): t.Fatalf("%s: context should have timed out", name) @@ -245,7 +261,7 @@ func testDeadline(c Context, name string, failAfter time.Duration, t *testing.T) } } -func TestDeadline(t *testing.T) { +func XTestDeadline(t testingT) { c, _ := WithDeadline(Background(), time.Now().Add(50*time.Millisecond)) if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { t.Errorf("c.String() = %q want prefix %q", got, prefix) @@ -268,7 +284,7 @@ func TestDeadline(t *testing.T) { testDeadline(c, "WithDeadline+now", time.Second, t) } -func TestTimeout(t *testing.T) { +func XTestTimeout(t testingT) { c, _ := WithTimeout(Background(), 50*time.Millisecond) if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { t.Errorf("c.String() = %q want prefix %q", got, prefix) @@ -285,7 +301,7 @@ func TestTimeout(t *testing.T) { testDeadline(c, "WithTimeout+otherContext+WithTimeout", 2*time.Second, t) } -func TestCanceledTimeout(t *testing.T) { +func XTestCanceledTimeout(t testingT) { c, _ := WithTimeout(Background(), time.Second) o := otherContext{c} c, cancel := WithTimeout(o, 2*time.Second) @@ -308,7 +324,7 @@ var k1 = key1(1) var k2 = key2(1) // same int as k1, different type var k3 = key2(3) // same type as k2, different int -func TestValues(t *testing.T) { +func XTestValues(t testingT) { check := func(c Context, nm, v1, v2, v3 string) { if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 { t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0) @@ -356,7 +372,7 @@ func TestValues(t *testing.T) { check(o4, "o4", "", "c2k2", "") } -func TestAllocs(t *testing.T) { +func XTestAllocs(t testingT, testingShort func() bool, testingAllocsPerRun func(int, func()) float64) { bg := Background() for _, test := range []struct { desc string @@ -416,16 +432,16 @@ func TestAllocs(t *testing.T) { limit = test.gccgoLimit } numRuns := 100 - if testing.Short() { + if testingShort() { numRuns = 10 } - if n := testing.AllocsPerRun(numRuns, test.f); n > limit { + if n := testingAllocsPerRun(numRuns, test.f); n > limit { t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit)) } } } -func TestSimultaneousCancels(t *testing.T) { +func XTestSimultaneousCancels(t testingT) { root, cancel := WithCancel(Background()) m := map[Context]CancelFunc{root: cancel} q := []Context{root} @@ -473,7 +489,7 @@ func TestSimultaneousCancels(t *testing.T) { } } -func TestInterlockedCancels(t *testing.T) { +func XTestInterlockedCancels(t testingT) { parent, cancelParent := WithCancel(Background()) child, cancelChild := WithCancel(parent) go func() { @@ -490,15 +506,15 @@ func TestInterlockedCancels(t *testing.T) { } } -func TestLayersCancel(t *testing.T) { +func XTestLayersCancel(t testingT) { testLayers(t, time.Now().UnixNano(), false) } -func TestLayersTimeout(t *testing.T) { +func XTestLayersTimeout(t testingT) { testLayers(t, time.Now().UnixNano(), true) } -func testLayers(t *testing.T, seed int64, testTimeout bool) { +func testLayers(t testingT, seed int64, testTimeout bool) { rand.Seed(seed) errorf := func(format string, a ...interface{}) { t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...) @@ -567,7 +583,7 @@ func testLayers(t *testing.T, seed int64, testTimeout bool) { } } -func TestCancelRemoves(t *testing.T) { +func XTestCancelRemoves(t testingT) { checkChildren := func(when string, ctx Context, want int) { if got := len(ctx.(*cancelCtx).children); got != want { t.Errorf("%s: context has %d children, want %d", when, got, want) @@ -589,7 +605,7 @@ func TestCancelRemoves(t *testing.T) { checkChildren("after cancelling WithTimeout child", ctx, 0) } -func TestWithCancelCanceledParent(t *testing.T) { +func XTestWithCancelCanceledParent(t testingT) { parent, pcancel := WithCancel(Background()) pcancel() @@ -604,7 +620,7 @@ func TestWithCancelCanceledParent(t *testing.T) { } } -func TestWithValueChecksKey(t *testing.T) { +func XTestWithValueChecksKey(t testingT) { panicVal := recoveredValue(func() { WithValue(Background(), []byte("foo"), "bar") }) if panicVal == nil { t.Error("expected panic") @@ -621,7 +637,7 @@ func recoveredValue(fn func()) (v interface{}) { return } -func TestDeadlineExceededSupportsTimeout(t *testing.T) { +func XTestDeadlineExceededSupportsTimeout(t testingT) { i, ok := DeadlineExceeded.(interface { Timeout() bool }) @@ -632,36 +648,3 @@ func TestDeadlineExceededSupportsTimeout(t *testing.T) { t.Fatal("wrong value for timeout") } } - -func BenchmarkContextCancelTree(b *testing.B) { - depths := []int{1, 10, 100, 1000} - for _, d := range depths { - b.Run(fmt.Sprintf("depth=%d", d), func(b *testing.B) { - b.Run("Root=Background", func(b *testing.B) { - for i := 0; i < b.N; i++ { - buildContextTree(Background(), d) - } - }) - b.Run("Root=OpenCanceler", func(b *testing.B) { - for i := 0; i < b.N; i++ { - ctx, cancel := WithCancel(Background()) - buildContextTree(ctx, d) - cancel() - } - }) - b.Run("Root=ClosedCanceler", func(b *testing.B) { - for i := 0; i < b.N; i++ { - ctx, cancel := WithCancel(Background()) - cancel() - buildContextTree(ctx, d) - } - }) - }) - } -} - -func buildContextTree(root Context, depth int) { - for d := 0; d < depth; d++ { - root, _ = WithCancel(root) - } -} diff --git a/src/context/x_test.go b/src/context/x_test.go new file mode 100644 index 0000000000..d14b6f1a32 --- /dev/null +++ b/src/context/x_test.go @@ -0,0 +1,29 @@ +// Copyright 2016 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. + +package context_test + +import ( + . "context" + "testing" +) + +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 TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) }