First passing test

buidler/draft
cgewecke 5 years ago
parent 92fa5e0f77
commit c91838793e
  1. 164
      dist/buidler.plugin.js
  2. 83
      dist/plugin-assets/buidler.ui.js
  3. 45
      dist/plugin-assets/buidler.utils.js
  4. 3
      dist/plugin-assets/plugin.utils.js
  5. 10
      lib/api.js
  6. 2
      lib/validator.js
  7. 62
      test/units/buidler/standard.js
  8. 1
      test/units/validator.js
  9. 43
      test/util/integration.js

@ -0,0 +1,164 @@
const API = require('./../lib/api');
const utils = require('./plugin-assets/plugin.utils');
const buidlerUtils = require('./plugin-assets/buidler.utils');
const PluginUI = require('./plugin-assets/buidler.ui');
const pkg = require('./../package.json');
const death = require('death');
const path = require('path');
const Web3 = require('web3');
const ganache = require('ganache-cli');
const { task, internalTask, types } = require("@nomiclabs/buidler/config");
const { ensurePluginLoadedWithUsePlugin } = require("@nomiclabs/buidler/plugins");
const { BuidlerPluginError } = require("@nomiclabs/buidler/internal/core/errors");
const { createProvider } = require("@nomiclabs/buidler/internal/core/providers/construction");
const {
TASK_TEST_RUN_MOCHA_TESTS,
TASK_TEST,
TASK_COMPILE,
} = require("@nomiclabs/buidler/builtin-tasks/task-names");
const util = require('util');
function plugin() {
let api;
let address;
let network;
let error;
let testsErrored = false;
const ui = new PluginUI();
extendEnvironment(env => {
env.config.logger = {log: null};
env.config = buidlerUtils.normalizeConfig(env.config);
api = new API(utils.loadSolcoverJS(env.config));
const networkConfig = {
url: `http://${api.host}:${api.port}`,
gas: api.gasLimit,
gasPrice: api.gasPrice
}
const provider = createProvider(api.defaultNetworkName, networkConfig);
env.config.networks[api.defaultNetworkName] = networkConfig;
env.config.defaultNetwork = api.defaultNetworkName;
env.network = {
name: api.defaultNetworkName,
config: networkConfig,
provider: provider,
}
env.ethereum = provider;
// Keep a reference so we can set the from account
network = env.network;
})
function myTimeout(){
return new Promise(resolve => {
setTimeout(()=>{
console.log('TIMEOUT')
}, 2000)
})
}
task("timeout", 'desc').setAction(async function(taskArguments, { config }, runSuper){
await myTimeout();
});
task("coverage", "Generates a code coverage report for tests")
.addOptionalParam("file", ui.flags.file, null, types.string)
.addOptionalParam("solcoverjs", ui.flags.solcoverjs, null, types.string)
.addOptionalParam('temp', ui.flags.temp, null, types.string)
.setAction(async function(taskArguments, { run, config }, runSuper){
console.log(util.inspect())
try {
death(buidlerUtils.finish.bind(null, config, api)); // Catch interrupt signals
config.logger = {log: null};
config = buidlerUtils.normalizeConfig(config);
api = new API(utils.loadSolcoverJS(config));
// Server launch
const address = await api.ganache(ganache);
const web3 = new Web3(address);
const accounts = await web3.eth.getAccounts();
const nodeInfo = await web3.eth.getNodeInfo();
const ganacheVersion = nodeInfo.split('/')[1];
// Set default account
network.from = accounts[0];
// Version Info
ui.report('versions', [
ganacheVersion,
pkg.version
]);
// Network Info
ui.report('network', [
api.defaultNetworkName,
api.port
]);
// Run post-launch server hook;
await api.onServerReady(config);
// Instrument
const skipFiles = api.skipFiles || [];
let {
targets,
skipped
} = utils.assembleFiles(config, skipFiles);
targets = api.instrument(targets);
utils.reportSkipped(config, skipped);
// Filesystem & Compiler Re-configuration
const {
tempArtifactsDir,
tempContractsDir
} = utils.getTempLocations(config);
utils.save(targets, config.paths.sources, tempContractsDir);
utils.save(skipped, config.paths.sources, tempContractsDir);
config.paths.sources = tempContractsDir;
config.paths.artifacts = tempArtifactsDir;
config.paths.cache = buidlerUtils.tempCacheDir(config);
console.log(config.paths.cache)
config.solc.optimizer.enabled = false;
await run(TASK_COMPILE);
await api.onCompileComplete(config);
try {
failures = await run(TASK_TEST, {testFiles: []})
} catch (e) {
error = e.stack;
console.log(e.message + error)
}
await api.onTestsComplete(config);
// Run Istanbul
await api.report();
await api.onIstanbulComplete(config);
} catch(e) {
error = e;
}
})
}
module.exports = plugin;

