<commit_before>#!/usr/bin/env node

const shell = require('shelljs');
const fs = require('fs');
const reqCwd = require('req-cwd');
const path = require('path');
const childprocess = require('child_process');
const getInstrumentedVersion = require('./instrumentSolidity.js');
const CoverageMap = require('./coverageMap.js');
const istanbul = require('istanbul');

const istanbulCollector = new istanbul.Collector();
const istanbulReporter = new istanbul.Reporter();

// Very high gas block limits / contract deployment limits
const gasLimitString = '0xfffffffffff';
const gasLimitHex = 0xfffffffffff;
const gasPriceHex = 0x01;

const coverage = new CoverageMap();

// Paths
const coverageDir = './coverageEnv';        // Env that instrumented .sols are tested in

// Options
let workingDir = '.';                       // Default location of contracts folder
let port = 8555;                            // Default port - NOT 8545 & configurable via --port
let coverageOption = '--network coverage';  // Default truffle network execution flag
let silence = '';                           // Default log level: configurable by --silence
let log = console.log;                      // Default log level: configurable by --silence

let testrpcProcess;                         // ref to testrpc server we need to close on exit
let events;                                 // ref to string loaded from 'allFiredEvents'

// --------------------------------------- Utilities -----------------------------------------------
/**
 * Removes coverage build artifacts, kills testrpc.
 * Exits (1) and prints msg on error, exits (0) otherwise.
 * @param  {String} err error message
 */
function cleanUp(err) {
  log('Cleaning up...');
  shell.config.silent = true;
  shell.rm('-Rf', `${coverageDir}`);
  shell.rm('./allFiredEvents');
  if (testrpcProcess) { testrpcProcess.kill(); }

  if (err) {
    log(`${err}\nExiting without generating coverage...`);
    process.exit(1);
  } else {
    process.exit(0);
  }
}
// --------------------------------------- Script --------------------------------------------------
const config = reqCwd.silent(`${workingDir}/.solcover.js`) || {};

if (config.dir) workingDir = config.dir;
if (config.port) port = config.port;

if (config.silent) {
  silence = '> /dev/null 2>&1';       // Silence for solcover's unit tests / CI
  log = () => {};
}

// Run the modified testrpc with large block limit, on (hopefully) unused port.
// (Changes here should be also be added to the before() block of test/run.js).
if (!config.norpc) {
  try {
    // NPM installs the testrpc-sc fork at different locations in node_modules based on
    // whether testrpc is a pre-existing dependency of the project solcover is being added to
    // using (--save-dev).
    let command;
    if (shell.test('-e', './node_modules/ethereumjs-testrpc-sc')) {
      command = './node_modules/ethereumjs-testrpc-sc/bin/testrpc ';
    } else {
      command = './node_modules/solcover/node_modules/ethereumjs-testrpc-sc/bin/testrpc ';
    }

    const options = `--gasLimit ${gasLimitString} --port ${port}`;
    testrpcProcess = childprocess.exec(command + options);
    log(`Launching testrpc on port ${port}`);
  } catch (err) {
    const msg = `There was a problem launching testrpc: ${err}`;
    cleanUp(msg);
  }
}

// Generate a copy of the target truffle project configured for solcover and save to the coverage
// environment folder.
log('Generating coverage environment');
try {
  shell.mkdir(`${coverageDir}`);
  shell.cp('-R', `${workingDir}/contracts`, `${coverageDir}`);
  shell.cp('-R', `${workingDir}/migrations`, `${coverageDir}`);
  shell.cp('-R', `${workingDir}/test`, `${coverageDir}`);

  const truffleConfig = reqCwd(`${workingDir}/truffle.js`);

  // Coverage network opts specified: copy truffle.js whole to coverage environment
  if (truffleConfig.networks.coverage) {
    shell.cp(`${workingDir}/truffle.js`, `${coverageDir}/truffle.js`);

  // Coverage network opts NOT specified: default to the development network w/ modified
  // port, gasLimit, gasPrice. Export the config object only.
  } else {
    const trufflejs = `
      module.exports = {
        networks: {
          development: {
            host: "localhost", 
            network_id: "*",
            port: ${port},
            gas: ${gasLimitHex},
            gasPrice: ${gasPriceHex}
          }
        }
      };`;

    coverageOption = '';
    fs.writeFileSync(`${coverageDir}/truffle.js`, trufflejs);
  }
} catch (err) {
  const msg = ('There was a problem generating the coverage environment: ');
  cleanUp(msg + err);
}

