github.com/ewagmig/fabric@v2.1.1+incompatible/core/ledger/kvledger/kv_ledger_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 kvledger
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  	"testing"
    15  
    16  	"github.com/golang/protobuf/proto"
    17  	"github.com/hyperledger/fabric-protos-go/common"
    18  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    19  	"github.com/hyperledger/fabric-protos-go/peer"
    20  	"github.com/hyperledger/fabric/bccsp/sw"
    21  	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
    22  	"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
    23  	"github.com/hyperledger/fabric/common/ledger/dataformat"
    24  	"github.com/hyperledger/fabric/common/ledger/testutil"
    25  	"github.com/hyperledger/fabric/common/metrics/disabled"
    26  	"github.com/hyperledger/fabric/common/util"
    27  	"github.com/hyperledger/fabric/core/ledger"
    28  	lgr "github.com/hyperledger/fabric/core/ledger"
    29  	"github.com/hyperledger/fabric/core/ledger/kvledger/msgs"
    30  	"github.com/hyperledger/fabric/core/ledger/mock"
    31  	"github.com/hyperledger/fabric/protoutil"
    32  	"github.com/stretchr/testify/assert"
    33  	"github.com/stretchr/testify/require"
    34  )
    35  
    36  func TestLedgerProvider(t *testing.T) {
    37  	conf, cleanup := testConfig(t)
    38  	defer cleanup()
    39  	provider := testutilNewProvider(conf, t)
    40  	numLedgers := 10
    41  	existingLedgerIDs, err := provider.List()
    42  	assert.NoError(t, err)
    43  	assert.Len(t, existingLedgerIDs, 0)
    44  	genesisBlocks := make([]*common.Block, numLedgers)
    45  	for i := 0; i < numLedgers; i++ {
    46  		genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i))
    47  		genesisBlocks[i] = genesisBlock
    48  		provider.Create(genesisBlock)
    49  	}
    50  	existingLedgerIDs, err = provider.List()
    51  	assert.NoError(t, err)
    52  	assert.Len(t, existingLedgerIDs, numLedgers)
    53  
    54  	// verify formatKey is present in idStore
    55  	s := provider.idStore
    56  	val, err := s.db.Get(formatKey)
    57  	require.NoError(t, err)
    58  	require.Equal(t, []byte(dataformat.Version20), val)
    59  
    60  	provider.Close()
    61  
    62  	provider = testutilNewProvider(conf, t)
    63  	defer provider.Close()
    64  	ledgerIds, _ := provider.List()
    65  	assert.Len(t, ledgerIds, numLedgers)
    66  	for i := 0; i < numLedgers; i++ {
    67  		assert.Equal(t, constructTestLedgerID(i), ledgerIds[i])
    68  	}
    69  	for i := 0; i < numLedgers; i++ {
    70  		ledgerid := constructTestLedgerID(i)
    71  		status, _ := provider.Exists(ledgerid)
    72  		assert.True(t, status)
    73  		ledger, err := provider.Open(ledgerid)
    74  		assert.NoError(t, err)
    75  		bcInfo, err := ledger.GetBlockchainInfo()
    76  		ledger.Close()
    77  		assert.NoError(t, err)
    78  		assert.Equal(t, uint64(1), bcInfo.Height)
    79  
    80  		// check that the genesis block was persisted in the provider's db
    81  		s := provider.idStore
    82  		gbBytesInProviderStore, err := s.db.Get(s.encodeLedgerKey(ledgerid, ledgerKeyPrefix))
    83  		assert.NoError(t, err)
    84  		gb := &common.Block{}
    85  		assert.NoError(t, proto.Unmarshal(gbBytesInProviderStore, gb))
    86  		assert.True(t, proto.Equal(gb, genesisBlocks[i]), "proto messages are not equal")
    87  
    88  		// check that ledger metadata keys were persisted in idStore with active status
    89  		val, err := s.db.Get(s.encodeLedgerKey(ledgerid, metadataKeyPrefix))
    90  		require.NoError(t, err)
    91  		metadata := &msgs.LedgerMetadata{}
    92  		require.NoError(t, proto.Unmarshal(val, metadata))
    93  		require.Equal(t, msgs.Status_ACTIVE, metadata.Status)
    94  	}
    95  	gb, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(2))
    96  	_, err = provider.Create(gb)
    97  	assert.Equal(t, ErrLedgerIDExists, err)
    98  
    99  	status, err := provider.Exists(constructTestLedgerID(numLedgers))
   100  	assert.NoError(t, err, "Failed to check for ledger existence")
   101  	assert.Equal(t, status, false)
   102  
   103  	_, err = provider.Open(constructTestLedgerID(numLedgers))
   104  	assert.Equal(t, ErrNonExistingLedgerID, err)
   105  }
   106  
   107  func TestGetActiveLedgerIDsIteratorError(t *testing.T) {
   108  	conf, cleanup := testConfig(t)
   109  	defer cleanup()
   110  	provider := testutilNewProvider(conf, t)
   111  
   112  	for i := 0; i < 2; i++ {
   113  		genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i))
   114  		provider.Create(genesisBlock)
   115  	}
   116  
   117  	// close provider to trigger db error
   118  	provider.Close()
   119  	_, err := provider.idStore.getActiveLedgerIDs()
   120  	require.EqualError(t, err, "error getting ledger ids from idStore: leveldb: closed")
   121  }
   122  
   123  func TestLedgerMetataDataUnmarshalError(t *testing.T) {
   124  	conf, cleanup := testConfig(t)
   125  	defer cleanup()
   126  	provider := testutilNewProvider(conf, t)
   127  	defer provider.Close()
   128  
   129  	ledgerID := constructTestLedgerID(0)
   130  	genesisBlock, _ := configtxtest.MakeGenesisBlock(ledgerID)
   131  	provider.Create(genesisBlock)
   132  
   133  	// put invalid bytes for the metatdata key
   134  	provider.idStore.db.Put(provider.idStore.encodeLedgerKey(ledgerID, metadataKeyPrefix), []byte("invalid"), true)
   135  
   136  	_, err := provider.List()
   137  	require.EqualError(t, err, "error unmarshalling ledger metadata: unexpected EOF")
   138  
   139  	_, err = provider.Open(ledgerID)
   140  	require.EqualError(t, err, "error unmarshalling ledger metadata: unexpected EOF")
   141  }
   142  
   143  func TestNewProviderIdStoreFormatError(t *testing.T) {
   144  	conf, cleanup := testConfig(t)
   145  	defer cleanup()
   146  
   147  	require.NoError(t, testutil.Unzip("tests/testdata/v11/sample_ledgers/ledgersData.zip", conf.RootFSPath, false))
   148  
   149  	// NewProvider fails because ledgerProvider (idStore) has old format
   150  	_, err := NewProvider(
   151  		&lgr.Initializer{
   152  			DeployedChaincodeInfoProvider: &mock.DeployedChaincodeInfoProvider{},
   153  			MetricsProvider:               &disabled.Provider{},
   154  			Config:                        conf,
   155  		},
   156  	)
   157  	require.EqualError(t, err, fmt.Sprintf("unexpected format. db info = [leveldb for channel-IDs at [%s]], data format = [], expected format = [2.0]", LedgerProviderPath(conf.RootFSPath)))
   158  }
   159  
   160  func TestUpgradeIDStoreFormatDBError(t *testing.T) {
   161  	conf, cleanup := testConfig(t)
   162  	defer cleanup()
   163  	provider := testutilNewProvider(conf, t)
   164  	provider.Close()
   165  
   166  	err := provider.idStore.upgradeFormat()
   167  	require.EqualError(t, err, "error retrieving leveldb key [[]byte{0x66}]: leveldb: closed")
   168  }
   169  
   170  func TestLedgerProviderHistoryDBDisabled(t *testing.T) {
   171  	conf, cleanup := testConfig(t)
   172  	conf.HistoryDBConfig.Enabled = false
   173  	defer cleanup()
   174  	provider := testutilNewProvider(conf, t)
   175  	numLedgers := 10
   176  	existingLedgerIDs, err := provider.List()
   177  	assert.NoError(t, err)
   178  	assert.Len(t, existingLedgerIDs, 0)
   179  	genesisBlocks := make([]*common.Block, numLedgers)
   180  	for i := 0; i < numLedgers; i++ {
   181  		genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i))
   182  		genesisBlocks[i] = genesisBlock
   183  		provider.Create(genesisBlock)
   184  	}
   185  	existingLedgerIDs, err = provider.List()
   186  	assert.NoError(t, err)
   187  	assert.Len(t, existingLedgerIDs, numLedgers)
   188  
   189  	provider.Close()
   190  
   191  	provider = testutilNewProvider(conf, t)
   192  	defer provider.Close()
   193  	ledgerIds, _ := provider.List()
   194  	assert.Len(t, ledgerIds, numLedgers)
   195  	t.Logf("ledgerIDs=%#v", ledgerIds)
   196  	for i := 0; i < numLedgers; i++ {
   197  		assert.Equal(t, constructTestLedgerID(i), ledgerIds[i])
   198  	}
   199  	for i := 0; i < numLedgers; i++ {
   200  		ledgerid := constructTestLedgerID(i)
   201  		status, _ := provider.Exists(ledgerid)
   202  		assert.True(t, status)
   203  		ledger, err := provider.Open(ledgerid)
   204  		assert.NoError(t, err)
   205  		bcInfo, err := ledger.GetBlockchainInfo()
   206  		ledger.Close()
   207  		assert.NoError(t, err)
   208  		assert.Equal(t, uint64(1), bcInfo.Height)
   209  
   210  		// check that the genesis block was persisted in the provider's db
   211  		s := provider.idStore
   212  		gbBytesInProviderStore, err := s.db.Get(s.encodeLedgerKey(ledgerid, ledgerKeyPrefix))
   213  		assert.NoError(t, err)
   214  		gb := &common.Block{}
   215  		assert.NoError(t, proto.Unmarshal(gbBytesInProviderStore, gb))
   216  		assert.True(t, proto.Equal(gb, genesisBlocks[i]), "proto messages are not equal")
   217  	}
   218  	gb, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(2))
   219  	_, err = provider.Create(gb)
   220  	assert.Equal(t, ErrLedgerIDExists, err)
   221  
   222  	status, err := provider.Exists(constructTestLedgerID(numLedgers))
   223  	assert.NoError(t, err, "Failed to check for ledger existence")
   224  	assert.Equal(t, status, false)
   225  
   226  	_, err = provider.Open(constructTestLedgerID(numLedgers))
   227  	assert.Equal(t, ErrNonExistingLedgerID, err)
   228  
   229  }
   230  
   231  func TestRecovery(t *testing.T) {
   232  	conf, cleanup := testConfig(t)
   233  	defer cleanup()
   234  	provider1 := testutilNewProvider(conf, t)
   235  	defer provider1.Close()
   236  
   237  	// now create the genesis block
   238  	genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(1))
   239  	ledger, err := provider1.openInternal(constructTestLedgerID(1))
   240  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: genesisBlock}, &lgr.CommitOptions{})
   241  	ledger.Close()
   242  
   243  	// Case 1: assume a crash happens, force underconstruction flag to be set to simulate
   244  	// a failure where ledgerid is being created - ie., block is written but flag is not unset
   245  	provider1.idStore.setUnderConstructionFlag(constructTestLedgerID(1))
   246  	provider1.Close()
   247  
   248  	// construct a new provider1 to invoke recovery
   249  	provider1 = testutilNewProvider(conf, t)
   250  	// verify the underecoveryflag and open the ledger
   251  	flag, err := provider1.idStore.getUnderConstructionFlag()
   252  	assert.NoError(t, err, "Failed to read the underconstruction flag")
   253  	assert.Equal(t, "", flag)
   254  	ledger, err = provider1.Open(constructTestLedgerID(1))
   255  	assert.NoError(t, err, "Failed to open the ledger")
   256  	ledger.Close()
   257  
   258  	// Case 0: assume a crash happens before the genesis block of ledger 2 is committed
   259  	// Open the ID store (inventory of chainIds/ledgerIds)
   260  	provider1.idStore.setUnderConstructionFlag(constructTestLedgerID(2))
   261  	provider1.Close()
   262  
   263  	// construct a new provider to invoke recovery
   264  	provider2 := testutilNewProvider(conf, t)
   265  	defer provider2.Close()
   266  	assert.NoError(t, err, "Provider failed to recover an underConstructionLedger")
   267  	flag, err = provider2.idStore.getUnderConstructionFlag()
   268  	assert.NoError(t, err, "Failed to read the underconstruction flag")
   269  	assert.Equal(t, "", flag)
   270  }
   271  
   272  func TestRecoveryHistoryDBDisabled(t *testing.T) {
   273  	conf, cleanup := testConfig(t)
   274  	conf.HistoryDBConfig.Enabled = false
   275  	defer cleanup()
   276  	provider1 := testutilNewProvider(conf, t)
   277  	defer provider1.Close()
   278  
   279  	// now create the genesis block
   280  	genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(1))
   281  	ledger, err := provider1.openInternal(constructTestLedgerID(1))
   282  	assert.NoError(t, err, "Failed to open the ledger")
   283  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: genesisBlock}, &lgr.CommitOptions{})
   284  	ledger.Close()
   285  
   286  	// Case 1: assume a crash happens, force underconstruction flag to be set to simulate
   287  	// a failure where ledgerid is being created - ie., block is written but flag is not unset
   288  	provider1.idStore.setUnderConstructionFlag(constructTestLedgerID(1))
   289  	provider1.Close()
   290  
   291  	// construct a new provider to invoke recovery
   292  	provider2 := testutilNewProvider(conf, t)
   293  	defer provider2.Close()
   294  	// verify the underecoveryflag and open the ledger
   295  	flag, err := provider2.idStore.getUnderConstructionFlag()
   296  	assert.NoError(t, err, "Failed to read the underconstruction flag")
   297  	assert.Equal(t, "", flag)
   298  	ledger, err = provider2.Open(constructTestLedgerID(1))
   299  	assert.NoError(t, err, "Failed to open the ledger")
   300  	ledger.Close()
   301  
   302  	// Case 0: assume a crash happens before the genesis block of ledger 2 is committed
   303  	// Open the ID store (inventory of chainIds/ledgerIds)
   304  	provider2.idStore.setUnderConstructionFlag(constructTestLedgerID(2))
   305  	provider2.Close()
   306  
   307  	// construct a new provider to invoke recovery
   308  	provider3 := testutilNewProvider(conf, t)
   309  	defer provider3.Close()
   310  	assert.NoError(t, err, "Provider failed to recover an underConstructionLedger")
   311  	flag, err = provider3.idStore.getUnderConstructionFlag()
   312  	assert.NoError(t, err, "Failed to read the underconstruction flag")
   313  	assert.Equal(t, "", flag)
   314  }
   315  
   316  func TestMultipleLedgerBasicRW(t *testing.T) {
   317  	conf, cleanup := testConfig(t)
   318  	defer cleanup()
   319  	provider1 := testutilNewProvider(conf, t)
   320  	defer provider1.Close()
   321  
   322  	numLedgers := 10
   323  	ledgers := make([]lgr.PeerLedger, numLedgers)
   324  	for i := 0; i < numLedgers; i++ {
   325  		bg, gb := testutil.NewBlockGenerator(t, constructTestLedgerID(i), false)
   326  		l, err := provider1.Create(gb)
   327  		assert.NoError(t, err)
   328  		ledgers[i] = l
   329  		txid := util.GenerateUUID()
   330  		s, _ := l.NewTxSimulator(txid)
   331  		err = s.SetState("ns", "testKey", []byte(fmt.Sprintf("testValue_%d", i)))
   332  		s.Done()
   333  		assert.NoError(t, err)
   334  		res, err := s.GetTxSimulationResults()
   335  		assert.NoError(t, err)
   336  		pubSimBytes, _ := res.GetPubSimulationBytes()
   337  		b := bg.NextBlock([][]byte{pubSimBytes})
   338  		err = l.CommitLegacy(&lgr.BlockAndPvtData{Block: b}, &ledger.CommitOptions{})
   339  		l.Close()
   340  		assert.NoError(t, err)
   341  	}
   342  
   343  	provider1.Close()
   344  
   345  	provider2 := testutilNewProvider(conf, t)
   346  	defer provider2.Close()
   347  	ledgers = make([]lgr.PeerLedger, numLedgers)
   348  	for i := 0; i < numLedgers; i++ {
   349  		l, err := provider2.Open(constructTestLedgerID(i))
   350  		assert.NoError(t, err)
   351  		ledgers[i] = l
   352  	}
   353  
   354  	for i, l := range ledgers {
   355  		q, _ := l.NewQueryExecutor()
   356  		val, err := q.GetState("ns", "testKey")
   357  		q.Done()
   358  		assert.NoError(t, err)
   359  		assert.Equal(t, []byte(fmt.Sprintf("testValue_%d", i)), val)
   360  		l.Close()
   361  	}
   362  }
   363  
   364  func TestLedgerBackup(t *testing.T) {
   365  	ledgerid := "TestLedger"
   366  	basePath, err := ioutil.TempDir("", "kvledger")
   367  	require.NoError(t, err, "Failed to create ledger directory")
   368  	defer os.RemoveAll(basePath)
   369  	originalPath := filepath.Join(basePath, "kvledger1")
   370  	restorePath := filepath.Join(basePath, "kvledger2")
   371  
   372  	// create and populate a ledger in the original environment
   373  	origConf := &lgr.Config{
   374  		RootFSPath:    originalPath,
   375  		StateDBConfig: &lgr.StateDBConfig{},
   376  		PrivateDataConfig: &lgr.PrivateDataConfig{
   377  			MaxBatchSize:    5000,
   378  			BatchesInterval: 1000,
   379  			PurgeInterval:   100,
   380  		},
   381  		HistoryDBConfig: &lgr.HistoryDBConfig{
   382  			Enabled: true,
   383  		},
   384  	}
   385  	provider := testutilNewProvider(origConf, t)
   386  	bg, gb := testutil.NewBlockGenerator(t, ledgerid, false)
   387  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   388  	ledger, _ := provider.Create(gb)
   389  
   390  	txid := util.GenerateUUID()
   391  	simulator, _ := ledger.NewTxSimulator(txid)
   392  	simulator.SetState("ns1", "key1", []byte("value1"))
   393  	simulator.SetState("ns1", "key2", []byte("value2"))
   394  	simulator.SetState("ns1", "key3", []byte("value3"))
   395  	simulator.Done()
   396  	simRes, _ := simulator.GetTxSimulationResults()
   397  	pubSimBytes, _ := simRes.GetPubSimulationBytes()
   398  	block1 := bg.NextBlock([][]byte{pubSimBytes})
   399  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block1}, &lgr.CommitOptions{})
   400  
   401  	txid = util.GenerateUUID()
   402  	simulator, _ = ledger.NewTxSimulator(txid)
   403  	simulator.SetState("ns1", "key1", []byte("value4"))
   404  	simulator.SetState("ns1", "key2", []byte("value5"))
   405  	simulator.SetState("ns1", "key3", []byte("value6"))
   406  	simulator.Done()
   407  	simRes, _ = simulator.GetTxSimulationResults()
   408  	pubSimBytes, _ = simRes.GetPubSimulationBytes()
   409  	block2 := bg.NextBlock([][]byte{pubSimBytes})
   410  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block2}, &lgr.CommitOptions{})
   411  
   412  	ledger.Close()
   413  	provider.Close()
   414  
   415  	// remove the statedb, historydb, and block indexes (they are supposed to be auto created during opening of an existing ledger)
   416  	// and rename the originalPath to restorePath
   417  	assert.NoError(t, os.RemoveAll(StateDBPath(originalPath)))
   418  	assert.NoError(t, os.RemoveAll(HistoryDBPath(originalPath)))
   419  	assert.NoError(t, os.RemoveAll(filepath.Join(BlockStorePath(originalPath), fsblkstorage.IndexDir)))
   420  	assert.NoError(t, os.Rename(originalPath, restorePath))
   421  
   422  	// Instantiate the ledger from restore environment and this should behave exactly as it would have in the original environment
   423  	restoreConf := &lgr.Config{
   424  		RootFSPath:    restorePath,
   425  		StateDBConfig: &lgr.StateDBConfig{},
   426  		PrivateDataConfig: &lgr.PrivateDataConfig{
   427  			MaxBatchSize:    5000,
   428  			BatchesInterval: 1000,
   429  			PurgeInterval:   100,
   430  		},
   431  		HistoryDBConfig: &lgr.HistoryDBConfig{
   432  			Enabled: true,
   433  		},
   434  	}
   435  	provider = testutilNewProvider(restoreConf, t)
   436  	defer provider.Close()
   437  
   438  	_, err = provider.Create(gb)
   439  	assert.Equal(t, ErrLedgerIDExists, err)
   440  
   441  	ledger, _ = provider.Open(ledgerid)
   442  	defer ledger.Close()
   443  
   444  	block1Hash := protoutil.BlockHeaderHash(block1.Header)
   445  	block2Hash := protoutil.BlockHeaderHash(block2.Header)
   446  	bcInfo, _ := ledger.GetBlockchainInfo()
   447  	assert.Equal(t, &common.BlockchainInfo{
   448  		Height: 3, CurrentBlockHash: block2Hash, PreviousBlockHash: block1Hash,
   449  	}, bcInfo)
   450  
   451  	b0, _ := ledger.GetBlockByHash(gbHash)
   452  	assert.True(t, proto.Equal(b0, gb), "proto messages are not equal")
   453  
   454  	b1, _ := ledger.GetBlockByHash(block1Hash)
   455  	assert.True(t, proto.Equal(b1, block1), "proto messages are not equal")
   456  
   457  	b2, _ := ledger.GetBlockByHash(block2Hash)
   458  	assert.True(t, proto.Equal(b2, block2), "proto messages are not equal")
   459  
   460  	b0, _ = ledger.GetBlockByNumber(0)
   461  	assert.True(t, proto.Equal(b0, gb), "proto messages are not equal")
   462  
   463  	b1, _ = ledger.GetBlockByNumber(1)
   464  	assert.True(t, proto.Equal(b1, block1), "proto messages are not equal")
   465  
   466  	b2, _ = ledger.GetBlockByNumber(2)
   467  	assert.True(t, proto.Equal(b2, block2), "proto messages are not equal")
   468  
   469  	// get the tran id from the 2nd block, then use it to test GetTransactionByID()
   470  	txEnvBytes2 := block1.Data.Data[0]
   471  	txEnv2, err := protoutil.GetEnvelopeFromBlock(txEnvBytes2)
   472  	assert.NoError(t, err, "Error upon GetEnvelopeFromBlock")
   473  	payload2, err := protoutil.UnmarshalPayload(txEnv2.Payload)
   474  	assert.NoError(t, err, "Error upon GetPayload")
   475  	chdr, err := protoutil.UnmarshalChannelHeader(payload2.Header.ChannelHeader)
   476  	assert.NoError(t, err, "Error upon GetChannelHeaderFromBytes")
   477  	txID2 := chdr.TxId
   478  	processedTran2, err := ledger.GetTransactionByID(txID2)
   479  	assert.NoError(t, err, "Error upon GetTransactionByID")
   480  	// get the tran envelope from the retrieved ProcessedTransaction
   481  	retrievedTxEnv2 := processedTran2.TransactionEnvelope
   482  	assert.Equal(t, txEnv2, retrievedTxEnv2)
   483  
   484  	qe, _ := ledger.NewQueryExecutor()
   485  	value1, _ := qe.GetState("ns1", "key1")
   486  	assert.Equal(t, []byte("value4"), value1)
   487  
   488  	hqe, err := ledger.NewHistoryQueryExecutor()
   489  	assert.NoError(t, err)
   490  	itr, err := hqe.GetHistoryForKey("ns1", "key1")
   491  	assert.NoError(t, err)
   492  	defer itr.Close()
   493  
   494  	result1, err := itr.Next()
   495  	assert.NoError(t, err)
   496  	assert.Equal(t, []byte("value4"), result1.(*queryresult.KeyModification).Value)
   497  	result2, err := itr.Next()
   498  	assert.NoError(t, err)
   499  	assert.Equal(t, []byte("value1"), result2.(*queryresult.KeyModification).Value)
   500  }
   501  
   502  func constructTestLedgerID(i int) string {
   503  	return fmt.Sprintf("ledger_%06d", i)
   504  }
   505  
   506  func testConfig(t *testing.T) (conf *lgr.Config, cleanup func()) {
   507  	path, err := ioutil.TempDir("", "kvledger")
   508  	require.NoError(t, err, "Failed to create test ledger directory")
   509  	conf = &lgr.Config{
   510  		RootFSPath:    path,
   511  		StateDBConfig: &lgr.StateDBConfig{},
   512  		PrivateDataConfig: &lgr.PrivateDataConfig{
   513  			MaxBatchSize:    5000,
   514  			BatchesInterval: 1000,
   515  			PurgeInterval:   100,
   516  		},
   517  		HistoryDBConfig: &lgr.HistoryDBConfig{
   518  			Enabled: true,
   519  		},
   520  	}
   521  	cleanup = func() {
   522  		os.RemoveAll(path)
   523  	}
   524  
   525  	return conf, cleanup
   526  }
   527  
   528  func testutilNewProvider(conf *lgr.Config, t *testing.T) *Provider {
   529  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   530  	assert.NoError(t, err)
   531  
   532  	provider, err := NewProvider(
   533  		&lgr.Initializer{
   534  			DeployedChaincodeInfoProvider: &mock.DeployedChaincodeInfoProvider{},
   535  			MetricsProvider:               &disabled.Provider{},
   536  			Config:                        conf,
   537  			Hasher:                        cryptoProvider,
   538  		},
   539  	)
   540  	require.NoError(t, err, "Failed to create new Provider")
   541  	return provider
   542  }
   543  
   544  func testutilNewProviderWithCollectionConfig(
   545  	t *testing.T,
   546  	namespace string,
   547  	btlConfigs map[string]uint64,
   548  	conf *lgr.Config,
   549  ) *Provider {
   550  	provider := testutilNewProvider(conf, t)
   551  	mockCCInfoProvider := provider.initializer.DeployedChaincodeInfoProvider.(*mock.DeployedChaincodeInfoProvider)
   552  	collMap := map[string]*peer.StaticCollectionConfig{}
   553  	var collConf []*peer.CollectionConfig
   554  	for collName, btl := range btlConfigs {
   555  		staticConf := &peer.StaticCollectionConfig{Name: collName, BlockToLive: btl}
   556  		collMap[collName] = staticConf
   557  		collectionConf := &peer.CollectionConfig{}
   558  		collectionConf.Payload = &peer.CollectionConfig_StaticCollectionConfig{StaticCollectionConfig: staticConf}
   559  		collConf = append(collConf, collectionConf)
   560  	}
   561  	collectionConfPkg := &peer.CollectionConfigPackage{Config: collConf}
   562  
   563  	mockCCInfoProvider.ChaincodeInfoStub = func(channelName, ccName string, qe lgr.SimpleQueryExecutor) (*lgr.DeployedChaincodeInfo, error) {
   564  		if ccName == namespace {
   565  			return &lgr.DeployedChaincodeInfo{
   566  				Name: namespace, ExplicitCollectionConfigPkg: collectionConfPkg}, nil
   567  		}
   568  		return nil, nil
   569  	}
   570  
   571  	mockCCInfoProvider.AllCollectionsConfigPkgStub = func(channelName, ccName string, qe lgr.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) {
   572  		if ccName == namespace {
   573  			return collectionConfPkg, nil
   574  		}
   575  		return nil, nil
   576  	}
   577  
   578  	mockCCInfoProvider.CollectionInfoStub = func(channelName, ccName, collName string, qe lgr.SimpleQueryExecutor) (*peer.StaticCollectionConfig, error) {
   579  		if ccName == namespace {
   580  			return collMap[collName], nil
   581  		}
   582  		return nil, nil
   583  	}
   584  	return provider
   585  }