]> Cypherpunks.ru repositories - gostls13.git/blob - test/recover1.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / recover1.go
1 // run
2
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.
6
7 // Test of recover during recursive panics.
8 // Here be dragons.
9
10 package main
11
12 import "runtime"
13
14 func main() {
15         test1()
16         test2()
17         test3()
18         test4()
19         test5()
20         test6()
21         test7()
22 }
23
24 func die() {
25         runtime.Breakpoint()    // can't depend on panic
26 }
27
28 func mustRecover(x interface{}) {
29         mustNotRecover()        // because it's not a defer call
30         v := recover()
31         if v == nil {
32                 println("missing recover")
33                 die()   // panic is useless here
34         }
35         if v != x {
36                 println("wrong value", v, x)
37                 die()
38         }
39         
40         // the value should be gone now regardless
41         v = recover()
42         if v != nil {
43                 println("recover didn't recover")
44                 die()
45         }
46 }
47
48 func mustNotRecover() {
49         v := recover()
50         if v != nil {
51                 println("spurious recover")
52                 die()
53         }
54 }
55
56 func withoutRecover() {
57         mustNotRecover()        // because it's a sub-call
58 }
59
60 func test1() {
61         // Easy nested recursive panic.
62         defer mustRecover(1)
63         defer func() {
64                 defer mustRecover(2)
65                 panic(2)
66         }()
67         panic(1)
68 }
69
70 func test2() {
71         // Sequential panic.
72         defer mustNotRecover()
73         defer func() {
74                 v := recover()
75                 if v == nil || v.(int) != 2 {
76                         println("wrong value", v, 2)
77                         die()
78                 }
79                 defer mustRecover(3)
80                 panic(3)
81         }()
82         panic(2)
83 }
84
85 func test3() {
86         // Sequential panic - like test2 but less picky.
87         defer mustNotRecover()
88         defer func() {
89                 recover()
90                 defer mustRecover(3)
91                 panic(3)
92         }()
93         panic(2)
94 }
95
96 func test4() {
97         // Single panic.
98         defer mustNotRecover()
99         defer func() {
100                 recover()
101         }()
102         panic(4)
103 }
104
105 func test5() {
106         // Single panic but recover called via defer
107         defer mustNotRecover()
108         defer func() {
109                 defer recover()
110         }()
111         panic(5)
112 }
113
114 func test6() {
115         // Sequential panic.
116         // Like test3, but changed recover to defer (same change as test4 → test5).
117         defer mustNotRecover()
118         defer func() {
119                 defer recover() // like a normal call from this func; runs because mustRecover stops the panic
120                 defer mustRecover(3)
121                 panic(3)
122         }()
123         panic(2)
124 }
125
126 func test7() {
127         // Like test6, but swapped defer order.
128         // The recover in "defer recover()" is now a no-op,
129         // because it runs called from panic, not from the func,
130         // and therefore cannot see the panic of 2.
131         // (Alternately, it cannot see the panic of 2 because
132         // there is an active panic of 3.  And it cannot see the
133         // panic of 3 because it is at the wrong level (too high on the stack).)
134         defer mustRecover(2)
135         defer func() {
136                 defer mustRecover(3)
137                 defer recover() // now a no-op, unlike in test6.
138                 panic(3)
139         }()
140         panic(2)
141 }