OLD | NEW |
1 // $G $D/$F.go && $L $F.$A && ./$A.out | 1 // $G $D/$F.go && $L $F.$A && ./$A.out |
2 | 2 |
3 // Copyright 2010 The Go Authors. All rights reserved. | 3 // Copyright 2010 The Go Authors. All rights reserved. |
4 // Use of this source code is governed by a BSD-style | 4 // Use of this source code is governed by a BSD-style |
5 // license that can be found in the LICENSE file. | 5 // license that can be found in the LICENSE file. |
6 | 6 |
7 // Test of basic recover functionality. | 7 // Test of basic recover functionality. |
8 | 8 |
9 package main | 9 package main |
10 | 10 |
11 import "runtime" | 11 import "runtime" |
12 | 12 |
13 func main() { | 13 func main() { |
| 14 println("xxx") |
14 test1() | 15 test1() |
| 16 println("xxx") |
15 test1WithClosures() | 17 test1WithClosures() |
| 18 println("xxx") |
16 test2() | 19 test2() |
| 20 println("xxx") |
17 test3() | 21 test3() |
| 22 println("xxx") |
18 test4() | 23 test4() |
| 24 println("xxx") |
19 test5() | 25 test5() |
| 26 println("xxx") |
20 test6() | 27 test6() |
| 28 println("xxx") |
21 test6WithClosures() | 29 test6WithClosures() |
| 30 println("xxx") |
22 test7() | 31 test7() |
23 } | 32 } |
24 | 33 |
25 func die() { | 34 func die() { |
26 » runtime.Breakpoint()» // can't depend on panic | 35 » runtime.Breakpoint() // can't depend on panic |
27 } | 36 } |
28 | 37 |
29 func mustRecover(x interface{}) { | 38 func mustRecover(x interface{}) { |
30 » mustNotRecover()» // because it's not a defer call | 39 » mustNotRecover() // because it's not a defer call |
31 v := recover() | 40 v := recover() |
32 if v == nil { | 41 if v == nil { |
33 println("missing recover") | 42 println("missing recover") |
34 » » die()» // panic is useless here | 43 » » die() // panic is useless here |
35 } | 44 } |
36 if v != x { | 45 if v != x { |
37 println("wrong value", v, x) | 46 println("wrong value", v, x) |
38 die() | 47 die() |
39 } | 48 } |
40 » | 49 |
41 // the value should be gone now regardless | 50 // the value should be gone now regardless |
42 v = recover() | 51 v = recover() |
43 if v != nil { | 52 if v != nil { |
44 println("recover didn't recover") | 53 println("recover didn't recover") |
45 die() | 54 die() |
46 } | 55 } |
47 } | 56 } |
48 | 57 |
49 func mustNotRecover() { | 58 func mustNotRecover() { |
50 v := recover() | 59 v := recover() |
51 if v != nil { | 60 if v != nil { |
52 » » println("spurious recover") | 61 » » println("spurious recover", v) |
53 die() | 62 die() |
54 } | 63 } |
55 } | 64 } |
56 | 65 |
57 func withoutRecover() { | 66 func withoutRecover() { |
58 » mustNotRecover()» // because it's a sub-call | 67 » mustNotRecover() // because it's a sub-call |
59 } | 68 } |
60 | 69 |
61 func test1() { | 70 func test1() { |
62 » defer mustNotRecover()» // because mustRecover will squelch it | 71 » defer mustNotRecover() // because mustRecover will squelch it |
63 » defer mustRecover(1)» // because of panic below | 72 » defer mustRecover(1) // because of panic below |
64 » defer withoutRecover()» // should be no-op, leaving for mustRecover to f
ind | 73 » defer withoutRecover() // should be no-op, leaving for mustRecover to fi
nd |
65 panic(1) | 74 panic(1) |
66 } | 75 } |
67 | 76 |
68 // Repeat test1 with closures instead of standard function. | 77 // Repeat test1 with closures instead of standard function. |
69 // Interesting because recover bases its decision | 78 // Interesting because recover bases its decision |
70 // on the frame pointer of its caller, and a closure's | 79 // on the frame pointer of its caller, and a closure's |
71 // frame pointer is in the middle of its actual arguments | 80 // frame pointer is in the middle of its actual arguments |
72 // (after the hidden ones for the closed-over variables). | 81 // (after the hidden ones for the closed-over variables). |
73 func test1WithClosures() { | 82 func test1WithClosures() { |
74 defer func() { | 83 defer func() { |
(...skipping 20 matching lines...) Expand all Loading... |
95 }() | 104 }() |
96 panic(1) | 105 panic(1) |
97 } | 106 } |
98 | 107 |
99 func test2() { | 108 func test2() { |
100 // Recover only sees the panic argument | 109 // Recover only sees the panic argument |
101 // if it is called from a deferred call. | 110 // if it is called from a deferred call. |
102 // It does not see the panic when called from a call within a deferred c
all (too late) | 111 // It does not see the panic when called from a call within a deferred c
all (too late) |
103 // nor does it see the panic when it *is* the deferred call (too early). | 112 // nor does it see the panic when it *is* the deferred call (too early). |
104 defer mustRecover(2) | 113 defer mustRecover(2) |
105 » defer recover()»// should be no-op | 114 » defer recover() // should be no-op |
106 panic(2) | 115 panic(2) |
107 } | 116 } |
108 | 117 |
109 func test3() { | 118 func test3() { |
110 defer mustNotRecover() | 119 defer mustNotRecover() |
111 defer func() { | 120 defer func() { |
112 » » recover()» // should squelch | 121 » » recover() // should squelch |
113 }() | 122 }() |
114 panic(3) | 123 panic(3) |
115 } | 124 } |
116 | 125 |
117 func test4() { | 126 func test4() { |
118 // Equivalent to test3 but using defer to make the call. | 127 // Equivalent to test3 but using defer to make the call. |
119 defer mustNotRecover() | 128 defer mustNotRecover() |
120 defer func() { | 129 defer func() { |
121 » » defer recover()»// should squelch | 130 » » defer recover() // should squelch |
122 }() | 131 }() |
123 panic(4) | 132 panic(4) |
124 } | 133 } |
125 | 134 |
126 // Check that closures can set output arguments. | 135 // Check that closures can set output arguments. |
127 // Run g(). If it panics, return x; else return deflt. | 136 // Run g(). If it panics, return x; else return deflt. |
128 func try(g func(), deflt interface{}) (x interface{}) { | 137 func try(g func(), deflt interface{}) (x interface{}) { |
129 defer func() { | 138 defer func() { |
130 if v := recover(); v != nil { | 139 if v := recover(); v != nil { |
131 x = v | 140 x = v |
(...skipping 15 matching lines...) Expand all Loading... |
147 x = deflt | 156 x = deflt |
148 return | 157 return |
149 } | 158 } |
150 | 159 |
151 func test5() { | 160 func test5() { |
152 v := try(func() { panic(5) }, 55).(int) | 161 v := try(func() { panic(5) }, 55).(int) |
153 if v != 5 { | 162 if v != 5 { |
154 println("wrong value", v, 5) | 163 println("wrong value", v, 5) |
155 die() | 164 die() |
156 } | 165 } |
157 » | 166 |
158 » s := try(func() { }, "hi").(string) | 167 » s := try(func() {}, "hi").(string) |
159 if s != "hi" { | 168 if s != "hi" { |
160 println("wrong value", s, "hi") | 169 println("wrong value", s, "hi") |
161 die() | 170 die() |
162 } | 171 } |
163 | 172 |
164 v = try1(func() { panic(5) }, 55).(int) | 173 v = try1(func() { panic(5) }, 55).(int) |
165 if v != 5 { | 174 if v != 5 { |
166 println("try1 wrong value", v, 5) | 175 println("try1 wrong value", v, 5) |
167 die() | 176 die() |
168 } | 177 } |
169 » | 178 |
170 » s = try1(func() { }, "hi").(string) | 179 » s = try1(func() {}, "hi").(string) |
171 if s != "hi" { | 180 if s != "hi" { |
172 println("try1 wrong value", s, "hi") | 181 println("try1 wrong value", s, "hi") |
173 die() | 182 die() |
174 } | 183 } |
175 } | 184 } |
176 | 185 |
177 // When a deferred big call starts, it must first | 186 // When a deferred big call starts, it must first |
178 // create yet another stack segment to hold the | 187 // create yet another stack segment to hold the |
179 // giant frame for x. Make sure that doesn't | 188 // giant frame for x. Make sure that doesn't |
180 // confuse recover. | 189 // confuse recover. |
181 func big(mustRecover bool) { | 190 func big(mustRecover bool) { |
182 var x [100000]int | 191 var x [100000]int |
183 x[0] = 1 | 192 x[0] = 1 |
184 x[99999] = 1 | 193 x[99999] = 1 |
185 _ = x | 194 _ = x |
186 » | 195 |
187 v := recover() | 196 v := recover() |
188 if mustRecover { | 197 if mustRecover { |
189 if v == nil { | 198 if v == nil { |
190 println("missing big recover") | 199 println("missing big recover") |
191 die() | 200 die() |
192 } | 201 } |
193 } else { | 202 } else { |
194 if v != nil { | 203 if v != nil { |
195 println("spurious big recover") | 204 println("spurious big recover") |
196 die() | 205 die() |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 // this test checks that the defer func on the next line actuall
y runs. | 246 // this test checks that the defer func on the next line actuall
y runs. |
238 defer func() { ok = true }() | 247 defer func() { ok = true }() |
239 defer mustRecover(7) | 248 defer mustRecover(7) |
240 panic(7) | 249 panic(7) |
241 }() | 250 }() |
242 if !ok { | 251 if !ok { |
243 println("did not run ok func") | 252 println("did not run ok func") |
244 die() | 253 die() |
245 } | 254 } |
246 } | 255 } |
OLD | NEW |