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  }