github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/core/ledger/kvledger/pause_resume_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package kvledger
     8  
     9  import (
    10  	"testing"
    11  
    12  	"github.com/golang/protobuf/proto"
    13  	"github.com/hyperledger/fabric-protos-go/common"
    14  	configtxtest "github.com/osdi23p228/fabric/common/configtx/test"
    15  	"github.com/osdi23p228/fabric/core/ledger/mock"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestPauseAndResume(t *testing.T) {
    20  	conf, cleanup := testConfig(t)
    21  	conf.HistoryDBConfig.Enabled = false
    22  	defer cleanup()
    23  	provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
    24  
    25  	numLedgers := 10
    26  	activeLedgerIDs, err := provider.List()
    27  	require.NoError(t, err)
    28  	require.Len(t, activeLedgerIDs, 0)
    29  	genesisBlocks := make([]*common.Block, numLedgers)
    30  	for i := 0; i < numLedgers; i++ {
    31  		genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i))
    32  		genesisBlocks[i] = genesisBlock
    33  		provider.Create(genesisBlock)
    34  	}
    35  	activeLedgerIDs, err = provider.List()
    36  	require.NoError(t, err)
    37  	require.Len(t, activeLedgerIDs, numLedgers)
    38  	provider.Close()
    39  
    40  	// pause channels
    41  	pausedLedgers := []int{1, 3, 5}
    42  	for _, i := range pausedLedgers {
    43  		err = PauseChannel(conf.RootFSPath, constructTestLedgerID(i))
    44  		require.NoError(t, err)
    45  	}
    46  	// pause again should not fail
    47  	err = PauseChannel(conf.RootFSPath, constructTestLedgerID(1))
    48  	require.NoError(t, err)
    49  	// verify ledger status after pause
    50  	provider = testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
    51  	assertLedgerStatus(t, provider, genesisBlocks, numLedgers, pausedLedgers)
    52  	provider.Close()
    53  
    54  	// resume channels
    55  	resumedLedgers := []int{1, 5}
    56  	for _, i := range resumedLedgers {
    57  		err = ResumeChannel(conf.RootFSPath, constructTestLedgerID(i))
    58  		require.NoError(t, err)
    59  	}
    60  	// resume again should not fail
    61  	err = ResumeChannel(conf.RootFSPath, constructTestLedgerID(1))
    62  	require.NoError(t, err)
    63  	// verify ledger status after resume
    64  	pausedLedgersAfterResume := []int{3}
    65  	provider = testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
    66  	defer provider.Close()
    67  	assertLedgerStatus(t, provider, genesisBlocks, numLedgers, pausedLedgersAfterResume)
    68  
    69  	// open paused channel should fail
    70  	_, err = provider.Open(constructTestLedgerID(3))
    71  	require.Equal(t, ErrInactiveLedger, err)
    72  }
    73  
    74  func TestPauseAndResumeErrors(t *testing.T) {
    75  	conf, cleanup := testConfig(t)
    76  	conf.HistoryDBConfig.Enabled = false
    77  	defer cleanup()
    78  	provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
    79  
    80  	ledgerID := constructTestLedgerID(0)
    81  	genesisBlock, _ := configtxtest.MakeGenesisBlock(ledgerID)
    82  	provider.Create(genesisBlock)
    83  	// purposely set an invalid metatdata
    84  	provider.idStore.db.Put(provider.idStore.encodeLedgerKey(ledgerID, metadataKeyPrefix), []byte("invalid"), true)
    85  
    86  	// fail if provider is open (e.g., peer is up running)
    87  	err := PauseChannel(conf.RootFSPath, constructTestLedgerID(0))
    88  	require.Error(t, err, "as another peer node command is executing, wait for that command to complete its execution or terminate it before retrying")
    89  
    90  	err = ResumeChannel(conf.RootFSPath, constructTestLedgerID(0))
    91  	require.Error(t, err, "as another peer node command is executing, wait for that command to complete its execution or terminate it before retrying")
    92  
    93  	provider.Close()
    94  
    95  	// fail if ledgerID does not exists
    96  	err = PauseChannel(conf.RootFSPath, "dummy")
    97  	require.Error(t, err, "LedgerID does not exist")
    98  
    99  	err = ResumeChannel(conf.RootFSPath, "dummy")
   100  	require.Error(t, err, "LedgerID does not exist")
   101  
   102  	// error if metadata cannot be unmarshaled
   103  	err = PauseChannel(conf.RootFSPath, ledgerID)
   104  	require.EqualError(t, err, "error unmarshalling ledger metadata: unexpected EOF")
   105  
   106  	err = ResumeChannel(conf.RootFSPath, ledgerID)
   107  	require.EqualError(t, err, "error unmarshalling ledger metadata: unexpected EOF")
   108  }
   109  
   110  // verify status for paused ledgers and non-paused ledgers
   111  func assertLedgerStatus(t *testing.T, provider *Provider, genesisBlocks []*common.Block, numLedgers int, pausedLedgers []int) {
   112  	s := provider.idStore
   113  
   114  	activeLedgerIDs, err := provider.List()
   115  	require.NoError(t, err)
   116  	require.Len(t, activeLedgerIDs, numLedgers-len(pausedLedgers))
   117  	for i := 0; i < numLedgers; i++ {
   118  		if !contains(pausedLedgers, i) {
   119  			require.Contains(t, activeLedgerIDs, constructTestLedgerID(i))
   120  		}
   121  	}
   122  
   123  	for i := 0; i < numLedgers; i++ {
   124  		active, exists, err := s.ledgerIDActive(constructTestLedgerID(i))
   125  		require.NoError(t, err)
   126  		if !contains(pausedLedgers, i) {
   127  			require.True(t, active)
   128  			require.True(t, exists)
   129  		} else {
   130  			require.False(t, active)
   131  			require.True(t, exists)
   132  		}
   133  
   134  		// every channel (paused or non-paused) should have an entry for genesis block
   135  		gbBytes, err := s.db.Get(s.encodeLedgerKey(constructTestLedgerID(i), ledgerKeyPrefix))
   136  		require.NoError(t, err)
   137  		gb := &common.Block{}
   138  		require.NoError(t, proto.Unmarshal(gbBytes, gb))
   139  		require.True(t, proto.Equal(gb, genesisBlocks[i]), "proto messages are not equal")
   140  
   141  	}
   142  }
   143  
   144  func contains(slice []int, val int) bool {
   145  	for _, item := range slice {
   146  		if item == val {
   147  			return true
   148  		}
   149  	}
   150  	return false
   151  }