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.
18 // go.tools/ssa/interp still has:
19 // - some lesser bugs in recover()
20 // - incomplete support for reflection
21 interp := os.Getenv("GOSSAINTERP") != ""
69 runtime.Breakpoint() // can't depend on panic
72 func mustRecoverBody(v1, v2, v3, x interface{}) {
75 println("spurious recover", v)
80 println("missing recover")
81 die() // panic is useless here
84 println("wrong value", v, x)
88 // the value should be gone now regardless
91 println("recover didn't recover")
96 func doubleRecover() interface{} {
100 func mustRecover(x interface{}) {
101 mustRecoverBody(doubleRecover(), recover(), recover(), x)
104 func mustNotRecover() {
107 println("spurious recover", v)
112 func withoutRecover() {
113 mustNotRecover() // because it's a sub-call
117 defer mustNotRecover() // because mustRecover will squelch it
118 defer mustRecover(1) // because of panic below
119 defer withoutRecover() // should be no-op, leaving for mustRecover to find
123 // Repeat test1 with closures instead of standard function.
124 // Interesting because recover bases its decision
125 // on the frame pointer of its caller, and a closure's
126 // frame pointer is in the middle of its actual arguments
127 // (after the hidden ones for the closed-over variables).
128 func test1WithClosures() {
132 println("spurious recover in closure")
136 defer func(x interface{}) {
140 println("missing recover")
144 println("wrong value", v, x)
155 // Recover only sees the panic argument
156 // if it is called from a deferred call.
157 // It does not see the panic when called from a call within a deferred call (too late)
158 // nor does it see the panic when it *is* the deferred call (too early).
160 defer recover() // should be no-op
165 defer mustNotRecover()
167 recover() // should squelch
173 // Equivalent to test3 but using defer to make the call.
174 defer mustNotRecover()
176 defer recover() // should squelch
181 // Check that closures can set output arguments.
182 // Run g(). If it panics, return x; else return deflt.
183 func try(g func(), deflt interface{}) (x interface{}) {
185 if v := recover(); v != nil {
193 // Check that closures can set output arguments.
194 // Run g(). If it panics, return x; else return deflt.
195 func try1(g func(), deflt interface{}) (x interface{}) {
197 if v := recover(); v != nil {
207 v := try(func() { panic(5) }, 55).(int)
209 println("wrong value", v, 5)
213 s := try(func() {}, "hi").(string)
215 println("wrong value", s, "hi")
219 v = try1(func() { panic(5) }, 55).(int)
221 println("try1 wrong value", v, 5)
225 s = try1(func() {}, "hi").(string)
227 println("try1 wrong value", s, "hi")
232 // When a deferred big call starts, it must first
233 // create yet another stack segment to hold the
234 // giant frame for x. Make sure that doesn't
236 func big(mustRecover bool) {
245 println("missing big recover")
250 println("spurious big recover")
262 func test6WithClosures() {
268 if recover() != nil {
269 println("spurious big closure recover")
278 if recover() == nil {
279 println("missing big closure recover")
283 panic("6WithClosures")
289 // should panic, then call mustRecover 7, which stops the panic.
290 // then should keep processing ordinary defers earlier than that one
292 // this test checks that the defer func on the next line actually runs.
293 defer func() { ok = true }()
298 println("did not run ok func")
303 func varargs(s *int, a ...int) {
305 for _, v := range a {
308 if recover() != nil {
313 func test8a() (r int) {
314 defer varargs(&r, 1, 2, 3)
318 func test8b() (r int) {
319 defer varargs(&r, 4, 5, 6)
324 if test8a() != 106 || test8b() != 15 {
325 println("wrong value")
334 // pointer receiver, so no wrapper in i.M()
338 mustRecoverBody(doubleRecover(), recover(), recover(), 9)
347 func test9reflect1() {
348 f := reflect.ValueOf(&T1{}).Method(0).Interface().(func())
353 func test9reflect2() {
354 f := reflect.TypeOf(&T1{}).Method(0).Func.Interface().(func(*T1))
359 // word-sized value receiver, so no wrapper in i.M()
363 mustRecoverBody(doubleRecover(), recover(), recover(), 10)
372 func test10reflect1() {
373 f := reflect.ValueOf(T2(0)).Method(0).Interface().(func())
378 func test10reflect2() {
379 f := reflect.TypeOf(T2(0)).Method(0).Func.Interface().(func(T2))
384 // tiny receiver, so basic wrapper in i.M()
388 mustRecoverBody(doubleRecover(), recover(), recover(), 11)
397 func test11reflect1() {
398 f := reflect.ValueOf(T3{}).Method(0).Interface().(func())
403 func test11reflect2() {
404 f := reflect.TypeOf(T3{}).Method(0).Func.Interface().(func(T3))
409 // large receiver, so basic wrapper in i.M()
413 mustRecoverBody(doubleRecover(), recover(), recover(), 12)
422 func test12reflect1() {
423 f := reflect.ValueOf(T4{}).Method(0).Interface().(func())
428 func test12reflect2() {
429 f := reflect.TypeOf(T4{}).Method(0).Func.Interface().(func(T4))
434 // enormous receiver, so wrapper splits stack to call M
438 mustRecoverBody(doubleRecover(), recover(), recover(), 13)
447 func test13reflect1() {
448 f := reflect.ValueOf(T5{}).Method(0).Interface().(func())
453 func test13reflect2() {
454 f := reflect.TypeOf(T5{}).Method(0).Func.Interface().(func(T5))
459 // enormous receiver + enormous method frame, so wrapper splits stack to call M,
460 // and then M splits stack to allocate its frame.
461 // recover must look back two frames to find the panic.
473 mustRecoverBody(doubleRecover(), recover(), recover(), 14)
482 func test14reflect1() {
483 f := reflect.ValueOf(T6{}).Method(0).Interface().(func())
488 func test14reflect2() {
489 f := reflect.TypeOf(T6{}).Method(0).Func.Interface().(func(T6))
494 // function created by reflect.MakeFunc
496 func reflectFunc(args []reflect.Value) (results []reflect.Value) {
497 mustRecoverBody(doubleRecover(), recover(), recover(), 15)
502 f := reflect.MakeFunc(reflect.TypeOf((func())(nil)), reflectFunc).Interface().(func())