diff options
Diffstat (limited to 'libgo/go/testing/testing.go')
-rw-r--r-- | libgo/go/testing/testing.go | 55 |
1 files changed, 47 insertions, 8 deletions
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() |