Create separate contract & artifact temp folders at root (#386)

pull/387/head
cgewecke 5 years ago committed by GitHub
parent 9ea10859b1
commit 35aa892b51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      dist/truffle.plugin.js
  2. 48
      lib/app.js
  3. 44
      test/units/app.js

@ -50,7 +50,7 @@ async function plugin(truffleConfig){
coverageConfig = req.silent(coverageConfigPath) || {}; coverageConfig = req.silent(coverageConfigPath) || {};
coverageConfig.cwd = truffleConfig.working_directory; coverageConfig.cwd = truffleConfig.working_directory;
coverageConfig.contractsDir = truffleConfig.contracts_directory; coverageConfig.originalContractsDir = truffleConfig.contracts_directory;
app = new App(coverageConfig); app = new App(coverageConfig);
@ -66,8 +66,8 @@ async function plugin(truffleConfig){
app.instrument(); app.instrument();
// Ask truffle to use temp folders // Ask truffle to use temp folders
truffleConfig.contracts_directory = paths.contracts(app); truffleConfig.contracts_directory = app.contractsDir;
truffleConfig.build_directory = paths.build(app); truffleConfig.build_directory = app.artifactsDir;
truffleConfig.contracts_build_directory = paths.artifacts(truffleConfig, app); truffleConfig.contracts_build_directory = paths.artifacts(truffleConfig, app);
// Additional config // Additional config
@ -142,27 +142,11 @@ function loadTruffleLibrary(){
* @type {Object} * @type {Object}
*/ */
const paths = { 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": // "contracts_build_directory":
artifacts: (truffle, app) => { artifacts: (truffle, app) => {
return path.join( return path.join(
app.coverageDir, app.artifactsDir,
app.artifactsDirName,
path.basename(truffle.contracts_build_directory) path.basename(truffle.contracts_build_directory)
) )
} }

@ -23,11 +23,12 @@ class App {
this.testsErrored = false; this.testsErrored = false;
this.cwd = config.cwd; this.cwd = config.cwd;
this.tempFolderName = '.coverageEnv'; this.contractsDirName = '.coverage_contracts';
this.contractsDir = config.contractsDir this.artifactsDirName = '.coverage_artifacts';
this.coverageDir = path.join(this.cwd, this.tempFolderName); this.contractsDir = path.join(this.cwd, this.contractsDirName);
this.contractsDirName = 'contracts'; this.artifactsDir = path.join(this.cwd, this.artifactsDirName);
this.artifactsDirName = 'artifacts';
this.originalContractsDir = config.originalContractsDir
this.client = config.provider; this.client = config.provider;
this.providerOptions = config.providerOptions || {}; this.providerOptions = config.providerOptions || {};
@ -55,7 +56,7 @@ class App {
this.registerSkippedItems(); this.registerSkippedItems();
this.generateEnvelope(); this.generateEnvelope();
const target = `${this.coverageDir}/**/*.sol`; const target = `${this.contractsDir}/**/*.sol`;
shell.ls(target).forEach(file => { shell.ls(target).forEach(file => {
currentFile = file; currentFile = file;
@ -66,10 +67,11 @@ class App {
// Remember the real path // Remember the real path
const contractPath = this.platformNeutralPath(file); const contractPath = this.platformNeutralPath(file);
const canonicalPath = path.join( const canonicalPath = path.join(
this.cwd, this.originalContractsDir,
contractPath.split(`/${this.tempFolderName}`)[1] contractPath.split(`/${this.contractsDirName}`)[1]
); );
// Instrument contract, save, add to coverage map // Instrument contract, save, add to coverage map
const contract = this.loadContract(contractPath); const contract = this.loadContract(contractPath);
const instrumented = this.instrumenter.instrument(contract, canonicalPath); const instrumented = this.instrumenter.instrument(contract, canonicalPath);
@ -115,7 +117,7 @@ class App {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { 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); const relativeMapping = this.makeKeysRelative(this.coverage.data, this.cwd);
this.saveCoverage(relativeMapping); this.saveCoverage(relativeMapping);
@ -147,7 +149,8 @@ class App {
const self = this; const self = this;
this.log('Cleaning up...'); this.log('Cleaning up...');
shell.config.silent = true; 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){ if (this.provider && this.provider.close){
this.log('Shutting down ganache-core') this.log('Shutting down ganache-core')
@ -168,26 +171,31 @@ class App {
} }
saveCoverage(data){ saveCoverage(data){
fs.writeFileSync('./coverage.json', JSON.stringify(data)); const covPath = path.join(this.cwd, "coverage.json");
fs.writeFileSync(covPath, JSON.stringify(data));
} }
// ====== // ======
// Launch // Launch
// ====== // ======
sanityCheckContext(contractsDir){ sanityCheckContext(){
if (!shell.test('-e', this.contractsDir)){ if (!shell.test('-e', this.originalContractsDir)){
this.cleanUp("Couldn't find a 'contracts' folder to instrument."); this.cleanUp("Couldn't find a 'contracts' folder to instrument.");
} }
if (shell.test('-e', path.join(this.cwd, this.coverageDir))){ if (shell.test('-e', path.join(this.cwd, this.contractsDir))){
shell.rm('-Rf', this.coverageDir); shell.rm('-Rf', this.contractsDir);
}
if (shell.test('-e', path.join(this.cwd, this.artifactsDir))){
shell.rm('-Rf', this.artifactsDir);
} }
} }
generateEnvelope(){ generateEnvelope(){
shell.mkdir(this.coverageDir); shell.mkdir(this.contractsDir);
shell.mkdir(path.join(this.coverageDir, this.artifactsDirName)) shell.mkdir(this.artifactsDir);
shell.cp('-Rf', this.contractsDir, this.coverageDir) shell.cp('-Rf', `${this.originalContractsDir}/*`, this.contractsDir);
} }
// ===== // =====
@ -226,7 +234,7 @@ class App {
*/ */
inSkippedFolder(file){ inSkippedFolder(file){
let shouldSkip; let shouldSkip;
const root = `${this.coverageDir}/${this.contractsDirName}`; const root = `${this.contractsDir}`;
this.skippedFolders.forEach(folderToSkip => { this.skippedFolders.forEach(folderToSkip => {
folderToSkip = `${root}/${folderToSkip}`; folderToSkip = `${root}/${folderToSkip}`;
if (file.indexOf(folderToSkip) === 0) if (file.indexOf(folderToSkip) === 0)
@ -239,7 +247,7 @@ class App {
* Parses the skipFiles option (which also accepts folders) * Parses the skipFiles option (which also accepts folders)
*/ */
registerSkippedItems(){ registerSkippedItems(){
const root = `${this.coverageDir}/${this.contractsDirName}`; const root = `${this.contractsDir}`;
this.skippedFolders = this.skipFiles.filter(item => path.extname(item) !== '.sol') this.skippedFolders = this.skipFiles.filter(item => path.extname(item) !== '.sol')
this.skipFiles = this.skipFiles.map(contract => `${root}/${contract}`); this.skipFiles = this.skipFiles.map(contract => `${root}/${contract}`);
this.skipFiles.push(`${root}/Migrations.sol`); this.skipFiles.push(`${root}/Migrations.sol`);

@ -3,6 +3,7 @@ const fs = require('fs');
const shell = require('shelljs'); const shell = require('shelljs');
const mock = require('../util/integration.truffle'); const mock = require('../util/integration.truffle');
const plugin = require('../../dist/truffle.plugin'); const plugin = require('../../dist/truffle.plugin');
const path = require('path')
const util = require('util') const util = require('util')
const opts = { compact: false, depth: 5, breakLength: 80 }; const opts = { compact: false, depth: 5, breakLength: 80 };
@ -16,18 +17,21 @@ function assertCleanInitialState(){
assert(pathExists('./coverage.json') === false, 'should start without: coverage.json'); 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') === 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') !== 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(){ function getOutput(truffleConfig){
return JSON.parse(fs.readFileSync('./coverage.json', 'utf8')); 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); mock.install('Simple', 'simple.js', solcoverConfig);
await plugin(truffleConfig); await plugin(truffleConfig);
assertCoverageGenerated(); assertCoverageGenerate(truffleConfig);
const output = getOutput(); const output = getOutput(truffleConfig);
const path = Object.keys(output)[0]; const path = Object.keys(output)[0];
assert(output[path].fnMap['1'].name === 'test', 'coverage.json missing "test"'); assert(output[path].fnMap['1'].name === 'test', 'coverage.json missing "test"');
@ -92,7 +96,7 @@ describe('app', function() {
await plugin(truffleConfig); 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(); assertCleanInitialState();
mock.installFullProject('import-paths'); mock.installFullProject('import-paths');
await plugin(truffleConfig); await plugin(truffleConfig);
@ -105,9 +109,9 @@ describe('app', function() {
mock.install('OnlyCall', 'only-call.js', solcoverConfig); mock.install('OnlyCall', 'only-call.js', solcoverConfig);
await plugin(truffleConfig); await plugin(truffleConfig);
assertCoverageGenerated(); assertCoverageGenerate(truffleConfig);
const output = getOutput(); const output = getOutput(truffleConfig);
const path = Object.keys(output)[0]; const path = Object.keys(output)[0];
assert(output[path].fnMap['1'].name === 'addTwo', 'cov should map "addTwo"'); assert(output[path].fnMap['1'].name === 'addTwo', 'cov should map "addTwo"');
}); });
@ -118,9 +122,9 @@ describe('app', function() {
mock.install('Wallet', 'wallet.js', solcoverConfig); mock.install('Wallet', 'wallet.js', solcoverConfig);
await plugin(truffleConfig); await plugin(truffleConfig);
assertCoverageGenerated(); assertCoverageGenerate(truffleConfig);
const output = getOutput(); const output = getOutput(truffleConfig);
const path = Object.keys(output)[0]; const path = Object.keys(output)[0];
assert(output[path].fnMap['1'].name === 'transferPayment', 'cov should map "transferPayment"'); 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); mock.installDouble(['Proxy', 'Owned'], 'inheritance.js', solcoverConfig);
await plugin(truffleConfig); await plugin(truffleConfig);
assertCoverageGenerated(); assertCoverageGenerate(truffleConfig);
const output = getOutput(); const output = getOutput(truffleConfig);
const firstKey = Object.keys(output)[0]; const firstKey = Object.keys(output)[0];
assert(Object.keys(output).length === 1, 'Wrong # of contracts covered'); assert(Object.keys(output).length === 1, 'Wrong # of contracts covered');
assert(firstKey.substr(firstKey.length - 9) === 'Proxy.sol', 'Wrong contract 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); mock.installDouble(['Proxy', 'Owned'], 'inheritance.js', solcoverConfig);
await plugin(truffleConfig); await plugin(truffleConfig);
assertCoverageGenerated(); assertCoverageGenerate(truffleConfig);
const output = getOutput(); const output = getOutput(truffleConfig);
const ownedPath = Object.keys(output)[0]; const ownedPath = Object.keys(output)[0];
const proxyPath = Object.keys(output)[1]; const proxyPath = Object.keys(output)[1];
assert(output[ownedPath].fnMap['1'].name === 'constructor', '"constructor" not covered'); assert(output[ownedPath].fnMap['1'].name === 'constructor', '"constructor" not covered');
@ -169,9 +173,9 @@ describe('app', function() {
assert(err.message.includes('failed under coverage')); assert(err.message.includes('failed under coverage'));
} }
assertCoverageGenerated(); assertCoverageGenerate(truffleConfig);
const output = getOutput(); const output = getOutput(truffleConfig);
const path = Object.keys(output)[0]; const path = Object.keys(output)[0];
assert(output[path].fnMap['1'].name === 'test', 'cov missing "test"'); assert(output[path].fnMap['1'].name === 'test', 'cov missing "test"');
@ -210,7 +214,7 @@ describe('app', function() {
assert(err.message.includes('Compilation failed')); assert(err.message.includes('Compilation failed'));
} }
assertCoverageNotGenerated(); assertCoverageNotGenerated(truffleConfig);
}); });
}); });

Loading…
Cancel
Save