github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/abci/client/socket_client_test.go (about)

     1  package abcicli_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/tendermint/tendermint/abci/types"
    12  
    13  	abcicli "github.com/line/ostracon/abci/client"
    14  	"github.com/line/ostracon/abci/server"
    15  	ocabci "github.com/line/ostracon/abci/types"
    16  	tmrand "github.com/line/ostracon/libs/rand"
    17  	"github.com/line/ostracon/libs/service"
    18  )
    19  
    20  func TestProperSyncCalls(t *testing.T) {
    21  	app := slowApp{}
    22  
    23  	s, c := setupClientServer(t, app)
    24  	t.Cleanup(func() {
    25  		if err := s.Stop(); err != nil {
    26  			t.Error(err)
    27  		}
    28  	})
    29  	t.Cleanup(func() {
    30  		if err := c.Stop(); err != nil {
    31  			t.Error(err)
    32  		}
    33  	})
    34  
    35  	resp := make(chan error, 1)
    36  	go func() {
    37  		// This is BeginBlockSync unrolled....
    38  		reqres := c.BeginBlockAsync(ocabci.RequestBeginBlock{}, nil)
    39  		_, err := c.FlushSync()
    40  		require.NoError(t, err)
    41  		res := reqres.Response.GetBeginBlock()
    42  		require.NotNil(t, res)
    43  		resp <- c.Error()
    44  	}()
    45  
    46  	select {
    47  	case <-time.After(time.Second):
    48  		require.Fail(t, "No response arrived")
    49  	case err, ok := <-resp:
    50  		require.True(t, ok, "Must not close channel")
    51  		assert.NoError(t, err, "This should return success")
    52  	}
    53  }
    54  
    55  func TestHangingSyncCalls(t *testing.T) {
    56  	app := slowApp{}
    57  
    58  	s, c := setupClientServer(t, app)
    59  	t.Cleanup(func() {
    60  		if err := s.Stop(); err != nil {
    61  			t.Log(err)
    62  		}
    63  	})
    64  	t.Cleanup(func() {
    65  		if err := c.Stop(); err != nil {
    66  			t.Log(err)
    67  		}
    68  	})
    69  
    70  	resp := make(chan error, 1)
    71  	go func() {
    72  		// Start BeginBlock and flush it
    73  		reqres := c.BeginBlockAsync(ocabci.RequestBeginBlock{}, nil)
    74  		flush := c.FlushAsync(nil)
    75  		// wait 20 ms for all events to travel socket, but
    76  		// no response yet from server
    77  		time.Sleep(20 * time.Millisecond)
    78  		// kill the server, so the connections break
    79  		err := s.Stop()
    80  		require.NoError(t, err)
    81  
    82  		// wait for the response from BeginBlock
    83  		reqres.Wait()
    84  		flush.Wait()
    85  		resp <- c.Error()
    86  	}()
    87  
    88  	select {
    89  	case <-time.After(time.Second):
    90  		require.Fail(t, "No response arrived")
    91  	case err, ok := <-resp:
    92  		require.True(t, ok, "Must not close channel")
    93  		assert.Error(t, err, "We should get EOF error")
    94  	}
    95  }
    96  
    97  func setupClientServer(t *testing.T, app ocabci.Application) (
    98  	service.Service, abcicli.Client) {
    99  	// some port between 20k and 30k
   100  	port := 20000 + tmrand.Int32()%10000
   101  	addr := fmt.Sprintf("localhost:%d", port)
   102  
   103  	s, err := server.NewServer(addr, "socket", app)
   104  	require.NoError(t, err)
   105  	err = s.Start()
   106  	require.NoError(t, err)
   107  
   108  	c := abcicli.NewSocketClient(addr, true)
   109  	err = c.Start()
   110  	require.NoError(t, err)
   111  
   112  	return s, c
   113  }
   114  
   115  type slowApp struct {
   116  	ocabci.BaseApplication
   117  }
   118  
   119  func (slowApp) BeginBlock(req ocabci.RequestBeginBlock) types.ResponseBeginBlock {
   120  	time.Sleep(200 * time.Millisecond)
   121  	return types.ResponseBeginBlock{}
   122  }
   123  
   124  func TestSockerClientCalls(t *testing.T) {
   125  	app := sampleApp{}
   126  
   127  	s, c := setupClientServer(t, app)
   128  	t.Cleanup(func() {
   129  		if err := s.Stop(); err != nil {
   130  			t.Error(err)
   131  		}
   132  	})
   133  	t.Cleanup(func() {
   134  		if err := c.Stop(); err != nil {
   135  			t.Error(err)
   136  		}
   137  	})
   138  
   139  	c.SetGlobalCallback(func(*ocabci.Request, *ocabci.Response) {
   140  	})
   141  
   142  	c.EchoAsync("msg", getResponseCallback(t))
   143  	c.FlushAsync(getResponseCallback(t))
   144  	c.InfoAsync(types.RequestInfo{}, getResponseCallback(t))
   145  	c.SetOptionAsync(types.RequestSetOption{}, getResponseCallback(t))
   146  	c.DeliverTxAsync(types.RequestDeliverTx{}, getResponseCallback(t))
   147  	c.CheckTxAsync(types.RequestCheckTx{}, getResponseCallback(t))
   148  	c.QueryAsync(types.RequestQuery{}, getResponseCallback(t))
   149  	c.CommitAsync(getResponseCallback(t))
   150  	c.InitChainAsync(types.RequestInitChain{}, getResponseCallback(t))
   151  	c.BeginBlockAsync(ocabci.RequestBeginBlock{}, getResponseCallback(t))
   152  	c.EndBlockAsync(types.RequestEndBlock{}, getResponseCallback(t))
   153  	c.BeginRecheckTxAsync(ocabci.RequestBeginRecheckTx{}, getResponseCallback(t))
   154  	c.EndRecheckTxAsync(ocabci.RequestEndRecheckTx{}, getResponseCallback(t))
   155  	c.ListSnapshotsAsync(types.RequestListSnapshots{}, getResponseCallback(t))
   156  	c.OfferSnapshotAsync(types.RequestOfferSnapshot{}, getResponseCallback(t))
   157  	c.LoadSnapshotChunkAsync(types.RequestLoadSnapshotChunk{}, getResponseCallback(t))
   158  	c.ApplySnapshotChunkAsync(types.RequestApplySnapshotChunk{}, getResponseCallback(t))
   159  
   160  	_, err := c.EchoSync("msg")
   161  	require.NoError(t, err)
   162  
   163  	_, err = c.FlushSync()
   164  	require.NoError(t, err)
   165  
   166  	_, err = c.InfoSync(types.RequestInfo{})
   167  	require.NoError(t, err)
   168  
   169  	_, err = c.SetOptionSync(types.RequestSetOption{})
   170  	require.NoError(t, err)
   171  
   172  	_, err = c.DeliverTxSync(types.RequestDeliverTx{})
   173  	require.NoError(t, err)
   174  
   175  	_, err = c.CheckTxSync(types.RequestCheckTx{})
   176  	require.NoError(t, err)
   177  
   178  	_, err = c.QuerySync(types.RequestQuery{})
   179  	require.NoError(t, err)
   180  
   181  	_, err = c.CommitSync()
   182  	require.NoError(t, err)
   183  
   184  	_, err = c.InitChainSync(types.RequestInitChain{})
   185  	require.NoError(t, err)
   186  
   187  	_, err = c.BeginBlockSync(ocabci.RequestBeginBlock{})
   188  	require.NoError(t, err)
   189  
   190  	_, err = c.EndBlockSync(types.RequestEndBlock{})
   191  	require.NoError(t, err)
   192  
   193  	_, err = c.BeginRecheckTxSync(ocabci.RequestBeginRecheckTx{})
   194  	require.NoError(t, err)
   195  
   196  	_, err = c.EndRecheckTxSync(ocabci.RequestEndRecheckTx{})
   197  	require.NoError(t, err)
   198  
   199  	_, err = c.ListSnapshotsSync(types.RequestListSnapshots{})
   200  	require.NoError(t, err)
   201  
   202  	_, err = c.OfferSnapshotSync(types.RequestOfferSnapshot{})
   203  	require.NoError(t, err)
   204  
   205  	_, err = c.LoadSnapshotChunkSync(types.RequestLoadSnapshotChunk{})
   206  	require.NoError(t, err)
   207  
   208  	_, err = c.ApplySnapshotChunkSync(types.RequestApplySnapshotChunk{})
   209  	require.NoError(t, err)
   210  }
   211  
   212  type sampleApp struct {
   213  	ocabci.BaseApplication
   214  }
   215  
   216  func newDoneChan(t *testing.T) chan struct{} {
   217  	result := make(chan struct{})
   218  	go func() {
   219  		select {
   220  		case <-time.After(time.Second):
   221  			require.Fail(t, "callback is not called for a second")
   222  		case <-result:
   223  			return
   224  		}
   225  	}()
   226  	return result
   227  }
   228  
   229  func getResponseCallback(t *testing.T) abcicli.ResponseCallback {
   230  	doneChan := newDoneChan(t)
   231  	return func(res *ocabci.Response) {
   232  		require.NotNil(t, res)
   233  		doneChan <- struct{}{}
   234  	}
   235  }