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