@ -0,0 +1,83 @@
const UI = require('./../../lib/ui').UI;
/**
* Truffle Plugin logging
*/
class PluginUI extends UI {
constructor(log){
super(log);
this.flags = {
file: `Path (or glob) defining a subset of tests to run`,
solcoverjs: `Relative path from working directory to config. ` +
`Useful for monorepo packages that share settings.`,
temp: `Path to a disposable folder to store compilation artifacts in. ` +
`Useful when your test setup scripts include hard-coded paths to ` +
`a build directory.`,
}
}
/**
* Writes a formatted message via log
* @param {String} kind message selector
* @param {String[]} args info to inject into template
*/
report(kind, args=[]){
const c = this.chalk;
const ct = c.bold.green('>');
const ds = c.bold.yellow('>');
const w = ":warning:";
const kinds = {
'instr-skip': `\n${c.bold('Coverage skipped for:')}` +
`\n${c.bold('=====================')}\n`,
'instr-skipped': `${ds} ${c.grey(args[0])}`,
'versions': `${ct} ${c.bold('ganache-core')}: ${args[0]}\n` +
`${ct} ${c.bold('solidity-coverage')}: v${args[1]}`,
'network': `\n${c.bold('Network Info')}` +
`\n${c.bold('============')}\n` +
`${ct} ${c.bold('port')}: ${args[1]}\n` +
`${ct} ${c.bold('network')}: ${args[0]}\n`,
}
this._write(kinds[kind]);
}
/**
* Returns a formatted message. Useful for error message.
* @param {String} kind message selector
* @param {String[]} args info to inject into template
* @return {String} message
*/
generate(kind, args=[]){
const c = this.chalk;
const x = ":x:";
const kinds = {
'sources-fail': `${c.red('Cannot locate expected contract sources folder: ')} ${args[0]}`,
'solcoverjs-fail': `${c.red('Could not load .solcover.js config file. ')}` +
`${c.red('This can happen if it has a syntax error or ')}` +
`${c.red('the path you specified for it is wrong.')}`,
'tests-fail': `${x} ${c.bold(args[0])} ${c.red('test(s) failed under coverage.')}`,
'no-network': `${c.red('Network: ')} ${args[0]} ` +
`${c.red(' is not defined in your truffle-config networks. ')}`,
}
return this._format(kinds[kind])
}
}
module.exports = PluginUI;

@ -0,0 +1,45 @@
const shell = require('shelljs');
const pluginUtils = require("./plugin.utils");
const path = require('path')
const util = require('util')
function normalizeConfig(config){
config.workingDir = config.paths.root;
config.contractsDir = config.paths.sources;
config.testDir = config.paths.tests;
config.artifactsDir = config.paths.artifacts;
return config;
}
function tempCacheDir(config){
return path.join(config.paths.root, '.coverage_cache');
}
/**
* Silently removes temporary folders and calls api.finish to shut server down
* @param {buidlerConfig} config
* @param {SolidityCoverage} api
* @return {Promise}
*/
async function finish(config, api){
const {
tempContractsDir,
tempArtifactsDir
} = pluginUtils.getTempLocations(config);
shell.config.silent = true;
shell.rm('-Rf', tempContractsDir);
shell.rm('-Rf', tempArtifactsDir);
shell.rm('-Rf', path.join(config.paths.root, '.coverage_cache'));
shell.config.silent = false;
if (api) await api.finish();
}
module.exports = {
normalizeConfig: normalizeConfig,
finish: finish,
tempCacheDir: tempCacheDir
}

