diff options
Diffstat (limited to 'test/recover1.go')
-rw-r--r-- | test/recover1.go | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/test/recover1.go b/test/recover1.go new file mode 100644 index 0000000..c14a607 --- /dev/null +++ b/test/recover1.go @@ -0,0 +1,141 @@ +// run + +// Copyright 2010 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. + +// Test of recover during recursive panics. +// Here be dragons. + +package main + +import "runtime" + +func main() { + test1() + test2() + test3() + test4() + test5() + test6() + test7() +} + +func die() { + runtime.Breakpoint() // can't depend on panic +} + +func mustRecover(x interface{}) { + mustNotRecover() // because it's not a defer call + v := recover() + if v == nil { + println("missing recover") + die() // panic is useless here + } + if v != x { + println("wrong value", v, x) + die() + } + + // the value should be gone now regardless + v = recover() + if v != nil { + println("recover didn't recover") + die() + } +} + +func mustNotRecover() { + v := recover() + if v != nil { + println("spurious recover") + die() + } +} + +func withoutRecover() { + mustNotRecover() // because it's a sub-call +} + +func test1() { + // Easy nested recursive panic. + defer mustRecover(1) + defer func() { + defer mustRecover(2) + panic(2) + }() + panic(1) +} + +func test2() { + // Sequential panic. + defer mustNotRecover() + defer func() { + v := recover() + if v == nil || v.(int) != 2 { + println("wrong value", v, 2) + die() + } + defer mustRecover(3) + panic(3) + }() + panic(2) +} + +func test3() { + // Sequential panic - like test2 but less picky. + defer mustNotRecover() + defer func() { + recover() + defer mustRecover(3) + panic(3) + }() + panic(2) +} + +func test4() { + // Single panic. + defer mustNotRecover() + defer func() { + recover() + }() + panic(4) +} + +func test5() { + // Single panic but recover called via defer + defer mustNotRecover() + defer func() { + defer recover() + }() + panic(5) +} + +func test6() { + // Sequential panic. + // Like test3, but changed recover to defer (same change as test4 → test5). + defer mustNotRecover() + defer func() { + defer recover() // like a normal call from this func; runs because mustRecover stops the panic + defer mustRecover(3) + panic(3) + }() + panic(2) +} + +func test7() { + // Like test6, but swapped defer order. + // The recover in "defer recover()" is now a no-op, + // because it runs called from panic, not from the func, + // and therefore cannot see the panic of 2. + // (Alternately, it cannot see the panic of 2 because + // there is an active panic of 3. And it cannot see the + // panic of 3 because it is at the wrong level (too high on the stack).) + defer mustRecover(2) + defer func() { + defer mustRecover(3) + defer recover() // now a no-op, unlike in test6. + panic(3) + }() + panic(2) +} |