From c7876bc7cdc6c83c586a05464fae60df3ddbd827 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 28 Jun 2018 14:01:44 -0400 Subject: [PATCH 1/7] add reporter with event to get receipt --- lib/contracts/contract_deployer.js | 1 + lib/tests/reporter.js | 72 ++++++++++++++++++++++++++++++ lib/tests/run_tests.js | 2 + 3 files changed, 75 insertions(+) create mode 100644 lib/tests/reporter.js diff --git a/lib/contracts/contract_deployer.js b/lib/contracts/contract_deployer.js index b97bb4750..50140085b 100644 --- a/lib/contracts/contract_deployer.js +++ b/lib/contracts/contract_deployer.js @@ -242,6 +242,7 @@ class ContractDeployer { self.logger.info(contract.className.bold.cyan + " " + __("deployed at").green + " " + receipt.contractAddress.bold.cyan); contract.deployedAddress = receipt.contractAddress; contract.transactionHash = receipt.transactionHash; + receipt.className = contract.className; self.events.emit("deploy:contract:receipt", receipt); self.events.emit("deploy:contract:deployed", contract); diff --git a/lib/tests/reporter.js b/lib/tests/reporter.js new file mode 100644 index 000000000..91cfbfcc9 --- /dev/null +++ b/lib/tests/reporter.js @@ -0,0 +1,72 @@ +const Base = require('mocha/lib/reporters/base'); +const color = Base.color; + +class EmbarkSpec extends Base { + constructor(runner, options) { + super(runner, options); + + const self = this; + self.embarkEvents = options.reporterOptions.events; + let indents = 0; + let n = 0; + + function onContractReceipt(receipt) { + console.log(receipt.className, receipt.gasUsed); + } + self.embarkEvents.on("deploy:contract:receipt", onContractReceipt); + + function indent() { + return Array(indents).join(' '); + } + + runner.on('start', function () { + console.log(); + }); + + runner.on('suite', function (suite) { + ++indents; + console.log(color('suite', '%s%s'), indent(), suite.title); + }); + + runner.on('suite end', function () { + --indents; + if (indents === 1) { + console.log(); + } + }); + + runner.on('pending', function (test) { + const fmt = indent() + color('pending', ' - %s'); + console.log(fmt, test.title); + }); + + runner.on('pass', function (test) { + let fmt; + if (test.speed === 'fast') { + fmt = + indent() + + color('checkmark', ' ' + Base.symbols.ok) + + color('pass', ' %s'); + console.log(fmt, test.title); + } else { + fmt = + indent() + + color('checkmark', ' ' + Base.symbols.ok) + + color('pass', ' %s') + + color(test.speed, ' (%dms)'); + console.log(fmt, test.title, test.duration); + } + }); + + runner.on('fail', function (test) { + console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); + }); + + runner.once('end', function() { + self.embarkEvents.removeListener("deploy:contract:receipt", onContractReceipt); + self.epilogue(); + }); + } +} + +module.exports = EmbarkSpec; diff --git a/lib/tests/run_tests.js b/lib/tests/run_tests.js index 80d238705..89fe40340 100644 --- a/lib/tests/run_tests.js +++ b/lib/tests/run_tests.js @@ -4,6 +4,7 @@ const Mocha = require('mocha'); const path = require('path'); const assert = require('assert'); const Test = require('./test'); +const EmbarkSpec = require('./reporter'); function getFilesFromDir(filePath, cb) { fs.readdir(filePath, (err, files) => { @@ -100,6 +101,7 @@ module.exports = { function executeForAllFiles(files, next) { async.eachLimit(files, 1, (file, eachCb) => { const mocha = new Mocha(); + mocha.reporter(EmbarkSpec, {events: global.embark.engine.events}); mocha.addFile(file); mocha.suite.timeout(0); From 18fa4307d75c4a5aa79a72d6897b800d9c29c351 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 28 Jun 2018 15:18:28 -0400 Subject: [PATCH 2/7] log gas cost at the end of each suite --- lib/tests/reporter.js | 43 ++++++++++++++++++++++++++++++++++++++++-- lib/tests/run_tests.js | 1 + 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/tests/reporter.js b/lib/tests/reporter.js index 91cfbfcc9..ef6c13334 100644 --- a/lib/tests/reporter.js +++ b/lib/tests/reporter.js @@ -9,10 +9,12 @@ class EmbarkSpec extends Base { self.embarkEvents = options.reporterOptions.events; let indents = 0; let n = 0; + self.stats.gasCost = 0; function onContractReceipt(receipt) { - console.log(receipt.className, receipt.gasUsed); + self.stats.gasCost += receipt.gasUsed; } + self.embarkEvents.on("deploy:contract:receipt", onContractReceipt); function indent() { @@ -62,11 +64,48 @@ class EmbarkSpec extends Base { console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); }); - runner.once('end', function() { + runner.once('end', function () { + runner.removeAllListeners(); self.embarkEvents.removeListener("deploy:contract:receipt", onContractReceipt); self.epilogue(); }); } + + epilogue() { + const stats = this.stats; + let fmt; + + console.log(); + + // passes + fmt = color('bright pass', ' ') + + color('green', ' %d passing') + + color('light', ' (%s gas)'); + + console.log(fmt, + stats.passes || 0, + stats.gasCost); + + // pending + if (stats.pending) { + fmt = color('pending', ' ') + + color('pending', ' %d pending'); + + console.log(fmt, stats.pending); + } + + // failures + if (stats.failures) { + fmt = color('fail', ' %d failing'); + + console.log(fmt, stats.failures); + + Base.list(this.failures); + console.log(); + } + + console.log(); + } } module.exports = EmbarkSpec; diff --git a/lib/tests/run_tests.js b/lib/tests/run_tests.js index 89fe40340..fd94307e9 100644 --- a/lib/tests/run_tests.js +++ b/lib/tests/run_tests.js @@ -114,6 +114,7 @@ module.exports = { mocha.run(function (fails) { failures += fails; + mocha.suite.removeAllListeners(); // Mocha prints the error already eachCb(); }); From 2648d0536e87bbf54a97df4fd506fb7313d92c0e Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 28 Jun 2018 15:48:57 -0400 Subject: [PATCH 3/7] add option to show details of gas cost for each contract --- lib/cmd.js | 3 ++- lib/tests/reporter.js | 13 +++++++++++++ lib/tests/run_tests.js | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/cmd.js b/lib/cmd.js index 419e194d5..7cccc16a2 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -188,12 +188,13 @@ class Cmd { test() { program .command('test [file]') + .option('-d , --gasDetails', __('When set, will print the gas cost for each contract')) .option('--locale [locale]', __('language to use (default: en)')) .option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'warn') .description(__('run tests')) .action(function (file, options) { i18n.setOrDetectLocale(options.locale); - embark.runTests({file, loglevel: options.loglevel}); + embark.runTests({file, loglevel: options.loglevel, gasDetails: options.gasDetails}); }); } diff --git a/lib/tests/reporter.js b/lib/tests/reporter.js index ef6c13334..cbd7a8cc4 100644 --- a/lib/tests/reporter.js +++ b/lib/tests/reporter.js @@ -7,12 +7,22 @@ class EmbarkSpec extends Base { const self = this; self.embarkEvents = options.reporterOptions.events; + self.gasDetails = options.reporterOptions.gasDetails; let indents = 0; let n = 0; self.stats.gasCost = 0; function onContractReceipt(receipt) { self.stats.gasCost += receipt.gasUsed; + if (self.gasDetails) { + const fmt = color('bright pass', ' ') + + color('green', ' %s') + + ' deployed for ' + + color('green', '%s') + + color('light', ' gas'); + + console.log(fmt, receipt.className, receipt.gasUsed); + } } self.embarkEvents.on("deploy:contract:receipt", onContractReceipt); @@ -27,6 +37,9 @@ class EmbarkSpec extends Base { runner.on('suite', function (suite) { ++indents; + if (self.gasDetails) { + console.log(); + } console.log(color('suite', '%s%s'), indent(), suite.title); }); diff --git a/lib/tests/run_tests.js b/lib/tests/run_tests.js index fd94307e9..ceaab2fae 100644 --- a/lib/tests/run_tests.js +++ b/lib/tests/run_tests.js @@ -101,7 +101,7 @@ module.exports = { function executeForAllFiles(files, next) { async.eachLimit(files, 1, (file, eachCb) => { const mocha = new Mocha(); - mocha.reporter(EmbarkSpec, {events: global.embark.engine.events}); + mocha.reporter(EmbarkSpec, {events: global.embark.engine.events, gasDetails: options.gasDetails}); mocha.addFile(file); mocha.suite.timeout(0); From 555e1f3c9e0c6ccff4216b0a195a4375efa36aab Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 28 Jun 2018 16:14:34 -0400 Subject: [PATCH 4/7] set color of gas cost --- lib/tests/reporter.js | 15 +++++++++++++-- lib/tests/run_tests.js | 6 +++++- lib/tests/test.js | 4 ++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/tests/reporter.js b/lib/tests/reporter.js index cbd7a8cc4..d67959f7e 100644 --- a/lib/tests/reporter.js +++ b/lib/tests/reporter.js @@ -8,6 +8,7 @@ class EmbarkSpec extends Base { const self = this; self.embarkEvents = options.reporterOptions.events; self.gasDetails = options.reporterOptions.gasDetails; + self.gasLimit = options.reporterOptions.gasLimit; let indents = 0; let n = 0; self.stats.gasCost = 0; @@ -18,7 +19,7 @@ class EmbarkSpec extends Base { const fmt = color('bright pass', ' ') + color('green', ' %s') + ' deployed for ' + - color('green', '%s') + + color(self.getGasColor(receipt.gasUsed), '%s') + color('light', ' gas'); console.log(fmt, receipt.className, receipt.gasUsed); @@ -84,6 +85,16 @@ class EmbarkSpec extends Base { }); } + getGasColor(gasCost) { + if (gasCost <= this.gasLimit/10) { + return 'fast'; + } + if (gasCost <= 3 * (this.gasLimit/4)) { + return 'medium'; + } + return 'slow'; + } + epilogue() { const stats = this.stats; let fmt; @@ -93,7 +104,7 @@ class EmbarkSpec extends Base { // passes fmt = color('bright pass', ' ') + color('green', ' %d passing') + - color('light', ' (%s gas)'); + color(this.getGasColor(stats.gasCost), ' (%s gas)'); console.log(fmt, stats.passes || 0, diff --git a/lib/tests/run_tests.js b/lib/tests/run_tests.js index ceaab2fae..d544e6ef0 100644 --- a/lib/tests/run_tests.js +++ b/lib/tests/run_tests.js @@ -101,7 +101,11 @@ module.exports = { function executeForAllFiles(files, next) { async.eachLimit(files, 1, (file, eachCb) => { const mocha = new Mocha(); - mocha.reporter(EmbarkSpec, {events: global.embark.engine.events, gasDetails: options.gasDetails}); + mocha.reporter(EmbarkSpec, { + events: global.embark.engine.events, + gasDetails: options.gasDetails, + gasLimit: global.embark.engine.deployManager.gasLimit + }); mocha.addFile(file); mocha.suite.timeout(0); diff --git a/lib/tests/test.js b/lib/tests/test.js index af7f81699..7c6c23588 100644 --- a/lib/tests/test.js +++ b/lib/tests/test.js @@ -98,6 +98,8 @@ class Test { trackContracts: false //ipcRole: 'client' // disabled for now due to issues with ipc file }); + this.engine.deployManager.gasLimit = 6000000; + this.engine.contractsManager.gasLimit = 6000000; } init(callback) { @@ -282,8 +284,6 @@ class Test { }); }, function deploy(accounts, next) { - self.engine.deployManager.gasLimit = 6000000; - self.engine.contractsManager.gasLimit = 6000000; self.engine.deployManager.fatalErrors = true; self.engine.deployManager.deployOnlyOnConfig = true; self.engine.events.request('deploy:contracts', () => { From 8ec5d53aa48dc1b365be850179c7a4dd87fc0a9b Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 29 Jun 2018 10:29:07 -0400 Subject: [PATCH 5/7] display gas cost of each test --- lib/core/events.js | 2 +- lib/tests/reporter.js | 50 ++++++++++++++++++++++++++----------------- lib/tests/test.js | 14 ++++++++++++ 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/lib/core/events.js b/lib/core/events.js index 42f6958a5..6bc9bcd1f 100644 --- a/lib/core/events.js +++ b/lib/core/events.js @@ -14,7 +14,7 @@ function log(eventType, eventName) { //console.log(eventType, eventName); } -EventEmitter.prototype._maxListeners = 300; +EventEmitter.prototype._maxListeners = 350; const _on = EventEmitter.prototype.on; const _setHandler = EventEmitter.prototype.setHandler; diff --git a/lib/tests/reporter.js b/lib/tests/reporter.js index d67959f7e..b1927b4dd 100644 --- a/lib/tests/reporter.js +++ b/lib/tests/reporter.js @@ -1,4 +1,5 @@ const Base = require('mocha/lib/reporters/base'); +const ms = require('mocha/lib/ms'); const color = Base.color; class EmbarkSpec extends Base { @@ -11,10 +12,12 @@ class EmbarkSpec extends Base { self.gasLimit = options.reporterOptions.gasLimit; let indents = 0; let n = 0; - self.stats.gasCost = 0; + self.stats.totalGasCost = 0; + self.stats.test = {}; + self.stats.test.gasUsed = 0; function onContractReceipt(receipt) { - self.stats.gasCost += receipt.gasUsed; + self.stats.totalGasCost += receipt.gasUsed; if (self.gasDetails) { const fmt = color('bright pass', ' ') + color('green', ' %s') + @@ -25,8 +28,13 @@ class EmbarkSpec extends Base { console.log(fmt, receipt.className, receipt.gasUsed); } } + function onBlockHeader(blockHeader) { + self.stats.totalGasCost += blockHeader.gasUsed; + self.stats.test.gasUsed += blockHeader.gasUsed; + } self.embarkEvents.on("deploy:contract:receipt", onContractReceipt); + self.embarkEvents.on("block:header", onBlockHeader); function indent() { return Array(indents).join(' '); @@ -56,31 +64,31 @@ class EmbarkSpec extends Base { console.log(fmt, test.title); }); + + runner.on('test', function () { + self.stats.test.gasUsed = 0; + }); + runner.on('pass', function (test) { - let fmt; - if (test.speed === 'fast') { - fmt = - indent() + - color('checkmark', ' ' + Base.symbols.ok) + - color('pass', ' %s'); - console.log(fmt, test.title); - } else { - fmt = - indent() + - color('checkmark', ' ' + Base.symbols.ok) + - color('pass', ' %s') + - color(test.speed, ' (%dms)'); - console.log(fmt, test.title, test.duration); - } + let fmt = + indent() + + color('checkmark', ' ' + Base.symbols.ok) + + color('pass', ' %s') + + color(test.speed, ' (%dms)') + + ' - ' + + color(self.getGasColor(self.stats.test.gasUsed), '[%d gas]'); + console.log(fmt, test.title, test.duration, self.stats.test.gasUsed); }); runner.on('fail', function (test) { - console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); + console.log(indent() + color('fail', ' %d) %s') + ' - ' + color(self.getGasColor(self.stats.test.gasUsed), '[%d gas]'), + ++n, test.title, self.stats.test.gasUsed); }); runner.once('end', function () { runner.removeAllListeners(); self.embarkEvents.removeListener("deploy:contract:receipt", onContractReceipt); + self.embarkEvents.removeListener("block:header", onBlockHeader); self.epilogue(); }); } @@ -104,11 +112,13 @@ class EmbarkSpec extends Base { // passes fmt = color('bright pass', ' ') + color('green', ' %d passing') + - color(this.getGasColor(stats.gasCost), ' (%s gas)'); + color('light', ' (%s)') + + color('light', ' - [Total: %s gas]'); console.log(fmt, stats.passes || 0, - stats.gasCost); + ms(stats.duration), + stats.totalGasCost); // pending if (stats.pending) { diff --git a/lib/tests/test.js b/lib/tests/test.js index 7c6c23588..1c6842138 100644 --- a/lib/tests/test.js +++ b/lib/tests/test.js @@ -39,6 +39,7 @@ class Test { this.error = false; this.builtContracts = {}; this.compiledContracts = {}; + this.logsSubscription = null; this.web3 = new Web3(); } @@ -87,9 +88,22 @@ class Test { this.sim = getSimulator(); } this.web3.setProvider(this.sim.provider(this.simOptions)); + this.subscribeToPendingTransactions(); callback(); } + subscribeToPendingTransactions() { + const self = this; + if (self.logsSubscription) { + self.logsSubscription.unsubscribe(); + } + self.logsSubscription = self.web3.eth + .subscribe('newBlockHeaders') + .on("data", function (blockHeader) { + self.engine.events.emit('block:header', blockHeader); + }); + } + initDeployServices() { this.engine.startService("web3", { web3: this.web3 From c832b24e2ac4706b887afef4dade70c24972e02e Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 6 Jul 2018 15:16:04 -0400 Subject: [PATCH 6/7] fix conflict in test and provider --- lib/cmd.js | 2 +- lib/tests/reporter.js | 24 ++++++++++++------------ lib/tests/test.js | 10 ++++++++-- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/lib/cmd.js b/lib/cmd.js index 7cccc16a2..eb0294132 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -188,7 +188,7 @@ class Cmd { test() { program .command('test [file]') - .option('-d , --gasDetails', __('When set, will print the gas cost for each contract')) + .option('-d , --gasDetails', __('When set, will print the gas cost for each contract deploy')) .option('--locale [locale]', __('language to use (default: en)')) .option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'warn') .description(__('run tests')) diff --git a/lib/tests/reporter.js b/lib/tests/reporter.js index b1927b4dd..75d8ff01c 100644 --- a/lib/tests/reporter.js +++ b/lib/tests/reporter.js @@ -17,23 +17,23 @@ class EmbarkSpec extends Base { self.stats.test.gasUsed = 0; function onContractReceipt(receipt) { - self.stats.totalGasCost += receipt.gasUsed; - if (self.gasDetails) { - const fmt = color('bright pass', ' ') + - color('green', ' %s') + - ' deployed for ' + - color(self.getGasColor(receipt.gasUsed), '%s') + - color('light', ' gas'); + const fmt = color('bright pass', ' ') + + color('suite', ' %s') + + color('light', ' deployed for ') + + color(self.getGasColor(receipt.gasUsed), '%s') + + color('light', ' gas'); - console.log(fmt, receipt.className, receipt.gasUsed); - } + console.log(fmt, receipt.className, receipt.gasUsed); } + function onBlockHeader(blockHeader) { self.stats.totalGasCost += blockHeader.gasUsed; self.stats.test.gasUsed += blockHeader.gasUsed; } - self.embarkEvents.on("deploy:contract:receipt", onContractReceipt); + if (self.gasDetails) { + self.embarkEvents.on("deploy:contract:receipt", onContractReceipt); + } self.embarkEvents.on("block:header", onBlockHeader); function indent() { @@ -94,10 +94,10 @@ class EmbarkSpec extends Base { } getGasColor(gasCost) { - if (gasCost <= this.gasLimit/10) { + if (gasCost <= this.gasLimit / 10) { return 'fast'; } - if (gasCost <= 3 * (this.gasLimit/4)) { + if (gasCost <= 3 * (this.gasLimit / 4)) { return 'medium'; } return 'slow'; diff --git a/lib/tests/test.js b/lib/tests/test.js index 1c6842138..5de48aaac 100644 --- a/lib/tests/test.js +++ b/lib/tests/test.js @@ -45,6 +45,7 @@ class Test { } initWeb3Provider(callback) { + const self = this; if (this.provider) { this.provider.stop(); } @@ -71,8 +72,13 @@ class Test { return callback(err); } - this.provider = new Provider(providerOptions); - this.provider.startWeb3Provider(callback); + return self.provider.startWeb3Provider((err) => { + if (err) { + return callback(err); + } + self.subscribeToPendingTransactions(); + callback(); + }); }); } From 2077f88312da8bbc2f7331cce915f536d25a6789 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 6 Jul 2018 15:30:16 -0400 Subject: [PATCH 7/7] fix provider --- lib/tests/test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tests/test.js b/lib/tests/test.js index 5de48aaac..f13f01135 100644 --- a/lib/tests/test.js +++ b/lib/tests/test.js @@ -72,6 +72,7 @@ class Test { return callback(err); } + self.provider = new Provider(providerOptions); return self.provider.startWeb3Provider((err) => { if (err) { return callback(err);