github.com/fiagdao/tendermint@v0.32.11-0.20220824195748-2087fcc480c1/abci/client/socket_client_test.go (about)

     1  package abcicli_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	abcicli "github.com/tendermint/tendermint/abci/client"
    13  	"github.com/tendermint/tendermint/abci/server"
    14  	"github.com/tendermint/tendermint/abci/types"
    15  	tmrand "github.com/tendermint/tendermint/libs/rand"
    16  	"github.com/tendermint/tendermint/libs/service"
    17  )
    18  
    19  type errorStopper interface {
    20  	StopForError(error)
    21  }
    22  
    23  func TestSocketClientStopForErrorDeadlock(t *testing.T) {
    24  	c := abcicli.NewSocketClient(":80", false).(errorStopper)
    25  	err := errors.New("foo-tendermint")
    26  
    27  	// See Issue https://github.com/tendermint/abci/issues/114
    28  	doneChan := make(chan bool)
    29  	go func() {
    30  		defer close(doneChan)
    31  		c.StopForError(err)
    32  		c.StopForError(err)
    33  	}()
    34  
    35  	select {
    36  	case <-doneChan:
    37  	case <-time.After(time.Second * 4):
    38  		t.Fatalf("Test took too long, potential deadlock still exists")
    39  	}
    40  }
    41  
    42  func TestProperSyncCalls(t *testing.T) {
    43  	app := slowApp{}
    44  
    45  	s, c := setupClientServer(t, app)
    46  	defer s.Stop()
    47  	defer c.Stop()
    48  
    49  	resp := make(chan error, 1)
    50  	go func() {
    51  		// This is BeginBlockSync unrolled....
    52  		reqres := c.BeginBlockAsync(types.RequestBeginBlock{})
    53  		c.FlushSync()
    54  		res := reqres.Response.GetBeginBlock()
    55  		require.NotNil(t, res)
    56  		resp <- c.Error()
    57  	}()
    58  
    59  	select {
    60  	case <-time.After(time.Second):
    61  		require.Fail(t, "No response arrived")
    62  	case err, ok := <-resp:
    63  		require.True(t, ok, "Must not close channel")
    64  		assert.NoError(t, err, "This should return success")
    65  	}
    66  }
    67  
    68  func TestHangingSyncCalls(t *testing.T) {
    69  	app := slowApp{}
    70  
    71  	s, c := setupClientServer(t, app)
    72  	defer s.Stop()
    73  	defer c.Stop()
    74  
    75  	resp := make(chan error, 1)
    76  	go func() {
    77  		// Start BeginBlock and flush it
    78  		reqres := c.BeginBlockAsync(types.RequestBeginBlock{})
    79  		flush := c.FlushAsync()
    80  		// wait 20 ms for all events to travel socket, but
    81  		// no response yet from server
    82  		time.Sleep(20 * time.Millisecond)
    83  		// kill the server, so the connections break
    84  		s.Stop()
    85  
    86  		// wait for the response from BeginBlock
    87  		reqres.Wait()
    88  		flush.Wait()
    89  		resp <- c.Error()
    90  	}()
    91  
    92  	select {
    93  	case <-time.After(time.Second):
    94  		require.Fail(t, "No response arrived")
    95  	case err, ok := <-resp:
    96  		require.True(t, ok, "Must not close channel")
    97  		assert.Error(t, err, "We should get EOF error")
    98  	}
    99  }
   100  
   101  func setupClientServer(t *testing.T, app types.Application) (
   102  	service.Service, abcicli.Client) {
   103  	// some port between 20k and 30k
   104  	port := 20000 + tmrand.Int32()%10000
   105  	addr := fmt.Sprintf("localhost:%d", port)
   106  
   107  	s, err := server.NewServer(addr, "socket", app)
   108  	require.NoError(t, err)
   109  	err = s.Start()
   110  	require.NoError(t, err)
   111  
   112  	c := abcicli.NewSocketClient(addr, true)
   113  	err = c.Start()
   114  	require.NoError(t, err)
   115  
   116  	return s, c
   117  }
   118  
   119  type slowApp struct {
   120  	types.BaseApplication
   121  }
   122  
   123  func (slowApp) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
   124  	time.Sleep(200 * time.Millisecond)
   125  	return types.ResponseBeginBlock{}
   126  }