OSDN Git Service

ea009eb6bd3c9c720de5699ac84327a9b5b5e3c3
[bytom/vapor.git] / database / store_test.go
1 package database
2
3 import (
4         "os"
5         "testing"
6
7         "github.com/vapor/config"
8         dbm "github.com/vapor/database/leveldb"
9         "github.com/vapor/database/storage"
10         "github.com/vapor/protocol"
11         "github.com/vapor/protocol/bc"
12         "github.com/vapor/protocol/bc/types"
13         "github.com/vapor/protocol/state"
14         "github.com/vapor/testutil"
15 )
16
17 func TestLoadBlockIndex(t *testing.T) {
18         config.CommonConfig = config.DefaultConfig()
19         testDB := dbm.NewDB("testdb", "leveldb", "temp")
20         store := NewStore(testDB)
21         defer func() {
22                 testDB.Close()
23                 os.RemoveAll("temp")
24         }()
25
26         block := config.GenesisBlock()
27         txStatus := bc.NewTransactionStatus()
28
29         if err := store.SaveBlock(block, txStatus); err != nil {
30                 t.Fatal(err)
31         }
32
33         for block.Height <= 128 {
34                 preHash := block.Hash()
35                 block.PreviousBlockHash = preHash
36                 block.Height++
37                 if err := store.SaveBlock(block, txStatus); err != nil {
38                         t.Fatal(err)
39                 }
40
41                 if block.Height%32 != 0 {
42                         continue
43                 }
44
45                 for i := uint64(0); i < block.Height/32; i++ {
46                         block.Version++
47                         if err := store.SaveBlock(block, txStatus); err != nil {
48                                 t.Fatal(err)
49                         }
50                 }
51         }
52
53         if _, err := store.LoadBlockIndex(128); err != nil {
54                 t.Fatal(err)
55         }
56 }
57
58 func TestLoadBlockIndexBestHeight(t *testing.T) {
59         cases := []struct {
60                 blockBestHeight uint64
61                 stateBestHeight uint64
62         }{
63                 {
64                         blockBestHeight: 100,
65                         stateBestHeight: 90,
66                 },
67                 {
68                         blockBestHeight: 100,
69                         stateBestHeight: 0,
70                 },
71                 {
72                         blockBestHeight: 100,
73                         stateBestHeight: 100,
74                 },
75         }
76
77         testDB := dbm.NewDB("testdb", "leveldb", "temp")
78         defer func() {
79                 testDB.Close()
80                 os.RemoveAll("temp")
81         }()
82         store := NewStore(testDB)
83         var savedBlocks []types.Block
84
85         for _, c := range cases {
86                 block := config.GenesisBlock()
87                 txStatus := bc.NewTransactionStatus()
88
89                 for i := uint64(0); i < c.blockBestHeight; i++ {
90                         if err := store.SaveBlock(block, txStatus); err != nil {
91                                 t.Fatal(err)
92                         }
93
94                         savedBlocks = append(savedBlocks, *block)
95                         block.PreviousBlockHash = block.Hash()
96                         block.Height++
97                 }
98
99                 index, err := store.LoadBlockIndex(c.stateBestHeight)
100                 if err != nil {
101                         t.Fatal(err)
102                 }
103
104                 for _, block := range savedBlocks {
105                         blockHash := block.Hash()
106                         if block.Height <= c.stateBestHeight != index.BlockExist(&blockHash) {
107                                 t.Errorf("Error in load block index")
108                         }
109                 }
110         }
111 }
112
113 func TestLoadBlockIndexEquals(t *testing.T) {
114         testDB := dbm.NewDB("testdb", "leveldb", "temp")
115         store := NewStore(testDB)
116         defer func() {
117                 testDB.Close()
118                 os.RemoveAll("temp")
119         }()
120
121         block := config.GenesisBlock()
122         txStatus := bc.NewTransactionStatus()
123         expectBlockIndex := state.NewBlockIndex()
124         var parent *state.BlockNode
125
126         for block.Height <= 100 {
127                 if err := store.SaveBlock(block, txStatus); err != nil {
128                         t.Fatal(err)
129                 }
130
131                 if block.Height != 0 {
132                         parent = expectBlockIndex.GetNode(&block.PreviousBlockHash)
133                 }
134
135                 node, err := state.NewBlockNode(&block.BlockHeader, parent)
136                 if err != nil {
137                         t.Fatal(err)
138                 }
139
140                 expectBlockIndex.AddNode(node)
141                 block.PreviousBlockHash = block.Hash()
142                 block.Height++
143         }
144
145         index, err := store.LoadBlockIndex(100)
146         if err != nil {
147                 t.Fatal(err)
148         }
149
150         if !testutil.DeepEqual(expectBlockIndex, index) {
151                 t.Errorf("got block index:%v, expect block index:%v", index, expectBlockIndex)
152         }
153 }
154
155 func TestSaveChainStatus(t *testing.T) {
156         testDB := dbm.NewDB("testdb", "leveldb", "temp")
157         defer func() {
158                 testDB.Close()
159                 os.RemoveAll("temp")
160         }()
161
162         store := NewStore(testDB)
163
164         node := &state.BlockNode{Height: 100, Hash: bc.Hash{V0: 0, V1: 1, V2: 2, V3: 3}}
165         view := &state.UtxoViewpoint{
166                 Entries: map[bc.Hash]*storage.UtxoEntry{
167                         bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.NormalUTXOType, BlockHeight: 100, Spent: false},
168                         bc.Hash{V0: 1, V1: 2, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.CoinbaseUTXOType, BlockHeight: 100, Spent: true},
169                         bc.Hash{V0: 1, V1: 1, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.NormalUTXOType, BlockHeight: 100, Spent: true},
170                         bc.Hash{V0: 1, V1: 1, V2: 3, V3: 5}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: false},
171                         bc.Hash{V0: 1, V1: 1, V2: 3, V3: 6}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: true},
172                         bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: false},
173                         bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: true},
174                 },
175         }
176
177         if err := store.SaveChainStatus(node, node, view, []*state.VoteResult{}); err != nil {
178                 t.Fatal(err)
179         }
180
181         expectStatus := &protocol.BlockStoreState{Height: node.Height, Hash: &node.Hash, IrreversibleHeight: node.Height, IrreversibleHash: &node.Hash}
182         if !testutil.DeepEqual(store.GetStoreStatus(), expectStatus) {
183                 t.Errorf("got block status:%v, expect block status:%v", store.GetStoreStatus(), expectStatus)
184         }
185
186         for hash, utxo := range view.Entries {
187                 if (utxo.Type == storage.NormalUTXOType) && utxo.Spent {
188                         continue
189                 }
190                 if (utxo.Type == storage.CrosschainUTXOType) && (!utxo.Spent) {
191                         continue
192                 }
193                 if (utxo.Type == storage.VoteUTXOType) && (utxo.Spent) {
194                         continue
195                 }
196
197                 gotUtxo, err := store.GetUtxo(&hash)
198                 if err != nil {
199                         t.Fatal(err)
200                 }
201
202                 if !testutil.DeepEqual(utxo, gotUtxo) {
203                         t.Errorf("got utxo entry:%v, expect utxo entry:%v", gotUtxo, utxo)
204                 }
205         }
206 }
207
208 func TestSaveBlock(t *testing.T) {
209         testDB := dbm.NewDB("testdb", "leveldb", "temp")
210         defer func() {
211                 testDB.Close()
212                 os.RemoveAll("temp")
213         }()
214
215         store := NewStore(testDB)
216
217         block := config.GenesisBlock()
218         status := &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{{StatusFail: true}}}
219         if err := store.SaveBlock(block, status); err != nil {
220                 t.Fatal(err)
221         }
222
223         blockHash := block.Hash()
224         gotBlock, err := store.GetBlock(&blockHash, block.Height)
225         if err != nil {
226                 t.Fatal(err)
227         }
228
229         gotBlock.Transactions[0].Tx.SerializedSize = 0
230         gotBlock.Transactions[0].SerializedSize = 0
231         if !testutil.DeepEqual(block, gotBlock) {
232                 t.Errorf("got block:%v, expect block:%v", gotBlock, block)
233         }
234
235         gotStatus, err := store.GetTransactionStatus(&blockHash)
236         if err != nil {
237                 t.Fatal(err)
238         }
239
240         if !testutil.DeepEqual(status, gotStatus) {
241                 t.Errorf("got status:%v, expect status:%v", gotStatus, status)
242         }
243
244         data := store.db.Get(calcBlockHeaderKey(block.Height, &blockHash))
245         gotBlockHeader := types.BlockHeader{}
246         if err := gotBlockHeader.UnmarshalText(data); err != nil {
247                 t.Fatal(err)
248         }
249
250         if !testutil.DeepEqual(block.BlockHeader, gotBlockHeader) {
251                 t.Errorf("got block header:%v, expect block header:%v", gotBlockHeader, block.BlockHeader)
252         }
253 }