diff options
Diffstat (limited to 'packages/sol-cov')
-rw-r--r-- | packages/sol-cov/CHANGELOG.json | 18 | ||||
-rw-r--r-- | packages/sol-cov/CHANGELOG.md | 10 | ||||
-rw-r--r-- | packages/sol-cov/compiler.json | 18 | ||||
-rw-r--r-- | packages/sol-cov/package.json | 24 | ||||
-rw-r--r-- | packages/sol-cov/src/collect_contract_data.ts | 27 | ||||
-rw-r--r-- | packages/sol-cov/src/coverage_manager.ts | 63 | ||||
-rw-r--r-- | packages/sol-cov/src/coverage_subprovider.ts | 10 | ||||
-rw-r--r-- | packages/sol-cov/src/utils.ts | 4 | ||||
-rw-r--r-- | packages/sol-cov/test/collect_contracts_data_test.ts | 3 |
9 files changed, 113 insertions, 64 deletions
diff --git a/packages/sol-cov/CHANGELOG.json b/packages/sol-cov/CHANGELOG.json index 508b70631..468957fe3 100644 --- a/packages/sol-cov/CHANGELOG.json +++ b/packages/sol-cov/CHANGELOG.json @@ -1,5 +1,23 @@ [ { + "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": [ diff --git a/packages/sol-cov/CHANGELOG.md b/packages/sol-cov/CHANGELOG.md index fa8039919..9e2995328 100644 --- a/packages/sol-cov/CHANGELOG.md +++ b/packages/sol-cov/CHANGELOG.md @@ -5,11 +5,19 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.0.10 - _May 5, 2018_ + + * Dependencies updated + +## v0.0.9 - _May 4, 2018_ + + * Dependencies updated + ## v0.0.8 - _April 18, 2018_ * Dependencies updated -## v0.0.7 - _April 12, 2018_ +## v0.0.7 - _April 11, 2018_ * Dependencies updated diff --git a/packages/sol-cov/compiler.json b/packages/sol-cov/compiler.json new file mode 100644 index 000000000..a6a0c6d3a --- /dev/null +++ b/packages/sol-cov/compiler.json @@ -0,0 +1,18 @@ +{ + "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/package.json b/packages/sol-cov/package.json index 886ca52c2..6268df4c7 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -1,20 +1,20 @@ { "name": "@0xproject/sol-cov", - "version": "0.0.8", + "version": "0.0.10", "description": "Generate coverage reports for Solidity code", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { "build:watch": "tsc -w", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "test": "run-s clean build compile_test run_mocha", "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 lib/test/**/*_test.js --exit", - "clean": "shx rm -rf lib scripts", + "clean": "shx rm -rf lib scripts test/fixtures/artifacts src/artifacts", "build": "copyfiles 'test/fixtures/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", - "compile_test": "node ../deployer/lib/src/cli.js compile --contracts SimpleStorage --contracts-dir test/fixtures/contracts --artifacts-dir test/fixtures/artifacts", + "compile_test": "node ../sol-compiler/lib/src/cli.js compile", "manual:postpublish": "yarn build; node ./scripts/postpublish.js", "docs:stage": "yarn build && node ./scripts/stage_docs.js", "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES", @@ -43,21 +43,23 @@ }, "homepage": "https://github.com/0xProject/0x.js/packages/sol-cov/README.md", "dependencies": { - "@0xproject/subproviders": "^0.9.0", - "@0xproject/types": "^0.6.1", - "@0xproject/typescript-typings": "^0.2.0", + "@0xproject/subproviders": "^0.10.1", + "@0xproject/types": "^0.6.3", + "@0xproject/typescript-typings": "^0.3.1", + "@0xproject/utils": "^0.6.1", "ethereumjs-util": "^5.1.1", "glob": "^7.1.2", "istanbul": "^0.4.5", "lodash": "^4.17.4", + "mkdirp": "^0.5.1", "semaphore-async-await": "^1.5.1", "solidity-parser-antlr": "^0.2.8" }, "devDependencies": { - "@0xproject/deployer": "^0.3.5", - "@0xproject/monorepo-scripts": "^0.1.18", - "@0xproject/tslint-config": "^0.4.16", - "@types/istanbul": "^0.4.29", + "@0xproject/monorepo-scripts": "^0.1.19", + "@0xproject/tslint-config": "^0.4.17", + "@types/istanbul": "^0.4.30", + "@types/mkdirp": "^0.5.1", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", "chai": "^4.0.1", diff --git a/packages/sol-cov/src/collect_contract_data.ts b/packages/sol-cov/src/collect_contract_data.ts index 1d8bc7178..2c2a12835 100644 --- a/packages/sol-cov/src/collect_contract_data.ts +++ b/packages/sol-cov/src/collect_contract_data.ts @@ -5,28 +5,27 @@ import * as path from 'path'; import { ContractData } from './types'; -export const collectContractsData = (artifactsPath: string, sourcesPath: string, networkId: number) => { +export const collectContractsData = (artifactsPath: string, sourcesPath: string) => { const artifactsGlob = `${artifactsPath}/**/*.json`; const artifactFileNames = glob.sync(artifactsGlob, { absolute: true }); - const contractsDataIfExists: Array<ContractData | {}> = _.map(artifactFileNames, artifactFileName => { + const contractsData: ContractData[] = []; + _.forEach(artifactFileNames, artifactFileName => { const artifact = JSON.parse(fs.readFileSync(artifactFileName).toString()); - const sources = artifact.networks[networkId].sources; - const contractName = artifact.contract_name; + const sources = _.keys(artifact.sources); + const contractName = artifact.contractName; // We don't compute coverage for dependencies - const sourceCodes = _.map(sources, (source: string) => fs.readFileSync(source).toString()); - if (_.isUndefined(artifact.networks[networkId])) { - throw new Error(`No ${contractName} artifacts found for networkId ${networkId}`); - } + const sourceCodes = _.map(sources, (source: string) => + fs.readFileSync(path.join(sourcesPath, source)).toString(), + ); const contractData = { sourceCodes, sources, - sourceMap: artifact.networks[networkId].source_map, - sourceMapRuntime: artifact.networks[networkId].source_map_runtime, - runtimeBytecode: artifact.networks[networkId].runtime_bytecode, - bytecode: artifact.networks[networkId].bytecode, + bytecode: artifact.compilerOutput.evm.bytecode.object, + sourceMap: artifact.compilerOutput.evm.bytecode.sourceMap, + runtimeBytecode: artifact.compilerOutput.evm.deployedBytecode.object, + sourceMapRuntime: artifact.compilerOutput.evm.deployedBytecode.sourceMap, }; - return contractData; + contractsData.push(contractData); }); - const contractsData = _.filter(contractsDataIfExists, contractData => !_.isEmpty(contractData)) as ContractData[]; return contractsData; }; diff --git a/packages/sol-cov/src/coverage_manager.ts b/packages/sol-cov/src/coverage_manager.ts index 230ccc3c9..800ca96dd 100644 --- a/packages/sol-cov/src/coverage_manager.ts +++ b/packages/sol-cov/src/coverage_manager.ts @@ -1,6 +1,9 @@ +import { promisify } from '@0xproject/utils'; +import { addHexPrefix } from 'ethereumjs-util'; import * as fs from 'fs'; import { Collector } from 'istanbul'; import * as _ from 'lodash'; +import * as mkdirp from 'mkdirp'; import * as path from 'path'; import { collectContractsData } from './collect_contract_data'; @@ -28,11 +31,32 @@ import { } from './types'; import { utils } from './utils'; +const mkdirpAsync = promisify<undefined>(mkdirp); + export class CoverageManager { + private _sourcesPath: string; private _traceInfos: TraceInfo[] = []; private _contractsData: ContractData[] = []; private _getContractCodeAsync: (address: string) => Promise<string>; - private static _getSingleFileCoverageForTrace( + constructor( + artifactsPath: string, + sourcesPath: string, + getContractCodeAsync: (address: string) => Promise<string>, + ) { + this._getContractCodeAsync = getContractCodeAsync; + this._sourcesPath = sourcesPath; + this._contractsData = collectContractsData(artifactsPath, this._sourcesPath); + } + public appendTraceInfo(traceInfo: TraceInfo): void { + this._traceInfos.push(traceInfo); + } + public async writeCoverageAsync(): Promise<void> { + const finalCoverage = await this._computeCoverageAsync(); + const stringifiedCoverage = JSON.stringify(finalCoverage, null, '\t'); + await mkdirpAsync('coverage'); + fs.writeFileSync('coverage/coverage.json', stringifiedCoverage); + } + private _getSingleFileCoverageForTrace( contractData: ContractData, coveredPcs: number[], pcToSourceRange: { [programCounter: number]: SourceRange }, @@ -94,11 +118,12 @@ export class CoverageManager { ); statementCoverage[modifierStatementId] = isModifierCovered; } + const absoluteFileName = path.join(this._sourcesPath, fileName); const partialCoverage = { - [contractData.sources[fileIndex]]: { + [absoluteFileName]: { ...coverageEntriesDescription, l: {}, // It's able to derive it from statement coverage - path: fileName, + path: absoluteFileName, f: functionCoverage, s: statementCoverage, b: branchCoverage, @@ -106,31 +131,13 @@ export class CoverageManager { }; return partialCoverage; } - constructor( - artifactsPath: string, - sourcesPath: string, - networkId: number, - getContractCodeAsync: (address: string) => Promise<string>, - ) { - this._getContractCodeAsync = getContractCodeAsync; - this._contractsData = collectContractsData(artifactsPath, sourcesPath, networkId); - } - public appendTraceInfo(traceInfo: TraceInfo): void { - this._traceInfos.push(traceInfo); - } - public async writeCoverageAsync(): Promise<void> { - const finalCoverage = await this._computeCoverageAsync(); - const jsonReplacer: null = null; - const numberOfJsonSpaces = 4; - const stringifiedCoverage = JSON.stringify(finalCoverage, jsonReplacer, numberOfJsonSpaces); - fs.writeFileSync('coverage/coverage.json', stringifiedCoverage); - } private async _computeCoverageAsync(): Promise<Coverage> { const collector = new Collector(); for (const traceInfo of this._traceInfos) { if (traceInfo.address !== constants.NEW_CONTRACT) { // Runtime transaction - const runtimeBytecode = (traceInfo as TraceInfoExistingContract).runtimeBytecode; + let runtimeBytecode = (traceInfo as TraceInfoExistingContract).runtimeBytecode; + runtimeBytecode = addHexPrefix(runtimeBytecode); const contractData = _.find(this._contractsData, { runtimeBytecode }) as ContractData; if (_.isUndefined(contractData)) { throw new Error(`Transaction to an unknown address: ${traceInfo.address}`); @@ -144,7 +151,7 @@ export class CoverageManager { contractData.sources, ); for (let fileIndex = 0; fileIndex < contractData.sources.length; fileIndex++) { - const singleFileCoverageForTrace = CoverageManager._getSingleFileCoverageForTrace( + const singleFileCoverageForTrace = this._getSingleFileCoverageForTrace( contractData, traceInfo.coveredPcs, pcToSourceRange, @@ -154,7 +161,8 @@ export class CoverageManager { } } else { // Contract creation transaction - const bytecode = (traceInfo as TraceInfoNewContract).bytecode; + let bytecode = (traceInfo as TraceInfoNewContract).bytecode; + bytecode = addHexPrefix(bytecode); const contractData = _.find(this._contractsData, contractDataCandidate => bytecode.startsWith(contractDataCandidate.bytecode), ) as ContractData; @@ -170,7 +178,7 @@ export class CoverageManager { contractData.sources, ); for (let fileIndex = 0; fileIndex < contractData.sources.length; fileIndex++) { - const singleFileCoverageForTrace = CoverageManager._getSingleFileCoverageForTrace( + const singleFileCoverageForTrace = this._getSingleFileCoverageForTrace( contractData, traceInfo.coveredPcs, pcToSourceRange, @@ -180,7 +188,6 @@ export class CoverageManager { } } } - // TODO: Remove any cast as soon as https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24233 gets merged - return (collector as any).getFinalCoverage(); + return collector.getFinalCoverage(); } } diff --git a/packages/sol-cov/src/coverage_subprovider.ts b/packages/sol-cov/src/coverage_subprovider.ts index 6504d5a46..b08291afb 100644 --- a/packages/sol-cov/src/coverage_subprovider.ts +++ b/packages/sol-cov/src/coverage_subprovider.ts @@ -28,19 +28,13 @@ export class CoverageSubprovider extends Subprovider { * Instantiates a CoverageSubprovider instance * @param artifactsPath Path to the smart contract artifacts * @param sourcesPath Path to the smart contract source files - * @param networkId network id * @param defaultFromAddress default from address to use when sending transactions */ - constructor(artifactsPath: string, sourcesPath: string, networkId: number, defaultFromAddress: string) { + constructor(artifactsPath: string, sourcesPath: string, defaultFromAddress: string) { super(); this._lock = new Lock(); this._defaultFromAddress = defaultFromAddress; - this._coverageManager = new CoverageManager( - artifactsPath, - sourcesPath, - networkId, - this._getContractCodeAsync.bind(this), - ); + this._coverageManager = new CoverageManager(artifactsPath, sourcesPath, this._getContractCodeAsync.bind(this)); } /** * Write the test coverage results to a file in Istanbul format. diff --git a/packages/sol-cov/src/utils.ts b/packages/sol-cov/src/utils.ts index f155043a1..d970c42ee 100644 --- a/packages/sol-cov/src/utils.ts +++ b/packages/sol-cov/src/utils.ts @@ -4,6 +4,10 @@ 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 && diff --git a/packages/sol-cov/test/collect_contracts_data_test.ts b/packages/sol-cov/test/collect_contracts_data_test.ts index 943a4a878..c7c1dfe32 100644 --- a/packages/sol-cov/test/collect_contracts_data_test.ts +++ b/packages/sol-cov/test/collect_contracts_data_test.ts @@ -12,8 +12,7 @@ describe('Collect contracts data', () => { it('correctly collects contracts data', () => { const artifactsPath = path.resolve(__dirname, 'fixtures/artifacts'); const sourcesPath = path.resolve(__dirname, 'fixtures/contracts'); - const networkId = 50; - const contractsData = collectContractsData(artifactsPath, sourcesPath, networkId); + const contractsData = collectContractsData(artifactsPath, sourcesPath); _.forEach(contractsData, contractData => { expect(contractData).to.have.keys([ 'sourceCodes', |