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  }