You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
2.9 KiB

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