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.

155 lines
4.8 KiB

7 years ago
  1. package blockchain
  2. import (
  3. "testing"
  4. wire "github.com/tendermint/go-wire"
  5. cmn "github.com/tendermint/tmlibs/common"
  6. dbm "github.com/tendermint/tmlibs/db"
  7. "github.com/tendermint/tmlibs/log"
  8. cfg "github.com/tendermint/tendermint/config"
  9. "github.com/tendermint/tendermint/p2p"
  10. sm "github.com/tendermint/tendermint/state"
  11. "github.com/tendermint/tendermint/types"
  12. )
  13. func makeStateAndBlockStore(logger log.Logger) (sm.State, *BlockStore) {
  14. config := cfg.ResetTestRoot("blockchain_reactor_test")
  15. blockStore := NewBlockStore(dbm.NewMemDB())
  16. // Get State
  17. stateDB := dbm.NewMemDB()
  18. state, _ := sm.GetState(stateDB, config.GenesisFile())
  19. sm.SaveState(stateDB, state)
  20. return state, blockStore
  21. }
  22. func newBlockchainReactor(logger log.Logger, maxBlockHeight int64) *BlockchainReactor {
  23. state, blockStore := makeStateAndBlockStore(logger)
  24. // Make the blockchainReactor itself
  25. fastSync := true
  26. blockExec := sm.NewBlockExecutor(dbm.NewMemDB(), log.TestingLogger(),
  27. types.NopEventBus{}, nil, types.MockMempool{}, types.MockEvidencePool{})
  28. bcReactor := NewBlockchainReactor(state.Copy(), blockExec, blockStore, fastSync)
  29. bcReactor.SetLogger(logger.With("module", "blockchain"))
  30. // Next: we need to set a switch in order for peers to be added in
  31. bcReactor.Switch = p2p.NewSwitch(cfg.DefaultP2PConfig())
  32. // Lastly: let's add some blocks in
  33. for blockHeight := int64(1); blockHeight <= maxBlockHeight; blockHeight++ {
  34. firstBlock := makeBlock(blockHeight, state)
  35. secondBlock := makeBlock(blockHeight+1, state)
  36. firstParts := firstBlock.MakePartSet(state.ConsensusParams.BlockGossip.BlockPartSizeBytes)
  37. blockStore.SaveBlock(firstBlock, firstParts, secondBlock.LastCommit)
  38. }
  39. return bcReactor
  40. }
  41. func TestNoBlockMessageResponse(t *testing.T) {
  42. maxBlockHeight := int64(20)
  43. bcr := newBlockchainReactor(log.TestingLogger(), maxBlockHeight)
  44. bcr.Start()
  45. defer bcr.Stop()
  46. // Add some peers in
  47. peer := newbcrTestPeer(cmn.RandStr(12))
  48. bcr.AddPeer(peer)
  49. chID := byte(0x01)
  50. tests := []struct {
  51. height int64
  52. existent bool
  53. }{
  54. {maxBlockHeight + 2, false},
  55. {10, true},
  56. {1, true},
  57. {100, false},
  58. }
  59. // receive a request message from peer,
  60. // wait to hear response
  61. for _, tt := range tests {
  62. reqBlockMsg := &bcBlockRequestMessage{tt.height}
  63. reqBlockBytes := wire.BinaryBytes(struct{ BlockchainMessage }{reqBlockMsg})
  64. bcr.Receive(chID, peer, reqBlockBytes)
  65. value := peer.lastValue()
  66. msg := value.(struct{ BlockchainMessage }).BlockchainMessage
  67. if tt.existent {
  68. if blockMsg, ok := msg.(*bcBlockResponseMessage); !ok {
  69. t.Fatalf("Expected to receive a block response for height %d", tt.height)
  70. } else if blockMsg.Block.Height != tt.height {
  71. t.Fatalf("Expected response to be for height %d, got %d", tt.height, blockMsg.Block.Height)
  72. }
  73. } else {
  74. if noBlockMsg, ok := msg.(*bcNoBlockResponseMessage); !ok {
  75. t.Fatalf("Expected to receive a no block response for height %d", tt.height)
  76. } else if noBlockMsg.Height != tt.height {
  77. t.Fatalf("Expected response to be for height %d, got %d", tt.height, noBlockMsg.Height)
  78. }
  79. }
  80. }
  81. }
  82. //----------------------------------------------
  83. // utility funcs
  84. func makeTxs(height int64) (txs []types.Tx) {
  85. for i := 0; i < 10; i++ {
  86. txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
  87. }
  88. return txs
  89. }
  90. func makeBlock(height int64, state sm.State) *types.Block {
  91. block, _ := state.MakeBlock(height, makeTxs(height), new(types.Commit))
  92. return block
  93. }
  94. // The Test peer
  95. type bcrTestPeer struct {
  96. cmn.Service
  97. key string
  98. ch chan interface{}
  99. }
  100. var _ p2p.Peer = (*bcrTestPeer)(nil)
  101. func newbcrTestPeer(key string) *bcrTestPeer {
  102. return &bcrTestPeer{
  103. Service: cmn.NewBaseService(nil, "bcrTestPeer", nil),
  104. key: key,
  105. ch: make(chan interface{}, 2),
  106. }
  107. }
  108. func (tp *bcrTestPeer) lastValue() interface{} { return <-tp.ch }
  109. func (tp *bcrTestPeer) TrySend(chID byte, value interface{}) bool {
  110. if _, ok := value.(struct{ BlockchainMessage }).BlockchainMessage.(*bcStatusResponseMessage); ok {
  111. // Discard status response messages since they skew our results
  112. // We only want to deal with:
  113. // + bcBlockResponseMessage
  114. // + bcNoBlockResponseMessage
  115. } else {
  116. tp.ch <- value
  117. }
  118. return true
  119. }
  120. func (tp *bcrTestPeer) Send(chID byte, data interface{}) bool { return tp.TrySend(chID, data) }
  121. func (tp *bcrTestPeer) NodeInfo() *p2p.NodeInfo { return nil }
  122. func (tp *bcrTestPeer) Status() p2p.ConnectionStatus { return p2p.ConnectionStatus{} }
  123. func (tp *bcrTestPeer) Key() string { return tp.key }
  124. func (tp *bcrTestPeer) IsOutbound() bool { return false }
  125. func (tp *bcrTestPeer) IsPersistent() bool { return true }
  126. func (tp *bcrTestPeer) Get(s string) interface{} { return s }
  127. func (tp *bcrTestPeer) Set(string, interface{}) {}