github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/blkstorage/pkg_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package blkstorage 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "math" 13 "os" 14 "testing" 15 16 "github.com/golang/protobuf/proto" 17 "github.com/hechain20/hechain/common/flogging" 18 "github.com/hechain20/hechain/common/metrics" 19 "github.com/hechain20/hechain/common/metrics/disabled" 20 "github.com/hechain20/hechain/protoutil" 21 "github.com/hyperledger/fabric-protos-go/common" 22 "github.com/hyperledger/fabric-protos-go/peer" 23 "github.com/stretchr/testify/require" 24 ) 25 26 func TestMain(m *testing.M) { 27 flogging.ActivateSpec("blkstorage=debug") 28 os.Exit(m.Run()) 29 } 30 31 func testPath() string { 32 if path, err := ioutil.TempDir("", "blkstorage-"); err != nil { 33 panic(err) 34 } else { 35 return path 36 } 37 } 38 39 type testEnv struct { 40 t testing.TB 41 provider *BlockStoreProvider 42 } 43 44 var attrsToIndex = []IndexableAttr{ 45 IndexableAttrBlockHash, 46 IndexableAttrBlockNum, 47 IndexableAttrTxID, 48 IndexableAttrBlockNumTranNum, 49 } 50 51 func newTestEnv(t testing.TB, conf *Conf) *testEnv { 52 return newTestEnvWithMetricsProvider(t, conf, &disabled.Provider{}) 53 } 54 55 func newTestEnvWithMetricsProvider(t testing.TB, conf *Conf, metricsProvider metrics.Provider) *testEnv { 56 return newTestEnvSelectiveIndexing(t, conf, attrsToIndex, metricsProvider) 57 } 58 59 func newTestEnvSelectiveIndexing(t testing.TB, conf *Conf, attrsToIndex []IndexableAttr, metricsProvider metrics.Provider) *testEnv { 60 indexConfig := &IndexConfig{AttrsToIndex: attrsToIndex} 61 p, err := NewProvider(conf, indexConfig, metricsProvider) 62 require.NoError(t, err) 63 return &testEnv{t, p} 64 } 65 66 func (env *testEnv) Cleanup() { 67 env.provider.Close() 68 env.removeFSPath() 69 } 70 71 func (env *testEnv) removeFSPath() { 72 fsPath := env.provider.conf.blockStorageDir 73 os.RemoveAll(fsPath) 74 } 75 76 type testBlockfileMgrWrapper struct { 77 t testing.TB 78 blockfileMgr *blockfileMgr 79 } 80 81 func newTestBlockfileWrapper(env *testEnv, ledgerid string) *testBlockfileMgrWrapper { 82 blkStore, err := env.provider.Open(ledgerid) 83 require.NoError(env.t, err) 84 return &testBlockfileMgrWrapper{env.t, blkStore.fileMgr} 85 } 86 87 func (w *testBlockfileMgrWrapper) addBlocks(blocks []*common.Block) { 88 for _, blk := range blocks { 89 err := w.blockfileMgr.addBlock(blk) 90 require.NoError(w.t, err, "Error while adding block to blockfileMgr") 91 } 92 } 93 94 func (w *testBlockfileMgrWrapper) testGetBlockByHash(blocks []*common.Block) { 95 for i, block := range blocks { 96 hash := protoutil.BlockHeaderHash(block.Header) 97 b, err := w.blockfileMgr.retrieveBlockByHash(hash) 98 require.NoError(w.t, err, "Error while retrieving [%d]th block from blockfileMgr", i) 99 require.Equal(w.t, block, b) 100 } 101 } 102 103 func (w *testBlockfileMgrWrapper) testGetBlockByNumber(blocks []*common.Block) { 104 for i := 0; i < len(blocks); i++ { 105 b, err := w.blockfileMgr.retrieveBlockByNumber(blocks[0].Header.Number + uint64(i)) 106 require.NoError(w.t, err, "Error while retrieving [%d]th block from blockfileMgr", i) 107 require.Equal(w.t, blocks[i], b) 108 } 109 // test getting the last block 110 b, err := w.blockfileMgr.retrieveBlockByNumber(math.MaxUint64) 111 iLastBlock := len(blocks) - 1 112 require.NoError(w.t, err, "Error while retrieving last block from blockfileMgr") 113 require.Equal(w.t, blocks[iLastBlock], b) 114 } 115 116 func (w *testBlockfileMgrWrapper) testGetBlockByTxID(blocks []*common.Block) { 117 for i, block := range blocks { 118 for _, txEnv := range block.Data.Data { 119 txID, err := protoutil.GetOrComputeTxIDFromEnvelope(txEnv) 120 require.NoError(w.t, err) 121 b, err := w.blockfileMgr.retrieveBlockByTxID(txID) 122 require.NoError(w.t, err, "Error while retrieving [%d]th block from blockfileMgr", i) 123 require.Equal(w.t, block, b) 124 } 125 } 126 } 127 128 func (w *testBlockfileMgrWrapper) testGetBlockByHashNotIndexed(blocks []*common.Block) { 129 for _, block := range blocks { 130 hash := protoutil.BlockHeaderHash(block.Header) 131 _, err := w.blockfileMgr.retrieveBlockByHash(hash) 132 require.EqualError(w.t, err, fmt.Sprintf("no such block hash [%x] in index", hash)) 133 } 134 } 135 136 func (w *testBlockfileMgrWrapper) testGetBlockByTxIDNotIndexed(blocks []*common.Block) { 137 for _, block := range blocks { 138 for _, txEnv := range block.Data.Data { 139 txID, err := protoutil.GetOrComputeTxIDFromEnvelope(txEnv) 140 require.NoError(w.t, err) 141 _, err = w.blockfileMgr.retrieveBlockByTxID(txID) 142 require.EqualError(w.t, err, fmt.Sprintf("no such transaction ID [%s] in index", txID)) 143 } 144 } 145 } 146 147 func (w *testBlockfileMgrWrapper) testGetTransactionByTxID(txID string, expectedEnvelope []byte, expectedErr error) { 148 envelope, err := w.blockfileMgr.retrieveTransactionByID(txID) 149 if expectedErr != nil { 150 require.Equal(w.t, err.Error(), expectedErr.Error()) 151 return 152 } 153 actualEnvelope, err := proto.Marshal(envelope) 154 require.NoError(w.t, err) 155 require.Equal(w.t, expectedEnvelope, actualEnvelope) 156 } 157 158 func (w *testBlockfileMgrWrapper) testGetMultipleDataByTxID( 159 txID string, 160 expectedData []*expectedBlkTxValidationCode, 161 ) { 162 rangescan := constructTxIDRangeScan(txID) 163 itr, err := w.blockfileMgr.db.GetIterator(rangescan.startKey, rangescan.stopKey) 164 require := require.New(w.t) 165 require.NoError(err) 166 defer itr.Release() 167 168 fetchedData := []*expectedBlkTxValidationCode{} 169 for itr.Next() { 170 v := &TxIDIndexValue{} 171 require.NoError(proto.Unmarshal(itr.Value(), v)) 172 173 blkFLP := &fileLocPointer{} 174 require.NoError(blkFLP.unmarshal(v.BlkLocation)) 175 blk, err := w.blockfileMgr.fetchBlock(blkFLP) 176 require.NoError(err) 177 178 txFLP := &fileLocPointer{} 179 require.NoError(txFLP.unmarshal(v.TxLocation)) 180 txEnv, err := w.blockfileMgr.fetchTransactionEnvelope(txFLP) 181 require.NoError(err) 182 183 fetchedData = append(fetchedData, &expectedBlkTxValidationCode{ 184 blk: blk, 185 txEnv: txEnv, 186 validationCode: peer.TxValidationCode(v.TxValidationCode), 187 }) 188 } 189 require.Equal(expectedData, fetchedData) 190 } 191 192 func (w *testBlockfileMgrWrapper) close() { 193 w.blockfileMgr.close() 194 } 195 196 type expectedBlkTxValidationCode struct { 197 blk *common.Block 198 txEnv *common.Envelope 199 validationCode peer.TxValidationCode 200 }