dbm "github.com/vapor/database/leveldb"
"github.com/vapor/errors"
msgs "github.com/vapor/netsync/messages"
+ "github.com/vapor/netsync/peers"
+ "github.com/vapor/protocol"
"github.com/vapor/protocol/bc"
"github.com/vapor/protocol/bc/types"
"github.com/vapor/test/mock"
"github.com/vapor/testutil"
)
+func TestCheckSyncType(t *testing.T) {
+ tmp, err := ioutil.TempDir(".", "")
+ if err != nil {
+ t.Fatalf("failed to create temporary data folder: %v", err)
+ }
+ fastSyncDB := dbm.NewDB("testdb", "leveldb", tmp)
+ defer func() {
+ fastSyncDB.Close()
+ os.RemoveAll(tmp)
+ }()
+
+ blocks := mockBlocks(nil, 50)
+ chain := mock.NewChain(nil)
+ chain.SetBestBlockHeader(&blocks[len(blocks)-1].BlockHeader)
+ for _, block := range blocks {
+ chain.SetBlockByHeight(block.Height, block)
+ }
+
+ type syncPeer struct {
+ peer *P2PPeer
+ bestHeight uint64
+ irreversibleHeight uint64
+ }
+
+ cases := []struct {
+ peers []*syncPeer
+ syncType int
+ }{
+ {
+ peers: []*syncPeer{},
+ syncType: noNeedSync,
+ },
+ {
+ peers: []*syncPeer{
+ {peer: &P2PPeer{id: "peer1", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 1000, irreversibleHeight: 500},
+ {peer: &P2PPeer{id: "peer2", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 50, irreversibleHeight: 50},
+ },
+ syncType: fastSyncType,
+ },
+ {
+ peers: []*syncPeer{
+ {peer: &P2PPeer{id: "peer1", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 1000, irreversibleHeight: 100},
+ {peer: &P2PPeer{id: "peer2", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 500, irreversibleHeight: 50},
+ },
+ syncType: regularSyncType,
+ },
+ {
+ peers: []*syncPeer{
+ {peer: &P2PPeer{id: "peer1", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 51, irreversibleHeight: 50},
+ },
+ syncType: regularSyncType,
+ },
+ {
+ peers: []*syncPeer{
+ {peer: &P2PPeer{id: "peer1", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 30, irreversibleHeight: 30},
+ },
+ syncType: noNeedSync,
+ },
+ {
+ peers: []*syncPeer{
+ {peer: &P2PPeer{id: "peer1", flag: consensus.SFFullNode}, bestHeight: 1000, irreversibleHeight: 1000},
+ },
+ syncType: regularSyncType,
+ },
+ {
+ peers: []*syncPeer{
+ {peer: &P2PPeer{id: "peer1", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 1000, irreversibleHeight: 50},
+ {peer: &P2PPeer{id: "peer2", flag: consensus.SFFullNode | consensus.SFFastSync}, bestHeight: 800, irreversibleHeight: 800},
+ },
+ syncType: fastSyncType,
+ },
+ }
+
+ for i, c := range cases {
+ peers := peers.NewPeerSet(NewPeerSet())
+ blockKeeper := newBlockKeeper(chain, peers, fastSyncDB)
+ for _, syncPeer := range c.peers {
+ blockKeeper.peers.AddPeer(syncPeer.peer)
+ blockKeeper.peers.SetStatus(syncPeer.peer.id, syncPeer.bestHeight, nil)
+ blockKeeper.peers.SetIrreversibleStatus(syncPeer.peer.id, syncPeer.irreversibleHeight, nil)
+ }
+ gotType := blockKeeper.checkSyncType()
+ if c.syncType != gotType {
+ t.Errorf("case %d: got %d want %d", i, gotType, c.syncType)
+ }
+ }
+}
+
func TestRegularBlockSync(t *testing.T) {
baseChain := mockBlocks(nil, 50)
chainX := append(baseChain, mockBlocks(baseChain[50], 60)...)
chainY := append(baseChain, mockBlocks(baseChain[50], 70)...)
chainZ := append(baseChain, mockBlocks(baseChain[50], 200)...)
+ chainE := append(baseChain, mockErrorBlocks(baseChain[50], 200, 60)...)
cases := []struct {
syncTimeout time.Duration
syncTimeout: 30 * time.Second,
aBlocks: chainX[:52],
bBlocks: chainZ,
- want: chainZ[:201],
+ want: chainZ[:180],
err: nil,
},
+ {
+ syncTimeout: 0 * time.Second,
+ aBlocks: chainX[:52],
+ bBlocks: chainZ,
+ want: chainX[:52],
+ err: errRequestTimeout,
+ },
+ {
+ syncTimeout: 30 * time.Second,
+ aBlocks: chainX[:52],
+ bBlocks: chainE,
+ want: chainE[:60],
+ err: protocol.ErrBadStateRoot,
+ },
}
tmp, err := ioutil.TempDir(".", "")
if err != nil {
go A2B.postMan()
}
+ requireBlockTimeout = c.syncTimeout
a.blockKeeper.syncPeer = a.peers.GetPeer("test node B")
if err := a.blockKeeper.regularBlockSync(); errors.Root(err) != c.err {
t.Errorf("case %d: got %v want %v", i, err, c.err)
locator []uint64
stopHash bc.Hash
wantHeight []uint64
+ wantErr error
}{
{
locator: []uint64{20},
stopHash: blocks[100].Hash(),
wantHeight: []uint64{20, 21, 22, 23, 24},
+ wantErr: nil,
+ },
+ {
+ locator: []uint64{20},
+ stopHash: bc.NewHash([32]byte{0x01, 0x02}),
+ wantHeight: []uint64{},
+ wantErr: mock.ErrFoundHeaderByHash,
},
}
want = append(want, blocks[i])
}
- got, _ := bk.locateBlocks(locator, &c.stopHash)
+ got, err := bk.locateBlocks(locator, &c.stopHash)
+ if err != c.wantErr {
+ t.Errorf("case %d: got %v want err = %v", i, err, c.wantErr)
+ }
+
if !testutil.DeepEqual(got, want) {
t.Errorf("case %d: got %v want %v", i, got, want)
}
stopHash *bc.Hash
skip uint64
wantHeight []uint64
- err bool
+ err error
}{
{
chainHeight: 100,
stopHash: &blocksHash[100],
skip: 0,
wantHeight: []uint64{90, 91, 92, 93, 94, 95, 96, 97, 98, 99},
- err: false,
+ err: nil,
},
{
chainHeight: 100,
stopHash: &blocksHash[24],
skip: 0,
wantHeight: []uint64{20, 21, 22, 23, 24},
- err: false,
+ err: nil,
},
{
chainHeight: 100,
locator: []uint64{20},
stopHash: &blocksHash[20],
wantHeight: []uint64{20},
- err: false,
+ err: nil,
},
{
chainHeight: 100,
locator: []uint64{20},
stopHash: &blocksHash[120],
wantHeight: []uint64{},
- err: false,
+ err: mock.ErrFoundHeaderByHash,
},
{
chainHeight: 100,
locator: []uint64{120, 70},
stopHash: &blocksHash[78],
wantHeight: []uint64{70, 71, 72, 73, 74, 75, 76, 77, 78},
- err: false,
+ err: nil,
},
{
chainHeight: 100,
stopHash: &blocksHash[10],
skip: 10,
wantHeight: []uint64{},
- err: false,
+ err: nil,
},
{
chainHeight: 100,
stopHash: &blocksHash[80],
skip: 10,
wantHeight: []uint64{15, 26, 37, 48, 59, 70, 80},
- err: false,
+ err: nil,
},
{
chainHeight: 100,
stopHash: &blocksHash[100],
skip: 9,
wantHeight: []uint64{0, 10, 20, 30, 40, 50, 60, 70, 80, 90},
- err: false,
+ err: nil,
},
}
}
got, err := bk.locateHeaders(locator, c.stopHash, c.skip, maxNumOfHeadersPerMsg)
- if err != nil != c.err {
+ if err != c.err {
t.Errorf("case %d: got %v want err = %v", i, err, c.err)
}
if !testutil.DeepEqual(got, want) {