aboutsummaryrefslogtreecommitdiffstats
path: root/packages/sol-cov
diff options
context:
space:
mode:
authorLeonid Logvinov <logvinov.leon@gmail.com>2019-01-08 19:23:33 +0800
committerLeonid Logvinov <logvinov.leon@gmail.com>2019-01-08 21:48:06 +0800
commit2c974b5f3ffa0e9736000273e39cdeee4a251b94 (patch)
treea1772f93d796e3b4ba7a988194a44a3e8bcd6d31 /packages/sol-cov
parent0ac36cef288deecd36caa601c53d13517eef5ca8 (diff)
downloaddexon-sol-tools-2c974b5f3ffa0e9736000273e39cdeee4a251b94.tar
dexon-sol-tools-2c974b5f3ffa0e9736000273e39cdeee4a251b94.tar.gz
dexon-sol-tools-2c974b5f3ffa0e9736000273e39cdeee4a251b94.tar.bz2
dexon-sol-tools-2c974b5f3ffa0e9736000273e39cdeee4a251b94.tar.lz
dexon-sol-tools-2c974b5f3ffa0e9736000273e39cdeee4a251b94.tar.xz
dexon-sol-tools-2c974b5f3ffa0e9736000273e39cdeee4a251b94.tar.zst
dexon-sol-tools-2c974b5f3ffa0e9736000273e39cdeee4a251b94.zip
Refactor out sol-cov, sol-profiler and sol-trace into their separate packages
Diffstat (limited to 'packages/sol-cov')
-rw-r--r--packages/sol-cov/.npmignore6
-rw-r--r--packages/sol-cov/CHANGELOG.json389
-rw-r--r--packages/sol-cov/CHANGELOG.md158
-rw-r--r--packages/sol-cov/README.md75
-rw-r--r--packages/sol-cov/compiler.json18
-rw-r--r--packages/sol-cov/coverage/.gitkeep0
-rw-r--r--packages/sol-cov/package.json87
-rw-r--r--packages/sol-cov/src/artifact_adapters/abstract_artifact_adapter.ts5
-rw-r--r--packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts61
-rw-r--r--packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts88
-rw-r--r--packages/sol-cov/src/ast_visitor.ts168
-rw-r--r--packages/sol-cov/src/collect_coverage_entries.ts41
-rw-r--r--packages/sol-cov/src/constants.ts8
-rw-r--r--packages/sol-cov/src/coverage_subprovider.ts146
-rw-r--r--packages/sol-cov/src/get_source_range_snippet.ts180
-rw-r--r--packages/sol-cov/src/globals.d.ts7
-rw-r--r--packages/sol-cov/src/index.ts25
-rw-r--r--packages/sol-cov/src/instructions.ts23
-rw-r--r--packages/sol-cov/src/profiler_subprovider.ts91
-rw-r--r--packages/sol-cov/src/revert_trace.ts90
-rw-r--r--packages/sol-cov/src/revert_trace_subprovider.ts163
-rw-r--r--packages/sol-cov/src/source_maps.ts81
-rw-r--r--packages/sol-cov/src/trace.ts99
-rw-r--r--packages/sol-cov/src/trace_collection_subprovider.ts188
-rw-r--r--packages/sol-cov/src/trace_collector.ts93
-rw-r--r--packages/sol-cov/src/trace_info_subprovider.ts59
-rw-r--r--packages/sol-cov/src/types.ts126
-rw-r--r--packages/sol-cov/src/utils.ts87
-rw-r--r--packages/sol-cov/test/collect_coverage_entries_test.ts155
-rw-r--r--packages/sol-cov/test/fixtures/contracts/AllSolidityFeatures.sol413
-rw-r--r--packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol11
-rw-r--r--packages/sol-cov/test/fixtures/contracts/Simplest.sol2
-rw-r--r--packages/sol-cov/test/fixtures/contracts/SolcovIgnore.sol22
-rw-r--r--packages/sol-cov/test/instructions_test.ts19
-rw-r--r--packages/sol-cov/test/sol_compiler_artifact_adapter_test.ts29
-rw-r--r--packages/sol-cov/test/source_maps_test.ts71
-rw-r--r--packages/sol-cov/test/trace_test.ts55
-rw-r--r--packages/sol-cov/test/utils_test.ts53
-rw-r--r--packages/sol-cov/tsconfig.json8
-rw-r--r--packages/sol-cov/tslint.json6
-rw-r--r--packages/sol-cov/typedoc-tsconfig.json7
41 files changed, 0 insertions, 3413 deletions
diff --git a/packages/sol-cov/.npmignore b/packages/sol-cov/.npmignore
deleted file mode 100644
index 037786e46..000000000
--- a/packages/sol-cov/.npmignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.*
-yarn-error.log
-/src/
-/scripts/
-tsconfig.json
-/lib/src/monorepo_scripts/
diff --git a/packages/sol-cov/CHANGELOG.json b/packages/sol-cov/CHANGELOG.json
deleted file mode 100644
index b7973c135..000000000
--- a/packages/sol-cov/CHANGELOG.json
+++ /dev/null
@@ -1,389 +0,0 @@
-[
- {
- "version": "2.1.16",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1544739608
- },
- {
- "version": "2.1.15",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1544570656
- },
- {
- "timestamp": 1543401373,
- "version": "2.1.14",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542821676,
- "version": "2.1.13",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542208198,
- "version": "2.1.12",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542134075,
- "version": "2.1.11",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1542028948,
- "version": "2.1.10",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "2.1.9",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1541740904
- },
- {
- "version": "2.1.8",
- "changes": [
- {
- "note": "Make @types/solidity-parser-antlr a 'dependency' so it's available to users of the library",
- "pr": 1105
- }
- ],
- "timestamp": 1539871071
- },
- {
- "version": "2.1.7",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1538693146
- },
- {
- "timestamp": 1538157789,
- "version": "2.1.6",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537907159,
- "version": "2.1.5",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537875740,
- "version": "2.1.4",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1537541580,
- "version": "2.1.3",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1536142250,
- "version": "2.1.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1535377027,
- "version": "2.1.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "2.1.0",
- "changes": [
- {
- "note":
- "Export types: `JSONRPCRequestPayload`, `Provider`, `JSONRPCErrorCallback`, `JSONRPCResponsePayload`, `JSONRPCRequestPayloadWithMethod`, `NextCallback`, `ErrorCallback`, `OnNextCompleted` and `Callback`",
- "pr": 924
- }
- ],
- "timestamp": 1535133899
- },
- {
- "version": "2.0.0",
- "changes": [
- {
- "note":
- "Fix a bug when eth_call coverage was not computed because of silent schema validation failures",
- "pr": 938
- },
- {
- "note": "Make `TruffleArtifactAdapter` read the `truffle.js` config for `solc` settings",
- "pr": 938
- },
- {
- "note":
- "Change the first param of `TruffleArtifactAdapter` to be the `projectRoot` instead of `sourcesDir`",
- "pr": 938
- },
- {
- "note":
- "Throw a helpful error message if truffle artifacts were generated with a different solc version than the one passed in",
- "pr": 938
- }
- ],
- "timestamp": 1534210131
- },
- {
- "version": "1.0.3",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ],
- "timestamp": 1532619515
- },
- {
- "timestamp": 1532605697,
- "version": "1.0.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1532357734,
- "version": "1.0.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1532043000,
- "version": "1.0.0",
- "changes": [
- {
- "note":
- "Add artifact adapter as a parameter for `CoverageSubprovider`. Export `AbstractArtifactAdapter`",
- "pr": 589
- },
- {
- "note": "Implement `SolCompilerArtifactAdapter` and `TruffleArtifactAdapter`",
- "pr": 589
- },
- {
- "note": "Properly parse multi-level traces",
- "pr": 589
- },
- {
- "note": "Add support for solidity libraries",
- "pr": 589
- },
- {
- "note": "Fixed a bug causing `RegExp` to crash if contract code is longer that 32767 characters",
- "pr": 675
- },
- {
- "note": "Fixed a bug caused by Geth debug trace depth being 1indexed",
- "pr": 675
- },
- {
- "note": "Fixed a bug when the tool crashed on empty traces",
- "pr": 675
- },
- {
- "note": "Use `BlockchainLifecycle` to support reverts on Geth",
- "pr": 675
- },
- {
- "note": "Add `ProfilerSubprovider` as a hacky way to profile code using coverage tools",
- "pr": 675
- },
- {
- "note": "Collect traces from `estimate_gas` calls",
- "pr": 675
- },
- {
- "note": "Fix a race condition caused by not awaiting the transaction before getting a trace",
- "pr": 675
- },
- {
- "note": "Add `start`/`stop` functionality to `CoverageSubprovider` and `ProfilerSubprovider`",
- "pr": 675
- },
- {
- "note": "Skip interface artifacts with a warning instead of failing",
- "pr": 675
- },
- {
- "note": "Fix `solcVersion` regex in parameter validation",
- "pr": 690
- },
- {
- "note":
- "Fix a bug when in `TruffleArtifactsAdapter` causing it to throw if `compiler.json` is not there",
- "pr": 690
- },
- {
- "note": "HUGE perf improvements",
- "pr": 690
- },
- {
- "note": "Create `RevertTraceSubprovider` which prints a stack trace when a `REVERT` is detected",
- "pr": 705
- },
- {
- "note": "Add source code snippets to stack traces printed by `RevertTraceSubprovider`",
- "pr": 725
- }
- ]
- },
- {
- "timestamp": 1531919263,
- "version": "0.1.3",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1531149657,
- "version": "0.1.2",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1529397769,
- "version": "0.1.1",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "version": "0.1.0",
- "changes": [
- {
- "note": "Incorrect publish that was unpublished"
- }
- ],
- "timestamp": 1527810075
- },
- {
- "timestamp": 1527009134,
- "version": "0.0.11",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1525477860,
- "version": "0.0.10",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1525428773,
- "version": "0.0.9",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1524044013,
- "version": "0.0.8",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1523462196,
- "version": "0.0.7",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1522673609,
- "version": "0.0.6",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- },
- {
- "timestamp": 1522658513,
- "version": "0.0.5",
- "changes": [
- {
- "note": "Dependencies updated"
- }
- ]
- }
-]
diff --git a/packages/sol-cov/CHANGELOG.md b/packages/sol-cov/CHANGELOG.md
deleted file mode 100644
index 879ef9c95..000000000
--- a/packages/sol-cov/CHANGELOG.md
+++ /dev/null
@@ -1,158 +0,0 @@
-<!--
-changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
-Edit the package's CHANGELOG.json file only.
--->
-
-CHANGELOG
-
-## v2.1.16 - _December 13, 2018_
-
- * Dependencies updated
-
-## v2.1.15 - _December 11, 2018_
-
- * Dependencies updated
-
-## v2.1.14 - _November 28, 2018_
-
- * Dependencies updated
-
-## v2.1.13 - _November 21, 2018_
-
- * Dependencies updated
-
-## v2.1.12 - _November 14, 2018_
-
- * Dependencies updated
-
-## v2.1.11 - _November 13, 2018_
-
- * Dependencies updated
-
-## v2.1.10 - _November 12, 2018_
-
- * Dependencies updated
-
-## v2.1.9 - _November 9, 2018_
-
- * Dependencies updated
-
-## v2.1.8 - _October 18, 2018_
-
- * Make @types/solidity-parser-antlr a 'dependency' so it's available to users of the library (#1105)
-
-## v2.1.7 - _October 4, 2018_
-
- * Dependencies updated
-
-## v2.1.6 - _September 28, 2018_
-
- * Dependencies updated
-
-## v2.1.5 - _September 25, 2018_
-
- * Dependencies updated
-
-## v2.1.4 - _September 25, 2018_
-
- * Dependencies updated
-
-## v2.1.3 - _September 21, 2018_
-
- * Dependencies updated
-
-## v2.1.2 - _September 5, 2018_
-
- * Dependencies updated
-
-## v2.1.1 - _August 27, 2018_
-
- * Dependencies updated
-
-## v2.1.0 - _August 24, 2018_
-
- * Export types: `JSONRPCRequestPayload`, `Provider`, `JSONRPCErrorCallback`, `JSONRPCResponsePayload`, `JSONRPCRequestPayloadWithMethod`, `NextCallback`, `ErrorCallback`, `OnNextCompleted` and `Callback` (#924)
-
-## v2.0.0 - _August 14, 2018_
-
- * Fix a bug when eth_call coverage was not computed because of silent schema validation failures (#938)
- * Make `TruffleArtifactAdapter` read the `truffle.js` config for `solc` settings (#938)
- * Change the first param of `TruffleArtifactAdapter` to be the `projectRoot` instead of `sourcesDir` (#938)
- * Throw a helpful error message if truffle artifacts were generated with a different solc version than the one passed in (#938)
-
-## v1.0.3 - _July 26, 2018_
-
- * Dependencies updated
-
-## v1.0.2 - _July 26, 2018_
-
- * Dependencies updated
-
-## v1.0.1 - _July 23, 2018_
-
- * Dependencies updated
-
-## v1.0.0 - _July 19, 2018_
-
- * Add artifact adapter as a parameter for `CoverageSubprovider`. Export `AbstractArtifactAdapter` (#589)
- * Implement `SolCompilerArtifactAdapter` and `TruffleArtifactAdapter` (#589)
- * Properly parse multi-level traces (#589)
- * Add support for solidity libraries (#589)
- * Fixed a bug causing `RegExp` to crash if contract code is longer that 32767 characters (#675)
- * Fixed a bug caused by Geth debug trace depth being 1indexed (#675)
- * Fixed a bug when the tool crashed on empty traces (#675)
- * Use `BlockchainLifecycle` to support reverts on Geth (#675)
- * Add `ProfilerSubprovider` as a hacky way to profile code using coverage tools (#675)
- * Collect traces from `estimate_gas` calls (#675)
- * Fix a race condition caused by not awaiting the transaction before getting a trace (#675)
- * Add `start`/`stop` functionality to `CoverageSubprovider` and `ProfilerSubprovider` (#675)
- * Skip interface artifacts with a warning instead of failing (#675)
- * Fix `solcVersion` regex in parameter validation (#690)
- * Fix a bug when in `TruffleArtifactsAdapter` causing it to throw if `compiler.json` is not there (#690)
- * HUGE perf improvements (#690)
- * Create `RevertTraceSubprovider` which prints a stack trace when a `REVERT` is detected (#705)
- * Add source code snippets to stack traces printed by `RevertTraceSubprovider` (#725)
-
-## v0.1.3 - _July 18, 2018_
-
- * Dependencies updated
-
-## v0.1.2 - _July 9, 2018_
-
- * Dependencies updated
-
-## v0.1.1 - _June 19, 2018_
-
- * Dependencies updated
-
-## v0.1.0 - _May 31, 2018_
-
- * Incorrect publish that was unpublished
-
-## v0.0.11 - _May 22, 2018_
-
- * Dependencies updated
-
-## v0.0.10 - _May 4, 2018_
-
- * Dependencies updated
-
-## v0.0.9 - _May 4, 2018_
-
- * Dependencies updated
-
-## v0.0.8 - _April 18, 2018_
-
- * Dependencies updated
-
-## v0.0.7 - _April 11, 2018_
-
- * Dependencies updated
-
-## v0.0.6 - _April 2, 2018_
-
- * Dependencies updated
-
-## v0.0.5 - _April 2, 2018_
-
- * Dependencies updated
diff --git a/packages/sol-cov/README.md b/packages/sol-cov/README.md
deleted file mode 100644
index 31d73dc63..000000000
--- a/packages/sol-cov/README.md
+++ /dev/null
@@ -1,75 +0,0 @@
-## @0x/sol-cov
-
-A Solidity code coverage tool.
-
-### Read the [Documentation](https://0xproject.com/docs/sol-cov).
-
-## Installation
-
-```bash
-yarn add @0x/sol-cov
-```
-
-**Import**
-
-```javascript
-import { CoverageSubprovider } from '@0x/sol-cov';
-```
-
-or
-
-```javascript
-var CoverageSubprovider = require('@0x/sol-cov').CoverageSubprovider;
-```
-
-## Contributing
-
-We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
-
-Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
-
-### Install dependencies
-
-If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
-
-```bash
-yarn config set workspaces-experimental true
-```
-
-Then install dependencies
-
-```bash
-yarn install
-```
-
-### Build
-
-To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
-
-```bash
-PKG=@0x/sol-cov yarn build
-```
-
-Or continuously rebuild on change:
-
-```bash
-PKG=@0x/sol-cov yarn watch
-```
-
-### Clean
-
-```bash
-yarn clean
-```
-
-### Lint
-
-```bash
-yarn lint
-```
-
-### Run Tests
-
-```bash
-yarn test
-```
diff --git a/packages/sol-cov/compiler.json b/packages/sol-cov/compiler.json
deleted file mode 100644
index a6a0c6d3a..000000000
--- a/packages/sol-cov/compiler.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "contracts": ["SimpleStorage"],
- "contractsDir": "test/fixtures/contracts",
- "artifactsDir": "test/fixtures/artifacts",
- "compilerSettings": {
- "outputSelection": {
- "*": {
- "*": [
- "abi",
- "evm.bytecode.object",
- "evm.bytecode.sourceMap",
- "evm.deployedBytecode.object",
- "evm.deployedBytecode.sourceMap"
- ]
- }
- }
- }
-}
diff --git a/packages/sol-cov/coverage/.gitkeep b/packages/sol-cov/coverage/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
--- a/packages/sol-cov/coverage/.gitkeep
+++ /dev/null
diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json
deleted file mode 100644
index 3ade51c80..000000000
--- a/packages/sol-cov/package.json
+++ /dev/null
@@ -1,87 +0,0 @@
-{
- "name": "@0x/sol-cov",
- "version": "2.1.16",
- "engines": {
- "node": ">=6.12"
- },
- "description": "Generate coverage reports for Solidity code",
- "main": "lib/src/index.js",
- "types": "lib/src/index.d.ts",
- "scripts": {
- "build": "yarn pre_build && tsc -b",
- "build:ci": "yarn build",
- "pre_build": "run-s copy_test_fixtures",
- "lint": "tslint --format stylish --project .",
- "test": "run-s compile_test run_mocha",
- "rebuild_and_test": "run-s clean build test",
- "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
- "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
- "test:circleci": "yarn test:coverage",
- "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
- "clean": "shx rm -rf lib test/fixtures/artifacts src/artifacts generated_docs",
- "copy_test_fixtures": "copyfiles 'test/fixtures/**/*' ./lib",
- "compile_test": "sol-compiler compile",
- "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
- },
- "config": {
- "postpublish": {
- "assets": [],
- "docOmitExports": [
- "ProfilerSubprovider",
- "RevertTraceSubprovider"
- ]
- }
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/0xProject/0x.js.git"
- },
- "license": "Apache-2.0",
- "bugs": {
- "url": "https://github.com/0xProject/0x.js/issues"
- },
- "homepage": "https://github.com/0xProject/0x.js/packages/sol-cov/README.md",
- "dependencies": {
- "@0x/dev-utils": "^1.0.21",
- "@0x/sol-compiler": "^1.1.16",
- "@0x/subproviders": "^2.1.8",
- "@0x/typescript-typings": "^3.0.6",
- "@0x/utils": "^2.0.8",
- "@0x/web3-wrapper": "^3.2.1",
- "@types/solidity-parser-antlr": "^0.2.0",
- "ethereum-types": "^1.1.4",
- "ethereumjs-util": "^5.1.1",
- "glob": "^7.1.2",
- "istanbul": "^0.4.5",
- "lodash": "^4.17.5",
- "loglevel": "^1.6.1",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.6.2",
- "semaphore-async-await": "^1.5.1",
- "solidity-parser-antlr": "^0.2.12"
- },
- "devDependencies": {
- "@0x/tslint-config": "^2.0.0",
- "@types/istanbul": "^0.4.30",
- "@types/loglevel": "^1.5.3",
- "@types/mkdirp": "^0.5.1",
- "@types/mocha": "^2.2.42",
- "@types/node": "*",
- "@types/rimraf": "^2.0.2",
- "chai": "^4.0.1",
- "copyfiles": "^2.0.0",
- "dirty-chai": "^2.0.1",
- "make-promises-safe": "^1.1.0",
- "mocha": "^4.1.0",
- "npm-run-all": "^4.1.2",
- "nyc": "^11.0.1",
- "shx": "^0.2.2",
- "sinon": "^4.0.0",
- "tslint": "5.11.0",
- "typedoc": "0.13.0",
- "typescript": "3.0.1"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/packages/sol-cov/src/artifact_adapters/abstract_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/abstract_artifact_adapter.ts
deleted file mode 100644
index fcc6562ad..000000000
--- a/packages/sol-cov/src/artifact_adapters/abstract_artifact_adapter.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { ContractData } from '../types';
-
-export abstract class AbstractArtifactAdapter {
- public abstract async collectContractsDataAsync(): Promise<ContractData[]>;
-}
diff --git a/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts
deleted file mode 100644
index 57391abbe..000000000
--- a/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { logUtils } from '@0x/utils';
-import { CompilerOptions, ContractArtifact } from 'ethereum-types';
-import * as fs from 'fs';
-import * as glob from 'glob';
-import * as _ from 'lodash';
-import * as path from 'path';
-
-import { ContractData } from '../types';
-
-import { AbstractArtifactAdapter } from './abstract_artifact_adapter';
-
-const CONFIG_FILE = 'compiler.json';
-
-export class SolCompilerArtifactAdapter extends AbstractArtifactAdapter {
- private readonly _artifactsPath: string;
- private readonly _sourcesPath: string;
- /**
- * Instantiates a SolCompilerArtifactAdapter
- * @param artifactsPath Path to your artifacts directory
- * @param sourcesPath Path to your contract sources directory
- */
- constructor(artifactsPath?: string, sourcesPath?: string) {
- super();
- const config: CompilerOptions = fs.existsSync(CONFIG_FILE)
- ? JSON.parse(fs.readFileSync(CONFIG_FILE).toString())
- : {};
- if (_.isUndefined(artifactsPath) && _.isUndefined(config.artifactsDir)) {
- throw new Error(`artifactsDir not found in ${CONFIG_FILE}`);
- }
- this._artifactsPath = (artifactsPath || config.artifactsDir) as string;
- if (_.isUndefined(sourcesPath) && _.isUndefined(config.contractsDir)) {
- throw new Error(`contractsDir not found in ${CONFIG_FILE}`);
- }
- this._sourcesPath = (sourcesPath || config.contractsDir) as string;
- }
- public async collectContractsDataAsync(): Promise<ContractData[]> {
- const artifactsGlob = `${this._artifactsPath}/**/*.json`;
- const artifactFileNames = glob.sync(artifactsGlob, { absolute: true });
- const contractsData: ContractData[] = [];
- for (const artifactFileName of artifactFileNames) {
- const artifact: ContractArtifact = JSON.parse(fs.readFileSync(artifactFileName).toString());
- if (_.isUndefined(artifact.compilerOutput.evm)) {
- logUtils.warn(`${artifactFileName} doesn't contain bytecode. Skipping...`);
- continue;
- }
- let sources = _.keys(artifact.sources);
- sources = _.map(sources, relativeFilePath => path.resolve(this._sourcesPath, relativeFilePath));
- const sourceCodes = _.map(sources, (source: string) => fs.readFileSync(source).toString());
- const contractData = {
- sourceCodes,
- sources,
- bytecode: artifact.compilerOutput.evm.bytecode.object,
- sourceMap: artifact.compilerOutput.evm.bytecode.sourceMap,
- runtimeBytecode: artifact.compilerOutput.evm.deployedBytecode.object,
- sourceMapRuntime: artifact.compilerOutput.evm.deployedBytecode.sourceMap,
- };
- contractsData.push(contractData);
- }
- return contractsData;
- }
-}
diff --git a/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts
deleted file mode 100644
index f064911d3..000000000
--- a/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import { Compiler, CompilerOptions } from '@0x/sol-compiler';
-import * as fs from 'fs';
-import * as glob from 'glob';
-import * as path from 'path';
-
-import { ContractData } from '../types';
-
-import { AbstractArtifactAdapter } from './abstract_artifact_adapter';
-import { SolCompilerArtifactAdapter } from './sol_compiler_artifact_adapter';
-
-const DEFAULT_TRUFFLE_ARTIFACTS_DIR = './build/contracts';
-
-interface TruffleConfig {
- solc?: any;
- contracts_build_directory?: string;
-}
-
-export class TruffleArtifactAdapter extends AbstractArtifactAdapter {
- private readonly _solcVersion: string;
- private readonly _projectRoot: string;
- /**
- * Instantiates a TruffleArtifactAdapter
- * @param projectRoot Path to the truffle project's root directory
- * @param solcVersion Solidity version with which to compile all the contracts
- */
- constructor(projectRoot: string, solcVersion: string) {
- super();
- this._solcVersion = solcVersion;
- this._projectRoot = projectRoot;
- }
- public async collectContractsDataAsync(): Promise<ContractData[]> {
- const artifactsDir = '.0x-artifacts';
- const contractsDir = path.join(this._projectRoot, 'contracts');
- const truffleConfig = this._getTruffleConfig();
- const solcConfig = truffleConfig.solc || {};
- const truffleArtifactsDirectory = truffleConfig.contracts_build_directory || DEFAULT_TRUFFLE_ARTIFACTS_DIR;
- this._assertSolidityVersionIsCorrect(truffleArtifactsDirectory);
- const compilerOptions: CompilerOptions = {
- contractsDir,
- artifactsDir,
- compilerSettings: {
- ...solcConfig,
- outputSelection: {
- ['*']: {
- ['*']: ['abi', 'evm.bytecode.object', 'evm.deployedBytecode.object'],
- },
- },
- },
- contracts: '*',
- solcVersion: this._solcVersion,
- };
- const compiler = new Compiler(compilerOptions);
- await compiler.compileAsync();
- const solCompilerArtifactAdapter = new SolCompilerArtifactAdapter(artifactsDir, contractsDir);
- const contractsDataFrom0xArtifacts = await solCompilerArtifactAdapter.collectContractsDataAsync();
- return contractsDataFrom0xArtifacts;
- }
- private _getTruffleConfig(): TruffleConfig {
- const truffleConfigFileShort = path.resolve(path.join(this._projectRoot, 'truffle.js'));
- const truffleConfigFileLong = path.resolve(path.join(this._projectRoot, 'truffle-config.js'));
- if (fs.existsSync(truffleConfigFileShort)) {
- const truffleConfig = require(truffleConfigFileShort);
- return truffleConfig;
- } else if (fs.existsSync(truffleConfigFileLong)) {
- const truffleConfig = require(truffleConfigFileLong);
- return truffleConfig;
- } else {
- throw new Error(
- `Neither ${truffleConfigFileShort} nor ${truffleConfigFileLong} exists. Make sure the project root is correct`,
- );
- }
- }
- private _assertSolidityVersionIsCorrect(truffleArtifactsDirectory: string): void {
- const artifactsGlob = `${truffleArtifactsDirectory}/**/*.json`;
- const artifactFileNames = glob.sync(artifactsGlob, { absolute: true });
- for (const artifactFileName of artifactFileNames) {
- const artifact = JSON.parse(fs.readFileSync(artifactFileName).toString());
- const compilerVersion = artifact.compiler.version;
- if (!compilerVersion.startsWith(this._solcVersion)) {
- throw new Error(
- `${artifact.contractName} was compiled with solidity ${compilerVersion} but specified version is ${
- this._solcVersion
- } making it impossible for sol-cov to process traces`,
- );
- }
- }
- }
-}
diff --git a/packages/sol-cov/src/ast_visitor.ts b/packages/sol-cov/src/ast_visitor.ts
deleted file mode 100644
index e55cdf6ec..000000000
--- a/packages/sol-cov/src/ast_visitor.ts
+++ /dev/null
@@ -1,168 +0,0 @@
-import * as _ from 'lodash';
-import * as Parser from 'solidity-parser-antlr';
-
-import { BranchMap, FnMap, LocationByOffset, SingleFileSourceRange, StatementMap } from './types';
-
-export interface CoverageEntriesDescription {
- fnMap: FnMap;
- branchMap: BranchMap;
- statementMap: StatementMap;
- modifiersStatementIds: number[];
-}
-
-enum BranchType {
- If = 'if',
- ConditionalExpression = 'cond-expr',
- BinaryExpression = 'binary-expr',
-}
-
-export class ASTVisitor {
- private _entryId = 0;
- private readonly _fnMap: FnMap = {};
- private readonly _branchMap: BranchMap = {};
- private readonly _modifiersStatementIds: number[] = [];
- private readonly _statementMap: StatementMap = {};
- private readonly _locationByOffset: LocationByOffset;
- private readonly _ignoreRangesBeginningAt: number[];
- // keep track of contract/function ranges that are to be ignored
- // so we can also ignore any children nodes within the contract/function
- private readonly _ignoreRangesWithin: Array<[number, number]> = [];
- constructor(locationByOffset: LocationByOffset, ignoreRangesBeginningAt: number[] = []) {
- this._locationByOffset = locationByOffset;
- this._ignoreRangesBeginningAt = ignoreRangesBeginningAt;
- }
- public getCollectedCoverageEntries(): CoverageEntriesDescription {
- const coverageEntriesDescription = {
- fnMap: this._fnMap,
- branchMap: this._branchMap,
- statementMap: this._statementMap,
- modifiersStatementIds: this._modifiersStatementIds,
- };
- return coverageEntriesDescription;
- }
- public IfStatement(ast: Parser.IfStatement): void {
- this._visitStatement(ast);
- this._visitBinaryBranch(ast, ast.trueBody, ast.falseBody || ast, BranchType.If);
- }
- public FunctionDefinition(ast: Parser.FunctionDefinition): void {
- this._visitFunctionLikeDefinition(ast);
- }
- public ContractDefinition(ast: Parser.ContractDefinition): void {
- if (this._shouldIgnoreExpression(ast)) {
- this._ignoreRangesWithin.push(ast.range as [number, number]);
- }
- }
- public ModifierDefinition(ast: Parser.ModifierDefinition): void {
- this._visitFunctionLikeDefinition(ast);
- }
- public ForStatement(ast: Parser.ForStatement): void {
- this._visitStatement(ast);
- }
- public ReturnStatement(ast: Parser.ReturnStatement): void {
- this._visitStatement(ast);
- }
- public BreakStatement(ast: Parser.BreakStatement): void {
- this._visitStatement(ast);
- }
- public ContinueStatement(ast: Parser.ContinueStatement): void {
- this._visitStatement(ast);
- }
- public EmitStatement(ast: any /* TODO: Parser.EmitStatement */): void {
- this._visitStatement(ast);
- }
- public VariableDeclarationStatement(ast: Parser.VariableDeclarationStatement): void {
- this._visitStatement(ast);
- }
- public Statement(ast: Parser.Statement): void {
- this._visitStatement(ast);
- }
- public WhileStatement(ast: Parser.WhileStatement): void {
- this._visitStatement(ast);
- }
- public SimpleStatement(ast: Parser.SimpleStatement): void {
- this._visitStatement(ast);
- }
- public ThrowStatement(ast: Parser.ThrowStatement): void {
- this._visitStatement(ast);
- }
- public DoWhileStatement(ast: Parser.DoWhileStatement): void {
- this._visitStatement(ast);
- }
- public ExpressionStatement(ast: Parser.ExpressionStatement): void {
- this._visitStatement(ast.expression);
- }
- public InlineAssemblyStatement(ast: Parser.InlineAssemblyStatement): void {
- this._visitStatement(ast);
- }
- public BinaryOperation(ast: Parser.BinaryOperation): void {
- const BRANCHING_BIN_OPS = ['&&', '||'];
- if (_.includes(BRANCHING_BIN_OPS, ast.operator)) {
- this._visitBinaryBranch(ast, ast.left, ast.right, BranchType.BinaryExpression);
- }
- }
- public Conditional(ast: Parser.Conditional): void {
- this._visitBinaryBranch(ast, ast.trueExpression, ast.falseExpression, BranchType.ConditionalExpression);
- }
- public ModifierInvocation(ast: Parser.ModifierInvocation): void {
- const BUILTIN_MODIFIERS = ['public', 'view', 'payable', 'external', 'internal', 'pure', 'constant'];
- if (!_.includes(BUILTIN_MODIFIERS, ast.name)) {
- if (this._shouldIgnoreExpression(ast)) {
- return;
- }
- this._modifiersStatementIds.push(this._entryId);
- this._visitStatement(ast);
- }
- }
- private _visitBinaryBranch(
- ast: Parser.ASTNode,
- left: Parser.ASTNode,
- right: Parser.ASTNode,
- type: BranchType,
- ): void {
- if (this._shouldIgnoreExpression(ast)) {
- return;
- }
- this._branchMap[this._entryId++] = {
- line: this._getExpressionRange(ast).start.line,
- type,
- locations: [this._getExpressionRange(left), this._getExpressionRange(right)],
- };
- }
- private _visitStatement(ast: Parser.ASTNode): void {
- if (this._shouldIgnoreExpression(ast)) {
- return;
- }
- this._statementMap[this._entryId++] = this._getExpressionRange(ast);
- }
- private _getExpressionRange(ast: Parser.ASTNode): SingleFileSourceRange {
- const astRange = ast.range as [number, number];
- const start = this._locationByOffset[astRange[0]];
- const end = this._locationByOffset[astRange[1] + 1];
- const range = {
- start,
- end,
- };
- return range;
- }
- private _shouldIgnoreExpression(ast: Parser.ASTNode): boolean {
- const [astStart, astEnd] = ast.range as [number, number];
- const isRangeIgnored = _.some(
- this._ignoreRangesWithin,
- ([rangeStart, rangeEnd]: [number, number]) => astStart >= rangeStart && astEnd <= rangeEnd,
- );
- return this._ignoreRangesBeginningAt.includes(astStart) || isRangeIgnored;
- }
- private _visitFunctionLikeDefinition(ast: Parser.ModifierDefinition | Parser.FunctionDefinition): void {
- if (this._shouldIgnoreExpression(ast)) {
- this._ignoreRangesWithin.push(ast.range as [number, number]);
- return;
- }
- const loc = this._getExpressionRange(ast);
- this._fnMap[this._entryId++] = {
- name: ast.name,
- line: loc.start.line,
- loc,
- };
- this._visitStatement(ast);
- }
-}
diff --git a/packages/sol-cov/src/collect_coverage_entries.ts b/packages/sol-cov/src/collect_coverage_entries.ts
deleted file mode 100644
index bdbcd613e..000000000
--- a/packages/sol-cov/src/collect_coverage_entries.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import * as ethUtil from 'ethereumjs-util';
-import * as _ from 'lodash';
-import * as parser from 'solidity-parser-antlr';
-
-import { ASTVisitor, CoverageEntriesDescription } from './ast_visitor';
-import { getLocationByOffset } from './source_maps';
-
-const IGNORE_RE = /\/\*\s*solcov\s+ignore\s+next\s*\*\/\s*/gm;
-
-// Parsing source code for each transaction/code is slow and therefore we cache it
-const coverageEntriesBySourceHash: { [sourceHash: string]: CoverageEntriesDescription } = {};
-
-export const collectCoverageEntries = (contractSource: string) => {
- const sourceHash = ethUtil.sha3(contractSource).toString('hex');
- if (_.isUndefined(coverageEntriesBySourceHash[sourceHash]) && !_.isUndefined(contractSource)) {
- const ast = parser.parse(contractSource, { range: true });
- const locationByOffset = getLocationByOffset(contractSource);
- const ignoreRangesBegingingAt = gatherRangesToIgnore(contractSource);
- const visitor = new ASTVisitor(locationByOffset, ignoreRangesBegingingAt);
- parser.visit(ast, visitor);
- coverageEntriesBySourceHash[sourceHash] = visitor.getCollectedCoverageEntries();
- }
- const coverageEntriesDescription = coverageEntriesBySourceHash[sourceHash];
- return coverageEntriesDescription;
-};
-
-// Gather the start index of all code blocks preceeded by "/* solcov ignore next */"
-function gatherRangesToIgnore(contractSource: string): number[] {
- const ignoreRangesStart = [];
-
- let match;
- do {
- match = IGNORE_RE.exec(contractSource);
- if (match) {
- const matchLen = match[0].length;
- ignoreRangesStart.push(match.index + matchLen);
- }
- } while (match);
-
- return ignoreRangesStart;
-}
diff --git a/packages/sol-cov/src/constants.ts b/packages/sol-cov/src/constants.ts
deleted file mode 100644
index 34d62b537..000000000
--- a/packages/sol-cov/src/constants.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// tslint:disable:number-literal-format
-export const constants = {
- NEW_CONTRACT: 'NEW_CONTRACT' as 'NEW_CONTRACT',
- PUSH1: 0x60,
- PUSH2: 0x61,
- PUSH32: 0x7f,
- TIMESTAMP: 0x42,
-};
diff --git a/packages/sol-cov/src/coverage_subprovider.ts b/packages/sol-cov/src/coverage_subprovider.ts
deleted file mode 100644
index 9667e891c..000000000
--- a/packages/sol-cov/src/coverage_subprovider.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-import * as _ from 'lodash';
-
-import { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter';
-import { collectCoverageEntries } from './collect_coverage_entries';
-import { SingleFileSubtraceHandler, TraceCollector } from './trace_collector';
-import { TraceInfoSubprovider } from './trace_info_subprovider';
-import {
- BranchCoverage,
- ContractData,
- Coverage,
- FunctionCoverage,
- FunctionDescription,
- SourceRange,
- StatementCoverage,
- StatementDescription,
- Subtrace,
- TraceInfo,
-} from './types';
-import { utils } from './utils';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It's used to compute your code coverage while running solidity tests.
- */
-export class CoverageSubprovider extends TraceInfoSubprovider {
- private readonly _coverageCollector: TraceCollector;
- /**
- * Instantiates a CoverageSubprovider instance
- * @param artifactAdapter Adapter for used artifacts format (0x, truffle, giveth, etc.)
- * @param defaultFromAddress default from address to use when sending transactions
- * @param isVerbose If true, we will log any unknown transactions. Otherwise we will ignore them
- */
- constructor(artifactAdapter: AbstractArtifactAdapter, defaultFromAddress: string, isVerbose: boolean = true) {
- const traceCollectionSubproviderConfig = {
- shouldCollectTransactionTraces: true,
- shouldCollectGasEstimateTraces: true,
- shouldCollectCallTraces: true,
- };
- super(defaultFromAddress, traceCollectionSubproviderConfig);
- this._coverageCollector = new TraceCollector(artifactAdapter, isVerbose, coverageHandler);
- }
- protected async _handleTraceInfoAsync(traceInfo: TraceInfo): Promise<void> {
- await this._coverageCollector.computeSingleTraceCoverageAsync(traceInfo);
- }
- /**
- * Write the test coverage results to a file in Istanbul format.
- */
- public async writeCoverageAsync(): Promise<void> {
- await this._coverageCollector.writeOutputAsync();
- }
-}
-
-/**
- * Computed partial coverage for a single file & subtrace.
- * @param contractData Contract metadata (source, srcMap, bytecode)
- * @param subtrace A subset of a transcation/call trace that was executed within that contract
- * @param pcToSourceRange A mapping from program counters to source ranges
- * @param fileIndex Index of a file to compute coverage for
- * @return Partial istanbul coverage for that file & subtrace
- */
-export const coverageHandler: SingleFileSubtraceHandler = (
- contractData: ContractData,
- subtrace: Subtrace,
- pcToSourceRange: { [programCounter: number]: SourceRange },
- fileIndex: number,
-): Coverage => {
- const absoluteFileName = contractData.sources[fileIndex];
- const coverageEntriesDescription = collectCoverageEntries(contractData.sourceCodes[fileIndex]);
-
- // if the source wasn't provided for the fileIndex, we can't cover the file
- if (_.isUndefined(coverageEntriesDescription)) {
- return {};
- }
-
- let sourceRanges = _.map(subtrace, structLog => pcToSourceRange[structLog.pc]);
- sourceRanges = _.compact(sourceRanges); // Some PC's don't map to a source range and we just ignore them.
- // By default lodash does a shallow object comparasion. We JSON.stringify them and compare as strings.
- sourceRanges = _.uniqBy(sourceRanges, s => JSON.stringify(s)); // We don't care if one PC was covered multiple times within a single transaction
- sourceRanges = _.filter(sourceRanges, sourceRange => sourceRange.fileName === absoluteFileName);
- const branchCoverage: BranchCoverage = {};
- const branchIds = _.keys(coverageEntriesDescription.branchMap);
- for (const branchId of branchIds) {
- const branchDescription = coverageEntriesDescription.branchMap[branchId];
- const isBranchCoveredByBranchIndex = _.map(branchDescription.locations, location => {
- const isBranchCovered = _.some(sourceRanges, range => utils.isRangeInside(range.location, location));
- const timesBranchCovered = Number(isBranchCovered);
- return timesBranchCovered;
- });
- branchCoverage[branchId] = isBranchCoveredByBranchIndex;
- }
- const statementCoverage: StatementCoverage = {};
- const statementIds = _.keys(coverageEntriesDescription.statementMap);
- for (const statementId of statementIds) {
- const statementDescription = coverageEntriesDescription.statementMap[statementId];
- const isStatementCovered = _.some(sourceRanges, range =>
- utils.isRangeInside(range.location, statementDescription),
- );
- const timesStatementCovered = Number(isStatementCovered);
- statementCoverage[statementId] = timesStatementCovered;
- }
- const functionCoverage: FunctionCoverage = {};
- const functionIds = _.keys(coverageEntriesDescription.fnMap);
- for (const fnId of functionIds) {
- const functionDescription = coverageEntriesDescription.fnMap[fnId];
- const isFunctionCovered = _.some(sourceRanges, range =>
- utils.isRangeInside(range.location, functionDescription.loc),
- );
- const timesFunctionCovered = Number(isFunctionCovered);
- functionCoverage[fnId] = timesFunctionCovered;
- }
- // HACK: Solidity doesn't emit any opcodes that map back to modifiers with no args, that's why we map back to the
- // function range and check if there is any covered statement within that range.
- for (const modifierStatementId of coverageEntriesDescription.modifiersStatementIds) {
- if (statementCoverage[modifierStatementId]) {
- // Already detected as covered
- continue;
- }
- const modifierDescription = coverageEntriesDescription.statementMap[modifierStatementId];
- const enclosingFunction = _.find(coverageEntriesDescription.fnMap, functionDescription =>
- utils.isRangeInside(modifierDescription, functionDescription.loc),
- ) as FunctionDescription;
- const isModifierCovered = _.some(
- coverageEntriesDescription.statementMap,
- (statementDescription: StatementDescription, statementId: number) => {
- const isInsideTheModifierEnclosingFunction = utils.isRangeInside(
- statementDescription,
- enclosingFunction.loc,
- );
- const isCovered = statementCoverage[statementId];
- return isInsideTheModifierEnclosingFunction && isCovered;
- },
- );
- const timesModifierCovered = Number(isModifierCovered);
- statementCoverage[modifierStatementId] = timesModifierCovered;
- }
- const partialCoverage = {
- [absoluteFileName]: {
- ...coverageEntriesDescription,
- path: absoluteFileName,
- f: functionCoverage,
- s: statementCoverage,
- b: branchCoverage,
- },
- };
- return partialCoverage;
-};
diff --git a/packages/sol-cov/src/get_source_range_snippet.ts b/packages/sol-cov/src/get_source_range_snippet.ts
deleted file mode 100644
index bea17beae..000000000
--- a/packages/sol-cov/src/get_source_range_snippet.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-import * as ethUtil from 'ethereumjs-util';
-import * as _ from 'lodash';
-import * as Parser from 'solidity-parser-antlr';
-
-import { SingleFileSourceRange, SourceRange, SourceSnippet } from './types';
-import { utils } from './utils';
-
-interface ASTInfo {
- type: string;
- node: Parser.ASTNode;
- name: string | null;
- range?: SingleFileSourceRange;
-}
-
-// Parsing source code for each transaction/code is slow and therefore we cache it
-const parsedSourceByHash: { [sourceHash: string]: Parser.ASTNode } = {};
-
-export function getSourceRangeSnippet(sourceRange: SourceRange, sourceCode: string): SourceSnippet | null {
- const sourceHash = ethUtil.sha3(sourceCode).toString('hex');
- if (_.isUndefined(parsedSourceByHash[sourceHash])) {
- parsedSourceByHash[sourceHash] = Parser.parse(sourceCode, { loc: true });
- }
- const astNode = parsedSourceByHash[sourceHash];
- const visitor = new ASTInfoVisitor();
- Parser.visit(astNode, visitor);
- const astInfo = visitor.getASTInfoForRange(sourceRange);
- if (astInfo === null) {
- return null;
- }
- const sourceCodeInRange = utils.getRange(sourceCode, sourceRange.location);
- return {
- ...astInfo,
- range: astInfo.range as SingleFileSourceRange,
- source: sourceCodeInRange,
- fileName: sourceRange.fileName,
- };
-}
-
-// A visitor which collects ASTInfo for most nodes in the AST.
-class ASTInfoVisitor {
- private readonly _astInfos: ASTInfo[] = [];
- public getASTInfoForRange(sourceRange: SourceRange): ASTInfo | null {
- // HACK(albrow): Sometimes the source range doesn't exactly match that
- // of astInfo. To work around that we try with a +/-1 offset on
- // end.column. If nothing matches even with the offset, we return null.
- const offset = {
- start: {
- line: 0,
- column: 0,
- },
- end: {
- line: 0,
- column: 0,
- },
- };
- let astInfo = this._getASTInfoForRange(sourceRange, offset);
- if (astInfo !== null) {
- return astInfo;
- }
- offset.end.column += 1;
- astInfo = this._getASTInfoForRange(sourceRange, offset);
- if (astInfo !== null) {
- return astInfo;
- }
- offset.end.column -= 2;
- astInfo = this._getASTInfoForRange(sourceRange, offset);
- if (astInfo !== null) {
- return astInfo;
- }
- return null;
- }
- public ContractDefinition(ast: Parser.ContractDefinition): void {
- this._visitContractDefinition(ast);
- }
- public IfStatement(ast: Parser.IfStatement): void {
- this._visitStatement(ast);
- }
- public FunctionDefinition(ast: Parser.FunctionDefinition): void {
- this._visitFunctionLikeDefinition(ast);
- }
- public ModifierDefinition(ast: Parser.ModifierDefinition): void {
- this._visitFunctionLikeDefinition(ast);
- }
- public ForStatement(ast: Parser.ForStatement): void {
- this._visitStatement(ast);
- }
- public ReturnStatement(ast: Parser.ReturnStatement): void {
- this._visitStatement(ast);
- }
- public BreakStatement(ast: Parser.BreakStatement): void {
- this._visitStatement(ast);
- }
- public ContinueStatement(ast: Parser.ContinueStatement): void {
- this._visitStatement(ast);
- }
- public EmitStatement(ast: any /* TODO: Parser.EmitStatement */): void {
- this._visitStatement(ast);
- }
- public VariableDeclarationStatement(ast: Parser.VariableDeclarationStatement): void {
- this._visitStatement(ast);
- }
- public Statement(ast: Parser.Statement): void {
- this._visitStatement(ast);
- }
- public WhileStatement(ast: Parser.WhileStatement): void {
- this._visitStatement(ast);
- }
- public SimpleStatement(ast: Parser.SimpleStatement): void {
- this._visitStatement(ast);
- }
- public ThrowStatement(ast: Parser.ThrowStatement): void {
- this._visitStatement(ast);
- }
- public DoWhileStatement(ast: Parser.DoWhileStatement): void {
- this._visitStatement(ast);
- }
- public ExpressionStatement(ast: Parser.ExpressionStatement): void {
- this._visitStatement(ast.expression);
- }
- public InlineAssemblyStatement(ast: Parser.InlineAssemblyStatement): void {
- this._visitStatement(ast);
- }
- public ModifierInvocation(ast: Parser.ModifierInvocation): void {
- const BUILTIN_MODIFIERS = ['public', 'view', 'payable', 'external', 'internal', 'pure', 'constant'];
- if (!_.includes(BUILTIN_MODIFIERS, ast.name)) {
- this._visitStatement(ast);
- }
- }
- private _visitStatement(ast: Parser.ASTNode): void {
- this._astInfos.push({
- type: ast.type,
- node: ast,
- name: null,
- range: ast.loc,
- });
- }
- private _visitFunctionLikeDefinition(ast: Parser.ModifierDefinition | Parser.FunctionDefinition): void {
- this._astInfos.push({
- type: ast.type,
- node: ast,
- name: ast.name,
- range: ast.loc,
- });
- }
- private _visitContractDefinition(ast: Parser.ContractDefinition): void {
- this._astInfos.push({
- type: ast.type,
- node: ast,
- name: ast.name,
- range: ast.loc,
- });
- }
- private _getASTInfoForRange(sourceRange: SourceRange, offset: SingleFileSourceRange): ASTInfo | null {
- const offsetSourceRange = {
- ...sourceRange,
- location: {
- start: {
- line: sourceRange.location.start.line + offset.start.line,
- column: sourceRange.location.start.column + offset.start.column,
- },
- end: {
- line: sourceRange.location.end.line + offset.end.line,
- column: sourceRange.location.end.column + offset.end.column,
- },
- },
- };
- for (const astInfo of this._astInfos) {
- const astInfoRange = astInfo.range as SingleFileSourceRange;
- if (
- astInfoRange.start.column === offsetSourceRange.location.start.column &&
- astInfoRange.start.line === offsetSourceRange.location.start.line &&
- astInfoRange.end.column === offsetSourceRange.location.end.column &&
- astInfoRange.end.line === offsetSourceRange.location.end.line
- ) {
- return astInfo;
- }
- }
- return null;
- }
-}
diff --git a/packages/sol-cov/src/globals.d.ts b/packages/sol-cov/src/globals.d.ts
deleted file mode 100644
index e799b3529..000000000
--- a/packages/sol-cov/src/globals.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// tslint:disable:completed-docs
-declare module '*.json' {
- const json: any;
- /* tslint:disable */
- export default json;
- /* tslint:enable */
-}
diff --git a/packages/sol-cov/src/index.ts b/packages/sol-cov/src/index.ts
deleted file mode 100644
index 348e0fc9b..000000000
--- a/packages/sol-cov/src/index.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export { CoverageSubprovider } from './coverage_subprovider';
-export { SolCompilerArtifactAdapter } from './artifact_adapters/sol_compiler_artifact_adapter';
-export { TruffleArtifactAdapter } from './artifact_adapters/truffle_artifact_adapter';
-export { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter';
-
-// HACK: ProfilerSubprovider is a hacky way to do profiling using coverage tools. Not production ready
-export { ProfilerSubprovider } from './profiler_subprovider';
-export { RevertTraceSubprovider } from './revert_trace_subprovider';
-
-export { ContractData } from './types';
-export {
- JSONRPCRequestPayload,
- Provider,
- JSONRPCErrorCallback,
- JSONRPCResponsePayload,
- JSONRPCResponseError,
-} from 'ethereum-types';
-
-export {
- JSONRPCRequestPayloadWithMethod,
- NextCallback,
- ErrorCallback,
- OnNextCompleted,
- Callback,
-} from '@0x/subproviders';
diff --git a/packages/sol-cov/src/instructions.ts b/packages/sol-cov/src/instructions.ts
deleted file mode 100644
index 40987dbe5..000000000
--- a/packages/sol-cov/src/instructions.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { constants } from './constants';
-
-const isPush = (inst: number) => inst >= constants.PUSH1 && inst <= constants.PUSH32;
-
-const pushDataLength = (inst: number) => inst - constants.PUSH1 + 1;
-
-const instructionLength = (inst: number) => (isPush(inst) ? pushDataLength(inst) + 1 : 1);
-
-export const getPcToInstructionIndexMapping = (bytecode: Uint8Array) => {
- const result: {
- [programCounter: number]: number;
- } = {};
- let byteIndex = 0;
- let instructionIndex = 0;
- while (byteIndex < bytecode.length) {
- const instruction = bytecode[byteIndex];
- const length = instructionLength(instruction);
- result[byteIndex] = instructionIndex;
- byteIndex += length;
- instructionIndex += 1;
- }
- return result;
-};
diff --git a/packages/sol-cov/src/profiler_subprovider.ts b/packages/sol-cov/src/profiler_subprovider.ts
deleted file mode 100644
index ae9351f17..000000000
--- a/packages/sol-cov/src/profiler_subprovider.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import * as _ from 'lodash';
-
-import { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter';
-import { collectCoverageEntries } from './collect_coverage_entries';
-import { SingleFileSubtraceHandler, TraceCollector } from './trace_collector';
-import { TraceInfoSubprovider } from './trace_info_subprovider';
-import { ContractData, Coverage, SourceRange, Subtrace, TraceInfo } from './types';
-import { utils } from './utils';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * ProfilerSubprovider is used to profile Solidity code while running tests.
- */
-export class ProfilerSubprovider extends TraceInfoSubprovider {
- private readonly _profilerCollector: TraceCollector;
- /**
- * Instantiates a ProfilerSubprovider instance
- * @param artifactAdapter Adapter for used artifacts format (0x, truffle, giveth, etc.)
- * @param defaultFromAddress default from address to use when sending transactions
- * @param isVerbose If true, we will log any unknown transactions. Otherwise we will ignore them
- */
- constructor(artifactAdapter: AbstractArtifactAdapter, defaultFromAddress: string, isVerbose: boolean = true) {
- const traceCollectionSubproviderConfig = {
- shouldCollectTransactionTraces: true,
- shouldCollectGasEstimateTraces: false,
- shouldCollectCallTraces: false,
- };
- super(defaultFromAddress, traceCollectionSubproviderConfig);
- this._profilerCollector = new TraceCollector(artifactAdapter, isVerbose, profilerHandler);
- }
- protected async _handleTraceInfoAsync(traceInfo: TraceInfo): Promise<void> {
- await this._profilerCollector.computeSingleTraceCoverageAsync(traceInfo);
- }
- /**
- * Write the test profiler results to a file in Istanbul format.
- */
- public async writeProfilerOutputAsync(): Promise<void> {
- await this._profilerCollector.writeOutputAsync();
- }
-}
-
-/**
- * Computed partial coverage for a single file & subtrace for the purposes of
- * gas profiling.
- * @param contractData Contract metadata (source, srcMap, bytecode)
- * @param subtrace A subset of a transcation/call trace that was executed within that contract
- * @param pcToSourceRange A mapping from program counters to source ranges
- * @param fileIndex Index of a file to compute coverage for
- * @return Partial istanbul coverage for that file & subtrace
- */
-export const profilerHandler: SingleFileSubtraceHandler = (
- contractData: ContractData,
- subtrace: Subtrace,
- pcToSourceRange: { [programCounter: number]: SourceRange },
- fileIndex: number,
-): Coverage => {
- const absoluteFileName = contractData.sources[fileIndex];
- const profilerEntriesDescription = collectCoverageEntries(contractData.sourceCodes[fileIndex]);
- const gasConsumedByStatement: { [statementId: string]: number } = {};
- const statementIds = _.keys(profilerEntriesDescription.statementMap);
- for (const statementId of statementIds) {
- const statementDescription = profilerEntriesDescription.statementMap[statementId];
- const totalGasCost = _.sum(
- _.map(subtrace, structLog => {
- const sourceRange = pcToSourceRange[structLog.pc];
- if (_.isUndefined(sourceRange)) {
- return 0;
- }
- if (sourceRange.fileName !== absoluteFileName) {
- return 0;
- }
- if (utils.isRangeInside(sourceRange.location, statementDescription)) {
- return structLog.gasCost;
- } else {
- return 0;
- }
- }),
- );
- gasConsumedByStatement[statementId] = totalGasCost;
- }
- const partialProfilerOutput = {
- [absoluteFileName]: {
- ...profilerEntriesDescription,
- path: absoluteFileName,
- f: {}, // I's meaningless in profiling context
- s: gasConsumedByStatement,
- b: {}, // I's meaningless in profiling context
- },
- };
- return partialProfilerOutput;
-};
diff --git a/packages/sol-cov/src/revert_trace.ts b/packages/sol-cov/src/revert_trace.ts
deleted file mode 100644
index d60c6e7d9..000000000
--- a/packages/sol-cov/src/revert_trace.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { logUtils } from '@0x/utils';
-import { OpCode, StructLog } from 'ethereum-types';
-
-import * as _ from 'lodash';
-
-import { EvmCallStack } from './types';
-import { utils } from './utils';
-
-export function getRevertTrace(structLogs: StructLog[], startAddress: string): EvmCallStack {
- const evmCallStack: EvmCallStack = [];
- const addressStack = [startAddress];
- if (_.isEmpty(structLogs)) {
- return [];
- }
- const normalizedStructLogs = utils.normalizeStructLogs(structLogs);
- // tslint:disable-next-line:prefer-for-of
- for (let i = 0; i < normalizedStructLogs.length; i++) {
- const structLog = normalizedStructLogs[i];
- if (structLog.depth !== addressStack.length - 1) {
- throw new Error("Malformed trace. Trace depth doesn't match call stack depth");
- }
- // After that check we have a guarantee that call stack is never empty
- // If it would: callStack.length - 1 === structLog.depth === -1
- // That means that we can always safely pop from it
-
- if (utils.isCallLike(structLog.op)) {
- const currentAddress = _.last(addressStack) as string;
- const jumpAddressOffset = 1;
- const newAddress = utils.getAddressFromStackEntry(
- structLog.stack[structLog.stack.length - jumpAddressOffset - 1],
- );
-
- // Sometimes calls don't change the execution context (current address). When we do a transfer to an
- // externally owned account - it does the call and immediately returns because there is no fallback
- // function. We manually check if the call depth had changed to handle that case.
- const nextStructLog = normalizedStructLogs[i + 1];
- if (nextStructLog.depth !== structLog.depth) {
- addressStack.push(newAddress);
- evmCallStack.push({
- address: currentAddress,
- structLog,
- });
- }
- } else if (utils.isEndOpcode(structLog.op) && structLog.op !== OpCode.Revert) {
- // Just like with calls, sometimes returns/stops don't change the execution context (current address).
- const nextStructLog = normalizedStructLogs[i + 1];
- if (_.isUndefined(nextStructLog) || nextStructLog.depth !== structLog.depth) {
- evmCallStack.pop();
- addressStack.pop();
- }
- if (structLog.op === OpCode.SelfDestruct) {
- // After contract execution, we look at all sub-calls to external contracts, and for each one, fetch
- // the bytecode and compute the coverage for the call. If the contract is destroyed with a call
- // to `selfdestruct`, we are unable to fetch it's bytecode and compute coverage.
- // TODO: Refactor this logic to fetch the sub-called contract bytecode before the selfdestruct is called
- // in order to handle this edge-case.
- logUtils.warn(
- "Detected a selfdestruct. Sol-cov currently doesn't support that scenario. We'll just skip the trace part for a destructed contract",
- );
- }
- } else if (structLog.op === OpCode.Revert) {
- evmCallStack.push({
- address: _.last(addressStack) as string,
- structLog,
- });
- return evmCallStack;
- } else if (structLog.op === OpCode.Create) {
- // TODO: Extract the new contract address from the stack and handle that scenario
- logUtils.warn(
- "Detected a contract created from within another contract. Sol-cov currently doesn't support that scenario. We'll just skip that trace",
- );
- return [];
- } else {
- if (structLog !== _.last(normalizedStructLogs)) {
- const nextStructLog = normalizedStructLogs[i + 1];
- if (nextStructLog.depth === structLog.depth) {
- continue;
- } else if (nextStructLog.depth === structLog.depth - 1) {
- addressStack.pop();
- } else {
- throw new Error('Malformed trace. Unexpected call depth change');
- }
- }
- }
- }
- if (evmCallStack.length !== 0) {
- logUtils.warn('Malformed trace. Call stack non empty at the end. (probably out of gas)');
- }
- return [];
-}
diff --git a/packages/sol-cov/src/revert_trace_subprovider.ts b/packages/sol-cov/src/revert_trace_subprovider.ts
deleted file mode 100644
index 6ccf59653..000000000
--- a/packages/sol-cov/src/revert_trace_subprovider.ts
+++ /dev/null
@@ -1,163 +0,0 @@
-import { stripHexPrefix } from 'ethereumjs-util';
-import * as _ from 'lodash';
-import { getLogger, levels, Logger } from 'loglevel';
-
-import { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter';
-import { constants } from './constants';
-import { getSourceRangeSnippet } from './get_source_range_snippet';
-import { getRevertTrace } from './revert_trace';
-import { parseSourceMap } from './source_maps';
-import { TraceCollectionSubprovider } from './trace_collection_subprovider';
-import { ContractData, EvmCallStack, SourceRange, SourceSnippet } from './types';
-import { utils } from './utils';
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It is used to report call stack traces whenever a revert occurs.
- */
-export class RevertTraceSubprovider extends TraceCollectionSubprovider {
- // Lock is used to not accept normal transactions while doing call/snapshot magic because they'll be reverted later otherwise
- private _contractsData!: ContractData[];
- private readonly _artifactAdapter: AbstractArtifactAdapter;
- private readonly _logger: Logger;
-
- /**
- * Instantiates a RevertTraceSubprovider instance
- * @param artifactAdapter Adapter for used artifacts format (0x, truffle, giveth, etc.)
- * @param defaultFromAddress default from address to use when sending transactions
- * @param isVerbose If true, we will log any unknown transactions. Otherwise we will ignore them
- */
- constructor(artifactAdapter: AbstractArtifactAdapter, defaultFromAddress: string, isVerbose: boolean = true) {
- const traceCollectionSubproviderConfig = {
- shouldCollectTransactionTraces: true,
- shouldCollectGasEstimateTraces: true,
- shouldCollectCallTraces: true,
- };
- super(defaultFromAddress, traceCollectionSubproviderConfig);
- this._artifactAdapter = artifactAdapter;
- this._logger = getLogger('sol-cov');
- this._logger.setLevel(isVerbose ? levels.TRACE : levels.ERROR);
- }
- // tslint:disable-next-line:no-unused-variable
- protected async _recordTxTraceAsync(address: string, data: string | undefined, txHash: string): Promise<void> {
- await this._web3Wrapper.awaitTransactionMinedAsync(txHash, 0);
- const trace = await this._web3Wrapper.getTransactionTraceAsync(txHash, {
- disableMemory: true,
- disableStack: false,
- disableStorage: true,
- });
- const evmCallStack = getRevertTrace(trace.structLogs, address);
- if (evmCallStack.length > 0) {
- // if getRevertTrace returns a call stack it means there was a
- // revert.
- await this._printStackTraceAsync(evmCallStack);
- }
- }
- private async _printStackTraceAsync(evmCallStack: EvmCallStack): Promise<void> {
- const sourceSnippets: SourceSnippet[] = [];
- if (_.isUndefined(this._contractsData)) {
- this._contractsData = await this._artifactAdapter.collectContractsDataAsync();
- }
- for (const evmCallStackEntry of evmCallStack) {
- const isContractCreation = evmCallStackEntry.address === constants.NEW_CONTRACT;
- if (isContractCreation) {
- this._logger.error('Contract creation not supported');
- continue;
- }
- const bytecode = await this._web3Wrapper.getContractCodeAsync(evmCallStackEntry.address);
- const contractData = utils.getContractDataIfExists(this._contractsData, bytecode);
- if (_.isUndefined(contractData)) {
- const errMsg = isContractCreation
- ? `Unknown contract creation transaction`
- : `Transaction to an unknown address: ${evmCallStackEntry.address}`;
- this._logger.warn(errMsg);
- continue;
- }
- const bytecodeHex = stripHexPrefix(bytecode);
- const sourceMap = isContractCreation ? contractData.sourceMap : contractData.sourceMapRuntime;
-
- const pcToSourceRange = parseSourceMap(
- contractData.sourceCodes,
- sourceMap,
- bytecodeHex,
- contractData.sources,
- );
- // tslint:disable-next-line:no-unnecessary-initializer
- let sourceRange: SourceRange | undefined = undefined;
- let pc = evmCallStackEntry.structLog.pc;
- // Sometimes there is not a mapping for this pc (e.g. if the revert
- // actually happens in assembly). In that case, we want to keep
- // searching backwards by decrementing the pc until we find a
- // mapped source range.
- while (_.isUndefined(sourceRange) && pc > 0) {
- sourceRange = pcToSourceRange[pc];
- pc -= 1;
- }
- if (_.isUndefined(sourceRange)) {
- this._logger.warn(
- `could not find matching sourceRange for structLog: ${JSON.stringify(
- _.omit(evmCallStackEntry.structLog, 'stack'),
- )}`,
- );
- continue;
- }
-
- const fileIndex = contractData.sources.indexOf(sourceRange.fileName);
- const sourceSnippet = getSourceRangeSnippet(sourceRange, contractData.sourceCodes[fileIndex]);
- if (sourceSnippet !== null) {
- sourceSnippets.push(sourceSnippet);
- }
- }
- const filteredSnippets = filterSnippets(sourceSnippets);
- if (filteredSnippets.length > 0) {
- this._logger.error('\n\nStack trace for REVERT:\n');
- _.forEach(_.reverse(filteredSnippets), snippet => {
- const traceString = getStackTraceString(snippet);
- this._logger.error(traceString);
- });
- this._logger.error('\n');
- } else {
- this._logger.error('REVERT detected but could not determine stack trace');
- }
- }
-}
-
-// removes duplicates and if statements
-function filterSnippets(sourceSnippets: SourceSnippet[]): SourceSnippet[] {
- if (sourceSnippets.length === 0) {
- return [];
- }
- const results: SourceSnippet[] = [sourceSnippets[0]];
- let prev = sourceSnippets[0];
- for (const sourceSnippet of sourceSnippets) {
- if (sourceSnippet.type === 'IfStatement') {
- continue;
- } else if (sourceSnippet.source === prev.source) {
- prev = sourceSnippet;
- continue;
- }
- results.push(sourceSnippet);
- prev = sourceSnippet;
- }
- return results;
-}
-
-function getStackTraceString(sourceSnippet: SourceSnippet): string {
- let result = `${sourceSnippet.fileName}:${sourceSnippet.range.start.line}:${sourceSnippet.range.start.column}`;
- const snippetString = getSourceSnippetString(sourceSnippet);
- if (snippetString !== '') {
- result += `:\n ${snippetString}`;
- }
- return result;
-}
-
-function getSourceSnippetString(sourceSnippet: SourceSnippet): string {
- switch (sourceSnippet.type) {
- case 'ContractDefinition':
- return `contract ${sourceSnippet.name}`;
- case 'FunctionDefinition':
- return `function ${sourceSnippet.name}`;
- default:
- return `${sourceSnippet.source}`;
- }
-}
diff --git a/packages/sol-cov/src/source_maps.ts b/packages/sol-cov/src/source_maps.ts
deleted file mode 100644
index 90b21dda1..000000000
--- a/packages/sol-cov/src/source_maps.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import * as _ from 'lodash';
-
-import { getPcToInstructionIndexMapping } from './instructions';
-import { LineColumn, LocationByOffset, SourceRange } from './types';
-
-const RADIX = 10;
-
-export interface SourceLocation {
- offset: number;
- length: number;
- fileIndex: number;
-}
-
-export function getLocationByOffset(str: string): LocationByOffset {
- const locationByOffset: LocationByOffset = { 0: { line: 1, column: 0 } };
- let currentOffset = 0;
- for (const char of str.split('')) {
- const location = locationByOffset[currentOffset];
- const isNewline = char === '\n';
- locationByOffset[currentOffset + 1] = {
- line: location.line + (isNewline ? 1 : 0),
- column: isNewline ? 0 : location.column + 1,
- };
- currentOffset++;
- }
- return locationByOffset;
-}
-
-// Parses a sourcemap string
-// The solidity sourcemap format is documented here: https://github.com/ethereum/solidity/blob/develop/docs/miscellaneous.rst#source-mappings
-export function parseSourceMap(
- sourceCodes: string[],
- srcMap: string,
- bytecodeHex: string,
- sources: string[],
-): { [programCounter: number]: SourceRange } {
- const bytecode = Uint8Array.from(Buffer.from(bytecodeHex, 'hex'));
- const pcToInstructionIndex: { [programCounter: number]: number } = getPcToInstructionIndexMapping(bytecode);
- const locationByOffsetByFileIndex = _.map(sourceCodes, s => (_.isUndefined(s) ? {} : getLocationByOffset(s)));
- const entries = srcMap.split(';');
- let lastParsedEntry: SourceLocation = {} as any;
- const instructionIndexToSourceRange: { [instructionIndex: number]: SourceRange } = {};
- _.each(entries, (entry: string, i: number) => {
- // tslint:disable-next-line:no-unused-variable
- const [instructionIndexStrIfExists, lengthStrIfExists, fileIndexStrIfExists, jumpTypeStrIfExists] = entry.split(
- ':',
- );
- const instructionIndexIfExists = parseInt(instructionIndexStrIfExists, RADIX);
- const lengthIfExists = parseInt(lengthStrIfExists, RADIX);
- const fileIndexIfExists = parseInt(fileIndexStrIfExists, RADIX);
- const offset = _.isNaN(instructionIndexIfExists) ? lastParsedEntry.offset : instructionIndexIfExists;
- const length = _.isNaN(lengthIfExists) ? lastParsedEntry.length : lengthIfExists;
- const fileIndex = _.isNaN(fileIndexIfExists) ? lastParsedEntry.fileIndex : fileIndexIfExists;
- const parsedEntry = {
- offset,
- length,
- fileIndex,
- };
- if (parsedEntry.fileIndex !== -1 && !_.isUndefined(locationByOffsetByFileIndex[parsedEntry.fileIndex])) {
- const sourceRange = {
- location: {
- start: locationByOffsetByFileIndex[parsedEntry.fileIndex][parsedEntry.offset],
- end: locationByOffsetByFileIndex[parsedEntry.fileIndex][parsedEntry.offset + parsedEntry.length],
- },
- fileName: sources[parsedEntry.fileIndex],
- };
- instructionIndexToSourceRange[i] = sourceRange;
- } else {
- // Some assembly code generated by Solidity can't be mapped back to a line of source code.
- // Source: https://github.com/ethereum/solidity/issues/3629
- }
- lastParsedEntry = parsedEntry;
- });
- const pcsToSourceRange: { [programCounter: number]: SourceRange } = {};
- for (const programCounterKey of _.keys(pcToInstructionIndex)) {
- const pc = parseInt(programCounterKey, RADIX);
- const instructionIndex: number = pcToInstructionIndex[pc];
- pcsToSourceRange[pc] = instructionIndexToSourceRange[instructionIndex];
- }
- return pcsToSourceRange;
-}
diff --git a/packages/sol-cov/src/trace.ts b/packages/sol-cov/src/trace.ts
deleted file mode 100644
index b38dbdce0..000000000
--- a/packages/sol-cov/src/trace.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import { logUtils } from '@0x/utils';
-import { OpCode, StructLog } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { utils } from './utils';
-
-export interface TraceByContractAddress {
- [contractAddress: string]: StructLog[];
-}
-
-export function getTracesByContractAddress(structLogs: StructLog[], startAddress: string): TraceByContractAddress {
- const traceByContractAddress: TraceByContractAddress = {};
- let currentTraceSegment = [];
- const addressStack = [startAddress];
- if (_.isEmpty(structLogs)) {
- return traceByContractAddress;
- }
- const normalizedStructLogs = utils.normalizeStructLogs(structLogs);
- // tslint:disable-next-line:prefer-for-of
- for (let i = 0; i < normalizedStructLogs.length; i++) {
- const structLog = normalizedStructLogs[i];
- if (structLog.depth !== addressStack.length - 1) {
- throw new Error("Malformed trace. Trace depth doesn't match call stack depth");
- }
- // After that check we have a guarantee that call stack is never empty
- // If it would: callStack.length - 1 === structLog.depth === -1
- // That means that we can always safely pop from it
- currentTraceSegment.push(structLog);
-
- if (utils.isCallLike(structLog.op)) {
- const currentAddress = _.last(addressStack) as string;
- const jumpAddressOffset = 1;
- const newAddress = utils.getAddressFromStackEntry(
- structLog.stack[structLog.stack.length - jumpAddressOffset - 1],
- );
-
- // Sometimes calls don't change the execution context (current address). When we do a transfer to an
- // externally owned account - it does the call and immediately returns because there is no fallback
- // function. We manually check if the call depth had changed to handle that case.
- const nextStructLog = normalizedStructLogs[i + 1];
- if (nextStructLog.depth !== structLog.depth) {
- addressStack.push(newAddress);
- traceByContractAddress[currentAddress] = (traceByContractAddress[currentAddress] || []).concat(
- currentTraceSegment,
- );
- currentTraceSegment = [];
- }
- } else if (utils.isEndOpcode(structLog.op)) {
- const currentAddress = addressStack.pop() as string;
- traceByContractAddress[currentAddress] = (traceByContractAddress[currentAddress] || []).concat(
- currentTraceSegment,
- );
- currentTraceSegment = [];
- if (structLog.op === OpCode.SelfDestruct) {
- // After contract execution, we look at all sub-calls to external contracts, and for each one, fetch
- // the bytecode and compute the coverage for the call. If the contract is destroyed with a call
- // to `selfdestruct`, we are unable to fetch it's bytecode and compute coverage.
- // TODO: Refactor this logic to fetch the sub-called contract bytecode before the selfdestruct is called
- // in order to handle this edge-case.
- logUtils.warn(
- "Detected a selfdestruct. Sol-cov currently doesn't support that scenario. We'll just skip the trace part for a destructed contract",
- );
- }
- } else if (structLog.op === OpCode.Create) {
- // TODO: Extract the new contract address from the stack and handle that scenario
- logUtils.warn(
- "Detected a contract created from within another contract. Sol-cov currently doesn't support that scenario. We'll just skip that trace",
- );
- return traceByContractAddress;
- } else {
- if (structLog !== _.last(normalizedStructLogs)) {
- const nextStructLog = normalizedStructLogs[i + 1];
- if (nextStructLog.depth === structLog.depth) {
- continue;
- } else if (nextStructLog.depth === structLog.depth - 1) {
- const currentAddress = addressStack.pop() as string;
- traceByContractAddress[currentAddress] = (traceByContractAddress[currentAddress] || []).concat(
- currentTraceSegment,
- );
- currentTraceSegment = [];
- } else {
- throw new Error('Malformed trace. Unexpected call depth change');
- }
- }
- }
- }
- if (addressStack.length !== 0) {
- logUtils.warn('Malformed trace. Call stack non empty at the end');
- }
- if (currentTraceSegment.length !== 0) {
- const currentAddress = addressStack.pop() as string;
- traceByContractAddress[currentAddress] = (traceByContractAddress[currentAddress] || []).concat(
- currentTraceSegment,
- );
- currentTraceSegment = [];
- logUtils.warn('Malformed trace. Current trace segment non empty at the end');
- }
- return traceByContractAddress;
-}
diff --git a/packages/sol-cov/src/trace_collection_subprovider.ts b/packages/sol-cov/src/trace_collection_subprovider.ts
deleted file mode 100644
index 25e38768d..000000000
--- a/packages/sol-cov/src/trace_collection_subprovider.ts
+++ /dev/null
@@ -1,188 +0,0 @@
-import { BlockchainLifecycle } from '@0x/dev-utils';
-import { Callback, ErrorCallback, NextCallback, Subprovider } from '@0x/subproviders';
-import { CallDataRPC, marshaller, Web3Wrapper } from '@0x/web3-wrapper';
-import { JSONRPCRequestPayload, Provider, TxData } from 'ethereum-types';
-import * as _ from 'lodash';
-import { Lock } from 'semaphore-async-await';
-
-import { constants } from './constants';
-import { BlockParamLiteral } from './types';
-
-interface MaybeFakeTxData extends TxData {
- isFakeTransaction?: boolean;
-}
-
-const BLOCK_GAS_LIMIT = 6000000;
-
-export interface TraceCollectionSubproviderConfig {
- shouldCollectTransactionTraces: boolean;
- shouldCollectCallTraces: boolean;
- shouldCollectGasEstimateTraces: boolean;
-}
-
-// Because there is no notion of a call trace in the Ethereum rpc - we collect them in a rather non-obvious/hacky way.
-// On each call - we create a snapshot, execute the call as a transaction, get the trace, revert the snapshot.
-// That allows us to avoid influencing test behaviour.
-
-/**
- * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
- * It collects traces of all transactions that were sent and all calls that were executed through JSON RPC. It must
- * be extended by implementing the _recordTxTraceAsync method which is called for every transaction.
- */
-export abstract class TraceCollectionSubprovider extends Subprovider {
- protected _web3Wrapper!: Web3Wrapper;
- // Lock is used to not accept normal transactions while doing call/snapshot magic because they'll be reverted later otherwise
- private readonly _lock = new Lock();
- private readonly _defaultFromAddress: string;
- private _isEnabled = true;
- private readonly _config: TraceCollectionSubproviderConfig;
- /**
- * Instantiates a TraceCollectionSubprovider instance
- * @param defaultFromAddress default from address to use when sending transactions
- */
- constructor(defaultFromAddress: string, config: TraceCollectionSubproviderConfig) {
- super();
- this._defaultFromAddress = defaultFromAddress;
- this._config = config;
- }
- /**
- * Starts trace collection
- */
- public start(): void {
- this._isEnabled = true;
- }
- /**
- * Stops trace collection
- */
- public stop(): void {
- this._isEnabled = false;
- }
- /**
- * This method conforms to the web3-provider-engine interface.
- * It is called internally by the ProviderEngine when it is this subproviders
- * turn to handle a JSON RPC request.
- * @param payload JSON RPC payload
- * @param next Callback to call if this subprovider decides not to handle the request
- * @param _end Callback to call if subprovider handled the request and wants to pass back the request.
- */
- // tslint:disable-next-line:prefer-function-over-method async-suffix
- public async handleRequest(payload: JSONRPCRequestPayload, next: NextCallback, _end: ErrorCallback): Promise<void> {
- if (this._isEnabled) {
- switch (payload.method) {
- case 'eth_sendTransaction':
- if (!this._config.shouldCollectTransactionTraces) {
- next();
- } else {
- const txData = payload.params[0];
- next(this._onTransactionSentAsync.bind(this, txData));
- }
- return;
-
- case 'eth_call':
- if (!this._config.shouldCollectCallTraces) {
- next();
- } else {
- const callData = payload.params[0];
- next(this._onCallOrGasEstimateExecutedAsync.bind(this, callData));
- }
- return;
-
- case 'eth_estimateGas':
- if (!this._config.shouldCollectGasEstimateTraces) {
- next();
- } else {
- const estimateGasData = payload.params[0];
- next(this._onCallOrGasEstimateExecutedAsync.bind(this, estimateGasData));
- }
- return;
-
- default:
- next();
- return;
- }
- } else {
- next();
- return;
- }
- }
- /**
- * Set's the subprovider's engine to the ProviderEngine it is added to.
- * This is only called within the ProviderEngine source code, do not call
- * directly.
- * @param engine The ProviderEngine this subprovider is added to
- */
- public setEngine(engine: Provider): void {
- super.setEngine(engine);
- this._web3Wrapper = new Web3Wrapper(engine);
- }
- protected abstract async _recordTxTraceAsync(
- address: string,
- data: string | undefined,
- txHash: string,
- ): Promise<void>;
- private async _onTransactionSentAsync(
- txData: MaybeFakeTxData,
- err: Error | null,
- txHash: string | undefined,
- cb: Callback,
- ): Promise<void> {
- if (!txData.isFakeTransaction) {
- // This transaction is a usual transaction. Not a call executed as one.
- // And we don't want it to be executed within a snapshotting period
- await this._lock.acquire();
- }
- const NULL_ADDRESS = '0x0';
- if (_.isNull(err)) {
- const toAddress =
- _.isUndefined(txData.to) || txData.to === NULL_ADDRESS ? constants.NEW_CONTRACT : txData.to;
- await this._recordTxTraceAsync(toAddress, txData.data, txHash as string);
- } else {
- const latestBlock = await this._web3Wrapper.getBlockWithTransactionDataAsync(BlockParamLiteral.Latest);
- const transactions = latestBlock.transactions;
- for (const transaction of transactions) {
- const toAddress =
- _.isUndefined(txData.to) || txData.to === NULL_ADDRESS ? constants.NEW_CONTRACT : txData.to;
- await this._recordTxTraceAsync(toAddress, transaction.input, transaction.hash);
- }
- }
- if (!txData.isFakeTransaction) {
- // This transaction is a usual transaction. Not a call executed as one.
- // And we don't want it to be executed within a snapshotting period
- this._lock.release();
- }
- cb();
- }
- private async _onCallOrGasEstimateExecutedAsync(
- callData: Partial<CallDataRPC>,
- _err: Error | null,
- _callResult: string,
- cb: Callback,
- ): Promise<void> {
- await this._recordCallOrGasEstimateTraceAsync(callData);
- cb();
- }
- private async _recordCallOrGasEstimateTraceAsync(callData: Partial<CallDataRPC>): Promise<void> {
- // We don't want other transactions to be exeucted during snashotting period, that's why we lock the
- // transaction execution for all transactions except our fake ones.
- await this._lock.acquire();
- const blockchainLifecycle = new BlockchainLifecycle(this._web3Wrapper);
- await blockchainLifecycle.startAsync();
- const fakeTxData = {
- gas: BLOCK_GAS_LIMIT.toString(16), // tslint:disable-line:custom-no-magic-numbers
- isFakeTransaction: true, // This transaction (and only it) is allowed to come through when the lock is locked
- ...callData,
- from: callData.from || this._defaultFromAddress,
- };
- try {
- const txData = marshaller.unmarshalTxData(fakeTxData);
- const txHash = await this._web3Wrapper.sendTransactionAsync(txData);
- await this._web3Wrapper.awaitTransactionMinedAsync(txHash, 0);
- } catch (err) {
- // TODO(logvinov) Check that transaction failed and not some other exception
- // Even if this transaction failed - we've already recorded it's trace.
- _.noop();
- }
- await blockchainLifecycle.revertAsync();
- this._lock.release();
- }
-}
diff --git a/packages/sol-cov/src/trace_collector.ts b/packages/sol-cov/src/trace_collector.ts
deleted file mode 100644
index 44cffc238..000000000
--- a/packages/sol-cov/src/trace_collector.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { promisify } from '@0x/utils';
-import { stripHexPrefix } from 'ethereumjs-util';
-import * as fs from 'fs';
-import { Collector } from 'istanbul';
-import * as _ from 'lodash';
-import { getLogger, levels, Logger } from 'loglevel';
-import * as mkdirp from 'mkdirp';
-
-import { AbstractArtifactAdapter } from './artifact_adapters/abstract_artifact_adapter';
-import { constants } from './constants';
-import { parseSourceMap } from './source_maps';
-import {
- ContractData,
- Coverage,
- SourceRange,
- Subtrace,
- TraceInfo,
- TraceInfoExistingContract,
- TraceInfoNewContract,
-} from './types';
-import { utils } from './utils';
-
-const mkdirpAsync = promisify<undefined>(mkdirp);
-
-export type SingleFileSubtraceHandler = (
- contractData: ContractData,
- subtrace: Subtrace,
- pcToSourceRange: { [programCounter: number]: SourceRange },
- fileIndex: number,
-) => Coverage;
-
-/**
- * TraceCollector is used by CoverageSubprovider to compute code coverage based on collected trace data.
- */
-export class TraceCollector {
- private readonly _artifactAdapter: AbstractArtifactAdapter;
- private readonly _logger: Logger;
- private _contractsData!: ContractData[];
- private readonly _collector = new Collector();
- private readonly _singleFileSubtraceHandler: SingleFileSubtraceHandler;
-
- /**
- * Instantiates a TraceCollector instance
- * @param artifactAdapter Adapter for used artifacts format (0x, truffle, giveth, etc.)
- * @param isVerbose If true, we will log any unknown transactions. Otherwise we will ignore them
- * @param singleFileSubtraceHandler A handler function for computing partial coverage for a single file & subtrace
- */
- constructor(
- artifactAdapter: AbstractArtifactAdapter,
- isVerbose: boolean,
- singleFileSubtraceHandler: SingleFileSubtraceHandler,
- ) {
- this._artifactAdapter = artifactAdapter;
- this._logger = getLogger('sol-cov');
- this._logger.setLevel(isVerbose ? levels.TRACE : levels.ERROR);
- this._singleFileSubtraceHandler = singleFileSubtraceHandler;
- }
- public async writeOutputAsync(): Promise<void> {
- const finalCoverage = this._collector.getFinalCoverage();
- const stringifiedCoverage = JSON.stringify(finalCoverage, null, '\t');
- await mkdirpAsync('coverage');
- fs.writeFileSync('coverage/coverage.json', stringifiedCoverage);
- }
- public async computeSingleTraceCoverageAsync(traceInfo: TraceInfo): Promise<void> {
- if (_.isUndefined(this._contractsData)) {
- this._contractsData = await this._artifactAdapter.collectContractsDataAsync();
- }
- const isContractCreation = traceInfo.address === constants.NEW_CONTRACT;
- const bytecode = isContractCreation
- ? (traceInfo as TraceInfoNewContract).bytecode
- : (traceInfo as TraceInfoExistingContract).runtimeBytecode;
- const contractData = utils.getContractDataIfExists(this._contractsData, bytecode);
- if (_.isUndefined(contractData)) {
- const errMsg = isContractCreation
- ? `Unknown contract creation transaction`
- : `Transaction to an unknown address: ${traceInfo.address}`;
- this._logger.warn(errMsg);
- return;
- }
- const bytecodeHex = stripHexPrefix(bytecode);
- const sourceMap = isContractCreation ? contractData.sourceMap : contractData.sourceMapRuntime;
- const pcToSourceRange = parseSourceMap(contractData.sourceCodes, sourceMap, bytecodeHex, contractData.sources);
- for (let fileIndex = 0; fileIndex < contractData.sources.length; fileIndex++) {
- const singleFileCoverageForTrace = this._singleFileSubtraceHandler(
- contractData,
- traceInfo.subtrace,
- pcToSourceRange,
- fileIndex,
- );
- this._collector.add(singleFileCoverageForTrace);
- }
- }
-}
diff --git a/packages/sol-cov/src/trace_info_subprovider.ts b/packages/sol-cov/src/trace_info_subprovider.ts
deleted file mode 100644
index 635a68f58..000000000
--- a/packages/sol-cov/src/trace_info_subprovider.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import * as _ from 'lodash';
-
-import { constants } from './constants';
-import { getTracesByContractAddress } from './trace';
-import { TraceCollectionSubprovider } from './trace_collection_subprovider';
-import { TraceInfo, TraceInfoExistingContract, TraceInfoNewContract } from './types';
-
-// TraceInfoSubprovider is extended by subproviders which need to work with one
-// TraceInfo at a time. It has one abstract method: _handleTraceInfoAsync, which
-// is called for each TraceInfo.
-export abstract class TraceInfoSubprovider extends TraceCollectionSubprovider {
- protected abstract _handleTraceInfoAsync(traceInfo: TraceInfo): Promise<void>;
- protected async _recordTxTraceAsync(address: string, data: string | undefined, txHash: string): Promise<void> {
- await this._web3Wrapper.awaitTransactionMinedAsync(txHash, 0);
- const trace = await this._web3Wrapper.getTransactionTraceAsync(txHash, {
- disableMemory: true,
- disableStack: false,
- disableStorage: true,
- });
- const tracesByContractAddress = getTracesByContractAddress(trace.structLogs, address);
- const subcallAddresses = _.keys(tracesByContractAddress);
- if (address === constants.NEW_CONTRACT) {
- for (const subcallAddress of subcallAddresses) {
- let traceInfo: TraceInfoNewContract | TraceInfoExistingContract;
- if (subcallAddress === 'NEW_CONTRACT') {
- const traceForThatSubcall = tracesByContractAddress[subcallAddress];
- traceInfo = {
- subtrace: traceForThatSubcall,
- txHash,
- address: subcallAddress,
- bytecode: data as string,
- };
- } else {
- const runtimeBytecode = await this._web3Wrapper.getContractCodeAsync(subcallAddress);
- const traceForThatSubcall = tracesByContractAddress[subcallAddress];
- traceInfo = {
- subtrace: traceForThatSubcall,
- txHash,
- address: subcallAddress,
- runtimeBytecode,
- };
- }
- await this._handleTraceInfoAsync(traceInfo);
- }
- } else {
- for (const subcallAddress of subcallAddresses) {
- const runtimeBytecode = await this._web3Wrapper.getContractCodeAsync(subcallAddress);
- const traceForThatSubcall = tracesByContractAddress[subcallAddress];
- const traceInfo: TraceInfoExistingContract = {
- subtrace: traceForThatSubcall,
- txHash,
- address: subcallAddress,
- runtimeBytecode,
- };
- await this._handleTraceInfoAsync(traceInfo);
- }
- }
- }
-}
diff --git a/packages/sol-cov/src/types.ts b/packages/sol-cov/src/types.ts
deleted file mode 100644
index 54ade0400..000000000
--- a/packages/sol-cov/src/types.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-import { StructLog } from 'ethereum-types';
-import * as Parser from 'solidity-parser-antlr';
-
-export interface LineColumn {
- line: number;
- column: number;
-}
-
-export interface SourceRange {
- location: SingleFileSourceRange;
- fileName: string;
-}
-
-export interface SingleFileSourceRange {
- start: LineColumn;
- end: LineColumn;
-}
-
-export interface LocationByOffset {
- [offset: number]: LineColumn;
-}
-
-export interface FunctionDescription {
- name: string;
- line: number;
- loc: SingleFileSourceRange;
- skip?: boolean;
-}
-
-export type StatementDescription = SingleFileSourceRange;
-
-export interface BranchDescription {
- line: number;
- type: 'if' | 'switch' | 'cond-expr' | 'binary-expr';
- locations: SingleFileSourceRange[];
-}
-
-export interface FnMap {
- [functionId: string]: FunctionDescription;
-}
-
-export interface BranchMap {
- [branchId: string]: BranchDescription;
-}
-
-export interface StatementMap {
- [statementId: string]: StatementDescription;
-}
-
-export interface LineCoverage {
- [lineNo: number]: number;
-}
-
-export interface FunctionCoverage {
- [functionId: string]: number;
-}
-
-export interface StatementCoverage {
- [statementId: string]: number;
-}
-
-export interface BranchCoverage {
- [branchId: string]: number[];
-}
-
-export interface Coverage {
- [fineName: string]: {
- l?: LineCoverage;
- f: FunctionCoverage;
- s: StatementCoverage;
- b: BranchCoverage;
- fnMap: FnMap;
- branchMap: BranchMap;
- statementMap: StatementMap;
- path: string;
- };
-}
-
-export interface ContractData {
- bytecode: string;
- sourceMap: string;
- runtimeBytecode: string;
- sourceMapRuntime: string;
- sourceCodes: string[];
- sources: string[];
-}
-
-// Part of the trace executed within the same context
-export type Subtrace = StructLog[];
-
-export interface TraceInfoBase {
- subtrace: Subtrace;
- txHash: string;
-}
-
-export interface TraceInfoNewContract extends TraceInfoBase {
- address: 'NEW_CONTRACT';
- bytecode: string;
-}
-
-export interface TraceInfoExistingContract extends TraceInfoBase {
- address: string;
- runtimeBytecode: string;
-}
-
-export type TraceInfo = TraceInfoNewContract | TraceInfoExistingContract;
-
-export enum BlockParamLiteral {
- Latest = 'latest',
-}
-
-export interface EvmCallStackEntry {
- structLog: StructLog;
- address: string;
-}
-
-export type EvmCallStack = EvmCallStackEntry[];
-
-export interface SourceSnippet {
- source: string;
- fileName: string;
- type: string;
- node: Parser.ASTNode;
- name: string | null;
- range: SingleFileSourceRange;
-}
diff --git a/packages/sol-cov/src/utils.ts b/packages/sol-cov/src/utils.ts
deleted file mode 100644
index d8bc65e73..000000000
--- a/packages/sol-cov/src/utils.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import { addressUtils, BigNumber } from '@0x/utils';
-import { OpCode, StructLog } from 'ethereum-types';
-import { addHexPrefix } from 'ethereumjs-util';
-import * as _ from 'lodash';
-
-import { ContractData, LineColumn, SingleFileSourceRange } from './types';
-
-// This is the minimum length of valid contract bytecode. The Solidity compiler
-// metadata is 86 bytes. If you add the '0x' prefix, we get 88.
-const MIN_CONTRACT_BYTECODE_LENGTH = 88;
-
-export const utils = {
- compareLineColumn(lhs: LineColumn, rhs: LineColumn): number {
- return lhs.line !== rhs.line ? lhs.line - rhs.line : lhs.column - rhs.column;
- },
- removeHexPrefix(hex: string): string {
- const hexPrefix = '0x';
- return hex.startsWith(hexPrefix) ? hex.slice(hexPrefix.length) : hex;
- },
- isRangeInside(childRange: SingleFileSourceRange, parentRange: SingleFileSourceRange): boolean {
- return (
- utils.compareLineColumn(parentRange.start, childRange.start) <= 0 &&
- utils.compareLineColumn(childRange.end, parentRange.end) <= 0
- );
- },
- bytecodeToBytecodeRegex(bytecode: string): string {
- const bytecodeRegex = bytecode
- // Library linking placeholder: __ConvertLib____________________________
- .replace(/_.*_/, '.*')
- // Last 86 characters is solidity compiler metadata that's different between compilations
- .replace(/.{86}$/, '')
- // Libraries contain their own address at the beginning of the code and it's impossible to know it in advance
- .replace(/^0x730000000000000000000000000000000000000000/, '0x73........................................');
- // HACK: Node regexes can't be longer that 32767 characters. Contracts bytecode can. We just truncate the regexes. It's safe in practice.
- const MAX_REGEX_LENGTH = 32767;
- const truncatedBytecodeRegex = bytecodeRegex.slice(0, MAX_REGEX_LENGTH);
- return truncatedBytecodeRegex;
- },
- getContractDataIfExists(contractsData: ContractData[], bytecode: string): ContractData | undefined {
- if (!bytecode.startsWith('0x')) {
- throw new Error(`0x hex prefix missing: ${bytecode}`);
- }
- const contractData = _.find(contractsData, contractDataCandidate => {
- const bytecodeRegex = utils.bytecodeToBytecodeRegex(contractDataCandidate.bytecode);
- // If the bytecode is less than the minimum length, we are probably
- // dealing with an interface. This isn't what we're looking for.
- if (bytecodeRegex.length < MIN_CONTRACT_BYTECODE_LENGTH) {
- return false;
- }
- const runtimeBytecodeRegex = utils.bytecodeToBytecodeRegex(contractDataCandidate.runtimeBytecode);
- if (runtimeBytecodeRegex.length < MIN_CONTRACT_BYTECODE_LENGTH) {
- return false;
- }
- // We use that function to find by bytecode or runtimeBytecode. Those are quasi-random strings so
- // collisions are practically impossible and it allows us to reuse that code
- return !_.isNull(bytecode.match(bytecodeRegex)) || !_.isNull(bytecode.match(runtimeBytecodeRegex));
- });
- return contractData;
- },
- isCallLike(op: OpCode): boolean {
- return _.includes([OpCode.CallCode, OpCode.StaticCall, OpCode.Call, OpCode.DelegateCall], op);
- },
- isEndOpcode(op: OpCode): boolean {
- return _.includes([OpCode.Return, OpCode.Stop, OpCode.Revert, OpCode.Invalid, OpCode.SelfDestruct], op);
- },
- getAddressFromStackEntry(stackEntry: string): string {
- const hexBase = 16;
- return addressUtils.padZeros(new BigNumber(addHexPrefix(stackEntry)).toString(hexBase));
- },
- normalizeStructLogs(structLogs: StructLog[]): StructLog[] {
- if (structLogs[0].depth === 1) {
- // Geth uses 1-indexed depth counter whilst ganache starts from 0
- const newStructLogs = _.map(structLogs, structLog => ({
- ...structLog,
- depth: structLog.depth - 1,
- }));
- return newStructLogs;
- }
- return structLogs;
- },
- getRange(sourceCode: string, range: SingleFileSourceRange): string {
- const lines = sourceCode.split('\n').slice(range.start.line - 1, range.end.line);
- lines[lines.length - 1] = lines[lines.length - 1].slice(0, range.end.column);
- lines[0] = lines[0].slice(range.start.column);
- return lines.join('\n');
- },
-};
diff --git a/packages/sol-cov/test/collect_coverage_entries_test.ts b/packages/sol-cov/test/collect_coverage_entries_test.ts
deleted file mode 100644
index 7832ec316..000000000
--- a/packages/sol-cov/test/collect_coverage_entries_test.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-import * as chai from 'chai';
-import * as fs from 'fs';
-import * as _ from 'lodash';
-import 'mocha';
-import * as path from 'path';
-
-import { collectCoverageEntries } from '../src/collect_coverage_entries';
-import { utils } from '../src/utils';
-
-const expect = chai.expect;
-
-describe('Collect coverage entries', () => {
- describe('#collectCoverageEntries', () => {
- it('correctly collects coverage entries for Simplest contract', () => {
- const simplestContractBaseName = 'Simplest.sol';
- const simplestContractFileName = path.resolve(__dirname, 'fixtures/contracts', simplestContractBaseName);
- const simplestContract = fs.readFileSync(simplestContractFileName).toString();
- const coverageEntries = collectCoverageEntries(simplestContract);
- expect(coverageEntries.fnMap).to.be.deep.equal({});
- expect(coverageEntries.branchMap).to.be.deep.equal({});
- expect(coverageEntries.statementMap).to.be.deep.equal({});
- expect(coverageEntries.modifiersStatementIds).to.be.deep.equal([]);
- });
- it('correctly collects coverage entries for SimpleStorage contract', () => {
- const simpleStorageContractBaseName = 'SimpleStorage.sol';
- const simpleStorageContractFileName = path.resolve(
- __dirname,
- 'fixtures/contracts',
- simpleStorageContractBaseName,
- );
- const simpleStorageContract = fs.readFileSync(simpleStorageContractFileName).toString();
- const coverageEntries = collectCoverageEntries(simpleStorageContract);
- const fnIds = _.keys(coverageEntries.fnMap);
- expect(coverageEntries.fnMap[fnIds[0]].name).to.be.equal('set');
- // tslint:disable-next-line:custom-no-magic-numbers
- expect(coverageEntries.fnMap[fnIds[0]].line).to.be.equal(5);
- const setFunction = `function set(uint x) {
- storedData = x;
- }`;
- expect(utils.getRange(simpleStorageContract, coverageEntries.fnMap[fnIds[0]].loc)).to.be.equal(setFunction);
- expect(coverageEntries.fnMap[fnIds[1]].name).to.be.equal('get');
- // tslint:disable-next-line:custom-no-magic-numbers
- expect(coverageEntries.fnMap[fnIds[1]].line).to.be.equal(8);
- const getFunction = `function get() constant returns (uint retVal) {
- return storedData;
- }`;
- expect(utils.getRange(simpleStorageContract, coverageEntries.fnMap[fnIds[1]].loc)).to.be.equal(getFunction);
- expect(coverageEntries.branchMap).to.be.deep.equal({});
- const statementIds = _.keys(coverageEntries.statementMap);
- expect(utils.getRange(simpleStorageContract, coverageEntries.statementMap[statementIds[1]])).to.be.equal(
- 'storedData = x',
- );
- expect(utils.getRange(simpleStorageContract, coverageEntries.statementMap[statementIds[3]])).to.be.equal(
- 'return storedData;',
- );
- expect(coverageEntries.modifiersStatementIds).to.be.deep.equal([]);
- });
- it('correctly collects coverage entries for AllSolidityFeatures contract', () => {
- const simpleStorageContractBaseName = 'AllSolidityFeatures.sol';
- const simpleStorageContractFileName = path.resolve(
- __dirname,
- 'fixtures/contracts',
- simpleStorageContractBaseName,
- );
- const simpleStorageContract = fs.readFileSync(simpleStorageContractFileName).toString();
- const coverageEntries = collectCoverageEntries(simpleStorageContract);
- const fnDescriptions = _.values(coverageEntries.fnMap);
- const fnNames = _.map(fnDescriptions, fnDescription => fnDescription.name);
- const expectedFnNames = [
- 'f',
- 'c',
- 'test',
- 'getChoice',
- 'Base',
- 'Derived',
- 'f',
- 'f',
- '',
- 'g',
- 'setData',
- 'getData',
- 'sendHalf',
- 'insert',
- 'remove',
- 'contains',
- 'iterate_start',
- 'iterate_valid',
- 'iterate_advance',
- 'iterate_get',
- 'insert',
- 'sum',
- 'restricted',
- 'DualIndex',
- 'set',
- 'transfer_ownership',
- 'lookup',
- '',
- '',
- 'sum',
- 'someFunction',
- 'fun',
- 'at',
- 'test',
- 'get',
- 'returnNumber',
- 'alloc',
- 'ham',
- 'getMyTuple',
- 'ham',
- 'abstain',
- 'foobar',
- 'foobar',
- 'a',
- ];
- expect(fnNames).to.be.deep.equal(expectedFnNames);
-
- const branchDescriptions = _.values(coverageEntries.branchMap);
- const branchLines = _.map(branchDescriptions, branchDescription => branchDescription.line);
- // tslint:disable-next-line:custom-no-magic-numbers
- expect(branchLines).to.be.deep.equal([94, 115, 119, 130, 151, 187]);
- const branchTypes = _.map(branchDescriptions, branchDescription => branchDescription.type);
- expect(branchTypes).to.be.deep.equal(['if', 'if', 'if', 'if', 'binary-expr', 'if']);
- });
-
- it('correctly ignores all coverage entries for Ignore contract', () => {
- const solcovIgnoreContractBaseName = 'SolcovIgnore.sol';
- const solcovIgnoreContractFileName = path.resolve(
- __dirname,
- 'fixtures/contracts',
- solcovIgnoreContractBaseName,
- );
- const solcovIgnoreContract = fs.readFileSync(solcovIgnoreContractFileName).toString();
- const coverageEntries = collectCoverageEntries(solcovIgnoreContract);
- const fnIds = _.keys(coverageEntries.fnMap);
-
- expect(fnIds.length).to.be.equal(1);
- expect(coverageEntries.fnMap[fnIds[0]].name).to.be.equal('set');
- // tslint:disable-next-line:custom-no-magic-numbers
- expect(coverageEntries.fnMap[fnIds[0]].line).to.be.equal(6);
- const setFunction = `function set(uint x) public {
- /* solcov ignore next */
- storedData = x;
- }`;
- expect(utils.getRange(solcovIgnoreContract, coverageEntries.fnMap[fnIds[0]].loc)).to.be.equal(setFunction);
-
- expect(coverageEntries.branchMap).to.be.deep.equal({});
- const statementIds = _.keys(coverageEntries.statementMap);
- expect(utils.getRange(solcovIgnoreContract, coverageEntries.statementMap[statementIds[0]])).to.be.equal(
- setFunction,
- );
- expect(statementIds.length).to.be.equal(1);
- expect(coverageEntries.modifiersStatementIds.length).to.be.equal(0);
- });
- });
-});
diff --git a/packages/sol-cov/test/fixtures/contracts/AllSolidityFeatures.sol b/packages/sol-cov/test/fixtures/contracts/AllSolidityFeatures.sol
deleted file mode 100644
index 21137347e..000000000
--- a/packages/sol-cov/test/fixtures/contracts/AllSolidityFeatures.sol
+++ /dev/null
@@ -1,413 +0,0 @@
-// Examples taken from the Solidity documentation online.
-
-// for pragma version numbers, see https://docs.npmjs.com/misc/semver#versions
-pragma solidity 0.4.0;
-pragma solidity ^0.4.0;
-
-import "SomeFile.sol";
-import "SomeFile.sol" as SomeOtherFile;
-import * as SomeSymbol from "AnotherFile.sol";
-import {symbol1 as alias, symbol2} from "File.sol";
-
-interface i {
- function f();
-}
-
-contract c {
- function c()
- {
- val1 = 1 wei; // 1
- val2 = 1 szabo; // 1 * 10 ** 12
- val3 = 1 finney; // 1 * 10 ** 15
- val4 = 1 ether; // 1 * 10 ** 18
- }
- uint256 val1;
- uint256 val2;
- uint256 val3;
- uint256 val4;
-}
-
-contract test {
- enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
-
- function test()
- {
- choices = ActionChoices.GoStraight;
- }
- function getChoice() returns (uint d)
- {
- d = uint256(choices);
- }
- ActionChoices choices;
-}
-
-contract Base {
- function Base(uint i)
- {
- m_i = i;
- }
- uint public m_i;
-}
-contract Derived is Base(0) {
- function Derived(uint i) Base(i) {}
-}
-
-contract C {
- uint248 x; // 31 bytes: slot 0, offset 0
- uint16 y; // 2 bytes: slot 1, offset 0 (does not fit in slot 0)
- uint240 z; // 30 bytes: slot 1, offset 2 bytes
- uint8 a; // 1 byte: slot 2, offset 0 bytes
- struct S {
- uint8 a; // 1 byte, slot +0, offset 0 bytes
- uint256 b; // 32 bytes, slot +1, offset 0 bytes (does not fit)
- }
- S structData; // 2 slots, slot 3, offset 0 bytes (does not really apply)
- uint8 alpha; // 1 byte, slot 4 (start new slot after struct)
- uint16[3] beta; // 3*16 bytes, slots 5+6 (start new slot for array)
- uint8 gamma; // 1 byte, slot 7 (start new slot after array)
-}
-
-contract test {
- function f(uint x, uint y) returns (uint z) {
- var c = x + 3;
- var b = 7 + (c * (8 - 7)) - x;
- return -(-b | 0);
- }
-}
-
-contract test {
- function f(uint x, uint y) returns (uint z) {
- return 10;
- }
-}
-
-contract c {
- function () returns (uint) { return g(8); }
- function g(uint pos) internal returns (uint) { setData(pos, 8); return getData(pos); }
- function setData(uint pos, uint value) internal { data[pos] = value; }
- function getData(uint pos) internal { return data[pos]; }
- mapping(uint => uint) data;
-}
-
-contract Sharer {
- function sendHalf(address addr) returns (uint balance) {
- if (!addr.send(msg.value/2))
- throw; // also reverts the transfer to Sharer
- return address(this).balance;
- }
-}
-
-/// @dev Models a modifiable and iterable set of uint values.
-library IntegerSet
-{
- struct data
- {
- /// Mapping item => index (or zero if not present)
- mapping(uint => uint) index;
- /// Items by index (index 0 is invalid), items with index[item] == 0 are invalid.
- uint[] items;
- /// Number of stored items.
- uint size;
- }
- function insert(data storage self, uint value) returns (bool alreadyPresent)
- {
- uint index = self.index[value];
- if (index > 0)
- return true;
- else
- {
- if (self.items.length == 0) self.items.length = 1;
- index = self.items.length++;
- self.items[index] = value;
- self.index[value] = index;
- self.size++;
- return false;
- }
- }
- function remove(data storage self, uint value) returns (bool success)
- {
- uint index = self.index[value];
- if (index == 0)
- return false;
- delete self.index[value];
- delete self.items[index];
- self.size --;
- }
- function contains(data storage self, uint value) returns (bool)
- {
- return self.index[value] > 0;
- }
- function iterate_start(data storage self) returns (uint index)
- {
- return iterate_advance(self, 0);
- }
- function iterate_valid(data storage self, uint index) returns (bool)
- {
- return index < self.items.length;
- }
- function iterate_advance(data storage self, uint index) returns (uint r_index)
- {
- index++;
- while (iterate_valid(self, index) && self.index[self.items[index]] == index)
- index++;
- return index;
- }
- function iterate_get(data storage self, uint index) returns (uint value)
- {
- return self.items[index];
- }
-}
-
-/// How to use it:
-contract User
-{
- /// Just a struct holding our data.
- IntegerSet.data data;
- /// Insert something
- function insert(uint v) returns (uint size)
- {
- /// Sends `data` via reference, so IntegerSet can modify it.
- IntegerSet.insert(data, v);
- /// We can access members of the struct - but we should take care not to mess with them.
- return data.size;
- }
- /// Computes the sum of all stored data.
- function sum() returns (uint s)
- {
- for (var i = IntegerSet.iterate_start(data); IntegerSet.iterate_valid(data, i); i = IntegerSet.iterate_advance(data, i))
- s += IntegerSet.iterate_get(data, i);
- }
-}
-
-// This broke it at one point (namely the modifiers).
-contract DualIndex {
- mapping(uint => mapping(uint => uint)) data;
- address public admin;
-
- modifier restricted { if (msg.sender == admin) _; }
-
- function DualIndex() {
- admin = msg.sender;
- }
-
- function set(uint key1, uint key2, uint value) restricted {
- uint[2][4] memory defaults; // "memory" broke things at one time.
- data[key1][key2] = value;
- }
-
- function transfer_ownership(address _admin) restricted {
- admin = _admin;
- }
-
- function lookup(uint key1, uint key2) returns(uint) {
- return data[key1][key2];
- }
-}
-
-contract A {
-
-}
-
-contract B {
-
-}
-
-contract C is A, B {
-
-}
-
-contract TestPrivate
-{
- uint private value;
-}
-
-contract TestInternal
-{
- uint internal value;
-}
-
-contract FromSolparse is A, B, TestPrivate, TestInternal {
- function() {
- uint a = 6 ** 9;
- var (x) = 100;
- uint y = 2 days;
- }
-}
-
-contract CommentedOutFunction {
- // FYI: This empty function, as well as the commented
- // out function below (bad code) is important to this test.
- function() {
-
- }
-
- // function something()
- // uint x = 10;
- // }
-}
-
-library VarHasBrackets {
- string constant specialRight = "}";
- //string storage specialLeft = "{";
-}
-
-library UsingExampleLibrary {
- function sum(uint[] storage self) returns (uint s) {
- for (uint i = 0; i < self.length; i++)
- s += self[i];
- }
-}
-
-contract UsingExampleContract {
- using UsingExampleLibrary for uint[];
-}
-
-contract NewStuff {
- uint[] b;
-
- function someFunction() payable {
- string storage a = hex"ab1248fe";
- b[2+2];
- }
-}
-
-// modifier with expression
-contract MyContract {
- function fun() mymodifier(foo.bar()) {}
-}
-
-library GetCode {
- function at(address _addr) returns (bytes o_code) {
- assembly {
- // retrieve the size of the code, this needs assembly
- let size := extcodesize(_addr)
- // allocate output byte array - this could also be done without assembly
- // by using o_code = new bytes(size)
- o_code := mload(0x40)
- // new "memory end" including padding
- mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
- // store length in memory
- mstore(o_code, size)
- // actually retrieve the code, this needs assembly
- extcodecopy(_addr, add(o_code, 0x20), 0, size)
- }
- }
-}
-
-contract assemblyLocalBinding {
- function test(){
- assembly {
- let v := 1
- let x := 0x00
- let y := x
- let z := "hello"
- }
- }
-}
-
-contract assemblyReturn {
- uint a = 10;
-
- function get() constant returns(uint) {
- assembly {
- mstore(0x40, sload(0))
- byte(0)
- address(0)
- return(0x40,32)
- }
- }
-}
-
-contract usesConst {
- uint const = 0;
-}
-
-contract memoryArrays {
- uint seven = 7;
-
- function returnNumber(uint number) returns (uint){
- return number;
- }
-
- function alloc() {
- uint[] memory a = new uint[](7);
- uint[] memory b = new uint[](returnNumber(seven));
- }
-}
-
-contract DeclarativeExpressions {
- uint a;
- uint b = 7;
- uint b2=0;
- uint public c;
- uint constant public d;
- uint public constant e;
- uint private constant f = 7;
- struct S { uint q;}
-
- function ham(S storage s1, uint[] storage arr) internal {
- uint x;
- uint y = 7;
- S storage s2 = s1;
- uint[] memory stor;
- uint[] storage stor2 = arr;
- }
-}
-
-contract VariableDeclarationTuple {
- function getMyTuple() returns (bool, bool){
- return (true, false);
- }
-
- function ham (){
- var (x, y) = (10, 20);
- var (a, b) = getMyTuple();
- var (,c) = (10, 20);
- var (d,,) = (10, 20, 30);
- var (,e,,f,) = (10, 20, 30, 40, 50);
-
- var (
- num1, num2,
- num3, ,num5
- ) = (10, 20, 30, 40, 50);
- }
-}
-
-contract TypeIndexSpacing {
- uint [ 7 ] x;
- uint [] y;
-}
-
-contract Ballot {
-
- struct Voter {
- uint weight;
- bool voted;
- }
-
- function abstain() returns (bool) {
- return false;
- }
-
- function foobar() payable owner (myPrice) returns (uint[], address myAdd, string[] names) {}
- function foobar() payable owner (myPrice) returns (uint[], address myAdd, string[] names);
-
- Voter you = Voter(1, true);
-
- Voter me = Voter({
- weight: 2,
- voted: abstain()
- });
-
- Voter airbnb = Voter({
- weight: 2,
- voted: true,
- });
-}
-
-contract multilineReturn {
- function a() returns (uint x) {
- return
- 5;
- }
-}
diff --git a/packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol b/packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol
deleted file mode 100644
index e4b4ac246..000000000
--- a/packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol
+++ /dev/null
@@ -1,11 +0,0 @@
-pragma solidity ^0.4.21;
-
-contract SimpleStorage {
- uint public storedData;
- function set(uint x) {
- storedData = x;
- }
- function get() constant returns (uint retVal) {
- return storedData;
- }
-}
diff --git a/packages/sol-cov/test/fixtures/contracts/Simplest.sol b/packages/sol-cov/test/fixtures/contracts/Simplest.sol
deleted file mode 100644
index d71016e07..000000000
--- a/packages/sol-cov/test/fixtures/contracts/Simplest.sol
+++ /dev/null
@@ -1,2 +0,0 @@
-contract Simplest {
-}
diff --git a/packages/sol-cov/test/fixtures/contracts/SolcovIgnore.sol b/packages/sol-cov/test/fixtures/contracts/SolcovIgnore.sol
deleted file mode 100644
index a7977ffb4..000000000
--- a/packages/sol-cov/test/fixtures/contracts/SolcovIgnore.sol
+++ /dev/null
@@ -1,22 +0,0 @@
-pragma solidity ^0.4.21;
-
-contract SolcovIgnore {
- uint public storedData;
-
- function set(uint x) public {
- /* solcov ignore next */
- storedData = x;
- }
-
- /* solcov ignore next */
- function get() constant public returns (uint retVal) {
- return storedData;
- }
-}
-
-/* solcov ignore next */
-contract Ignore {
- function ignored() public returns (bool) {
- return false;
- }
-}
diff --git a/packages/sol-cov/test/instructions_test.ts b/packages/sol-cov/test/instructions_test.ts
deleted file mode 100644
index 058053cf9..000000000
--- a/packages/sol-cov/test/instructions_test.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import * as chai from 'chai';
-import 'mocha';
-
-import { constants } from '../src/constants';
-import { getPcToInstructionIndexMapping } from '../src/instructions';
-
-const expect = chai.expect;
-
-describe('instructions', () => {
- describe('#getPcToInstructionIndexMapping', () => {
- it('correctly maps pcs to instruction indexed', () => {
- // tslint:disable-next-line:custom-no-magic-numbers
- const bytecode = new Uint8Array([constants.PUSH1, 42, constants.PUSH2, 1, 2, constants.TIMESTAMP]);
- const pcToInstruction = getPcToInstructionIndexMapping(bytecode);
- const expectedPcToInstruction = { '0': 0, '2': 1, '5': 2 };
- expect(pcToInstruction).to.be.deep.equal(expectedPcToInstruction);
- });
- });
-});
diff --git a/packages/sol-cov/test/sol_compiler_artifact_adapter_test.ts b/packages/sol-cov/test/sol_compiler_artifact_adapter_test.ts
deleted file mode 100644
index 9c58d2cef..000000000
--- a/packages/sol-cov/test/sol_compiler_artifact_adapter_test.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import * as chai from 'chai';
-import * as _ from 'lodash';
-import 'mocha';
-import * as path from 'path';
-
-import { SolCompilerArtifactAdapter } from '../src/artifact_adapters/sol_compiler_artifact_adapter';
-
-const expect = chai.expect;
-
-describe('SolCompilerArtifactAdapter', () => {
- describe('#collectContractsData', () => {
- it('correctly collects contracts data', async () => {
- const artifactsPath = path.resolve(__dirname, 'fixtures/artifacts');
- const sourcesPath = path.resolve(__dirname, 'fixtures/contracts');
- const zeroExArtifactsAdapter = new SolCompilerArtifactAdapter(artifactsPath, sourcesPath);
- const contractsData = await zeroExArtifactsAdapter.collectContractsDataAsync();
- _.forEach(contractsData, contractData => {
- expect(contractData).to.have.keys([
- 'sourceCodes',
- 'sources',
- 'sourceMap',
- 'sourceMapRuntime',
- 'bytecode',
- 'runtimeBytecode',
- ]);
- });
- });
- });
-});
diff --git a/packages/sol-cov/test/source_maps_test.ts b/packages/sol-cov/test/source_maps_test.ts
deleted file mode 100644
index 5820bedd7..000000000
--- a/packages/sol-cov/test/source_maps_test.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import * as chai from 'chai';
-import * as fs from 'fs';
-import * as _ from 'lodash';
-import 'mocha';
-import * as path from 'path';
-
-import { getLocationByOffset, parseSourceMap } from '../src/source_maps';
-
-const expect = chai.expect;
-
-const simplestContractBaseName = 'Simplest.sol';
-const simplestContractFileName = path.resolve(__dirname, 'fixtures/contracts', simplestContractBaseName);
-const simplestContract = fs.readFileSync(simplestContractFileName).toString();
-
-describe('source maps', () => {
- describe('#getLocationByOffset', () => {
- it('correctly computes location by offset', () => {
- const locationByOffset = getLocationByOffset(simplestContract);
- const expectedLocationByOffset = {
- '0': { line: 1, column: 0 },
- '1': { line: 1, column: 1 },
- '2': { line: 1, column: 2 },
- '3': { line: 1, column: 3 },
- '4': { line: 1, column: 4 },
- '5': { line: 1, column: 5 },
- '6': { line: 1, column: 6 },
- '7': { line: 1, column: 7 },
- '8': { line: 1, column: 8 },
- '9': { line: 1, column: 9 },
- '10': { line: 1, column: 10 },
- '11': { line: 1, column: 11 },
- '12': { line: 1, column: 12 },
- '13': { line: 1, column: 13 },
- '14': { line: 1, column: 14 },
- '15': { line: 1, column: 15 },
- '16': { line: 1, column: 16 },
- '17': { line: 1, column: 17 },
- '18': { line: 1, column: 18 },
- '19': { line: 1, column: 19 },
- '20': { line: 2, column: 0 },
- '21': { line: 2, column: 1 },
- '22': { line: 3, column: 0 },
- };
- expect(locationByOffset).to.be.deep.equal(expectedLocationByOffset);
- });
- });
- describe('#parseSourceMap', () => {
- it('correctly parses the source map', () => {
- // This is the source map and bytecode for an empty contract like Example.sol
- const srcMap = '0:21:0:-;;;;;;;;;;;;;;;;;';
- const bytecodeHex =
- '60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00a165627a7a72305820377cdef690e46589f40efeef14d8ef73504af059fb3fd46f1da3cd2fc52ef7890029';
- const sources = [simplestContractBaseName];
- const pcToSourceRange = parseSourceMap([simplestContract], srcMap, bytecodeHex, sources);
- const expectedSourceRange = {
- location: {
- start: { line: 1, column: 0 },
- end: { line: 2, column: 1 },
- },
- fileName: simplestContractBaseName,
- };
- _.forEach(pcToSourceRange, sourceRange => {
- // Solidity source maps are too short and we map some instructions to undefined
- // Source: https://github.com/ethereum/solidity/issues/3741
- if (!_.isUndefined(sourceRange)) {
- expect(sourceRange).to.be.deep.equal(expectedSourceRange);
- }
- });
- });
- });
-});
diff --git a/packages/sol-cov/test/trace_test.ts b/packages/sol-cov/test/trace_test.ts
deleted file mode 100644
index 7a034362c..000000000
--- a/packages/sol-cov/test/trace_test.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import * as chai from 'chai';
-import { OpCode, StructLog } from 'ethereum-types';
-import * as _ from 'lodash';
-import 'mocha';
-
-import { getTracesByContractAddress } from '../src/trace';
-
-const expect = chai.expect;
-
-const DEFAULT_STRUCT_LOG: StructLog = {
- depth: 0,
- error: '',
- gas: 0,
- gasCost: 0,
- memory: [],
- op: OpCode.Invalid,
- pc: 0,
- stack: [],
- storage: {},
-};
-
-function addDefaultStructLogFields(compactStructLog: Partial<StructLog> & { op: OpCode; depth: number }): StructLog {
- return { ...DEFAULT_STRUCT_LOG, ...compactStructLog };
-}
-
-describe('Trace', () => {
- describe('#getTracesByContractAddress', () => {
- it('correctly splits trace by contract address', () => {
- const delegateCallAddress = '0x0000000000000000000000000000000000000002';
- const trace = [
- {
- op: OpCode.DelegateCall,
- stack: [delegateCallAddress, '0x'],
- depth: 0,
- },
- {
- op: OpCode.Return,
- depth: 1,
- },
- {
- op: OpCode.Return,
- depth: 0,
- },
- ];
- const fullTrace = _.map(trace, compactStructLog => addDefaultStructLogFields(compactStructLog));
- const startAddress = '0x0000000000000000000000000000000000000001';
- const traceByContractAddress = getTracesByContractAddress(fullTrace, startAddress);
- const expectedTraceByContractAddress = {
- [startAddress]: [fullTrace[0], fullTrace[2]],
- [delegateCallAddress]: [fullTrace[1]],
- };
- expect(traceByContractAddress).to.be.deep.equal(expectedTraceByContractAddress);
- });
- });
-});
diff --git a/packages/sol-cov/test/utils_test.ts b/packages/sol-cov/test/utils_test.ts
deleted file mode 100644
index 6fc8fcfe1..000000000
--- a/packages/sol-cov/test/utils_test.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import * as chai from 'chai';
-import * as dirtyChai from 'dirty-chai';
-import 'mocha';
-
-import { utils } from '../src/utils';
-
-chai.use(dirtyChai);
-const expect = chai.expect;
-
-describe('utils', () => {
- describe('#compareLineColumn', () => {
- it('correctly compares LineColumns', () => {
- expect(utils.compareLineColumn({ line: 1, column: 3 }, { line: 1, column: 4 })).to.be.lessThan(0);
- expect(utils.compareLineColumn({ line: 1, column: 4 }, { line: 1, column: 3 })).to.be.greaterThan(0);
- expect(utils.compareLineColumn({ line: 1, column: 3 }, { line: 1, column: 3 })).to.be.equal(0);
- expect(utils.compareLineColumn({ line: 0, column: 2 }, { line: 1, column: 0 })).to.be.lessThan(0);
- expect(utils.compareLineColumn({ line: 1, column: 0 }, { line: 0, column: 2 })).to.be.greaterThan(0);
- });
- });
-
- describe('#isRangeInside', () => {
- it('returns true if inside', () => {
- expect(
- utils.isRangeInside(
- { start: { line: 1, column: 3 }, end: { line: 1, column: 4 } },
- { start: { line: 1, column: 2 }, end: { line: 1, column: 5 } },
- ),
- ).to.be.true();
- });
- it('returns true if the same', () => {
- expect(
- utils.isRangeInside(
- { start: { line: 1, column: 3 }, end: { line: 1, column: 4 } },
- { start: { line: 1, column: 3 }, end: { line: 1, column: 4 } },
- ),
- ).to.be.true();
- });
- it('returns false if not inside', () => {
- expect(
- utils.isRangeInside(
- { start: { line: 1, column: 3 }, end: { line: 1, column: 4 } },
- { start: { line: 1, column: 4 }, end: { line: 1, column: 4 } },
- ),
- ).to.be.false();
- expect(
- utils.isRangeInside(
- { start: { line: 1, column: 3 }, end: { line: 1, column: 4 } },
- { start: { line: 1, column: 4 }, end: { line: 1, column: 5 } },
- ),
- ).to.be.false();
- });
- });
-});
diff --git a/packages/sol-cov/tsconfig.json b/packages/sol-cov/tsconfig.json
deleted file mode 100644
index 2ee711adc..000000000
--- a/packages/sol-cov/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "../../tsconfig",
- "compilerOptions": {
- "outDir": "lib",
- "rootDir": "."
- },
- "include": ["./src/**/*", "./test/**/*"]
-}
diff --git a/packages/sol-cov/tslint.json b/packages/sol-cov/tslint.json
deleted file mode 100644
index 631f46bca..000000000
--- a/packages/sol-cov/tslint.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "extends": ["@0x/tslint-config"],
- "rules": {
- "completed-docs": false
- }
-}
diff --git a/packages/sol-cov/typedoc-tsconfig.json b/packages/sol-cov/typedoc-tsconfig.json
deleted file mode 100644
index c9b0af1ae..000000000
--- a/packages/sol-cov/typedoc-tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../typedoc-tsconfig",
- "compilerOptions": {
- "outDir": "lib"
- },
- "include": ["./src/**/*", "./test/**/*"]
-}