OSDN Git Service

feat: add build crosschain input (#91)
[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                 },
173         }
174
175         if err := store.SaveChainStatus(node, node, view, map[uint64]*state.VoteResult{}); err != nil {
176                 t.Fatal(err)
177         }
178
179         expectStatus := &protocol.BlockStoreState{Height: node.Height, Hash: &node.Hash, IrreversibleHeight: node.Height, IrreversibleHash: &node.Hash}
180         if !testutil.DeepEqual(store.GetStoreStatus(), expectStatus) {
181                 t.Errorf("got block status:%v, expect block status:%v", store.GetStoreStatus(), expectStatus)
182         }
183
184         for hash, utxo := range view.Entries {
185                 if (utxo.Type == storage.NormalUTXOType) && utxo.Spent {
186                         continue
187                 }
188                 if (utxo.Type == storage.CrosschainUTXOType) && (!utxo.Spent) {
189                         continue
190                 }
191
192                 gotUtxo, err := store.GetUtxo(&hash)
193                 if err != nil {
194                         t.Fatal(err)
195                 }
196
197                 if !testutil.DeepEqual(utxo, gotUtxo) {
198                         t.Errorf("got utxo entry:%v, expect utxo entry:%v", gotUtxo, utxo)
199                 }
200         }
201 }
202
203 func TestSaveBlock(t *testing.T) {
204         testDB := dbm.NewDB("testdb", "leveldb", "temp")
205         defer func() {
206                 testDB.Close()
207                 os.RemoveAll("temp")
208         }()
209
210         store := NewStore(testDB)
211
212         block := config.GenesisBlock()
213         status := &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{{StatusFail: true}}}
214         if err := store.SaveBlock(block, status); err != nil {
215                 t.Fatal(err)
216         }
217
218         blockHash := block.Hash()
219         gotBlock, err := store.GetBlock(&blockHash)
220         if err != nil {
221                 t.Fatal(err)
222         }
223
224         gotBlock.Transactions[0].Tx.SerializedSize = 0
225         gotBlock.Transactions[0].SerializedSize = 0
226         if !testutil.DeepEqual(block, gotBlock) {
227                 t.Errorf("got block:%v, expect block:%v", gotBlock, block)
228         }
229
230         gotStatus, err := store.GetTransactionStatus(&blockHash)
231         if err != nil {
232                 t.Fatal(err)
233         }
234
235         if !testutil.DeepEqual(status, gotStatus) {
236                 t.Errorf("got status:%v, expect status:%v", gotStatus, status)
237         }
238
239         data := store.db.Get(calcBlockHeaderKey(block.Height, &blockHash))
240         gotBlockHeader := types.BlockHeader{}
241         if err := gotBlockHeader.UnmarshalText(data); err != nil {
242                 t.Fatal(err)
243         }
244
245         if !testutil.DeepEqual(block.BlockHeader, gotBlockHeader) {
246                 t.Errorf("got block header:%v, expect block header:%v", gotBlockHeader, block.BlockHeader)
247         }
248 }