From e0bc58dfaa211f8ac750302dfdc263fdc4b5825a Mon Sep 17 00:00:00 2001
From: Attila Klenik <a.klenik@gmail.com>
Date: Wed, 1 Apr 2020 13:48:08 +0000
Subject: [PATCH] Fix CI workloads and enhance error handling

Signed-off-by: Attila Klenik <a.klenik@gmail.com>
---
 .../lib/worker/client/message-handler.js      | 29 ++++---
 packages/caliper-ethereum/lib/ethereum.js     | 80 ++++++++++++-------
 packages/caliper-sawtooth/lib/sawtooth.js     |  2 +-
 .../besu_tests/open.js                        |  4 +-
 .../besu_tests/query.js                       |  2 +-
 .../besu_tests/transfer.js                    |  4 +-
 .../ethereum_tests/open.js                    |  4 +-
 .../ethereum_tests/query.js                   |  2 +-
 .../ethereum_tests/transfer.js                |  4 +-
 9 files changed, 80 insertions(+), 51 deletions(-)

diff --git a/packages/caliper-core/lib/worker/client/message-handler.js b/packages/caliper-core/lib/worker/client/message-handler.js
index 44af9d876a..1b1c940d76 100644
--- a/packages/caliper-core/lib/worker/client/message-handler.js
+++ b/packages/caliper-core/lib/worker/client/message-handler.js
@@ -88,7 +88,7 @@ class MessageHandler {
         if (error) {
             // send(to, type, data)
             context.messenger.send(['orchestrator'], type, {error: error.toString()});
-            logger.error(`Handled unsuccessful "init" message for worker ${context.workerId}, with error: ${error.toString()}`);
+            logger.error(`Handled unsuccessful "init" message for worker ${context.workerId}, with error: ${error.stack}`);
         } else {
             context.workerClient = new CaliperLocalClient(context.adapter, context.workerId, context.messenger);
             context.messenger.send(['orchestrator'], type, {});
@@ -117,7 +117,7 @@ class MessageHandler {
         if (error) {
             // send(to, type, data)
             context.messenger.send(['orchestrator'], type, {error: error.toString()});
-            logger.error(`Handled unsuccessful "prepare" message for worker ${context.workerId} and test round ${message.testRound} with error ${error.toString()}`);
+            logger.error(`Handled unsuccessful "prepare" message for worker ${context.workerId} and test round ${message.testRound} with error ${error.stack}`);
         } else {
             context.messenger.send(['orchestrator'], type, {});
             logger.info(`Handled successful "prepare" message for worker ${context.workerId} and test round ${message.testRound}`);
@@ -139,12 +139,19 @@ class MessageHandler {
      * Called after processing the "test" message.
      * @param {object} context The context/state of the message handler.
      * @param {object} message The message object.
+     * @param {object} error An error conditioning message
      */
-    static async afterTest(context, message) {
-        await CaliperUtils.sleep(200);
+    static async afterTest(context, message, error) {
         const type = 'testResult';
-        context.messenger.send(['orchestrator'], type, context.testResult);
-        logger.info(`Handled "test" message for worker ${context.workerId}`);
+
+        if (error) {
+            // send(to, type, data)
+            context.messenger.send(['orchestrator'], type, {error: error.toString()});
+            logger.error(`Handled unsuccessful "test" message for worker ${context.workerId} and test round ${message.testRound} with error ${error.stack}`);
+        } else {
+            context.messenger.send(['orchestrator'], type, context.testResult);
+            logger.info(`Handled successful "test" message for worker ${context.workerId} and test round ${message.testRound}`);
+        }
     }
 
     /**
@@ -216,9 +223,13 @@ class MessageHandler {
                 break;
             }
             case 'test': {
-                await context.beforeTestHandler(context, message);
-                context.testResult = await context.testHandler(context, message);
-                await context.afterTestHandler(context, message);
+                try {
+                    await context.beforeTestHandler(context, message);
+                    context.testResult = await context.testHandler(context, message);
+                    await context.afterTestHandler(context, message, undefined);
+                } catch (err) {
+                    await context.afterTestHandler(context, message, err);
+                }
 
                 break;
             }
diff --git a/packages/caliper-ethereum/lib/ethereum.js b/packages/caliper-ethereum/lib/ethereum.js
index 420b3715e7..b646a9aac0 100644
--- a/packages/caliper-ethereum/lib/ethereum.js
+++ b/packages/caliper-ethereum/lib/ethereum.js
@@ -201,42 +201,60 @@ class Ethereum extends BlockchainInterface {
         let status = new TxStatus();
         let params = {from: context.fromAddress};
         let contractInfo = context.contracts[contractID];
-        try {
-            context.engine.submitCallback(1);
-            let receipt = null;
-            let methodType = 'send';
-            if (methodCall.isView) {
-                methodType = 'call';
-            } else if (context.nonces && (typeof context.nonces[context.fromAddress] !== 'undefined')) {
-                let nonce = context.nonces[context.fromAddress];
-                context.nonces[context.fromAddress] = nonce + 1;
-                params.nonce = nonce;
+
+        context.engine.submitCallback(1);
+        let receipt = null;
+        let methodType = 'send';
+        if (methodCall.isView) {
+            methodType = 'call';
+        } else if (context.nonces && (typeof context.nonces[context.fromAddress] !== 'undefined')) {
+            let nonce = context.nonces[context.fromAddress];
+            context.nonces[context.fromAddress] = nonce + 1;
+            params.nonce = nonce;
+        }
+
+        const onFailure = (err) => {
+            status.SetStatusFail();
+            logger.error('Failed tx on ' + contractID + ' calling method ' + methodCall.verb + ' nonce ' + params.nonce);
+            logger.error(err);
+        };
+
+        const onSuccess = (rec) => {
+            status.SetID(rec.transactionHash);
+            status.SetResult(rec);
+            status.SetVerification(true);
+            status.SetStatusSuccess();
+        };
+
+        if (methodCall.args) {
+            if (contractInfo.gas && contractInfo.gas[methodCall.verb]) {
+                params.gas = contractInfo.gas[methodCall.verb];
+            } else if (contractInfo.estimateGas) {
+                params.gas = 1000 + await contractInfo.contract.methods[methodCall.verb](...methodCall.args).estimateGas();
             }
-            if (methodCall.args) {
-                if (contractInfo.gas && contractInfo.gas[methodCall.verb]) {
-                    params.gas = contractInfo.gas[methodCall.verb];
-                } else if (contractInfo.estimateGas) {
-                    params.gas = 1000 + await contractInfo.contract.methods[methodCall.verb](...methodCall.args).estimateGas();
-                }
+
+            try {
                 receipt = await contractInfo.contract.methods[methodCall.verb](...methodCall.args)[methodType](params);
-            } else {
-                if (contractInfo.gas && contractInfo.gas[methodCall.verb]) {
-                    params.gas = contractInfo.gas[methodCall.verb];
-                } else if (contractInfo.estimateGas) {
-                    params.gas = 1000 + await contractInfo.contract.methods[methodCall.verb].estimateGas(params);
-                }
+                onSuccess(receipt);
+            } catch (err) {
+                onFailure(err);
+            }
+        } else {
+            if (contractInfo.gas && contractInfo.gas[methodCall.verb]) {
+                params.gas = contractInfo.gas[methodCall.verb];
+            } else if (contractInfo.estimateGas) {
+                params.gas = 1000 + await contractInfo.contract.methods[methodCall.verb].estimateGas(params);
+            }
+
+            try {
                 receipt = await contractInfo.contract.methods[methodCall.verb]()[methodType](params);
+                onSuccess(receipt);
+            } catch (err) {
+                onFailure(err);
             }
-            status.SetID(receipt.transactionHash);
-            status.SetResult(receipt);
-            status.SetVerification(true);
-            status.SetStatusSuccess();
-        } catch (err) {
-            status.SetStatusFail();
-            logger.error('Failed tx on ' + contractID + ' calling method ' + methodCall.verb + ' nonce ' + params.nonce);
-            logger.error(err);
         }
-        return Promise.resolve(status);
+
+        return status;
     }
 
     /**
diff --git a/packages/caliper-sawtooth/lib/sawtooth.js b/packages/caliper-sawtooth/lib/sawtooth.js
index 3e2b164821..9c5a741591 100644
--- a/packages/caliper-sawtooth/lib/sawtooth.js
+++ b/packages/caliper-sawtooth/lib/sawtooth.js
@@ -365,7 +365,7 @@ class Sawtooth extends BlockchainInterface {
      * @return {Promise} The return promise.
      */
     getContext(name, args) {
-        let config  = require(this.configPath);
+        let config  = require(configPath);
         let context = config.sawtooth.context;
         if(typeof context === 'undefined') {
             let validatorUrl = config.sawtooth.network.validator.url;
diff --git a/packages/caliper-tests-integration/besu_tests/open.js b/packages/caliper-tests-integration/besu_tests/open.js
index 330ace593d..b769849da8 100644
--- a/packages/caliper-tests-integration/besu_tests/open.js
+++ b/packages/caliper-tests-integration/besu_tests/open.js
@@ -74,12 +74,12 @@ function generateWorkload() {
         let acc_id = generateAccount();
         account_array.push(acc_id);
 
-        if (bc.bcType === 'fabric') {
+        if (bc.getType() === 'fabric') {
             workload.push({
                 chaincodeFunction: 'open',
                 chaincodeArguments: [acc_id, initMoney.toString()],
             });
-        } else if (bc.bcType === 'ethereum') {
+        } else if (bc.getType() === 'ethereum') {
                 workload.push({
                     verb: 'open',
                     args: [acc_id, initMoney]
diff --git a/packages/caliper-tests-integration/besu_tests/query.js b/packages/caliper-tests-integration/besu_tests/query.js
index ec5df40122..3c131b7364 100644
--- a/packages/caliper-tests-integration/besu_tests/query.js
+++ b/packages/caliper-tests-integration/besu_tests/query.js
@@ -32,7 +32,7 @@ module.exports.init = function(blockchain, context, args) {
 module.exports.run = function() {
     const acc  = account_array[Math.floor(Math.random()*(account_array.length))];
 
-    if (bc.bcType === 'fabric') {
+    if (bc.getType() === 'fabric') {
         let args = {
             chaincodeFunction: 'query',
             chaincodeArguments: [acc],
diff --git a/packages/caliper-tests-integration/besu_tests/transfer.js b/packages/caliper-tests-integration/besu_tests/transfer.js
index 90f4919e73..aa317312d9 100644
--- a/packages/caliper-tests-integration/besu_tests/transfer.js
+++ b/packages/caliper-tests-integration/besu_tests/transfer.js
@@ -39,12 +39,12 @@ module.exports.run = function () {
     const account2 = account_array[Math.floor(Math.random() * (account_array.length))];
     let args;
 
-    if (bc.bcType === 'fabric') {
+    if (bc.getType() === 'fabric') {
         args = {
             chaincodeFunction: 'transfer',
             chaincodeArguments: [account1, account2, initmoney.toString()],
         };
-    } else if (bc.bcType === 'ethereum') {
+    } else if (bc.getType() === 'ethereum') {
         args = {
             verb: 'transfer',
             args: [account1, account2, initmoney]
diff --git a/packages/caliper-tests-integration/ethereum_tests/open.js b/packages/caliper-tests-integration/ethereum_tests/open.js
index 330ace593d..b769849da8 100644
--- a/packages/caliper-tests-integration/ethereum_tests/open.js
+++ b/packages/caliper-tests-integration/ethereum_tests/open.js
@@ -74,12 +74,12 @@ function generateWorkload() {
         let acc_id = generateAccount();
         account_array.push(acc_id);
 
-        if (bc.bcType === 'fabric') {
+        if (bc.getType() === 'fabric') {
             workload.push({
                 chaincodeFunction: 'open',
                 chaincodeArguments: [acc_id, initMoney.toString()],
             });
-        } else if (bc.bcType === 'ethereum') {
+        } else if (bc.getType() === 'ethereum') {
                 workload.push({
                     verb: 'open',
                     args: [acc_id, initMoney]
diff --git a/packages/caliper-tests-integration/ethereum_tests/query.js b/packages/caliper-tests-integration/ethereum_tests/query.js
index ec5df40122..3c131b7364 100644
--- a/packages/caliper-tests-integration/ethereum_tests/query.js
+++ b/packages/caliper-tests-integration/ethereum_tests/query.js
@@ -32,7 +32,7 @@ module.exports.init = function(blockchain, context, args) {
 module.exports.run = function() {
     const acc  = account_array[Math.floor(Math.random()*(account_array.length))];
 
-    if (bc.bcType === 'fabric') {
+    if (bc.getType() === 'fabric') {
         let args = {
             chaincodeFunction: 'query',
             chaincodeArguments: [acc],
diff --git a/packages/caliper-tests-integration/ethereum_tests/transfer.js b/packages/caliper-tests-integration/ethereum_tests/transfer.js
index 90f4919e73..aa317312d9 100644
--- a/packages/caliper-tests-integration/ethereum_tests/transfer.js
+++ b/packages/caliper-tests-integration/ethereum_tests/transfer.js
@@ -39,12 +39,12 @@ module.exports.run = function () {
     const account2 = account_array[Math.floor(Math.random() * (account_array.length))];
     let args;
 
-    if (bc.bcType === 'fabric') {
+    if (bc.getType() === 'fabric') {
         args = {
             chaincodeFunction: 'transfer',
             chaincodeArguments: [account1, account2, initmoney.toString()],
         };
-    } else if (bc.bcType === 'ethereum') {
+    } else if (bc.getType() === 'ethereum') {
         args = {
             verb: 'transfer',
             args: [account1, account2, initmoney]