2018-08-08 18:26:40 +00:00
|
|
|
/*global web3*/
|
2018-08-09 19:46:10 +00:00
|
|
|
const fs = require('../../core/fs');
|
2018-08-07 19:26:39 +00:00
|
|
|
const ContractSources = require('./contract_sources');
|
|
|
|
|
2018-08-08 18:26:40 +00:00
|
|
|
// Set up the web3 extension
|
|
|
|
web3.extend({
|
|
|
|
property: 'debug',
|
|
|
|
methods: [{name: 'traceTransaction', call: 'debug_traceTransaction', params: 2}]
|
|
|
|
});
|
|
|
|
|
2018-08-01 15:48:17 +00:00
|
|
|
class CodeCoverage {
|
2018-08-01 16:08:47 +00:00
|
|
|
constructor(embark, _options) {
|
2018-08-01 15:48:17 +00:00
|
|
|
this.events = embark.events;
|
|
|
|
this.logger = embark.logger;
|
2018-08-01 16:08:47 +00:00
|
|
|
|
2018-08-07 19:26:39 +00:00
|
|
|
embark.events.on('contracts:compile:solc', this.compileSolc.bind(this));
|
|
|
|
embark.events.on('contracts:compiled:solc', this.compiledSolc.bind(this));
|
|
|
|
embark.events.on('contracts:run:solc', this.runSolc.bind(this));
|
|
|
|
embark.events.on('block:header', this.runSolc.bind(this));
|
2018-08-08 18:26:40 +00:00
|
|
|
|
2018-09-14 20:31:40 +00:00
|
|
|
// These events are emitted from a test-specific Embark instance, so we need to
|
|
|
|
// pull it in from global.
|
|
|
|
global.embark.events.on('tests:finished', this.updateCoverageReport.bind(this));
|
|
|
|
|
2018-08-08 18:26:40 +00:00
|
|
|
this.seenTransactions = {};
|
2018-08-20 17:54:44 +00:00
|
|
|
this.coverageReport = {};
|
2018-08-28 17:39:18 +00:00
|
|
|
this.contractSources = new ContractSources([]);
|
2018-08-08 18:26:40 +00:00
|
|
|
|
2018-09-14 17:16:02 +00:00
|
|
|
this.dotEmbarkPath = fs.dappPath('.embark');
|
|
|
|
this.coverageReportPath = fs.dappPath('.embark', 'coverage.json');
|
2018-08-07 19:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
compileSolc(input) {
|
2018-08-28 17:39:18 +00:00
|
|
|
Object.keys(input.sources).forEach((file) => {
|
|
|
|
this.contractSources.addFile(file, input.sources[file].content);
|
|
|
|
});
|
2018-08-07 19:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
compiledSolc(output) {
|
|
|
|
this.contractSources.parseSolcOutput(output);
|
|
|
|
}
|
|
|
|
|
2018-09-14 20:31:40 +00:00
|
|
|
updateCoverageReport(cb) {
|
2018-09-14 20:43:58 +00:00
|
|
|
fs.mkdirp(this.dotEmbarkPath, () => {
|
|
|
|
fs.writeFile(this.coverageReportPath, JSON.stringify(this.coverageReport), cb);
|
|
|
|
});
|
2018-09-14 17:16:02 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 18:26:40 +00:00
|
|
|
async runSolc(receipt) {
|
2018-08-09 20:46:20 +00:00
|
|
|
let block = await web3.eth.getBlock(receipt.number);
|
|
|
|
if(block.transactions.length == 0) return;
|
|
|
|
|
|
|
|
let requests = [];
|
|
|
|
for(let i in block.transactions) {
|
2018-08-08 18:26:40 +00:00
|
|
|
var txHash = block.transactions[i];
|
2018-08-01 16:08:47 +00:00
|
|
|
|
2018-08-08 18:26:40 +00:00
|
|
|
if(this.seenTransactions[txHash]) return;
|
|
|
|
|
|
|
|
this.seenTransactions[txHash] = true;
|
2018-08-09 20:46:20 +00:00
|
|
|
requests.push(web3.debug.traceTransaction(txHash, {}));
|
|
|
|
}
|
|
|
|
|
|
|
|
let traces = await Promise.all(requests);
|
|
|
|
|
|
|
|
for(let i in traces) {
|
2018-08-28 17:39:18 +00:00
|
|
|
this.coverageReport = this.contractSources.generateCodeCoverage(traces[i]);
|
2018-08-08 18:26:40 +00:00
|
|
|
}
|
2018-08-01 15:48:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:08:47 +00:00
|
|
|
module.exports = CodeCoverage;
|