diff options
author | Changkun Ou <hi@changkun.us> | 2020-09-14 10:24:59 +0200 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-09-14 20:27:49 +0000 |
commit | a408139bb0166f6e0a5d9fd17fc934da960c354e (patch) | |
tree | f5cade5946cab5b71a931a344a4a56143695b57d /src/testing/testing.go | |
parent | 57646534297a9bd193e6aaa4239c98984f371b97 (diff) | |
download | go-a408139bb0166f6e0a5d9fd17fc934da960c354e.tar.gz go-a408139bb0166f6e0a5d9fd17fc934da960c354e.zip |
testing: fix panicking tests hang if Cleanup calls FailNow
Previously, it was impossible to call FailNow in a Cleanup.
Because it can terminate a panicking goroutine and cause its
parent hangs on t.signal channel. This CL sends the signal
in a deferred call to prevent the hang.
Fixes #41355
Change-Id: I4552d3a7ea763ef86817bf9b50c0e37fb34bf20f
Reviewed-on: https://go-review.googlesource.com/c/go/+/254637
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Emmanuel Odeke <emm.odeke@gmail.com>
Diffstat (limited to 'src/testing/testing.go')
-rw-r--r-- | src/testing/testing.go | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/src/testing/testing.go b/src/testing/testing.go index 66f296234a..d86354093a 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1075,6 +1075,7 @@ func tRunner(t *T, fn func(t *T)) { // If the test panicked, print any test output before dying. err := recover() signal := true + if !t.finished && err == nil { err = errNilPanicOrGoexit for p := t.parent; p != nil; p = p.parent { @@ -1086,6 +1087,15 @@ func tRunner(t *T, fn func(t *T)) { } } } + // Use a deferred call to ensure that we report that the test is + // complete even if a cleanup function calls t.FailNow. See issue 41355. + didPanic := false + defer func() { + t.signal <- signal + if err != nil && !didPanic { + panic(err) + } + }() doPanic := func(err interface{}) { t.Fail() @@ -1103,6 +1113,7 @@ func tRunner(t *T, fn func(t *T)) { fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r) } } + didPanic = true panic(err) } if err != nil { @@ -1144,7 +1155,6 @@ func tRunner(t *T, fn func(t *T)) { if t.parent != nil && atomic.LoadInt32(&t.hasSub) == 0 { t.setRan() } - t.signal <- signal }() defer func() { if len(t.sub) == 0 { |