From 35aa892b51b7c19756daa282587fac7aaaac7489 Mon Sep 17 00:00:00 2001 From: cgewecke Date: Sun, 8 Sep 2019 20:42:45 -0700 Subject: [PATCH] Create separate contract & artifact temp folders at root (#386) --- dist/truffle.plugin.js | 24 ++++----------------- lib/app.js | 48 ++++++++++++++++++++++++------------------ test/units/app.js | 44 ++++++++++++++++++++------------------ 3 files changed, 56 insertions(+), 60 deletions(-) diff --git a/dist/truffle.plugin.js b/dist/truffle.plugin.js index bb3021c..3be8b3c 100644 --- a/dist/truffle.plugin.js +++ b/dist/truffle.plugin.js @@ -50,7 +50,7 @@ async function plugin(truffleConfig){ coverageConfig = req.silent(coverageConfigPath) || {}; coverageConfig.cwd = truffleConfig.working_directory; - coverageConfig.contractsDir = truffleConfig.contracts_directory; + coverageConfig.originalContractsDir = truffleConfig.contracts_directory; app = new App(coverageConfig); @@ -66,8 +66,8 @@ async function plugin(truffleConfig){ app.instrument(); // Ask truffle to use temp folders - truffleConfig.contracts_directory = paths.contracts(app); - truffleConfig.build_directory = paths.build(app); + truffleConfig.contracts_directory = app.contractsDir; + truffleConfig.build_directory = app.artifactsDir; truffleConfig.contracts_build_directory = paths.artifacts(truffleConfig, app); // Additional config @@ -142,27 +142,11 @@ function loadTruffleLibrary(){ * @type {Object} */ const paths = { - // "contracts_directory": - contracts: (app) => { - return path.join( - app.coverageDir, - app.contractsDirName - ) - }, - - // "build_directory": - build: (app) => { - return path.join( - app.coverageDir, - app.artifactsDirName - ) - }, // "contracts_build_directory": artifacts: (truffle, app) => { return path.join( - app.coverageDir, - app.artifactsDirName, + app.artifactsDir, path.basename(truffle.contracts_build_directory) ) } diff --git a/lib/app.js b/lib/app.js index d4e2624..bcfbd02 100644 --- a/lib/app.js +++ b/lib/app.js @@ -23,11 +23,12 @@ class App { this.testsErrored = false; this.cwd = config.cwd; - this.tempFolderName = '.coverageEnv'; - this.contractsDir = config.contractsDir - this.coverageDir = path.join(this.cwd, this.tempFolderName); - this.contractsDirName = 'contracts'; - this.artifactsDirName = 'artifacts'; + this.contractsDirName = '.coverage_contracts'; + this.artifactsDirName = '.coverage_artifacts'; + this.contractsDir = path.join(this.cwd, this.contractsDirName); + this.artifactsDir = path.join(this.cwd, this.artifactsDirName); + + this.originalContractsDir = config.originalContractsDir this.client = config.provider; this.providerOptions = config.providerOptions || {}; @@ -55,7 +56,7 @@ class App { this.registerSkippedItems(); this.generateEnvelope(); - const target = `${this.coverageDir}/**/*.sol`; + const target = `${this.contractsDir}/**/*.sol`; shell.ls(target).forEach(file => { currentFile = file; @@ -66,10 +67,11 @@ class App { // Remember the real path const contractPath = this.platformNeutralPath(file); const canonicalPath = path.join( - this.cwd, - contractPath.split(`/${this.tempFolderName}`)[1] + this.originalContractsDir, + contractPath.split(`/${this.contractsDirName}`)[1] ); + // Instrument contract, save, add to coverage map const contract = this.loadContract(contractPath); const instrumented = this.instrumenter.instrument(contract, canonicalPath); @@ -115,7 +117,7 @@ class App { return new Promise((resolve, reject) => { try { - this.coverage.generate(this.instrumenter.instrumentationData, this.contractsDir); + this.coverage.generate(this.instrumenter.instrumentationData, this.originalContractsDir); const relativeMapping = this.makeKeysRelative(this.coverage.data, this.cwd); this.saveCoverage(relativeMapping); @@ -147,7 +149,8 @@ class App { const self = this; this.log('Cleaning up...'); shell.config.silent = true; - shell.rm('-Rf', this.coverageDir); + shell.rm('-Rf', this.contractsDir); + shell.rm('-Rf', this.artifactsDir); if (this.provider && this.provider.close){ this.log('Shutting down ganache-core') @@ -168,26 +171,31 @@ class App { } saveCoverage(data){ - fs.writeFileSync('./coverage.json', JSON.stringify(data)); + const covPath = path.join(this.cwd, "coverage.json"); + fs.writeFileSync(covPath, JSON.stringify(data)); } // ====== // Launch // ====== - sanityCheckContext(contractsDir){ - if (!shell.test('-e', this.contractsDir)){ + sanityCheckContext(){ + if (!shell.test('-e', this.originalContractsDir)){ this.cleanUp("Couldn't find a 'contracts' folder to instrument."); } - if (shell.test('-e', path.join(this.cwd, this.coverageDir))){ - shell.rm('-Rf', this.coverageDir); + if (shell.test('-e', path.join(this.cwd, this.contractsDir))){ + shell.rm('-Rf', this.contractsDir); + } + + if (shell.test('-e', path.join(this.cwd, this.artifactsDir))){ + shell.rm('-Rf', this.artifactsDir); } } generateEnvelope(){ - shell.mkdir(this.coverageDir); - shell.mkdir(path.join(this.coverageDir, this.artifactsDirName)) - shell.cp('-Rf', this.contractsDir, this.coverageDir) + shell.mkdir(this.contractsDir); + shell.mkdir(this.artifactsDir); + shell.cp('-Rf', `${this.originalContractsDir}/*`, this.contractsDir); } // ===== @@ -226,7 +234,7 @@ class App { */ inSkippedFolder(file){ let shouldSkip; - const root = `${this.coverageDir}/${this.contractsDirName}`; + const root = `${this.contractsDir}`; this.skippedFolders.forEach(folderToSkip => { folderToSkip = `${root}/${folderToSkip}`; if (file.indexOf(folderToSkip) === 0) @@ -239,7 +247,7 @@ class App { * Parses the skipFiles option (which also accepts folders) */ registerSkippedItems(){ - const root = `${this.coverageDir}/${this.contractsDirName}`; + const root = `${this.contractsDir}`; this.skippedFolders = this.skipFiles.filter(item => path.extname(item) !== '.sol') this.skipFiles = this.skipFiles.map(contract => `${root}/${contract}`); this.skipFiles.push(`${root}/Migrations.sol`); diff --git a/test/units/app.js b/test/units/app.js index 1583028..fc438e0 100644 --- a/test/units/app.js +++ b/test/units/app.js @@ -3,6 +3,7 @@ const fs = require('fs'); const shell = require('shelljs'); const mock = require('../util/integration.truffle'); const plugin = require('../../dist/truffle.plugin'); +const path = require('path') const util = require('util') const opts = { compact: false, depth: 5, breakLength: 80 }; @@ -16,18 +17,21 @@ function assertCleanInitialState(){ assert(pathExists('./coverage.json') === false, 'should start without: coverage.json'); } -function assertCoverageGenerated(){ +function assertCoverageGenerate(truffleConfig){ + const jsonPath = path.join(truffleConfig.working_directory, "coverage.json"); assert(pathExists('./coverage') === true, 'should gen coverage folder'); - assert(pathExists('./coverage.json') === true, 'should gen coverage.json'); + assert(pathExists(jsonPath) === true, 'should gen coverage.json'); } -function assertCoverageNotGenerated(){ +function assertCoverageNotGenerated(truffleConfig){ + const jsonPath = path.join(truffleConfig.working_directory, "coverage.json"); assert(pathExists('./coverage') !== true, 'should NOT gen coverage folder'); - assert(pathExists('./coverage.json') !== true, 'should NOT gen coverage.json'); + assert(pathExists(jsonPath) !== true, 'should NOT gen coverage.json'); } -function getOutput(){ - return JSON.parse(fs.readFileSync('./coverage.json', 'utf8')); +function getOutput(truffleConfig){ + const jsonPath = path.join(truffleConfig.working_directory, "coverage.json"); + return JSON.parse(fs.readFileSync(jsonPath, 'utf8')); } // ======== @@ -54,9 +58,9 @@ describe('app', function() { mock.install('Simple', 'simple.js', solcoverConfig); await plugin(truffleConfig); - assertCoverageGenerated(); + assertCoverageGenerate(truffleConfig); - const output = getOutput(); + const output = getOutput(truffleConfig); const path = Object.keys(output)[0]; assert(output[path].fnMap['1'].name === 'test', 'coverage.json missing "test"'); @@ -92,7 +96,7 @@ describe('app', function() { await plugin(truffleConfig); }); - it.skip('project with node_modules packages and relative path solidity imports', async function() { + it('project with node_modules packages and relative path solidity imports', async function() { assertCleanInitialState(); mock.installFullProject('import-paths'); await plugin(truffleConfig); @@ -105,9 +109,9 @@ describe('app', function() { mock.install('OnlyCall', 'only-call.js', solcoverConfig); await plugin(truffleConfig); - assertCoverageGenerated(); + assertCoverageGenerate(truffleConfig); - const output = getOutput(); + const output = getOutput(truffleConfig); const path = Object.keys(output)[0]; assert(output[path].fnMap['1'].name === 'addTwo', 'cov should map "addTwo"'); }); @@ -118,9 +122,9 @@ describe('app', function() { mock.install('Wallet', 'wallet.js', solcoverConfig); await plugin(truffleConfig); - assertCoverageGenerated(); + assertCoverageGenerate(truffleConfig); - const output = getOutput(); + const output = getOutput(truffleConfig); const path = Object.keys(output)[0]; assert(output[path].fnMap['1'].name === 'transferPayment', 'cov should map "transferPayment"'); }); @@ -133,9 +137,9 @@ describe('app', function() { mock.installDouble(['Proxy', 'Owned'], 'inheritance.js', solcoverConfig); await plugin(truffleConfig); - assertCoverageGenerated(); + assertCoverageGenerate(truffleConfig); - const output = getOutput(); + const output = getOutput(truffleConfig); const firstKey = Object.keys(output)[0]; assert(Object.keys(output).length === 1, 'Wrong # of contracts covered'); assert(firstKey.substr(firstKey.length - 9) === 'Proxy.sol', 'Wrong contract covered'); @@ -147,9 +151,9 @@ describe('app', function() { mock.installDouble(['Proxy', 'Owned'], 'inheritance.js', solcoverConfig); await plugin(truffleConfig); - assertCoverageGenerated(); + assertCoverageGenerate(truffleConfig); - const output = getOutput(); + const output = getOutput(truffleConfig); const ownedPath = Object.keys(output)[0]; const proxyPath = Object.keys(output)[1]; assert(output[ownedPath].fnMap['1'].name === 'constructor', '"constructor" not covered'); @@ -169,9 +173,9 @@ describe('app', function() { assert(err.message.includes('failed under coverage')); } - assertCoverageGenerated(); + assertCoverageGenerate(truffleConfig); - const output = getOutput(); + const output = getOutput(truffleConfig); const path = Object.keys(output)[0]; assert(output[path].fnMap['1'].name === 'test', 'cov missing "test"'); @@ -210,7 +214,7 @@ describe('app', function() { assert(err.message.includes('Compilation failed')); } - assertCoverageNotGenerated(); + assertCoverageNotGenerated(truffleConfig); }); });