This commit is contained in:
Andre Medeiros 2018-08-28 13:51:55 -04:00
parent 543f883b7d
commit 824353fb32
3 changed files with 19 additions and 17 deletions

View File

@ -1,5 +1,3 @@
const util = require('util');
const SourceMap = require('./source_map'); const SourceMap = require('./source_map');
class ContractSource { class ContractSource {
@ -99,7 +97,7 @@ class ContractSource {
} }
} }
/*eslint complexity: ["error", 27]*/ /*eslint complexity: ["error", 34]*/
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');
@ -135,7 +133,7 @@ class ContractSource {
// We don't need to do anything with these. Just carry on. // We don't need to do anything with these. Just carry on.
break; break;
case 'IfStatement': case 'IfStatement': {
location = this.sourceMapToLocations(node.src); location = this.sourceMapToLocations(node.src);
let trueBranchLocation = this.sourceMapToLocations(node.trueBody.src); let trueBranchLocation = this.sourceMapToLocations(node.trueBody.src);
@ -173,10 +171,12 @@ class ContractSource {
sourceMapToNodeType[node.src] = [{type: 'b', id: node.id, body: {loc: location}}]; sourceMapToNodeType[node.src] = [{type: 'b', id: node.id, body: {loc: location}}];
break; break;
}
case 'EmitStatement': case 'EmitStatement': {
children = [node.eventCall]; children = [node.eventCall];
break; break;
}
case 'BinaryOperation': case 'BinaryOperation':
case 'ExpressionStatement': case 'ExpressionStatement':
@ -235,7 +235,7 @@ class ContractSource {
markLocations = [location]; markLocations = [location];
break; break;
case 'ForStatement': case 'ForStatement': {
// For statements will be a bit of a special case. We want to count the body // For statements will be a bit of a special case. We want to count the body
// iterations but we only want to count the for loop being hit once. Because // iterations but we only want to count the for loop being hit once. Because
// of this, we cover the initialization on the node. // of this, we cover the initialization on the node.
@ -255,8 +255,9 @@ class ContractSource {
children = node.body.statements; children = node.body.statements;
markLocations = [initializationLocation]; markLocations = [initializationLocation];
break; break;
}
case 'VariableDeclarationStatement': case 'VariableDeclarationStatement': {
location = this.sourceMapToLocations(node.src); location = this.sourceMapToLocations(node.src);
coverage.s[node.id] = 0; coverage.s[node.id] = 0;
@ -267,6 +268,7 @@ class ContractSource {
sourceMapToNodeType[node.src].push({type: 's', id: node.id, body: {loc: location}, foo: 'bar'}); sourceMapToNodeType[node.src].push({type: 's', id: node.id, body: {loc: location}, foo: 'bar'});
break; break;
}
default: default:
console.log(`Don't know how to handle node type ${node.nodeType}`); console.log(`Don't know how to handle node type ${node.nodeType}`);

View File

@ -33,8 +33,8 @@ class SourceMap {
let [offset, length, id, jump] = sourceMapString.split(":"); let [offset, length, id, jump] = sourceMapString.split(":");
(offset == '') ? offset = this.offset : offset = parseInt(offset, 10); offset = (offset == '') ? this.offset : parseInt(offset, 10);
(id == '' || id == undefined) ? id = this.id : id = parseInt(id, 10); id = (id == '' || id == undefined) ? this.id : parseInt(id, 10);
length = parseInt(length, 10); length = parseInt(length, 10);
return new SourceMap(offset, length, id, jump); return new SourceMap(offset, length, id, jump);
@ -48,7 +48,7 @@ class SourceMap {
let parts = [this.offset, this.length]; let parts = [this.offset, this.length];
if(this.id !== undefined && this.id != '') { if(this.id !== undefined && this.id != '') {
parts.push(this.id) parts.push(this.id);
} else if(defaultId !== undefined) { } else if(defaultId !== undefined) {
parts.push(defaultId); parts.push(defaultId);
} }

View File

@ -41,7 +41,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'); }, "ENOENT: no such file or directory, open 'fixtures/404.sol'");
done(); done();
}); });
@ -162,10 +162,10 @@ contract x {
var bytecode = contractSource.contractBytecode['x']; var bytecode = contractSource.contractBytecode['x'];
assert.deepEqual({instruction: 'PUSH1', sourceMap: {offset: 26, length: 487, id: 0}, seen: false}, bytecode[0]); assert.deepEqual({instruction: 'PUSH1', sourceMap: {offset: 26, length: 487, id: 0, jump: '-'}, jump: '-', seen: false}, bytecode[0]);
assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false}, bytecode[2]); assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false, jump: undefined}, bytecode[2]);
assert.deepEqual({instruction: 'MSTORE', sourceMap: SourceMap.empty(), seen: false}, bytecode[4]); assert.deepEqual({instruction: 'MSTORE', sourceMap: SourceMap.empty(), seen: false, jump: undefined}, bytecode[4]);
assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false}, bytecode[5]); assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false, jump: undefined}, bytecode[5]);
done(); done();
}); });
@ -213,8 +213,8 @@ contract x {
// In the fixture, the branch has an ID of 61, and the function has the // In the fixture, the branch has an ID of 61, and the function has the
// ID of 63 // ID of 63
assert.deepEqual([1,1], coverage.b['61']); assert.deepEqual([1,0], coverage.b['61']);
assert.equal(4, coverage.f['63']); assert.equal(6, coverage.f['63']);
done(); done();
}); });