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.

158 lines
4.9 KiB

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