diff --git a/wasm-port/docs/compatibility-validation.md b/wasm-port/docs/compatibility-validation.md index c8db8bf..94fa335 100644 --- a/wasm-port/docs/compatibility-validation.md +++ b/wasm-port/docs/compatibility-validation.md @@ -195,10 +195,11 @@ INI parser smoke harness and an initial interpreter-core canonical event smoke for `minimal_linear`, `arc_semantics`, `length_units`, `modal_incremental`, `plane_selection`, `coordinate_offsets`, `g53_machine_coordinates`, `feed_control_modes`, `position_params`, `probe_semantics`, `spindle_orient`, -`comment_logging`, and `numbered_params`. OPFS validation is limited to the -JavaScript host-boundary adapter plus the INI browser smoke harness. Full -browser coverage, full SDK coverage, and full machine-session validation remain -future work. +`comment_logging`, and `numbered_params`, plus the `g1_zero_feed`, +`arc_radius_mismatch`, `arc_zero_radius`, and `g53_incremental` negative +fixtures. OPFS validation is limited to the JavaScript host-boundary adapter +plus the INI browser smoke harness. Full browser coverage, full SDK coverage, +and full machine-session validation remain future work. The current fixture expectations validate standalone behavior against both the vendored LinuxCNC source path and an upstream `rs274` side-by-side baseline for diff --git a/wasm-port/tests/wasm/node/verify_interp_wasm.mjs b/wasm-port/tests/wasm/node/verify_interp_wasm.mjs index c1fab56..b517a37 100644 --- a/wasm-port/tests/wasm/node/verify_interp_wasm.mjs +++ b/wasm-port/tests/wasm/node/verify_interp_wasm.mjs @@ -27,6 +27,28 @@ function runProgram(mod, programText) { } } +function verifyExpectedOutput(fixtureName, output, expectedText) { + const expectedLines = expectedText.split("\n").filter(Boolean); + + for (const expectedLine of expectedLines) { + if (expectedLine.startsWith("absent=")) { + const forbidden = expectedLine.slice("absent=".length); + assert.equal( + output.includes(forbidden), + false, + `${fixtureName}: unexpected ${forbidden}`, + ); + continue; + } + + assert.equal( + output.includes(expectedLine), + true, + `${fixtureName}: ${expectedLine}`, + ); + } +} + const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const rootDir = resolve(__dirname, "../../.."); @@ -66,16 +88,26 @@ for (const fixtureName of fixtureNames) { "utf8", ).trimEnd(); - const output = runProgram(interp, programText); - const actualLineSet = new Set(output.split("\n").filter(Boolean)); - const expectedLines = expectedEvents.split("\n").filter(Boolean); + verifyExpectedOutput(fixtureName, runProgram(interp, programText), expectedEvents); +} - for (const expectedLine of expectedLines) { - assert.equal( - actualLineSet.has(expectedLine), - true, - `${fixtureName}: ${expectedLine}`, - ); - } +const errorFixtureNames = [ + "g1_zero_feed", + "arc_radius_mismatch", + "arc_zero_radius", + "g53_incremental", +]; + +for (const fixtureName of errorFixtureNames) { + const programText = readFileSync( + resolve(rootDir, `tests/fixtures/gcode_errors/${fixtureName}.ngc`), + "utf8", + ); + const expectedOutput = readFileSync( + resolve(rootDir, `tests/fixtures/canon_errors/${fixtureName}.expected`), + "utf8", + ).trimEnd(); + + verifyExpectedOutput(fixtureName, runProgram(interp, programText), expectedOutput); } console.log("interp_wasm_node_smoke=ok");