github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/cceventmgmt/mgmt_test.go (about)

     1  /*
     2  Copyright IBM Corp. 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/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    14  	"github.com/hyperledger/fabric/common/flogging"
    15  	"github.com/hyperledger/fabric/core/ledger"
    16  	"github.com/hyperledger/fabric/core/ledger/mock"
    17  	"github.com/stretchr/testify/assert"
    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  	assert.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  	cc2ExpectedEvent := &mockEvent{cc2Def, cc2DBArtifactsTar}
    53  	_ = cc2ExpectedEvent
    54  	cc3ExpectedEvent := &mockEvent{cc3Def, cc3DBArtifactsTar}
    55  
    56  	// Deploy cc3 on chain1 - handler1 and handler3 should recieve event because cc3 is being deployed only on chain1
    57  	eventMgr.HandleChaincodeDeploy("channel1", []*ChaincodeDefinition{cc3Def})
    58  	eventMgr.ChaincodeDeployDone("channel1")
    59  	assert.Contains(t, handler1.eventsRecieved, cc3ExpectedEvent)
    60  	assert.NotContains(t, handler2.eventsRecieved, cc3ExpectedEvent)
    61  	assert.Contains(t, handler3.eventsRecieved, cc3ExpectedEvent)
    62  	assert.Equal(t, 1, handler1.doneRecievedCount)
    63  	assert.Equal(t, 0, handler2.doneRecievedCount)
    64  	assert.Equal(t, 1, handler3.doneRecievedCount)
    65  
    66  	// Deploy cc3 on chain2 as well and this time handler2 should also recieve event
    67  	eventMgr.HandleChaincodeDeploy("channel2", []*ChaincodeDefinition{cc3Def})
    68  	eventMgr.ChaincodeDeployDone("channel2")
    69  	assert.Contains(t, handler2.eventsRecieved, cc3ExpectedEvent)
    70  	assert.Equal(t, 1, handler1.doneRecievedCount)
    71  	assert.Equal(t, 1, handler2.doneRecievedCount)
    72  	assert.Equal(t, 2, handler3.doneRecievedCount)
    73  
    74  	// Install CC2 - handler1 and handler 3 should receive event because cc2 is deployed only on chain1 and not on chain2
    75  	eventMgr.HandleChaincodeInstall(cc2Def, cc2DBArtifactsTar)
    76  	eventMgr.ChaincodeInstallDone(true)
    77  	assert.Contains(t, handler1.eventsRecieved, cc2ExpectedEvent)
    78  	assert.NotContains(t, handler2.eventsRecieved, cc2ExpectedEvent)
    79  	assert.Contains(t, handler3.eventsRecieved, cc2ExpectedEvent)
    80  	assert.Equal(t, 2, handler1.doneRecievedCount)
    81  	assert.Equal(t, 1, handler2.doneRecievedCount)
    82  	assert.Equal(t, 3, handler3.doneRecievedCount)
    83  
    84  	// setting cc2Def as a new lifecycle definition should cause install not to trigger event
    85  	mockProvider.setChaincodeDeployed("channel1", cc2Def, false)
    86  	handler1.eventsRecieved = []*mockEvent{}
    87  	eventMgr.HandleChaincodeInstall(cc2Def, cc2DBArtifactsTar)
    88  	eventMgr.ChaincodeInstallDone(true)
    89  	assert.NotContains(t, handler1.eventsRecieved, cc2ExpectedEvent)
    90  }
    91  
    92  func TestLSCCListener(t *testing.T) {
    93  	channelName := "testChannel"
    94  
    95  	cc1Def := &ChaincodeDefinition{Name: "testChaincode1", Version: "v1", Hash: []byte("hash_testChaincode")}
    96  	cc2Def := &ChaincodeDefinition{Name: "testChaincode2", Version: "v1", Hash: []byte("hash_testChaincode")}
    97  
    98  	ccDBArtifactsTar := []byte("ccDBArtifacts")
    99  
   100  	// cc1, cc2 installed but not deployed
   101  	mockProvider := newMockProvider()
   102  	mockProvider.setChaincodeInstalled(cc1Def, ccDBArtifactsTar)
   103  	mockProvider.setChaincodeInstalled(cc2Def, ccDBArtifactsTar)
   104  
   105  	setEventMgrForTest(newMgr(mockProvider))
   106  	defer clearEventMgrForTest()
   107  	handler1 := &mockHandler{}
   108  	GetMgr().Register(channelName, handler1)
   109  
   110  	mockInfoProvider := &mock.DeployedChaincodeInfoProvider{}
   111  	mockInfoProvider.UpdatedChaincodesStub =
   112  		func(map[string][]*kvrwset.KVWrite) ([]*ledger.ChaincodeLifecycleInfo, error) {
   113  			return []*ledger.ChaincodeLifecycleInfo{
   114  				{Name: cc1Def.Name},
   115  				{Name: cc2Def.Name},
   116  			}, nil
   117  		}
   118  	mockInfoProvider.ChaincodeInfoStub = func(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*ledger.DeployedChaincodeInfo, error) {
   119  		switch chaincodeName {
   120  		case cc1Def.Name:
   121  			return &ledger.DeployedChaincodeInfo{
   122  				Name:     chaincodeName,
   123  				Hash:     cc1Def.Hash,
   124  				Version:  cc1Def.Version,
   125  				IsLegacy: true, // event for legacy chaincode lifecycle
   126  			}, nil
   127  		case cc2Def.Name:
   128  			return &ledger.DeployedChaincodeInfo{
   129  				Name:     chaincodeName,
   130  				Hash:     cc1Def.Hash,
   131  				Version:  cc1Def.Version,
   132  				IsLegacy: false, // event for new chaincode lifecycle
   133  			}, nil
   134  		default:
   135  			return nil, nil
   136  		}
   137  	}
   138  	lsccStateListener := &KVLedgerLSCCStateListener{mockInfoProvider}
   139  
   140  	// test1 regular deploy lscc event gets sent to handler
   141  	t.Run("DeployEvent", func(t *testing.T) {
   142  		lsccStateListener.HandleStateUpdates(
   143  			&ledger.StateUpdateTrigger{
   144  				LedgerID: channelName,
   145  			},
   146  		)
   147  		// processes legacy event
   148  		assert.Contains(t, handler1.eventsRecieved, &mockEvent{cc1Def, ccDBArtifactsTar})
   149  		// does not processes new lifecycle event
   150  		assert.NotContains(t, handler1.eventsRecieved, &mockEvent{cc2Def, ccDBArtifactsTar})
   151  	})
   152  }
   153  
   154  type mockProvider struct {
   155  	chaincodesDeployed             map[[3]string]bool
   156  	chaincodesDeployedNewLifecycle map[[3]string]bool
   157  	chaincodesInstalled            map[[2]string][]byte
   158  }
   159  
   160  type mockHandler struct {
   161  	eventsRecieved    []*mockEvent
   162  	doneRecievedCount int
   163  }
   164  
   165  type mockEvent struct {
   166  	def            *ChaincodeDefinition
   167  	dbArtifactsTar []byte
   168  }
   169  
   170  func (l *mockHandler) HandleChaincodeDeploy(chaincodeDefinition *ChaincodeDefinition, dbArtifactsTar []byte) error {
   171  	l.eventsRecieved = append(l.eventsRecieved, &mockEvent{def: chaincodeDefinition, dbArtifactsTar: dbArtifactsTar})
   172  	return nil
   173  }
   174  
   175  func (l *mockHandler) ChaincodeDeployDone(succeeded bool) {
   176  	l.doneRecievedCount++
   177  }
   178  
   179  func newMockProvider() *mockProvider {
   180  	return &mockProvider{
   181  		make(map[[3]string]bool),
   182  		make(map[[3]string]bool),
   183  		make(map[[2]string][]byte),
   184  	}
   185  }
   186  
   187  func (p *mockProvider) setChaincodeDeployed(chainid string, chaincodeDefinition *ChaincodeDefinition, isLegacy bool) {
   188  	p.chaincodesDeployed[[3]string{chainid, chaincodeDefinition.Name, chaincodeDefinition.Version}] = isLegacy
   189  }
   190  
   191  func (p *mockProvider) setChaincodeInstalled(chaincodeDefinition *ChaincodeDefinition, dbArtifactsTar []byte) {
   192  	p.chaincodesInstalled[[2]string{chaincodeDefinition.Name, chaincodeDefinition.Version}] = dbArtifactsTar
   193  }
   194  
   195  func (p *mockProvider) GetDeployedChaincodeInfo(chainid string, chaincodeDefinition *ChaincodeDefinition) (*ledger.DeployedChaincodeInfo, error) {
   196  	isLegacy, ok := p.chaincodesDeployed[[3]string{chainid, chaincodeDefinition.Name, chaincodeDefinition.Version}]
   197  	if !ok {
   198  		return nil, nil
   199  	}
   200  	return &ledger.DeployedChaincodeInfo{
   201  		Name:     chaincodeDefinition.Name,
   202  		Version:  chaincodeDefinition.Version,
   203  		IsLegacy: isLegacy,
   204  	}, nil
   205  }
   206  
   207  func (p *mockProvider) RetrieveChaincodeArtifacts(chaincodeDefinition *ChaincodeDefinition) (installed bool, dbArtifactsTar []byte, err error) {
   208  	dbArtifactsTar, ok := p.chaincodesInstalled[[2]string{chaincodeDefinition.Name, chaincodeDefinition.Version}]
   209  	if !ok {
   210  		return false, nil, nil
   211  	}
   212  	return true, dbArtifactsTar, nil
   213  }
   214  
   215  func setEventMgrForTest(eventMgr *Mgr) {
   216  	mgr = eventMgr
   217  }
   218  
   219  func clearEventMgrForTest() {
   220  	mgr = nil
   221  }