@@ -2,14 +2,15 @@ import { WASI } from "node:wasi";
2
2
import { promises } from "node:fs" ;
3
3
import { ensureDirSync } from "fs-extra" ;
4
4
import { instantiate , Imports as ASImports } from "@assemblyscript/loader" ;
5
- import { ExecutionResult } from "../executionResult.js" ;
5
+ import { ExecutionResultSummary } from "../executionResult.js" ;
6
6
import { Imports , ImportsArgument , InstrumentResult } from "../interface.js" ;
7
7
import { mockInstrumentFunc } from "../utils/import.js" ;
8
8
import { supplyDefaultFunction } from "../utils/index.js" ;
9
9
import { parseImportFunctionInfo } from "../utils/wasmparser.js" ;
10
- import { ExecutionRecorder , SingleExecutionResult } from "./executionRecorder.js" ;
10
+ import { ExecutionRecorder , ExecutionResult } from "./executionRecorder.js" ;
11
11
import { CoverageRecorder } from "./covRecorder.js" ;
12
12
import assert from "node:assert" ;
13
+ import { ExecutionError , handleWebAssemblyError } from "../utils/errorTraceHandler.js" ;
13
14
14
15
const readFile = promises . readFile ;
15
16
@@ -18,7 +19,7 @@ async function nodeExecutor(
18
19
outFolder : string ,
19
20
matchedTestNames ?: string [ ] ,
20
21
imports ?: Imports
21
- ) : Promise < SingleExecutionResult > {
22
+ ) : Promise < ExecutionResult > {
22
23
const wasi = new WASI ( {
23
24
args : [ "node" , instrumentResult . baseName ] ,
24
25
env : process . env ,
@@ -48,36 +49,52 @@ async function nodeExecutor(
48
49
importsArg . module = ins . module ;
49
50
importsArg . instance = ins . instance ;
50
51
importsArg . exports = ins . exports ;
52
+ let isCrashed = false ; // we don't want to crash any code after crash. AS' heap may be broken.
51
53
try {
54
+ executionRecorder . startTestFunction ( `${ instrumentResult . baseName } - init` ) ;
52
55
wasi . start ( ins ) ;
53
- const execTestFunction = ins . exports [ "executeTestFunction" ] ;
54
- assert ( typeof execTestFunction === "function" ) ;
55
- if ( matchedTestNames === undefined ) {
56
- // By default, all testcases are executed
57
- for ( const functionInfo of executionRecorder . registerFunctions ) {
58
- const [ testCaseName , functionIndex ] = functionInfo ;
59
- executionRecorder . startTestFunction ( testCaseName ) ;
60
- ( execTestFunction as ( a : number ) => void ) ( functionIndex ) ;
61
- executionRecorder . finishTestFunction ( ) ;
62
- mockInstrumentFunc [ "mockFunctionStatus.clear" ] ( ) ;
63
- }
56
+ } catch ( error ) {
57
+ if ( error instanceof WebAssembly . RuntimeError ) {
58
+ isCrashed = true ;
59
+ const errorMessage : ExecutionError = await handleWebAssemblyError ( error , instrumentResult . instrumentedWasm ) ;
60
+ executionRecorder . notifyTestCrash ( errorMessage ) ;
64
61
} else {
65
- for ( const functionInfo of executionRecorder . registerFunctions ) {
66
- const [ testCaseName , functionIndex ] = functionInfo ;
67
- if ( matchedTestNames . includes ( testCaseName ) ) {
68
- executionRecorder . startTestFunction ( testCaseName ) ;
69
- ( execTestFunction as ( a : number ) => void ) ( functionIndex ) ;
70
- executionRecorder . finishTestFunction ( ) ;
71
- mockInstrumentFunc [ "mockFunctionStatus.clear" ] ( ) ;
72
- }
62
+ // unrecoverable error, rethrow
63
+ if ( error instanceof Error ) {
64
+ console . error ( error . stack ) ;
73
65
}
66
+ throw new Error ( "node executor abort" ) ;
74
67
}
75
- } catch ( error ) {
76
- if ( error instanceof Error ) {
77
- console . error ( error . stack ) ;
78
- }
79
- throw new Error ( "node executor abort." ) ;
80
68
}
69
+ executionRecorder . finishTestFunction ( ) ;
70
+ // try {
71
+ // const execTestFunction = ins.exports["executeTestFunction"];
72
+ // assert(typeof execTestFunction === "function");
73
+ // if (matchedTestNames === undefined) {
74
+ // // By default, all testcases are executed
75
+ // for (const functionInfo of executionRecorder.registerFunctions) {
76
+ // const [testCaseName, functionIndex] = functionInfo;
77
+ // executionRecorder.startTestFunction(testCaseName);
78
+ // (execTestFunction as (a: number) => void)(functionIndex);
79
+ // executionRecorder.finishTestFunction();
80
+ // mockInstrumentFunc["mockFunctionStatus.clear"]();
81
+ // }
82
+ // } else {
83
+ // for (const functionInfo of executionRecorder.registerFunctions) {
84
+ // const [testCaseName, functionIndex] = functionInfo;
85
+ // if (matchedTestNames.includes(testCaseName)) {
86
+ // executionRecorder.startTestFunction(testCaseName);
87
+ // (execTestFunction as (a: number) => void)(functionIndex);
88
+ // executionRecorder.finishTestFunction();
89
+ // mockInstrumentFunc["mockFunctionStatus.clear"]();
90
+ // }
91
+ // }
92
+ // }
93
+ // } catch (error) {
94
+ // if (error instanceof Error) {
95
+ // console.error(error.stack);
96
+ // }
97
+ // }
81
98
coverageRecorder . outputTrace ( instrumentResult . traceFile ) ;
82
99
return executionRecorder . result ;
83
100
}
@@ -87,12 +104,12 @@ export async function execWasmBinaries(
87
104
instrumentResults : InstrumentResult [ ] ,
88
105
matchedTestNames ?: string [ ] ,
89
106
imports ?: Imports
90
- ) : Promise < ExecutionResult > {
91
- const assertRes = new ExecutionResult ( ) ;
107
+ ) : Promise < ExecutionResultSummary > {
108
+ const assertRes = new ExecutionResultSummary ( ) ;
92
109
ensureDirSync ( outFolder ) ;
93
110
await Promise . all < void > (
94
111
instrumentResults . map ( async ( instrumentResult ) : Promise < void > => {
95
- const result : SingleExecutionResult = await nodeExecutor ( instrumentResult , outFolder , matchedTestNames , imports ) ;
112
+ const result : ExecutionResult = await nodeExecutor ( instrumentResult , outFolder , matchedTestNames , imports ) ;
96
113
await assertRes . merge ( result , instrumentResult . expectInfo ) ;
97
114
} )
98
115
) ;
0 commit comments