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.

187 lines
4.8 KiB

6 years ago
fix non deterministic test failures and race in privval socket (#3258) * node: decrease retry conn timeout in test Should fix #3256 The retry timeout was set to the default, which is the same as the accept timeout, so it's no wonder this would fail. Here we decrease the retry timeout so we can try many times before the accept timeout. * p2p: increase handshake timeout in test This fails sometimes, presumably because the handshake timeout is so low (only 50ms). So increase it to 1s. Should fix #3187 * privval: fix race with ping. closes #3237 Pings happen in a go-routine and can happen concurrently with other messages. Since we use a request/response protocol, we expect to send a request and get back the corresponding response. But with pings happening concurrently, this assumption could be violated. We were using a mutex, but only a RWMutex, where the RLock was being held for sending messages - this was to allow the underlying connection to be replaced if it fails. Turns out we actually need to use a full lock (not just a read lock) to prevent multiple requests from happening concurrently. * node: fix test name. DelayedStop -> DelayedStart * autofile: Wait() method In the TestWALTruncate in consensus/wal_test.go we remove the WAL directory at the end of the test. However the wal.Stop() does not properly wait for the autofile group to finish shutting down. Hence it was possible that the group's go-routine is still running when the cleanup happens, which causes a panic since the directory disappeared. Here we add a Wait() method to properly wait until the go-routine exits so we can safely clean up. This fixes #2852.
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. package consensus
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "path/filepath"
  9. // "sync"
  10. "testing"
  11. "time"
  12. "github.com/tendermint/tendermint/consensus/types"
  13. "github.com/tendermint/tendermint/libs/autofile"
  14. "github.com/tendermint/tendermint/libs/log"
  15. tmtypes "github.com/tendermint/tendermint/types"
  16. tmtime "github.com/tendermint/tendermint/types/time"
  17. "github.com/stretchr/testify/assert"
  18. "github.com/stretchr/testify/require"
  19. )
  20. func TestWALTruncate(t *testing.T) {
  21. walDir, err := ioutil.TempDir("", "wal")
  22. require.NoError(t, err)
  23. defer os.RemoveAll(walDir)
  24. walFile := filepath.Join(walDir, "wal")
  25. //this magic number 4K can truncate the content when RotateFile. defaultHeadSizeLimit(10M) is hard to simulate.
  26. //this magic number 1 * time.Millisecond make RotateFile check frequently. defaultGroupCheckDuration(5s) is hard to simulate.
  27. wal, err := NewWAL(walFile,
  28. autofile.GroupHeadSizeLimit(4096),
  29. autofile.GroupCheckDuration(1*time.Millisecond),
  30. )
  31. require.NoError(t, err)
  32. wal.SetLogger(log.TestingLogger())
  33. err = wal.Start()
  34. require.NoError(t, err)
  35. defer func() {
  36. wal.Stop()
  37. // wait for the wal to finish shutting down so we
  38. // can safely remove the directory
  39. wal.Wait()
  40. }()
  41. //60 block's size nearly 70K, greater than group's headBuf size(4096 * 10), when headBuf is full, truncate content will Flush to the file.
  42. //at this time, RotateFile is called, truncate content exist in each file.
  43. err = WALGenerateNBlocks(wal.Group(), 60)
  44. require.NoError(t, err)
  45. time.Sleep(1 * time.Millisecond) //wait groupCheckDuration, make sure RotateFile run
  46. wal.Group().Flush()
  47. h := int64(50)
  48. gr, found, err := wal.SearchForEndHeight(h, &WALSearchOptions{})
  49. assert.NoError(t, err, fmt.Sprintf("expected not to err on height %d", h))
  50. assert.True(t, found, fmt.Sprintf("expected to find end height for %d", h))
  51. assert.NotNil(t, gr, "expected group not to be nil")
  52. defer gr.Close()
  53. dec := NewWALDecoder(gr)
  54. msg, err := dec.Decode()
  55. assert.NoError(t, err, "expected to decode a message")
  56. rs, ok := msg.Msg.(tmtypes.EventDataRoundState)
  57. assert.True(t, ok, "expected message of type EventDataRoundState")
  58. assert.Equal(t, rs.Height, h+1, fmt.Sprintf("wrong height"))
  59. }
  60. func TestWALEncoderDecoder(t *testing.T) {
  61. now := tmtime.Now()
  62. msgs := []TimedWALMessage{
  63. {Time: now, Msg: EndHeightMessage{0}},
  64. {Time: now, Msg: timeoutInfo{Duration: time.Second, Height: 1, Round: 1, Step: types.RoundStepPropose}},
  65. }
  66. b := new(bytes.Buffer)
  67. for _, msg := range msgs {
  68. b.Reset()
  69. enc := NewWALEncoder(b)
  70. err := enc.Encode(&msg)
  71. require.NoError(t, err)
  72. dec := NewWALDecoder(b)
  73. decoded, err := dec.Decode()
  74. require.NoError(t, err)
  75. assert.Equal(t, msg.Time.UTC(), decoded.Time)
  76. assert.Equal(t, msg.Msg, decoded.Msg)
  77. }
  78. }
  79. func TestWALSearchForEndHeight(t *testing.T) {
  80. walBody, err := WALWithNBlocks(6)
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. walFile := tempWALWithData(walBody)
  85. wal, err := NewWAL(walFile)
  86. require.NoError(t, err)
  87. wal.SetLogger(log.TestingLogger())
  88. h := int64(3)
  89. gr, found, err := wal.SearchForEndHeight(h, &WALSearchOptions{})
  90. assert.NoError(t, err, fmt.Sprintf("expected not to err on height %d", h))
  91. assert.True(t, found, fmt.Sprintf("expected to find end height for %d", h))
  92. assert.NotNil(t, gr, "expected group not to be nil")
  93. defer gr.Close()
  94. dec := NewWALDecoder(gr)
  95. msg, err := dec.Decode()
  96. assert.NoError(t, err, "expected to decode a message")
  97. rs, ok := msg.Msg.(tmtypes.EventDataRoundState)
  98. assert.True(t, ok, "expected message of type EventDataRoundState")
  99. assert.Equal(t, rs.Height, h+1, fmt.Sprintf("wrong height"))
  100. }
  101. /*
  102. var initOnce sync.Once
  103. func registerInterfacesOnce() {
  104. initOnce.Do(func() {
  105. var _ = wire.RegisterInterface(
  106. struct{ WALMessage }{},
  107. wire.ConcreteType{[]byte{}, 0x10},
  108. )
  109. })
  110. }
  111. */
  112. func nBytes(n int) []byte {
  113. buf := make([]byte, n)
  114. n, _ = rand.Read(buf)
  115. return buf[:n]
  116. }
  117. func benchmarkWalDecode(b *testing.B, n int) {
  118. // registerInterfacesOnce()
  119. buf := new(bytes.Buffer)
  120. enc := NewWALEncoder(buf)
  121. data := nBytes(n)
  122. enc.Encode(&TimedWALMessage{Msg: data, Time: time.Now().Round(time.Second).UTC()})
  123. encoded := buf.Bytes()
  124. b.ResetTimer()
  125. for i := 0; i < b.N; i++ {
  126. buf.Reset()
  127. buf.Write(encoded)
  128. dec := NewWALDecoder(buf)
  129. if _, err := dec.Decode(); err != nil {
  130. b.Fatal(err)
  131. }
  132. }
  133. b.ReportAllocs()
  134. }
  135. func BenchmarkWalDecode512B(b *testing.B) {
  136. benchmarkWalDecode(b, 512)
  137. }
  138. func BenchmarkWalDecode10KB(b *testing.B) {
  139. benchmarkWalDecode(b, 10*1024)
  140. }
  141. func BenchmarkWalDecode100KB(b *testing.B) {
  142. benchmarkWalDecode(b, 100*1024)
  143. }
  144. func BenchmarkWalDecode1MB(b *testing.B) {
  145. benchmarkWalDecode(b, 1024*1024)
  146. }
  147. func BenchmarkWalDecode10MB(b *testing.B) {
  148. benchmarkWalDecode(b, 10*1024*1024)
  149. }
  150. func BenchmarkWalDecode100MB(b *testing.B) {
  151. benchmarkWalDecode(b, 100*1024*1024)
  152. }
  153. func BenchmarkWalDecode1GB(b *testing.B) {
  154. benchmarkWalDecode(b, 1024*1024*1024)
  155. }