github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/common/ledger/blkstorage/blockstore_provider_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 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/hyperledger/fabric-protos-go/common" 15 "github.com/hyperledger/fabric-protos-go/peer" 16 "github.com/osdi23p228/fabric/common/ledger/testutil" 17 "github.com/osdi23p228/fabric/internal/pkg/txflags" 18 "github.com/osdi23p228/fabric/protoutil" 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, err := store.RetrieveTxValidationCodeByTxID(txid) 134 require.NoError(t, err) 135 require.Equal(t, flags.Flag(txNum), retrievedTxValCode) 136 } 137 } 138 } 139 140 func checkWithWrongInputs(t *testing.T, store *BlockStore, numBlocks int) { 141 block, err := store.RetrieveBlockByHash([]byte("non-existent-hash")) 142 require.Nil(t, block) 143 require.Equal(t, ErrNotFoundInIndex, err) 144 145 block, err = store.RetrieveBlockByTxID("non-existent-txid") 146 require.Nil(t, block) 147 require.Equal(t, ErrNotFoundInIndex, err) 148 149 tx, err := store.RetrieveTxByID("non-existent-txid") 150 require.Nil(t, tx) 151 require.Equal(t, ErrNotFoundInIndex, err) 152 153 tx, err = store.RetrieveTxByBlockNumTranNum(uint64(numBlocks+1), uint64(0)) 154 require.Nil(t, tx) 155 require.Equal(t, ErrNotFoundInIndex, err) 156 157 txCode, err := store.RetrieveTxValidationCodeByTxID("non-existent-txid") 158 require.Equal(t, peer.TxValidationCode(-1), txCode) 159 require.Equal(t, ErrNotFoundInIndex, err) 160 } 161 162 func TestBlockStoreProvider(t *testing.T) { 163 env := newTestEnv(t, NewConf(testPath(), 0)) 164 defer env.Cleanup() 165 166 provider := env.provider 167 storeNames, err := provider.List() 168 require.NoError(t, err) 169 require.Empty(t, storeNames) 170 171 var stores []*BlockStore 172 numStores := 10 173 for i := 0; i < numStores; i++ { 174 store, _ := provider.Open(constructLedgerid(i)) 175 defer store.Shutdown() 176 stores = append(stores, store) 177 } 178 require.Equal(t, numStores, len(stores)) 179 180 storeNames, err = provider.List() 181 require.NoError(t, err) 182 require.Equal(t, numStores, len(storeNames)) 183 184 for i := 0; i < numStores; i++ { 185 exists, err := provider.Exists(constructLedgerid(i)) 186 require.NoError(t, err) 187 require.Equal(t, true, exists) 188 } 189 190 exists, err := provider.Exists(constructLedgerid(numStores + 1)) 191 require.NoError(t, err) 192 require.Equal(t, false, exists) 193 194 } 195 196 func TestRemove(t *testing.T) { 197 env := newTestEnv(t, NewConf(testPath(), 0)) 198 defer env.Cleanup() 199 200 provider := env.provider 201 store1, err := provider.Open("ledger1") 202 require.NoError(t, err) 203 defer store1.Shutdown() 204 store2, err := provider.Open("ledger2") 205 require.NoError(t, err) 206 defer store2.Shutdown() 207 208 blocks1 := addBlocksToStore(t, store1, 5) 209 blocks2 := addBlocksToStore(t, store2, 10) 210 211 checkBlocks(t, blocks1, store1) 212 checkBlocks(t, blocks2, store2) 213 storeNames, err := provider.List() 214 require.NoError(t, err) 215 require.ElementsMatch(t, storeNames, []string{"ledger1", "ledger2"}) 216 217 require.NoError(t, provider.Remove("ledger1")) 218 219 // verify ledger1 block dir and block indexes are deleted 220 exists, err := provider.Exists("ledger1") 221 require.NoError(t, err) 222 require.False(t, exists) 223 itr, err := provider.leveldbProvider.GetDBHandle("ledger1").GetIterator(nil, nil) 224 require.NoError(t, err) 225 defer itr.Release() 226 require.False(t, itr.Next()) 227 228 // verify ledger2 ledger data are remained same 229 checkBlocks(t, blocks2, store2) 230 storeNames, err = provider.List() 231 require.NoError(t, err) 232 require.ElementsMatch(t, storeNames, []string{"ledger2"}) 233 234 // remove again should return no error 235 require.NoError(t, provider.Remove("ledger1")) 236 237 // verify "ledger1" store can be opened again after remove, but it is an empty store 238 newstore1, err := provider.Open("ledger1") 239 require.NoError(t, err) 240 bcInfo, err := newstore1.GetBlockchainInfo() 241 require.NoError(t, err) 242 require.Equal(t, &common.BlockchainInfo{}, bcInfo) 243 244 // negative test 245 provider.Close() 246 require.EqualError(t, provider.Remove("ledger2"), "internal leveldb error while obtaining db iterator: leveldb: closed") 247 } 248 249 func constructLedgerid(id int) string { 250 return fmt.Sprintf("ledger_%d", id) 251 }