aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/testing
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-02-05 14:33:27 -0800
committerIan Lance Taylor <iant@golang.org>2020-02-15 09:14:10 -0800
commit0b3c2eed35d608d6541ecf004a9576b4eae0b4ef (patch)
treec92c05d53eb054d8085d069800f4e9b586fef5a3 /libgo/go/testing
parent17edb3310d8ce9d5f6c9e53f6c1f7d611c2a5a41 (diff)
downloadgcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.zip
gcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.tar.gz
gcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.tar.bz2
libgo: update to Go1.14rc1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/218017
Diffstat (limited to 'libgo/go/testing')
-rw-r--r--libgo/go/testing/benchmark.go2
-rw-r--r--libgo/go/testing/panic_test.go129
-rw-r--r--libgo/go/testing/sub_test.go31
-rw-r--r--libgo/go/testing/testing.go55
4 files changed, 207 insertions, 10 deletions
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 0412772..93f461b 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -86,7 +86,7 @@ type InternalBenchmark struct {
// may be called simultaneously from multiple goroutines.
//
// Like in tests, benchmark logs are accumulated during execution
-// and dumped to standard error when done. Unlike in tests, benchmark logs
+// and dumped to standard output when done. Unlike in tests, benchmark logs
// are always printed, so as not to hide output whose existence may be
// affecting benchmark results.
type B struct {
diff --git a/libgo/go/testing/panic_test.go b/libgo/go/testing/panic_test.go
index 3491510..6b8b953 100644
--- a/libgo/go/testing/panic_test.go
+++ b/libgo/go/testing/panic_test.go
@@ -16,6 +16,9 @@ import (
)
var testPanicTest = flag.String("test_panic_test", "", "TestPanic: indicates which test should panic")
+var testPanicParallel = flag.Bool("test_panic_parallel", false, "TestPanic: run subtests in parallel")
+var testPanicCleanup = flag.Bool("test_panic_cleanup", false, "TestPanic: indicates whether test should call Cleanup")
+var testPanicCleanupPanic = flag.String("test_panic_cleanup_panic", "", "TestPanic: indicate whether test should call Cleanup function that panics")
func TestPanic(t *testing.T) {
testenv.MustHaveExec(t)
@@ -40,6 +43,98 @@ func TestPanic(t *testing.T) {
--- FAIL: TestPanicHelper/1 (N.NNs)
panic_test.go:NNN: TestPanicHelper/1
`,
+ }, {
+ desc: "subtest panics with cleanup",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "subtest panics with outer cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+`,
+ }, {
+ desc: "subtest panics with middle cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "subtest panics with inner cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "parallel subtest panics with cleanup",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "parallel subtest panics with outer cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+`,
+ }, {
+ desc: "parallel subtest panics with middle cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "parallel subtest panics with inner cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
}}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
@@ -72,10 +167,42 @@ func TestPanicHelper(t *testing.T) {
if t.Name() == *testPanicTest {
panic("panic")
}
+ switch *testPanicCleanupPanic {
+ case "", "outer", "middle", "inner":
+ default:
+ t.Fatalf("bad -test_panic_cleanup_panic: %s", *testPanicCleanupPanic)
+ }
+ t.Cleanup(func() {
+ fmt.Println("ran outer cleanup")
+ if *testPanicCleanupPanic == "outer" {
+ panic("outer cleanup")
+ }
+ })
for i := 0; i < 3; i++ {
+ i := i
t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
+ chosen := t.Name() == *testPanicTest
+ if chosen && *testPanicCleanup {
+ t.Cleanup(func() {
+ fmt.Printf("ran middle cleanup %d\n", i)
+ if *testPanicCleanupPanic == "middle" {
+ panic("middle cleanup")
+ }
+ })
+ }
+ if chosen && *testPanicParallel {
+ t.Parallel()
+ }
t.Log(t.Name())
- if t.Name() == *testPanicTest {
+ if chosen {
+ if *testPanicCleanup {
+ t.Cleanup(func() {
+ fmt.Printf("ran inner cleanup %d\n", i)
+ if *testPanicCleanupPanic == "inner" {
+ panic("inner cleanup")
+ }
+ })
+ }
panic("panic")
}
})
diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go
index 3f0f71f..3dc30ee 100644
--- a/libgo/go/testing/sub_test.go
+++ b/libgo/go/testing/sub_test.go
@@ -460,6 +460,21 @@ func TestTRun(t *T) {
<-ch
t.Errorf("error")
},
+ }, {
+ // If a subtest panics we should run cleanups.
+ desc: "cleanup when subtest panics",
+ ok: false,
+ chatty: false,
+ output: `
+--- FAIL: cleanup when subtest panics (N.NNs)
+ --- FAIL: cleanup when subtest panics/sub (N.NNs)
+ sub_test.go:NNN: running cleanup`,
+ f: func(t *T) {
+ t.Cleanup(func() { t.Log("running cleanup") })
+ t.Run("sub", func(t2 *T) {
+ t2.FailNow()
+ })
+ },
}}
for _, tc := range testCases {
ctx := newTestContext(tc.maxPar, newMatcher(regexp.MatchString, "", ""))
@@ -855,3 +870,19 @@ func TestRunCleanup(t *T) {
t.Errorf("unexpected outer cleanup count; got %d want 0", outerCleanup)
}
}
+
+func TestCleanupParallelSubtests(t *T) {
+ ranCleanup := 0
+ t.Run("test", func(t *T) {
+ t.Cleanup(func() { ranCleanup++ })
+ t.Run("x", func(t *T) {
+ t.Parallel()
+ if ranCleanup > 0 {
+ t.Error("outer cleanup ran before parallel subtest")
+ }
+ })
+ })
+ if ranCleanup != 1 {
+ t.Errorf("unexpected cleanup count; got %d want 1", ranCleanup)
+ }
+}
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index e05314e..67892d7 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -812,9 +812,9 @@ func (c *common) Helper() {
c.helpers[callerName(1)] = struct{}{}
}
-// Cleanup registers a function to be called when the test finishes.
-// Cleanup functions will be called in last added, first called
-// order.
+// Cleanup registers a function to be called when the test and all its
+// subtests complete. Cleanup functions will be called in last added,
+// first called order.
func (c *common) Cleanup(f func()) {
c.mu.Lock()
defer c.mu.Unlock()
@@ -827,15 +827,34 @@ func (c *common) Cleanup(f func()) {
}
}
+// panicHanding is an argument to runCleanup.
+type panicHandling int
+
+const (
+ normalPanic panicHandling = iota
+ recoverAndReturnPanic
+)
+
// runCleanup is called at the end of the test.
-func (c *common) runCleanup() {
+// If catchPanic is true, this will catch panics, and return the recovered
+// value if any.
+func (c *common) runCleanup(ph panicHandling) (panicVal interface{}) {
c.mu.Lock()
cleanup := c.cleanup
c.cleanup = nil
c.mu.Unlock()
- if cleanup != nil {
- cleanup()
+ if cleanup == nil {
+ return nil
+ }
+
+ if ph == recoverAndReturnPanic {
+ defer func() {
+ panicVal = recover()
+ }()
}
+
+ cleanup()
+ return nil
}
// callerName gives the function name (qualified with a package path)
@@ -938,19 +957,29 @@ func tRunner(t *T, fn func(t *T)) {
}
}
}
- if err != nil {
+
+ doPanic := func(err interface{}) {
t.Fail()
+ if r := t.runCleanup(recoverAndReturnPanic); r != nil {
+ t.Logf("cleanup panicked with %v", r)
+ }
// Flush the output log up to the root before dying.
t.mu.Lock()
root := &t.common
for ; root.parent != nil; root = root.parent {
root.duration += time.Since(root.start)
fmt.Fprintf(root.parent.w, "--- FAIL: %s (%s)\n", root.name, fmtDuration(root.duration))
+ if r := root.parent.runCleanup(recoverAndReturnPanic); r != nil {
+ fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r)
+ }
root.parent.mu.Lock()
io.Copy(root.parent.w, bytes.NewReader(root.output))
}
panic(err)
}
+ if err != nil {
+ doPanic(err)
+ }
t.duration += time.Since(t.start)
@@ -964,6 +993,12 @@ func tRunner(t *T, fn func(t *T)) {
for _, sub := range t.sub {
<-sub.signal
}
+ cleanupStart := time.Now()
+ err := t.runCleanup(recoverAndReturnPanic)
+ t.duration += time.Since(cleanupStart)
+ if err != nil {
+ doPanic(err)
+ }
if !t.isParallel {
// Reacquire the count for sequential tests. See comment in Run.
t.context.waitParallel()
@@ -983,7 +1018,11 @@ func tRunner(t *T, fn func(t *T)) {
}
t.signal <- signal
}()
- defer t.runCleanup()
+ defer func() {
+ if len(t.sub) == 0 {
+ t.runCleanup(normalPanic)
+ }
+ }()
t.start = time.Now()
t.raceErrors = -race.Errors()