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.

151 lines
4.7 KiB

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