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  }