aboutsummaryrefslogtreecommitdiffstats
path: root/packages/sol-cov/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/sol-cov/src')
-rw-r--r--packages/sol-cov/src/collect_contract_data.ts25
-rw-r--r--packages/sol-cov/src/coverage_manager.ts57
-rw-r--r--packages/sol-cov/src/utils.ts4
3 files changed, 47 insertions, 39 deletions
diff --git a/packages/sol-cov/src/collect_contract_data.ts b/packages/sol-cov/src/collect_contract_data.ts
index 1d8bc7178..bb20e98be 100644
--- a/packages/sol-cov/src/collect_contract_data.ts
+++ b/packages/sol-cov/src/collect_contract_data.ts
@@ -8,25 +8,24 @@ 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<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..6a57d07c9 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<string>;
- private static _getSingleFileCoverageForTrace(
+ constructor(
+ artifactsPath: string,
+ sourcesPath: string,
+ networkId: number,
+ getContractCodeAsync: (address: string) => Promise<string>,
+ ) {
+ 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<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 _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,31 +128,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 = utils.removeHexPrefix(runtimeBytecode);
const contractData = _.find(this._contractsData, { runtimeBytecode }) as ContractData;
if (_.isUndefined(contractData)) {
throw new Error(`Transaction to an unknown address: ${traceInfo.address}`);
@@ -144,7 +148,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 +158,8 @@ export class CoverageManager {
}
} else {
// Contract creation transaction
- const bytecode = (traceInfo as TraceInfoNewContract).bytecode;
+ let bytecode = (traceInfo as TraceInfoNewContract).bytecode;
+ bytecode = utils.removeHexPrefix(bytecode);
const contractData = _.find(this._contractsData, contractDataCandidate =>
bytecode.startsWith(contractDataCandidate.bytecode),
) as ContractData;
@@ -170,7 +175,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,
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 &&