@ -11,6 +11,7 @@ const PluginUI = require('./truffle.ui');
const path = require('path'); const path = require('path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const shell = require('shelljs'); const shell = require('shelljs');
const util = require('util')
// === // ===
// UI // UI
@ -193,7 +194,6 @@ function loadSolcoverJS(config){
let coverageConfig; let coverageConfig;
let ui = new PluginUI(config.logger.log); let ui = new PluginUI(config.logger.log);
// Handle --solcoverjs flag // Handle --solcoverjs flag
(config.solcoverjs) (config.solcoverjs)
? solcoverjs = path.join(config.workingDir, config.solcoverjs) ? solcoverjs = path.join(config.workingDir, config.solcoverjs)
@ -251,6 +251,7 @@ async function finish(config, api){
shell.config.silent = true; shell.config.silent = true;
shell.rm('-Rf', tempContractsDir); shell.rm('-Rf', tempContractsDir);
shell.rm('-Rf', tempArtifactsDir); shell.rm('-Rf', tempArtifactsDir);
shell.config.silent = false;
if (api) await api.finish(); if (api) await api.finish();
} }

@ -30,7 +30,6 @@ class API {
this.testsErrored = false; this.testsErrored = false;
this.cwd = config.cwd || process.cwd(); this.cwd = config.cwd || process.cwd();
this.originalContractsDir = config.originalContractsDir
this.defaultHook = () => {}; this.defaultHook = () => {};
this.onServerReady = config.onServerReady || this.defaultHook; this.onServerReady = config.onServerReady || this.defaultHook;
@ -41,12 +40,12 @@ class API {
this.server = null; this.server = null;
this.provider = null; this.provider = null;
this.defaultPort = 8555; this.defaultPort = 8555;
this.defaultNetworkName = 'soliditycoverage';
this.client = config.client; this.client = config.client;
this.port = config.port || this.defaultPort; this.port = config.port || this.defaultPort;
this.host = config.host || "127.0.0.1"; this.host = config.host || "127.0.0.1";
this.providerOptions = config.providerOptions || {}; this.providerOptions = config.providerOptions || {};
this.skipFiles = config.skipFiles || []; this.skipFiles = config.skipFiles || [];
this.log = config.log || console.log; this.log = config.log || console.log;
@ -167,10 +166,7 @@ class API {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
this.coverage.generate( this.coverage.generate(this.instrumenter.instrumentationData);
this.instrumenter.instrumentationData,
this.originalContractsDir
);
const mapping = this.makeKeysRelative(this.coverage.data, this.cwd); const mapping = this.makeKeysRelative(this.coverage.data, this.cwd);
this.saveCoverage(mapping); this.saveCoverage(mapping);
@ -230,7 +226,7 @@ class API {
} }
// NB: EADDRINUSE errors are uncatch-able? // NB: EADDRINUSE errors are uncatch-able?
pify(this.server.listen)(this.port); await pify(this.server.listen)(this.port);
} }
assertHasBlockchain(provider){ assertHasBlockchain(provider){

@ -15,8 +15,6 @@ const configSchema = {
cwd: {type: "string"}, cwd: {type: "string"},
host: {type: "string"}, host: {type: "string"},
originalContractsDir: {type: "string"},
port: {type: "number"}, port: {type: "number"},
providerOptions: {type: "object"}, providerOptions: {type: "object"},
silent: {type: "boolean"}, silent: {type: "boolean"},

@ -0,0 +1,62 @@
const assert = require('assert');
const fs = require('fs');
const path = require('path')
const shell = require('shelljs');
const verify = require('../../util/verifiers')
const mock = require('../../util/integration');
const plugin = require('../../../dist/buidler.plugin');
const {
TASK_TEST
} = require("@nomiclabs/buidler/builtin-tasks/task-names");
// =======================
// Standard Use-case Tests
// =======================
describe.only('Buidler Plugin: standard use cases', function() {
let buidlerConfig;
let solcoverConfig;
beforeEach(() => {
mock.clean();
mock.loggerOutput.val = '';
solcoverConfig = {};
buidlerConfig = mock.getDefaultBuidlerConfig();
verify.cleanInitialState();
})
afterEach(() => {
mock.buidlerTearDownEnv();
mock.clean();
});
/*it.only('timeout', async function(){
mock.buidlerSetupEnv(this);
this.env.run('timeout')
});*/
it('simple contract', async function(){
mock.install('Simple', 'simple.js', solcoverConfig);
mock.buidlerSetupEnv(this);
await this.env.run("coverage");
/*verify.coverageGenerated(buidlerConfig);
const output = mock.getOutput(buidlerConfig);
const path = Object.keys(output)[0];
assert(
output[path].fnMap['1'].name === 'test',
'coverage.json missing "test"'
);
assert(
output[path].fnMap['2'].name === 'getX',
'coverage.json missing "getX"'
);*/
});
})

@ -22,7 +22,6 @@ describe('config validation', () => {
const options = [ const options = [
"cwd", "cwd",
"host", "host",
"originalContractsDir",
] ]
options.forEach(name => { options.forEach(name => {

@ -8,8 +8,8 @@ const fs = require('fs');
const shell = require('shelljs'); const shell = require('shelljs');
const decache = require('decache'); const decache = require('decache');
const PluginsTestHelpers = require("@nomiclabs/buidler/plugins-testing")
const TruffleConfig = require('truffle-config'); const TruffleConfig = require('truffle-config');
const { resetBuidlerContext } = require("@nomiclabs/buidler/plugins-testing")
const temp = './sc_temp'; const temp = './sc_temp';
const truffleConfigName = 'truffle-config.js'; const truffleConfigName = 'truffle-config.js';
@ -21,6 +21,7 @@ const migrationPath = `${temp}/migrations/2_deploy.js`;
const templatePath = './test/integration/generic/*'; const templatePath = './test/integration/generic/*';
const projectPath = './test/integration/projects/' const projectPath = './test/integration/projects/'
let previousCWD;
// ========================== // ==========================
// Misc Utils // Misc Utils
@ -51,22 +52,20 @@ function getOutput(truffleConfig){
return JSON.parse(fs.readFileSync(jsonPath, 'utf8')); return JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
} }
// Buidler env set up / tear down. // Buidler env set up
function useEnvironment(projectPath) { function buidlerSetupEnv(mocha) {
let previousCWD; const mockwd = path.join(process.cwd(), temp);
previousCWD = process.cwd();
beforeEach("Loading buidler environment", function() { process.chdir(mockwd);
previousCWD = process.cwd(); mocha.env = require("@nomiclabs/buidler");
process.chdir(projectPath); };
process.env.BUIDLER_NETWORK = "develop";
this.env = require("@nomiclabs/buidler");
});
afterEach("Resetting buidler", function() { // Buidler env tear down
PluginsTestHelpers.resetBuidlerContext(); function buidlerTearDownEnv() {
resetBuidlerContext();
process.chdir(previousCWD); process.chdir(previousCWD);
}); };
}
// ========================== // ==========================
// Truffle Configuration // Truffle Configuration
@ -144,10 +143,16 @@ function getDefaultBuidlerConfig() {
} }
function getBuidlerConfigJS(config){ function getBuidlerConfigJS(config){
const prefix =`
const { loadPluginFile } = require("@nomiclabs/buidler/plugins-testing");
loadPluginFile(__dirname + "/../dist/buidler.plugin");
usePlugin("@nomiclabs/buidler-truffle5");
`
if (config) { if (config) {
return `module.exports = ${JSON.stringify(config, null, ' ')}` return `${prefix}module.exports = ${JSON.stringify(config, null, ' ')}`;
} else { } else {
return `module.exports = ${JSON.stringify(getDefaultBuidlerConfig(), null, ' ')}` return `${prefix}module.exports = ${JSON.stringify(getDefaultBuidlerConfig(), null, ' ')}`;
} }
} }
@ -297,6 +302,8 @@ module.exports = {
installFullProject: installFullProject, installFullProject: installFullProject,
clean: clean, clean: clean,
pathToContract: pathToContract, pathToContract: pathToContract,
getOutput: getOutput getOutput: getOutput,
buidlerSetupEnv: buidlerSetupEnv,
buidlerTearDownEnv: buidlerTearDownEnv
} }

Loading…
Cancel
Save