Merge branch 'development' into breakUp0xjs
* development: (38 commits) Add fallback image support to relayer grid tile Clear relayer grid state when fetching Configure the compiler to generate artifacts with deployedBytecode Implement loading and error state for relayer grid Fallback image for relayer grid tile Change relayer grid tile to link on header Display top tokens from backend Remove overflowZ property from portal Suggestions and fix bad merge Fix typo Only show untracked tokens Make wallet scrollable Add token flow Update The Ocean logo Fix artifacts paths Create an artifacts folder Introduce a var Add removeHexPrefix util method CHeck if ABI exists Improve the readability of the check for should compile ... # Conflicts: # .gitignore # packages/contracts/test/multi_sig_with_time_lock.ts # packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts # packages/contracts/util/artifacts.ts
This commit is contained in:
18
packages/sol-cov/compiler.json
Normal file
18
packages/sol-cov/compiler.json
Normal file
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --exit",
|
||||
"clean": "shx rm -rf lib scripts",
|
||||
"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 ../deployer/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",
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
Reference in New Issue
Block a user