github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/core/chaincode/chaincode_support_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package chaincode
     8  
     9  import (
    10  	"archive/tar"
    11  	"bytes"
    12  	"compress/gzip"
    13  	"errors"
    14  	"fmt"
    15  	"io/ioutil"
    16  	"os"
    17  	"path/filepath"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/hyperledger/fabric/bccsp/sw"
    22  	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
    23  	"github.com/hyperledger/fabric/core/ledger/ledgermgmt/ledgermgmttest"
    24  
    25  	docker "github.com/fsouza/go-dockerclient"
    26  	"github.com/golang/protobuf/proto"
    27  	"github.com/hyperledger/fabric-chaincode-go/shim"
    28  	plgr "github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    29  	pb "github.com/hyperledger/fabric-protos-go/peer"
    30  	"github.com/hyperledger/fabric/common/crypto/tlsgen"
    31  	commonledger "github.com/hyperledger/fabric/common/ledger"
    32  	"github.com/hyperledger/fabric/common/metrics/disabled"
    33  	mockpeer "github.com/hyperledger/fabric/common/mocks/peer"
    34  	"github.com/hyperledger/fabric/common/util"
    35  	"github.com/hyperledger/fabric/core/aclmgmt/resources"
    36  	"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
    37  	"github.com/hyperledger/fabric/core/chaincode/lifecycle"
    38  	"github.com/hyperledger/fabric/core/chaincode/mock"
    39  	"github.com/hyperledger/fabric/core/chaincode/persistence"
    40  	"github.com/hyperledger/fabric/core/chaincode/platforms"
    41  	"github.com/hyperledger/fabric/core/chaincode/platforms/golang"
    42  	"github.com/hyperledger/fabric/core/common/ccprovider"
    43  	"github.com/hyperledger/fabric/core/config"
    44  	"github.com/hyperledger/fabric/core/container"
    45  	"github.com/hyperledger/fabric/core/container/ccintf"
    46  	"github.com/hyperledger/fabric/core/container/dockercontroller"
    47  	"github.com/hyperledger/fabric/core/ledger"
    48  	ledgermock "github.com/hyperledger/fabric/core/ledger/mock"
    49  	"github.com/hyperledger/fabric/core/peer"
    50  	"github.com/hyperledger/fabric/core/scc"
    51  	"github.com/hyperledger/fabric/core/scc/lscc"
    52  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    53  	"github.com/hyperledger/fabric/protoutil"
    54  	"github.com/stretchr/testify/assert"
    55  )
    56  
    57  // CCContext is a legacy structure that was utilized heavily in the tests
    58  // so it has been preserved, even though it basically passes a name/version pair
    59  // alone.
    60  type CCContext struct {
    61  	Name    string
    62  	Version string
    63  }
    64  
    65  var globalBlockNum map[string]uint64
    66  
    67  type mockResultsIterator struct {
    68  	current int
    69  	kvs     []*plgr.KV
    70  }
    71  
    72  func (mri *mockResultsIterator) Next() (commonledger.QueryResult, error) {
    73  	if mri.current == len(mri.kvs) {
    74  		return nil, nil
    75  	}
    76  	kv := mri.kvs[mri.current]
    77  	mri.current = mri.current + 1
    78  
    79  	return kv, nil
    80  }
    81  
    82  func (mri *mockResultsIterator) Close() {
    83  	mri.current = len(mri.kvs)
    84  }
    85  
    86  type mockExecQuerySimulator struct {
    87  	txsim       ledger.TxSimulator
    88  	resultsIter map[string]map[string]*mockResultsIterator
    89  }
    90  
    91  func (meqe *mockExecQuerySimulator) GetHistoryForKey(namespace, query string) (commonledger.ResultsIterator, error) {
    92  	return meqe.commonQuery(namespace, query)
    93  }
    94  
    95  func (meqe *mockExecQuerySimulator) ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error) {
    96  	return meqe.commonQuery(namespace, query)
    97  }
    98  
    99  func (meqe *mockExecQuerySimulator) commonQuery(namespace, query string) (commonledger.ResultsIterator, error) {
   100  	if meqe.resultsIter == nil {
   101  		return nil, fmt.Errorf("query executor not initialized")
   102  	}
   103  	nsiter := meqe.resultsIter[namespace]
   104  	if nsiter == nil {
   105  		return nil, fmt.Errorf("namespace %v not found for %s", namespace, query)
   106  	}
   107  	iter := nsiter[query]
   108  	if iter == nil {
   109  		fmt.Printf("iter not found for query %s\n", query)
   110  	}
   111  	return iter, nil
   112  }
   113  
   114  func (meqe *mockExecQuerySimulator) SetState(namespace string, key string, value []byte) error {
   115  	if meqe.txsim == nil {
   116  		return fmt.Errorf("SetState txsimulator not initialed")
   117  	}
   118  	return meqe.txsim.SetState(namespace, key, value)
   119  }
   120  
   121  func (meqe *mockExecQuerySimulator) DeleteState(namespace string, key string) error {
   122  	if meqe.txsim == nil {
   123  		return fmt.Errorf("SetState txsimulator not initialed")
   124  	}
   125  	return meqe.txsim.DeleteState(namespace, key)
   126  }
   127  
   128  func (meqe *mockExecQuerySimulator) SetStateMultipleKeys(namespace string, kvs map[string][]byte) error {
   129  	if meqe.txsim == nil {
   130  		return fmt.Errorf("SetState txsimulator not initialed")
   131  	}
   132  	return meqe.txsim.SetStateMultipleKeys(namespace, kvs)
   133  }
   134  
   135  func (meqe *mockExecQuerySimulator) ExecuteUpdate(query string) error {
   136  	if meqe.txsim == nil {
   137  		return fmt.Errorf("SetState txsimulator not initialed")
   138  	}
   139  	return meqe.txsim.ExecuteUpdate(query)
   140  }
   141  
   142  func (meqe *mockExecQuerySimulator) GetTxSimulationResults() ([]byte, error) {
   143  	if meqe.txsim == nil {
   144  		return nil, fmt.Errorf("SetState txsimulator not initialed")
   145  	}
   146  	simRes, err := meqe.txsim.GetTxSimulationResults()
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	return simRes.GetPubSimulationBytes()
   151  }
   152  
   153  //initialize peer and start up. If security==enabled, login as vp
   154  func initMockPeer(channelIDs ...string) (*peer.Peer, *ChaincodeSupport, func(), error) {
   155  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   156  	if err != nil {
   157  		panic(fmt.Sprintf("failed to create cryptoProvider: %s", err))
   158  	}
   159  
   160  	peerInstance := &peer.Peer{CryptoProvider: cryptoProvider}
   161  
   162  	tempdir, err := ioutil.TempDir("", "cc-support-test")
   163  	if err != nil {
   164  		panic(fmt.Sprintf("failed to create temporary directory: %s", err))
   165  	}
   166  
   167  	initializer := ledgermgmttest.NewInitializer(filepath.Join(tempdir, "ledgerData"))
   168  	peerInstance.LedgerMgr = ledgermgmt.NewLedgerMgr(initializer)
   169  
   170  	cleanup := func() {
   171  		peerInstance.LedgerMgr.Close()
   172  		os.RemoveAll(tempdir)
   173  	}
   174  
   175  	mockAclProvider := &mock.ACLProvider{}
   176  	ccprovider.SetChaincodesPath(tempdir)
   177  	ca, _ := tlsgen.NewCA()
   178  	certGenerator := accesscontrol.NewAuthenticator(ca)
   179  	globalConfig := GlobalConfig()
   180  	globalConfig.ExecuteTimeout = 1 * time.Second
   181  	globalConfig.InstallTimeout = 90 * time.Second
   182  	globalConfig.StartupTimeout = 10 * time.Second
   183  
   184  	buildRegistry := &container.BuildRegistry{}
   185  
   186  	client, err := docker.NewClientFromEnv()
   187  	if err != nil {
   188  		panic(err)
   189  	}
   190  
   191  	containerRouter := &container.Router{
   192  		DockerVM: &dockercontroller.DockerVM{
   193  			PlatformBuilder: &platforms.Builder{
   194  				Registry: platforms.NewRegistry(&golang.Platform{}),
   195  				Client:   client,
   196  			},
   197  		},
   198  		PackageProvider: &persistence.FallbackPackageLocator{
   199  			ChaincodePackageLocator: &persistence.ChaincodePackageLocator{},
   200  			LegacyCCPackageLocator:  &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider},
   201  		},
   202  	}
   203  
   204  	lsccImpl := &lscc.SCC{
   205  		BuiltinSCCs: map[string]struct{}{"lscc": {}},
   206  		Support: &lscc.SupportImpl{
   207  			GetMSPIDs: peerInstance.GetMSPIDs,
   208  		},
   209  		SCCProvider:      &lscc.PeerShim{Peer: peerInstance},
   210  		ACLProvider:      mockAclProvider,
   211  		GetMSPIDs:        peerInstance.GetMSPIDs,
   212  		PolicyChecker:    newPolicyChecker(peerInstance),
   213  		BCCSP:            cryptoProvider,
   214  		BuildRegistry:    buildRegistry,
   215  		ChaincodeBuilder: containerRouter,
   216  	}
   217  
   218  	ml := &mock.Lifecycle{}
   219  	ml.ChaincodeEndorsementInfoStub = func(_, name string, _ ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error) {
   220  		switch name {
   221  		case "shimTestCC", "calledCC":
   222  			return &lifecycle.ChaincodeEndorsementInfo{
   223  				ChaincodeID: name + ":0",
   224  			}, nil
   225  		case "lscc":
   226  			return &lifecycle.ChaincodeEndorsementInfo{
   227  				ChaincodeID: "lscc.syscc",
   228  			}, nil
   229  		default:
   230  			return nil, errors.New("oh-bother-no-chaincode-info")
   231  		}
   232  	}
   233  
   234  	containerRuntime := &ContainerRuntime{
   235  		BuildRegistry:   buildRegistry,
   236  		ContainerRouter: containerRouter,
   237  	}
   238  	userRunsCC := true
   239  	metricsProviders := &disabled.Provider{}
   240  	chaincodeHandlerRegistry := NewHandlerRegistry(userRunsCC)
   241  	chaincodeLauncher := &RuntimeLauncher{
   242  		Metrics:        NewLaunchMetrics(metricsProviders),
   243  		Runtime:        containerRuntime,
   244  		Registry:       chaincodeHandlerRegistry,
   245  		StartupTimeout: globalConfig.StartupTimeout,
   246  		CACert:         ca.CertBytes(),
   247  		CertGenerator:  certGenerator,
   248  	}
   249  	if !globalConfig.TLSEnabled {
   250  		chaincodeLauncher.CertGenerator = nil
   251  	}
   252  	chaincodeSupport := &ChaincodeSupport{
   253  		ACLProvider:            mockAclProvider,
   254  		AppConfig:              peerInstance,
   255  		DeployedCCInfoProvider: &ledgermock.DeployedChaincodeInfoProvider{},
   256  		ExecuteTimeout:         globalConfig.ExecuteTimeout,
   257  		InstallTimeout:         globalConfig.InstallTimeout,
   258  		HandlerMetrics:         NewHandlerMetrics(metricsProviders),
   259  		HandlerRegistry:        chaincodeHandlerRegistry,
   260  		Keepalive:              globalConfig.Keepalive,
   261  		Launcher:               chaincodeLauncher,
   262  		Lifecycle:              ml,
   263  		Peer:                   peerInstance,
   264  		Runtime:                containerRuntime,
   265  		BuiltinSCCs:            map[string]struct{}{"lscc": {}},
   266  		TotalQueryLimit:        globalConfig.TotalQueryLimit,
   267  		UserRunsCC:             userRunsCC,
   268  	}
   269  
   270  	scc.DeploySysCC(lsccImpl, chaincodeSupport)
   271  
   272  	globalBlockNum = make(map[string]uint64, len(channelIDs))
   273  	for _, id := range channelIDs {
   274  		if err := peer.CreateMockChannel(peerInstance, id, &mock.PolicyManager{}); err != nil {
   275  			cleanup()
   276  			return nil, nil, func() {}, err
   277  		}
   278  
   279  		// any channel other than the default testchannelid does not have a MSP set up -> create one
   280  		if id != "testchannelid" {
   281  			mspmgmt.XXXSetMSPManager(id, mspmgmt.GetManagerForChain("testchannelid"))
   282  		}
   283  		globalBlockNum[id] = 1
   284  	}
   285  
   286  	return peerInstance, chaincodeSupport, cleanup, nil
   287  }
   288  
   289  func finitMockPeer(peerInstance *peer.Peer, channelIDs ...string) {
   290  	for _, c := range channelIDs {
   291  		if lgr := peerInstance.GetLedger(c); lgr != nil {
   292  			lgr.Close()
   293  		}
   294  	}
   295  	ledgerPath := config.GetPath("peer.fileSystemPath")
   296  	os.RemoveAll(ledgerPath)
   297  	os.RemoveAll(filepath.Join(os.TempDir(), "hyperledger"))
   298  }
   299  
   300  //store the stream CC mappings here
   301  var mockPeerCCSupport = mockpeer.NewMockPeerSupport()
   302  
   303  func setupcc(name string) (*mockpeer.MockCCComm, *mockpeer.MockCCComm) {
   304  	send := make(chan *pb.ChaincodeMessage)
   305  	recv := make(chan *pb.ChaincodeMessage)
   306  	peerSide, _ := mockPeerCCSupport.AddCC(name, recv, send)
   307  	peerSide.SetName("peer")
   308  	ccSide := mockPeerCCSupport.GetCCMirror(name)
   309  	ccSide.SetPong(true)
   310  	return peerSide, ccSide
   311  }
   312  
   313  //assign this to done and failNow and keep using them
   314  func setuperror() chan error {
   315  	return make(chan error)
   316  }
   317  
   318  func processDone(t *testing.T, done chan error, expecterr bool) {
   319  	var err error
   320  	if done != nil {
   321  		err = <-done
   322  	}
   323  	if expecterr != (err != nil) {
   324  		if err == nil {
   325  			t.Fatalf("Expected error but got success")
   326  		} else {
   327  			t.Fatalf("Expected success but got error %s", err)
   328  		}
   329  	}
   330  }
   331  
   332  func startTx(t *testing.T, peerInstance *peer.Peer, channelID string, cis *pb.ChaincodeInvocationSpec, txId string) (*ccprovider.TransactionParams, ledger.TxSimulator) {
   333  	creator := []byte([]byte("Alice"))
   334  	sprop, prop := protoutil.MockSignedEndorserProposalOrPanic(channelID, cis.ChaincodeSpec, creator, []byte("msg1"))
   335  	txsim, hqe, err := startTxSimulation(peerInstance, channelID, txId)
   336  	if err != nil {
   337  		t.Fatalf("getting txsimulator failed %s", err)
   338  	}
   339  
   340  	txParams := &ccprovider.TransactionParams{
   341  		ChannelID:            channelID,
   342  		TxID:                 txId,
   343  		Proposal:             prop,
   344  		SignedProp:           sprop,
   345  		TXSimulator:          txsim,
   346  		HistoryQueryExecutor: hqe,
   347  	}
   348  
   349  	return txParams, txsim
   350  }
   351  
   352  func endTx(t *testing.T, peerInstance *peer.Peer, txParams *ccprovider.TransactionParams, txsim ledger.TxSimulator, cis *pb.ChaincodeInvocationSpec) {
   353  	if err := endTxSimulationCIS(peerInstance, txParams.ChannelID, cis.ChaincodeSpec.ChaincodeId, txParams.TxID, txsim, []byte("invoke"), true, cis, globalBlockNum[txParams.ChannelID]); err != nil {
   354  		t.Fatalf("simulation failed with error %s", err)
   355  	}
   356  	globalBlockNum[txParams.ChannelID] = globalBlockNum[txParams.ChannelID] + 1
   357  }
   358  
   359  func execCC(t *testing.T, txParams *ccprovider.TransactionParams, ccSide *mockpeer.MockCCComm, chaincodeName string, waitForERROR bool, expectExecErr bool, done chan error, cis *pb.ChaincodeInvocationSpec, respSet *mockpeer.MockResponseSet, chaincodeSupport *ChaincodeSupport) error {
   360  	ccSide.SetResponses(respSet)
   361  
   362  	resp, _, err := chaincodeSupport.Execute(txParams, chaincodeName, cis.ChaincodeSpec.Input)
   363  	if err == nil && resp.Status != shim.OK {
   364  		err = errors.New(resp.Message)
   365  	}
   366  
   367  	if err == nil && expectExecErr {
   368  		t.Fatalf("expected error but succeeded")
   369  	} else if err != nil && !expectExecErr {
   370  		t.Fatalf("exec failed with %s", err)
   371  	}
   372  
   373  	//wait
   374  	processDone(t, done, waitForERROR)
   375  
   376  	return nil
   377  }
   378  
   379  //initialize cc support env and startup the chaincode
   380  func startCC(t *testing.T, channelID string, ccname string, chaincodeSupport *ChaincodeSupport) (*mockpeer.MockCCComm, *mockpeer.MockCCComm) {
   381  	peerSide, ccSide := setupcc(ccname)
   382  	defer mockPeerCCSupport.RemoveCC(ccname)
   383  
   384  	//register peer side with ccsupport
   385  	go func() {
   386  		chaincodeSupport.HandleChaincodeStream(peerSide)
   387  	}()
   388  
   389  	done := setuperror()
   390  
   391  	errorFunc := func(ind int, err error) {
   392  		done <- err
   393  	}
   394  
   395  	ccDone := make(chan struct{})
   396  	defer close(ccDone)
   397  
   398  	//start the mock peer
   399  	go func() {
   400  		respSet := &mockpeer.MockResponseSet{
   401  			DoneFunc:  errorFunc,
   402  			ErrorFunc: nil,
   403  			Responses: []*mockpeer.MockResponse{
   404  				{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}, RespMsg: nil},
   405  				{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY}, RespMsg: nil},
   406  			},
   407  		}
   408  		ccSide.SetResponses(respSet)
   409  		ccSide.Run(ccDone)
   410  	}()
   411  
   412  	ccSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeID{Name: ccname + ":0"}), Txid: "0", ChannelId: channelID})
   413  
   414  	//wait for init
   415  	processDone(t, done, false)
   416  
   417  	return peerSide, ccSide
   418  }
   419  
   420  func getTarGZ(t *testing.T, name string, contents []byte) []byte {
   421  	startTime := time.Now()
   422  	inputbuf := bytes.NewBuffer(nil)
   423  	gw := gzip.NewWriter(inputbuf)
   424  	tr := tar.NewWriter(gw)
   425  	size := int64(len(contents))
   426  
   427  	tr.WriteHeader(&tar.Header{Name: name, Size: size, ModTime: startTime, AccessTime: startTime, ChangeTime: startTime})
   428  	tr.Write(contents)
   429  	tr.Close()
   430  	gw.Close()
   431  	ioutil.WriteFile("/tmp/t.gz", inputbuf.Bytes(), 0644)
   432  	return inputbuf.Bytes()
   433  }
   434  
   435  // Deploy a chaincode - i.e., build and initialize.
   436  func deployCC(t *testing.T, txParams *ccprovider.TransactionParams, ccContext *CCContext, spec *pb.ChaincodeSpec, chaincodeSupport *ChaincodeSupport) {
   437  	// First build and get the deployment spec
   438  	code := getTarGZ(t, "src/dummy/dummy.go", []byte("code"))
   439  	cds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: code}
   440  
   441  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   442  	assert.NoError(t, err)
   443  	ccinfoFSImpl := &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider}
   444  	_, err = ccinfoFSImpl.PutChaincode(cds)
   445  	assert.NoError(t, err)
   446  
   447  	b := protoutil.MarshalOrPanic(cds)
   448  
   449  	//wrap the deployment in an invocation spec to lscc...
   450  	lsccSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: "lscc"}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("deploy"), []byte(txParams.ChannelID), b}}}}
   451  
   452  	//write to lscc
   453  	if _, _, err := chaincodeSupport.Execute(txParams, "lscc", lsccSpec.ChaincodeSpec.Input); err != nil {
   454  		t.Fatalf("Error deploying chaincode %v (err: %s)", ccContext, err)
   455  	}
   456  }
   457  
   458  func initializeCC(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCComm, chaincodeSupport *ChaincodeSupport) error {
   459  	done := setuperror()
   460  
   461  	errorFunc := func(ind int, err error) {
   462  		done <- err
   463  	}
   464  
   465  	chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"}
   466  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("A"), []byte("100"), []byte("B"), []byte("200")}, Decorations: nil}
   467  	cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   468  
   469  	txid := util.GenerateUUID()
   470  	txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   471  
   472  	//bad txid in response (should be "1"), should fail
   473  	resp := &mockpeer.MockResponse{
   474  		RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION},
   475  		RespMsg: &pb.ChaincodeMessage{
   476  			Type:      pb.ChaincodeMessage_COMPLETED,
   477  			Payload:   protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("init succeeded")}),
   478  			Txid:      "unknowntxid",
   479  			ChannelId: chainID,
   480  		},
   481  	}
   482  	respSet := &mockpeer.MockResponseSet{
   483  		DoneFunc:  errorFunc,
   484  		ErrorFunc: nil,
   485  		Responses: []*mockpeer.MockResponse{resp},
   486  	}
   487  
   488  	execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport)
   489  
   490  	//set the right TxID in response now
   491  	resp = &mockpeer.MockResponse{
   492  		RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION},
   493  		RespMsg: &pb.ChaincodeMessage{
   494  			Type:      pb.ChaincodeMessage_COMPLETED,
   495  			Payload:   protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("init succeeded")}),
   496  			Txid:      txid,
   497  			ChannelId: chainID,
   498  		},
   499  	}
   500  	respSet = &mockpeer.MockResponseSet{
   501  		DoneFunc:  errorFunc,
   502  		ErrorFunc: nil,
   503  		Responses: []*mockpeer.MockResponse{resp},
   504  	}
   505  
   506  	//we are not going to reach the chaincode and so won't get a response from it. processDone will not
   507  	//be triggered by the chaincode stream.  We just expect an error from fabric. Hence pass nil for done
   508  	execCC(t, txParams, ccSide, "badccname", false, true, nil, cis, respSet, chaincodeSupport)
   509  
   510  	//---------try a successful init at last-------
   511  	//everything lined up
   512  	//    correct registered chaincode version
   513  	//    matching txid
   514  	//    txsim context
   515  	//    full response
   516  	//    correct block number for ending sim
   517  
   518  	respSet = &mockpeer.MockResponseSet{
   519  		DoneFunc:  errorFunc,
   520  		ErrorFunc: nil,
   521  		Responses: []*mockpeer.MockResponse{
   522  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("100")}), Txid: txid, ChannelId: chainID}},
   523  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("200")}), Txid: txid, ChannelId: chainID}},
   524  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), ChaincodeEvent: &pb.ChaincodeEvent{ChaincodeId: ccname}, Txid: txid, ChannelId: chainID}},
   525  		},
   526  	}
   527  
   528  	execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport)
   529  
   530  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   531  
   532  	return nil
   533  }
   534  
   535  func invokeCC(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCComm, chaincodeSupport *ChaincodeSupport) error {
   536  	done := setuperror()
   537  
   538  	errorFunc := func(ind int, err error) {
   539  		done <- err
   540  	}
   541  
   542  	chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"}
   543  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil}
   544  	cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   545  	txid := util.GenerateUUID()
   546  	txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   547  
   548  	respSet := &mockpeer.MockResponseSet{
   549  		DoneFunc:  errorFunc,
   550  		ErrorFunc: nil,
   551  		Responses: []*mockpeer.MockResponse{
   552  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "A"}), Txid: txid, ChannelId: chainID}},
   553  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "B"}), Txid: txid, ChannelId: chainID}},
   554  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("90")}), Txid: txid, ChannelId: chainID}},
   555  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("210")}), Txid: txid, ChannelId: chainID}},
   556  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "TODEL", Value: []byte("-to-be-deleted-")}), Txid: txid, ChannelId: chainID}},
   557  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}},
   558  		},
   559  	}
   560  
   561  	execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport)
   562  
   563  	//delete the extra var
   564  	respSet = &mockpeer.MockResponseSet{
   565  		DoneFunc:  errorFunc,
   566  		ErrorFunc: nil,
   567  		Responses: []*mockpeer.MockResponse{
   568  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "3", ChannelId: chainID}},
   569  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: protoutil.MarshalOrPanic(&pb.DelState{Collection: "", Key: "TODEL"}), Txid: "3", ChannelId: chainID}},
   570  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: "3", ChannelId: chainID}},
   571  		},
   572  	}
   573  
   574  	txParams.TxID = "3"
   575  	execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport)
   576  
   577  	//get the extra var and delete it
   578  	respSet = &mockpeer.MockResponseSet{
   579  		DoneFunc:  errorFunc,
   580  		ErrorFunc: nil,
   581  		Responses: []*mockpeer.MockResponse{
   582  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "4", ChannelId: chainID}},
   583  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: "4", ChannelId: chainID}},
   584  		},
   585  	}
   586  
   587  	txParams.TxID = "4"
   588  	execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport)
   589  
   590  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   591  
   592  	return nil
   593  }
   594  
   595  func getQueryStateByRange(t *testing.T, collection, chainID, ccname string, ccSide *mockpeer.MockCCComm, chaincodeSupport *ChaincodeSupport) error {
   596  	done := setuperror()
   597  	errorFunc := func(ind int, err error) {
   598  		done <- err
   599  	}
   600  
   601  	chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"}
   602  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil}
   603  	cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   604  	txid := util.GenerateUUID()
   605  	txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   606  
   607  	//create the response
   608  	queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage {
   609  		qr := &pb.QueryResponse{}
   610  		proto.Unmarshal(reqMsg.Payload, qr)
   611  		return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: protoutil.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid, ChannelId: chainID}
   612  	}
   613  	queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage {
   614  		qr := &pb.QueryResponse{}
   615  		proto.Unmarshal(reqMsg.Payload, qr)
   616  		return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: protoutil.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid, ChannelId: chainID}
   617  	}
   618  
   619  	var mkpeer []*mockpeer.MockResponse
   620  
   621  	mkpeer = append(mkpeer, &mockpeer.MockResponse{
   622  		RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION},
   623  		RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Payload: protoutil.MarshalOrPanic(&pb.GetStateByRange{Collection: collection, StartKey: "A", EndKey: "B"}), Txid: txid, ChannelId: chainID},
   624  	})
   625  
   626  	if collection == "" {
   627  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   628  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE},
   629  			RespMsg: queryStateNextFunc,
   630  		})
   631  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   632  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR},
   633  			RespMsg: queryStateCloseFunc,
   634  		})
   635  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   636  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE},
   637  			RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID},
   638  		})
   639  	} else {
   640  		// Range queries on private data is not yet implemented.
   641  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   642  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR},
   643  			RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid, ChannelId: chainID},
   644  		})
   645  	}
   646  
   647  	respSet := &mockpeer.MockResponseSet{
   648  		DoneFunc:  errorFunc,
   649  		ErrorFunc: nil,
   650  		Responses: mkpeer,
   651  	}
   652  
   653  	if collection == "" {
   654  		execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport)
   655  	} else {
   656  		execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport)
   657  	}
   658  
   659  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   660  
   661  	return nil
   662  }
   663  
   664  func cc2cc(t *testing.T, chainID, chainID2, ccname string, ccSide *mockpeer.MockCCComm, chaincodeSupport *ChaincodeSupport) error {
   665  	calledCC := "calledCC"
   666  	//starts and registers the CC
   667  	_, calledCCSide := startCC(t, chainID2, calledCC, chaincodeSupport)
   668  	if calledCCSide == nil {
   669  		t.Fatalf("start up failed for called CC")
   670  	}
   671  	defer calledCCSide.Quit()
   672  
   673  	done := setuperror()
   674  
   675  	errorFunc := func(ind int, err error) {
   676  		done <- err
   677  	}
   678  
   679  	chaincodeID := &pb.ChaincodeID{Name: calledCC, Version: "0"}
   680  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("deploycc")}, Decorations: nil}
   681  	cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   682  	txid := util.GenerateUUID()
   683  	//first deploy the new cc to LSCC
   684  	txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   685  
   686  	ccContext := &CCContext{
   687  		Name:    calledCC,
   688  		Version: "0",
   689  	}
   690  
   691  	deployCC(t, txParams, ccContext, cis.ChaincodeSpec, chaincodeSupport)
   692  
   693  	//commit
   694  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   695  
   696  	//now do the cc2cc
   697  	chaincodeID = &pb.ChaincodeID{Name: ccname, Version: "0"}
   698  	ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invokecc")}, Decorations: nil}
   699  	cis = &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   700  	txid = util.GenerateUUID()
   701  	txParams, txsim = startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   702  
   703  	//call a callable system CC, a regular cc, a regular but different cc on a different chain, a regular but same cc on a different chain,  and an uncallable system cc and expect an error inthe last one
   704  	respSet := &mockpeer.MockResponseSet{
   705  		DoneFunc:  errorFunc,
   706  		ErrorFunc: nil,
   707  		Responses: []*mockpeer.MockResponse{
   708  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "lscc.syscc"}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}},
   709  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}},
   710  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID2}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}},
   711  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "vscc.syscc"}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}},
   712  		},
   713  	}
   714  
   715  	respSet2 := &mockpeer.MockResponseSet{
   716  		DoneFunc:  nil,
   717  		ErrorFunc: nil,
   718  		Responses: []*mockpeer.MockResponse{
   719  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}},
   720  		},
   721  	}
   722  	calledCCSide.SetResponses(respSet2)
   723  
   724  	execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport)
   725  
   726  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   727  
   728  	//finally lets try a Bad ACL with CC-calling-CC
   729  	chaincodeID = &pb.ChaincodeID{Name: ccname, Version: "0"}
   730  	ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invokecc")}, Decorations: nil}
   731  	cis = &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   732  	txid = util.GenerateUUID()
   733  	txParams, txsim = startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   734  
   735  	mockAclProvider := chaincodeSupport.ACLProvider.(*mock.ACLProvider)
   736  	mockAclProvider.CheckACLStub = func(resource, channel string, _ interface{}) error {
   737  		if resource == resources.Peer_ChaincodeToChaincode && channel == chainID {
   738  			return errors.New("bad-acl-calling-cc")
   739  		}
   740  		return nil
   741  	}
   742  
   743  	//call regular cc but without ACL on called CC
   744  	respSet = &mockpeer.MockResponseSet{
   745  		DoneFunc:  errorFunc,
   746  		ErrorFunc: nil,
   747  		Responses: []*mockpeer.MockResponse{
   748  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}},
   749  		},
   750  	}
   751  
   752  	respSet2 = &mockpeer.MockResponseSet{
   753  		DoneFunc:  nil,
   754  		ErrorFunc: nil,
   755  		Responses: []*mockpeer.MockResponse{
   756  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}},
   757  		},
   758  	}
   759  
   760  	calledCCSide.SetResponses(respSet2)
   761  
   762  	execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport)
   763  
   764  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   765  
   766  	return nil
   767  }
   768  
   769  func getQueryResult(t *testing.T, collection, chainID, ccname string, ccSide *mockpeer.MockCCComm, chaincodeSupport *ChaincodeSupport) error {
   770  	done := setuperror()
   771  
   772  	errorFunc := func(ind int, err error) {
   773  		done <- err
   774  	}
   775  
   776  	chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"}
   777  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil}
   778  	cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   779  	txid := util.GenerateUUID()
   780  	txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   781  
   782  	kvs := make([]*plgr.KV, 1000)
   783  	for i := 0; i < 1000; i++ {
   784  		kvs[i] = &plgr.KV{Namespace: chainID, Key: fmt.Sprintf("%d", i), Value: []byte(fmt.Sprintf("%d", i))}
   785  	}
   786  
   787  	queryExec := &mockExecQuerySimulator{resultsIter: make(map[string]map[string]*mockResultsIterator)}
   788  	queryExec.resultsIter[ccname] = map[string]*mockResultsIterator{"goodquery": {kvs: kvs}}
   789  
   790  	queryExec.txsim = txParams.TXSimulator
   791  
   792  	//create the response
   793  	queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage {
   794  		qr := &pb.QueryResponse{}
   795  		proto.Unmarshal(reqMsg.Payload, qr)
   796  		return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: protoutil.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid, ChannelId: chainID}
   797  	}
   798  	queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage {
   799  		qr := &pb.QueryResponse{}
   800  		proto.Unmarshal(reqMsg.Payload, qr)
   801  		return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: protoutil.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid, ChannelId: chainID}
   802  	}
   803  
   804  	var mkpeer []*mockpeer.MockResponse
   805  
   806  	mkpeer = append(mkpeer, &mockpeer.MockResponse{
   807  		RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION},
   808  		RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Payload: protoutil.MarshalOrPanic(&pb.GetQueryResult{Collection: "", Query: "goodquery"}), Txid: txid, ChannelId: chainID},
   809  	})
   810  
   811  	if collection == "" {
   812  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   813  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE},
   814  			RespMsg: queryStateNextFunc,
   815  		})
   816  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   817  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR},
   818  			RespMsg: queryStateCloseFunc,
   819  		})
   820  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   821  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE},
   822  			RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID},
   823  		})
   824  	} else {
   825  		// Get query results on private data is not yet implemented.
   826  		mkpeer = append(mkpeer, &mockpeer.MockResponse{
   827  			RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR},
   828  			RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid, ChannelId: chainID},
   829  		})
   830  	}
   831  
   832  	respSet := &mockpeer.MockResponseSet{
   833  		DoneFunc:  errorFunc,
   834  		ErrorFunc: nil,
   835  		Responses: mkpeer,
   836  	}
   837  
   838  	if collection == "" {
   839  		execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport)
   840  	} else {
   841  		execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport)
   842  	}
   843  
   844  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   845  
   846  	return nil
   847  }
   848  
   849  func getHistory(t *testing.T, chainID, ccname string, ccSide *mockpeer.MockCCComm, chaincodeSupport *ChaincodeSupport) error {
   850  	done := setuperror()
   851  
   852  	errorFunc := func(ind int, err error) {
   853  		done <- err
   854  	}
   855  
   856  	chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"}
   857  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil}
   858  	cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
   859  	txid := util.GenerateUUID()
   860  	txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
   861  
   862  	kvs := make([]*plgr.KV, 1000)
   863  	for i := 0; i < 1000; i++ {
   864  		kvs[i] = &plgr.KV{Namespace: chainID, Key: fmt.Sprintf("%d", i), Value: []byte(fmt.Sprintf("%d", i))}
   865  	}
   866  
   867  	queryExec := &mockExecQuerySimulator{resultsIter: make(map[string]map[string]*mockResultsIterator)}
   868  	queryExec.resultsIter[ccname] = map[string]*mockResultsIterator{"goodquery": {kvs: kvs}}
   869  
   870  	queryExec.txsim = txParams.TXSimulator
   871  
   872  	//create the response
   873  	queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage {
   874  		qr := &pb.QueryResponse{}
   875  		proto.Unmarshal(reqMsg.Payload, qr)
   876  		return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: protoutil.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid}
   877  	}
   878  	queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage {
   879  		qr := &pb.QueryResponse{}
   880  		proto.Unmarshal(reqMsg.Payload, qr)
   881  		return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: protoutil.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid}
   882  	}
   883  
   884  	respSet := &mockpeer.MockResponseSet{
   885  		DoneFunc:  errorFunc,
   886  		ErrorFunc: nil,
   887  		Responses: []*mockpeer.MockResponse{
   888  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Payload: protoutil.MarshalOrPanic(&pb.GetQueryResult{Query: "goodquery"}), Txid: txid, ChannelId: chainID}},
   889  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: queryStateNextFunc},
   890  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: queryStateNextFunc},
   891  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, RespMsg: queryStateCloseFunc},
   892  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}},
   893  		},
   894  	}
   895  
   896  	execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport)
   897  
   898  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
   899  
   900  	return nil
   901  }
   902  
   903  //success case
   904  func TestStartAndWaitSuccess(t *testing.T) {
   905  	handlerRegistry := NewHandlerRegistry(false)
   906  	fakeRuntime := &mock.Runtime{}
   907  	fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error {
   908  		handlerRegistry.Ready("testcc:0")
   909  		return nil
   910  	}
   911  
   912  	launcher := &RuntimeLauncher{
   913  		Runtime:        fakeRuntime,
   914  		Registry:       handlerRegistry,
   915  		StartupTimeout: 10 * time.Second,
   916  		Metrics:        NewLaunchMetrics(&disabled.Provider{}),
   917  	}
   918  
   919  	//actual test - everythings good
   920  	err := launcher.Launch("testcc:0")
   921  	if err != nil {
   922  		t.Fatalf("expected success but failed with error %s", err)
   923  	}
   924  }
   925  
   926  //test timeout error
   927  func TestStartAndWaitTimeout(t *testing.T) {
   928  	fakeRuntime := &mock.Runtime{}
   929  	fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error {
   930  		time.Sleep(time.Second)
   931  		return nil
   932  	}
   933  
   934  	launcher := &RuntimeLauncher{
   935  		Runtime:        fakeRuntime,
   936  		Registry:       NewHandlerRegistry(false),
   937  		StartupTimeout: 500 * time.Millisecond,
   938  		Metrics:        NewLaunchMetrics(&disabled.Provider{}),
   939  	}
   940  
   941  	//the actual test - timeout 1000 > 500
   942  	err := launcher.Launch("testcc:0")
   943  	if err == nil {
   944  		t.Fatalf("expected error but succeeded")
   945  	}
   946  }
   947  
   948  //test container return error
   949  func TestStartAndWaitLaunchError(t *testing.T) {
   950  	fakeRuntime := &mock.Runtime{}
   951  	fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error {
   952  		return errors.New("Bad lunch; upset stomach")
   953  	}
   954  
   955  	launcher := &RuntimeLauncher{
   956  		Runtime:        fakeRuntime,
   957  		Registry:       NewHandlerRegistry(false),
   958  		StartupTimeout: 10 * time.Second,
   959  		Metrics:        NewLaunchMetrics(&disabled.Provider{}),
   960  	}
   961  
   962  	//actual test - container launch gives error
   963  	err := launcher.Launch("testcc:0")
   964  	if err == nil {
   965  		t.Fatalf("expected error but succeeded")
   966  	}
   967  	assert.EqualError(t, err, "error starting container: Bad lunch; upset stomach")
   968  }
   969  
   970  func TestGetTxContextFromHandler(t *testing.T) {
   971  	chnl := "test"
   972  	peerInstance, _, cleanup, err := initMockPeer(chnl)
   973  	assert.NoError(t, err, "failed to initialize mock peer")
   974  	defer cleanup()
   975  
   976  	h := Handler{
   977  		TXContexts:  NewTransactionContexts(),
   978  		BuiltinSCCs: map[string]struct{}{"lscc": {}},
   979  	}
   980  
   981  	txid := "1"
   982  	// test getTxContext for TEST channel, tx=1, msgType=IVNOKE_CHAINCODE and empty payload - empty payload => expect to return empty txContext
   983  	txContext, _ := h.getTxContextForInvoke(chnl, "1", []byte(""), "[%s]No ledger context for %s. Sending %s", 12345, "TestCC", pb.ChaincodeMessage_ERROR)
   984  	assert.Nil(t, txContext, "expected empty txContext for empty payload")
   985  
   986  	pldgr := peerInstance.GetLedger(chnl)
   987  
   988  	// prepare a payload and generate a TxContext in the handler to be used in the following getTxContextFroMessage with a normal UCC
   989  	txCtxGenerated, payload := genNewPldAndCtxFromLdgr(t, "shimTestCC", chnl, txid, pldgr, &h)
   990  
   991  	// test getTxContext for TEST channel, tx=1, msgType=IVNOKE_CHAINCODE and non empty payload => must return a non empty txContext
   992  	txContext, ccMsg := h.getTxContextForInvoke(chnl, txid, payload, "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR)
   993  	if txContext == nil || ccMsg != nil || txContext != txCtxGenerated {
   994  		t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg)
   995  	}
   996  
   997  	// test for another msgType (PUT_STATE) with the same payload ==> must return a non empty txContext
   998  	txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload, "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_PUT_STATE, pb.ChaincodeMessage_ERROR)
   999  	if txContext == nil || ccMsg != nil || txContext != txCtxGenerated {
  1000  		t.Fatalf("expected successful txContext for non empty payload and PUT_STATE msgType. triggerNextStateMsg: %s.", ccMsg)
  1001  	}
  1002  
  1003  	// get a new txContext for our SCC tests
  1004  	txid = "2"
  1005  	// reset channel to "" to test getting a context for an SCC without a channel
  1006  	chnl = ""
  1007  	txCtxGenerated, payload = genNewPldAndCtxFromLdgr(t, "lscc", chnl, txid, pldgr, &h)
  1008  
  1009  	// test getting a TxContext with an SCC without a channel => expect to return a non empty txContext
  1010  	txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload,
  1011  		"[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR)
  1012  	if txContext == nil || ccMsg != nil || txContext != txCtxGenerated {
  1013  		t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg)
  1014  	}
  1015  
  1016  	// now reset back to non empty channel and test with an SCC
  1017  	txid = "3"
  1018  	chnl = "TEST"
  1019  	txCtxGenerated, payload = genNewPldAndCtxFromLdgr(t, "lscc", chnl, txid, pldgr, &h)
  1020  
  1021  	// test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext
  1022  	txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload,
  1023  		"[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR)
  1024  	if txContext == nil || ccMsg != nil || txContext != txCtxGenerated {
  1025  		t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg)
  1026  	}
  1027  
  1028  	// now test getting a context with an empty channel and a UCC instead of an SCC
  1029  	txid = "4"
  1030  	chnl = ""
  1031  	txCtxGenerated, payload = genNewPldAndCtxFromLdgr(t, "shimTestCC", chnl, txid, pldgr, &h)
  1032  	// test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext
  1033  	txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload,
  1034  		"[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR)
  1035  	if txContext == nil || ccMsg != nil || txContext != txCtxGenerated {
  1036  		t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg)
  1037  	}
  1038  
  1039  	// new test getting a context with an empty channel without the ledger creating a new context for a UCC
  1040  	txid = "5"
  1041  	payload = genNewPld(t, "shimTestCC")
  1042  	// test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext
  1043  	txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload,
  1044  		"[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR)
  1045  	if txContext != nil || ccMsg == nil {
  1046  		t.Fatal("expected nil txContext for non empty payload and INVOKE_CHAINCODE msgType without the ledger generating a TxContext . unexpected non nil tcContext")
  1047  	}
  1048  
  1049  	// test same scenario as above but for an SCC this time
  1050  	txid = "6"
  1051  	payload = genNewPld(t, "lscc")
  1052  	// test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext
  1053  	txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload,
  1054  		"[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR)
  1055  	if txContext != nil || ccMsg == nil {
  1056  		t.Fatal("expected nil txContext for non empty payload and INVOKE_CHAINCODE msgType without the ledger generating a TxContext . unexpected non nil tcContext")
  1057  	}
  1058  }
  1059  
  1060  func genNewPldAndCtxFromLdgr(t *testing.T, ccName string, chnl string, txid string, pldgr ledger.PeerLedger, h *Handler) (*TransactionContext, []byte) {
  1061  	// create a new TxSimulator for the received txid
  1062  	txsim, err := pldgr.NewTxSimulator(txid)
  1063  	if err != nil {
  1064  		t.Fatalf("failed to create TxSimulator %s", err)
  1065  	}
  1066  	txParams := &ccprovider.TransactionParams{
  1067  		TxID:        txid,
  1068  		ChannelID:   chnl,
  1069  		TXSimulator: txsim,
  1070  		NamespaceID: ccName,
  1071  	}
  1072  	newTxCtxt, err := h.TXContexts.Create(txParams)
  1073  	if err != nil {
  1074  		t.Fatalf("Error creating TxContext by the handler for cc %s and channel '%s': %s", ccName, chnl, err)
  1075  	}
  1076  	if newTxCtxt == nil {
  1077  		t.Fatalf("Error creating TxContext: newTxCtxt created by the handler is nil for cc %s and channel '%s'.", ccName, chnl)
  1078  	}
  1079  	// build a new cds and payload for the CC called ccName
  1080  	payload := genNewPld(t, ccName)
  1081  	return newTxCtxt, payload
  1082  }
  1083  
  1084  func genNewPld(t *testing.T, ccName string) []byte {
  1085  	// build a new cds and payload for the CC called ccName
  1086  	chaincodeID := &pb.ChaincodeID{Name: ccName, Version: "0"}
  1087  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("deploycc")}, Decorations: nil}
  1088  	cds := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}
  1089  	payload, err := proto.Marshal(cds)
  1090  	if err != nil {
  1091  		t.Fatalf("failed to marshal CDS %s", err)
  1092  	}
  1093  	return payload
  1094  }
  1095  
  1096  func cc2SameCC(t *testing.T, chainID, chainID2, ccname string, ccSide *mockpeer.MockCCComm, chaincodeSupport *ChaincodeSupport) {
  1097  	//first deploy the CC on chainID2
  1098  	chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"}
  1099  	ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("deploycc")}, Decorations: nil}
  1100  	cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
  1101  
  1102  	txid := util.GenerateUUID()
  1103  	txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID2, cis, txid)
  1104  
  1105  	ccContext := &CCContext{
  1106  		Name:    ccname,
  1107  		Version: "0",
  1108  	}
  1109  
  1110  	deployCC(t, txParams, ccContext, cis.ChaincodeSpec, chaincodeSupport)
  1111  
  1112  	//commit
  1113  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
  1114  
  1115  	done := setuperror()
  1116  
  1117  	errorFunc := func(ind int, err error) {
  1118  		done <- err
  1119  	}
  1120  
  1121  	//now for the test - call the same cc on a different channel(should succeed), call the same cc on the same channel(should fail)
  1122  	//Note the error "Another request pending for this Txid. Cannot process." in the logs under TX "cctosamecctx"
  1123  	ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil}
  1124  	cis = &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}}
  1125  	txid = util.GenerateUUID()
  1126  	txParams, txsim = startTx(t, chaincodeSupport.Peer, chainID, cis, txid)
  1127  
  1128  	txid = "cctosamecctx"
  1129  	respSet := &mockpeer.MockResponseSet{
  1130  		DoneFunc:  errorFunc,
  1131  		ErrorFunc: nil,
  1132  		Responses: []*mockpeer.MockResponse{
  1133  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: ccname + ":0/" + chainID2}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}},
  1134  			{RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: ccname + ":0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}},
  1135  		},
  1136  	}
  1137  
  1138  	execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport)
  1139  
  1140  	endTx(t, chaincodeSupport.Peer, txParams, txsim, cis)
  1141  }
  1142  
  1143  func TestCCFramework(t *testing.T) {
  1144  	//register 2 channels
  1145  	chainID := "mockchainid"
  1146  	chainID2 := "secondchain"
  1147  	peerInstance, chaincodeSupport, cleanup, err := initMockPeer(chainID, chainID2)
  1148  	if err != nil {
  1149  		t.Fatalf("%s", err)
  1150  	}
  1151  	defer cleanup()
  1152  	defer finitMockPeer(peerInstance, chainID, chainID2)
  1153  	//create a chaincode
  1154  	ccname := "shimTestCC"
  1155  
  1156  	//starts and registers the CC
  1157  	_, ccSide := startCC(t, chainID, ccname, chaincodeSupport)
  1158  	if ccSide == nil {
  1159  		t.Fatalf("start up failed")
  1160  	}
  1161  	defer ccSide.Quit()
  1162  
  1163  	//call's init and does some PUT (after doing some negative testing)
  1164  	initializeCC(t, chainID, ccname, ccSide, chaincodeSupport)
  1165  
  1166  	//chaincode support should not allow dups
  1167  	handler := &Handler{chaincodeID: ccname + ":0", BuiltinSCCs: chaincodeSupport.BuiltinSCCs}
  1168  	if err := chaincodeSupport.HandlerRegistry.Register(handler); err == nil {
  1169  		t.Fatalf("expected re-register to fail")
  1170  	}
  1171  
  1172  	//call's init and does some PUT (after doing some negative testing)
  1173  	initializeCC(t, chainID2, ccname, ccSide, chaincodeSupport)
  1174  
  1175  	//call's invoke and do some GET
  1176  	invokeCC(t, chainID, ccname, ccSide, chaincodeSupport)
  1177  
  1178  	//call's query state range
  1179  	getQueryStateByRange(t, "", chainID, ccname, ccSide, chaincodeSupport)
  1180  
  1181  	//call's cc2cc on the same chaincode only call to chainID2 should succeed
  1182  	cc2SameCC(t, chainID, chainID2, ccname, ccSide, chaincodeSupport)
  1183  
  1184  	//call's cc2cc (variation with syscc calls)
  1185  	cc2cc(t, chainID, chainID2, ccname, ccSide, chaincodeSupport)
  1186  	// reset mock
  1187  	chaincodeSupport.ACLProvider = &mock.ACLProvider{}
  1188  
  1189  	//call's query result
  1190  	getQueryResult(t, "", chainID, ccname, ccSide, chaincodeSupport)
  1191  
  1192  	//call's history result
  1193  	getHistory(t, chainID, ccname, ccSide, chaincodeSupport)
  1194  
  1195  	ccSide.Quit()
  1196  }
  1197  
  1198  func TestExecuteTimeout(t *testing.T) {
  1199  	_, cs, cleanup, err := initMockPeer("testchannel")
  1200  	assert.NoError(t, err)
  1201  	defer cleanup()
  1202  
  1203  	tests := []struct {
  1204  		executeTimeout  time.Duration
  1205  		installTimeout  time.Duration
  1206  		namespace       string
  1207  		command         string
  1208  		expectedTimeout time.Duration
  1209  	}{
  1210  		{
  1211  			executeTimeout:  time.Second,
  1212  			installTimeout:  time.Minute,
  1213  			namespace:       "lscc",
  1214  			command:         "install",
  1215  			expectedTimeout: time.Minute,
  1216  		},
  1217  		{
  1218  			executeTimeout:  time.Minute,
  1219  			installTimeout:  time.Second,
  1220  			namespace:       "lscc",
  1221  			command:         "install",
  1222  			expectedTimeout: time.Minute,
  1223  		},
  1224  		{
  1225  			executeTimeout:  time.Second,
  1226  			installTimeout:  time.Minute,
  1227  			namespace:       "_lifecycle",
  1228  			command:         "InstallChaincode",
  1229  			expectedTimeout: time.Minute,
  1230  		},
  1231  		{
  1232  			executeTimeout:  time.Minute,
  1233  			installTimeout:  time.Second,
  1234  			namespace:       "_lifecycle",
  1235  			command:         "InstallChaincode",
  1236  			expectedTimeout: time.Minute,
  1237  		},
  1238  		{
  1239  			executeTimeout:  time.Second,
  1240  			installTimeout:  time.Minute,
  1241  			namespace:       "_lifecycle",
  1242  			command:         "anything",
  1243  			expectedTimeout: time.Second,
  1244  		},
  1245  		{
  1246  			executeTimeout:  time.Second,
  1247  			installTimeout:  time.Minute,
  1248  			namespace:       "lscc",
  1249  			command:         "anything",
  1250  			expectedTimeout: time.Second,
  1251  		},
  1252  		{
  1253  			executeTimeout:  time.Second,
  1254  			installTimeout:  time.Minute,
  1255  			namespace:       "anything",
  1256  			command:         "",
  1257  			expectedTimeout: time.Second,
  1258  		},
  1259  	}
  1260  	for _, tt := range tests {
  1261  		t.Run(tt.namespace+"_"+tt.command, func(t *testing.T) {
  1262  			cs.ExecuteTimeout = tt.executeTimeout
  1263  			cs.InstallTimeout = tt.installTimeout
  1264  			input := &pb.ChaincodeInput{Args: util.ToChaincodeArgs(tt.command)}
  1265  
  1266  			result := cs.executeTimeout(tt.namespace, input)
  1267  			assert.Equalf(t, tt.expectedTimeout, result, "want %s, got %s", tt.expectedTimeout, result)
  1268  		})
  1269  	}
  1270  }
  1271  
  1272  func TestMaxDuration(t *testing.T) {
  1273  	tests := []struct {
  1274  		durations []time.Duration
  1275  		expected  time.Duration
  1276  	}{
  1277  		{
  1278  			durations: []time.Duration{},
  1279  			expected:  time.Duration(0),
  1280  		},
  1281  		{
  1282  			durations: []time.Duration{time.Second, time.Hour, time.Minute},
  1283  			expected:  time.Hour,
  1284  		},
  1285  		{
  1286  			durations: []time.Duration{-time.Second},
  1287  			expected:  time.Duration(0),
  1288  		},
  1289  	}
  1290  	for _, tt := range tests {
  1291  		result := maxDuration(tt.durations...)
  1292  		assert.Equalf(t, tt.expected, result, "want %s got %s", tt.expected, result)
  1293  	}
  1294  }