mirror of https://github.com/embarklabs/embark.git
make code coverage work with refactored tests
This commit is contained in:
parent
7516bad619
commit
f4d7636b7a
|
@ -557,6 +557,8 @@ class EmbarkController {
|
|||
engine.startService("web3", {wait: true}); // Empty web3 as Test changes it
|
||||
engine.startService("deployment");
|
||||
engine.startService("codeGenerator");
|
||||
engine.startService("codeRunner");
|
||||
engine.startService("codeCoverage");
|
||||
engine.startService("testRunner");
|
||||
callback();
|
||||
},
|
||||
|
|
|
@ -34,6 +34,11 @@ var Config = function(options) {
|
|||
cb(self.contractsConfig);
|
||||
});
|
||||
|
||||
self.events.setCommandHandler("config:contractsConfig:set", (config, cb) => {
|
||||
self.contractsConfig = config;
|
||||
cb();
|
||||
});
|
||||
|
||||
self.events.setCommandHandler("config:contractsFiles", (cb) => {
|
||||
cb(self.contractsFiles);
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ const utils = require('../../utils/utils');
|
|||
const constants = require('../../constants');
|
||||
const embarkJsUtils = require('embarkjs').Utils;
|
||||
|
||||
const WEB3_READY = 'web3Ready';
|
||||
const WEB3_READY = 'blockchain:ready';
|
||||
|
||||
// TODO: consider another name, this is the blockchain connector
|
||||
class BlockchainConnector {
|
||||
|
@ -40,6 +40,7 @@ class BlockchainConnector {
|
|||
this.registerRequests();
|
||||
this.registerWeb3Object();
|
||||
this.registerEvents();
|
||||
this.subscribeToPendingTransactions();
|
||||
}
|
||||
|
||||
initWeb3(cb) {
|
||||
|
@ -67,10 +68,46 @@ class BlockchainConnector {
|
|||
}
|
||||
|
||||
if (type === 'vm') {
|
||||
const sim = this._getSimulator();
|
||||
this.provider = sim.provider(this.contractsConfig.deployment);
|
||||
this.web3.setProvider(this.provider);
|
||||
this._emitWeb3Ready();
|
||||
const sim = self._getSimulator();
|
||||
self.provider = sim.provider(self.contractsConfig.deployment);
|
||||
|
||||
if (self.coverage) {
|
||||
// Here we patch the sendAsync method on the provider. The goal behind this is to force pure/constant/view calls to become
|
||||
// transactions, so that we can pull in execution traces and account for those executions in code coverage.
|
||||
//
|
||||
// Instead of a simple call, here's what happens:
|
||||
//
|
||||
// 1) A transaction is sent with the same payload, and a pre-defined gas price;
|
||||
// 2) We wait for the transaction to be mined by asking for the receipt;
|
||||
// 3) Once we get the receipt back, we dispatch the real call and pass the original callback;
|
||||
//
|
||||
// This will still allow tests to get the return value from the call and run contracts unmodified.
|
||||
self.provider.realSendAsync = self.provider.sendAsync.bind(self.provider);
|
||||
self.provider.sendAsync = function(payload, cb) {
|
||||
if(payload.method !== 'eth_call') {
|
||||
return self.provider.realSendAsync(payload, cb);
|
||||
}
|
||||
self.events.request('reporter:toggleGasListener');
|
||||
let newParams = Object.assign({}, payload.params[0], {gasPrice: '0x77359400'});
|
||||
let newPayload = {
|
||||
id: payload.id + 1,
|
||||
method: 'eth_sendTransaction',
|
||||
params: [newParams],
|
||||
jsonrpc: payload.jsonrpc
|
||||
};
|
||||
|
||||
self.provider.realSendAsync(newPayload, (_err, response) => {
|
||||
let txHash = response.result;
|
||||
self.web3.eth.getTransactionReceipt(txHash, (_err, _res) => {
|
||||
self.events.request('reporter:toggleGasListener');
|
||||
self.provider.realSendAsync(payload, cb);
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
self.web3.setProvider(self.provider);
|
||||
self._emitWeb3Ready();
|
||||
return cb();
|
||||
}
|
||||
|
||||
|
@ -115,6 +152,7 @@ class BlockchainConnector {
|
|||
this.isWeb3Ready = true;
|
||||
this.events.emit(WEB3_READY);
|
||||
this.registerWeb3Object();
|
||||
this.subscribeToPendingTransactions();
|
||||
}
|
||||
|
||||
_getSimulator() {
|
||||
|
|
|
@ -12,7 +12,7 @@ class ContractSource {
|
|||
this.lineCount = this.lineLengths.length;
|
||||
|
||||
this.lineOffsets = this.lineLengths.reduce((sum, _elt, i) => {
|
||||
sum[i] = (i == 0) ? 0 : self.lineLengths[i-1] + sum[i-1] + 1;
|
||||
sum[i] = (i === 0) ? 0 : self.lineLengths[i-1] + sum[i-1] + 1;
|
||||
return sum;
|
||||
}, []);
|
||||
|
||||
|
|
|
@ -2,11 +2,6 @@
|
|||
const fs = require('../../core/fs');
|
||||
const ContractSources = require('./contract_sources');
|
||||
|
||||
// Set up the web3 extension
|
||||
web3.extend({
|
||||
property: 'debug',
|
||||
methods: [{name: 'traceTransaction', call: 'debug_traceTransaction', params: 2}]
|
||||
});
|
||||
|
||||
class CodeCoverage {
|
||||
constructor(embark, _options) {
|
||||
|
@ -18,9 +13,18 @@ class CodeCoverage {
|
|||
embark.events.on('contracts:run:solc', this.runSolc.bind(this));
|
||||
embark.events.on('block:header', this.runSolc.bind(this));
|
||||
|
||||
// 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));
|
||||
embark.events.on('tests:finished', this.updateCoverageReport.bind(this));
|
||||
|
||||
embark.events.on('blockchain:ready', () => {
|
||||
embark.events.request('blockchain:get', (web3) => {
|
||||
// Set up the web3 extension
|
||||
web3.extend({
|
||||
property: 'debug',
|
||||
methods: [{name: 'traceTransaction', call: 'debug_traceTransaction', params: 2}]
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
this.seenTransactions = {};
|
||||
this.coverageReport = {};
|
||||
|
@ -48,7 +52,7 @@ class CodeCoverage {
|
|||
|
||||
async runSolc(receipt) {
|
||||
let block = await web3.eth.getBlock(receipt.number);
|
||||
if(block.transactions.length == 0) return;
|
||||
if(block.transactions.length === 0) return;
|
||||
|
||||
let requests = [];
|
||||
for(let i in block.transactions) {
|
||||
|
|
|
@ -11,7 +11,7 @@ const EmptySourceMap = {
|
|||
|
||||
class SourceMap {
|
||||
constructor(sourceMapStringOrOffset, length, id, jump) {
|
||||
if(typeof sourceMapStringOrOffset == 'string') {
|
||||
if(typeof sourceMapStringOrOffset === 'string') {
|
||||
let [offset, length, id, jump] = sourceMapStringOrOffset.split(":");
|
||||
|
||||
this.offset = parseInt(offset, 10);
|
||||
|
@ -46,7 +46,7 @@ class SourceMap {
|
|||
toString(defaultId) {
|
||||
let parts = [this.offset, this.length];
|
||||
|
||||
if(this.id !== undefined && this.id != '') {
|
||||
if(this.id !== undefined && this.id !== '') {
|
||||
parts.push(this.id);
|
||||
} else if(defaultId !== undefined) {
|
||||
parts.push(defaultId);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const async = require('async');
|
||||
const AccountParser = require('../../utils/accountParser');
|
||||
const EmbarkJS = require('embarkjs');
|
||||
|
||||
class Test {
|
||||
constructor(options) {
|
||||
|
@ -46,42 +47,10 @@ class Test {
|
|||
this.blockchainConnector.contractsConfig = this.configObj.contractsConfig;
|
||||
this.blockchainConnector.isWeb3Ready = false;
|
||||
this.blockchainConnector.wait = false;
|
||||
this.blockchainConnector.coverage = this.options.coverage;
|
||||
|
||||
// TODO change this
|
||||
/*if (this.options.coverage) {
|
||||
// Here we patch the sendAsync method on the provider. The goal behind this is to force pure/constant/view calls to become
|
||||
// transactions, so that we can pull in execution traces and account for those executions in code coverage.
|
||||
//
|
||||
// Instead of a simple call, here's what happens:
|
||||
//
|
||||
// 1) A transaction is sent with the same payload, and a pre-defined gas price;
|
||||
// 2) We wait for the transaction to be mined by asking for the receipt;
|
||||
// 3) Once we get the receipt back, we dispatch the real call and pass the original callback;
|
||||
//
|
||||
// This will still allow tests to get the return value from the call and run contracts unmodified.
|
||||
simProvider.realSendAsync = simProvider.sendAsync.bind(simProvider);
|
||||
simProvider.sendAsync = function(payload, cb) {
|
||||
if(payload.method !== 'eth_call') {
|
||||
return simProvider.realSendAsync(payload, cb);
|
||||
}
|
||||
self.events.request('reporter:toggleGasListener');
|
||||
let newParams = Object.assign({}, payload.params[0], {gasPrice: '0x77359400'});
|
||||
let newPayload = {
|
||||
id: payload.id + 1,
|
||||
method: 'eth_sendTransaction',
|
||||
params: [newParams],
|
||||
jsonrpc: payload.jsonrpc
|
||||
};
|
||||
|
||||
simProvider.realSendAsync(newPayload, (_err, response) => {
|
||||
let txHash = response.result;
|
||||
self.web3.eth.getTransactionReceipt(txHash, (_err, _res) => {
|
||||
self.events.request('reporter:toggleGasListener');
|
||||
simProvider.realSendAsync(payload, cb);
|
||||
});
|
||||
});
|
||||
};
|
||||
}*/
|
||||
|
||||
this.blockchainConnector.initWeb3(callback);
|
||||
}
|
||||
|
@ -203,6 +172,12 @@ class Test {
|
|||
function checkDeploymentOpts(next) {
|
||||
self.checkDeploymentOptions(options, next);
|
||||
},
|
||||
function changeGlobalWeb3(next) {
|
||||
self.events.request('blockchain:get', (web3) => {
|
||||
global.web3 = web3;
|
||||
next();
|
||||
});
|
||||
},
|
||||
function compileContracts(next) {
|
||||
if (!self.firstDeployment) {
|
||||
return next();
|
||||
|
@ -242,9 +217,8 @@ class Test {
|
|||
const self = this;
|
||||
async.waterfall([
|
||||
function getConfig(next) {
|
||||
// TODO use events instead of modifying directly
|
||||
self.configObj.contractsConfig = {contracts: config.contracts, versions: self.versions_default};
|
||||
next();
|
||||
self.events.request('config:contractsConfig:set',
|
||||
{contracts: config.contracts, versions: self.versions_default}, next);
|
||||
},
|
||||
function getAccounts(next) {
|
||||
self.events.request('blockchain:getAccounts', (err, accounts) => {
|
||||
|
@ -281,13 +255,19 @@ class Test {
|
|||
self.contracts[contract.className] = {};
|
||||
}
|
||||
|
||||
self.events.request('blockchain:contract:create', {
|
||||
abi: contract.abiDefinition,
|
||||
address: contract.deployedAddress
|
||||
}, (newContract) => {
|
||||
|
||||
self.events.request('blockchain:get', (web3) => {
|
||||
let newContract = new EmbarkJS.Blockchain.Contract({
|
||||
abi: contract.abiDefinition,
|
||||
address: contract.deployedAddress,
|
||||
from: web3.eth.defaultAccount,
|
||||
gas: 6000000,
|
||||
web3: web3
|
||||
});
|
||||
|
||||
if (newContract.options) {
|
||||
newContract.options.from = web3.eth.defaultAccount;
|
||||
newContract.options.data = contract.code;
|
||||
newContract.options.from = accounts[0];
|
||||
if (!newContract.options.data.startsWith('0x')) {
|
||||
newContract.options.data = '0x' + newContract.options.data;
|
||||
}
|
||||
|
@ -295,7 +275,6 @@ class Test {
|
|||
}
|
||||
|
||||
Object.setPrototypeOf(self.contracts[contract.className], newContract);
|
||||
|
||||
eachCb();
|
||||
});
|
||||
}, (err) => {
|
||||
|
|
|
@ -3,3 +3,4 @@ node_modules/
|
|||
dist/
|
||||
config/production/password
|
||||
config/livenet/password
|
||||
coverage/
|
||||
|
|
Loading…
Reference in New Issue