Improvements

This commit is contained in:
Andre Medeiros 2018-08-21 15:25:18 -04:00
parent 5dcd679e12
commit 4e9d2823e5
4 changed files with 105 additions and 1588 deletions

View File

@ -101,7 +101,7 @@ class ContractSource {
generateCodeCoverage(trace) { generateCodeCoverage(trace) {
if(!this.ast || !this.contractBytecode) throw new Error('Error generating coverage: solc output was not assigned'); if(!this.ast || !this.contractBytecode) throw new Error('Error generating coverage: solc output was not assigned');
var coverage = { let coverage = {
code: this.body.trim().split("\n"), code: this.body.trim().split("\n"),
l: {}, l: {},
path: this.file, path: this.file,
@ -117,11 +117,12 @@ class ContractSource {
var sourceMapToNodeType = {}; var sourceMapToNodeType = {};
do { do {
var node = nodesRequiringVisiting.pop(); let node = nodesRequiringVisiting.pop();
if(!node) continue; if(!node) continue;
var children = []; let children = [];
var markLocations = []; let markLocations = [];
let location;
switch(node.nodeType) { switch(node.nodeType) {
case 'Assignment': case 'Assignment':
@ -132,10 +133,11 @@ class ContractSource {
break; break;
case 'IfStatement': case 'IfStatement':
coverage.b[node.id] = [0,0]; location = this.sourceMapToLocations(node.src);
let trueBranchLocation = this.sourceMapToLocations(node.trueBody.src);
var location = this.sourceMapToLocations(node.src); let declarationSourceMap = new SourceMap(node.src).subtract(new SourceMap(node.trueBody.src));
var trueBranchLocation = this.sourceMapToLocations(node.trueBody.src); let declarationLocation = this.sourceMapToLocations(declarationSourceMap.toString());
var falseBranchLocation; var falseBranchLocation;
if(node.falseBody) { if(node.falseBody) {
@ -144,6 +146,7 @@ class ContractSource {
falseBranchLocation = trueBranchLocation; falseBranchLocation = trueBranchLocation;
} }
coverage.b[node.id] = [0,0];
coverage.branchMap[node.id] = { coverage.branchMap[node.id] = {
type: 'if', type: 'if',
locations: [trueBranchLocation, falseBranchLocation], locations: [trueBranchLocation, falseBranchLocation],
@ -155,7 +158,7 @@ class ContractSource {
if(node.falseBody) children = children.concat(node.falseBody.statements); if(node.falseBody) children = children.concat(node.falseBody.statements);
markLocations = [location, trueBranchLocation, falseBranchLocation]; markLocations = [declarationLocation];
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};
@ -169,18 +172,9 @@ class ContractSource {
break; break;
case 'BinaryOperation': case 'BinaryOperation':
children = [node.leftExpression, node.rightExpression];
break;
case 'Return':
// Return is a bit of a special case, because the statement src is the
// return "body". We don't `break` here on purpose so it can share the
// same logic below.
node.src = node.expression.src;
// falls through
case 'ExpressionStatement': case 'ExpressionStatement':
case 'Identifier': case 'Identifier':
case 'Return':
case 'UnaryOperation': case 'UnaryOperation':
coverage.s[node.id] = 0; coverage.s[node.id] = 0;
@ -196,7 +190,7 @@ class ContractSource {
}); });
children = node.expression ? [node.expression] : []; //children = node.expression ? [node.expression] : [];
markLocations = [location]; markLocations = [location];
break; break;
@ -250,8 +244,6 @@ class ContractSource {
if(!sourceMapToNodeType[node.initializationExpression.src]) sourceMapToNodeType[node.initializationExpression.src] = []; if(!sourceMapToNodeType[node.initializationExpression.src]) sourceMapToNodeType[node.initializationExpression.src] = [];
sourceMapToNodeType[node.initializationExpression.src].push({type: 's', id: node.id, body: {loc: location}}); sourceMapToNodeType[node.initializationExpression.src].push({type: 's', id: node.id, body: {loc: location}});
console.dir(node);
children = node.body.statements; children = node.body.statements;
markLocations = [initializationLocation]; markLocations = [initializationLocation];
break; break;
@ -293,22 +285,21 @@ class ContractSource {
if(!contractMatches) break; if(!contractMatches) break;
console.log(sourceMapToNodeType); console.log(sourceMapToNodeType);
console.log('---------------------------------------------------');
trace.structLogs.forEach((step) => { trace.structLogs.forEach((step) => {
step = bytecode[step.pc]; step = bytecode[step.pc];
if(!step.sourceMap || step.sourceMap == '') return; if(!step.sourceMap || step.sourceMap == '' || step.sourceMap == SourceMap.empty()) return;
console.dir(step.sourceMap);
let sourceMapString = step.sourceMap.toString(this.id); let sourceMapString = step.sourceMap.toString(this.id);
var nodes = sourceMapToNodeType[sourceMapString]; var nodes = sourceMapToNodeType[sourceMapString];
if(step.sourceMap.offset == 189) console.log(nodes);
if(!nodes) return; if(!nodes) return;
nodes.forEach((node) => { nodes.forEach((node) => {
// Skip duplicate function reports by only reporting when there is a jump. // Skip duplicate function reports by only reporting when there is a jump.
if(node.type == 'f' && step.jump) return; if(node.type == 'f' && step.jump) return;
if(node.body && node.body.loc) { if(node.type != 'b' && node.body && node.body.loc) {
for(var line = node.body.loc.start.line; line <= node.body.loc.end.line; line++) { for(var line = node.body.loc.start.line; line <= node.body.loc.end.line; line++) {
coverage.l[line]++; coverage.l[line]++;
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
pragma solidity ^0.4.23;
contract Branches {
uint public lastComparison;
uint public storedData;
constructor(uint initialValue) public {
storedData = initialValue;
}
function bigger(uint x) public returns (uint biggest) {
lastComparison = x;
if(x > storedData) {
storedData = x;
return x;
} else {
return storedData;
}
}
function smaller(uint x) public returns (uint smallest) {
lastComparison = x;
if(x < storedData) {
return x;
} else {
return storedData;
}
}
function get() public view returns (uint retVal) {
return storedData;
}
}

View File

@ -0,0 +1,31 @@
/*global contract, config, it, assert*/
const Branches = require('Embark/contracts/Branches');
config({
contracts: {
"Branches": {
args: [5]
}
}
});
contract("Branches", function() {
it("should return the bigger value and set it", function(done) {
Branches.methods.bigger(10).send().then(() => {
Branches.methods.get().call().then((result) => {
assert.strictEqual(parseInt(result, 10), 10);
done();
});
});
});
it("should return the set number if it's bigger", function(done) {
Branches.methods.bigger(1).send().then(() => {
done();
});
});
it("should return the smaller number", function(done) {
Branches.methods.smaller(10).send().then(() => { done() });
});
});