github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/cceventmgmt/mgmt_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package cceventmgmt
     8  
     9  import (
    10  	"os"
    11  	"testing"
    12  
    13  	"github.com/hechain20/hechain/common/flogging"
    14  	"github.com/hechain20/hechain/core/ledger"
    15  	"github.com/hechain20/hechain/core/ledger/mock"
    16  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestMain(m *testing.M) {
    21  	flogging.ActivateSpec("eventmgmt=debug")
    22  	os.Exit(m.Run())
    23  }
    24  
    25  func TestCCEventMgmt(t *testing.T) {
    26  	cc1Def := &ChaincodeDefinition{Name: "cc1", Version: "v1", Hash: []byte("cc1")}
    27  	cc1DBArtifactsTar := []byte("cc1DBArtifacts")
    28  
    29  	cc2Def := &ChaincodeDefinition{Name: "cc2", Version: "v1", Hash: []byte("cc2")}
    30  	cc2DBArtifactsTar := []byte("cc2DBArtifacts")
    31  
    32  	cc3Def := &ChaincodeDefinition{Name: "cc3", Version: "v1", Hash: []byte("cc3")}
    33  	cc3DBArtifactsTar := []byte("cc3DBArtifacts")
    34  
    35  	// cc1 is deployed and installed. cc2 is deployed but not installed. cc3 is not deployed but installed
    36  	mockProvider := newMockProvider()
    37  	mockProvider.setChaincodeInstalled(cc1Def, cc1DBArtifactsTar)
    38  	mockProvider.setChaincodeDeployed("channel1", cc1Def, true)
    39  	mockProvider.setChaincodeDeployed("channel1", cc2Def, true)
    40  	mockProvider.setChaincodeInstalled(cc3Def, cc3DBArtifactsTar)
    41  	setEventMgrForTest(newMgr(mockProvider))
    42  	defer clearEventMgrForTest()
    43  
    44  	handler1, handler2, handler3 := &mockHandler{}, &mockHandler{}, &mockHandler{}
    45  	eventMgr := GetMgr()
    46  	require.NotNil(t, eventMgr)
    47  	eventMgr.Register("channel1", handler1)
    48  	eventMgr.Register("channel2", handler2)
    49  	eventMgr.Register("channel1", handler3)
    50  	eventMgr.Register("channel2", handler3)
    51  
    52  	cc1ExpectedEvent := &mockEvent{cc1Def, cc1DBArtifactsTar}
    53  	cc2ExpectedEvent := &mockEvent{cc2Def, cc2DBArtifactsTar}
    54  	cc3ExpectedEvent := &mockEvent{cc3Def, cc3DBArtifactsTar}
    55  
    56  	// Deploy cc3 on chain1 - handler1 and handler3 should receive event because cc3 is being deployed only on chain1
    57  	require.NoError(t,
    58  		eventMgr.HandleChaincodeDeploy("channel1", []*ChaincodeDefinition{cc3Def}),
    59  	)
    60  	eventMgr.ChaincodeDeployDone("channel1")
    61  	require.Contains(t, handler1.eventsRecieved, cc3ExpectedEvent)
    62  	require.NotContains(t, handler2.eventsRecieved, cc3ExpectedEvent)
    63  	require.Contains(t, handler3.eventsRecieved, cc3ExpectedEvent)
    64  	require.Equal(t, 1, handler1.doneRecievedCount)
    65  	require.Equal(t, 0, handler2.doneRecievedCount)
    66  	require.Equal(t, 1, handler3.doneRecievedCount)
    67  
    68  	// Deploy cc3 on chain2 as well and this time handler2 should also receive event
    69  	require.NoError(t,
    70  		eventMgr.HandleChaincodeDeploy("channel2", []*ChaincodeDefinition{cc3Def}),
    71  	)
    72  	eventMgr.ChaincodeDeployDone("channel2")
    73  	require.Contains(t, handler2.eventsRecieved, cc3ExpectedEvent)
    74  	require.Equal(t, 1, handler1.doneRecievedCount)
    75  	require.Equal(t, 1, handler2.doneRecievedCount)
    76  	require.Equal(t, 2, handler3.doneRecievedCount)
    77  
    78  	// Install CC2 - handler1 and handler 3 should receive event because cc2 is deployed only on chain1 and not on chain2
    79  	require.NoError(t,
    80  		eventMgr.HandleChaincodeInstall(cc2Def, cc2DBArtifactsTar),
    81  	)
    82  	eventMgr.ChaincodeInstallDone(true)
    83  	require.Contains(t, handler1.eventsRecieved, cc2ExpectedEvent)
    84  	require.NotContains(t, handler2.eventsRecieved, cc2ExpectedEvent)
    85  	require.Contains(t, handler3.eventsRecieved, cc2ExpectedEvent)
    86  	require.Equal(t, 2, handler1.doneRecievedCount)
    87  	require.Equal(t, 1, handler2.doneRecievedCount)
    88  	require.Equal(t, 3, handler3.doneRecievedCount)
    89  
    90  	// setting cc2Def as a new lifecycle definition should cause install not to trigger event
    91  	mockProvider.setChaincodeDeployed("channel1", cc2Def, false)
    92  	handler1.eventsRecieved = []*mockEvent{}
    93  	require.NoError(t,
    94  		eventMgr.HandleChaincodeInstall(cc2Def, cc2DBArtifactsTar),
    95  	)
    96  	eventMgr.ChaincodeInstallDone(true)
    97  	require.NotContains(t, handler1.eventsRecieved, cc2ExpectedEvent)
    98  
    99  	mockListener := &mockHandler{}
   100  	require.NoError(t,
   101  		mgr.RegisterAndInvokeFor([]*ChaincodeDefinition{cc1Def, cc2Def, cc3Def},
   102  			"test-ledger", mockListener,
   103  		),
   104  	)
   105  	require.Contains(t, mockListener.eventsRecieved, cc1ExpectedEvent)
   106  	require.Contains(t, mockListener.eventsRecieved, cc3ExpectedEvent)
   107  	require.NotContains(t, mockListener.eventsRecieved, cc2ExpectedEvent)
   108  	require.Equal(t, 2, mockListener.doneRecievedCount)
   109  	require.Contains(t, mgr.ccLifecycleListeners["test-ledger"], mockListener)
   110  }
   111  
   112  func TestLSCCListener(t *testing.T) {
   113  	channelName := "testChannel"
   114  
   115  	cc1Def := &ChaincodeDefinition{Name: "testChaincode1", Version: "v1", Hash: []byte("hash_testChaincode")}
   116  	cc2Def := &ChaincodeDefinition{Name: "testChaincode2", Version: "v1", Hash: []byte("hash_testChaincode")}
   117  
   118  	ccDBArtifactsTar := []byte("ccDBArtifacts")
   119  
   120  	// cc1, cc2 installed but not deployed
   121  	mockProvider := newMockProvider()
   122  	mockProvider.setChaincodeInstalled(cc1Def, ccDBArtifactsTar)
   123  	mockProvider.setChaincodeInstalled(cc2Def, ccDBArtifactsTar)
   124  
   125  	setEventMgrForTest(newMgr(mockProvider))
   126  	defer clearEventMgrForTest()
   127  	handler1 := &mockHandler{}
   128  	GetMgr().Register(channelName, handler1)
   129  
   130  	mockInfoProvider := &mock.DeployedChaincodeInfoProvider{}
   131  	mockInfoProvider.UpdatedChaincodesStub =
   132  		func(map[string][]*kvrwset.KVWrite) ([]*ledger.ChaincodeLifecycleInfo, error) {
   133  			return []*ledger.ChaincodeLifecycleInfo{
   134  				{Name: cc1Def.Name},
   135  				{Name: cc2Def.Name},
   136  			}, nil
   137  		}
   138  	mockInfoProvider.ChaincodeInfoStub = func(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*ledger.DeployedChaincodeInfo, error) {
   139  		switch chaincodeName {
   140  		case cc1Def.Name:
   141  			return &ledger.DeployedChaincodeInfo{
   142  				Name:     chaincodeName,
   143  				Hash:     cc1Def.Hash,
   144  				Version:  cc1Def.Version,
   145  				IsLegacy: true, // event for legacy chaincode lifecycle
   146  			}, nil
   147  		case cc2Def.Name:
   148  			return &ledger.DeployedChaincodeInfo{
   149  				Name:     chaincodeName,
   150  				Hash:     cc1Def.Hash,
   151  				Version:  cc1Def.Version,
   152  				IsLegacy: false, // event for new chaincode lifecycle
   153  			}, nil
   154  		default:
   155  			return nil, nil
   156  		}
   157  	}
   158  	lsccStateListener := &KVLedgerLSCCStateListener{mockInfoProvider}
   159  
   160  	// test1 regular deploy lscc event gets sent to handler
   161  	t.Run("DeployEvent", func(t *testing.T) {
   162  		require.NoError(t,
   163  			lsccStateListener.HandleStateUpdates(
   164  				&ledger.StateUpdateTrigger{
   165  					LedgerID: channelName,
   166  				},
   167  			),
   168  		)
   169  		// processes legacy event
   170  		require.Contains(t, handler1.eventsRecieved, &mockEvent{cc1Def, ccDBArtifactsTar})
   171  		// does not processes new lifecycle event
   172  		require.NotContains(t, handler1.eventsRecieved, &mockEvent{cc2Def, ccDBArtifactsTar})
   173  	})
   174  }
   175  
   176  type mockProvider struct {
   177  	chaincodesDeployed             map[[3]string]bool
   178  	chaincodesDeployedNewLifecycle map[[3]string]bool
   179  	chaincodesInstalled            map[[2]string][]byte
   180  }
   181  
   182  type mockHandler struct {
   183  	eventsRecieved    []*mockEvent
   184  	doneRecievedCount int
   185  }
   186  
   187  type mockEvent struct {
   188  	def            *ChaincodeDefinition
   189  	dbArtifactsTar []byte
   190  }
   191  
   192  func (l *mockHandler) HandleChaincodeDeploy(chaincodeDefinition *ChaincodeDefinition, dbArtifactsTar []byte) error {
   193  	l.eventsRecieved = append(l.eventsRecieved, &mockEvent{def: chaincodeDefinition, dbArtifactsTar: dbArtifactsTar})
   194  	return nil
   195  }
   196  
   197  func (l *mockHandler) ChaincodeDeployDone(succeeded bool) {
   198  	l.doneRecievedCount++
   199  }
   200  
   201  func newMockProvider() *mockProvider {
   202  	return &mockProvider{
   203  		make(map[[3]string]bool),
   204  		make(map[[3]string]bool),
   205  		make(map[[2]string][]byte),
   206  	}
   207  }
   208  
   209  func (p *mockProvider) setChaincodeDeployed(chainid string, chaincodeDefinition *ChaincodeDefinition, isLegacy bool) {
   210  	p.chaincodesDeployed[[3]string{chainid, chaincodeDefinition.Name, chaincodeDefinition.Version}] = isLegacy
   211  }
   212  
   213  func (p *mockProvider) setChaincodeInstalled(chaincodeDefinition *ChaincodeDefinition, dbArtifactsTar []byte) {
   214  	p.chaincodesInstalled[[2]string{chaincodeDefinition.Name, chaincodeDefinition.Version}] = dbArtifactsTar
   215  }
   216  
   217  func (p *mockProvider) GetDeployedChaincodeInfo(chainid string, chaincodeDefinition *ChaincodeDefinition) (*ledger.DeployedChaincodeInfo, error) {
   218  	isLegacy, ok := p.chaincodesDeployed[[3]string{chainid, chaincodeDefinition.Name, chaincodeDefinition.Version}]
   219  	if !ok {
   220  		return nil, nil
   221  	}
   222  	return &ledger.DeployedChaincodeInfo{
   223  		Name:     chaincodeDefinition.Name,
   224  		Version:  chaincodeDefinition.Version,
   225  		IsLegacy: isLegacy,
   226  	}, nil
   227  }
   228  
   229  func (p *mockProvider) RetrieveChaincodeArtifacts(chaincodeDefinition *ChaincodeDefinition) (installed bool, dbArtifactsTar []byte, err error) {
   230  	dbArtifactsTar, ok := p.chaincodesInstalled[[2]string{chaincodeDefinition.Name, chaincodeDefinition.Version}]
   231  	if !ok {
   232  		return false, nil, nil
   233  	}
   234  	return true, dbArtifactsTar, nil
   235  }
   236  
   237  func setEventMgrForTest(eventMgr *Mgr) {
   238  	mgr = eventMgr
   239  }
   240  
   241  func clearEventMgrForTest() {
   242  	mgr = nil
   243  }