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 }