package abcicli_test import ( "context" "fmt" "testing" "time" "math/rand" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abcicli "github.com/tendermint/tendermint/abci/client" "github.com/tendermint/tendermint/abci/server" "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/service" ) var ctx = context.Background() func TestProperSyncCalls(t *testing.T) { app := slowApp{} s, c := setupClientServer(t, app) t.Cleanup(func() { if err := s.Stop(); err != nil { t.Error(err) } }) t.Cleanup(func() { if err := c.Stop(); err != nil { t.Error(err) } }) resp := make(chan error, 1) go func() { // This is BeginBlockSync unrolled.... reqres, err := c.BeginBlockAsync(ctx, types.RequestBeginBlock{}) assert.NoError(t, err) err = c.FlushSync(context.Background()) assert.NoError(t, err) res := reqres.Response.GetBeginBlock() assert.NotNil(t, res) resp <- c.Error() }() select { case <-time.After(time.Second): require.Fail(t, "No response arrived") case err, ok := <-resp: require.True(t, ok, "Must not close channel") assert.NoError(t, err, "This should return success") } } func TestHangingSyncCalls(t *testing.T) { app := slowApp{} s, c := setupClientServer(t, app) t.Cleanup(func() { if err := s.Stop(); err != nil { t.Log(err) } }) t.Cleanup(func() { if err := c.Stop(); err != nil { t.Log(err) } }) resp := make(chan error, 1) go func() { // Start BeginBlock and flush it reqres, err := c.BeginBlockAsync(ctx, types.RequestBeginBlock{}) assert.NoError(t, err) flush, err := c.FlushAsync(ctx) assert.NoError(t, err) // wait 20 ms for all events to travel socket, but // no response yet from server time.Sleep(20 * time.Millisecond) // kill the server, so the connections break err = s.Stop() assert.NoError(t, err) // wait for the response from BeginBlock reqres.Wait() flush.Wait() resp <- c.Error() }() select { case <-time.After(time.Second): require.Fail(t, "No response arrived") case err, ok := <-resp: require.True(t, ok, "Must not close channel") assert.Error(t, err, "We should get EOF error") } } func setupClientServer(t *testing.T, app types.Application) ( service.Service, abcicli.Client) { // some port between 20k and 30k port := 20000 + rand.Int31()%10000 addr := fmt.Sprintf("localhost:%d", port) s, err := server.NewServer(addr, "socket", app) require.NoError(t, err) err = s.Start() require.NoError(t, err) c := abcicli.NewSocketClient(addr, true) err = c.Start() require.NoError(t, err) return s, c } type slowApp struct { types.BaseApplication } func (slowApp) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { time.Sleep(200 * time.Millisecond) return types.ResponseBeginBlock{} }