OSDN Git Service

ffacb56af3aa4cb7ce3ff3ac136f0bd3e0ef66c7
[bytom/vapor.git] / netsync / chainmgr / fast_sync_test.go
1 package chainmgr
2
3 import (
4         "io/ioutil"
5         "os"
6         "testing"
7         "time"
8
9         "github.com/vapor/consensus"
10         dbm "github.com/vapor/database/leveldb"
11         "github.com/vapor/errors"
12         "github.com/vapor/protocol/bc"
13         "github.com/vapor/protocol/bc/types"
14         "github.com/vapor/test/mock"
15         "github.com/vapor/testutil"
16 )
17
18 func TestBlockLocator(t *testing.T) {
19         blocks := mockBlocks(nil, 500)
20         cases := []struct {
21                 bestHeight uint64
22                 wantHeight []uint64
23         }{
24                 {
25                         bestHeight: 0,
26                         wantHeight: []uint64{0},
27                 },
28                 {
29                         bestHeight: 1,
30                         wantHeight: []uint64{1, 0},
31                 },
32                 {
33                         bestHeight: 7,
34                         wantHeight: []uint64{7, 6, 5, 4, 3, 2, 1, 0},
35                 },
36                 {
37                         bestHeight: 10,
38                         wantHeight: []uint64{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
39                 },
40                 {
41                         bestHeight: 100,
42                         wantHeight: []uint64{100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 89, 85, 77, 61, 29, 0},
43                 },
44                 {
45                         bestHeight: 500,
46                         wantHeight: []uint64{500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 489, 485, 477, 461, 429, 365, 237, 0},
47                 },
48         }
49
50         for i, c := range cases {
51                 mockChain := mock.NewChain(nil)
52                 fs := &fastSync{chain: mockChain}
53                 mockChain.SetBestBlockHeader(&blocks[c.bestHeight].BlockHeader)
54                 for i := uint64(0); i <= c.bestHeight; i++ {
55                         mockChain.SetBlockByHeight(i, blocks[i])
56                 }
57
58                 want := []*bc.Hash{}
59                 for _, i := range c.wantHeight {
60                         hash := blocks[i].Hash()
61                         want = append(want, &hash)
62                 }
63
64                 if got := fs.blockLocator(); !testutil.DeepEqual(got, want) {
65                         t.Errorf("case %d: got %v want %v", i, got, want)
66                 }
67         }
68 }
69
70 func TestFastBlockSync(t *testing.T) {
71         tmp, err := ioutil.TempDir(".", "")
72         if err != nil {
73                 t.Fatalf("failed to create temporary data folder: %v", err)
74         }
75         testDBA := dbm.NewDB("testdba", "leveldb", tmp)
76         testDBB := dbm.NewDB("testdbb", "leveldb", tmp)
77         defer func() {
78                 testDBA.Close()
79                 testDBB.Close()
80                 os.RemoveAll(tmp)
81         }()
82
83         maxSizeOfSyncSkeleton = 11
84         numOfBlocksSkeletonGap = 10
85         maxNumOfBlocksPerSync = numOfBlocksSkeletonGap * uint64(maxSizeOfSyncSkeleton-1)
86         fastSyncPivotGap = uint64(5)
87         minGapStartFastSync = uint64(6)
88
89         defer func() {
90                 maxSizeOfSyncSkeleton = 11
91                 numOfBlocksSkeletonGap = maxNumOfBlocksPerMsg
92                 maxNumOfBlocksPerSync = numOfBlocksSkeletonGap * uint64(maxSizeOfSyncSkeleton-1)
93                 fastSyncPivotGap = uint64(64)
94                 minGapStartFastSync = uint64(128)
95                 requireHeadersTimeout = 30 * time.Second
96         }()
97
98         baseChain := mockBlocks(nil, 300)
99
100         cases := []struct {
101                 syncTimeout time.Duration
102                 aBlocks     []*types.Block
103                 bBlocks     []*types.Block
104                 want        []*types.Block
105                 err         error
106         }{
107                 {
108                         syncTimeout: 30 * time.Second,
109                         aBlocks:     baseChain[:50],
110                         bBlocks:     baseChain[:301],
111                         want:        baseChain[:150],
112                         err:         nil,
113                 },
114                 {
115                         syncTimeout: 30 * time.Second,
116                         aBlocks:     baseChain[:2],
117                         bBlocks:     baseChain[:300],
118                         want:        baseChain[:102],
119                         err:         nil,
120                 },
121                 {
122                         syncTimeout: 30 * time.Second,
123                         aBlocks:     baseChain[:2],
124                         bBlocks:     baseChain[:53],
125                         want:        baseChain[:48],
126                         err:         nil,
127                 },
128                 {
129                         syncTimeout: 30 * time.Second,
130                         aBlocks:     baseChain[:2],
131                         bBlocks:     baseChain[:53],
132                         want:        baseChain[:48],
133                         err:         nil,
134                 },
135                 {
136                         syncTimeout: 30 * time.Second,
137                         aBlocks:     baseChain[:2],
138                         bBlocks:     baseChain[:10],
139                         want:        baseChain[:5],
140                         err:         nil,
141                 },
142                 {
143                         syncTimeout: 0 * time.Second,
144                         aBlocks:     baseChain[:50],
145                         bBlocks:     baseChain[:301],
146                         want:        baseChain[:50],
147                         err:         errSkeletonSize,
148                 },
149         }
150
151         for i, c := range cases {
152                 a := mockSync(c.aBlocks, nil, testDBA)
153                 b := mockSync(c.bBlocks, nil, testDBB)
154                 netWork := NewNetWork()
155                 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode|consensus.SFFastSync)
156                 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode|consensus.SFFastSync)
157                 if B2A, A2B, err := netWork.HandsShake(a, b); err != nil {
158                         t.Errorf("fail on peer hands shake %v", err)
159                 } else {
160                         go B2A.postMan()
161                         go A2B.postMan()
162                 }
163                 a.blockKeeper.syncPeer = a.peers.GetPeer("test node B")
164                 a.blockKeeper.fastSync.setSyncPeer(a.blockKeeper.syncPeer)
165
166                 requireHeadersTimeout = c.syncTimeout
167                 if err := a.blockKeeper.fastSync.process(); errors.Root(err) != c.err {
168                         t.Errorf("case %d: got %v want %v", i, err, c.err)
169                 }
170
171                 got := []*types.Block{}
172                 for i := uint64(0); i <= a.chain.BestBlockHeight(); i++ {
173                         block, err := a.chain.GetBlockByHeight(i)
174                         if err != nil {
175                                 t.Errorf("case %d got err %v", i, err)
176                         }
177                         got = append(got, block)
178                 }
179                 if !testutil.DeepEqual(got, c.want) {
180                         t.Errorf("case %d: got %v want %v", i, got, c.want)
181                 }
182         }
183 }