Add sol-cover implementation
This commit is contained in:
@@ -1,21 +1,24 @@
|
||||
import { RPC } from './rpc';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export class BlockchainLifecycle {
|
||||
private _rpc: RPC;
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
private _snapshotIdsStack: number[];
|
||||
constructor() {
|
||||
this._rpc = new RPC();
|
||||
constructor(web3Orweb3Wrapper: Web3Wrapper | Web3) {
|
||||
this._web3Wrapper = (web3Orweb3Wrapper as Web3Wrapper).isZeroExWeb3Wrapper
|
||||
? (web3Orweb3Wrapper as Web3Wrapper)
|
||||
: new Web3Wrapper((web3Orweb3Wrapper as Web3).currentProvider);
|
||||
this._snapshotIdsStack = [];
|
||||
}
|
||||
// TODO: In order to run these tests on an actual node, we should check if we are running against
|
||||
// TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
|
||||
public async startAsync(): Promise<void> {
|
||||
const snapshotId = await this._rpc.takeSnapshotAsync();
|
||||
const snapshotId = await this._web3Wrapper.takeSnapshotAsync();
|
||||
this._snapshotIdsStack.push(snapshotId);
|
||||
}
|
||||
public async revertAsync(): Promise<void> {
|
||||
const snapshotId = this._snapshotIdsStack.pop() as number;
|
||||
const didRevert = await this._rpc.revertSnapshotAsync(snapshotId);
|
||||
const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId);
|
||||
if (!didRevert) {
|
||||
throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
export const constants = {
|
||||
RPC_URL: 'http://localhost:8545',
|
||||
RPC_PORT: 8545,
|
||||
GAS_ESTIMATE: 1000000,
|
||||
GAS_ESTIMATE: 5000000,
|
||||
};
|
||||
|
14
packages/dev-utils/src/coverage.ts
Normal file
14
packages/dev-utils/src/coverage.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { CoverageSubprovider } from '@0xproject/sol-cov';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
let coverageSubprovider: CoverageSubprovider;
|
||||
|
||||
export function getCoverageSubprovider(): CoverageSubprovider {
|
||||
if (_.isUndefined(coverageSubprovider)) {
|
||||
const artifactsPath = './src/artifacts';
|
||||
const contractsPath = './src/contracts';
|
||||
const networkId = 50;
|
||||
coverageSubprovider = new CoverageSubprovider(artifactsPath, contractsPath, networkId);
|
||||
}
|
||||
return coverageSubprovider;
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
export { RPC } from './rpc';
|
||||
export { BlockchainLifecycle } from './blockchain_lifecycle';
|
||||
export { web3Factory } from './web3_factory';
|
||||
export { constants as devConstants } from './constants';
|
||||
export { getCoverageSubprovider } from './coverage';
|
||||
|
@@ -1,62 +0,0 @@
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as request from 'request-promise-native';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
export class RPC {
|
||||
private _url: string;
|
||||
private _id: number;
|
||||
constructor() {
|
||||
this._url = constants.RPC_URL;
|
||||
this._id = 0;
|
||||
}
|
||||
public async takeSnapshotAsync(): Promise<number> {
|
||||
const method = 'evm_snapshot';
|
||||
const params: any[] = [];
|
||||
const payload = this._toPayload(method, params);
|
||||
const snapshotIdHex = await this._sendAsync(payload);
|
||||
const snapshotId = ethUtil.bufferToInt(ethUtil.toBuffer(snapshotIdHex));
|
||||
return snapshotId;
|
||||
}
|
||||
public async revertSnapshotAsync(snapshotId: number): Promise<boolean> {
|
||||
const method = 'evm_revert';
|
||||
const params = [snapshotId];
|
||||
const payload = this._toPayload(method, params);
|
||||
const didRevert = await this._sendAsync(payload);
|
||||
return didRevert;
|
||||
}
|
||||
public async increaseTimeAsync(time: number) {
|
||||
const method = 'evm_increaseTime';
|
||||
const params = [time];
|
||||
const payload = this._toPayload(method, params);
|
||||
return this._sendAsync(payload);
|
||||
}
|
||||
public async mineBlockAsync(): Promise<void> {
|
||||
const method = 'evm_mine';
|
||||
const params: any[] = [];
|
||||
const payload = this._toPayload(method, params);
|
||||
await this._sendAsync(payload);
|
||||
}
|
||||
private _toPayload(method: string, params: any[] = []): string {
|
||||
const payload = JSON.stringify({
|
||||
id: this._id,
|
||||
method,
|
||||
params,
|
||||
});
|
||||
this._id += 1;
|
||||
return payload;
|
||||
}
|
||||
private async _sendAsync(payload: string): Promise<any> {
|
||||
const opts = {
|
||||
method: 'POST',
|
||||
uri: this._url,
|
||||
body: payload,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
};
|
||||
const bodyString = await request(opts);
|
||||
const body = JSON.parse(bodyString);
|
||||
return body.result;
|
||||
}
|
||||
}
|
@@ -6,9 +6,13 @@
|
||||
import ProviderEngine = require('web3-provider-engine');
|
||||
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
|
||||
import { EmptyWalletSubprovider, FakeGasEstimateSubprovider } from '@0xproject/subproviders';
|
||||
import { EmptyWalletSubprovider, FakeGasEstimateSubprovider, GanacheSubprovider } from '@0xproject/subproviders';
|
||||
import * as fs from 'fs';
|
||||
import * as _ from 'lodash';
|
||||
import * as process from 'process';
|
||||
|
||||
import { constants } from './constants';
|
||||
import { getCoverageSubprovider } from './coverage';
|
||||
|
||||
// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
|
||||
// because they are using the wrong XHR package.
|
||||
@@ -17,24 +21,51 @@ import { constants } from './constants';
|
||||
// tslint:disable-next-line:ordered-imports
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export interface Web3Config {
|
||||
hasAddresses?: boolean; // default: true
|
||||
useInProcessGanache?: boolean; // default: false
|
||||
}
|
||||
|
||||
export const web3Factory = {
|
||||
create(hasAddresses: boolean = true): Web3 {
|
||||
const provider = this.getRpcProvider(hasAddresses);
|
||||
create(config: Web3Config = {}): Web3 {
|
||||
const provider = this.getRpcProvider(config);
|
||||
const web3 = new Web3();
|
||||
web3.setProvider(provider);
|
||||
return web3;
|
||||
},
|
||||
getRpcProvider(hasAddresses: boolean = true): Web3.Provider {
|
||||
getRpcProvider(config: Web3Config = {}): Web3.Provider {
|
||||
const provider = new ProviderEngine();
|
||||
if (process.env.COVERAGE) {
|
||||
provider.addProvider(getCoverageSubprovider());
|
||||
}
|
||||
const hasAddresses = _.isUndefined(config.hasAddresses) || config.hasAddresses;
|
||||
if (!hasAddresses) {
|
||||
provider.addProvider(new EmptyWalletSubprovider());
|
||||
}
|
||||
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_ESTIMATE));
|
||||
provider.addProvider(
|
||||
new RpcSubprovider({
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}),
|
||||
);
|
||||
const logger = {
|
||||
log: (arg: any) => {
|
||||
fs.appendFileSync('ganache.log', `${arg}\n`);
|
||||
},
|
||||
};
|
||||
const useInProcessGanache = config.useInProcessGanache;
|
||||
if (useInProcessGanache) {
|
||||
provider.addProvider(
|
||||
new GanacheSubprovider({
|
||||
logger,
|
||||
verbose: process.env.VERBOSE_GANACHE,
|
||||
port: 8545,
|
||||
networkId: 50,
|
||||
mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic',
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
provider.addProvider(
|
||||
new RpcSubprovider({
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}),
|
||||
);
|
||||
}
|
||||
provider.start();
|
||||
return provider;
|
||||
},
|
||||
|
Reference in New Issue
Block a user