OSDN Git Service

add fast sync func (#204)
[bytom/vapor.git] / netsync / chainmgr / fast_sync_test.go
1 package chainmgr
2
3 import (
4         "testing"
5         "time"
6
7         "github.com/vapor/consensus"
8         "github.com/vapor/errors"
9         "github.com/vapor/protocol/bc"
10         "github.com/vapor/protocol/bc/types"
11         "github.com/vapor/test/mock"
12         "github.com/vapor/testutil"
13 )
14
15 func TestBlockLocator(t *testing.T) {
16         blocks := mockBlocks(nil, 500)
17         cases := []struct {
18                 bestHeight uint64
19                 wantHeight []uint64
20         }{
21                 {
22                         bestHeight: 0,
23                         wantHeight: []uint64{0},
24                 },
25                 {
26                         bestHeight: 1,
27                         wantHeight: []uint64{1, 0},
28                 },
29                 {
30                         bestHeight: 7,
31                         wantHeight: []uint64{7, 6, 5, 4, 3, 2, 1, 0},
32                 },
33                 {
34                         bestHeight: 10,
35                         wantHeight: []uint64{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
36                 },
37                 {
38                         bestHeight: 100,
39                         wantHeight: []uint64{100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 89, 85, 77, 61, 29, 0},
40                 },
41                 {
42                         bestHeight: 500,
43                         wantHeight: []uint64{500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 489, 485, 477, 461, 429, 365, 237, 0},
44                 },
45         }
46
47         for i, c := range cases {
48                 mockChain := mock.NewChain(nil)
49                 fs := &fastSync{chain: mockChain}
50                 mockChain.SetBestBlockHeader(&blocks[c.bestHeight].BlockHeader)
51                 for i := uint64(0); i <= c.bestHeight; i++ {
52                         mockChain.SetBlockByHeight(i, blocks[i])
53                 }
54
55                 want := []*bc.Hash{}
56                 for _, i := range c.wantHeight {
57                         hash := blocks[i].Hash()
58                         want = append(want, &hash)
59                 }
60
61                 if got := fs.blockLocator(); !testutil.DeepEqual(got, want) {
62                         t.Errorf("case %d: got %v want %v", i, got, want)
63                 }
64         }
65 }
66
67 func TestFastBlockSync(t *testing.T) {
68         maxBlocksPerMsg = 10
69         maxHeadersPerMsg = 10
70         maxFastSyncBlocksNum = 200
71         baseChain := mockBlocks(nil, 300)
72
73         cases := []struct {
74                 syncTimeout time.Duration
75                 aBlocks     []*types.Block
76                 bBlocks     []*types.Block
77                 want        []*types.Block
78                 err         error
79         }{
80                 {
81                         syncTimeout: 30 * time.Second,
82                         aBlocks:     baseChain[:50],
83                         bBlocks:     baseChain[:301],
84                         want:        baseChain[:237],
85                         err:         nil,
86                 },
87                 {
88                         syncTimeout: 30 * time.Second,
89                         aBlocks:     baseChain[:2],
90                         bBlocks:     baseChain[:300],
91                         want:        baseChain[:202],
92                         err:         nil,
93                 },
94         }
95
96         for i, c := range cases {
97                 syncTimeout = c.syncTimeout
98                 a := mockSync(c.aBlocks, nil)
99                 b := mockSync(c.bBlocks, nil)
100                 netWork := NewNetWork()
101                 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode|consensus.SFFastSync)
102                 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode|consensus.SFFastSync)
103                 if B2A, A2B, err := netWork.HandsShake(a, b); err != nil {
104                         t.Errorf("fail on peer hands shake %v", err)
105                 } else {
106                         go B2A.postMan()
107                         go A2B.postMan()
108                 }
109                 a.blockKeeper.syncPeer = a.peers.GetPeer("test node B")
110                 a.blockKeeper.fastSync.setSyncPeer(a.blockKeeper.syncPeer)
111
112                 if err := a.blockKeeper.fastSync.process(); errors.Root(err) != c.err {
113                         t.Errorf("case %d: got %v want %v", i, err, c.err)
114                 }
115
116                 got := []*types.Block{}
117                 for i := uint64(0); i <= a.chain.BestBlockHeight(); i++ {
118                         block, err := a.chain.GetBlockByHeight(i)
119                         if err != nil {
120                                 t.Errorf("case %d got err %v", i, err)
121                         }
122                         got = append(got, block)
123                 }
124                 if !testutil.DeepEqual(got, c.want) {
125                         t.Errorf("case %d: got %v want %v", i, got, c.want)
126                 }
127         }
128 }
129
130 func TestLocateBlocks(t *testing.T) {
131         maxBlocksPerMsg = 5
132         blocks := mockBlocks(nil, 100)
133         cases := []struct {
134                 locator    []uint64
135                 stopHash   bc.Hash
136                 wantHeight []uint64
137         }{
138                 {
139                         locator:    []uint64{20},
140                         stopHash:   blocks[100].Hash(),
141                         wantHeight: []uint64{20, 21, 22, 23, 24},
142                 },
143         }
144
145         mockChain := mock.NewChain(nil)
146         fs := &fastSync{chain: mockChain}
147         for _, block := range blocks {
148                 mockChain.SetBlockByHeight(block.Height, block)
149         }
150
151         for i, c := range cases {
152                 locator := []*bc.Hash{}
153                 for _, i := range c.locator {
154                         hash := blocks[i].Hash()
155                         locator = append(locator, &hash)
156                 }
157
158                 want := []*types.Block{}
159                 for _, i := range c.wantHeight {
160                         want = append(want, blocks[i])
161                 }
162
163                 got, _ := fs.locateBlocks(locator, &c.stopHash)
164                 if !testutil.DeepEqual(got, want) {
165                         t.Errorf("case %d: got %v want %v", i, got, want)
166                 }
167         }
168 }
169
170 func TestLocateHeaders(t *testing.T) {
171         maxHeadersPerMsg = 10
172         blocks := mockBlocks(nil, 150)
173         blocksHash := []bc.Hash{}
174         for _, block := range blocks {
175                 blocksHash = append(blocksHash, block.Hash())
176         }
177
178         cases := []struct {
179                 chainHeight uint64
180                 locator     []uint64
181                 stopHash    *bc.Hash
182                 skip        uint64
183                 wantHeight  []uint64
184                 err         bool
185         }{
186                 {
187                         chainHeight: 100,
188                         locator:     []uint64{90},
189                         stopHash:    &blocksHash[100],
190                         skip:        0,
191                         wantHeight:  []uint64{90, 91, 92, 93, 94, 95, 96, 97, 98, 99},
192                         err:         false,
193                 },
194                 {
195                         chainHeight: 100,
196                         locator:     []uint64{20},
197                         stopHash:    &blocksHash[24],
198                         skip:        0,
199                         wantHeight:  []uint64{20, 21, 22, 23, 24},
200                         err:         false,
201                 },
202                 {
203                         chainHeight: 100,
204                         locator:     []uint64{20},
205                         stopHash:    &blocksHash[20],
206                         wantHeight:  []uint64{20},
207                         err:         false,
208                 },
209                 {
210                         chainHeight: 100,
211                         locator:     []uint64{20},
212                         stopHash:    &blocksHash[120],
213                         wantHeight:  []uint64{},
214                         err:         false,
215                 },
216                 {
217                         chainHeight: 100,
218                         locator:     []uint64{120, 70},
219                         stopHash:    &blocksHash[78],
220                         wantHeight:  []uint64{70, 71, 72, 73, 74, 75, 76, 77, 78},
221                         err:         false,
222                 },
223                 {
224                         chainHeight: 100,
225                         locator:     []uint64{15},
226                         stopHash:    &blocksHash[10],
227                         skip:        10,
228                         wantHeight:  []uint64{},
229                         err:         false,
230                 },
231                 {
232                         chainHeight: 100,
233                         locator:     []uint64{15},
234                         stopHash:    &blocksHash[80],
235                         skip:        10,
236                         wantHeight:  []uint64{15, 26, 37, 48, 59, 70},
237                         err:         false,
238                 },
239                 {
240                         chainHeight: 100,
241                         locator:     []uint64{0},
242                         stopHash:    &blocksHash[100],
243                         skip:        9,
244                         wantHeight:  []uint64{0, 10, 20, 30, 40, 50, 60, 70, 80, 90},
245                         err:         false,
246                 },
247         }
248
249         for i, c := range cases {
250                 mockChain := mock.NewChain(nil)
251                 fs := &fastSync{chain: mockChain}
252                 for i := uint64(0); i <= c.chainHeight; i++ {
253                         mockChain.SetBlockByHeight(i, blocks[i])
254                 }
255
256                 locator := []*bc.Hash{}
257                 for _, i := range c.locator {
258                         hash := blocks[i].Hash()
259                         locator = append(locator, &hash)
260                 }
261
262                 want := []*types.BlockHeader{}
263                 for _, i := range c.wantHeight {
264                         want = append(want, &blocks[i].BlockHeader)
265                 }
266
267                 got, err := fs.locateHeaders(locator, c.stopHash, c.skip, maxHeadersPerMsg)
268                 if err != nil != c.err {
269                         t.Errorf("case %d: got %v want err = %v", i, err, c.err)
270                 }
271                 if !testutil.DeepEqual(got, want) {
272                         t.Errorf("case %d: got %v want %v", i, got, want)
273                 }
274         }
275 }