OSDN Git Service

Dev utxo unit test (#1606)
[bytom/bytom.git] / test / utxo_view / utxo_view_test.go
1 package utxo_view
2
3 import (
4         "os"
5         "testing"
6
7         "github.com/bytom/testutil"
8
9         "github.com/golang/protobuf/proto"
10         dbm "github.com/tendermint/tmlibs/db"
11
12         "github.com/bytom/database/leveldb"
13         "github.com/bytom/database/storage"
14         "github.com/bytom/protocol/bc"
15         "github.com/bytom/protocol/bc/types"
16         "github.com/bytom/protocol/state"
17 )
18
19 func TestAttachOrDetachBlocks(t *testing.T) {
20         cases := []struct {
21                 desc           string
22                 before         map[bc.Hash]*storage.UtxoEntry
23                 want           map[bc.Hash]*storage.UtxoEntry
24                 attachBlock    []*bc.Block
25                 detachBlock    []*bc.Block
26                 attachTxStatus []*bc.TransactionStatus
27                 detachTxStatus []*bc.TransactionStatus
28         }{
29                 {
30                         desc:   "coinbase tx",
31                         before: make(map[bc.Hash]*storage.UtxoEntry),
32                         want:   map[bc.Hash]*storage.UtxoEntry{*newTx(mockBlocks[0].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[0].Block.Height, false)},
33                         attachBlock: []*bc.Block{
34                                 types.MapBlock(&mockBlocks[0].Block),
35                         },
36                         attachTxStatus: []*bc.TransactionStatus{
37                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
38                                         &bc.TxVerifyResult{StatusFail: false},
39                                 }},
40                         },
41                 },
42                 {
43                         desc: "Chain trading 3",
44                         before: map[bc.Hash]*storage.UtxoEntry{
45                                 newTx(mockBlocks[1].Transactions[1]).getSpentOutputID(): storage.NewUtxoEntry(false, mockBlocks[1].Height-1, false),
46                         },
47                         want: map[bc.Hash]*storage.UtxoEntry{
48                                 *newTx(mockBlocks[1].Transactions[0]).OutputHash(0): storage.NewUtxoEntry(true, mockBlocks[1].Height, false),
49                                 *newTx(mockBlocks[1].Transactions[1]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
50                                 *newTx(mockBlocks[1].Transactions[2]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
51                                 *newTx(mockBlocks[1].Transactions[3]).OutputHash(0): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
52                                 *newTx(mockBlocks[1].Transactions[3]).OutputHash(1): storage.NewUtxoEntry(false, mockBlocks[1].Height, false),
53                         },
54                         attachBlock: []*bc.Block{
55                                 types.MapBlock(&mockBlocks[1].Block),
56                         },
57                         attachTxStatus: []*bc.TransactionStatus{
58                                 &bc.TransactionStatus{VerifyStatus: []*bc.TxVerifyResult{
59                                         &bc.TxVerifyResult{StatusFail: false},
60                                         &bc.TxVerifyResult{StatusFail: false},
61                                         &bc.TxVerifyResult{StatusFail: false},
62                                         &bc.TxVerifyResult{StatusFail: false},
63                                 }},
64                         },
65                 },
66         }
67         node := blockNode(types.MapBlock(&mockBlocks[0].Block).BlockHeader)
68         defer os.RemoveAll("temp")
69         for index, c := range cases {
70                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
71                 store := leveldb.NewStore(testDB)
72
73                 utxoViewpoint := state.NewUtxoViewpoint()
74                 for k, v := range c.before {
75                         utxoViewpoint.Entries[k] = v
76                 }
77                 if err := store.SaveChainStatus(node, utxoViewpoint); err != nil {
78                         t.Error(err)
79                 }
80
81                 utxoViewpoint = state.NewUtxoViewpoint()
82                 for index, block := range c.detachBlock {
83                         if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
84                                 t.Error(err)
85                         }
86                         if err := utxoViewpoint.DetachBlock(block, c.detachTxStatus[index]); err != nil {
87                                 t.Error(err)
88                         }
89                 }
90
91                 for index, block := range c.attachBlock {
92                         if err := store.GetTransactionsUtxo(utxoViewpoint, block.Transactions); err != nil {
93                                 t.Error(err)
94                         }
95                         if err := utxoViewpoint.ApplyBlock(block, c.attachTxStatus[index]); err != nil {
96                                 t.Error(err)
97                         }
98                 }
99                 if err := store.SaveChainStatus(node, utxoViewpoint); err != nil {
100                         t.Error(err)
101                 }
102
103                 want := map[string]*storage.UtxoEntry{}
104                 result := make(map[string]*storage.UtxoEntry)
105
106                 for k, v := range c.want {
107                         want[string(calcUtxoKey(&k))] = v
108                 }
109
110                 iter := testDB.IteratorPrefix([]byte(utxoPreFix))
111                 defer iter.Release()
112
113                 for iter.Next() {
114                         utxoEntry := &storage.UtxoEntry{}
115                         if err := proto.Unmarshal(iter.Value(), utxoEntry); err != nil {
116                                 t.Error(err)
117                         }
118                         key := string(iter.Key())
119                         result[key] = utxoEntry
120                 }
121
122                 if !testutil.DeepEqual(want, result) {
123                         t.Errorf("case [%d] fail. want: %v, result: %v", index, want, result)
124                 }
125                 testDB.Close()
126                 os.RemoveAll("temp")
127         }
128 }