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.

144 lines
3.2 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. t.Cleanup(func() {
  38. if err := s.Stop(); err != nil {
  39. t.Error(err)
  40. }
  41. })
  42. t.Cleanup(func() {
  43. if err := c.Stop(); err != nil {
  44. t.Error(err)
  45. }
  46. })
  47. resp := make(chan error, 1)
  48. go func() {
  49. // This is BeginBlockSync unrolled....
  50. reqres := c.BeginBlockAsync(types.RequestBeginBlock{})
  51. err := c.FlushSync()
  52. require.NoError(t, err)
  53. res := reqres.Response.GetBeginBlock()
  54. require.NotNil(t, res)
  55. resp <- c.Error()
  56. }()
  57. select {
  58. case <-time.After(time.Second):
  59. require.Fail(t, "No response arrived")
  60. case err, ok := <-resp:
  61. require.True(t, ok, "Must not close channel")
  62. assert.NoError(t, err, "This should return success")
  63. }
  64. }
  65. func TestHangingSyncCalls(t *testing.T) {
  66. app := slowApp{}
  67. s, c := setupClientServer(t, app)
  68. t.Cleanup(func() {
  69. if err := s.Stop(); err != nil {
  70. t.Log(err)
  71. }
  72. })
  73. t.Cleanup(func() {
  74. if err := c.Stop(); err != nil {
  75. t.Log(err)
  76. }
  77. })
  78. resp := make(chan error, 1)
  79. go func() {
  80. // Start BeginBlock and flush it
  81. reqres := c.BeginBlockAsync(types.RequestBeginBlock{})
  82. flush := c.FlushAsync()
  83. // wait 20 ms for all events to travel socket, but
  84. // no response yet from server
  85. time.Sleep(20 * time.Millisecond)
  86. // kill the server, so the connections break
  87. err := s.Stop()
  88. require.NoError(t, err)
  89. // wait for the response from BeginBlock
  90. reqres.Wait()
  91. flush.Wait()
  92. resp <- c.Error()
  93. }()
  94. select {
  95. case <-time.After(time.Second):
  96. require.Fail(t, "No response arrived")
  97. case err, ok := <-resp:
  98. require.True(t, ok, "Must not close channel")
  99. assert.Error(t, err, "We should get EOF error")
  100. }
  101. }
  102. func setupClientServer(t *testing.T, app types.Application) (
  103. service.Service, abcicli.Client) {
  104. // some port between 20k and 30k
  105. port := 20000 + tmrand.Int32()%10000
  106. addr := fmt.Sprintf("localhost:%d", port)
  107. s, err := server.NewServer(addr, "socket", app)
  108. require.NoError(t, err)
  109. err = s.Start()
  110. require.NoError(t, err)
  111. c := abcicli.NewSocketClient(addr, true)
  112. err = c.Start()
  113. require.NoError(t, err)
  114. return s, c
  115. }
  116. type slowApp struct {
  117. types.BaseApplication
  118. }
  119. func (slowApp) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
  120. time.Sleep(200 * time.Millisecond)
  121. return types.ResponseBeginBlock{}
  122. }