1 // $G $D/$F.go && $L $F.$A && ./$A.out
3 // Copyright 2010 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 // Test of basic recover functionality.
26 runtime.Breakpoint() // can't depend on panic
29 func mustRecover(x interface{}) {
30 mustNotRecover() // because it's not a defer call
33 println("missing recover")
34 die() // panic is useless here
37 println("wrong value", v, x)
41 // the value should be gone now regardless
44 println("recover didn't recover")
49 func mustNotRecover() {
52 println("spurious recover", v)
57 func withoutRecover() {
58 mustNotRecover() // because it's a sub-call
62 defer mustNotRecover() // because mustRecover will squelch it
63 defer mustRecover(1) // because of panic below
64 defer withoutRecover() // should be no-op, leaving for mustRecover to find
68 // Repeat test1 with closures instead of standard function.
69 // Interesting because recover bases its decision
70 // on the frame pointer of its caller, and a closure's
71 // frame pointer is in the middle of its actual arguments
72 // (after the hidden ones for the closed-over variables).
73 func test1WithClosures() {
77 println("spurious recover in closure")
81 defer func(x interface{}) {
85 println("missing recover")
89 println("wrong value", v, x)
100 // Recover only sees the panic argument
101 // if it is called from a deferred call.
102 // It does not see the panic when called from a call within a deferred call (too late)
103 // nor does it see the panic when it *is* the deferred call (too early).
105 defer recover() // should be no-op
110 defer mustNotRecover()
112 recover() // should squelch
118 // Equivalent to test3 but using defer to make the call.
119 defer mustNotRecover()
121 defer recover() // should squelch
126 // Check that closures can set output arguments.
127 // Run g(). If it panics, return x; else return deflt.
128 func try(g func(), deflt interface{}) (x interface{}) {
130 if v := recover(); v != nil {
138 // Check that closures can set output arguments.
139 // Run g(). If it panics, return x; else return deflt.
140 func try1(g func(), deflt interface{}) (x interface{}) {
142 if v := recover(); v != nil {
152 v := try(func() { panic(5) }, 55).(int)
154 println("wrong value", v, 5)
158 s := try(func() {}, "hi").(string)
160 println("wrong value", s, "hi")
164 v = try1(func() { panic(5) }, 55).(int)
166 println("try1 wrong value", v, 5)
170 s = try1(func() {}, "hi").(string)
172 println("try1 wrong value", s, "hi")
177 // When a deferred big call starts, it must first
178 // create yet another stack segment to hold the
179 // giant frame for x. Make sure that doesn't
181 func big(mustRecover bool) {
190 println("missing big recover")
195 println("spurious big recover")
207 func test6WithClosures() {
213 if recover() != nil {
214 println("spurious big closure recover")
223 if recover() == nil {
224 println("missing big closure recover")
228 panic("6WithClosures")
234 // should panic, then call mustRecover 7, which stops the panic.
235 // then should keep processing ordinary defers earlier than that one
237 // this test checks that the defer func on the next line actually runs.
238 defer func() { ok = true }()
243 println("did not run ok func")