commit
88a8988a71
File diff suppressed because one or more lines are too long
@ -0,0 +1,108 @@ |
|||||||
|
var CmdLine = require('./src/cmdline/index.js') |
||||||
|
// var compilation = require('./compilation.json')
|
||||||
|
|
||||||
|
var solc = require('solc') |
||||||
|
var fs = require('fs') |
||||||
|
|
||||||
|
var filename = 'test/sol/simple_storage.sol' |
||||||
|
var shortFilename = 'simple_storage.sol' |
||||||
|
|
||||||
|
var inputJson = { |
||||||
|
language: 'Solidity', |
||||||
|
sources: { |
||||||
|
}, |
||||||
|
settings: { |
||||||
|
optimizer: { |
||||||
|
enabled: true, |
||||||
|
runs: 200 |
||||||
|
}, |
||||||
|
outputSelection: { |
||||||
|
'*': { |
||||||
|
'': [ 'legacyAST' ], |
||||||
|
'*': [ 'abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates' ] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inputJson.sources[shortFilename] = {content: fs.readFileSync(filename).toString()} |
||||||
|
|
||||||
|
console.dir(inputJson) |
||||||
|
|
||||||
|
console.log('compiling...') |
||||||
|
|
||||||
|
let compilationData = JSON.parse(solc.compileStandardWrapper(JSON.stringify(inputJson))) |
||||||
|
console.dir(Object.keys(compilationData)) |
||||||
|
var compilation = {} |
||||||
|
compilation.data = compilationData |
||||||
|
compilation.source = { sources: inputJson.sources } |
||||||
|
console.dir(compilation) |
||||||
|
console.dir(compilation.data.errors) |
||||||
|
|
||||||
|
var cmdLine = new CmdLine() |
||||||
|
cmdLine.connect('http', 'http://localhost:8545') |
||||||
|
cmdLine.loadCompilationResult(compilation) |
||||||
|
cmdLine.initDebugger() |
||||||
|
|
||||||
|
// var deployContract = function (cb) {
|
||||||
|
// let _web3 = cmdLine.debugger.debugger.web3
|
||||||
|
//
|
||||||
|
// let blockNumber = null
|
||||||
|
// let txNumber = null
|
||||||
|
// let tx = null
|
||||||
|
//
|
||||||
|
// let code = compilation.data.contracts[shortFilename].SimpleStorage.evm.bytecode.object
|
||||||
|
// console.dir('deploying...')
|
||||||
|
// console.dir(code)
|
||||||
|
// _web3.eth.sendTransaction({data: '0x' + code, from: _web3.eth.accounts[0], gas: 800000}, cb)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let _web3 = cmdLine.debugger.debugger.web3
|
||||||
|
var tx = '0xf510c4f0b1d9ee262d7b9e9e87b4262f275fe029c2c733feef7dfa1e2b1e32aa' |
||||||
|
|
||||||
|
// deployContract((err, tx) => {
|
||||||
|
cmdLine.startDebug(tx, shortFilename) |
||||||
|
|
||||||
|
cmdLine.events.on('source', () => { |
||||||
|
cmdLine.getSource().forEach(console.dir) |
||||||
|
}) |
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
|
const repl = require('repl') |
||||||
|
|
||||||
|
repl.start({ |
||||||
|
prompt: '> ', |
||||||
|
eval: (cmd, context, filename, cb) => { |
||||||
|
let command = cmd.trim() |
||||||
|
if (command === 'next' || command === 'n') { |
||||||
|
cmdLine.stepOverForward(true) |
||||||
|
} |
||||||
|
if (command === 'previous' || command === 'p' || command === 'prev') { |
||||||
|
cmdLine.stepOverBack(true) |
||||||
|
} |
||||||
|
if (command === 'step' || command === 's') { |
||||||
|
cmdLine.stepIntoForward(true) |
||||||
|
} |
||||||
|
if (command === 'stepback' || command === 'sb') { |
||||||
|
cmdLine.stepIntoBack(true) |
||||||
|
} |
||||||
|
if (command === 'exit' || command === 'quit') { |
||||||
|
process.exit(0) |
||||||
|
} |
||||||
|
if (command === 'var local' || command === 'v l' || command === 'vl') { |
||||||
|
cmdLine.displayLocals() |
||||||
|
} |
||||||
|
if (command === 'var global' || command === 'v g' || command === 'vg') { |
||||||
|
cmdLine.displayGlobals() |
||||||
|
} |
||||||
|
if (command.split(' ')[0] === 'jump') { |
||||||
|
let stepIndex = parseInt(command.split(' ')[1], 10) |
||||||
|
cmdLine.jumpTo(stepIndex) |
||||||
|
} |
||||||
|
cb(null, '') |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
module.exports = cmdLine |
||||||
|
|
@ -0,0 +1,60 @@ |
|||||||
|
var remixLib = require('remix-lib') |
||||||
|
|
||||||
|
var EventManager = remixLib.EventManager |
||||||
|
var executionContext = remixLib.execution.executionContext |
||||||
|
var Web3Providers = remixLib.vm.Web3Providers |
||||||
|
var DummyProvider = remixLib.vm.DummyProvider |
||||||
|
var init = remixLib.init |
||||||
|
|
||||||
|
class ContextManager { |
||||||
|
constructor () { |
||||||
|
this.executionContext = executionContext |
||||||
|
this.web3 = this.executionContext.web3() |
||||||
|
this.event = new EventManager() |
||||||
|
} |
||||||
|
|
||||||
|
initProviders () { |
||||||
|
this.web3Providers = new Web3Providers() |
||||||
|
this.addProvider('DUMMYWEB3', new DummyProvider()) |
||||||
|
this.switchProvider('DUMMYWEB3') |
||||||
|
|
||||||
|
this.addProvider('vm', this.executionContext.vm()) |
||||||
|
this.addProvider('injected', this.executionContext.internalWeb3()) |
||||||
|
this.addProvider('web3', this.executionContext.internalWeb3()) |
||||||
|
this.switchProvider(this.executionContext.getProvider()) |
||||||
|
} |
||||||
|
|
||||||
|
getWeb3 () { |
||||||
|
return this.web3 |
||||||
|
} |
||||||
|
|
||||||
|
addProvider (type, obj) { |
||||||
|
this.web3Providers.addProvider(type, obj) |
||||||
|
this.event.trigger('providerAdded', [type]) |
||||||
|
} |
||||||
|
|
||||||
|
switchProvider (type, cb) { |
||||||
|
var self = this |
||||||
|
this.web3Providers.get(type, function (error, obj) { |
||||||
|
if (error) { |
||||||
|
// console.log('provider ' + type + ' not defined')
|
||||||
|
} else { |
||||||
|
self.web3 = obj |
||||||
|
self.executionContext.detectNetwork((error, network) => { |
||||||
|
if (error || !network) { |
||||||
|
self.web3 = obj |
||||||
|
} else { |
||||||
|
var webDebugNode = init.web3DebugNode(network.name) |
||||||
|
self.web3 = (!webDebugNode ? obj : webDebugNode) |
||||||
|
} |
||||||
|
self.event.trigger('providerChanged', [type, self.web3]) |
||||||
|
if (cb) return cb() |
||||||
|
}) |
||||||
|
self.event.trigger('providerChanged', [type, self.web3]) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
module.exports = ContextManager |
@ -0,0 +1,215 @@ |
|||||||
|
var Web3 = require('web3') |
||||||
|
var Debugger = require('../debugger/debugger.js') |
||||||
|
var ContextManager = require('./contextManager.js') |
||||||
|
var EventManager = require('events') |
||||||
|
|
||||||
|
class CmdLine { |
||||||
|
|
||||||
|
constructor () { |
||||||
|
this.events = new EventManager() |
||||||
|
this.lineColumnPos = null |
||||||
|
this.rawLocation = null |
||||||
|
} |
||||||
|
|
||||||
|
connect (providerType, url) { |
||||||
|
if (providerType !== 'http') throw new Error('unsupported provider type') |
||||||
|
this.web3 = new Web3(new Web3.providers.HttpProvider(url)) |
||||||
|
} |
||||||
|
|
||||||
|
loadCompilationData (inputJson, outputJson) { |
||||||
|
let data = {} |
||||||
|
data.data = outputJson |
||||||
|
data.source = { sources: inputJson.sources } |
||||||
|
this.loadCompilationResult(data) |
||||||
|
} |
||||||
|
|
||||||
|
loadCompilationResult (compilationResult) { |
||||||
|
this.compilation = {} |
||||||
|
this.compilation.lastCompilationResult = compilationResult |
||||||
|
} |
||||||
|
|
||||||
|
initDebugger (cb) { |
||||||
|
const self = this |
||||||
|
this.contextManager = new ContextManager() |
||||||
|
|
||||||
|
this.debugger = new Debugger({ |
||||||
|
web3: this.contextManager.getWeb3(), |
||||||
|
compiler: this.compilation |
||||||
|
}) |
||||||
|
|
||||||
|
this.contextManager.event.register('providerChanged', () => { |
||||||
|
self.debugger.updateWeb3(self.contextManager.getWeb3()) |
||||||
|
}) |
||||||
|
|
||||||
|
this.contextManager.initProviders() |
||||||
|
|
||||||
|
this.contextManager.addProvider('debugger_web3', this.web3) |
||||||
|
this.contextManager.switchProvider('debugger_web3', cb) |
||||||
|
} |
||||||
|
|
||||||
|
getSource () { |
||||||
|
const self = this |
||||||
|
|
||||||
|
let lineColumnPos = this.lineColumnPos |
||||||
|
|
||||||
|
if (!lineColumnPos || !lineColumnPos.start) return [] |
||||||
|
|
||||||
|
let content = self.compilation.lastCompilationResult.source.sources[this.filename].content.split('\n') |
||||||
|
|
||||||
|
let source = [] |
||||||
|
|
||||||
|
let line |
||||||
|
line = content[lineColumnPos.start.line - 2] |
||||||
|
if (line !== undefined) { |
||||||
|
source.push(' ' + (lineColumnPos.start.line - 1) + ': ' + line) |
||||||
|
} |
||||||
|
line = content[lineColumnPos.start.line - 1] |
||||||
|
if (line !== undefined) { |
||||||
|
source.push(' ' + lineColumnPos.start.line + ': ' + line) |
||||||
|
} |
||||||
|
|
||||||
|
let currentLineNumber = lineColumnPos.start.line |
||||||
|
let currentLine = content[currentLineNumber] |
||||||
|
source.push('=> ' + (currentLineNumber + 1) + ': ' + currentLine) |
||||||
|
|
||||||
|
let startLine = lineColumnPos.start.line |
||||||
|
for (var i = 1; i < 4; i++) { |
||||||
|
let line = content[startLine + i] |
||||||
|
source.push(' ' + (startLine + i + 1) + ': ' + line) |
||||||
|
} |
||||||
|
|
||||||
|
return source |
||||||
|
} |
||||||
|
|
||||||
|
getCurrentLine () { |
||||||
|
let lineColumnPos = this.lineColumnPos |
||||||
|
if (!lineColumnPos) return '' |
||||||
|
let currentLineNumber = lineColumnPos.start.line |
||||||
|
let content = this.compilation.lastCompilationResult.source.sources[this.filename].content.split('\n') |
||||||
|
return content[currentLineNumber] |
||||||
|
} |
||||||
|
|
||||||
|
startDebug (txNumber, filename, cb) { |
||||||
|
const self = this |
||||||
|
this.filename = filename |
||||||
|
this.txHash = txNumber |
||||||
|
this.debugger.debug(null, txNumber, null, () => { |
||||||
|
self.debugger.event.register('newSourceLocation', function (lineColumnPos, rawLocation) { |
||||||
|
self.lineColumnPos = lineColumnPos |
||||||
|
self.rawLocation = rawLocation |
||||||
|
self.events.emit('source', [lineColumnPos, rawLocation]) |
||||||
|
}) |
||||||
|
|
||||||
|
self.debugger.vmDebuggerLogic.event.register('solidityState', (data) => { |
||||||
|
self.solidityState = data |
||||||
|
self.events.emit('globals', data) |
||||||
|
}) |
||||||
|
|
||||||
|
// TODO: this doesnt work too well, it should request the data instead...
|
||||||
|
self.debugger.vmDebuggerLogic.event.register('solidityLocals', (data) => { |
||||||
|
if (JSON.stringify(data) === '{}') return |
||||||
|
self.solidityLocals = data |
||||||
|
self.events.emit('locals', data) |
||||||
|
}) |
||||||
|
|
||||||
|
if (cb) { |
||||||
|
// TODO: this should be an onReady event
|
||||||
|
setTimeout(cb, 1000) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
getVars () { |
||||||
|
return { |
||||||
|
locals: this.solidityLocals, |
||||||
|
contract: this.solidityState |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
triggerSourceUpdate () { |
||||||
|
this.events.emit('source', [this.lineColumnPos, this.rawLocation]) |
||||||
|
} |
||||||
|
|
||||||
|
stepJumpNextBreakpoint () { |
||||||
|
this.debugger.step_manager.jumpNextBreakpoint() |
||||||
|
} |
||||||
|
|
||||||
|
stepJumpPreviousBreakpoint () { |
||||||
|
this.debugger.step_manager.jumpPreviousBreakpoint() |
||||||
|
} |
||||||
|
|
||||||
|
stepOverForward (solidityMode) { |
||||||
|
this.debugger.step_manager.stepOverForward(solidityMode) |
||||||
|
} |
||||||
|
|
||||||
|
stepOverBack (solidityMode) { |
||||||
|
this.debugger.step_manager.stepOverBack(solidityMode) |
||||||
|
} |
||||||
|
|
||||||
|
stepIntoForward (solidityMode) { |
||||||
|
this.debugger.step_manager.stepIntoForward(solidityMode) |
||||||
|
} |
||||||
|
|
||||||
|
stepIntoBack (solidityMode) { |
||||||
|
this.debugger.step_manager.stepIntoBack(solidityMode) |
||||||
|
} |
||||||
|
|
||||||
|
jumpTo (step) { |
||||||
|
this.debugger.step_manager.jumpTo(step) |
||||||
|
} |
||||||
|
|
||||||
|
getTraceLength () { |
||||||
|
if (!this.debugger.step_manager) return 0 |
||||||
|
return this.debugger.step_manager.traceLength |
||||||
|
} |
||||||
|
|
||||||
|
getCodeFirstStep () { |
||||||
|
if (!this.debugger.step_manager) return 0 |
||||||
|
return this.debugger.step_manager.calculateFirstStep() |
||||||
|
} |
||||||
|
|
||||||
|
getCodeTraceLength () { |
||||||
|
if (!this.debugger.step_manager) return 0 |
||||||
|
return this.debugger.step_manager.calculateCodeLength() |
||||||
|
} |
||||||
|
|
||||||
|
nextStep () { |
||||||
|
if (!this.debugger.step_manager) return 0 |
||||||
|
return this.debugger.step_manager.nextStep() |
||||||
|
} |
||||||
|
|
||||||
|
previousStep () { |
||||||
|
if (!this.debugger.step_manager) return 0 |
||||||
|
return this.debugger.step_manager.previousStep() |
||||||
|
} |
||||||
|
|
||||||
|
currentStep () { |
||||||
|
if (!this.debugger.step_manager) return 0 |
||||||
|
return this.debugger.step_manager.currentStepIndex |
||||||
|
} |
||||||
|
|
||||||
|
canGoNext () { |
||||||
|
return this.currentStep() < this.getCodeTraceLength() |
||||||
|
} |
||||||
|
|
||||||
|
canGoPrevious () { |
||||||
|
return this.currentStep() > this.getCodeFirstStep() |
||||||
|
} |
||||||
|
|
||||||
|
unload () { |
||||||
|
return this.debugger.unload() |
||||||
|
} |
||||||
|
|
||||||
|
displayLocals () { |
||||||
|
console.dir('= displayLocals') |
||||||
|
console.dir(this.solidityLocals) |
||||||
|
} |
||||||
|
|
||||||
|
displayGlobals () { |
||||||
|
console.dir('= displayGlobals') |
||||||
|
console.dir(this.solidityState) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = CmdLine |
||||||
|
|
@ -0,0 +1,65 @@ |
|||||||
|
pragma solidity ^0.4.0; |
||||||
|
contract Ballot { |
||||||
|
|
||||||
|
struct Voter { |
||||||
|
uint weight; |
||||||
|
bool voted; |
||||||
|
uint8 vote; |
||||||
|
address delegate; |
||||||
|
} |
||||||
|
struct Proposal { |
||||||
|
uint voteCount; |
||||||
|
} |
||||||
|
|
||||||
|
address chairperson; |
||||||
|
mapping(address => Voter) voters; |
||||||
|
Proposal[] proposals; |
||||||
|
|
||||||
|
/// Create a new ballot with $(_numProposals) different proposals. |
||||||
|
function Ballot(uint8 _numProposals) public { |
||||||
|
chairperson = msg.sender; |
||||||
|
voters[chairperson].weight = 1; |
||||||
|
proposals.length = _numProposals; |
||||||
|
} |
||||||
|
|
||||||
|
/// Give $(toVoter) the right to vote on this ballot. |
||||||
|
/// May only be called by $(chairperson). |
||||||
|
function giveRightToVote(address toVoter) public { |
||||||
|
if (msg.sender != chairperson || voters[toVoter].voted) return; |
||||||
|
voters[toVoter].weight = 1; |
||||||
|
} |
||||||
|
|
||||||
|
/// Delegate your vote to the voter $(to). |
||||||
|
function delegate(address to) public { |
||||||
|
Voter storage sender = voters[msg.sender]; // assigns reference |
||||||
|
if (sender.voted) return; |
||||||
|
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) |
||||||
|
to = voters[to].delegate; |
||||||
|
if (to == msg.sender) return; |
||||||
|
sender.voted = true; |
||||||
|
sender.delegate = to; |
||||||
|
Voter storage delegateTo = voters[to]; |
||||||
|
if (delegateTo.voted) |
||||||
|
proposals[delegateTo.vote].voteCount += sender.weight; |
||||||
|
else |
||||||
|
delegateTo.weight += sender.weight; |
||||||
|
} |
||||||
|
|
||||||
|
/// Give a single vote to proposal $(toProposal). |
||||||
|
function vote(uint8 toProposal) public { |
||||||
|
Voter storage sender = voters[msg.sender]; |
||||||
|
if (sender.voted || toProposal >= proposals.length) return; |
||||||
|
sender.voted = true; |
||||||
|
sender.vote = toProposal; |
||||||
|
proposals[toProposal].voteCount += sender.weight; |
||||||
|
} |
||||||
|
|
||||||
|
function winningProposal() public constant returns (uint8 _winningProposal) { |
||||||
|
uint256 winningVoteCount = 0; |
||||||
|
for (uint8 prop = 0; prop < proposals.length; prop++) |
||||||
|
if (proposals[prop].voteCount > winningVoteCount) { |
||||||
|
winningVoteCount = proposals[prop].voteCount; |
||||||
|
_winningProposal = prop; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
pragma solidity ^0.4.25; |
||||||
|
|
||||||
|
contract SimpleStorage { |
||||||
|
uint public storedData; |
||||||
|
address owner; |
||||||
|
|
||||||
|
constructor(uint initialValue) public { |
||||||
|
storedData = initialValue; |
||||||
|
owner = msg.sender; |
||||||
|
} |
||||||
|
|
||||||
|
function set(uint x) public { |
||||||
|
storedData = x; |
||||||
|
require(msg.sender != owner); |
||||||
|
storedData = x + 2; |
||||||
|
} |
||||||
|
|
||||||
|
function get() public view returns (uint retVal) { |
||||||
|
return storedData; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
'use strict' |
||||||
|
var SourceMappingDecoder = require('./sourceMappingDecoder') |
||||||
|
|
||||||
|
function offsetToColumnConverter (compilerEvent) { |
||||||
|
this.lineBreakPositionsByContent = {} |
||||||
|
this.sourceMappingDecoder = new SourceMappingDecoder() |
||||||
|
var self = this |
||||||
|
if (compilerEvent) { |
||||||
|
compilerEvent.register('compilationFinished', function (success, data, source) { |
||||||
|
self.clear() |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, sources, asts) { |
||||||
|
if (!this.lineBreakPositionsByContent[file]) { |
||||||
|
for (var filename in asts) { |
||||||
|
var source = asts[filename] |
||||||
|
if (source.id === file) { |
||||||
|
this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[filename].content) |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) |
||||||
|
} |
||||||
|
|
||||||
|
offsetToColumnConverter.prototype.clear = function () { |
||||||
|
this.lineBreakPositionsByContent = {} |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = offsetToColumnConverter |
@ -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 |
@ -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 |
@ -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 |
Loading…
Reference in new issue