Merge pull request #747 from ethereum/addTest

Add debug tests
pull/7/head
yann300 7 years ago committed by GitHub
commit c6ae7908c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      .circleci/config.yml
  2. 6
      remix-debug/package.json
  3. 184
      remix-debug/test/tests.js
  4. 64
      remix-debug/test/vmCall.js

@ -31,6 +31,15 @@ jobs:
- checkout
- run: cd remix-solidity && npm install && npm test
remix-debug:
docker:
- image: circleci/node:7.10
environment:
working_directory: ~/repo
steps:
- checkout
- run: cd remix-debug && npm install && npm test
workflows:
version: 2
build_all:
@ -38,4 +47,5 @@ workflows:
- remix-lib
- remix-core
- remix-solidity
- remix-debug

@ -22,6 +22,8 @@
"babel-preset-es2015": "^6.24.0",
"babel-preset-stage-0": "^6.24.1",
"babelify": "^7.3.0",
"ethereumjs-util": "^4.5.0",
"ethereumjs-vm": "2.3.1",
"notify-error": "^1.2.0",
"npm-run-all": "^4.1.2",
"remix-core": "latest",
@ -32,7 +34,9 @@
},
"scripts": {
"build": "mkdirp build; browserify index.js > build/app.js",
"lint": "standard | notify-error"
"lint": "standard | notify-error",
"downloadsolc": "cd node_modules/solc && (test -e soljson.js || wget --no-check-certificate https://solc-bin.ethereum.org/soljson.js) && cd ..",
"test": "standard && npm run downloadsolc && tape ./test/tests.js"
},
"repository": {
"type": "git",

@ -0,0 +1,184 @@
'use strict'
var tape = require('tape')
var remixLib = require('remix-lib')
var remixCore = require('remix-core')
var compilerInput = remixLib.helpers.compiler.compilerInput
var vmCall = require('./vmCall')
var Debugger = require('../src/Ethdebugger')
var compiler = require('solc')
tape('debug contract', function (t) {
t.plan(12)
var privateKey = new Buffer('dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a', 'hex')
var vm = vmCall.initVM(t, privateKey)
var output = compiler.compileStandardWrapper(compilerInput(ballot))
output = JSON.parse(output)
var web3VM = new remixLib.vm.Web3VMProvider()
web3VM.setVM(vm)
vmCall.sendTx(vm, {nonce: 0, privateKey: privateKey}, null, 0, output.contracts['test.sol']['Ballot'].evm.bytecode.object, (error, txHash) => {
if (error) {
t.end(error)
} else {
web3VM.eth.getTransaction(txHash, (error, tx) => {
if (error) {
t.end(error)
} else {
var debugManager = new Debugger({
compilationResult: function () {
return output
}
})
debugManager.addProvider('web3vmprovider', web3VM)
debugManager.switchProvider('web3vmprovider')
debugManager.callTree.event.register('callTreeReady', () => {
testDebugging(t, debugManager)
})
debugManager.debug(tx)
}
})
}
})
})
function testDebugging (t, debugManager) {
// stack
debugManager.traceManager.getStackAt(4, (error, callstack) => {
if (error) return t.end(error)
t.equal(JSON.stringify(callstack), JSON.stringify([ '0x0000000000000000000000000000000000000000000000000000000000000000' ]))
})
debugManager.traceManager.getStackAt(41, (error, callstack) => {
if (error) return t.end(error)
/*
t.equal(JSON.stringify(callstack), JSON.stringify(['0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000004b0897b0513fdc7c541b6d9d7e929c4e5364d2db', '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000001', '0x000000000000000000000000000000000000000000000000000000000000002d']))
*/
})
// storage
debugManager.traceManager.getCurrentCalledAddressAt(38, (error, address) => {
if (error) return t.end(error)
var storageView = debugManager.storageViewAt(38, address)
storageView.storageRange((error, storage) => {
if (error) return t.end(error)
t.equal(JSON.stringify(storage), JSON.stringify({ '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563': { key: '0x0000000000000000000000000000000000000000000000000000000000000000', value: '0x0000000000000000000000004b0897b0513fdc7c541b6d9d7e929c4e5364d2db' } }))
})
})
debugManager.extractStateAt(138, (error, state) => {
if (error) return t.end(error)
debugManager.decodeStateAt(138, state, (error, decodedState) => {
if (error) return t.end(error)
t.equal(decodedState['chairperson'].value, '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB')
t.equal(decodedState['chairperson'].type, 'address')
t.equal(decodedState['proposals'].value[0].value.voteCount.value, '0')
t.equal(decodedState['proposals'].value[0].value.voteCount.type, 'uint256')
t.equal(decodedState['proposals'].value[0].type, 'struct Ballot.Proposal')
t.equal(decodedState['proposals'].length, '0x1')
t.equal(decodedState['proposals'].type, 'struct Ballot.Proposal[]')
})
})
debugManager.traceManager.getCurrentCalledAddressAt(138, (error, address) => {
if (error) return t.end(error)
debugManager.sourceLocationFromVMTraceIndex(address, 138, (error, location) => {
if (error) return t.end(error)
debugManager.decodeLocalsAt(138, location, (error, decodedlocals) => {
if (error) return t.end(error)
t.equal(JSON.stringify(decodedlocals), JSON.stringify({'p': {'value': '45', 'type': 'uint256'}, 'addressLocal': {'value': '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB', 'type': 'address'}, 'proposalsLocals': {'value': [{'value': {'voteCount': {'value': '0', 'type': 'uint256'}}, 'type': 'struct Ballot.Proposal'}], 'length': '0x1', 'type': 'struct Ballot.Proposal[]'}}))
})
})
})
var sourceMappingDecoder = new remixLib.SourceMappingDecoder()
var breakPointManager = new remixCore.code.BreakpointManager(debugManager, (rawLocation) => {
return sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, sourceMappingDecoder.getLinebreakPositions(ballot))
})
breakPointManager.add({fileName: 'test.sol', row: 23})
breakPointManager.event.register('breakpointHit', function (sourceLocation, step) {
console.log('breakpointHit')
t.equal(JSON.stringify(sourceLocation), JSON.stringify({ start: 591, length: 1, file: 0, jump: '-' }))
t.equal(step, 73)
})
breakPointManager.event.register('noBreakpointHit', function () {
t.end('noBreakpointHit')
console.log('noBreakpointHit')
})
breakPointManager.jumpNextBreakpoint(0, true)
}
var ballot = `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() public {
uint p = 45;
chairperson = msg.sender;
address addressLocal = msg.sender; // copy of state variable
voters[chairperson].weight = 1;
proposals.length = 1;
Proposal[] proposalsLocals = proposals; // copy of state variable
}
/// 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,64 @@
'use strict'
var utileth = require('ethereumjs-util')
var Tx = require('ethereumjs-tx')
var Block = require('ethereumjs-block')
var BN = require('ethereumjs-util').BN
var remixLib = require('remix-lib')
function sendTx (vm, from, to, value, data, cb) {
var tx = new Tx({
nonce: new BN(from.nonce++),
gasPrice: new BN(1),
gasLimit: new BN(3000000, 10),
to: to,
value: new BN(value, 10),
data: new Buffer(data, 'hex')
})
tx.sign(from.privateKey)
var block = new Block({
header: {
timestamp: new Date().getTime() / 1000 | 0,
number: 0
},
transactions: [],
uncleHeaders: []
})
vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}, function (error, result) {
setTimeout(() => {
cb(error, utileth.bufferToHex(tx.hash()))
}, 500)
})
}
/*
Init VM / Send Transaction
*/
function initVM (st, privateKey) {
var utileth = require('ethereumjs-util')
var VM = require('ethereumjs-vm')
var Web3Providers = remixLib.vm.Web3Providers
var address = utileth.privateToAddress(privateKey)
var vm = new VM({
enableHomestead: true,
activatePrecompiles: true
})
vm.stateManager.putAccountBalance(address, 'f00000000000000001', function cb () {})
var web3Providers = new Web3Providers()
web3Providers.addVM('VM', vm)
web3Providers.get('VM', function (error, obj) {
if (error) {
var mes = 'provider TEST not defined'
console.log(mes)
st.fail(mes)
} else {
remixLib.global.web3 = obj
remixLib.global.web3Debug = obj
}
})
return vm
}
module.exports = {
sendTx: sendTx,
initVM: initVM
}
Loading…
Cancel
Save