OSDN Git Service

Fix sync orphan block system panic (#281)
[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         maxNumOfSkeletonPerSync = 10
84         numOfBlocksSkeletonGap = 10
85         maxNumOfBlocksPerSync = maxNumOfSkeletonPerSync * maxNumOfSkeletonPerSync
86         fastSyncPivotGap = uint64(5)
87         minGapStartFastSync = uint64(6)
88
89         defer func() {
90                 maxNumOfSkeletonPerSync = 10
91                 numOfBlocksSkeletonGap = maxNumOfBlocksPerMsg
92                 maxNumOfBlocksPerSync = maxNumOfSkeletonPerSync * maxNumOfSkeletonPerSync
93                 fastSyncPivotGap = uint64(64)
94                 minGapStartFastSync = uint64(128)
95
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
144         for i, c := range cases {
145                 a := mockSync(c.aBlocks, nil, testDBA)
146                 b := mockSync(c.bBlocks, nil, testDBB)
147                 netWork := NewNetWork()
148                 netWork.Register(a, "192.168.0.1", "test node A", consensus.SFFullNode|consensus.SFFastSync)
149                 netWork.Register(b, "192.168.0.2", "test node B", consensus.SFFullNode|consensus.SFFastSync)
150                 if B2A, A2B, err := netWork.HandsShake(a, b); err != nil {
151                         t.Errorf("fail on peer hands shake %v", err)
152                 } else {
153                         go B2A.postMan()
154                         go A2B.postMan()
155                 }
156                 a.blockKeeper.syncPeer = a.peers.GetPeer("test node B")
157                 a.blockKeeper.fastSync.setSyncPeer(a.blockKeeper.syncPeer)
158
159                 if err := a.blockKeeper.fastSync.process(); errors.Root(err) != c.err {
160                         t.Errorf("case %d: got %v want %v", i, err, c.err)
161                 }
162
163                 got := []*types.Block{}
164                 for i := uint64(0); i <= a.chain.BestBlockHeight(); i++ {
165                         block, err := a.chain.GetBlockByHeight(i)
166                         if err != nil {
167                                 t.Errorf("case %d got err %v", i, err)
168                         }
169                         got = append(got, block)
170                 }
171                 if !testutil.DeepEqual(got, c.want) {
172                         t.Errorf("case %d: got %v want %v", i, got, c.want)
173                 }
174         }
175 }