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