Source file
src/runtime/defer_test.go
Documentation: runtime
1
2
3
4
5 package runtime_test
6
7 import (
8 "fmt"
9 "reflect"
10 "runtime"
11 "testing"
12 )
13
14
15
16 func TestUnconditionalPanic(t *testing.T) {
17 defer func() {
18 if recover() != "testUnconditional" {
19 t.Fatal("expected unconditional panic")
20 }
21 }()
22 panic("testUnconditional")
23 }
24
25 var glob int = 3
26
27
28
29 func TestOpenAndNonOpenDefers(t *testing.T) {
30 for {
31
32 defer func(n int) {
33 if recover() != "testNonOpenDefer" {
34 t.Fatal("expected testNonOpen panic")
35 }
36 }(3)
37 if glob > 2 {
38 break
39 }
40 }
41 testOpen(t, 47)
42 panic("testNonOpenDefer")
43 }
44
45
46 func testOpen(t *testing.T, arg int) {
47 defer func(n int) {
48 if recover() != "testOpenDefer" {
49 t.Fatal("expected testOpen panic")
50 }
51 }(4)
52 if arg > 2 {
53 panic("testOpenDefer")
54 }
55 }
56
57
58
59 func TestNonOpenAndOpenDefers(t *testing.T) {
60 testOpen(t, 47)
61 for {
62
63 defer func(n int) {
64 if recover() != "testNonOpenDefer" {
65 t.Fatal("expected testNonOpen panic")
66 }
67 }(3)
68 if glob > 2 {
69 break
70 }
71 }
72 panic("testNonOpenDefer")
73 }
74
75 var list []int
76
77
78
79 func TestConditionalDefers(t *testing.T) {
80 list = make([]int, 0, 10)
81
82 defer func() {
83 if recover() != "testConditional" {
84 t.Fatal("expected panic")
85 }
86 want := []int{4, 2, 1}
87 if !reflect.DeepEqual(want, list) {
88 t.Fatal(fmt.Sprintf("wanted %v, got %v", want, list))
89 }
90
91 }()
92 testConditionalDefers(8)
93 }
94
95 func testConditionalDefers(n int) {
96 doappend := func(i int) {
97 list = append(list, i)
98 }
99
100 defer doappend(1)
101 if n > 5 {
102 defer doappend(2)
103 if n > 8 {
104 defer doappend(3)
105 } else {
106 defer doappend(4)
107 }
108 }
109 panic("testConditional")
110 }
111
112
113
114 func TestDisappearingDefer(t *testing.T) {
115 switch runtime.GOOS {
116 case "invalidOS":
117 defer func() {
118 t.Fatal("Defer shouldn't run")
119 }()
120 }
121 }
122
123
124
125
126
127
128
129
130
131
132 func TestAbortedPanic(t *testing.T) {
133 defer func() {
134 r := recover()
135 if r != nil {
136 t.Fatal(fmt.Sprintf("wanted nil recover, got %v", r))
137 }
138 }()
139 defer func() {
140 r := recover()
141 if r != "panic2" {
142 t.Fatal(fmt.Sprintf("wanted %v, got %v", "panic2", r))
143 }
144 }()
145 defer func() {
146 panic("panic2")
147 }()
148 panic("panic1")
149 }
150
151
152
153
154
155 func TestRecoverMatching(t *testing.T) {
156 defer func() {
157 r := recover()
158 if r != "panic1" {
159 t.Fatal(fmt.Sprintf("wanted %v, got %v", "panic1", r))
160 }
161 }()
162 defer func() {
163 defer func() {
164
165
166
167 r := recover()
168 if r != nil {
169 t.Fatal(fmt.Sprintf("wanted nil recover, got %v", r))
170 }
171 }()
172 }()
173 panic("panic1")
174 }
175
176 type nonSSAable [128]byte
177
178 type bigStruct struct {
179 x, y, z, w, p, q int64
180 }
181
182 type containsBigStruct struct {
183 element bigStruct
184 }
185
186 func mknonSSAable() nonSSAable {
187 globint1++
188 return nonSSAable{0, 0, 0, 0, 5}
189 }
190
191 var globint1, globint2, globint3 int
192
193
194 func sideeffect(n int64) int64 {
195 globint2++
196 return n
197 }
198
199 func sideeffect2(in containsBigStruct) containsBigStruct {
200 globint3++
201 return in
202 }
203
204
205 func TestNonSSAableArgs(t *testing.T) {
206 globint1 = 0
207 globint2 = 0
208 globint3 = 0
209 var save1 byte
210 var save2 int64
211 var save3 int64
212 var save4 int64
213
214 defer func() {
215 if globint1 != 1 {
216 t.Fatal(fmt.Sprintf("globint1: wanted: 1, got %v", globint1))
217 }
218 if save1 != 5 {
219 t.Fatal(fmt.Sprintf("save1: wanted: 5, got %v", save1))
220 }
221 if globint2 != 1 {
222 t.Fatal(fmt.Sprintf("globint2: wanted: 1, got %v", globint2))
223 }
224 if save2 != 2 {
225 t.Fatal(fmt.Sprintf("save2: wanted: 2, got %v", save2))
226 }
227 if save3 != 4 {
228 t.Fatal(fmt.Sprintf("save3: wanted: 4, got %v", save3))
229 }
230 if globint3 != 1 {
231 t.Fatal(fmt.Sprintf("globint3: wanted: 1, got %v", globint3))
232 }
233 if save4 != 4 {
234 t.Fatal(fmt.Sprintf("save1: wanted: 4, got %v", save4))
235 }
236 }()
237
238
239 defer func(n nonSSAable) {
240 save1 = n[4]
241 }(mknonSSAable())
242
243 defer func(b bigStruct) {
244 save2 = b.y
245 }(bigStruct{1, 2, 3, 4, 5, sideeffect(6)})
246
247
248 foo := containsBigStruct{}
249 foo.element.z = 4
250 defer func(element bigStruct) {
251 save3 = element.z
252 }(foo.element)
253 defer func(element bigStruct) {
254 save4 = element.z
255 }(sideeffect2(foo).element)
256 }
257
258
259 func doPanic() {
260 panic("Test panic")
261 }
262
263 func TestDeferForFuncWithNoExit(t *testing.T) {
264 cond := 1
265 defer func() {
266 if cond != 2 {
267 t.Fatal(fmt.Sprintf("cond: wanted 2, got %v", cond))
268 }
269 if recover() != "Test panic" {
270 t.Fatal("Didn't find expected panic")
271 }
272 }()
273 x := 0
274
275
276 growStackIter(&x, 1000)
277 cond = 2
278 doPanic()
279
280
281 for {
282 }
283 }
284
285
286
287
288
289
290
291 func TestDeferWithRepeatedRepanics(t *testing.T) {
292 interpreter(0, 6, 2)
293 recurseFnPanicRec(0, 10)
294 interpreter(0, 5, 1)
295 recurseFnPanicRec(0, 10)
296 interpreter(0, 6, 3)
297 recurseFnPanicRec(0, 10)
298 }
299
300 func interpreter(level int, maxlevel int, rec int) {
301 defer func() {
302 e := recover()
303 if e == nil {
304 return
305 }
306 if level != e.(int) {
307
308 panic(e)
309 }
310
311 }()
312 if level+1 < maxlevel {
313 interpreter(level+1, maxlevel, rec)
314 } else {
315
316 panic(rec)
317 }
318 }
319
320 func recurseFnPanicRec(level int, maxlevel int) {
321 defer func() {
322 recover()
323 }()
324 recurseFn(level, maxlevel)
325 }
326
327 var saveInt uint32
328
329 func recurseFn(level int, maxlevel int) {
330 a := [40]uint32{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}
331 if level+1 < maxlevel {
332
333 saveInt = a[4]
334 recurseFn(level+1, maxlevel)
335 } else {
336 panic("recurseFn panic")
337 }
338 }
339
340
341
342
343
344 func TestIssue37688(t *testing.T) {
345 for j := 0; j < 10; j++ {
346 g2()
347 g3()
348 }
349 }
350
351 type foo struct {
352 }
353
354
355 func (f *foo) method1() {
356 }
357
358
359 func (f *foo) method2() {
360 }
361
362 func g2() {
363 var a foo
364 ap := &a
365
366
367 for i := 0; i < 1; i++ {
368 defer ap.method1()
369 }
370 defer ap.method2()
371 defer ap.method1()
372 ff1(ap, 1, 2, 3, 4, 5, 6, 7, 8, 9)
373
374
375 rec1(2000)
376 }
377
378 func g3() {
379
380 g2()
381 }
382
383 var globstruct struct {
384 a, b, c, d, e, f, g, h, i int
385 }
386
387 func ff1(ap *foo, a, b, c, d, e, f, g, h, i int) {
388 defer ap.method1()
389
390
391
392
393 defer func(ap *foo, a, b, c, d, e, f, g, h, i int) {
394 if v := recover(); v != nil {
395 }
396 globstruct.a = a
397 globstruct.b = b
398 globstruct.c = c
399 globstruct.d = d
400 globstruct.e = e
401 globstruct.f = f
402 globstruct.g = g
403 globstruct.h = h
404 }(ap, a, b, c, d, e, f, g, h, i)
405 panic("ff1 panic")
406 }
407
408 func rec1(max int) {
409 if max > 0 {
410 rec1(max - 1)
411 }
412 }
413
414 func TestIssue43921(t *testing.T) {
415 defer func() {
416 expect(t, 1, recover())
417 }()
418 func() {
419
420 for {
421 defer func() {}()
422 break
423 }
424
425 defer func() {
426 defer func() {
427 expect(t, 4, recover())
428 }()
429 panic(4)
430 }()
431 panic(1)
432
433 }()
434 }
435
436 func expect(t *testing.T, n int, err interface{}) {
437 if n != err {
438 t.Fatalf("have %v, want %v", err, n)
439 }
440 }
441
View as plain text