--- /dev/null
+package consensusmgr
+
+import (
+ "math/rand"
+ "net"
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/tendermint/tmlibs/flowrate"
+
+ "github.com/vapor/consensus"
+ "github.com/vapor/event"
+ "github.com/vapor/netsync/peers"
+ "github.com/vapor/p2p"
+ "github.com/vapor/protocol/bc"
+ "github.com/vapor/protocol/bc/types"
+)
+
+type p2peer struct {
+}
+
+func (p *p2peer) Addr() net.Addr {
+ return nil
+}
+
+func (p *p2peer) ID() string {
+ return ""
+}
+
+func (p *p2peer) RemoteAddrHost() string {
+ return ""
+}
+func (p *p2peer) ServiceFlag() consensus.ServiceFlag {
+ return 0
+}
+func (p *p2peer) TrafficStatus() (*flowrate.Status, *flowrate.Status) {
+ return nil, nil
+}
+func (p *p2peer) TrySend(byte, interface{}) bool {
+ return true
+}
+func (p *p2peer) IsLAN() bool {
+ return false
+}
+
+func mockBlocks(startBlock *types.Block, height uint64) []*types.Block {
+ blocks := []*types.Block{}
+ indexBlock := &types.Block{}
+ if startBlock == nil {
+ indexBlock = &types.Block{BlockHeader: types.BlockHeader{Version: uint64(rand.Uint32())}}
+ blocks = append(blocks, indexBlock)
+ } else {
+ indexBlock = startBlock
+ }
+
+ for indexBlock.Height < height {
+ block := &types.Block{
+ BlockHeader: types.BlockHeader{
+ Height: indexBlock.Height + 1,
+ PreviousBlockHash: indexBlock.Hash(),
+ Version: uint64(rand.Uint32()),
+ },
+ }
+ blocks = append(blocks, block)
+ indexBlock = block
+ }
+ return blocks
+}
+
+type mockSW struct {
+}
+
+func (s *mockSW) AddReactor(name string, reactor p2p.Reactor) p2p.Reactor {
+ return nil
+}
+
+type mockChain struct {
+}
+
+func (c *mockChain) BestBlockHeight() uint64 {
+ return 0
+}
+
+func (c *mockChain) GetHeaderByHash(*bc.Hash) (*types.BlockHeader, error) {
+ return nil, nil
+}
+
+func (c *mockChain) ProcessBlock(*types.Block) (bool, error) {
+ return false, nil
+}
+
+func (c *mockChain) ProcessBlockSignature(signature, pubkey []byte, blockHash *bc.Hash) error {
+ return nil
+}
+
+type mockPeers struct {
+ msgCount *int
+ knownBlock *bc.Hash
+ blockHeight *uint64
+ knownSignature *[]byte
+}
+
+func newMockPeers(msgCount *int, knownBlock *bc.Hash, blockHeight *uint64, signature *[]byte) *mockPeers {
+ return &mockPeers{
+ msgCount: msgCount,
+ knownBlock: knownBlock,
+ blockHeight: blockHeight,
+ knownSignature: signature,
+ }
+}
+
+func (ps *mockPeers) AddPeer(peer peers.BasePeer) {
+
+}
+
+func (ps *mockPeers) BroadcastMsg(bm peers.BroadcastMsg) error {
+ *ps.msgCount++
+ return nil
+}
+func (ps *mockPeers) GetPeer(id string) *peers.Peer {
+ return &peers.Peer{BasePeer: &p2peer{}}
+}
+func (ps *mockPeers) MarkBlock(peerID string, hash *bc.Hash) {
+ *ps.knownBlock = *hash
+}
+
+func (ps *mockPeers) MarkBlockSignature(peerID string, signature []byte) {
+ *ps.knownSignature = append(*ps.knownSignature, signature...)
+}
+
+func (ps *mockPeers) ProcessIllegal(peerID string, level byte, reason string) {
+
+}
+func (p *mockPeers) RemovePeer(peerID string) {
+
+}
+func (ps *mockPeers) SetStatus(peerID string, height uint64, hash *bc.Hash) {
+ *ps.blockHeight = height
+}
+
+func TestBlockProposeMsgBroadcastLoop(t *testing.T) {
+ dispatcher := event.NewDispatcher()
+ msgCount := 0
+ blockHeight := 100
+ mgr := NewManager(&mockSW{}, &mockChain{}, newMockPeers(&msgCount, nil, nil, nil), dispatcher)
+ blocks := mockBlocks(nil, uint64(blockHeight))
+
+ mgr.Start()
+ defer mgr.Stop()
+ time.Sleep(10 * time.Millisecond)
+ for _, block := range blocks {
+ mgr.eventDispatcher.Post(event.NewProposedBlockEvent{Block: *block})
+ }
+ time.Sleep(10 * time.Millisecond)
+ if msgCount != blockHeight+1 {
+ t.Fatalf("broad propose block msg err. got:%d\n want:%d", msgCount, blockHeight+1)
+ }
+}
+
+func TestBlockSignatureMsgBroadcastLoop(t *testing.T) {
+ dispatcher := event.NewDispatcher()
+ msgCount := 0
+ blockHeight := 100
+ mgr := NewManager(&mockSW{}, &mockChain{}, newMockPeers(&msgCount, nil, nil, nil), dispatcher)
+ blocks := mockBlocks(nil, uint64(blockHeight))
+
+ mgr.Start()
+ defer mgr.Stop()
+ time.Sleep(10 * time.Millisecond)
+ for _, block := range blocks {
+ mgr.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: block.Hash(), Signature: []byte{0x1, 0x2}, XPub: []byte{0x011, 0x022}})
+ }
+ time.Sleep(10 * time.Millisecond)
+ if msgCount != blockHeight+1 {
+ t.Fatalf("broad propose block msg err. got:%d\n want:%d", msgCount, blockHeight+1)
+ }
+}
+
+func TestProcessBlockProposeMsg(t *testing.T) {
+ dispatcher := event.NewDispatcher()
+ msgCount := 0
+ var knownBlock bc.Hash
+ blockHeight := uint64(0)
+ peerID := "Peer1"
+ mgr := NewManager(&mockSW{}, &mockChain{}, newMockPeers(&msgCount, &knownBlock, &blockHeight, nil), dispatcher)
+ block := &types.Block{
+ BlockHeader: types.BlockHeader{
+ Height: 100,
+ PreviousBlockHash: bc.NewHash([32]byte{0x1}),
+ Version: uint64(rand.Uint32()),
+ },
+ }
+ msg, err := NewBlockProposeMsg(block)
+ if err != nil {
+ t.Fatal("create new block propose msg err", err)
+ }
+
+ mgr.processMsg(peerID, 0, msg)
+ if knownBlock != block.Hash() {
+ t.Fatalf("mark propose block msg err. got:%d\n want:%d", knownBlock, block.Hash())
+ }
+
+ if blockHeight != block.Height {
+ t.Fatalf("set peer status err. got:%d\n want:%d", blockHeight, block.Height)
+ }
+}
+
+func TestProcessBlockSignatureMsg(t *testing.T) {
+ dispatcher := event.NewDispatcher()
+ msgCount := 0
+ knownSignature := []byte{}
+ peerID := "Peer1"
+ mgr := NewManager(&mockSW{}, &mockChain{}, newMockPeers(&msgCount, nil, nil, &knownSignature), dispatcher)
+ block := &types.Block{
+ BlockHeader: types.BlockHeader{
+ Height: 100,
+ PreviousBlockHash: bc.NewHash([32]byte{0x1}),
+ Version: uint64(rand.Uint32()),
+ },
+ }
+
+ signature := []byte{0x01, 0x02}
+ msg := NewBlockSignatureMsg(block.Hash(), signature, []byte{0x03, 0x04})
+
+ mgr.processMsg(peerID, 0, msg)
+
+ if !reflect.DeepEqual(knownSignature, signature) {
+ t.Fatalf("set peer status err. got:%d\n want:%d", knownSignature, signature)
+ }
+}