parent
435120ab24
commit
3a46a2fd4b
@ -0,0 +1,149 @@ |
||||
var async = require('async') |
||||
var changeCase = require('change-case') |
||||
var Web3 = require('web3') |
||||
|
||||
function getFunctionFullName (signature, methodIdentifiers) { |
||||
for (var method in methodIdentifiers) { |
||||
if (signature.replace('0x', '') === methodIdentifiers[method].replace('0x', '')) { |
||||
return method |
||||
} |
||||
} |
||||
return null |
||||
} |
||||
|
||||
function getOverridedSender (userdoc, signature, methodIdentifiers) { |
||||
let fullName = getFunctionFullName(signature, methodIdentifiers) |
||||
let match = /sender: account-+(\d)/g |
||||
let accountIndex = userdoc.methods[fullName] ? match.exec(userdoc.methods[fullName].notice) : null |
||||
return fullName && accountIndex ? accountIndex[1] : null |
||||
} |
||||
|
||||
function getAvailableFunctions (jsonInterface) { |
||||
return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name) |
||||
} |
||||
|
||||
function getTestFunctions (jsonInterface) { |
||||
let specialFunctions = ['beforeAll', 'beforeEach', 'afterAll', 'afterEach'] |
||||
return jsonInterface.filter((x) => specialFunctions.indexOf(x.name) < 0 && x.type === 'function') |
||||
} |
||||
|
||||
function createRunList (jsonInterface) { |
||||
let availableFunctions = getAvailableFunctions(jsonInterface) |
||||
let testFunctions = getTestFunctions(jsonInterface) |
||||
let runList = [] |
||||
|
||||
if (availableFunctions.indexOf('beforeAll') >= 0) { |
||||
runList.push({name: 'beforeAll', type: 'internal', constant: false}) |
||||
} |
||||
|
||||
for (let func of testFunctions) { |
||||
if (availableFunctions.indexOf('beforeEach') >= 0) { |
||||
runList.push({name: 'beforeEach', type: 'internal', constant: false}) |
||||
} |
||||
runList.push({name: func.name, signature: func.signature, type: 'test', constant: func.constant}) |
||||
if (availableFunctions.indexOf('afterEach') >= 0) { |
||||
runList.push({name: 'afterEach', type: 'internal', constant: false}) |
||||
} |
||||
} |
||||
|
||||
if (availableFunctions.indexOf('afterAll') >= 0) { |
||||
runList.push({name: 'afterAll', type: 'internal', constant: false}) |
||||
} |
||||
|
||||
return runList |
||||
} |
||||
|
||||
function runTest (testName, testObject, contractDetails, opts, testCallback, resultsCallback) { |
||||
let runList = createRunList(testObject._jsonInterface) |
||||
|
||||
let passingNum = 0 |
||||
let failureNum = 0 |
||||
let timePassed = 0 |
||||
let web3 = new Web3() |
||||
|
||||
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' |
||||
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) |
||||
if (!isBrowser) { |
||||
let signale = require('signale') |
||||
signale.warn('DO NOT TRY TO ACCESS (IN YOUR SOLIDITY TEST) AN ACCOUNT GREATER THAN THE LENGTH OF THE FOLLOWING ARRAY (' + opts.accounts.length + ') :') |
||||
signale.warn(opts.accounts) |
||||
signale.warn('e.g: the following code won\'t work in the current context:') |
||||
signale.warn('TestsAccounts.getAccount(' + opts.accounts.length + ')') |
||||
} |
||||
|
||||
testCallback({type: 'contract', value: testName, filename: testObject.filename}) |
||||
async.eachOfLimit(runList, 1, function (func, index, next) { |
||||
let sender |
||||
if (func.signature) { |
||||
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) |
||||
if (opts.accounts) { |
||||
sender = opts.accounts[sender] |
||||
} |
||||
} |
||||
let sendParams |
||||
if (sender) sendParams = { from: sender } |
||||
|
||||
let method = testObject.methods[func.name].apply(testObject.methods[func.name], []) |
||||
let startTime = Date.now() |
||||
if (func.constant) { |
||||
method.call(sendParams).then((result) => { |
||||
let time = Math.ceil((Date.now() - startTime) / 1000.0) |
||||
if (result) { |
||||
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) |
||||
passingNum += 1 |
||||
timePassed += time |
||||
} else { |
||||
testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: 'function returned false', context: testName}) |
||||
failureNum += 1 |
||||
} |
||||
next() |
||||
}) |
||||
} else { |
||||
method.send(sendParams).on('receipt', function (receipt) { |
||||
try { |
||||
let time = Math.ceil((Date.now() - startTime) / 1000.0) |
||||
let topic = Web3.utils.sha3('AssertionEvent(bool,string)') |
||||
|
||||
let testPassed = false |
||||
|
||||
for (let i in receipt.events) { |
||||
let event = receipt.events[i] |
||||
if (event.raw.topics.indexOf(topic) >= 0) { |
||||
var testEvent = web3.eth.abi.decodeParameters(['bool', 'string'], event.raw.data) |
||||
if (!testEvent[0]) { |
||||
testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: testEvent[1], context: testName}) |
||||
failureNum += 1 |
||||
return next() |
||||
} |
||||
testPassed = true |
||||
} |
||||
} |
||||
|
||||
if (testPassed) { |
||||
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) |
||||
passingNum += 1 |
||||
} |
||||
|
||||
return next() |
||||
} catch (err) { |
||||
console.log('error!') |
||||
console.dir(err) |
||||
return next(err) |
||||
} |
||||
}).on('error', function (err) { |
||||
console.error(err) |
||||
next(err) |
||||
}) |
||||
} |
||||
}, function (error) { |
||||
resultsCallback(error, { |
||||
passingNum: passingNum, |
||||
failureNum: failureNum, |
||||
timePassed: timePassed |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
module.exports = { |
||||
runTest: runTest |
||||
} |
@ -1,10 +1,10 @@ |
||||
import runTestFiles from './runTestFiles.ts' |
||||
import runTestSources from './runTestSources.ts' |
||||
import TestRunner from './testRunner.ts' |
||||
import runTestFiles from './runTestFiles' |
||||
import runTestSources from './runTestSources' |
||||
import runTest from './testRunner' |
||||
|
||||
module.exports = { |
||||
runTestFiles: runTestFiles, |
||||
runTestSources: runTestSources, |
||||
runTest: TestRunner.runTest, |
||||
runTest: runTest, |
||||
assertLibCode: require('../sol/tests.sol.js') |
||||
} |
||||
|
@ -0,0 +1,133 @@ |
||||
import async = require('async') |
||||
import path = require('path') |
||||
import fs = require('./fs') |
||||
import runTest = require('./testRunner.js') |
||||
require('colors') |
||||
|
||||
import Compiler = require('./compiler.js') |
||||
import Deployer = require('./deployer.js') |
||||
|
||||
function runTestFiles(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: any[] = [] |
||||
let contractsToTestDetails: any[] = [] |
||||
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: any[] = [] |
||||
|
||||
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) => { |
||||
runTest(contractName, contracts(contractName), contractsToTestDetails[index], { accounts }, testCallback, (err, result) => { |
||||
if (err) { |
||||
return cb(err) |
||||
} |
||||
resultsCallback(null, result, cb) |
||||
}) |
||||
}, function (err) { |
||||
if (err) { |
||||
return next(err) |
||||
} |
||||
|
||||
console.log('\n') |
||||
if (totalPassing > 0) { |
||||
console.log(('%c ' + totalPassing + ' passing ') + ('%c(' + totalTime + 's)'),'color: green','color: grey') |
||||
} |
||||
if (totalFailing > 0) { |
||||
console.log(('%c ' + totalFailing + ' failing'),'color: red') |
||||
} |
||||
console.log('') |
||||
|
||||
errors.forEach((error, index) => { |
||||
console.log(' ' + (index + 1) + ') ' + error.context + ' ' + error.value) |
||||
console.log('') |
||||
console.log(('%c\t error: ' + error.errMsg),'color: red') |
||||
}) |
||||
console.log('') |
||||
|
||||
next() |
||||
}) |
||||
} |
||||
], function () { |
||||
}) |
||||
} |
||||
|
||||
export = runTestFiles; |
@ -0,0 +1,118 @@ |
||||
import async = require('async') |
||||
require('colors') |
||||
|
||||
import Compiler = require('./compiler.js') |
||||
import Deployer = require('./deployer.js') |
||||
import runTest = require('./testRunner.js') |
||||
|
||||
import Web3 = require('web3') |
||||
import Provider from 'remix-simulator' |
||||
|
||||
interface FinalResult { |
||||
totalPassing: number, |
||||
totalFailing: number, |
||||
totalTime: number, |
||||
errors: any[], |
||||
} |
||||
|
||||
var createWeb3Provider = function () { |
||||
let web3 = new Web3() |
||||
web3.setProvider(new Provider()) |
||||
return web3 |
||||
} |
||||
|
||||
function runTestSources(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: any[] = [] |
||||
let contractsToTestDetails: any[] = [] |
||||
|
||||
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: any[] = [] |
||||
|
||||
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) => { |
||||
runTest(contractName, contracts(contractName), contractsToTestDetails[index], { accounts }, _testCallback, (err, result) => { |
||||
if (err) { |
||||
return cb(err) |
||||
} |
||||
_resultsCallback(null, result, cb) |
||||
}) |
||||
}, function (err) { |
||||
if (err) { |
||||
return next(err) |
||||
} |
||||
|
||||
let finalResults: FinalResult = { |
||||
totalPassing: 0, |
||||
totalFailing: 0, |
||||
totalTime: 0, |
||||
errors: [], |
||||
} |
||||
|
||||
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) |
||||
} |
||||
export = runTestSources; |
@ -1,149 +1,135 @@ |
||||
var async = require('async') |
||||
var changeCase = require('change-case') |
||||
var Web3 = require('web3') |
||||
|
||||
function getFunctionFullName (signature, methodIdentifiers) { |
||||
for (var method in methodIdentifiers) { |
||||
if (signature.replace('0x', '') === methodIdentifiers[method].replace('0x', '')) { |
||||
return method |
||||
"use strict"; |
||||
exports.__esModule = true; |
||||
var async = require("async"); |
||||
var changeCase = require("change-case"); |
||||
var Web3 = require("web3"); |
||||
function getFunctionFullName(signature, methodIdentifiers) { |
||||
for (var method in methodIdentifiers) { |
||||
if (signature.replace('0x', '') === methodIdentifiers[method].replace('0x', '')) { |
||||
return method; |
||||
} |
||||
} |
||||
} |
||||
return null |
||||
return null; |
||||
} |
||||
|
||||
function getOverridedSender (userdoc, signature, methodIdentifiers) { |
||||
let fullName = getFunctionFullName(signature, methodIdentifiers) |
||||
let match = /sender: account-+(\d)/g |
||||
let accountIndex = userdoc.methods[fullName] ? match.exec(userdoc.methods[fullName].notice) : null |
||||
return fullName && accountIndex ? accountIndex[1] : null |
||||
function getOverridedSender(userdoc, signature, methodIdentifiers) { |
||||
var fullName = getFunctionFullName(signature, methodIdentifiers); |
||||
var match = /sender: account-+(\d)/g; |
||||
var accountIndex = userdoc.methods[fullName] ? match.exec(userdoc.methods[fullName].notice) : null; |
||||
return fullName && accountIndex ? accountIndex[1] : null; |
||||
} |
||||
|
||||
function getAvailableFunctions (jsonInterface) { |
||||
return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name) |
||||
function getAvailableFunctions(jsonInterface) { |
||||
return jsonInterface.reverse().filter(function (x) { return x.type === 'function'; }).map(function (x) { return x.name; }); |
||||
} |
||||
|
||||
function getTestFunctions (jsonInterface) { |
||||
let specialFunctions = ['beforeAll', 'beforeEach', 'afterAll', 'afterEach'] |
||||
return jsonInterface.filter((x) => specialFunctions.indexOf(x.name) < 0 && x.type === 'function') |
||||
function getTestFunctions(jsonInterface) { |
||||
var specialFunctions = ['beforeAll', 'beforeEach', 'afterAll', 'afterEach']; |
||||
return jsonInterface.filter(function (x) { return specialFunctions.indexOf(x.name) < 0 && x.type === 'function'; }); |
||||
} |
||||
|
||||
function createRunList (jsonInterface) { |
||||
let availableFunctions = getAvailableFunctions(jsonInterface) |
||||
let testFunctions = getTestFunctions(jsonInterface) |
||||
let runList = [] |
||||
|
||||
if (availableFunctions.indexOf('beforeAll') >= 0) { |
||||
runList.push({name: 'beforeAll', type: 'internal', constant: false}) |
||||
} |
||||
|
||||
for (let func of testFunctions) { |
||||
if (availableFunctions.indexOf('beforeEach') >= 0) { |
||||
runList.push({name: 'beforeEach', type: 'internal', constant: false}) |
||||
function createRunList(jsonInterface) { |
||||
var availableFunctions = getAvailableFunctions(jsonInterface); |
||||
var testFunctions = getTestFunctions(jsonInterface); |
||||
var runList = []; |
||||
if (availableFunctions.indexOf('beforeAll') >= 0) { |
||||
runList.push({ name: 'beforeAll', type: 'internal', constant: false }); |
||||
} |
||||
runList.push({name: func.name, signature: func.signature, type: 'test', constant: func.constant}) |
||||
if (availableFunctions.indexOf('afterEach') >= 0) { |
||||
runList.push({name: 'afterEach', type: 'internal', constant: false}) |
||||
for (var _i = 0, testFunctions_1 = testFunctions; _i < testFunctions_1.length; _i++) { |
||||
var func = testFunctions_1[_i]; |
||||
if (availableFunctions.indexOf('beforeEach') >= 0) { |
||||
runList.push({ name: 'beforeEach', type: 'internal', constant: false }); |
||||
} |
||||
runList.push({ name: func.name, signature: func.signature, type: 'test', constant: func.constant }); |
||||
if (availableFunctions.indexOf('afterEach') >= 0) { |
||||
runList.push({ name: 'afterEach', type: 'internal', constant: false }); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (availableFunctions.indexOf('afterAll') >= 0) { |
||||
runList.push({name: 'afterAll', type: 'internal', constant: false}) |
||||
} |
||||
|
||||
return runList |
||||
if (availableFunctions.indexOf('afterAll') >= 0) { |
||||
runList.push({ name: 'afterAll', type: 'internal', constant: false }); |
||||
} |
||||
return runList; |
||||
} |
||||
|
||||
function runTest (testName, testObject, contractDetails, opts, testCallback, resultsCallback) { |
||||
let runList = createRunList(testObject._jsonInterface) |
||||
|
||||
let passingNum = 0 |
||||
let failureNum = 0 |
||||
let timePassed = 0 |
||||
let web3 = new Web3() |
||||
|
||||
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' |
||||
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) |
||||
if (!isBrowser) { |
||||
let signale = require('signale') |
||||
signale.warn('DO NOT TRY TO ACCESS (IN YOUR SOLIDITY TEST) AN ACCOUNT GREATER THAN THE LENGTH OF THE FOLLOWING ARRAY (' + opts.accounts.length + ') :') |
||||
signale.warn(opts.accounts) |
||||
signale.warn('e.g: the following code won\'t work in the current context:') |
||||
signale.warn('TestsAccounts.getAccount(' + opts.accounts.length + ')') |
||||
} |
||||
|
||||
testCallback({type: 'contract', value: testName, filename: testObject.filename}) |
||||
async.eachOfLimit(runList, 1, function (func, index, next) { |
||||
let sender |
||||
if (func.signature) { |
||||
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) |
||||
if (opts.accounts) { |
||||
sender = opts.accounts[sender] |
||||
} |
||||
function runTest(testName, testObject, contractDetails, opts, testCallback, resultsCallback) { |
||||
var runList = createRunList(testObject._jsonInterface); |
||||
var passingNum = 0; |
||||
var failureNum = 0; |
||||
var timePassed = 0; |
||||
var web3 = new Web3(); |
||||
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-'; |
||||
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1); |
||||
if (!isBrowser) { |
||||
var signale = require('signale'); |
||||
signale.warn('DO NOT TRY TO ACCESS (IN YOUR SOLIDITY TEST) AN ACCOUNT GREATER THAN THE LENGTH OF THE FOLLOWING ARRAY (' + opts.accounts.length + ') :'); |
||||
signale.warn(opts.accounts); |
||||
signale.warn('e.g: the following code won\'t work in the current context:'); |
||||
signale.warn('TestsAccounts.getAccount(' + opts.accounts.length + ')'); |
||||
} |
||||
let sendParams |
||||
if (sender) sendParams = { from: sender } |
||||
|
||||
let method = testObject.methods[func.name].apply(testObject.methods[func.name], []) |
||||
let startTime = Date.now() |
||||
if (func.constant) { |
||||
method.call(sendParams).then((result) => { |
||||
let time = Math.ceil((Date.now() - startTime) / 1000.0) |
||||
if (result) { |
||||
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) |
||||
passingNum += 1 |
||||
timePassed += time |
||||
} else { |
||||
testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: 'function returned false', context: testName}) |
||||
failureNum += 1 |
||||
} |
||||
next() |
||||
}) |
||||
} else { |
||||
method.send(sendParams).on('receipt', function (receipt) { |
||||
try { |
||||
let time = Math.ceil((Date.now() - startTime) / 1000.0) |
||||
let topic = Web3.utils.sha3('AssertionEvent(bool,string)') |
||||
|
||||
let testPassed = false |
||||
|
||||
for (let i in receipt.events) { |
||||
let event = receipt.events[i] |
||||
if (event.raw.topics.indexOf(topic) >= 0) { |
||||
var testEvent = web3.eth.abi.decodeParameters(['bool', 'string'], event.raw.data) |
||||
if (!testEvent[0]) { |
||||
testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: testEvent[1], context: testName}) |
||||
failureNum += 1 |
||||
return next() |
||||
} |
||||
testPassed = true |
||||
testCallback({ type: 'contract', value: testName, filename: testObject.filename }); |
||||
async.eachOfLimit(runList, 1, function (func, index, next) { |
||||
var sender; |
||||
if (func.signature) { |
||||
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers); |
||||
if (opts.accounts) { |
||||
sender = opts.accounts[sender]; |
||||
} |
||||
} |
||||
|
||||
if (testPassed) { |
||||
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) |
||||
passingNum += 1 |
||||
} |
||||
|
||||
return next() |
||||
} catch (err) { |
||||
console.log('error!') |
||||
console.dir(err) |
||||
return next(err) |
||||
} |
||||
}).on('error', function (err) { |
||||
console.error(err) |
||||
next(err) |
||||
}) |
||||
} |
||||
}, function (error) { |
||||
resultsCallback(error, { |
||||
passingNum: passingNum, |
||||
failureNum: failureNum, |
||||
timePassed: timePassed |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
module.exports = { |
||||
runTest: runTest |
||||
var sendParams; |
||||
if (sender) |
||||
sendParams = { from: sender }; |
||||
var method = testObject.methods[func.name].apply(testObject.methods[func.name], []); |
||||
var startTime = Date.now(); |
||||
if (func.constant) { |
||||
method.call(sendParams).then(function (result) { |
||||
var time = Math.ceil((Date.now() - startTime) / 1000.0); |
||||
if (result) { |
||||
testCallback({ type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName }); |
||||
passingNum += 1; |
||||
timePassed += time; |
||||
} |
||||
else { |
||||
testCallback({ type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: 'function returned false', context: testName }); |
||||
failureNum += 1; |
||||
} |
||||
next(); |
||||
}); |
||||
} |
||||
else { |
||||
method.send(sendParams).on('receipt', function (receipt) { |
||||
try { |
||||
var time = Math.ceil((Date.now() - startTime) / 1000.0); |
||||
var topic = Web3.utils.sha3('AssertionEvent(bool,string)'); |
||||
var testPassed = false; |
||||
for (var i in receipt.events) { |
||||
var event_1 = receipt.events[i]; |
||||
if (event_1.raw.topics.indexOf(topic) >= 0) { |
||||
var testEvent = web3.eth.abi.decodeParameters(['bool', 'string'], event_1.raw.data); |
||||
if (!testEvent[0]) { |
||||
testCallback({ type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: testEvent[1], context: testName }); |
||||
failureNum += 1; |
||||
return next(); |
||||
} |
||||
testPassed = true; |
||||
} |
||||
} |
||||
if (testPassed) { |
||||
testCallback({ type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName }); |
||||
passingNum += 1; |
||||
} |
||||
return next(); |
||||
} |
||||
catch (err) { |
||||
console.log('error!'); |
||||
console.dir(err); |
||||
return next(err); |
||||
} |
||||
}).on('error', function (err) { |
||||
console.error(err); |
||||
next(err); |
||||
}); |
||||
} |
||||
}, function (error) { |
||||
resultsCallback(error, { |
||||
passingNum: passingNum, |
||||
failureNum: failureNum, |
||||
timePassed: timePassed |
||||
}); |
||||
}); |
||||
} |
||||
exports.runTest = runTest; |
||||
|
@ -0,0 +1,147 @@ |
||||
import async = require('async'); |
||||
import changeCase = require('change-case'); |
||||
import Web3 = require('web3'); |
||||
|
||||
function getFunctionFullName (signature, methodIdentifiers) { |
||||
for (var method in methodIdentifiers) { |
||||
if (signature.replace('0x', '') === methodIdentifiers[method].replace('0x', '')) { |
||||
return method |
||||
} |
||||
} |
||||
return null |
||||
} |
||||
|
||||
function getOverridedSender (userdoc, signature, methodIdentifiers) { |
||||
let fullName: any = getFunctionFullName(signature, methodIdentifiers) |
||||
let match = /sender: account-+(\d)/g |
||||
let accountIndex = userdoc.methods[fullName] ? match.exec(userdoc.methods[fullName].notice) : null |
||||
return fullName && accountIndex ? accountIndex[1] : null |
||||
} |
||||
|
||||
function getAvailableFunctions (jsonInterface) { |
||||
return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name) |
||||
} |
||||
|
||||
function getTestFunctions (jsonInterface) { |
||||
let specialFunctions = ['beforeAll', 'beforeEach', 'afterAll', 'afterEach'] |
||||
return jsonInterface.filter((x) => specialFunctions.indexOf(x.name) < 0 && x.type === 'function') |
||||
} |
||||
|
||||
function createRunList (jsonInterface) { |
||||
let availableFunctions = getAvailableFunctions(jsonInterface) |
||||
let testFunctions = getTestFunctions(jsonInterface) |
||||
let runList: any[] = [] |
||||
|
||||
if (availableFunctions.indexOf('beforeAll') >= 0) { |
||||
runList.push({name: 'beforeAll', type: 'internal', constant: false}) |
||||
} |
||||
|
||||
for (let func of testFunctions) { |
||||
if (availableFunctions.indexOf('beforeEach') >= 0) { |
||||
runList.push({name: 'beforeEach', type: 'internal', constant: false}) |
||||
} |
||||
runList.push({name: func.name, signature: func.signature, type: 'test', constant: func.constant}) |
||||
if (availableFunctions.indexOf('afterEach') >= 0) { |
||||
runList.push({name: 'afterEach', type: 'internal', constant: false}) |
||||
} |
||||
} |
||||
|
||||
if (availableFunctions.indexOf('afterAll') >= 0) { |
||||
runList.push({name: 'afterAll', type: 'internal', constant: false}) |
||||
} |
||||
|
||||
return runList |
||||
} |
||||
|
||||
function runTest (testName, testObject, contractDetails, opts, testCallback, resultsCallback) { |
||||
let runList = createRunList(testObject._jsonInterface) |
||||
|
||||
let passingNum = 0 |
||||
let failureNum = 0 |
||||
let timePassed = 0 |
||||
let web3 = new Web3() |
||||
|
||||
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' |
||||
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) |
||||
if (!isBrowser) { |
||||
let signale = require('signale') |
||||
signale.warn('DO NOT TRY TO ACCESS (IN YOUR SOLIDITY TEST) AN ACCOUNT GREATER THAN THE LENGTH OF THE FOLLOWING ARRAY (' + opts.accounts.length + ') :') |
||||
signale.warn(opts.accounts) |
||||
signale.warn('e.g: the following code won\'t work in the current context:') |
||||
signale.warn('TestsAccounts.getAccount(' + opts.accounts.length + ')') |
||||
} |
||||
|
||||
testCallback({type: 'contract', value: testName, filename: testObject.filename}) |
||||
async.eachOfLimit(runList, 1, function (func, index, next) { |
||||
let sender |
||||
if (func.signature) { |
||||
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) |
||||
if (opts.accounts) { |
||||
sender = opts.accounts[sender] |
||||
} |
||||
} |
||||
let sendParams |
||||
if (sender) sendParams = { from: sender } |
||||
|
||||
let method = testObject.methods[func.name].apply(testObject.methods[func.name], []) |
||||
let startTime = Date.now() |
||||
if (func.constant) { |
||||
method.call(sendParams).then((result) => { |
||||
let time = Math.ceil((Date.now() - startTime) / 1000.0) |
||||
if (result) { |
||||
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) |
||||
passingNum += 1 |
||||
timePassed += time |
||||
} else { |
||||
testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: 'function returned false', context: testName}) |
||||
failureNum += 1 |
||||
} |
||||
next() |
||||
}) |
||||
} else { |
||||
method.send(sendParams).on('receipt', function (receipt) { |
||||
try { |
||||
let time = Math.ceil((Date.now() - startTime) / 1000.0) |
||||
let topic = Web3.utils.sha3('AssertionEvent(bool,string)') |
||||
|
||||
let testPassed = false |
||||
|
||||
for (let i in receipt.events) { |
||||
let event = receipt.events[i] |
||||
if (event.raw.topics.indexOf(topic) >= 0) { |
||||
var testEvent = web3.eth.abi.decodeParameters(['bool', 'string'], event.raw.data) |
||||
if (!testEvent[0]) { |
||||
testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: testEvent[1], context: testName}) |
||||
failureNum += 1 |
||||
return next() |
||||
} |
||||
testPassed = true |
||||
} |
||||
} |
||||
|
||||
if (testPassed) { |
||||
testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName}) |
||||
passingNum += 1 |
||||
} |
||||
|
||||
return next() |
||||
} catch (err) { |
||||
console.log('error!') |
||||
console.dir(err) |
||||
return next(err) |
||||
} |
||||
}).on('error', function (err) { |
||||
console.error(err) |
||||
next(err) |
||||
}) |
||||
} |
||||
}, function (error) { |
||||
resultsCallback(error, { |
||||
passingNum: passingNum, |
||||
failureNum: failureNum, |
||||
timePassed: timePassed |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
export = runTest |
Loading…
Reference in new issue