From 203a2f3799f3b756566cacf182ae2fd6abb8b7cf Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 24 Oct 2018 22:08:28 -0400 Subject: [PATCH 01/21] Work on #1013 --- remix-tests/src/index.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index 91aa7e3a01..d0e90f0d58 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -164,8 +164,26 @@ var runTestFiles = function (filepath, isDirectory, web3, opts) { } if (isDirectory) { - fs.readdirSync(filepath).forEach(filename => { - gatherContractsFrom(filename) + fs.walkSync = function (start, callback) { + fs.readdirSync(start).forEach(name => { + if (name === 'node_modules') { + return; // hack + } + var abspath = path.join(start, name); + if (fs.statSync(abspath).isDirectory()) { + fs.walkSync(abspath, callback); + } else { + callback(abspath); + } + }); + }; + fs.walkSync(filepath, foundpath => { + if (foundpath.indexOf('_test.sol') < 0) { + return + } + Object.keys(compilationResult[foundpath]).forEach(contractName => { + contractsToTest.push(contractName) + }) }) } else { gatherContractsFrom(filepath) From 580d85aa8044d019fedac972e981e73ed25882cd Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 24 Oct 2018 22:09:13 -0400 Subject: [PATCH 02/21] Work on multiple directories --- remix-tests/src/compiler.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 83d3506ac5..52d8250c04 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -37,16 +37,31 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { // should be replaced with remix's & browser solidity compiler code filepath = (isDirectory ? filename : path.dirname(filename)) - fs.readdirSync(filepath).forEach(file => { + // https://github.com/mikeal/node-utils/blob/master/file/lib/main.js + fs.walkSync = function (start, callback) { + fs.readdirSync(start).forEach(name => { + if (name === 'node_modules') { + return; // hack + } + var abspath = path.join(start, name); + if (fs.statSync(abspath).isDirectory()) { + fs.walkSync(abspath, callback); + } else { + callback(abspath); + } + }); + }; + + fs.walkSync(filepath, foundpath => { // only process .sol files - if (file.split('.').pop() === 'sol') { - let c = fs.readFileSync(path.join(filepath, file)).toString() + if (foundpath.split('.').pop() === 'sol') { + let c = fs.readFileSync(foundpath).toString() const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm let includeTestLibs = '\nimport \'remix_tests.sol\';\n' if (file.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { c = includeTestLibs.concat(c) } - sources[file] = { content: c } + sources[foundpath] = { content: c } } }) @@ -62,7 +77,7 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { compiler.event.register('compilationFinished', this, function (success, data, source) { next(null, data) }) - compiler.compile(sources, filepath) + compiler.compile(sources, false) } ], function (err, result) { let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') From c12b83a574326cf7b701f4224a21701fa676cafe Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 24 Oct 2018 22:30:36 -0400 Subject: [PATCH 03/21] less semicolons --- remix-tests/src/compiler.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 52d8250c04..2c9d55921d 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -41,16 +41,16 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { fs.walkSync = function (start, callback) { fs.readdirSync(start).forEach(name => { if (name === 'node_modules') { - return; // hack + return // hack } - var abspath = path.join(start, name); + var abspath = path.join(start, name) if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback); + fs.walkSync(abspath, callback) } else { - callback(abspath); + callback(abspath) } - }); - }; + }) + } fs.walkSync(filepath, foundpath => { // only process .sol files From ad1f68eddc93d50695fec4e9c8e93522c2d528dd Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 24 Oct 2018 22:31:36 -0400 Subject: [PATCH 04/21] Less semicolons --- remix-tests/src/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index d0e90f0d58..dfefef5329 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -167,16 +167,16 @@ var runTestFiles = function (filepath, isDirectory, web3, opts) { fs.walkSync = function (start, callback) { fs.readdirSync(start).forEach(name => { if (name === 'node_modules') { - return; // hack + return // hack } - var abspath = path.join(start, name); + var abspath = path.join(start, name) if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback); + fs.walkSync(abspath, callback) } else { - callback(abspath); + callback(abspath) } - }); - }; + }) + } fs.walkSync(filepath, foundpath => { if (foundpath.indexOf('_test.sol') < 0) { return From 6ec4f03f0368aea8ad3deb1217b68b984fcc6dc1 Mon Sep 17 00:00:00 2001 From: William Entriken Date: Tue, 6 Nov 2018 22:49:41 -0500 Subject: [PATCH 05/21] Expect full contract name in test run --- remix-tests/tests/testRunner.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/remix-tests/tests/testRunner.js b/remix-tests/tests/testRunner.js index 1871d19e13..b55292afcf 100644 --- a/remix-tests/tests/testRunner.js +++ b/remix-tests/tests/testRunner.js @@ -61,7 +61,7 @@ describe('testRunner', function () { it('should returns 5 messages', function () { assert.deepEqual(tests, [ - { type: 'contract', value: 'MyTest', filename: 'simple_storage_test.sol' }, + { type: 'contract', value: 'MyTest', filename: 'tests/examples_1/simple_storage_test.sol' }, { type: 'testFailure', value: 'Should trigger one fail', time: 1, context: 'MyTest', errMsg: 'the test 1 fails' }, { type: 'testPass', value: 'Should trigger one pass', time: 1, context: 'MyTest'}, { type: 'testPass', value: 'Initial value should be100', time: 1, context: 'MyTest' }, @@ -97,7 +97,7 @@ describe('testRunner', function () { it('should returns 3 messages', function () { assert.deepEqual(tests, [ - { type: 'contract', value: 'MyTest', filename: 'simple_storage_test.sol' }, + { type: 'contract', value: 'MyTest', filename: 'tests/examples_2/simple_storage_test.sol' }, { type: 'testPass', value: 'Initial value should be100', time: 1, context: 'MyTest' }, { type: 'testPass', value: 'Initial value should be200', time: 1, context: 'MyTest' } ]) @@ -133,8 +133,8 @@ describe('testRunner', function () { it('should returns 3 messages', function () { assert.deepEqual(tests, [ - { type: 'contract', value: 'StringTest', filename: 'simple_string_test.sol' }, - { type: 'testFailure', value: 'Value should be hello world', time: 1, context: 'StringTest', "errMsg": "initial value is not correct" }, + { type: 'contract', value: 'StringTest', filename: 'tests/examples_3/simple_string_test.sol' }, + { type: 'testFailure', value: 'Value should be hello world', time: 1, context: 'StringTest', "errMsg": "function returned false" }, { type: 'testPass', value: 'Value should not be hello world', time: 1, context: 'StringTest' }, { type: 'testPass', value: 'Initial value should be hello', time: 1, context: 'StringTest' }, ]) From b941bb42fd5b30da7749e6a58b302ce467ef330f Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Sat, 10 Nov 2018 10:16:30 +0530 Subject: [PATCH 06/21] unit testing fix for PR #1014 --- remix-tests/tests/testRunner.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/remix-tests/tests/testRunner.js b/remix-tests/tests/testRunner.js index b55292afcf..3b5dc673f6 100644 --- a/remix-tests/tests/testRunner.js +++ b/remix-tests/tests/testRunner.js @@ -29,8 +29,8 @@ function compileAndDeploy (filename, callback) { ], function (_err, contracts) { callback(null, compilationData, contracts, accounts) }) -} - +} + describe('testRunner', function () { describe('#runTest', function() { @@ -47,7 +47,7 @@ describe('testRunner', function () { results = _results done() } - TestRunner.runTest('MyTest', contracts.MyTest, compilationData['simple_storage_test.sol']['MyTest'], { accounts }, testCallback, resultsCallback) + TestRunner.runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], { accounts }, testCallback, resultsCallback) }) }) @@ -83,7 +83,7 @@ describe('testRunner', function () { results = _results done() } - TestRunner.runTest('MyTest', contracts.MyTest, compilationData['simple_storage_test.sol']['MyTest'], { accounts }, testCallback, resultsCallback) + TestRunner.runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], { accounts }, testCallback, resultsCallback) }) }) @@ -118,8 +118,8 @@ describe('testRunner', function () { results = _results done() } - TestRunner.runTest('StringTest', contracts.StringTest, compilationData['simple_string_test.sol']['StringTest'], { accounts }, testCallback, resultsCallback) - TestRunner.runTest('StringTest2', contracts.StringTest2, compilationData['simple_string_test.sol']['StringTest2'], { accounts }, testCallback, resultsCallback) + TestRunner.runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], { accounts }, testCallback, resultsCallback) + TestRunner.runTest('StringTest2', contracts.StringTest2, compilationData[filename]['StringTest2'], { accounts }, testCallback, resultsCallback) }) }) @@ -155,7 +155,7 @@ describe('testRunner', function () { results = _results done() } - TestRunner.runTest('IntegerTest', contracts.IntegerTest, compilationData['number_test.sol']['IntegerTest'], { accounts }, testCallback, resultsCallback) + TestRunner.runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], { accounts }, testCallback, resultsCallback) }) }) @@ -181,9 +181,9 @@ describe('testRunner', function () { results = _results done() } - - TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData['sender_test.sol']['SenderTest'], { accounts }, testCallback, resultsCallback) - + + TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData[filename]['SenderTest'], { accounts }, testCallback, resultsCallback) + }) }) From 84714c6899a733b8f4552bd9cb4ec02a4e69f54f Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Wed, 14 Nov 2018 19:06:25 +0530 Subject: [PATCH 07/21] Use gatherContractsFrom to collect contracts in fs.walkSync --- remix-tests/src/index.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index dfefef5329..7e430bcacf 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -153,7 +153,7 @@ var runTestFiles = function (filepath, isDirectory, web3, opts) { function determineTestContractsToRun (compilationResult, contracts, next) { let contractsToTest = [] let contractsToTestDetails = [] - var gatherContractsFrom = (filename) => { + const gatherContractsFrom = (filename) => { if (filename.indexOf('_test.sol') < 0) { return } @@ -178,12 +178,7 @@ var runTestFiles = function (filepath, isDirectory, web3, opts) { }) } fs.walkSync(filepath, foundpath => { - if (foundpath.indexOf('_test.sol') < 0) { - return - } - Object.keys(compilationResult[foundpath]).forEach(contractName => { - contractsToTest.push(contractName) - }) + gatherContractsFrom(foundpath) }) } else { gatherContractsFrom(filepath) From 730595472bc6686d706a536d9df62757e26b4156 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Fri, 16 Nov 2018 15:37:35 +0530 Subject: [PATCH 08/21] split index.js into multiple files, reuse functions --- remix-tests/src/compiler.js | 88 +++++------ remix-tests/src/fs.js | 20 +++ remix-tests/src/index.js | 247 +----------------------------- remix-tests/src/runTestFiles.js | 133 ++++++++++++++++ remix-tests/src/runTestSources.js | 107 +++++++++++++ 5 files changed, 303 insertions(+), 292 deletions(-) create mode 100644 remix-tests/src/fs.js create mode 100644 remix-tests/src/runTestFiles.js create mode 100644 remix-tests/src/runTestSources.js diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 2c9d55921d..ff00ed2cab 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -1,5 +1,5 @@ /* eslint no-extend-native: "warn" */ -let fs = require('fs') +let fs = require('./fs') var async = require('async') var path = require('path') let RemixCompiler = require('remix-solidity').Compiler @@ -35,58 +35,50 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { } // TODO: for now assumes filepath dir contains all tests, later all this // should be replaced with remix's & browser solidity compiler code - filepath = (isDirectory ? filename : path.dirname(filename)) - // https://github.com/mikeal/node-utils/blob/master/file/lib/main.js - fs.walkSync = function (start, callback) { - fs.readdirSync(start).forEach(name => { - if (name === 'node_modules') { - return // hack + // This logic is wrong + // We should only look into current file if a full file name with path is given + // We should only walk through directory if a directory name is passed + try { + filepath = (isDirectory ? filename : path.dirname(filename)) + // walkSync only if it is a directory + fs.walkSync(filepath, foundpath => { + // only process .sol files + if (foundpath.split('.').pop() === 'sol') { + let c = fs.readFileSync(foundpath).toString() + const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm + if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { + c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') + } + sources[foundpath] = { content: c } } - var abspath = path.join(start, name) - if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback) - } else { - callback(abspath) + }) + } catch (e) { + throw e + } finally { + async.waterfall([ + function loadCompiler (next) { + compiler = new RemixCompiler() + compiler.onInternalCompilerLoaded() + // compiler.event.register('compilerLoaded', this, function (version) { + next() + // }); + }, + function doCompilation (next) { + compiler.event.register('compilationFinished', this, function (success, data, source) { + next(null, data) + }) + compiler.compile(sources, false) + } + ], function (err, result) { + let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') + if (errors.length > 0) { + if (!isBrowser) require('signale').fatal(errors) + return cb(new Error('errors compiling')) } + cb(err, result.contracts) }) } - - fs.walkSync(filepath, foundpath => { - // only process .sol files - if (foundpath.split('.').pop() === 'sol') { - let c = fs.readFileSync(foundpath).toString() - const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm - let includeTestLibs = '\nimport \'remix_tests.sol\';\n' - if (file.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { - c = includeTestLibs.concat(c) - } - sources[foundpath] = { content: c } - } - }) - - async.waterfall([ - function loadCompiler (next) { - compiler = new RemixCompiler() - compiler.onInternalCompilerLoaded() - // compiler.event.register('compilerLoaded', this, function (version) { - next() - // }); - }, - function doCompilation (next) { - compiler.event.register('compilationFinished', this, function (success, data, source) { - next(null, data) - }) - compiler.compile(sources, false) - } - ], function (err, result) { - let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') - if (errors.length > 0) { - if (!isBrowser) require('signale').fatal(errors) - return cb(new Error('errors compiling')) - } - cb(err, result.contracts) - }) } function compileContractSources (sources, importFileCb, opts, cb) { diff --git a/remix-tests/src/fs.js b/remix-tests/src/fs.js new file mode 100644 index 0000000000..fa2dd4dfd7 --- /dev/null +++ b/remix-tests/src/fs.js @@ -0,0 +1,20 @@ +// Extend fs +var fs = require('fs') +const path = require('path') + +// https://github.com/mikeal/node-utils/blob/master/file/lib/main.js +fs.walkSync = function (start, callback) { + fs.readdirSync(start).forEach(name => { + if (name === 'node_modules') { + return // hack + } + var abspath = path.join(start, name) + if (fs.statSync(abspath).isDirectory()) { + fs.walkSync(abspath, callback) + } else { + callback(abspath) + } + }) +} + +module.exports = fs diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index 7e430bcacf..b2b64a0430 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -1,247 +1,6 @@ -const async = require('async') -const path = require('path') -const fs = require('fs') -require('colors') - -let Compiler = require('./compiler.js') -let Deployer = require('./deployer.js') -let TestRunner = require('./testRunner.js') - -const Web3 = require('web3') -const Provider = require('remix-simulator').Provider - -var createWeb3Provider = function () { - let web3 = new Web3() - web3.setProvider(new Provider()) - return web3 -} - -var runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb, opts) { - opts = opts || {} - let web3 = opts.web3 || createWeb3Provider() - let accounts = opts.accounts || null - async.waterfall([ - function getAccountList (next) { - if (accounts) return next() - web3.eth.getAccounts((_err, _accounts) => { - accounts = _accounts - next() - }) - }, - function compile (next) { - Compiler.compileContractSources(contractSources, importFileCb, { accounts }, next) - }, - function deployAllContracts (compilationResult, next) { - Deployer.deployAll(compilationResult, web3, function (err, contracts) { - if (err) { - next(err) - } - - next(null, compilationResult, contracts) - }) - }, - function determineTestContractsToRun (compilationResult, contracts, next) { - let contractsToTest = [] - let contractsToTestDetails = [] - - for (let filename in compilationResult) { - if (filename.indexOf('_test.sol') < 0) { - continue - } - Object.keys(compilationResult[filename]).forEach(contractName => { - contractsToTestDetails.push(compilationResult[filename][contractName]) - contractsToTest.push(contractName) - }) - } - - next(null, contractsToTest, contractsToTestDetails, contracts) - }, - function runTests (contractsToTest, contractsToTestDetails, contracts, next) { - let totalPassing = 0 - let totalFailing = 0 - let totalTime = 0 - let errors = [] - - var _testCallback = function (result) { - if (result.type === 'testFailure') { - errors.push(result) - } - testCallback(result) - } - - var _resultsCallback = function (_err, result, cb) { - resultCallback(_err, result, () => {}) - totalPassing += result.passingNum - totalFailing += result.failureNum - totalTime += result.timePassed - cb() - } - - async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { - TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, _testCallback, (err, result) => { - if (err) { - return cb(err) - } - _resultsCallback(null, result, cb) - }) - }, function (err, _results) { - if (err) { - return next(err) - } - - let finalResults = {} - - finalResults.totalPassing = totalPassing || 0 - finalResults.totalFailing = totalFailing || 0 - finalResults.totalTime = totalTime || 0 - finalResults.errors = [] - - errors.forEach((error, _index) => { - finalResults.errors.push({context: error.context, value: error.value, message: error.errMsg}) - }) - - next(null, finalResults) - }) - } - ], finalCallback) -} - -var runTestFiles = function (filepath, isDirectory, web3, opts) { - opts = opts || {} - const { Signale } = require('signale') - // signale configuration - const options = { - types: { - result: { - badge: '\t✓', - label: '', - color: 'greenBright' - }, - name: { - badge: '\n\t◼', - label: '', - color: 'white' - }, - error: { - badge: '\t✘', - label: '', - color: 'redBright' - } - } - } - const signale = new Signale(options) - let accounts = opts.accounts || null - async.waterfall([ - function getAccountList (next) { - if (accounts) return next(null) - web3.eth.getAccounts((_err, _accounts) => { - accounts = _accounts - next(null) - }) - }, - function compile (next) { - Compiler.compileFileOrFiles(filepath, isDirectory, { accounts }, next) - }, - function deployAllContracts (compilationResult, next) { - Deployer.deployAll(compilationResult, web3, function (err, contracts) { - if (err) { - next(err) - } - next(null, compilationResult, contracts) - }) - }, - function determineTestContractsToRun (compilationResult, contracts, next) { - let contractsToTest = [] - let contractsToTestDetails = [] - const gatherContractsFrom = (filename) => { - if (filename.indexOf('_test.sol') < 0) { - return - } - Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => { - contractsToTest.push(contractName) - contractsToTestDetails.push(compilationResult[path.basename(filename)][contractName]) - }) - } - - if (isDirectory) { - fs.walkSync = function (start, callback) { - fs.readdirSync(start).forEach(name => { - if (name === 'node_modules') { - return // hack - } - var abspath = path.join(start, name) - if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback) - } else { - callback(abspath) - } - }) - } - fs.walkSync(filepath, foundpath => { - gatherContractsFrom(foundpath) - }) - } else { - gatherContractsFrom(filepath) - } - next(null, contractsToTest, contractsToTestDetails, contracts) - }, - function runTests (contractsToTest, contractsToTestDetails, contracts, next) { - let totalPassing = 0 - let totalFailing = 0 - let totalTime = 0 - let errors = [] - - var testCallback = function (result) { - if (result.type === 'contract') { - signale.name(result.value.white) - } else if (result.type === 'testPass') { - signale.result(result.value) - } else if (result.type === 'testFailure') { - signale.result(result.value.red) - errors.push(result) - } - } - var resultsCallback = function (_err, result, cb) { - totalPassing += result.passingNum - totalFailing += result.failureNum - totalTime += result.timePassed - cb() - } - - async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { - TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, testCallback, (err, result) => { - if (err) { - return cb(err) - } - resultsCallback(null, result, cb) - }) - }, function (err, _results) { - if (err) { - return next(err) - } - - console.log('\n') - if (totalPassing > 0) { - console.log((' ' + totalPassing + ' passing ').green + ('(' + totalTime + 's)').grey) - } - if (totalFailing > 0) { - console.log((' ' + totalFailing + ' failing').red) - } - console.log('') - - errors.forEach((error, index) => { - console.log(' ' + (index + 1) + ') ' + error.context + ' ' + error.value) - console.log('') - console.log(('\t error: ' + error.errMsg).red) - }) - console.log('') - - next() - }) - } - ], function () { - }) -} +const runTestFiles = require('./runTestFiles.js') +const runTestSources = require('./runTestSources.js') +const TestRunner = require('./testRunner.js') module.exports = { runTestFiles: runTestFiles, diff --git a/remix-tests/src/runTestFiles.js b/remix-tests/src/runTestFiles.js new file mode 100644 index 0000000000..a733b76efd --- /dev/null +++ b/remix-tests/src/runTestFiles.js @@ -0,0 +1,133 @@ +const async = require('async') +const path = require('path') +const fs = require('./fs') +const TestRunner = require('./testRunner.js') +require('colors') + +let Compiler = require('./compiler.js') +let Deployer = require('./deployer.js') + +const runTestFiles = function (filepath, isDirectory, web3, opts) { + opts = opts || {} + const { Signale } = require('signale') + // signale configuration + const options = { + types: { + result: { + badge: '\t✓', + label: '', + color: 'greenBright' + }, + name: { + badge: '\n\t◼', + label: '', + color: 'white' + }, + error: { + badge: '\t✘', + label: '', + color: 'redBright' + } + } + } + const signale = new Signale(options) + let accounts = opts.accounts || null + async.waterfall([ + function getAccountList (next) { + if (accounts) return next(null) + web3.eth.getAccounts((_err, _accounts) => { + accounts = _accounts + next(null) + }) + }, + function compile (next) { + Compiler.compileFileOrFiles(filepath, isDirectory, { accounts }, next) + }, + function deployAllContracts (compilationResult, next) { + Deployer.deployAll(compilationResult, web3, function (err, contracts) { + if (err) { + next(err) + } + next(null, compilationResult, contracts) + }) + }, + function determineTestContractsToRun (compilationResult, contracts, next) { + let contractsToTest = [] + let contractsToTestDetails = [] + const gatherContractsFrom = (filename) => { + if (filename.indexOf('_test.sol') < 0) { + return + } + Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => { + contractsToTest.push(contractName) + contractsToTestDetails.push(compilationResult[path.basename(filename)][contractName]) + }) + } + if (isDirectory) { + fs.walkSync(filepath, foundpath => { + gatherContractsFrom(foundpath) + }) + } else { + gatherContractsFrom(filepath) + } + next(null, contractsToTest, contractsToTestDetails, contracts) + }, + function runTests (contractsToTest, contractsToTestDetails, contracts, next) { + let totalPassing = 0 + let totalFailing = 0 + let totalTime = 0 + let errors = [] + + var testCallback = function (result) { + if (result.type === 'contract') { + signale.name(result.value.white) + } else if (result.type === 'testPass') { + signale.result(result.value) + } else if (result.type === 'testFailure') { + signale.result(result.value.red) + errors.push(result) + } + } + var resultsCallback = function (_err, result, cb) { + totalPassing += result.passingNum + totalFailing += result.failureNum + totalTime += result.timePassed + cb() + } + + async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { + TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, testCallback, (err, result) => { + if (err) { + return cb(err) + } + resultsCallback(null, result, cb) + }) + }, function (err, _results) { + if (err) { + return next(err) + } + + console.log('\n') + if (totalPassing > 0) { + console.log((' ' + totalPassing + ' passing ').green + ('(' + totalTime + 's)').grey) + } + if (totalFailing > 0) { + console.log((' ' + totalFailing + ' failing').red) + } + console.log('') + + errors.forEach((error, index) => { + console.log(' ' + (index + 1) + ') ' + error.context + ' ' + error.value) + console.log('') + console.log(('\t error: ' + error.errMsg).red) + }) + console.log('') + + next() + }) + } + ], function () { + }) +} + +module.exports = runTestFiles diff --git a/remix-tests/src/runTestSources.js b/remix-tests/src/runTestSources.js new file mode 100644 index 0000000000..e91bd66a98 --- /dev/null +++ b/remix-tests/src/runTestSources.js @@ -0,0 +1,107 @@ +const async = require('async') +require('colors') + +let Compiler = require('./compiler.js') +let Deployer = require('./deployer.js') +let TestRunner = require('./testRunner.js') + +const Web3 = require('web3') +const Provider = require('remix-simulator').Provider + +var createWeb3Provider = function () { + let web3 = new Web3() + web3.setProvider(new Provider()) + return web3 +} + +const runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb, opts) { + opts = opts || {} + let web3 = opts.web3 || createWeb3Provider() + let accounts = opts.accounts || null + async.waterfall([ + function getAccountList (next) { + if (accounts) return next() + web3.eth.getAccounts((_err, _accounts) => { + accounts = _accounts + next() + }) + }, + function compile (next) { + Compiler.compileContractSources(contractSources, importFileCb, next) + }, + function deployAllContracts (compilationResult, next) { + Deployer.deployAll(compilationResult, web3, function (err, contracts) { + if (err) { + next(err) + } + + next(null, compilationResult, contracts) + }) + }, + function determineTestContractsToRun (compilationResult, contracts, next) { + let contractsToTest = [] + let contractsToTestDetails = [] + + for (let filename in compilationResult) { + if (filename.indexOf('_test.sol') < 0) { + continue + } + Object.keys(compilationResult[filename]).forEach(contractName => { + contractsToTestDetails.push(compilationResult[filename][contractName]) + contractsToTest.push(contractName) + }) + } + + next(null, contractsToTest, contractsToTestDetails, contracts) + }, + function runTests (contractsToTest, contractsToTestDetails, contracts, next) { + let totalPassing = 0 + let totalFailing = 0 + let totalTime = 0 + let errors = [] + + var _testCallback = function (result) { + if (result.type === 'testFailure') { + errors.push(result) + } + testCallback(result) + } + + var _resultsCallback = function (_err, result, cb) { + resultCallback(_err, result, () => {}) + totalPassing += result.passingNum + totalFailing += result.failureNum + totalTime += result.timePassed + cb() + } + + async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { + TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, _testCallback, (err, result) => { + if (err) { + return cb(err) + } + _resultsCallback(null, result, cb) + }) + }, function (err, _results) { + if (err) { + return next(err) + } + + let finalResults = {} + + finalResults.totalPassing = totalPassing || 0 + finalResults.totalFailing = totalFailing || 0 + finalResults.totalTime = totalTime || 0 + finalResults.errors = [] + + errors.forEach((error, _index) => { + finalResults.errors.push({context: error.context, value: error.value, message: error.errMsg}) + }) + + next(null, finalResults) + }) + } + ], finalCallback) +} + +module.exports = runTestSources From 0efc902da50737a59457e83bcc228cc49f9c28af Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Mon, 19 Nov 2018 09:45:42 +0530 Subject: [PATCH 09/21] use filepath again --- remix-tests/src/compiler.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index ff00ed2cab..932e3911da 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -26,13 +26,14 @@ var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electro // TODO: replace this with remix's own compiler code function compileFileOrFiles (filename, isDirectory, opts, cb) { - let compiler, filepath + let compiler let accounts = opts.accounts || [] const sources = { 'tests.sol': { content: require('../sol/tests.sol.js') }, 'remix_tests.sol': { content: require('../sol/tests.sol.js') }, 'remix_accounts.sol': { content: writeTestAccountsContract(accounts) } } + const filepath = (isDirectory ? filename : path.dirname(filename)) // TODO: for now assumes filepath dir contains all tests, later all this // should be replaced with remix's & browser solidity compiler code @@ -40,7 +41,6 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { // We should only look into current file if a full file name with path is given // We should only walk through directory if a directory name is passed try { - filepath = (isDirectory ? filename : path.dirname(filename)) // walkSync only if it is a directory fs.walkSync(filepath, foundpath => { // only process .sol files @@ -68,7 +68,7 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { compiler.event.register('compilationFinished', this, function (success, data, source) { next(null, data) }) - compiler.compile(sources, false) + compiler.compile(sources, filepath) } ], function (err, result) { let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') From ff03ade1d0d08b8ed994f2a61ce9902e1bf7beff Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 20 Nov 2018 14:57:26 +0530 Subject: [PATCH 10/21] fix conflicts --- remix-tests/src/index.js | 252 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 249 insertions(+), 3 deletions(-) diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index b2b64a0430..d0e90f0d58 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -1,6 +1,252 @@ -const runTestFiles = require('./runTestFiles.js') -const runTestSources = require('./runTestSources.js') -const TestRunner = require('./testRunner.js') +const async = require('async') +const path = require('path') +const fs = require('fs') +require('colors') + +let Compiler = require('./compiler.js') +let Deployer = require('./deployer.js') +let TestRunner = require('./testRunner.js') + +const Web3 = require('web3') +const Provider = require('remix-simulator').Provider + +var createWeb3Provider = function () { + let web3 = new Web3() + web3.setProvider(new Provider()) + return web3 +} + +var runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb, opts) { + opts = opts || {} + let web3 = opts.web3 || createWeb3Provider() + let accounts = opts.accounts || null + async.waterfall([ + function getAccountList (next) { + if (accounts) return next() + web3.eth.getAccounts((_err, _accounts) => { + accounts = _accounts + next() + }) + }, + function compile (next) { + Compiler.compileContractSources(contractSources, importFileCb, { accounts }, next) + }, + function deployAllContracts (compilationResult, next) { + Deployer.deployAll(compilationResult, web3, function (err, contracts) { + if (err) { + next(err) + } + + next(null, compilationResult, contracts) + }) + }, + function determineTestContractsToRun (compilationResult, contracts, next) { + let contractsToTest = [] + let contractsToTestDetails = [] + + for (let filename in compilationResult) { + if (filename.indexOf('_test.sol') < 0) { + continue + } + Object.keys(compilationResult[filename]).forEach(contractName => { + contractsToTestDetails.push(compilationResult[filename][contractName]) + contractsToTest.push(contractName) + }) + } + + next(null, contractsToTest, contractsToTestDetails, contracts) + }, + function runTests (contractsToTest, contractsToTestDetails, contracts, next) { + let totalPassing = 0 + let totalFailing = 0 + let totalTime = 0 + let errors = [] + + var _testCallback = function (result) { + if (result.type === 'testFailure') { + errors.push(result) + } + testCallback(result) + } + + var _resultsCallback = function (_err, result, cb) { + resultCallback(_err, result, () => {}) + totalPassing += result.passingNum + totalFailing += result.failureNum + totalTime += result.timePassed + cb() + } + + async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { + TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, _testCallback, (err, result) => { + if (err) { + return cb(err) + } + _resultsCallback(null, result, cb) + }) + }, function (err, _results) { + if (err) { + return next(err) + } + + let finalResults = {} + + finalResults.totalPassing = totalPassing || 0 + finalResults.totalFailing = totalFailing || 0 + finalResults.totalTime = totalTime || 0 + finalResults.errors = [] + + errors.forEach((error, _index) => { + finalResults.errors.push({context: error.context, value: error.value, message: error.errMsg}) + }) + + next(null, finalResults) + }) + } + ], finalCallback) +} + +var runTestFiles = function (filepath, isDirectory, web3, opts) { + opts = opts || {} + const { Signale } = require('signale') + // signale configuration + const options = { + types: { + result: { + badge: '\t✓', + label: '', + color: 'greenBright' + }, + name: { + badge: '\n\t◼', + label: '', + color: 'white' + }, + error: { + badge: '\t✘', + label: '', + color: 'redBright' + } + } + } + const signale = new Signale(options) + let accounts = opts.accounts || null + async.waterfall([ + function getAccountList (next) { + if (accounts) return next(null) + web3.eth.getAccounts((_err, _accounts) => { + accounts = _accounts + next(null) + }) + }, + function compile (next) { + Compiler.compileFileOrFiles(filepath, isDirectory, { accounts }, next) + }, + function deployAllContracts (compilationResult, next) { + Deployer.deployAll(compilationResult, web3, function (err, contracts) { + if (err) { + next(err) + } + next(null, compilationResult, contracts) + }) + }, + function determineTestContractsToRun (compilationResult, contracts, next) { + let contractsToTest = [] + let contractsToTestDetails = [] + var gatherContractsFrom = (filename) => { + if (filename.indexOf('_test.sol') < 0) { + return + } + Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => { + contractsToTest.push(contractName) + contractsToTestDetails.push(compilationResult[path.basename(filename)][contractName]) + }) + } + + if (isDirectory) { + fs.walkSync = function (start, callback) { + fs.readdirSync(start).forEach(name => { + if (name === 'node_modules') { + return; // hack + } + var abspath = path.join(start, name); + if (fs.statSync(abspath).isDirectory()) { + fs.walkSync(abspath, callback); + } else { + callback(abspath); + } + }); + }; + fs.walkSync(filepath, foundpath => { + if (foundpath.indexOf('_test.sol') < 0) { + return + } + Object.keys(compilationResult[foundpath]).forEach(contractName => { + contractsToTest.push(contractName) + }) + }) + } else { + gatherContractsFrom(filepath) + } + next(null, contractsToTest, contractsToTestDetails, contracts) + }, + function runTests (contractsToTest, contractsToTestDetails, contracts, next) { + let totalPassing = 0 + let totalFailing = 0 + let totalTime = 0 + let errors = [] + + var testCallback = function (result) { + if (result.type === 'contract') { + signale.name(result.value.white) + } else if (result.type === 'testPass') { + signale.result(result.value) + } else if (result.type === 'testFailure') { + signale.result(result.value.red) + errors.push(result) + } + } + var resultsCallback = function (_err, result, cb) { + totalPassing += result.passingNum + totalFailing += result.failureNum + totalTime += result.timePassed + cb() + } + + async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { + TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, testCallback, (err, result) => { + if (err) { + return cb(err) + } + resultsCallback(null, result, cb) + }) + }, function (err, _results) { + if (err) { + return next(err) + } + + console.log('\n') + if (totalPassing > 0) { + console.log((' ' + totalPassing + ' passing ').green + ('(' + totalTime + 's)').grey) + } + if (totalFailing > 0) { + console.log((' ' + totalFailing + ' failing').red) + } + console.log('') + + errors.forEach((error, index) => { + console.log(' ' + (index + 1) + ') ' + error.context + ' ' + error.value) + console.log('') + console.log(('\t error: ' + error.errMsg).red) + }) + console.log('') + + next() + }) + } + ], function () { + }) +} module.exports = { runTestFiles: runTestFiles, From 4ee3a6f496bf299cd6201e2a5a661554ea15817b Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 20 Nov 2018 14:58:46 +0530 Subject: [PATCH 11/21] fix conflicts --- remix-tests/src/compiler.js | 85 ++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 932e3911da..9a42bd2397 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -37,48 +37,55 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { // TODO: for now assumes filepath dir contains all tests, later all this // should be replaced with remix's & browser solidity compiler code - // This logic is wrong - // We should only look into current file if a full file name with path is given - // We should only walk through directory if a directory name is passed - try { - // walkSync only if it is a directory - fs.walkSync(filepath, foundpath => { - // only process .sol files - if (foundpath.split('.').pop() === 'sol') { - let c = fs.readFileSync(foundpath).toString() - const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm - if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { - c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') - } - sources[foundpath] = { content: c } + // https://github.com/mikeal/node-utils/blob/master/file/lib/main.js + fs.walkSync = function (start, callback) { + fs.readdirSync(start).forEach(name => { + if (name === 'node_modules') { + return; // hack } - }) - } catch (e) { - throw e - } finally { - async.waterfall([ - function loadCompiler (next) { - compiler = new RemixCompiler() - compiler.onInternalCompilerLoaded() - // compiler.event.register('compilerLoaded', this, function (version) { - next() - // }); - }, - function doCompilation (next) { - compiler.event.register('compilationFinished', this, function (success, data, source) { - next(null, data) - }) - compiler.compile(sources, filepath) + var abspath = path.join(start, name); + if (fs.statSync(abspath).isDirectory()) { + fs.walkSync(abspath, callback); + } else { + callback(abspath); } - ], function (err, result) { - let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') - if (errors.length > 0) { - if (!isBrowser) require('signale').fatal(errors) - return cb(new Error('errors compiling')) + }); + }; + + fs.walkSync(filepath, foundpath => { + // only process .sol files + if (foundpath.split('.').pop() === 'sol') { + let c = fs.readFileSync(foundpath).toString() + const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm + if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { + c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') } - cb(err, result.contracts) - }) - } + sources[foundpath] = { content: c } + } + }) + + async.waterfall([ + function loadCompiler (next) { + compiler = new RemixCompiler() + compiler.onInternalCompilerLoaded() + // compiler.event.register('compilerLoaded', this, function (version) { + next() + // }); + }, + function doCompilation (next) { + compiler.event.register('compilationFinished', this, function (success, data, source) { + next(null, data) + }) + compiler.compile(sources, false) + } + ], function (err, result) { + let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') + if (errors.length > 0) { + if (!isBrowser) require('signale').fatal(errors) + return cb(new Error('errors compiling')) + } + cb(err, result.contracts) + }) } function compileContractSources (sources, importFileCb, opts, cb) { From aa9c054a1f1435f725c16d649782f63d2eb786b1 Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 24 Oct 2018 22:30:36 -0400 Subject: [PATCH 12/21] less semicolons --- remix-tests/src/compiler.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 9a42bd2397..45a6004924 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -41,16 +41,16 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { fs.walkSync = function (start, callback) { fs.readdirSync(start).forEach(name => { if (name === 'node_modules') { - return; // hack + return // hack } - var abspath = path.join(start, name); + var abspath = path.join(start, name) if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback); + fs.walkSync(abspath, callback) } else { - callback(abspath); + callback(abspath) } - }); - }; + }) + } fs.walkSync(filepath, foundpath => { // only process .sol files From 585a5703d1616f5f9cf043649316c6fa3c0a5b4b Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 24 Oct 2018 22:31:13 -0400 Subject: [PATCH 13/21] Better indentation --- remix-tests/src/compiler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 45a6004924..392dcc81a7 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -57,7 +57,7 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { if (foundpath.split('.').pop() === 'sol') { let c = fs.readFileSync(foundpath).toString() const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm - if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { + if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') } sources[foundpath] = { content: c } From df8b2a1a96e067f679c3834ae12d5e999b35e82c Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 24 Oct 2018 22:31:36 -0400 Subject: [PATCH 14/21] Less semicolons --- remix-tests/src/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index d0e90f0d58..dfefef5329 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -167,16 +167,16 @@ var runTestFiles = function (filepath, isDirectory, web3, opts) { fs.walkSync = function (start, callback) { fs.readdirSync(start).forEach(name => { if (name === 'node_modules') { - return; // hack + return // hack } - var abspath = path.join(start, name); + var abspath = path.join(start, name) if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback); + fs.walkSync(abspath, callback) } else { - callback(abspath); + callback(abspath) } - }); - }; + }) + } fs.walkSync(filepath, foundpath => { if (foundpath.indexOf('_test.sol') < 0) { return From fc01e7b576b8c6a46d5cc61fe5a0b7bde08b6ffa Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 20 Nov 2018 14:59:57 +0530 Subject: [PATCH 15/21] fix conflicts --- remix-tests/tests/testRunner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remix-tests/tests/testRunner.js b/remix-tests/tests/testRunner.js index 3b5dc673f6..3a38c9d973 100644 --- a/remix-tests/tests/testRunner.js +++ b/remix-tests/tests/testRunner.js @@ -182,7 +182,7 @@ describe('testRunner', function () { done() } - TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData[filename]['SenderTest'], { accounts }, testCallback, resultsCallback) + TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData['sender_test.sol']['SenderTest'], { accounts }, testCallback, resultsCallback) }) }) From 0e6fe2a495103e1afd1c40ff478f4853bced1d51 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 20 Nov 2018 15:00:39 +0530 Subject: [PATCH 16/21] fix conflicts --- remix-tests/tests/testRunner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remix-tests/tests/testRunner.js b/remix-tests/tests/testRunner.js index 3a38c9d973..3b5dc673f6 100644 --- a/remix-tests/tests/testRunner.js +++ b/remix-tests/tests/testRunner.js @@ -182,7 +182,7 @@ describe('testRunner', function () { done() } - TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData['sender_test.sol']['SenderTest'], { accounts }, testCallback, resultsCallback) + TestRunner.runTest('SenderTest', contracts.SenderTest, compilationData[filename]['SenderTest'], { accounts }, testCallback, resultsCallback) }) }) From 5793f1c9e2bcf618f08687a40db12b018e6c367d Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Wed, 14 Nov 2018 19:06:25 +0530 Subject: [PATCH 17/21] Use gatherContractsFrom to collect contracts in fs.walkSync --- remix-tests/src/index.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index dfefef5329..7e430bcacf 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -153,7 +153,7 @@ var runTestFiles = function (filepath, isDirectory, web3, opts) { function determineTestContractsToRun (compilationResult, contracts, next) { let contractsToTest = [] let contractsToTestDetails = [] - var gatherContractsFrom = (filename) => { + const gatherContractsFrom = (filename) => { if (filename.indexOf('_test.sol') < 0) { return } @@ -178,12 +178,7 @@ var runTestFiles = function (filepath, isDirectory, web3, opts) { }) } fs.walkSync(filepath, foundpath => { - if (foundpath.indexOf('_test.sol') < 0) { - return - } - Object.keys(compilationResult[foundpath]).forEach(contractName => { - contractsToTest.push(contractName) - }) + gatherContractsFrom(foundpath) }) } else { gatherContractsFrom(filepath) From 90dce69ef5e10af02440d24e00c08e756f6ba24f Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 20 Nov 2018 15:01:42 +0530 Subject: [PATCH 18/21] fix conflicts --- remix-tests/src/compiler.js | 84 ++++++------ remix-tests/src/index.js | 247 +----------------------------------- 2 files changed, 42 insertions(+), 289 deletions(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 392dcc81a7..b45aef5184 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -37,55 +37,49 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { // TODO: for now assumes filepath dir contains all tests, later all this // should be replaced with remix's & browser solidity compiler code - // https://github.com/mikeal/node-utils/blob/master/file/lib/main.js - fs.walkSync = function (start, callback) { - fs.readdirSync(start).forEach(name => { - if (name === 'node_modules') { - return // hack + // This logic is wrong + // We should only look into current file if a full file name with path is given + // We should only walk through directory if a directory name is passed + try { + filepath = (isDirectory ? filename : path.dirname(filename)) + // walkSync only if it is a directory + fs.walkSync(filepath, foundpath => { + // only process .sol files + if (foundpath.split('.').pop() === 'sol') { + let c = fs.readFileSync(foundpath).toString() + const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm + if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { + c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') + } + sources[foundpath] = { content: c } } - var abspath = path.join(start, name) - if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback) - } else { - callback(abspath) + }) + } catch (e) { + throw e + } finally { + async.waterfall([ + function loadCompiler (next) { + compiler = new RemixCompiler() + compiler.onInternalCompilerLoaded() + // compiler.event.register('compilerLoaded', this, function (version) { + next() + // }); + }, + function doCompilation (next) { + compiler.event.register('compilationFinished', this, function (success, data, source) { + next(null, data) + }) + compiler.compile(sources, false) + } + ], function (err, result) { + let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') + if (errors.length > 0) { + if (!isBrowser) require('signale').fatal(errors) + return cb(new Error('errors compiling')) } + cb(err, result.contracts) }) } - - fs.walkSync(filepath, foundpath => { - // only process .sol files - if (foundpath.split('.').pop() === 'sol') { - let c = fs.readFileSync(foundpath).toString() - const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm - if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { - c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') - } - sources[foundpath] = { content: c } - } - }) - - async.waterfall([ - function loadCompiler (next) { - compiler = new RemixCompiler() - compiler.onInternalCompilerLoaded() - // compiler.event.register('compilerLoaded', this, function (version) { - next() - // }); - }, - function doCompilation (next) { - compiler.event.register('compilationFinished', this, function (success, data, source) { - next(null, data) - }) - compiler.compile(sources, false) - } - ], function (err, result) { - let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') - if (errors.length > 0) { - if (!isBrowser) require('signale').fatal(errors) - return cb(new Error('errors compiling')) - } - cb(err, result.contracts) - }) } function compileContractSources (sources, importFileCb, opts, cb) { diff --git a/remix-tests/src/index.js b/remix-tests/src/index.js index 7e430bcacf..b2b64a0430 100644 --- a/remix-tests/src/index.js +++ b/remix-tests/src/index.js @@ -1,247 +1,6 @@ -const async = require('async') -const path = require('path') -const fs = require('fs') -require('colors') - -let Compiler = require('./compiler.js') -let Deployer = require('./deployer.js') -let TestRunner = require('./testRunner.js') - -const Web3 = require('web3') -const Provider = require('remix-simulator').Provider - -var createWeb3Provider = function () { - let web3 = new Web3() - web3.setProvider(new Provider()) - return web3 -} - -var runTestSources = function (contractSources, testCallback, resultCallback, finalCallback, importFileCb, opts) { - opts = opts || {} - let web3 = opts.web3 || createWeb3Provider() - let accounts = opts.accounts || null - async.waterfall([ - function getAccountList (next) { - if (accounts) return next() - web3.eth.getAccounts((_err, _accounts) => { - accounts = _accounts - next() - }) - }, - function compile (next) { - Compiler.compileContractSources(contractSources, importFileCb, { accounts }, next) - }, - function deployAllContracts (compilationResult, next) { - Deployer.deployAll(compilationResult, web3, function (err, contracts) { - if (err) { - next(err) - } - - next(null, compilationResult, contracts) - }) - }, - function determineTestContractsToRun (compilationResult, contracts, next) { - let contractsToTest = [] - let contractsToTestDetails = [] - - for (let filename in compilationResult) { - if (filename.indexOf('_test.sol') < 0) { - continue - } - Object.keys(compilationResult[filename]).forEach(contractName => { - contractsToTestDetails.push(compilationResult[filename][contractName]) - contractsToTest.push(contractName) - }) - } - - next(null, contractsToTest, contractsToTestDetails, contracts) - }, - function runTests (contractsToTest, contractsToTestDetails, contracts, next) { - let totalPassing = 0 - let totalFailing = 0 - let totalTime = 0 - let errors = [] - - var _testCallback = function (result) { - if (result.type === 'testFailure') { - errors.push(result) - } - testCallback(result) - } - - var _resultsCallback = function (_err, result, cb) { - resultCallback(_err, result, () => {}) - totalPassing += result.passingNum - totalFailing += result.failureNum - totalTime += result.timePassed - cb() - } - - async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { - TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, _testCallback, (err, result) => { - if (err) { - return cb(err) - } - _resultsCallback(null, result, cb) - }) - }, function (err, _results) { - if (err) { - return next(err) - } - - let finalResults = {} - - finalResults.totalPassing = totalPassing || 0 - finalResults.totalFailing = totalFailing || 0 - finalResults.totalTime = totalTime || 0 - finalResults.errors = [] - - errors.forEach((error, _index) => { - finalResults.errors.push({context: error.context, value: error.value, message: error.errMsg}) - }) - - next(null, finalResults) - }) - } - ], finalCallback) -} - -var runTestFiles = function (filepath, isDirectory, web3, opts) { - opts = opts || {} - const { Signale } = require('signale') - // signale configuration - const options = { - types: { - result: { - badge: '\t✓', - label: '', - color: 'greenBright' - }, - name: { - badge: '\n\t◼', - label: '', - color: 'white' - }, - error: { - badge: '\t✘', - label: '', - color: 'redBright' - } - } - } - const signale = new Signale(options) - let accounts = opts.accounts || null - async.waterfall([ - function getAccountList (next) { - if (accounts) return next(null) - web3.eth.getAccounts((_err, _accounts) => { - accounts = _accounts - next(null) - }) - }, - function compile (next) { - Compiler.compileFileOrFiles(filepath, isDirectory, { accounts }, next) - }, - function deployAllContracts (compilationResult, next) { - Deployer.deployAll(compilationResult, web3, function (err, contracts) { - if (err) { - next(err) - } - next(null, compilationResult, contracts) - }) - }, - function determineTestContractsToRun (compilationResult, contracts, next) { - let contractsToTest = [] - let contractsToTestDetails = [] - const gatherContractsFrom = (filename) => { - if (filename.indexOf('_test.sol') < 0) { - return - } - Object.keys(compilationResult[path.basename(filename)]).forEach(contractName => { - contractsToTest.push(contractName) - contractsToTestDetails.push(compilationResult[path.basename(filename)][contractName]) - }) - } - - if (isDirectory) { - fs.walkSync = function (start, callback) { - fs.readdirSync(start).forEach(name => { - if (name === 'node_modules') { - return // hack - } - var abspath = path.join(start, name) - if (fs.statSync(abspath).isDirectory()) { - fs.walkSync(abspath, callback) - } else { - callback(abspath) - } - }) - } - fs.walkSync(filepath, foundpath => { - gatherContractsFrom(foundpath) - }) - } else { - gatherContractsFrom(filepath) - } - next(null, contractsToTest, contractsToTestDetails, contracts) - }, - function runTests (contractsToTest, contractsToTestDetails, contracts, next) { - let totalPassing = 0 - let totalFailing = 0 - let totalTime = 0 - let errors = [] - - var testCallback = function (result) { - if (result.type === 'contract') { - signale.name(result.value.white) - } else if (result.type === 'testPass') { - signale.result(result.value) - } else if (result.type === 'testFailure') { - signale.result(result.value.red) - errors.push(result) - } - } - var resultsCallback = function (_err, result, cb) { - totalPassing += result.passingNum - totalFailing += result.failureNum - totalTime += result.timePassed - cb() - } - - async.eachOfLimit(contractsToTest, 1, (contractName, index, cb) => { - TestRunner.runTest(contractName, contracts[contractName], contractsToTestDetails[index], { accounts }, testCallback, (err, result) => { - if (err) { - return cb(err) - } - resultsCallback(null, result, cb) - }) - }, function (err, _results) { - if (err) { - return next(err) - } - - console.log('\n') - if (totalPassing > 0) { - console.log((' ' + totalPassing + ' passing ').green + ('(' + totalTime + 's)').grey) - } - if (totalFailing > 0) { - console.log((' ' + totalFailing + ' failing').red) - } - console.log('') - - errors.forEach((error, index) => { - console.log(' ' + (index + 1) + ') ' + error.context + ' ' + error.value) - console.log('') - console.log(('\t error: ' + error.errMsg).red) - }) - console.log('') - - next() - }) - } - ], function () { - }) -} +const runTestFiles = require('./runTestFiles.js') +const runTestSources = require('./runTestSources.js') +const TestRunner = require('./testRunner.js') module.exports = { runTestFiles: runTestFiles, From 74559369fa998886a43d7f15e9b048591134b03a Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Mon, 19 Nov 2018 09:45:42 +0530 Subject: [PATCH 19/21] use filepath again --- remix-tests/src/compiler.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index b45aef5184..932e3911da 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -41,7 +41,6 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { // We should only look into current file if a full file name with path is given // We should only walk through directory if a directory name is passed try { - filepath = (isDirectory ? filename : path.dirname(filename)) // walkSync only if it is a directory fs.walkSync(filepath, foundpath => { // only process .sol files @@ -69,7 +68,7 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { compiler.event.register('compilationFinished', this, function (success, data, source) { next(null, data) }) - compiler.compile(sources, false) + compiler.compile(sources, filepath) } ], function (err, result) { let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') From e159b42ffa112c5eb480222dba06c24c2cf33fb7 Mon Sep 17 00:00:00 2001 From: 0mkar <0mkar@protonmail.com> Date: Tue, 20 Nov 2018 22:42:24 +0530 Subject: [PATCH 20/21] path 0.5.0 updates for remix-tests testing --- remix-tests/tests/examples_3/simple_string_test.sol | 4 ++-- remix-tests/tests/testRunner.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/remix-tests/tests/examples_3/simple_string_test.sol b/remix-tests/tests/examples_3/simple_string_test.sol index 9bcc562167..f1f62cf33c 100644 --- a/remix-tests/tests/examples_3/simple_string_test.sol +++ b/remix-tests/tests/examples_3/simple_string_test.sol @@ -12,8 +12,8 @@ contract StringTest { return Assert.equal(foo.get(), "Hello world!", "initial value is not correct"); } - function valueShouldNotBeHelloWorld() public returns (bool) { - return Assert.notEqual(foo.get(), "Hello wordl!", "initial value is not correct"); + function valueShouldNotBeHelloWordl() public returns (bool) { + return Assert.notEqual(foo.get(), "Hello wordl!", "value should not be hello world"); } function valueShouldBeHelloWorld() public returns (bool) { diff --git a/remix-tests/tests/testRunner.js b/remix-tests/tests/testRunner.js index 3b5dc673f6..092052fb7f 100644 --- a/remix-tests/tests/testRunner.js +++ b/remix-tests/tests/testRunner.js @@ -134,8 +134,8 @@ describe('testRunner', function () { it('should returns 3 messages', function () { assert.deepEqual(tests, [ { type: 'contract', value: 'StringTest', filename: 'tests/examples_3/simple_string_test.sol' }, - { type: 'testFailure', value: 'Value should be hello world', time: 1, context: 'StringTest', "errMsg": "function returned false" }, - { type: 'testPass', value: 'Value should not be hello world', time: 1, context: 'StringTest' }, + { type: 'testFailure', value: 'Value should be hello world', time: 1, context: 'StringTest', "errMsg": "initial value is not correct" }, + { type: 'testPass', value: 'Value should not be hello wordl', time: 1, context: 'StringTest' }, { type: 'testPass', value: 'Initial value should be hello', time: 1, context: 'StringTest' }, ]) }) From 0b405ed75f0744a5dd8d58aed6c3fd63da5777eb Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 2 Jan 2019 13:27:04 +0100 Subject: [PATCH 21/21] always append remix-tests:sol reference --- remix-tests/src/compiler.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/remix-tests/src/compiler.js b/remix-tests/src/compiler.js index 932e3911da..7b450e97c4 100644 --- a/remix-tests/src/compiler.js +++ b/remix-tests/src/compiler.js @@ -47,8 +47,9 @@ function compileFileOrFiles (filename, isDirectory, opts, cb) { if (foundpath.split('.').pop() === 'sol') { let c = fs.readFileSync(foundpath).toString() const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm + let includeTestLibs = '\nimport \'remix_tests.sol\';\n' if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { - c = c.replace(/(pragma solidity \^?\d+\.\d+\.\d+;)/, '$1\nimport \'remix_tests.sol\';') + c = includeTestLibs.concat(c) } sources[foundpath] = { content: c } }