Skip to content

Commit

Permalink
FABN-1453 NodeSDK add discovery test (#94)
Browse files Browse the repository at this point in the history
Add the discovery based query handler cucumber scenario test back
in after the rewrite had removed them.
Update the common utility code to be all for easier testing of
results.

Signed-off-by: Bret Harrison <[email protected]>
  • Loading branch information
harrisob authored and bestbeforetoday committed Jan 22, 2020
1 parent af14315 commit 94bcabc
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 39 deletions.
2 changes: 1 addition & 1 deletion fabric-common/lib/Proposal.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ message Endorsement {
if (this.type === 'Query') {
this._queryResults = [];
this._proposalResponses.forEach((response) => {
if (response.response && response.response.payload) {
if (response.response && response.response.payload && response.response.payload.length > 0) {
logger.debug('%s - have payload', method);
this._queryResults.push(response.response.payload);
} else {
Expand Down
6 changes: 3 additions & 3 deletions fabric-network/src/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ class Transaction {
request.targets = channel.getCommitters();
}

// by now we should have a discovery handler or the target orderers
// to perform the commit have been assigned from the channel
// by now we should have a discovery handler or use the target orderers
// that have been assigned from the channel to perform the commit

const commit = endorsement.newCommit();
commit.build(this.identityContext, request);
Expand Down Expand Up @@ -310,7 +310,7 @@ class Transaction {
// as part of an extended client side validation strategy but for now don't perform any client
// side checks as the peers will have to do this anyway and it impacts client performance
if (responseContent.response.status < 400) {
logger.debug('%s: valid response from peer %j', method, responseContent.connection);
logger.debug('%s: valid response from peer %j, status:%s', method, responseContent.connection, responseContent.response.status);
validResponses.push(responseContent);
} else {
logger.warn('%s: invalid response from peer %j', method, responseContent.peer);
Expand Down
10 changes: 6 additions & 4 deletions test/ts-scenario/config/handlers/sample-query-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ class SampleQueryHandler implements QueryHandler {
this.requestTimeout = requestTimeout;
}

public async evaluate(query: Query): Promise<any> {
public async evaluate(query: Query): Promise<Buffer> {
// send to all
const results = await query.send({targets: this.peers}, {requestTimeout: this.requestTimeout});

// check the results
if (results) {
// first check to see if we have any good results
// first check to see if we have results (any result with a payload will be here)
if (results && results.queryResults && results.queryResults.length > 0) {
return results.queryResults[0];
// maybe the request failed
Expand All @@ -37,10 +37,12 @@ class SampleQueryHandler implements QueryHandler {
// maybe the query failed
} else if (results.responses) {
for (const response of results.responses) {
if (response.response.status >= 400) {
return response.response.payload;
if (response.response.message) {
// return the first one found
throw new Error(`Query failed status:${response.response.status} message:${response.response.message}`);
}
}
throw new Error('Unknown result');
}
}

Expand Down
12 changes: 10 additions & 2 deletions test/ts-scenario/features/discovery.feature
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,16 @@ Feature: Configure Fabric using CLI and submit/evaluate using a network Gateway
When I modify myDiscoveryGateway to submit a transaction with args [createCar,1005,Ford,Mustang,Silver,Andy] for contract fabcar instantiated on channel discoverychannel using handler option NETWORK_SCOPE_ANYFORTX
Then The gateway named myDiscoveryGateway has a event type response containing "status":"VALID"

Scenario: Using a Gateway to evaluate transactions I can use different query handler strategies
When I modify myDiscoveryGateway to evaluate a transaction with args [queryCar,1001] for contract fabcar instantiated on channel discoverychannel using handler option MSPID_SCOPE_SINGLE
Then The gateway named myDiscoveryGateway has a evaluate type response matching {"color":"red","docType":"car","make":"Ariel","model":"Atom","owner":"Nick"}
When I modify myDiscoveryGateway to evaluate a transaction with args [queryCar,1001] for contract fabcar instantiated on channel discoverychannel using handler option MSPID_SCOPE_ROUND_ROBIN
Then The gateway named myDiscoveryGateway has a evaluate type response matching {"color":"red","docType":"car","make":"Ariel","model":"Atom","owner":"Nick"}
When I modify myDiscoveryGateway to evaluate a transaction with args [queryCar,1001] for contract fabcar instantiated on channel discoverychannel using handler option custom
Then The gateway named myDiscoveryGateway has a evaluate type response matching {"color":"red","docType":"car","make":"Ariel","model":"Atom","owner":"Nick"}

Scenario: Using a Gateway I can use transient data
When I modify myDiscoveryGateway to submit a transaction with transient data using args [getTransient,value1,value2] for contract fabcar instantiated on channel discoverychannel
Then The gateway named myDiscoveryGateway has a submit type response matching "{\"key0\":\"value1\",\"key1\":\"value2\"}"
Then The gateway named myDiscoveryGateway has a submit type response matching {"key0":"value1","key1":"value2"}
When I modify myDiscoveryGateway to evaluate a transaction with transient data using args [getTransient,valueA,valueB] for contract fabcar instantiated on channel discoverychannel
Then The gateway named myDiscoveryGateway has a evaluate type response matching "{\"key0\":\"valueA\",\"key1\":\"valueB\"}"
Then The gateway named myDiscoveryGateway has a evaluate type response matching {"key0":"valueA","key1":"valueB"}
6 changes: 3 additions & 3 deletions test/ts-scenario/features/gateway.feature
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ Feature: Configure Fabric using CLI and submit/evaluate using a network Gateway

Scenario: Using a Gateway I can use transient data
When I modify mycouchgateway to submit a transaction with transient data using args [getTransient,value1,value2] for contract fabcar instantiated on channel gatewaychannel
Then The gateway named mycouchgateway has a submit type response matching "{\"key0\":\"value1\",\"key1\":\"value2\"}"
Then The gateway named mycouchgateway has a submit type response matching {"key0":"value1","key1":"value2"}
When I modify mycouchgateway to evaluate a transaction with transient data using args [getTransient,valueA,valueB] for contract fabcar instantiated on channel gatewaychannel
Then The gateway named mycouchgateway has a evaluate type response matching "{\"key0\":\"valueA\",\"key1\":\"valueB\"}"
Then The gateway named mycouchgateway has a evaluate type response matching {"key0":"valueA","key1":"valueB"}

Scenario: Using a Gateway to evaluate transactions I can use different query handler strategies
When I modify mycouchgateway to evaluate a transaction with args [queryCar,1001] for contract fabcar instantiated on channel gatewaychannel using handler option MSPID_SCOPE_SINGLE
Then The gateway named mycouchgateway has a evaluate type response matching {"color":"brown","docType":"car","make":"Trabant","model":"601 Estate","owner":"Simon"}
When I modify mycouchgateway to evaluate a transaction with args [queryCar,1001] for contract fabcar instantiated on channel gatewaychannel using handler option MSPID_SCOPE_ROUND_ROBIN
Then The gateway named mycouchgateway has a evaluate type response matching {"color":"brown","docType":"car","make":"Trabant","model":"601 Estate","owner":"Simon"}
When I modify mycouchgateway to evaluate a transaction with args [queryCar,1001] for contract fabcar instantiated on channel gatewaychannel using handler option custom
Then The gateway named mycouchgateway has a evaluate type response containing "{\"color\":\"brown\",\"docType\":\"car\",\"make\":\"Trabant\",\"model\":\"601 Estate\",\"owner\":\"Simon\"}"
Then The gateway named mycouchgateway has a evaluate type response containing {"color":"brown","docType":"car","make":"Trabant","model":"601 Estate","owner":"Simon"}
66 changes: 40 additions & 26 deletions test/ts-scenario/steps/lib/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,19 +225,27 @@ export async function performGatewayTransaction(gatewayName: string, contractNam
try {
if (submit) {
BaseUtils.logMsg('Submitting transaction [' + func + '] with arguments ' + args);
const result: Buffer = await contract.submitTransaction(func, ...funcArgs);
gatewayObj.result = {type: 'submit', response: result.toString()};
BaseUtils.logMsg('Successfully submitted transaction [' + func + ']');
const resultBuffer: Buffer = await contract.submitTransaction(func, ...funcArgs);
const result: string = resultBuffer.toString();
BaseUtils.logMsg(`Successfully submitted transaction [${func}] with result [${result}]`);
// some functions do not return anything
if (result.length > 0) {
gatewayObj.result = {type: 'submit', response: JSON.parse(result)};
} else {
gatewayObj.result = {type: 'submit', response: ''};
}

} else {
BaseUtils.logMsg('Evaluating transaction [' + func + '] with arguments ' + args);
const result: Buffer = await contract.evaluateTransaction(func, ...funcArgs);
BaseUtils.logMsg('Successfully evaluated transaction [' + func + '] with result [' + result.toString() + ']');
gatewayObj.result = {type: 'evaluate', response: JSON.parse(result.toString())};
const resultBuffer: Buffer = await contract.evaluateTransaction(func, ...funcArgs);
const result: string = resultBuffer.toString('utf8');
BaseUtils.logMsg(`Successfully evaluated transaction [${func}] with result [${result}]`);
gatewayObj.result = {type: 'evaluate', response: JSON.parse(result)};
}
} catch (err) {
gatewayObj.result = {type: 'error', response: err.toString()};
// Don't log the full error, since we might be forcing the error
BaseUtils.logError(err.toString());
BaseUtils.logError(' --- in gateway transaction:' + err.toString());
}
}

Expand Down Expand Up @@ -333,32 +341,33 @@ export async function performHandledGatewayTransaction(gatewayName: string, ccNa

try {
// -------- S E N D
await transaction.submit(...funcArgs);
BaseUtils.logMsg(`Successfully submitted transaction [${func}] using handler [${EventStrategies[handlerOption]}]`);
const resultBuffer: Buffer = await transaction.submit(...funcArgs);
const result: string = resultBuffer.toString('utf8');
BaseUtils.logMsg(`Successfully submitted transaction [${func}] using handler [${EventStrategies[handlerOption]}] with result [${result}]`);

await notificationPromise;
listener.unregister();
BaseUtils.logMsg(`Successfully got event status [${func}] using handler [${EventStrategies[handlerOption]}]`, undefined);
BaseUtils.logMsg(`Successfully got event status [${func}] using handler [${EventStrategies[handlerOption]}] after submitting and getting status [${JSON.stringify(eventResults)}]`);
gatewayObj.result = {type: 'event', response: JSON.stringify(eventResults), commitTransactionId: transaction.transactionId};
} catch (error) {
gatewayObj.result = {type: 'error', response: error.toString()};
BaseUtils.logError(error.toString());
BaseUtils.logError('--- in Submit: ' + error.toString());
}
} else {
// No event hubs, just query away
try {
// Split args, capture response
const result: Buffer = await transaction.evaluate(...funcArgs);
BaseUtils.logMsg(`Successfully evaluated transaction [${func}] using handler [${QueryStrategies[handlerOption]}] with result [${result}]`, undefined);
if (handlerOption.localeCompare('custom') === 0) {
gatewayObj.result = {type: 'evaluate', response: result.toString()};
} else {
gatewayObj.result = {type: 'evaluate', response: JSON.parse(result.toString())};

const resultBuffer: Buffer = await transaction.evaluate(...funcArgs);
const result: string = resultBuffer.toString('utf8');
let handlerPrint: string = 'custom';
if (handlerOption.localeCompare('custom') !== 0) {
handlerPrint = QueryStrategies[handlerOption].toString();
}
BaseUtils.logMsg(`Successfully evaluated transaction [${func}] using handler [${handlerPrint}] with result [${result}]`);
gatewayObj.result = {type: 'evaluate', response: JSON.parse(result)};
} catch (error) {
gatewayObj.result = {type: 'error', response: error.toString()};
BaseUtils.logError(error.toString());
BaseUtils.logError('--- in Evaluate: ' + error.toString());
}
}
}
Expand Down Expand Up @@ -401,20 +410,25 @@ export async function performTransientGatewayTransaction(gatewayName: string, cc
i++;
}

let printType: string = 'Evaluate';

try {
const submit: boolean = ( txnType.localeCompare('submit') === 0 );
if (submit) {
const result: Buffer = await transaction.setTransient(transientMap).submit();
BaseUtils.logMsg(`Successfully submitted transaction [${func}] with transient data`);
gatewayObj.result = {type: 'submit', response: result.toString()};
printType = 'Submit';
const resultBuffer: Buffer = await transaction.setTransient(transientMap).submit();
const result: string = resultBuffer.toString('utf8');
BaseUtils.logMsg(`Successfully submitted transaction [${func}] with transient data with result of [${result}]`);
gatewayObj.result = {type: 'submit', response: JSON.parse(result)};
} else {
const result: Buffer = await transaction.setTransient(transientMap).evaluate();
BaseUtils.logMsg(`Successfully evaluated transaction [${func}] with transient data`);
gatewayObj.result = {type: 'evaluate', response: result.toString()};
const resultBuffer: Buffer = await transaction.setTransient(transientMap).evaluate();
const result: string = resultBuffer.toString('utf8');
BaseUtils.logMsg(`Successfully evaluated transaction [${func}] with transient data with result of [${result}]`);
gatewayObj.result = {type: 'evaluate', response: JSON.parse(result)};
}
} catch (error) {
gatewayObj.result = {type: 'error', response: error.toString()};
BaseUtils.logError(error.toString());
BaseUtils.logError('--- in ' + printType + ' with transient: ' + error.toString());
}
}

Expand Down

0 comments on commit 94bcabc

Please sign in to comment.