github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/peer/chaincode/invoke_test.go (about)

     1  /*
     2   Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4   Licensed under the Apache License, Version 2.0 (the "License");
     5   you may not use this file except in compliance with the License.
     6   You may obtain a copy of the License at
     7  
     8        http://www.apache.org/licenses/LICENSE-2.0
     9  
    10   Unless required by applicable law or agreed to in writing, software
    11   distributed under the License is distributed on an "AS IS" BASIS,
    12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   See the License for the specific language governing permissions and
    14   limitations under the License.
    15  */
    16  
    17  package chaincode
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"testing"
    24  
    25  	"github.com/hyperledger/fabric/common/flogging"
    26  	"github.com/hyperledger/fabric/common/util"
    27  	"github.com/hyperledger/fabric/msp"
    28  	"github.com/hyperledger/fabric/peer/common"
    29  	cb "github.com/hyperledger/fabric/protos/common"
    30  	pb "github.com/hyperledger/fabric/protos/peer"
    31  	"github.com/hyperledger/fabric/protos/utils"
    32  	logging "github.com/op/go-logging"
    33  	"github.com/stretchr/testify/assert"
    34  )
    35  
    36  func TestInvokeCmd(t *testing.T) {
    37  	InitMSP()
    38  	mockCF, err := getMockChaincodeCmdFactory()
    39  	assert.NoError(t, err, "Error getting mock chaincode command factory")
    40  
    41  	cmd := invokeCmd(mockCF)
    42  	addFlags(cmd)
    43  	args := []string{"-n", "example02", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}"}
    44  	cmd.SetArgs(args)
    45  	err = cmd.Execute()
    46  	assert.NoError(t, err, "Run chaincode invoke cmd error")
    47  
    48  	// Error case 1: no orderer endpoints
    49  	t.Logf("Start error case 1: no orderer endpoints")
    50  	getEndorserClient := common.GetEndorserClientFnc
    51  	getOrdererEndpointOfChain := common.GetOrdererEndpointOfChainFnc
    52  	getBroadcastClient := common.GetBroadcastClientFnc
    53  	getDefaultSigner := common.GetDefaultSignerFnc
    54  	defer func() {
    55  		common.GetEndorserClientFnc = getEndorserClient
    56  		common.GetOrdererEndpointOfChainFnc = getOrdererEndpointOfChain
    57  		common.GetBroadcastClientFnc = getBroadcastClient
    58  		common.GetDefaultSignerFnc = getDefaultSigner
    59  	}()
    60  	common.GetEndorserClientFnc = func() (pb.EndorserClient, error) {
    61  		return mockCF.EndorserClient, nil
    62  	}
    63  	common.GetOrdererEndpointOfChainFnc = func(chainID string, signer msp.SigningIdentity, endorserClient pb.EndorserClient) ([]string, error) {
    64  		return []string{}, nil
    65  	}
    66  	cmd = invokeCmd(nil)
    67  	addFlags(cmd)
    68  	args = []string{"-n", "example02", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}"}
    69  	cmd.SetArgs(args)
    70  	err = cmd.Execute()
    71  	assert.Error(t, err)
    72  
    73  	// Error case 2: getEndorserClient returns error
    74  	t.Logf("Start error case 2: getEndorserClient returns error")
    75  	common.GetEndorserClientFnc = func() (pb.EndorserClient, error) {
    76  		return nil, errors.New("error")
    77  	}
    78  	err = cmd.Execute()
    79  	assert.Error(t, err)
    80  
    81  	// Error case 3: getDefaultSignerFnc returns error
    82  	t.Logf("Start error case 3: getDefaultSignerFnc returns error")
    83  	common.GetEndorserClientFnc = func() (pb.EndorserClient, error) {
    84  		return mockCF.EndorserClient, nil
    85  	}
    86  	common.GetDefaultSignerFnc = func() (msp.SigningIdentity, error) {
    87  		return nil, errors.New("error")
    88  	}
    89  	err = cmd.Execute()
    90  	assert.Error(t, err)
    91  	common.GetDefaultSignerFnc = common.GetDefaultSigner
    92  
    93  	// Error case 4: getOrdererEndpointOfChainFnc returns error
    94  	t.Logf("Start error case 4: getOrdererEndpointOfChainFnc returns error")
    95  	common.GetEndorserClientFnc = func() (pb.EndorserClient, error) {
    96  		return mockCF.EndorserClient, nil
    97  	}
    98  	common.GetOrdererEndpointOfChainFnc = func(chainID string, signer msp.SigningIdentity, endorserClient pb.EndorserClient) ([]string, error) {
    99  		return nil, errors.New("error")
   100  	}
   101  	err = cmd.Execute()
   102  	assert.Error(t, err)
   103  
   104  	// Error case 5: getBroadcastClient returns error
   105  	t.Logf("Start error case 5: getBroadcastClient returns error")
   106  	common.GetOrdererEndpointOfChainFnc = func(chainID string, signer msp.SigningIdentity, endorserClient pb.EndorserClient) ([]string, error) {
   107  		return []string{"localhost:9999"}, nil
   108  	}
   109  	common.GetBroadcastClientFnc = func(orderingEndpoint string, tlsEnabled bool, caFile string) (common.BroadcastClient, error) {
   110  		return nil, errors.New("error")
   111  	}
   112  	err = cmd.Execute()
   113  	assert.Error(t, err)
   114  
   115  	// Success case
   116  	t.Logf("Start success case")
   117  	common.GetBroadcastClientFnc = func(orderingEndpoint string, tlsEnabled bool, caFile string) (common.BroadcastClient, error) {
   118  		return mockCF.BroadcastClient, nil
   119  	}
   120  	err = cmd.Execute()
   121  	assert.NoError(t, err)
   122  }
   123  
   124  func TestInvokeCmdEndorsementError(t *testing.T) {
   125  	InitMSP()
   126  	mockCF, err := getMockChaincodeCmdFactoryWithErr()
   127  	assert.NoError(t, err, "Error getting mock chaincode command factory")
   128  
   129  	cmd := invokeCmd(mockCF)
   130  	addFlags(cmd)
   131  	args := []string{"-n", "example02", "-c", "{\"Args\": [\"invoke\",\"a\",\"b\",\"10\"]}"}
   132  	cmd.SetArgs(args)
   133  	err = cmd.Execute()
   134  	assert.Error(t, err, "Expected error executing invoke command")
   135  }
   136  
   137  func TestInvokeCmdEndorsementFailure(t *testing.T) {
   138  	InitMSP()
   139  	ccRespStatus := [2]int32{502, 400}
   140  	ccRespPayload := [][]byte{[]byte("Invalid function name"), []byte("Incorrect parameters")}
   141  
   142  	for i := 0; i < 2; i++ {
   143  		mockCF, err := getMockChaincodeCmdFactoryEndorsementFailure(ccRespStatus[i], ccRespPayload[i])
   144  		assert.NoError(t, err, "Error getting mock chaincode command factory")
   145  
   146  		cmd := invokeCmd(mockCF)
   147  		addFlags(cmd)
   148  		args := []string{"-n", "example02", "-c", "{\"Args\": [\"invokeinvalid\",\"a\",\"b\",\"10\"]}"}
   149  		cmd.SetArgs(args)
   150  
   151  		// set logger to logger with a backend that writes to a byte buffer
   152  		var buffer bytes.Buffer
   153  		logger.SetBackend(logging.AddModuleLevel(logging.NewLogBackend(&buffer, "", 0)))
   154  		// reset the logger after test
   155  		defer func() {
   156  			flogging.Reset()
   157  		}()
   158  		// make sure buffer is "clean" before running the invoke
   159  		buffer.Reset()
   160  
   161  		err = cmd.Execute()
   162  		assert.NoError(t, err)
   163  		assert.Regexp(t, "Endorsement failure during invoke", buffer.String())
   164  		assert.Regexp(t, fmt.Sprintf("chaincode result: status:%d payload:\"%s\"", ccRespStatus[i], ccRespPayload[i]), buffer.String())
   165  	}
   166  
   167  }
   168  
   169  // Returns mock chaincode command factory
   170  func getMockChaincodeCmdFactory() (*ChaincodeCmdFactory, error) {
   171  	signer, err := common.GetDefaultSigner()
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  	mockResponse := &pb.ProposalResponse{
   176  		Response:    &pb.Response{Status: 200},
   177  		Endorsement: &pb.Endorsement{},
   178  	}
   179  	mockEndorserClient := common.GetMockEndorserClient(mockResponse, nil)
   180  	mockBroadcastClient := common.GetMockBroadcastClient(nil)
   181  	mockCF := &ChaincodeCmdFactory{
   182  		EndorserClient:  mockEndorserClient,
   183  		Signer:          signer,
   184  		BroadcastClient: mockBroadcastClient,
   185  	}
   186  	return mockCF, nil
   187  }
   188  
   189  // Returns mock chaincode command factory that is constructed with an endorser
   190  // client that returns an error for proposal request
   191  func getMockChaincodeCmdFactoryWithErr() (*ChaincodeCmdFactory, error) {
   192  	signer, err := common.GetDefaultSigner()
   193  	if err != nil {
   194  		return nil, err
   195  	}
   196  
   197  	errMsg := "invoke error"
   198  	mockEndorerClient := common.GetMockEndorserClient(nil, errors.New(errMsg))
   199  	mockBroadcastClient := common.GetMockBroadcastClient(nil)
   200  
   201  	mockCF := &ChaincodeCmdFactory{
   202  		EndorserClient:  mockEndorerClient,
   203  		Signer:          signer,
   204  		BroadcastClient: mockBroadcastClient,
   205  	}
   206  	return mockCF, nil
   207  }
   208  
   209  // Returns mock chaincode command factory
   210  func getMockChaincodeCmdFactoryEndorsementFailure(ccRespStatus int32, ccRespPayload []byte) (*ChaincodeCmdFactory, error) {
   211  	signer, err := common.GetDefaultSigner()
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  
   216  	// create a proposal from a ChaincodeInvocationSpec
   217  	prop, _, err := utils.CreateChaincodeProposal(cb.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), createCIS(), nil)
   218  	if err != nil {
   219  		return nil, fmt.Errorf("Could not create chaincode proposal, err %s\n", err)
   220  	}
   221  
   222  	response := &pb.Response{Status: ccRespStatus, Payload: ccRespPayload}
   223  	result := []byte("res")
   224  	ccid := &pb.ChaincodeID{Name: "foo", Version: "v1"}
   225  
   226  	mockRespFailure, err := utils.CreateProposalResponseFailure(prop.Header, prop.Payload, response, result, nil, ccid, nil)
   227  	if err != nil {
   228  
   229  		return nil, fmt.Errorf("Could not create proposal response failure, err %s\n", err)
   230  	}
   231  
   232  	mockEndorserClient := common.GetMockEndorserClient(mockRespFailure, nil)
   233  	mockBroadcastClient := common.GetMockBroadcastClient(nil)
   234  	mockCF := &ChaincodeCmdFactory{
   235  		EndorserClient:  mockEndorserClient,
   236  		Signer:          signer,
   237  		BroadcastClient: mockBroadcastClient,
   238  	}
   239  	return mockCF, nil
   240  }
   241  
   242  func createCIS() *pb.ChaincodeInvocationSpec {
   243  	return &pb.ChaincodeInvocationSpec{
   244  		ChaincodeSpec: &pb.ChaincodeSpec{
   245  			Type:        pb.ChaincodeSpec_GOLANG,
   246  			ChaincodeId: &pb.ChaincodeID{Name: "chaincode_name"},
   247  			Input:       &pb.ChaincodeInput{Args: [][]byte{[]byte("arg1"), []byte("arg2")}}}}
   248  }