This commit is contained in:
Andre Medeiros 2018-08-08 14:26:40 -04:00 committed by Iuri Matias
parent 8e396a17d8
commit 676f15fb49
4 changed files with 63 additions and 24 deletions

View File

@ -36,7 +36,7 @@ const parseResponse = function(ipc, resBody){
} catch(e) { } catch(e) {
return; // Response is not a json. Do nothing return; // Response is not a json. Do nothing
} }
console.log(jsonO);
if(commList[jsonO.id]){ if(commList[jsonO.id]){
commList[jsonO.id].transactionHash = jsonO.result; commList[jsonO.id].transactionHash = jsonO.result;
transactions[jsonO.result] = {commListId: jsonO.id}; transactions[jsonO.result] = {commListId: jsonO.id};

View File

@ -95,6 +95,7 @@ class ContractSource {
throw new Error('Error generating coverage: solc output was not assigned'); throw new Error('Error generating coverage: solc output was not assigned');
var coverage = { var coverage = {
code: this.body.split("\n"),
l: {}, l: {},
path: this.file, path: this.file,
s: {}, s: {},
@ -130,24 +131,31 @@ class ContractSource {
var location = this.sourceMapToLocations(node.src); var location = this.sourceMapToLocations(node.src);
var trueBranchLocation = this.sourceMapToLocations(node.trueBody.src); var trueBranchLocation = this.sourceMapToLocations(node.trueBody.src);
var falseBranchLocation = this.sourceMapToLocations(node.falseBody.src);
var falseBranchLocation;
if(node.falseBody) {
falseBranchLocation = this.sourceMapToLocations(node.falseBody.src);
} else {
falseBranchLocation = trueBranchLocation;
}
coverage.branchMap[node.id] = { coverage.branchMap[node.id] = {
type: 'if', type: 'if',
locations: [trueBranchLocation, falseBranchLocation], locations: [trueBranchLocation, falseBranchLocation],
line: location.start.line, line: location.start.line
} };
children = [node.condition] children = [node.condition]
.concat(node.trueBody.statements) .concat(node.trueBody.statements);
.concat(node.falseBody.statements);
if(node.falseBody) children = children.concat(node.falseBody.statements);
markLocations = [location, trueBranchLocation, falseBranchLocation]; markLocations = [location, trueBranchLocation, falseBranchLocation];
if(node.trueBody.statements[0]) if(node.trueBody.statements[0])
node.trueBody.statements[0]._parent = {type: 'b', id: node.id, idx: 0} node.trueBody.statements[0]._parent = {type: 'b', id: node.id, idx: 0}
if(node.falseBody.statements[0]) if(node.falseBody && node.falseBody.statements[0])
node.falseBody.statements[0]._parent = {type: 'b', id: node.id, idx: 1} node.falseBody.statements[0]._parent = {type: 'b', id: node.id, idx: 1}
sourceMapToNodeType[node.src] = [{ sourceMapToNodeType[node.src] = [{
@ -225,7 +233,7 @@ class ContractSource {
body: coverage.fnMap[node.id], body: coverage.fnMap[node.id],
}]; }];
children = node.body.statements; if(node.body) children = node.body.statements;
markLocations = [location]; markLocations = [location];
break; break;
@ -244,11 +252,26 @@ class ContractSource {
} while(nodesRequiringVisiting.length > 0); } while(nodesRequiringVisiting.length > 0);
var contractMatches = true;
for(var contractName in this.contractBytecode) { for(var contractName in this.contractBytecode) {
var bytecode = this.contractBytecode[contractName]; var bytecode = this.contractBytecode[contractName];
// Try to match the contract to the bytecode. If it doesn't,
// then we bail.
trace.structLogs.forEach((step) => {
if(!contractMatches) return;
if(!bytecode[step.pc]) {
// This contract won't match so we bail
contractMatches = false;
return;
}
})
if(!contractMatches) break;
trace.structLogs.forEach((step) => { trace.structLogs.forEach((step) => {
var step = bytecode[step.pc]; var step = bytecode[step.pc];
step.seen = true;
if(!step.sourceMap || step.sourceMap == '') if(!step.sourceMap || step.sourceMap == '')
return; return;

View File

@ -1,5 +1,15 @@
/*global web3*/
const fs = require('fs');
const process = require('process');
const ContractSources = require('./contract_sources'); const ContractSources = require('./contract_sources');
// Set up the web3 extension
web3.extend({
property: 'debug',
methods: [{name: 'traceTransaction', call: 'debug_traceTransaction', params: 2}]
});
class CodeCoverage { class CodeCoverage {
constructor(embark, _options) { constructor(embark, _options) {
this.events = embark.events; this.events = embark.events;
@ -8,9 +18,14 @@ class CodeCoverage {
embark.events.on('contracts:compile:solc', this.compileSolc.bind(this)); embark.events.on('contracts:compile:solc', this.compileSolc.bind(this));
embark.events.on('contracts:compiled:solc', this.compiledSolc.bind(this)); embark.events.on('contracts:compiled:solc', this.compiledSolc.bind(this));
embark.events.on('contracts:run:solc', this.runSolc.bind(this)); embark.events.on('contracts:run:solc', this.runSolc.bind(this));
embark.registerActionForEvent('contracts:deploy:afterAll', this.deployed.bind(this));
embark.events.on('block:header', this.runSolc.bind(this)); embark.events.on('block:header', this.runSolc.bind(this));
this.seenTransactions = {};
var self = this;
process.on('exit', (code) => {
fs.writeFileSync('/tmp/coverage.json', JSON.stringify(this.coverageReport));
});
} }
compileSolc(input) { compileSolc(input) {
@ -27,18 +42,18 @@ class CodeCoverage {
this.contractSources.parseSolcOutput(output); this.contractSources.parseSolcOutput(output);
} }
runSolc(receipt) { async runSolc(receipt) {
console.log('runSolc'); var block = await web3.eth.getBlock(receipt.number);
console.dir(receipt); for(var i in block.transactions) {
//this.contractSources.generateCodeCoverage(trace); var txHash = block.transactions[i];
}
deployed(cb) { if(this.seenTransactions[txHash]) return;
this.events.request('contracts:list', (error, contracts) => {
console.dir(error); this.seenTransactions[txHash] = true;
console.dir(contracts); var trace = await web3.debug.traceTransaction(txHash, {});
cb(); var cov = this.contractSources.generateCodeCoverage(trace);
}); this.coverageReport = cov;
}
} }
} }

View File

@ -1,4 +1,5 @@
const {assert, expect} = require('chai'); /*global describe, it*/
const {assert} = require('chai');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const sinon = require('sinon'); const sinon = require('sinon');
@ -39,7 +40,7 @@ describe('ContractSources', () => {
it('should throw an error when the file does not exist', (done) => { it('should throw an error when the file does not exist', (done) => {
assert.throws(() => { assert.throws(() => {
new ContractSources(['fixtures/404.sol']) new ContractSources(['fixtures/404.sol']);
}, 'Error loading fixtures/404.sol: ENOENT'); }, 'Error loading fixtures/404.sol: ENOENT');
done(); done();