From 72b2a1c66fa9fb85ea8515645b97332eee204550 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 18 Apr 2018 22:22:39 +0200 Subject: Implement new artifacts format --- packages/sol-cov/src/collect_contract_data.ts | 21 +++++++++------------ packages/sol-cov/src/coverage_manager.ts | 10 ++++++++-- 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'packages/sol-cov/src') diff --git a/packages/sol-cov/src/collect_contract_data.ts b/packages/sol-cov/src/collect_contract_data.ts index 1d8bc7178..3d8a45cec 100644 --- a/packages/sol-cov/src/collect_contract_data.ts +++ b/packages/sol-cov/src/collect_contract_data.ts @@ -8,25 +8,22 @@ import { ContractData } from './types'; export const collectContractsData = (artifactsPath: string, sourcesPath: string, networkId: number) => { const artifactsGlob = `${artifactsPath}/**/*.json`; const artifactFileNames = glob.sync(artifactsGlob, { absolute: true }); - const contractsDataIfExists: Array = _.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 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..509c1cb99 100644 --- a/packages/sol-cov/src/coverage_manager.ts +++ b/packages/sol-cov/src/coverage_manager.ts @@ -130,7 +130,10 @@ export class CoverageManager { 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; + if (runtimeBytecode.startsWith('0x')) { + runtimeBytecode = runtimeBytecode.slice(2); + } const contractData = _.find(this._contractsData, { runtimeBytecode }) as ContractData; if (_.isUndefined(contractData)) { throw new Error(`Transaction to an unknown address: ${traceInfo.address}`); @@ -154,7 +157,10 @@ export class CoverageManager { } } else { // Contract creation transaction - const bytecode = (traceInfo as TraceInfoNewContract).bytecode; + let bytecode = (traceInfo as TraceInfoNewContract).bytecode; + if (bytecode.startsWith('0x')) { + bytecode = bytecode.slice(2); + } const contractData = _.find(this._contractsData, contractDataCandidate => bytecode.startsWith(contractDataCandidate.bytecode), ) as ContractData; -- cgit v1.2.3 From c9b8f2a397606f3667e5829b5a0364f9896daec5 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 7 May 2018 10:52:28 +0200 Subject: Fix sol-cov to work with the new artifacts format --- packages/sol-cov/src/collect_contract_data.ts | 4 ++- packages/sol-cov/src/coverage_manager.ts | 51 ++++++++++++++------------- 2 files changed, 30 insertions(+), 25 deletions(-) (limited to 'packages/sol-cov/src') diff --git a/packages/sol-cov/src/collect_contract_data.ts b/packages/sol-cov/src/collect_contract_data.ts index 3d8a45cec..bb20e98be 100644 --- a/packages/sol-cov/src/collect_contract_data.ts +++ b/packages/sol-cov/src/collect_contract_data.ts @@ -14,7 +14,9 @@ export const collectContractsData = (artifactsPath: string, sourcesPath: string, 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()); + const sourceCodes = _.map(sources, (source: string) => + fs.readFileSync(path.join(sourcesPath, source)).toString(), + ); const contractData = { sourceCodes, sources, diff --git a/packages/sol-cov/src/coverage_manager.ts b/packages/sol-cov/src/coverage_manager.ts index 509c1cb99..e932ac081 100644 --- a/packages/sol-cov/src/coverage_manager.ts +++ b/packages/sol-cov/src/coverage_manager.ts @@ -29,10 +29,31 @@ import { import { utils } from './utils'; export class CoverageManager { + private _sourcesPath: string; private _traceInfos: TraceInfo[] = []; private _contractsData: ContractData[] = []; private _getContractCodeAsync: (address: string) => Promise; - private static _getSingleFileCoverageForTrace( + constructor( + artifactsPath: string, + sourcesPath: string, + networkId: number, + getContractCodeAsync: (address: string) => Promise, + ) { + this._getContractCodeAsync = getContractCodeAsync; + this._sourcesPath = sourcesPath; + this._contractsData = collectContractsData(artifactsPath, this._sourcesPath, networkId); + } + public appendTraceInfo(traceInfo: TraceInfo): void { + this._traceInfos.push(traceInfo); + } + public async writeCoverageAsync(): Promise { + 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 _getSingleFileCoverageForTrace( contractData: ContractData, coveredPcs: number[], pcToSourceRange: { [programCounter: number]: SourceRange }, @@ -94,11 +115,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,25 +128,6 @@ export class CoverageManager { }; return partialCoverage; } - constructor( - artifactsPath: string, - sourcesPath: string, - networkId: number, - getContractCodeAsync: (address: string) => Promise, - ) { - this._getContractCodeAsync = getContractCodeAsync; - this._contractsData = collectContractsData(artifactsPath, sourcesPath, networkId); - } - public appendTraceInfo(traceInfo: TraceInfo): void { - this._traceInfos.push(traceInfo); - } - public async writeCoverageAsync(): Promise { - 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 { const collector = new Collector(); for (const traceInfo of this._traceInfos) { @@ -147,7 +150,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, @@ -176,7 +179,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, -- cgit v1.2.3 From 9e67e12732a0fc87f0000917e6bbf21c3c2db260 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 7 May 2018 14:04:58 +0200 Subject: Add removeHexPrefix util method --- packages/sol-cov/src/coverage_manager.ts | 8 ++------ packages/sol-cov/src/utils.ts | 4 ++++ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/sol-cov/src') diff --git a/packages/sol-cov/src/coverage_manager.ts b/packages/sol-cov/src/coverage_manager.ts index e932ac081..6a57d07c9 100644 --- a/packages/sol-cov/src/coverage_manager.ts +++ b/packages/sol-cov/src/coverage_manager.ts @@ -134,9 +134,7 @@ export class CoverageManager { if (traceInfo.address !== constants.NEW_CONTRACT) { // Runtime transaction let runtimeBytecode = (traceInfo as TraceInfoExistingContract).runtimeBytecode; - if (runtimeBytecode.startsWith('0x')) { - runtimeBytecode = runtimeBytecode.slice(2); - } + runtimeBytecode = utils.removeHexPrefix(runtimeBytecode); const contractData = _.find(this._contractsData, { runtimeBytecode }) as ContractData; if (_.isUndefined(contractData)) { throw new Error(`Transaction to an unknown address: ${traceInfo.address}`); @@ -161,9 +159,7 @@ export class CoverageManager { } else { // Contract creation transaction let bytecode = (traceInfo as TraceInfoNewContract).bytecode; - if (bytecode.startsWith('0x')) { - bytecode = bytecode.slice(2); - } + bytecode = utils.removeHexPrefix(bytecode); const contractData = _.find(this._contractsData, contractDataCandidate => bytecode.startsWith(contractDataCandidate.bytecode), ) as ContractData; 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 && -- cgit v1.2.3