summaryrefslogtreecommitdiffstats
path: root/test/recover1.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/recover1.go')
-rw-r--r--test/recover1.go141
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)
+}