github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/ledger/kvledger/kv_ledger_provider_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package kvledger
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  
    25  	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
    26  	"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
    27  	"github.com/hyperledger/fabric/common/ledger/testutil"
    28  	"github.com/hyperledger/fabric/core/ledger"
    29  	"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
    30  	"github.com/hyperledger/fabric/protos/common"
    31  	"github.com/hyperledger/fabric/protos/ledger/queryresult"
    32  	putils "github.com/hyperledger/fabric/protos/utils"
    33  	"github.com/spf13/viper"
    34  )
    35  
    36  func TestLedgerProvider(t *testing.T) {
    37  	env := newTestEnv(t)
    38  	defer env.cleanup()
    39  	numLedgers := 10
    40  	provider, _ := NewProvider()
    41  	existingLedgerIDs, err := provider.List()
    42  	testutil.AssertNoError(t, err, "")
    43  	testutil.AssertEquals(t, len(existingLedgerIDs), 0)
    44  	for i := 0; i < numLedgers; i++ {
    45  		genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i))
    46  		provider.Create(genesisBlock)
    47  	}
    48  	existingLedgerIDs, err = provider.List()
    49  	testutil.AssertNoError(t, err, "")
    50  	testutil.AssertEquals(t, len(existingLedgerIDs), numLedgers)
    51  
    52  	provider.Close()
    53  
    54  	provider, _ = NewProvider()
    55  	defer provider.Close()
    56  	ledgerIds, _ := provider.List()
    57  	testutil.AssertEquals(t, len(ledgerIds), numLedgers)
    58  	t.Logf("ledgerIDs=%#v", ledgerIds)
    59  	for i := 0; i < numLedgers; i++ {
    60  		testutil.AssertEquals(t, ledgerIds[i], constructTestLedgerID(i))
    61  	}
    62  	for i := 0; i < numLedgers; i++ {
    63  		status, _ := provider.Exists(constructTestLedgerID(i))
    64  		testutil.AssertEquals(t, status, true)
    65  		ledger, err := provider.Open(constructTestLedgerID(i))
    66  		testutil.AssertNoError(t, err, "")
    67  		bcInfo, err := ledger.GetBlockchainInfo()
    68  		ledger.Close()
    69  		testutil.AssertNoError(t, err, "")
    70  		testutil.AssertEquals(t, bcInfo.Height, uint64(1))
    71  	}
    72  	gb, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(2))
    73  	_, err = provider.Create(gb)
    74  	testutil.AssertEquals(t, err, ErrLedgerIDExists)
    75  
    76  	status, err := provider.Exists(constructTestLedgerID(numLedgers))
    77  	testutil.AssertNoError(t, err, "Failed to check for ledger existence")
    78  	testutil.AssertEquals(t, false, status)
    79  
    80  	_, err = provider.Open(constructTestLedgerID(numLedgers))
    81  	testutil.AssertEquals(t, err, ErrNonExistingLedgerID)
    82  }
    83  
    84  func TestRecovery(t *testing.T) {
    85  	env := newTestEnv(t)
    86  	defer env.cleanup()
    87  	provider, _ := NewProvider()
    88  
    89  	// now create the genesis block
    90  	genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(1))
    91  	ledger, err := provider.(*Provider).openInternal(constructTestLedgerID(1))
    92  	ledger.Commit(genesisBlock)
    93  	ledger.Close()
    94  
    95  	// Case 1: assume a crash happens, force underconstruction flag to be set to simulate
    96  	// a failure where ledgerid is being created - ie., block is written but flag is not unset
    97  	provider.(*Provider).idStore.setUnderConstructionFlag(constructTestLedgerID(1))
    98  	provider.Close()
    99  
   100  	// construct a new provider to invoke recovery
   101  	provider, err = NewProvider()
   102  	testutil.AssertNoError(t, err, "Provider failed to recover an underConstructionLedger")
   103  	// verify the underecoveryflag and open the ledger
   104  	flag, err := provider.(*Provider).idStore.getUnderConstructionFlag()
   105  	testutil.AssertNoError(t, err, "Failed to read the underconstruction flag")
   106  	testutil.AssertEquals(t, flag, "")
   107  	ledger, err = provider.Open(constructTestLedgerID(1))
   108  	testutil.AssertNoError(t, err, "Failed to open the ledger")
   109  	ledger.Close()
   110  
   111  	// Case 0: assume a crash happens before the genesis block of ledger 2 is committed
   112  	// Open the ID store (inventory of chainIds/ledgerIds)
   113  	provider.(*Provider).idStore.setUnderConstructionFlag(constructTestLedgerID(2))
   114  	provider.Close()
   115  
   116  	// construct a new provider to invoke recovery
   117  	provider, err = NewProvider()
   118  	testutil.AssertNoError(t, err, "Provider failed to recover an underConstructionLedger")
   119  	flag, err = provider.(*Provider).idStore.getUnderConstructionFlag()
   120  	testutil.AssertNoError(t, err, "Failed to read the underconstruction flag")
   121  	testutil.AssertEquals(t, flag, "")
   122  
   123  }
   124  
   125  func TestMultipleLedgerBasicRW(t *testing.T) {
   126  	env := newTestEnv(t)
   127  	defer env.cleanup()
   128  	numLedgers := 10
   129  	provider, _ := NewProvider()
   130  	ledgers := make([]ledger.PeerLedger, numLedgers)
   131  	for i := 0; i < numLedgers; i++ {
   132  		bg, gb := testutil.NewBlockGenerator(t, constructTestLedgerID(i), false)
   133  		l, err := provider.Create(gb)
   134  		testutil.AssertNoError(t, err, "")
   135  		ledgers[i] = l
   136  		s, _ := l.NewTxSimulator()
   137  		err = s.SetState("ns", "testKey", []byte(fmt.Sprintf("testValue_%d", i)))
   138  		s.Done()
   139  		testutil.AssertNoError(t, err, "")
   140  		res, err := s.GetTxSimulationResults()
   141  		testutil.AssertNoError(t, err, "")
   142  		b := bg.NextBlock([][]byte{res})
   143  		err = l.Commit(b)
   144  		l.Close()
   145  		testutil.AssertNoError(t, err, "")
   146  	}
   147  
   148  	provider.Close()
   149  
   150  	provider, _ = NewProvider()
   151  	defer provider.Close()
   152  	ledgers = make([]ledger.PeerLedger, numLedgers)
   153  	for i := 0; i < numLedgers; i++ {
   154  		l, err := provider.Open(constructTestLedgerID(i))
   155  		testutil.AssertNoError(t, err, "")
   156  		ledgers[i] = l
   157  	}
   158  
   159  	for i, l := range ledgers {
   160  		q, _ := l.NewQueryExecutor()
   161  		val, err := q.GetState("ns", "testKey")
   162  		q.Done()
   163  		testutil.AssertNoError(t, err, "")
   164  		testutil.AssertEquals(t, val, []byte(fmt.Sprintf("testValue_%d", i)))
   165  		l.Close()
   166  	}
   167  }
   168  
   169  func TestLedgerBackup(t *testing.T) {
   170  	ledgerid := "TestLedger"
   171  	originalPath := "/tmp/fabric/ledgertests/kvledger1"
   172  	restorePath := "/tmp/fabric/ledgertests/kvledger2"
   173  	viper.Set("ledger.history.enableHistoryDatabase", true)
   174  
   175  	// create and populate a ledger in the original environment
   176  	env := createTestEnv(t, originalPath)
   177  	provider, _ := NewProvider()
   178  	bg, gb := testutil.NewBlockGenerator(t, ledgerid, false)
   179  	gbHash := gb.Header.Hash()
   180  	ledger, _ := provider.Create(gb)
   181  
   182  	simulator, _ := ledger.NewTxSimulator()
   183  	simulator.SetState("ns1", "key1", []byte("value1"))
   184  	simulator.SetState("ns1", "key2", []byte("value2"))
   185  	simulator.SetState("ns1", "key3", []byte("value3"))
   186  	simulator.Done()
   187  	simRes, _ := simulator.GetTxSimulationResults()
   188  	block1 := bg.NextBlock([][]byte{simRes})
   189  	ledger.Commit(block1)
   190  
   191  	simulator, _ = ledger.NewTxSimulator()
   192  	simulator.SetState("ns1", "key1", []byte("value4"))
   193  	simulator.SetState("ns1", "key2", []byte("value5"))
   194  	simulator.SetState("ns1", "key3", []byte("value6"))
   195  	simulator.Done()
   196  	simRes, _ = simulator.GetTxSimulationResults()
   197  	block2 := bg.NextBlock([][]byte{simRes})
   198  	ledger.Commit(block2)
   199  
   200  	ledger.Close()
   201  	provider.Close()
   202  
   203  	// Create restore environment
   204  	env = createTestEnv(t, restorePath)
   205  
   206  	// remove the statedb, historydb, and block indexes (they are supposed to be auto created during opening of an existing ledger)
   207  	// and rename the originalPath to restorePath
   208  	testutil.AssertNoError(t, os.RemoveAll(ledgerconfig.GetStateLevelDBPath()), "")
   209  	testutil.AssertNoError(t, os.RemoveAll(ledgerconfig.GetHistoryLevelDBPath()), "")
   210  	testutil.AssertNoError(t, os.RemoveAll(filepath.Join(ledgerconfig.GetBlockStorePath(), fsblkstorage.IndexDir)), "")
   211  	testutil.AssertNoError(t, os.Rename(originalPath, restorePath), "")
   212  	defer env.cleanup()
   213  
   214  	// Instantiate the ledger from restore environment and this should behave exactly as it would have in the original environment
   215  	provider, _ = NewProvider()
   216  	defer provider.Close()
   217  
   218  	_, err := provider.Create(gb)
   219  	testutil.AssertEquals(t, err, ErrLedgerIDExists)
   220  
   221  	ledger, _ = provider.Open(ledgerid)
   222  	defer ledger.Close()
   223  
   224  	block1Hash := block1.Header.Hash()
   225  	block2Hash := block2.Header.Hash()
   226  	bcInfo, _ := ledger.GetBlockchainInfo()
   227  	testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{
   228  		Height: 3, CurrentBlockHash: block2Hash, PreviousBlockHash: block1Hash})
   229  
   230  	b0, _ := ledger.GetBlockByHash(gbHash)
   231  	testutil.AssertEquals(t, b0, gb)
   232  
   233  	b1, _ := ledger.GetBlockByHash(block1Hash)
   234  	testutil.AssertEquals(t, b1, block1)
   235  
   236  	b2, _ := ledger.GetBlockByHash(block2Hash)
   237  	testutil.AssertEquals(t, b2, block2)
   238  
   239  	b0, _ = ledger.GetBlockByNumber(0)
   240  	testutil.AssertEquals(t, b0, gb)
   241  
   242  	b1, _ = ledger.GetBlockByNumber(1)
   243  	testutil.AssertEquals(t, b1, block1)
   244  
   245  	b2, _ = ledger.GetBlockByNumber(2)
   246  	testutil.AssertEquals(t, b2, block2)
   247  
   248  	// get the tran id from the 2nd block, then use it to test GetTransactionByID()
   249  	txEnvBytes2 := block1.Data.Data[0]
   250  	txEnv2, err := putils.GetEnvelopeFromBlock(txEnvBytes2)
   251  	testutil.AssertNoError(t, err, "Error upon GetEnvelopeFromBlock")
   252  	payload2, err := putils.GetPayload(txEnv2)
   253  	testutil.AssertNoError(t, err, "Error upon GetPayload")
   254  	chdr, err := putils.UnmarshalChannelHeader(payload2.Header.ChannelHeader)
   255  	testutil.AssertNoError(t, err, "Error upon GetChannelHeaderFromBytes")
   256  	txID2 := chdr.TxId
   257  	processedTran2, err := ledger.GetTransactionByID(txID2)
   258  	testutil.AssertNoError(t, err, "Error upon GetTransactionByID")
   259  	// get the tran envelope from the retrieved ProcessedTransaction
   260  	retrievedTxEnv2 := processedTran2.TransactionEnvelope
   261  	testutil.AssertEquals(t, retrievedTxEnv2, txEnv2)
   262  
   263  	qe, _ := ledger.NewQueryExecutor()
   264  	value1, _ := qe.GetState("ns1", "key1")
   265  	testutil.AssertEquals(t, value1, []byte("value4"))
   266  
   267  	hqe, err := ledger.NewHistoryQueryExecutor()
   268  	testutil.AssertNoError(t, err, "")
   269  	itr, err := hqe.GetHistoryForKey("ns1", "key1")
   270  	testutil.AssertNoError(t, err, "")
   271  	defer itr.Close()
   272  
   273  	result1, err := itr.Next()
   274  	testutil.AssertNoError(t, err, "")
   275  	testutil.AssertEquals(t, result1.(*queryresult.KeyModification).Value, []byte("value1"))
   276  	result2, err := itr.Next()
   277  	testutil.AssertNoError(t, err, "")
   278  	testutil.AssertEquals(t, result2.(*queryresult.KeyModification).Value, []byte("value4"))
   279  }
   280  
   281  func constructTestLedgerID(i int) string {
   282  	return fmt.Sprintf("ledger_%06d", i)
   283  }