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) } }