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