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 }