github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/test/integration/block_integration_util.go (about) 1 package integration 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "reflect" 8 "strings" 9 "sort" 10 11 "github.com/golang/protobuf/proto" 12 13 "github.com/bytom/bytom/database" 14 dbm "github.com/bytom/bytom/database/leveldb" 15 "github.com/bytom/bytom/database/storage" 16 "github.com/bytom/bytom/event" 17 "github.com/bytom/bytom/protocol" 18 "github.com/bytom/bytom/protocol/bc" 19 "github.com/bytom/bytom/protocol/bc/types" 20 "github.com/bytom/bytom/protocol/state" 21 "github.com/bytom/bytom/testutil" 22 ) 23 24 const ( 25 dbDir = "temp" 26 ) 27 28 type storeItem struct { 29 key []byte 30 val interface{} 31 } 32 33 type serialFun func(obj interface{}) ([]byte, error) 34 type deserialFun func(data []byte) (interface{}, error) 35 36 func getSerialFun(item interface{}) (serialFun, error) { 37 switch item.(type) { 38 case *protocol.BlockStoreState: 39 return json.Marshal, nil 40 case *types.Block: 41 return func(obj interface{}) ([]byte, error) { 42 block := obj.(*types.Block) 43 return block.MarshalText() 44 }, nil 45 case types.BlockHeader: 46 return func(obj interface{}) ([]byte, error) { 47 bh := obj.(types.BlockHeader) 48 return bh.MarshalText() 49 }, nil 50 case *bc.TransactionStatus: 51 return func(obj interface{}) ([]byte, error) { 52 status := obj.(*bc.TransactionStatus) 53 return proto.Marshal(status) 54 }, nil 55 case *storage.UtxoEntry: 56 return func(obj interface{}) ([]byte, error) { 57 utxo := obj.(*storage.UtxoEntry) 58 return proto.Marshal(utxo) 59 }, nil 60 } 61 typ := reflect.TypeOf(item) 62 return nil, fmt.Errorf("can not found any serialization function for type:%s", typ.Name()) 63 } 64 65 func getDeserialFun(key []byte) (deserialFun, error) { 66 funMap := map[string]deserialFun{ 67 string(database.BlockStoreKey): func(data []byte) (interface{}, error) { 68 storeState := &protocol.BlockStoreState{} 69 err := json.Unmarshal(data, storeState) 70 return storeState, err 71 }, 72 string(database.TxStatusPrefix): func(data []byte) (interface{}, error) { 73 status := &bc.TransactionStatus{} 74 err := proto.Unmarshal(data, status) 75 return status, err 76 }, 77 string(database.BlockPrefix): func(data []byte) (interface{}, error) { 78 block := &types.Block{} 79 err := block.UnmarshalText(data) 80 sortSpendOutputID(block) 81 return block, err 82 }, 83 string(database.BlockHeaderPrefix): func(data []byte) (interface{}, error) { 84 bh := types.BlockHeader{} 85 err := bh.UnmarshalText(data) 86 return bh, err 87 }, 88 database.UtxoPreFix: func(data []byte) (interface{}, error) { 89 utxo := &storage.UtxoEntry{} 90 err := proto.Unmarshal(data, utxo) 91 return utxo, err 92 }, 93 } 94 95 for prefix, converter := range funMap { 96 if strings.HasPrefix(string(key), prefix) { 97 return converter, nil 98 } 99 } 100 return nil, fmt.Errorf("can not found any deserialization function for key:%s", string(key)) 101 } 102 103 type storeItems []*storeItem 104 105 func (s1 storeItems) equals(s2 storeItems) bool { 106 if s2 == nil { 107 return false 108 } 109 110 itemMap1 := make(map[string]interface{}, len(s1)) 111 for _, item := range s1 { 112 itemMap1[string(item.key)] = item.val 113 } 114 115 itemMap2 := make(map[string]interface{}, len(s2)) 116 for _, item := range s2 { 117 itemMap2[string(item.key)] = item.val 118 } 119 120 return testutil.DeepEqual(itemMap1, itemMap2) 121 } 122 123 type processBlockTestCase struct { 124 desc string 125 initStore []*storeItem 126 wantStore []*storeItem 127 wantBlockIndex *state.BlockIndex 128 initOrphanManage *protocol.OrphanManage 129 wantOrphanManage *protocol.OrphanManage 130 wantIsOrphan bool 131 wantError bool 132 newBlock *types.Block 133 } 134 135 func (p *processBlockTestCase) Run() error { 136 defer os.RemoveAll(dbDir) 137 if p.initStore == nil { 138 p.initStore = make([]*storeItem, 0) 139 } 140 store, db, err := initStore(p) 141 if err != nil { 142 return err 143 } 144 145 orphanManage := p.initOrphanManage 146 if orphanManage == nil { 147 orphanManage = protocol.NewOrphanManage() 148 } 149 150 txPool := protocol.NewTxPool(store, event.NewDispatcher()) 151 chain, err := protocol.NewChainWithOrphanManage(store, txPool, orphanManage) 152 if err != nil { 153 return err 154 } 155 156 isOrphan, err := chain.ProcessBlock(p.newBlock) 157 if p.wantError != (err != nil) { 158 return fmt.Errorf("#case(%s) want error:%t, got error:%t", p.desc, p.wantError, err != nil) 159 } 160 161 if isOrphan != p.wantIsOrphan { 162 return fmt.Errorf("#case(%s) want orphan:%t, got orphan:%t", p.desc, p.wantIsOrphan, isOrphan) 163 } 164 165 if p.wantStore != nil { 166 gotStoreItems, err := loadStoreItems(db) 167 if err != nil { 168 return err 169 } 170 171 if !storeItems(gotStoreItems).equals(p.wantStore) { 172 return fmt.Errorf("#case(%s) want store:%v, got store:%v", p.desc, p.wantStore, gotStoreItems) 173 } 174 } 175 176 if p.wantBlockIndex != nil { 177 blockIndex := chain.GetBlockIndex() 178 if !blockIndex.Equals(p.wantBlockIndex) { 179 return fmt.Errorf("#case(%s) want block index:%v, got block index:%v", p.desc, *p.wantBlockIndex, *blockIndex) 180 } 181 } 182 183 if p.wantOrphanManage != nil { 184 if !orphanManage.Equals(p.wantOrphanManage) { 185 return fmt.Errorf("#case(%s) want orphan manage:%v, got orphan manage:%v", p.desc, *p.wantOrphanManage, *orphanManage) 186 } 187 } 188 return nil 189 } 190 191 func loadStoreItems(db dbm.DB) ([]*storeItem, error) { 192 iter := db.Iterator() 193 defer iter.Release() 194 195 var items []*storeItem 196 for iter.Next() { 197 item := &storeItem{key: iter.Key()} 198 fun, err := getDeserialFun(iter.Key()) 199 if err != nil { 200 return nil, err 201 } 202 203 val, err := fun(iter.Value()) 204 if err != nil { 205 return nil, err 206 } 207 208 item.val = val 209 items = append(items, item) 210 } 211 return items, nil 212 } 213 214 func initStore(c *processBlockTestCase) (protocol.Store, dbm.DB, error) { 215 testDB := dbm.NewDB("testdb", "leveldb", dbDir) 216 batch := testDB.NewBatch() 217 for _, item := range c.initStore { 218 fun, err := getSerialFun(item.val) 219 if err != nil { 220 return nil, nil, err 221 } 222 223 bytes, err := fun(item.val) 224 if err != nil { 225 return nil, nil, err 226 } 227 228 batch.Set(item.key, bytes) 229 } 230 batch.Write() 231 return database.NewStore(testDB), testDB, nil 232 } 233 234 func sortSpendOutputID(block *types.Block) { 235 for _, tx := range block.Transactions { 236 sort.Sort(HashSlice(tx.SpentOutputIDs)) 237 } 238 } 239 240 type HashSlice []bc.Hash 241 242 func (p HashSlice) Len() int { return len(p) } 243 func (p HashSlice) Less(i, j int) bool { return p[i].String() < p[j].String() } 244 func (p HashSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }