Skip to content

Commit

Permalink
FABN-826 restore backward compatibility for errors
Browse files Browse the repository at this point in the history
Error handling was still not backward compatible with previous release of
fabric for invoke, install, instantiate, upgrade. This fix should restore
backward compatibility

Change-Id: I70dc50261e8cd3acf20c58590006defa699e6251
Signed-off-by: Dave Kelsey <d_kelsey@uk.ibm.com>
  • Loading branch information
Dave Kelsey committed Jul 23, 2018
1 parent f4793ec commit 25fa4b0
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 92 deletions.
14 changes: 11 additions & 3 deletions fabric-client/lib/Peer.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,18 @@ var Peer = class extends Remote {
} else {
if (proposalResponse) {
logger.debug('%s - Received proposal response from peer "%s": status - %s', method, self._url, proposalResponse.response.status);
resolve(proposalResponse);
// 400 is the error threshold level, anything below that the endorser will endorse it.
if (proposalResponse.response && proposalResponse.response.status < 400) {
resolve(proposalResponse);
} else if (proposalResponse.response && proposalResponse.response.message) {
reject(new Error(proposalResponse.response.message));
} else {
logger.error('GRPC client failed to get a proper response from the peer "%s".', self._url);
reject(new Error(util.format('GRPC client failed to get a proper response from the peer "%s".', self._url)));
}
} else {
logger.error('GRPC client failed to get a proper response from the peer "%s".', self._url);
reject(new Error(util.format('GRPC client failed to get a proper response from the peer "%s".', self._url)));
logger.error('GRPC client got a null or undefined response from the peer "%s".', self._url);
reject(new Error(util.format('GRPC client got a null or undefined response from the peer "%s".', self._url)));
}
}
});
Expand Down
8 changes: 4 additions & 4 deletions test/fixtures/src/github.com/example_cc/example_cc.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
return t.query(stub, args)
}

if function == "queryError" {
return t.queryError(stub, args)
if function == "throwError" {
return t.throwError(stub, args)
}

if function == "move" {
Expand Down Expand Up @@ -203,8 +203,8 @@ func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string)
return shim.Success(Avalbytes)
}

func (t *SimpleChaincode) queryError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
err := fmt.Errorf("queryError: an error occurred")
func (t *SimpleChaincode) throwError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
err := fmt.Errorf("throwError: an error occurred")
return shim.Error(err.Error())
}

Expand Down
8 changes: 4 additions & 4 deletions test/fixtures/src/github.com/example_cc1/example_cc1.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
return t.query(stub, args)
}

if function == "queryError" {
return t.queryError(stub, args)
if function == "throwError" {
return t.throwError(stub, args)
}

if function == "move" {
Expand Down Expand Up @@ -178,8 +178,8 @@ func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string)
return shim.Success(Avalbytes)
}

func (t *SimpleChaincode) queryError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
err := fmt.Errorf("queryError: an error occurred")
func (t *SimpleChaincode) throwError(stub shim.ChaincodeStubInterface, args []string) pb.Response {
err := fmt.Errorf("throwError: an error occurred")
return shim.Error(err.Error())
}

Expand Down
8 changes: 4 additions & 4 deletions test/fixtures/src/node_cc/example_cc/chaincode.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ var Chaincode = class {
return this.query(stub, args);
}

if (fcn === 'queryError') {
return this.queryError(stub, args);
if (fcn === 'throwError') {
return this.throwError(stub, args);
}

if (fcn === 'move') {
Expand Down Expand Up @@ -183,8 +183,8 @@ var Chaincode = class {
return shim.success(Buffer.from(Aval.toString()));
}

async queryError(stub, args) {
return shim.error(new Error('queryError: an error occurred'));
async throwError(stub, args) {
return shim.error(new Error('throwError: an error occurred'));
}
};

Expand Down
8 changes: 4 additions & 4 deletions test/fixtures/src/node_cc/example_cc1/chaincode.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ var Chaincode = class {
return this.query(stub, args);
}

if (fcn === 'queryError') {
return this.queryError(stub, args);
if (fcn === 'throwError') {
return this.throwError(stub, args);
}

if (fcn === 'move') {
Expand Down Expand Up @@ -160,8 +160,8 @@ var Chaincode = class {
return shim.success(Buffer.from(Aval.toString()));
}

async queryError(stub, args) {
return shim.error(new Error('queryError: an error occurred'));
async throwError(stub, args) {
return shim.error(new Error('throwError: an error occurred'));
}

async testTransient(stub) {
Expand Down
53 changes: 34 additions & 19 deletions test/integration/e2e/e2eUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ function instantiateChaincodeWithId(userOrg, chaincode_id, chaincode_path, versi
let success = false;
if (proposalResponses && proposalResponses.length > 0) {
proposalResponses.forEach((response) => {
if (response &&
response.response.message.indexOf('Did not find expected key "test" in the transient map of the proposal')) {
if (response && response instanceof Error &&
response.message.includes('Did not find expected key "test" in the transient map of the proposal')) {
success = true;
} else {
success = false;
Expand Down Expand Up @@ -577,28 +577,38 @@ function invokeChaincode(userOrg, version, chaincodeId, t, useStore, fcn, args,
for(let i in proposalResponses) {
let one_good = false;
let proposal_response = proposalResponses[i];
logger.debug('invoke chaincode, proposal response: ' + util.inspect(proposal_response, {depth: null}));
if( proposal_response.response && proposal_response.response.status === 200) {
t.pass('transaction proposal has response status of good');
one_good = channel.verifyProposalResponse(proposal_response);
if(one_good) {
t.pass('transaction proposal signature and endorser are valid');
}

// check payload
let payload = proposal_response.response.payload.toString();
// verify payload is equal to expectedResult
if (payload === expectedResult){
t.pass('transaction proposal payloads are valid');
if (expectedResult instanceof Error) {
t.true((proposal_response instanceof Error), 'proposal response should be an instance of error');
t.true(proposal_response.message.includes(expectedResult.message), 'error should contain the correct message: ' + expectedResult.message);
} else {
logger.debug('invoke chaincode, proposal response: ' + util.inspect(proposal_response, {depth: null}));
if( proposal_response.response && proposal_response.response.status === 200) {
t.pass('transaction proposal has response status of good');
one_good = channel.verifyProposalResponse(proposal_response);
if(one_good) {
t.pass('transaction proposal signature and endorser are valid');
}

// check payload
let payload = proposal_response.response.payload.toString();
// verify payload is equal to expectedResult
if (payload === expectedResult){
t.pass('transaction proposal payloads are valid');
} else {
one_good = false;
t.fail('transaction proposal payloads are invalid, expect ' + expectedResult + ', but got ' + payload);
}
} else {
one_good = false;
t.fail('transaction proposal payloads are invalid, expect ' + expectedResult + ', but got ' + payload);
t.fail('invokeChaincode: transaction proposal was bad');
}
} else {
t.fail('invokeChaincode: transaction proposal was bad');
all_good = all_good & one_good;
}
all_good = all_good & one_good;
}
if (expectedResult instanceof Error) {
return;
}

if (all_good) {
// check all the read/write sets to see if the same, verify that each peer
// got the same results on the proposal
Expand Down Expand Up @@ -679,6 +689,11 @@ function invokeChaincode(userOrg, version, chaincodeId, t, useStore, fcn, args,
throw new Error('Failed to send proposal due to error: ' + err.stack ? err.stack : err);

}).then((response) => {
if (expectedResult instanceof Error) {
channel.close();
t.pass('Successfully closed all connections');
return true;
}

if (response.status === 'SUCCESS') {
t.pass('Successfully sent transaction to the orderer.');
Expand Down
43 changes: 22 additions & 21 deletions test/integration/e2e/invoke-transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,30 @@ const e2eUtils = require('./e2eUtils.js');
const testUtils = require('../../unit/util');
const chaincodeId = testUtils.END2END.chaincodeId;

test('\n\n***** End-to-end flow: invoke transaction to move money *****\n\n', (t) => {
test('\n\n***** End-to-end flow: invoke transaction to move money *****\n\n', async (t) => {
const fcn = 'move';
const args = ['a', 'b','100'];
const expectedResult = 'move succeed';
e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult)
.then((result) => {
if(result){
t.pass('Successfully invoke transaction chaincode on channel');
return sleep(5000);
}
else {
t.fail('Failed to invoke transaction chaincode ');
t.end();
}
}, (err) => {
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
t.end();
}).then(() => {
t.end();
}).catch((err) => {
t.fail('Test failed due to unexpected reasons. ' + err.stack ? err.stack : err);
t.end();
});
let expectedResult = 'move succeed';
try {
let result = await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult);
if(result){
t.pass('Successfully invoke transaction chaincode on channel');
await sleep(5000);
}
else {
t.fail('Failed to invoke transaction chaincode ');
}
} catch(err) {
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
}

try {
expectedResult = new Error('throwError: an error occurred');
await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, 'throwError', args, expectedResult);
} catch(err) {
t.fail('Failed to query chaincode on the channel. ' + err.stack ? err.stack : err);
}
t.end();
});

function sleep(ms) {
Expand Down
6 changes: 3 additions & 3 deletions test/integration/e2e/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ test('\n\n***** End-to-end flow: query chaincode *****\n\n', async (t) => {
}

try {
expectedResult = new Error('queryError: an error occurred');
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'queryError', args, expectedResult, chaincodeId, t);
expectedResult = new Error('throwError: an error occurred');
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'throwError', args, expectedResult, chaincodeId, t);
if(result){
t.pass('Successfully query chaincode on the channel');
t.pass('Successfully handled error from query');
}
else {
t.fail('Failed to query chaincode ');
Expand Down
4 changes: 2 additions & 2 deletions test/integration/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ test('\n\n** Test chaincode install using chaincodePath to create chaincodePacka
params.testDesc = params.testDesc+'0';
installChaincode(params, t)
.then((info) => {
if (info && info.response.message.indexOf('install.'+params.chaincodeVersion+' exists') > 0) {
if (info && info instanceof Error && info.message.includes('install.'+params.chaincodeVersion+' exists')) {
t.pass('passed check for exists on install again');
t.end();
} else {
Expand Down Expand Up @@ -115,7 +115,7 @@ test('\n\n** Test chaincode install using chaincodePackage[byte] **\n\n', (t) =>
params.testDesc = params.testDesc+'0';
installChaincode(params, t)
.then((info) => {
if (info && info.response.message.indexOf('install-package.'+params.chaincodeVersion+' exists') > 0) {
if (info && info instanceof Error && info.message.includes('install-package.'+params.chaincodeVersion+' exists')) {
t.pass('passed check for exists same code again');
t.end();
} else {
Expand Down
50 changes: 29 additions & 21 deletions test/integration/nodechaincode/invoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,37 @@ var e2eUtils = require('../e2e/e2eUtils.js');
var testUtils = require('../../unit/util');
var chaincodeId = testUtils.NODE_END2END.chaincodeId;

test('\n\n***** Node-Chaincode End-to-end flow: invoke transaction to move money *****\n\n', (t) => {
test('\n\n***** Node-Chaincode End-to-end flow: invoke transaction to move money *****\n\n', async (t) => {
const fcn = 'move';
const args = ['a', 'b','100'];
const expectedResult = 'move succeed';
e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult)
.then((result) => {
if(result){
t.pass('Successfully invoke transaction chaincode on channel');
return sleep(5000);
}
else {
t.fail('Failed to invoke transaction chaincode ');
t.end();
}
}, (err) => {
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
t.end();
}).then(() => {
t.end();
}).catch((err) => {
t.fail('Test failed due to unexpected reasons. ' + err.stack ? err.stack : err);
t.end();
});
let expectedResult = 'move succeed';
try {
let result = await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, fcn, args, expectedResult);
if(result){
t.pass('Successfully invoke transaction chaincode on channel');
await sleep(5000);
}
else {
t.fail('Failed to invoke transaction chaincode ');
}
} catch(err) {
t.fail('Failed to invoke transaction chaincode on channel. ' + err.stack ? err.stack : err);
}

try {
expectedResult = new Error('throwError: an error occurred');
let result = await e2eUtils.invokeChaincode('org2', 'v0', chaincodeId, t, false/*useStore*/, 'throwError', args, expectedResult);
if(result){
t.pass('Successfully handled invocation errors');
}
else {
t.fail('Failed to invoke transaction chaincode ');
}

} catch(err) {
t.fail('Failed to query chaincode on the channel. ' + err.stack ? err.stack : err);
}
t.end();
});

function sleep(ms) {
Expand Down
6 changes: 3 additions & 3 deletions test/integration/nodechaincode/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ test('\n\n***** Node-Chaincode End-to-end flow: query chaincode *****\n\n', asyn
}

try {
expectedResult = new Error('queryError: an error occurred');
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'queryError', args, expectedResult, chaincodeId, t);
expectedResult = new Error('throwError: an error occurred');
let result = await e2eUtils.queryChaincode('org2', 'v0', targets, 'throwError', args, expectedResult, chaincodeId, t);
if(result){
t.pass('Successfully query chaincode on the channel');
t.pass('Sucessfully handled error from a query');
}
else {
t.fail('Failed to query chaincode ');
Expand Down
8 changes: 4 additions & 4 deletions test/unit/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,15 @@ module.exports.checkResults = function(results, error_snip, t) {
var proposalResponses = results[0];
for(var i in proposalResponses) {
let proposal_response = proposalResponses[i];
if(proposal_response.response && proposal_response.response.message) {
if(proposal_response.response.message.indexOf(error_snip) > -1) {
if(proposal_response instanceof Error) {
if(proposal_response.message.includes(error_snip)) {
t.pass('Successfully got the error' + error_snip);
} else {
t.fail( 'Failed to get error with ' + error_snip + ' :: response message ' + proposal_response.response.message);
t.fail( 'Failed to get error with ' + error_snip + ' :: response message ' + proposal_response.message);
}
}
else {
t.fail(' Failed :: no response message found and should have had an error with '+ error_snip);
t.fail(' Failed :: no Error response message found and should have had an error with '+ error_snip);
}
}
};
Expand Down

0 comments on commit 25fa4b0

Please sign in to comment.