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