Skip to content

Commit 5622732

Browse files
authored
refactor: centralized control temporary file path (#40)
1 parent 0cbf790 commit 5622732

File tree

8 files changed

+66
-62
lines changed

8 files changed

+66
-62
lines changed

src/core/covRecorder.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import assert from "node:assert";
21
import { writeFileSync } from "node:fs";
32

43
export class CoverageRecorder {
@@ -25,9 +24,7 @@ export class CoverageRecorder {
2524
};
2625
}
2726

28-
outputTrace(wasm: string) {
29-
assert(wasm.endsWith("instrumented.wasm"));
30-
const traceOutputFile = wasm.slice(0, -17).concat("trace");
31-
writeFileSync(traceOutputFile, JSON.stringify(this._runtimeTrace));
27+
outputTrace(traceFile: string) {
28+
writeFileSync(traceFile, JSON.stringify(this._runtimeTrace));
3229
}
3330
}

src/core/execute.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { WASI } from "node:wasi";
22
import { promises } from "node:fs";
33
import { ensureDirSync } from "fs-extra";
4-
import { basename } from "node:path";
54
import { instantiate, Imports as ASImports } from "@assemblyscript/loader";
65
import { AssertResult } from "../assertResult.js";
76
import { Imports, ImportsArgument } from "../index.js";
@@ -14,9 +13,13 @@ import { CoverageRecorder } from "./covRecorder.js";
1413

1514
const readFile = promises.readFile;
1615

17-
async function nodeExecutor(wasm: string, outFolder: string, imports: Imports): Promise<ExecutionRecorder> {
16+
async function nodeExecutor(
17+
instrumentResult: InstrumentResult,
18+
outFolder: string,
19+
imports: Imports
20+
): Promise<ExecutionRecorder> {
1821
const wasi = new WASI({
19-
args: ["node", basename(wasm)],
22+
args: ["node", instrumentResult.baseName],
2023
env: process.env,
2124
preopens: {
2225
"/": outFolder,
@@ -36,7 +39,7 @@ async function nodeExecutor(wasm: string, outFolder: string, imports: Imports):
3639
...coverageRecorder.getCollectionFuncSet(),
3740
...userDefinedImportsObject,
3841
} as ASImports;
39-
const binaryBuffer = await readFile(wasm);
42+
const binaryBuffer = await readFile(instrumentResult.instrumentedWasm);
4043
const binary = binaryBuffer.buffer.slice(binaryBuffer.byteOffset, binaryBuffer.byteOffset + binaryBuffer.byteLength);
4144
const importFuncList = parseImportFunctionInfo(binary as ArrayBuffer);
4245
supplyDefaultFunction(importFuncList, importObject);
@@ -52,22 +55,21 @@ async function nodeExecutor(wasm: string, outFolder: string, imports: Imports):
5255
}
5356
throw new Error("node executor abort.");
5457
}
55-
coverageRecorder.outputTrace(wasm);
58+
coverageRecorder.outputTrace(instrumentResult.traceFile);
5659
return executionRecorder;
5760
}
5861

59-
export async function execWasmBinarys(
62+
export async function execWasmBinaries(
6063
outFolder: string,
61-
instrumentResult: InstrumentResult[],
64+
instrumentResults: InstrumentResult[],
6265
imports: Imports
6366
): Promise<AssertResult> {
6467
const assertRes = new AssertResult();
6568
ensureDirSync(outFolder);
6669
await Promise.all<void>(
67-
instrumentResult.map(async (res): Promise<void> => {
68-
const { instrumentedWasm, expectInfo } = res;
69-
const recorder: ExecutionRecorder = await nodeExecutor(instrumentedWasm, outFolder, imports);
70-
await assertRes.merge(recorder, expectInfo);
70+
instrumentResults.map(async (instrumentResult): Promise<void> => {
71+
const recorder: ExecutionRecorder = await nodeExecutor(instrumentResult, outFolder, imports);
72+
await assertRes.merge(recorder, instrumentResult.expectInfo);
7173
})
7274
);
7375
return assertRes;

src/core/instrument.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,19 @@ export async function instrument(sourceWasms: string[], sourceCodePaths: string[
1010
const instrumenter = await initInstrumenter();
1111
for (const sourceFile of sourceWasms) {
1212
const baseName = sourceFile.slice(0, -5);
13-
const outputFile = baseName.concat(".instrumented.wasm");
13+
const result = new InstrumentResult(baseName);
14+
1415
const reportFunction = "covInstrument/traceExpression";
15-
const sourceMapFile = baseName.concat(".wasm.map");
16-
const debugInfoFile = baseName.concat(".debugInfo.json");
17-
const expectInfoFile = baseName.concat(".expectInfo.json");
1816

1917
const source = instrumenter.allocateUTF8(sourceFile);
20-
const output = instrumenter.allocateUTF8(outputFile);
18+
const output = instrumenter.allocateUTF8(result.instrumentedWasm);
2119
const report = instrumenter.allocateUTF8(reportFunction);
22-
const sourceMap = instrumenter.allocateUTF8(sourceMapFile);
23-
const debugInfo = instrumenter.allocateUTF8(debugInfoFile);
24-
const expectInfo = instrumenter.allocateUTF8(expectInfoFile);
20+
const sourceMap = instrumenter.allocateUTF8(result.sourceMap);
21+
const debugInfo = instrumenter.allocateUTF8(result.debugInfo);
22+
const expectInfo = instrumenter.allocateUTF8(result.expectInfo);
2523
const include = instrumenter.allocateUTF8(includeFilter);
2624

2725
instrumenter._wasm_instrument(source, output, report, sourceMap, expectInfo, debugInfo, include, 0, true);
28-
const result: InstrumentResult = {
29-
sourceWasm: sourceFile,
30-
instrumentedWasm: outputFile,
31-
debugInfo: debugInfoFile,
32-
expectInfo: expectInfoFile,
33-
};
3426
for (const ptr of [source, output, report, sourceMap, debugInfo, expectInfo, include]) {
3527
instrumenter._free(ptr);
3628
}

src/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { compile } from "./core/compile.js";
66
import { AssertResult } from "./assertResult.js";
77
import { precompile } from "./core/precompile.js";
88
import { instrument } from "./core/instrument.js";
9-
import { execWasmBinarys } from "./core/execute.js";
9+
import { execWasmBinaries } from "./core/execute.js";
1010
import { generateReport, reportConfig } from "./generator/index.js";
1111

1212
function logAssertResult(trace: AssertResult): void {
@@ -81,12 +81,11 @@ export async function start_unit_test(fo: FileOption, to: TestOption, oo: Output
8181
console.log(chalk.blueBright("compile testcases: ") + chalk.bold.greenBright("OK"));
8282
const instrumentResult = await instrument(wasmPaths, Array.from(unittestPackage.sourceFunctions.keys()));
8383
console.log(chalk.blueBright("instrument: ") + chalk.bold.greenBright("OK"));
84-
const executedResult = await execWasmBinarys(oo.tempFolder, instrumentResult, to.imports);
84+
const executedResult = await execWasmBinaries(oo.tempFolder, instrumentResult, to.imports);
8585
console.log(chalk.blueBright("execute testcases: ") + chalk.bold.greenBright("OK"));
8686
logAssertResult(executedResult);
87-
const debugInfoFiles = instrumentResult.map((res) => res.debugInfo);
8887
const parser = new Parser();
89-
const fileCoverageInfo = await parser.parse(debugInfoFiles, unittestPackage.sourceFunctions);
88+
const fileCoverageInfo = await parser.parse(instrumentResult, unittestPackage.sourceFunctions);
9089
reportConfig.warningLimit = oo.warnLimit ?? reportConfig.warningLimit;
9190
reportConfig.errorLimit = oo.errorLimit ?? reportConfig.errorLimit;
9291
generateReport(oo.mode, oo.outputFolder, fileCoverageInfo);

src/interface.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,26 @@
66
import { Type } from "wasmparser";
77

88
// instrumented file information
9-
export interface InstrumentResult {
10-
sourceWasm: string;
11-
instrumentedWasm: string;
12-
debugInfo: string;
13-
expectInfo: string;
9+
export class InstrumentResult {
10+
constructor(public baseName: string) {}
11+
get sourceWasm() {
12+
return this.baseName.concat(".wasm");
13+
}
14+
get instrumentedWasm(): string {
15+
return this.baseName.concat(".instrumented.wasm");
16+
}
17+
get sourceMap(): string {
18+
return this.baseName.concat(".wasm.map");
19+
}
20+
get debugInfo(): string {
21+
return this.baseName.concat(".debugInfo.json");
22+
}
23+
get expectInfo(): string {
24+
return this.baseName.concat(".expectInfo.json");
25+
}
26+
get traceFile(): string {
27+
return this.baseName.concat(".trace");
28+
}
1429
}
1530

1631
export type CodeSnippetIndex = number;

src/parser/index.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
FunctionCoverageResult,
1515
SourceFunctionInfo,
1616
LineRange,
17+
InstrumentResult,
1718
} from "../interface.js";
1819

1920
export class Parser {
@@ -25,11 +26,11 @@ export class Parser {
2526
functionCovInfoMap = new Map<string, CovInfo>();
2627

2728
async parse(
28-
debugInfoFiles: string[],
29+
instrumentResults: InstrumentResult[],
2930
sourceFunctions: Map<string, SourceFunctionInfo[]>
3031
): Promise<FileCoverageResult[]> {
31-
for (const debugInfoFile of debugInfoFiles) {
32-
await this.traceParse(debugInfoFile);
32+
for (const instrumentResult of instrumentResults) {
33+
await this.traceParse(instrumentResult);
3334
}
3435
this.generateFunctionCoverage();
3536
await this.generateFileCoverage(sourceFunctions);
@@ -41,9 +42,9 @@ export class Parser {
4142
const tempCovTraceMap = new Map<FunctionIndex, CodeSnippetIndex[]>();
4243
for (const trace of traces) {
4344
const [funIndex, codeSnippetIndex] = trace;
44-
const codeIndexs = tempCovTraceMap.get(funIndex);
45-
if (codeIndexs) {
46-
codeIndexs.push(codeSnippetIndex);
45+
const codeIndexes = tempCovTraceMap.get(funIndex);
46+
if (codeIndexes) {
47+
codeIndexes.push(codeSnippetIndex);
4748
} else {
4849
tempCovTraceMap.set(funIndex, [codeSnippetIndex]);
4950
}
@@ -63,12 +64,10 @@ export class Parser {
6364
* parse debugInfo and traceInfo to functionCovTraceMap and functionCovInfoMap
6465
* @param debugInfoFile debugInfo file path generated by instrumenter
6566
*/
66-
async traceParse(debugInfoFile: string) {
67-
const traceFile = debugInfoFile.slice(0, -14).concat("trace");
68-
67+
async traceParse(instrumentResult: InstrumentResult) {
6968
const [tempCovTraceMap, { debugInfos, debugFiles }] = await Promise.all([
70-
this.getTempCovTraceMap(traceFile),
71-
this.getDebugInfos(debugInfoFile),
69+
this.getTempCovTraceMap(instrumentResult.traceFile),
70+
this.getDebugInfos(instrumentResult.debugInfo),
7271
]);
7372

7473
for (const [name, info] of debugInfos) {
@@ -86,7 +85,7 @@ export class Parser {
8685
.filter((range) => {
8786
const filename = debugFiles[range[0]];
8887
if (filename === undefined) {
89-
throw new Error(`unknown erorr: not find fileIndex ${range[0]} in ${debugInfoFile}`);
88+
throw new Error(`unknown error: not find fileIndex ${range[0]} in ${instrumentResult.debugInfo}`);
9089
}
9190
// if basicBlock is inline function from other files, ignore it
9291
return checkFunctionName(filename, name);

tests/ts/test/core/instrument.test.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,20 @@ const outputDir = join(tmpdir(), "assemblyscript-unittest-framework");
1010

1111
test("Instrument", async () => {
1212
await compile([fixturePath], outputDir, "--memoryBase 16 --exportTable");
13+
const base = join(outputDir, "constructor");
1314
const wasmPath = join(outputDir, "constructor.wasm");
1415
const sourceCodePath = "tests/ts/fixture/constructor.ts";
15-
const result = await instrument([wasmPath], [sourceCodePath]);
16-
expect(result.length).toEqual(1);
16+
const results = await instrument([wasmPath], [sourceCodePath]);
17+
expect(results.length).toEqual(1);
18+
const result = results[0]!;
1719
const instrumentedWasm = join(outputDir, "constructor.instrumented.wasm");
1820
const debugInfo = join(outputDir, "constructor.debugInfo.json");
1921
const expectInfo = join(outputDir, "constructor.expectInfo.json");
20-
expect(result[0]).toEqual({
21-
sourceWasm: wasmPath,
22-
instrumentedWasm,
23-
debugInfo,
24-
expectInfo,
25-
});
22+
expect(result.baseName).toEqual(base);
23+
expect(result.sourceWasm).toEqual(wasmPath);
24+
expect(result.instrumentedWasm).toEqual(instrumentedWasm);
25+
expect(result.debugInfo).toEqual(debugInfo);
26+
expect(result.expectInfo).toEqual(expectInfo);
2627
expect(fs.existsSync(instrumentedWasm)).toEqual(true);
2728
expect(fs.existsSync(debugInfo)).toEqual(true);
2829
expect(fs.existsSync(expectInfo)).toEqual(true);

tests/ts/test/parser/parser.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { join } from "node:path";
22
// eslint-disable-next-line n/no-extraneous-import
33
import { jest } from "@jest/globals";
44
import { fileURLToPath, URL } from "node:url";
5-
import { SourceFunctionInfo } from "../../../../src/interface.js";
5+
import { InstrumentResult, SourceFunctionInfo } from "../../../../src/interface.js";
66

77
jest.unstable_mockModule("node:fs/promises", () => ({
88
readFile: jest.fn(() => "\n".repeat(50)),
@@ -16,8 +16,7 @@ describe("Parser", () => {
1616
const parser = new Parser();
1717

1818
test("traceParse", async () => {
19-
const debugFilePath = join(dirname, "..", "..", "fixture", "traceParse.debugInfo.json");
20-
await parser.traceParse(debugFilePath);
19+
await parser.traceParse(new InstrumentResult(join(dirname, "..", "..", "fixture", "traceParse")));
2120
expect(parser.functionCovInfoMap).toMatchSnapshot();
2221
expect(parser.functionCovTraceMap).toMatchSnapshot();
2322
});

0 commit comments

Comments
 (0)