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.

148 lines
5.6 KiB

  1. package statesync
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/stretchr/testify/assert"
  6. "github.com/stretchr/testify/mock"
  7. "github.com/stretchr/testify/require"
  8. abci "github.com/tendermint/tendermint/abci/types"
  9. "github.com/tendermint/tendermint/p2p"
  10. p2pmocks "github.com/tendermint/tendermint/p2p/mocks"
  11. proxymocks "github.com/tendermint/tendermint/proxy/mocks"
  12. )
  13. func TestReactor_Receive_ChunkRequestMessage(t *testing.T) {
  14. testcases := map[string]struct {
  15. request *chunkRequestMessage
  16. chunk []byte
  17. expectResponse *chunkResponseMessage
  18. }{
  19. "chunk is returned": {
  20. &chunkRequestMessage{Height: 1, Format: 1, Index: 1},
  21. []byte{1, 2, 3},
  22. &chunkResponseMessage{Height: 1, Format: 1, Index: 1, Chunk: []byte{1, 2, 3}}},
  23. "empty chunk is returned, as nil": {
  24. &chunkRequestMessage{Height: 1, Format: 1, Index: 1},
  25. []byte{},
  26. &chunkResponseMessage{Height: 1, Format: 1, Index: 1, Chunk: nil}},
  27. "nil (missing) chunk is returned as missing": {
  28. &chunkRequestMessage{Height: 1, Format: 1, Index: 1},
  29. nil,
  30. &chunkResponseMessage{Height: 1, Format: 1, Index: 1, Missing: true},
  31. },
  32. }
  33. for name, tc := range testcases {
  34. tc := tc
  35. t.Run(name, func(t *testing.T) {
  36. // Mock ABCI connection to return local snapshots
  37. conn := &proxymocks.AppConnSnapshot{}
  38. conn.On("LoadSnapshotChunkSync", abci.RequestLoadSnapshotChunk{
  39. Height: tc.request.Height,
  40. Format: tc.request.Format,
  41. Chunk: tc.request.Index,
  42. }).Return(&abci.ResponseLoadSnapshotChunk{Chunk: tc.chunk}, nil)
  43. // Mock peer to store response, if found
  44. peer := &p2pmocks.Peer{}
  45. peer.On("ID").Return(p2p.ID("id"))
  46. var response *chunkResponseMessage
  47. if tc.expectResponse != nil {
  48. peer.On("Send", ChunkChannel, mock.Anything).Run(func(args mock.Arguments) {
  49. msg, err := decodeMsg(args[1].([]byte))
  50. require.NoError(t, err)
  51. response = msg.(*chunkResponseMessage)
  52. }).Return(true)
  53. }
  54. // Start a reactor and send a chunkRequestMessage, then wait for and check response
  55. r := NewReactor(conn, nil, "")
  56. err := r.Start()
  57. require.NoError(t, err)
  58. defer r.Stop()
  59. r.Receive(ChunkChannel, peer, cdc.MustMarshalBinaryBare(tc.request))
  60. time.Sleep(100 * time.Millisecond)
  61. assert.Equal(t, tc.expectResponse, response)
  62. conn.AssertExpectations(t)
  63. peer.AssertExpectations(t)
  64. })
  65. }
  66. }
  67. func TestReactor_Receive_SnapshotRequestMessage(t *testing.T) {
  68. testcases := map[string]struct {
  69. snapshots []*abci.Snapshot
  70. expectResponses []*snapshotsResponseMessage
  71. }{
  72. "no snapshots": {nil, []*snapshotsResponseMessage{}},
  73. ">10 unordered snapshots": {
  74. []*abci.Snapshot{
  75. {Height: 1, Format: 2, Chunks: 7, Hash: []byte{1, 2}, Metadata: []byte{1}},
  76. {Height: 2, Format: 2, Chunks: 7, Hash: []byte{2, 2}, Metadata: []byte{2}},
  77. {Height: 3, Format: 2, Chunks: 7, Hash: []byte{3, 2}, Metadata: []byte{3}},
  78. {Height: 1, Format: 1, Chunks: 7, Hash: []byte{1, 1}, Metadata: []byte{4}},
  79. {Height: 2, Format: 1, Chunks: 7, Hash: []byte{2, 1}, Metadata: []byte{5}},
  80. {Height: 3, Format: 1, Chunks: 7, Hash: []byte{3, 1}, Metadata: []byte{6}},
  81. {Height: 1, Format: 4, Chunks: 7, Hash: []byte{1, 4}, Metadata: []byte{7}},
  82. {Height: 2, Format: 4, Chunks: 7, Hash: []byte{2, 4}, Metadata: []byte{8}},
  83. {Height: 3, Format: 4, Chunks: 7, Hash: []byte{3, 4}, Metadata: []byte{9}},
  84. {Height: 1, Format: 3, Chunks: 7, Hash: []byte{1, 3}, Metadata: []byte{10}},
  85. {Height: 2, Format: 3, Chunks: 7, Hash: []byte{2, 3}, Metadata: []byte{11}},
  86. {Height: 3, Format: 3, Chunks: 7, Hash: []byte{3, 3}, Metadata: []byte{12}},
  87. },
  88. []*snapshotsResponseMessage{
  89. {Height: 3, Format: 4, Chunks: 7, Hash: []byte{3, 4}, Metadata: []byte{9}},
  90. {Height: 3, Format: 3, Chunks: 7, Hash: []byte{3, 3}, Metadata: []byte{12}},
  91. {Height: 3, Format: 2, Chunks: 7, Hash: []byte{3, 2}, Metadata: []byte{3}},
  92. {Height: 3, Format: 1, Chunks: 7, Hash: []byte{3, 1}, Metadata: []byte{6}},
  93. {Height: 2, Format: 4, Chunks: 7, Hash: []byte{2, 4}, Metadata: []byte{8}},
  94. {Height: 2, Format: 3, Chunks: 7, Hash: []byte{2, 3}, Metadata: []byte{11}},
  95. {Height: 2, Format: 2, Chunks: 7, Hash: []byte{2, 2}, Metadata: []byte{2}},
  96. {Height: 2, Format: 1, Chunks: 7, Hash: []byte{2, 1}, Metadata: []byte{5}},
  97. {Height: 1, Format: 4, Chunks: 7, Hash: []byte{1, 4}, Metadata: []byte{7}},
  98. {Height: 1, Format: 3, Chunks: 7, Hash: []byte{1, 3}, Metadata: []byte{10}},
  99. },
  100. },
  101. }
  102. for name, tc := range testcases {
  103. tc := tc
  104. t.Run(name, func(t *testing.T) {
  105. // Mock ABCI connection to return local snapshots
  106. conn := &proxymocks.AppConnSnapshot{}
  107. conn.On("ListSnapshotsSync", abci.RequestListSnapshots{}).Return(&abci.ResponseListSnapshots{
  108. Snapshots: tc.snapshots,
  109. }, nil)
  110. // Mock peer to catch responses and store them in a slice
  111. responses := []*snapshotsResponseMessage{}
  112. peer := &p2pmocks.Peer{}
  113. if len(tc.expectResponses) > 0 {
  114. peer.On("ID").Return(p2p.ID("id"))
  115. peer.On("Send", SnapshotChannel, mock.Anything).Run(func(args mock.Arguments) {
  116. msg, err := decodeMsg(args[1].([]byte))
  117. require.NoError(t, err)
  118. responses = append(responses, msg.(*snapshotsResponseMessage))
  119. }).Return(true)
  120. }
  121. // Start a reactor and send a SnapshotsRequestMessage, then wait for and check responses
  122. r := NewReactor(conn, nil, "")
  123. err := r.Start()
  124. require.NoError(t, err)
  125. defer r.Stop()
  126. r.Receive(SnapshotChannel, peer, cdc.MustMarshalBinaryBare(&snapshotsRequestMessage{}))
  127. time.Sleep(100 * time.Millisecond)
  128. assert.Equal(t, tc.expectResponses, responses)
  129. conn.AssertExpectations(t)
  130. peer.AssertExpectations(t)
  131. })
  132. }
  133. }