aboutsummaryrefslogtreecommitdiffstats
path: root/packages/dev-utils
diff options
context:
space:
mode:
Diffstat (limited to 'packages/dev-utils')
-rw-r--r--packages/dev-utils/CHANGELOG.md6
-rw-r--r--packages/dev-utils/README.md11
-rw-r--r--packages/dev-utils/package.json1
-rw-r--r--packages/dev-utils/src/blockchain_lifecycle.ts13
-rw-r--r--packages/dev-utils/src/constants.ts3
-rw-r--r--packages/dev-utils/src/coverage.ts22
-rw-r--r--packages/dev-utils/src/env.ts24
-rw-r--r--packages/dev-utils/src/index.ts3
-rw-r--r--packages/dev-utils/src/rpc.ts62
-rw-r--r--packages/dev-utils/src/web3_factory.ts51
-rw-r--r--packages/dev-utils/test/blockchain_lifecycle_test.ts11
-rw-r--r--packages/dev-utils/test/rpc_test.ts19
-rw-r--r--packages/dev-utils/tslint.json5
13 files changed, 135 insertions, 96 deletions
diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md
index ecc5546ae..8193b78ac 100644
--- a/packages/dev-utils/CHANGELOG.md
+++ b/packages/dev-utils/CHANGELOG.md
@@ -1,5 +1,11 @@
# CHANGELOG
+## v0.3.0 - _TBD, 2018_
+
+ * Add coverage subprovider if SOLIDITY_COVERAGE env variable is true (#426)
+ * Refactor `BlockchainLifecycle` to work with in-process ganache (#426)
+ * Remove `RPC` class and move it's logic to `Web3Wrapper` (#426)
+
## v0.2.0 - _February 16, 2018_
* Remove subproviders (#392)
diff --git a/packages/dev-utils/README.md b/packages/dev-utils/README.md
index f7e30df1e..0c4175e35 100644
--- a/packages/dev-utils/README.md
+++ b/packages/dev-utils/README.md
@@ -2,6 +2,17 @@
Dev utils to be shared across 0x projects and packages
+## Configuration
+
+Some env variables might be set to change the behaviour of created web3 providers/instances.
+
+```
+VERBOSE_GANACHE: boolean. Enables verbose Ganache logging. Every request/response payload. Slightly slower, but useful for testing.
+SOLIDITY_COVERAGE: boolean. If set - adds coverage subprovider which intercepts all calls/transactions and can be later used to compute code coverage.
+```
+
+Boolean env variables should be either `true` or `false`. Defaults to `false` if not set.
+
## Install
```bash
diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json
index 8912a7330..f9fc4e619 100644
--- a/packages/dev-utils/package.json
+++ b/packages/dev-utils/package.json
@@ -40,6 +40,7 @@
"typescript": "2.7.1"
},
"dependencies": {
+ "@0xproject/sol-cov": "^0.0.1",
"@0xproject/subproviders": "^0.7.0",
"@0xproject/types": "^0.3.1",
"@0xproject/utils": "^0.4.1",
diff --git a/packages/dev-utils/src/blockchain_lifecycle.ts b/packages/dev-utils/src/blockchain_lifecycle.ts
index c46902f76..3e35de861 100644
--- a/packages/dev-utils/src/blockchain_lifecycle.ts
+++ b/packages/dev-utils/src/blockchain_lifecycle.ts
@@ -1,21 +1,22 @@
-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(web3Wrapper: Web3Wrapper) {
+ this._web3Wrapper = web3Wrapper;
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`);
}
diff --git a/packages/dev-utils/src/constants.ts b/packages/dev-utils/src/constants.ts
index 4f7b4202a..05bcc1638 100644
--- a/packages/dev-utils/src/constants.ts
+++ b/packages/dev-utils/src/constants.ts
@@ -1,5 +1,6 @@
export const constants = {
RPC_URL: 'http://localhost:8545',
RPC_PORT: 8545,
- GAS_ESTIMATE: 1000000,
+ GAS_ESTIMATE: 5000000,
+ TESTRPC_FIRST_ADDRESS: '0x5409ed021d9299bf6814279a6a1411a7e866a631',
};
diff --git a/packages/dev-utils/src/coverage.ts b/packages/dev-utils/src/coverage.ts
new file mode 100644
index 000000000..40bb47e2d
--- /dev/null
+++ b/packages/dev-utils/src/coverage.ts
@@ -0,0 +1,22 @@
+import { CoverageSubprovider } from '@0xproject/sol-cov';
+import * as _ from 'lodash';
+
+import { constants } from './constants';
+
+let coverageSubprovider: CoverageSubprovider;
+
+export const coverage = {
+ getCoverageSubproviderSingleton(): CoverageSubprovider {
+ if (_.isUndefined(coverageSubprovider)) {
+ coverageSubprovider = coverage._getCoverageSubprovider();
+ }
+ return coverageSubprovider;
+ },
+ _getCoverageSubprovider(): CoverageSubprovider {
+ const artifactsPath = './src/artifacts';
+ const contractsPath = './src/contracts';
+ const networkId = 50;
+ const defaultFromAddress = constants.TESTRPC_FIRST_ADDRESS;
+ return new CoverageSubprovider(artifactsPath, contractsPath, networkId, defaultFromAddress);
+ },
+};
diff --git a/packages/dev-utils/src/env.ts b/packages/dev-utils/src/env.ts
new file mode 100644
index 000000000..114dbf4a8
--- /dev/null
+++ b/packages/dev-utils/src/env.ts
@@ -0,0 +1,24 @@
+import * as _ from 'lodash';
+import * as process from 'process';
+
+export enum EnvVars {
+ SolidityCoverage = 'SOLIDITY_COVERAGE',
+ VerboseGanache = 'VERBOSE_GANACHE',
+}
+
+export const env = {
+ parseBoolean(key: string): boolean {
+ let isTrue: boolean;
+ const envVarValue = process.env[key];
+ if (envVarValue === 'true') {
+ isTrue = true;
+ } else if (envVarValue === 'false' || _.isUndefined(envVarValue)) {
+ isTrue = false;
+ } else {
+ throw new Error(
+ `Failed to parse ENV variable ${key} as boolean. Please make sure it's either true or false. Defaults to false`,
+ );
+ }
+ return isTrue;
+ },
+};
diff --git a/packages/dev-utils/src/index.ts b/packages/dev-utils/src/index.ts
index e899ac206..2ff2a2238 100644
--- a/packages/dev-utils/src/index.ts
+++ b/packages/dev-utils/src/index.ts
@@ -1,4 +1,5 @@
-export { RPC } from './rpc';
export { BlockchainLifecycle } from './blockchain_lifecycle';
export { web3Factory } from './web3_factory';
export { constants as devConstants } from './constants';
+export { coverage } from './coverage';
+export { env, EnvVars } from './env';
diff --git a/packages/dev-utils/src/rpc.ts b/packages/dev-utils/src/rpc.ts
deleted file mode 100644
index 47a359263..000000000
--- a/packages/dev-utils/src/rpc.ts
+++ /dev/null
@@ -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;
- }
-}
diff --git a/packages/dev-utils/src/web3_factory.ts b/packages/dev-utils/src/web3_factory.ts
index b0e0e4d3f..6435f0f9a 100644
--- a/packages/dev-utils/src/web3_factory.ts
+++ b/packages/dev-utils/src/web3_factory.ts
@@ -6,9 +6,14 @@
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 { coverage } from './coverage';
+import { env, EnvVars } from './env';
// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
// because they are using the wrong XHR package.
@@ -17,24 +22,52 @@ import { constants } from './constants';
// tslint:disable-next-line:ordered-imports
import * as Web3 from 'web3';
+export interface Web3Config {
+ hasAddresses?: boolean; // default: true
+ shouldUseInProcessGanache?: 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();
+ const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage);
+ if (isCoverageEnabled) {
+ provider.addProvider(coverage.getCoverageSubproviderSingleton());
+ }
+ 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 shouldUseInProcessGanache = !!config.shouldUseInProcessGanache;
+ if (shouldUseInProcessGanache) {
+ provider.addProvider(
+ new GanacheSubprovider({
+ logger,
+ verbose: env.parseBoolean(EnvVars.SolidityCoverage),
+ 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;
},
diff --git a/packages/dev-utils/test/blockchain_lifecycle_test.ts b/packages/dev-utils/test/blockchain_lifecycle_test.ts
index 4fdc53c87..5ed67e012 100644
--- a/packages/dev-utils/test/blockchain_lifecycle_test.ts
+++ b/packages/dev-utils/test/blockchain_lifecycle_test.ts
@@ -3,20 +3,19 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import 'mocha';
-import { BlockchainLifecycle, RPC, web3Factory } from '../src';
+import { BlockchainLifecycle, web3Factory } from '../src';
const expect = chai.expect;
describe('BlockchainLifecycle tests', () => {
- const web3 = web3Factory.create();
- const web3Wrapper = new Web3Wrapper(web3.currentProvider);
- const rpc = new RPC();
- const blockchainLifecycle = new BlockchainLifecycle();
+ const web3Provider = web3Factory.getRpcProvider();
+ const web3Wrapper = new Web3Wrapper(web3Provider);
+ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('#startAsync/revertAsync', () => {
it('reverts changes in between', async () => {
const blockNumberBefore = await web3Wrapper.getBlockNumberAsync();
await blockchainLifecycle.startAsync();
- await rpc.mineBlockAsync();
+ await web3Wrapper.mineBlockAsync();
const blockNumberAfter = await web3Wrapper.getBlockNumberAsync();
expect(blockNumberAfter).to.be.equal(blockNumberBefore + 1);
await blockchainLifecycle.revertAsync();
diff --git a/packages/dev-utils/test/rpc_test.ts b/packages/dev-utils/test/rpc_test.ts
index 2f0e5ff7f..1bdea3613 100644
--- a/packages/dev-utils/test/rpc_test.ts
+++ b/packages/dev-utils/test/rpc_test.ts
@@ -3,18 +3,17 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import 'mocha';
-import { RPC, web3Factory } from '../src';
+import { web3Factory } from '../src';
const expect = chai.expect;
describe('RPC tests', () => {
- const web3 = web3Factory.create();
- const web3Wrapper = new Web3Wrapper(web3.currentProvider);
- const rpc = new RPC();
+ const web3Provider = web3Factory.getRpcProvider();
+ const web3Wrapper = new Web3Wrapper(web3Provider);
describe('#mineBlockAsync', () => {
it('increases block number when called', async () => {
const blockNumberBefore = await web3Wrapper.getBlockNumberAsync();
- await rpc.mineBlockAsync();
+ await web3Wrapper.mineBlockAsync();
const blockNumberAfter = await web3Wrapper.getBlockNumberAsync();
expect(blockNumberAfter).to.be.equal(blockNumberBefore + 1);
});
@@ -23,8 +22,8 @@ describe('RPC tests', () => {
it('increases time when called', async () => {
const TIME_DELTA = 1000;
const blockTimestampBefore = await web3Wrapper.getBlockTimestampAsync(BlockParamLiteral.Latest);
- await rpc.increaseTimeAsync(TIME_DELTA);
- await rpc.mineBlockAsync();
+ await web3Wrapper.increaseTimeAsync(TIME_DELTA);
+ await web3Wrapper.mineBlockAsync();
const blockTimestampAfter = await web3Wrapper.getBlockTimestampAsync(BlockParamLiteral.Latest);
expect(blockTimestampAfter).to.be.at.least(blockTimestampBefore + TIME_DELTA);
});
@@ -32,9 +31,9 @@ describe('RPC tests', () => {
describe('#takeSnapshotAsync/revertSnapshotAsync', () => {
it('reverts changes in between', async () => {
const blockNumberBefore = await web3Wrapper.getBlockNumberAsync();
- const snapshotId = await rpc.takeSnapshotAsync();
- await rpc.mineBlockAsync();
- await rpc.revertSnapshotAsync(snapshotId);
+ const snapshotId = await web3Wrapper.takeSnapshotAsync();
+ await web3Wrapper.mineBlockAsync();
+ await web3Wrapper.revertSnapshotAsync(snapshotId);
const blockNumberAfter = await web3Wrapper.getBlockNumberAsync();
expect(blockNumberAfter).to.be.equal(blockNumberBefore);
});
diff --git a/packages/dev-utils/tslint.json b/packages/dev-utils/tslint.json
index ffaefe83a..015dce851 100644
--- a/packages/dev-utils/tslint.json
+++ b/packages/dev-utils/tslint.json
@@ -1,3 +1,6 @@
{
- "extends": ["@0xproject/tslint-config"]
+ "extends": ["@0xproject/tslint-config"],
+ "rules": {
+ "completed-docs": false
+ }
}