// For each contract except migrations.sol:
// 1. Generate file path reference for coverage report
// 2. Load contract as string
// 3. Instrument contract
// 4. Save instrumented contract in the coverage environment folder where covered tests will run
// 5. Add instrumentation info to the coverage map
try {
  shell.ls(`${coverageDir}/contracts/**/*.sol`).forEach(file => {
    const migrations = `${coverageDir}/contracts/Migrations.sol`;

    if (file !== migrations) {
      log('Instrumenting ', file);
      const contractPath = path.resolve(file);
      const canonicalPath = contractPath.split('/coverageEnv').join('');
      const contract = fs.readFileSync(contractPath).toString();
      const instrumentedContractInfo = getInstrumentedVersion(contract, canonicalPath);
      fs.writeFileSync(contractPath, instrumentedContractInfo.contract);
      coverage.addContract(instrumentedContractInfo, canonicalPath);
    }
  });
} catch (err) {
  cleanUp(err);
}

// Run solcover's fork of truffle over instrumented contracts in the
// coverage environment folder
try {
  log('Launching Truffle (this can take a few seconds)...');
  const command = `cd coverageEnv && truffle test ${coverageOption} ${silence}`;
  shell.exec(command);
} catch (err) {
  cleanUp(err);
}

// Get events fired during instrumented contracts execution.
try {
  events = fs.readFileSync('./allFiredEvents').toString().split('\n');
  events.pop();
} catch (err) {
  const msg =
  `
    There was an error generating coverage. Possible reasons include:
    1. Another application is using port ${port} 
    2. Truffle crashed because your tests errored
    <commit_msg>Get truffle exec to recognize networks option flag<commit_after>#!/usr/bin/env node

const shell = require('shelljs');
const fs = require('fs');
const reqCwd = require('req-cwd');
const path = require('path');
const childprocess = require('child_process');
const getInstrumentedVersion = require('./instrumentSolidity.js');
const CoverageMap = require('./coverageMap.js');
const istanbul = require('istanbul');

const istanbulCollector = new istanbul.Collector();
const istanbulReporter = new istanbul.Reporter();

// Very high gas block limits / contract deployment limits
const gasLimitString = '0xfffffffffff';
const gasLimitHex = 0xfffffffffff;
const gasPriceHex = 0x01;

const coverage = new CoverageMap();

// Paths
const coverageDir = './coverageEnv';        // Env that instrumented .sols are tested in

// Options
let workingDir = '.';                       // Default location of contracts folder
let port = 8555;                            // Default port - NOT 8545 & configurable via --port
let coverageOption = '--network coverage';  // Default truffle network execution flag
let silence = '';                           // Default log level: configurable by --silence
let log = console.log;                      // Default log level: configurable by --silence

let testrpcProcess;                         // ref to testrpc server we need to close on exit
let events;                                 // ref to string loaded from 'allFiredEvents'

// --------------------------------------- Utilities -----------------------------------------------
/**
 * Removes coverage build artifacts, kills testrpc.
 * Exits (1) and prints msg on error, exits (0) otherwise.
 * @param  {String} err error message
 */
function cleanUp(err) {
  log('Cleaning up...');
  shell.config.silent = true;
  shell.rm('-Rf', `${coverageDir}`);
  shell.rm('./allFiredEvents');
  if (testrpcProcess) { testrpcProcess.kill(); }

  if (err) {
    log(`${err}\nExiting without generating coverage...`);
    process.exit(1);
  } else {
    process.exit(0);
  }
}
// --------------------------------------- Script --------------------------------------------------
const config = reqCwd.silent(`${workingDir}/.solcover.js`) || {};

if (config.dir) workingDir = config.dir;
if (config.port) port = config.port;

if (config.silent) {
  silence = '> /dev/null 2>&1';       // Silence for solcover's unit tests / CI
  log = () => {};
}

// Run the modified testrpc with large block limit, on (hopefully) unused port.
// (Changes here should be also be added to the before() block of test/run.js).
if (!config.norpc) {
  try {
    // NPM installs the testrpc-sc fork at different locations in node_modules based on
    // whether testrpc is a pre-existing dependency of the project solcover is being added to
    // using (--save-dev).
    let command;
    if (shell.test('-e', './node_modules/ethereumjs-testrpc-sc')) {
      command = './node_modules/ethereumjs-testrpc-sc/bin/testrpc ';
    } else {
      command = './node_modules/solcover/node_modules/ethereumjs-testrpc-sc/bin/testrpc ';
    }

    const options = `--gasLimit ${gasLimitString} --port ${port}`;
    testrpcProcess = childprocess.exec(command + options);
    log(`Launching testrpc on port ${port}`);
  } catch (err) {
    const msg = `There was a problem launching testrpc: ${err}`;
    cleanUp(msg);
  }
}

// Generate a copy of the target truffle project configured for solcover and save to the coverage
// environment folder.
log('Generating coverage environment');
try {
  shell.mkdir(`${coverageDir}`);
  shell.cp('-R', `${workingDir}/contracts`, `${coverageDir}`);
  shell.cp('-R', `${workingDir}/migrations`, `${coverageDir}`);
  shell.cp('-R', `${workingDir}/test`, `${coverageDir}`);

  const truffleConfig = reqCwd(`${workingDir}/truffle.js`);

  // Coverage network opts specified: copy truffle.js whole to coverage environment
  if (truffleConfig.networks.coverage) {
    shell.cp(`${workingDir}/truffle.js`, `${coverageDir}/truffle.js`);

  // Coverage network opts NOT specified: default to the development network w/ modified
  // port, gasLimit, gasPrice. Export the config object only.
  } else {
    const trufflejs = `
      module.exports = {
        networks: {
          development: {
            host: "localhost", 
            network_id: "*",
            port: ${port},
            gas: ${gasLimitHex},
            gasPrice: ${gasPriceHex}
          }
        }
      };`;

    coverageOption = '';
    fs.writeFileSync(`${coverageDir}/truffle.js`, trufflejs);
  }
} catch (err) {
  const msg = ('There was a problem generating the coverage environment: ');
  cleanUp(msg + err);
}

// For each contract except migrations.sol:
// 1. Generate file path reference for coverage report
// 2. Load contract as string
// 3. Instrument contract
// 4. Save instrumented contract in the coverage environment folder where covered tests will run
// 5. Add instrumentation info to the coverage map
try {
  shell.ls(`${coverageDir}/contracts/**/*.sol`).forEach(file => {
    const migrations = `${coverageDir}/contracts/Migrations.sol`;

    if (file !== migrations) {
      log('Instrumenting ', file);
      const contractPath = path.resolve(file);
      const canonicalPath = contractPath.split('/coverageEnv').join('');
      const contract = fs.readFileSync(contractPath).toString();
      const instrumentedContractInfo = getInstrumentedVersion(contract, canonicalPath);
      fs.writeFileSync(contractPath, instrumentedContractInfo.contract);
      coverage.addContract(instrumentedContractInfo, canonicalPath);
    }
  });
} catch (err) {
  cleanUp(err);
}

// Run solcover's fork of truffle over instrumented contracts in the
// coverage environment folder. Shell cd command needs to be invoked
// as its own statement for command line options to work, apparently.
try {
  log('Launching Truffle (this can take a few seconds)...');
  const command = `truffle test ${coverageOption} ${silence}`;
  shell.cd('./coverageEnv');
  shell.exec(command);
  shell.cd('./..');
} catch (err) {
  cleanUp(err);
}

// Get events fired during instrumented contracts execution.
try {
  events = fs.readFileSync('./allFiredEvents').toString().split('\n');
  events.pop();
} catch (err) {
  const msg =
  `
    There was an error generating coverage. Possible reasons include:
    1. Another application is using port ${port} 
    2. Truffle crashed because your tests errored
    
{'fraction_non_alphanumeric': 0.1583713970704048, 'fraction_numerical': 0.004095133091825485, 'mean_word_length': 2.8296139927623645, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5050424', 'n_tokens_mistral': 3610, 'n_tokens_neox': 3588, 'n_words': 1095}