github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/tests/deferblock_test.go (about) 1 package tests 2 3 import ( 4 "errors" 5 "fmt" 6 "testing" 7 "time" 8 ) 9 10 func inner(ch chan struct{}, b bool) ([]byte, error) { 11 // ensure gopherjs thinks that this inner function can block 12 if b { 13 <-ch 14 } 15 return []byte{}, nil 16 } 17 18 // this function's call to inner never blocks, but the deferred 19 // statement does. 20 func outer(ch chan struct{}, b bool) ([]byte, error) { 21 defer func() { 22 <-ch 23 }() 24 25 return inner(ch, b) 26 } 27 28 func TestBlockingInDefer(t *testing.T) { 29 defer func() { 30 if x := recover(); x != nil { 31 t.Errorf("run time panic: %v", x) 32 } 33 }() 34 35 ch := make(chan struct{}) 36 b := false 37 38 go func() { 39 time.Sleep(5 * time.Millisecond) 40 ch <- struct{}{} 41 }() 42 43 outer(ch, b) 44 } 45 46 func TestIssue1083(t *testing.T) { 47 // https://github.com/gopherjs/gopherjs/issues/1083 48 block := make(chan bool) 49 50 recoverCompleted := false 51 52 recoverAndBlock := func() { 53 defer func() {}() 54 recover() 55 block <- true 56 recoverCompleted = true 57 } 58 59 handle := func() { 60 defer func() {}() 61 panic("expected panic") 62 } 63 64 serve := func() { 65 defer recoverAndBlock() 66 handle() 67 t.Fatal("This line must never execute.") 68 } 69 70 go func() { <-block }() 71 72 serve() 73 if !recoverCompleted { 74 t.Fatal("Recovery function did not execute fully.") 75 } 76 } 77 78 func TestIssue780(t *testing.T) { 79 // https://github.com/gopherjs/gopherjs/issues/780 80 want := errors.New("expected error") 81 var got error 82 83 catch := func() { 84 if r := recover(); r != nil { 85 got = r.(error) 86 } 87 } 88 throw := func() { panic(want) } 89 90 catchAndThrow := func() { 91 t.Logf("catchAndThrow: %v", recover()) 92 panic(want) 93 } 94 95 execute := func(x int) (err error) { 96 defer catch() // Final recovery. 97 98 for i := 0; i < x; i++ { 99 // Test that several deferred panics can be handled. 100 defer catchAndThrow() 101 } 102 103 defer throw() // Emulates a panicing cleanup. 104 105 return nil 106 } 107 108 for _, x := range []int{0, 1, 2, 5, 10} { 109 t.Run(fmt.Sprint(x), func(t *testing.T) { 110 execute(x) 111 if !errors.Is(got, want) { 112 t.Errorf("process() returned error %v, want %v", got, want) 113 } 114 }) 115 } 116 }