diff --git a/coverageMap.js b/coverageMap.js index 214ab15..d17a0f3 100644 --- a/coverageMap.js +++ b/coverageMap.js @@ -70,23 +70,22 @@ module.exports = class CoverageMap { const event = JSON.parse(events[idx]); if (event.topics.indexOf(lineTopic) >= 0) { const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', '')); - const canonicalContractPath = path.resolve(pathPrefix + path.basename(data[0])); + const canonicalContractPath = data[0]; this.coverage[canonicalContractPath].l[data[1].toNumber()] += 1; } else if (event.topics.indexOf(functionTopic) >= 0) { const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', '')); - const canonicalContractPath = path.resolve(pathPrefix + path.basename(data[0])); + const canonicalContractPath = data[0]; this.coverage[canonicalContractPath].f[data[1].toNumber()] += 1; } else if (event.topics.indexOf(branchTopic) >= 0) { const data = SolidityCoder.decodeParams(['string', 'uint256', 'uint256'], event.data.replace('0x', '')); - const canonicalContractPath = path.resolve(pathPrefix + path.basename(data[0])); + const canonicalContractPath = data[0]; this.coverage[canonicalContractPath].b[data[1].toNumber()][data[2].toNumber()] += 1; } else if (event.topics.indexOf(statementTopic) >= 0) { const data = SolidityCoder.decodeParams(['string', 'uint256'], event.data.replace('0x', '')); - const canonicalContractPath = path.resolve(pathPrefix + path.basename(data[0])); + const canonicalContractPath = data[0]; this.coverage[canonicalContractPath].s[data[1].toNumber()] += 1; } } return Object.assign({}, this.coverage); } }; - diff --git a/package.json b/package.json index 9688c6d..7d84721 100644 --- a/package.json +++ b/package.json @@ -7,24 +7,25 @@ "test": "test" }, "scripts": { - "test": "mocha --timeout 15000" + "test": "mocha --timeout 30000" }, "author": "", "license": "ISC", "dependencies": { - "ethereumjs-testrpc": "^3.0.3", + "ethereumjs-testrpc": "https://github.com/ethereumjs/testrpc.git#5ba3c45b2ca306ab589f4a4c649d9afc39042680", "istanbul": "^0.4.5", + "mkdirp": "^0.5.1", "shelljs": "^0.7.4", "sol-explore": "^1.6.2", "solidity-parser": "^0.2.0" }, "devDependencies": { "crypto-js": "^3.1.9-1", - "ethereumjs-account": "^2.0.4", - "ethereumjs-tx": "^1.2.2", - "ethereumjs-util": "^5.0.1", - "merkle-patricia-tree": "^2.1.2", + "ethereumjs-account": "~2.0.4", + "ethereumjs-tx": "1.1.2", + "ethereumjs-util": "~4.5.0", + "merkle-patricia-tree": "~2.1.2", "mocha": "^3.1.0", - "solc": "^0.4.6" + "solc": "0.4.6" } } diff --git a/runCoveredTests.js b/runCoveredTests.js index 1fbf9aa..2f61078 100644 --- a/runCoveredTests.js +++ b/runCoveredTests.js @@ -8,6 +8,7 @@ var path = require('path'); var getInstrumentedVersion = require('./instrumentSolidity.js'); var CoverageMap = require('./coverageMap.js'); var coverage = new CoverageMap(); +var mkdirp = require('mkdirp'); var childprocess = require('child_process'); @@ -17,7 +18,7 @@ if (!shell.test('-e','./node_modules/ethereumjs-vm/lib/opFns.js.orig')){ shell.exec('patch -b ./node_modules/ethereumjs-vm/lib/opFns.js ./hookIntoEvents.patch') } //Run the modified testrpc with large block limit -var testrpcProcess = childprocess.exec('./node_modules/ethereumjs-testrpc/bin/testrpc --gasLimit 0xfffffffffff') +var testrpcProcess = childprocess.exec('./node_modules/ethereumjs-testrpc/bin/testrpc --gasLimit 0xfffffffffffff --gasPrice 0x1') if (shell.test('-d','../originalContracts')){ console.log("There is already an 'originalContracts' directory in your truffle directory.\nThis is probably due to a previous solcover failure.\nPlease make sure the ./contracts/ directory contains your contracts (perhaps by copying them from originalContracts), and then delete the originalContracts directory.") @@ -27,21 +28,22 @@ if (shell.test('-d','../originalContracts')){ shell.mv('./../contracts/', './../originalContracts/'); shell.mkdir('./../contracts/'); //For each contract in originalContracts, get the instrumented version -shell.ls('./../originalContracts/*.sol').forEach(function(file) { +shell.ls('./../originalContracts/**/*.sol').forEach(function(file) { if (file !== 'originalContracts/Migrations.sol') { - console.log("instrumenting ", file); - var contract = fs.readFileSync("./" + file).toString(); - var fileName = path.basename(file); - var instrumentedContractInfo = getInstrumentedVersion(contract, fileName, true); - fs.writeFileSync('./../contracts/' + path.basename(file), instrumentedContractInfo.contract); - var canonicalContractPath = path.resolve('./../originalContracts/' + path.basename(file)); + var canonicalContractPath = path.resolve(file); + + console.log("instrumenting ", canonicalContractPath); + var contract = fs.readFileSync(canonicalContractPath).toString(); + var instrumentedContractInfo = getInstrumentedVersion(contract, canonicalContractPath, true); + mkdirp.sync(path.dirname(canonicalContractPath.replace('originalContracts', 'contracts'))); + fs.writeFileSync(canonicalContractPath.replace('originalContracts','contracts'), instrumentedContractInfo.contract); coverage.addContract(instrumentedContractInfo, canonicalContractPath); } }); shell.cp("./../originalContracts/Migrations.sol", "./../contracts/Migrations.sol"); shell.rm('./allFiredEvents'); //Delete previous results -shell.exec('truffle test --network coverage'); +shell.exec('truffle test --network test'); events = fs.readFileSync('./allFiredEvents').toString().split('\n') events.pop(); diff --git a/test/if.js b/test/if.js index 2baf7fd..7d61c86 100644 --- a/test/if.js +++ b/test/if.js @@ -8,13 +8,12 @@ const assert = require('assert'); describe('if, else, and else if statements', function(){ - const fileName = 'test.sol'; const filePath = path.resolve('./test.sol'); const pathPrefix = './'; it('should cover an if statement with a bracketed consequent', (done) => { const contract = util.getCode('if/if-with-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -32,7 +31,7 @@ describe('if, else, and else if statements', function(){ // Runs: a(1) => if (x == 1) x = 2; it('should cover an unbracketed if consequent (single line)',function(done){ const contract = util.getCode('if/if-no-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -49,7 +48,7 @@ describe('if, else, and else if statements', function(){ it('should cover an if statement with multiline bracketed consequent', (done) => { const contract = util.getCode('if/if-with-brackets-multiline.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -67,7 +66,7 @@ describe('if, else, and else if statements', function(){ // Runs: a(1) => if (x == 1)\n x = 3; it('should cover an unbracketed if consequent (multi-line)', function(done){ const contract = util.getCode('if/if-no-brackets-multiline.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); // Same results as previous test @@ -83,7 +82,7 @@ describe('if, else, and else if statements', function(){ it('should cover a simple if statement with a failing condition', (done) => { const contract = util.getCode('if/if-with-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -101,7 +100,7 @@ describe('if, else, and else if statements', function(){ // Runs: a(2) => if (x == 1){\n throw;\n }else{\n x = 5; \n} it('should cover an if statement with a bracketed alternate', (done) => { const contract = util.getCode('if/else-with-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -117,7 +116,7 @@ describe('if, else, and else if statements', function(){ it('should cover an if statement with an unbracketed alternate',function(done){ const contract = util.getCode('if/else-without-brackets.sol'); - const info = getInstrumentedVersion(contract, "test.sol", true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -133,7 +132,7 @@ describe('if, else, and else if statements', function(){ it('should cover nested if statements with missing else statements',function(done){ const contract = util.getCode('if/nested-if-missing-else.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); vm.execute(info.contract, 'a', [2, 3, 3]).then(events => { @@ -145,4 +144,5 @@ describe('if, else, and else if statements', function(){ done(); }).catch(done) }) + }) diff --git a/test/loops.js b/test/loops.js index 524a51d..ab7755a 100644 --- a/test/loops.js +++ b/test/loops.js @@ -8,13 +8,12 @@ const assert = require('assert'); describe('for and while statements', function(){ - const fileName = 'test.sol'; const filePath = path.resolve('./test.sol'); const pathPrefix = './'; it('should cover a for statement with a bracketed body (multiline)', (done) => { const contract = util.getCode('loops/for-with-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -31,7 +30,7 @@ describe('for and while statements', function(){ it('should cover a for statement with an unbracketed body', (done) => { const contract = util.getCode('loops/for-no-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -48,7 +47,7 @@ describe('for and while statements', function(){ it('should cover a while statement with an bracketed body (multiline)', (done) => { const contract = util.getCode('loops/while-with-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); @@ -65,7 +64,7 @@ describe('for and while statements', function(){ it('should cover a while statement with an unbracketed body (multiline)', (done) => { const contract = util.getCode('loops/while-no-brackets.sol'); - const info = getInstrumentedVersion(contract, fileName, true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath); diff --git a/test/statements.js b/test/statements.js index 7ca5b5b..e87eb94 100644 --- a/test/statements.js +++ b/test/statements.js @@ -12,41 +12,40 @@ const assert = require('assert'); * and passing the error to mocha. */ describe('generic statements', function(){ - const fileName = 'test.sol'; const filePath = path.resolve('./test.sol'); const pathPrefix = './'; it('should compile after instrumenting a single statement (first line of function)', function(){ var contract = util.getCode('statements/single.sol'); - var info = getInstrumentedVersion(contract, "test.sol", true); + var info = getInstrumentedVersion(contract, filePath, true); var output = solc.compile(info.contract, 1); util.report(output.errors); }) it('should compile after instrumenting multiple statements', function(){ var contract = util.getCode('statements/multiple.sol'); - var info = getInstrumentedVersion(contract, "test.sol", true); + var info = getInstrumentedVersion(contract, filePath, true); var output = solc.compile(info.contract, 1); util.report(output.errors); }) it('should compile after instrumenting a statement that is a function argument (single line)', function(){ var contract = util.getCode('statements/fn-argument.sol'); - var info = getInstrumentedVersion(contract, "test.sol", true); + var info = getInstrumentedVersion(contract, filePath, true); var output = solc.compile(info.contract, 1); util.report(output.errors); }) it('should compile after instrumenting a statement that is a function argument (multi-line)', function(){ var contract = util.getCode('statements/fn-argument-multiline.sol'); - var info = getInstrumentedVersion(contract, "test.sol", true); - var output = solc.compile(info.contract, 1); + var info = getInstrumentedVersion(contract, filePath, true); + var output = solc.compile(info.contract, 1); util.report(output.errors); }) it('should cover a statement following a close brace', (done) => { const contract = util.getCode('statements/post-close-brace.sol'); - const info = getInstrumentedVersion(contract, "test.sol", true); + const info = getInstrumentedVersion(contract, filePath, true); const coverage = new CoverageMap(); coverage.addContract(info, filePath);