github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/blkstorage/blockstore_provider_test.go (about) 1 /* 2 Copyright hechain. 2022 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package blkstorage 8 9 import ( 10 "fmt" 11 "os" 12 "testing" 13 14 "github.com/hechain20/hechain/common/ledger/testutil" 15 "github.com/hechain20/hechain/internal/pkg/txflags" 16 "github.com/hechain20/hechain/protoutil" 17 "github.com/hyperledger/fabric-protos-go/common" 18 "github.com/hyperledger/fabric-protos-go/peer" 19 "github.com/stretchr/testify/require" 20 ) 21 22 func TestIndexConfig(t *testing.T) { 23 ic := &IndexConfig{ 24 AttrsToIndex: []IndexableAttr{ 25 IndexableAttrBlockNum, 26 IndexableAttrTxID, 27 }, 28 } 29 30 require := require.New(t) 31 require.True(ic.Contains(IndexableAttrBlockNum)) 32 require.True(ic.Contains(IndexableAttrTxID)) 33 require.False(ic.Contains(IndexableAttrBlockNumTranNum)) 34 } 35 36 func TestMultipleBlockStores(t *testing.T) { 37 tempdir := testPath() 38 defer os.RemoveAll(tempdir) 39 40 env := newTestEnv(t, NewConf(tempdir, 0)) 41 provider := env.provider 42 defer provider.Close() 43 44 subdirs, err := provider.List() 45 require.NoError(t, err) 46 require.Empty(t, subdirs) 47 48 store1, err := provider.Open("ledger1") 49 require.NoError(t, err) 50 defer store1.Shutdown() 51 store2, err := provider.Open("ledger2") 52 require.NoError(t, err) 53 defer store2.Shutdown() 54 55 blocks1 := addBlocksToStore(t, store1, 5) 56 blocks2 := addBlocksToStore(t, store2, 10) 57 58 checkBlocks(t, blocks1, store1) 59 checkBlocks(t, blocks2, store2) 60 checkWithWrongInputs(t, store1, 5) 61 checkWithWrongInputs(t, store2, 10) 62 63 store1.Shutdown() 64 store2.Shutdown() 65 provider.Close() 66 67 // Reopen provider 68 newenv := newTestEnv(t, NewConf(tempdir, 0)) 69 newprovider := newenv.provider 70 defer newprovider.Close() 71 72 subdirs, err = newprovider.List() 73 require.NoError(t, err) 74 require.Len(t, subdirs, 2) 75 76 newstore1, err := newprovider.Open("ledger1") 77 require.NoError(t, err) 78 defer newstore1.Shutdown() 79 newstore2, err := newprovider.Open("ledger2") 80 require.NoError(t, err) 81 defer newstore2.Shutdown() 82 83 checkBlocks(t, blocks1, newstore1) 84 checkBlocks(t, blocks2, newstore2) 85 checkWithWrongInputs(t, newstore1, 5) 86 checkWithWrongInputs(t, newstore2, 10) 87 } 88 89 func addBlocksToStore(t *testing.T, store *BlockStore, numBlocks int) []*common.Block { 90 blocks := testutil.ConstructTestBlocks(t, numBlocks) 91 for _, b := range blocks { 92 err := store.AddBlock(b) 93 require.NoError(t, err) 94 } 95 return blocks 96 } 97 98 func checkBlocks(t *testing.T, expectedBlocks []*common.Block, store *BlockStore) { 99 bcInfo, _ := store.GetBlockchainInfo() 100 require.Equal(t, uint64(len(expectedBlocks)), bcInfo.Height) 101 require.Equal(t, protoutil.BlockHeaderHash(expectedBlocks[len(expectedBlocks)-1].GetHeader()), bcInfo.CurrentBlockHash) 102 103 itr, _ := store.RetrieveBlocks(0) 104 for i := 0; i < len(expectedBlocks); i++ { 105 block, _ := itr.Next() 106 require.Equal(t, expectedBlocks[i], block) 107 } 108 109 for blockNum := 0; blockNum < len(expectedBlocks); blockNum++ { 110 block := expectedBlocks[blockNum] 111 flags := txflags.ValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 112 retrievedBlock, _ := store.RetrieveBlockByNumber(uint64(blockNum)) 113 require.Equal(t, block, retrievedBlock) 114 115 retrievedBlock, _ = store.RetrieveBlockByHash(protoutil.BlockHeaderHash(block.Header)) 116 require.Equal(t, block, retrievedBlock) 117 118 for txNum := 0; txNum < len(block.Data.Data); txNum++ { 119 txEnvBytes := block.Data.Data[txNum] 120 txEnv, _ := protoutil.GetEnvelopeFromBlock(txEnvBytes) 121 txid, err := protoutil.GetOrComputeTxIDFromEnvelope(txEnvBytes) 122 require.NoError(t, err) 123 124 retrievedBlock, _ := store.RetrieveBlockByTxID(txid) 125 require.Equal(t, block, retrievedBlock) 126 127 retrievedTxEnv, _ := store.RetrieveTxByID(txid) 128 require.Equal(t, txEnv, retrievedTxEnv) 129 130 retrievedTxEnv, _ = store.RetrieveTxByBlockNumTranNum(uint64(blockNum), uint64(txNum)) 131 require.Equal(t, txEnv, retrievedTxEnv) 132 133 retrievedTxValCode, blkNum, err := store.RetrieveTxValidationCodeByTxID(txid) 134 require.NoError(t, err) 135 require.Equal(t, flags.Flag(txNum), retrievedTxValCode) 136 require.Equal(t, uint64(blockNum), blkNum) 137 } 138 } 139 } 140 141 func checkWithWrongInputs(t *testing.T, store *BlockStore, numBlocks int) { 142 block, err := store.RetrieveBlockByHash([]byte("non-existent-hash")) 143 require.Nil(t, block) 144 require.EqualError(t, err, fmt.Sprintf("no such block hash [%x] in index", []byte("non-existent-hash"))) 145 146 block, err = store.RetrieveBlockByTxID("non-existent-txid") 147 require.Nil(t, block) 148 require.EqualError(t, err, "no such transaction ID [non-existent-txid] in index") 149 150 tx, err := store.RetrieveTxByID("non-existent-txid") 151 require.Nil(t, tx) 152 require.EqualError(t, err, "no such transaction ID [non-existent-txid] in index") 153 154 tx, err = store.RetrieveTxByBlockNumTranNum(uint64(numBlocks+1), uint64(0)) 155 require.Nil(t, tx) 156 require.EqualError(t, err, fmt.Sprintf("no such blockNumber, transactionNumber <%d, 0> in index", numBlocks+1)) 157 158 txCode, blkNum, err := store.RetrieveTxValidationCodeByTxID("non-existent-txid") 159 require.Equal(t, peer.TxValidationCode(-1), txCode) 160 require.Equal(t, uint64(0), blkNum) 161 require.EqualError(t, err, "no such transaction ID [non-existent-txid] in index") 162 } 163 164 func TestBlockStoreProvider(t *testing.T) { 165 env := newTestEnv(t, NewConf(testPath(), 0)) 166 defer env.Cleanup() 167 168 provider := env.provider 169 storeNames, err := provider.List() 170 require.NoError(t, err) 171 require.Empty(t, storeNames) 172 173 var stores []*BlockStore 174 numStores := 10 175 for i := 0; i < numStores; i++ { 176 store, _ := provider.Open(constructLedgerid(i)) 177 defer store.Shutdown() 178 stores = append(stores, store) 179 } 180 require.Equal(t, numStores, len(stores)) 181 182 storeNames, err = provider.List() 183 require.NoError(t, err) 184 require.Equal(t, numStores, len(storeNames)) 185 186 for i := 0; i < numStores; i++ { 187 exists, err := provider.Exists(constructLedgerid(i)) 188 require.NoError(t, err) 189 require.Equal(t, true, exists) 190 } 191 192 exists, err := provider.Exists(constructLedgerid(numStores + 1)) 193 require.NoError(t, err) 194 require.Equal(t, false, exists) 195 } 196 197 func TestDrop(t *testing.T) { 198 env := newTestEnv(t, NewConf(testPath(), 0)) 199 defer env.Cleanup() 200 201 provider := env.provider 202 store1, err := provider.Open("ledger1") 203 require.NoError(t, err) 204 defer store1.Shutdown() 205 store2, err := provider.Open("ledger2") 206 require.NoError(t, err) 207 defer store2.Shutdown() 208 209 blocks1 := addBlocksToStore(t, store1, 5) 210 blocks2 := addBlocksToStore(t, store2, 10) 211 212 checkBlocks(t, blocks1, store1) 213 checkBlocks(t, blocks2, store2) 214 storeNames, err := provider.List() 215 require.NoError(t, err) 216 require.ElementsMatch(t, storeNames, []string{"ledger1", "ledger2"}) 217 218 require.NoError(t, provider.Drop("ledger1")) 219 220 // verify ledger1 block dir and block indexes are deleted 221 exists, err := provider.Exists("ledger1") 222 require.NoError(t, err) 223 require.False(t, exists) 224 225 empty, err := provider.leveldbProvider.GetDBHandle("ledger1").IsEmpty() 226 require.NoError(t, err) 227 require.True(t, empty) 228 229 // verify ledger2 ledger data are remained same 230 checkBlocks(t, blocks2, store2) 231 storeNames, err = provider.List() 232 require.NoError(t, err) 233 require.ElementsMatch(t, storeNames, []string{"ledger2"}) 234 235 // drop again should return no error 236 require.NoError(t, provider.Drop("ledger1")) 237 238 // verify "ledger1" store can be opened again after remove, but it is an empty store 239 newstore1, err := provider.Open("ledger1") 240 require.NoError(t, err) 241 bcInfo, err := newstore1.GetBlockchainInfo() 242 require.NoError(t, err) 243 require.Equal(t, &common.BlockchainInfo{}, bcInfo) 244 245 // negative test 246 provider.Close() 247 require.EqualError(t, provider.Drop("ledger2"), "internal leveldb error while obtaining db iterator: leveldb: closed") 248 } 249 250 func constructLedgerid(id int) string { 251 return fmt.Sprintf("ledger_%d", id) 252 }