按规划继续工作

结论:解释器 Node WASM 与浏览器 smoke 已统一使用共享 fixture 矩阵,聚合 host/WASM/browser 验证通过。
This commit is contained in:
2026-06-08 07:28:50 +08:00
parent 706fd1e775
commit e5697970df
4 changed files with 133 additions and 123 deletions

View File

@@ -236,6 +236,12 @@ machine-session validation remain future work.
## WASM/Browser Fixture Matrix
The executable fixture lists for Node WASM and browser interpreter smoke tests
are centralized in `tests/fixtures/interp-fixture-matrix.mjs`. Additions to the
matrix must continue to route execution through the SDK and exported C ABI
backed by vendored LinuxCNC interpreter code; the matrix is only a test
coverage list, not a CNC behavior implementation.
Node WASM `Interp::execute()` coverage currently includes:
- `minimal_linear`

View File

@@ -8,6 +8,13 @@
<pre id="status">running</pre>
<script type="module">
import { createLinuxCncInterpSdk } from "../../runtime/sdk/src/index.js";
import {
INTERP_BROWSER_FILE_FIXTURES,
INTERP_BROWSER_MDI_FIXTURES,
INTERP_ERROR_FIXTURES,
INTERP_INI_FIXTURE,
INTERP_POSITION_PARAMS_FILE_FIXTURE,
} from "../fixtures/interp-fixture-matrix.mjs";
const status = document.getElementById("status");
@@ -49,47 +56,13 @@
},
});
for (const fixtureName of [
"minimal_linear",
"arc_semantics",
"length_units",
"modal_incremental",
"plane_selection",
"coordinate_offsets",
"g53_machine_coordinates",
"feed_control_modes",
"canned_cycles",
"numbered_params",
"comment_logging",
"tool_semantics",
"tool_table_setup",
"probe_semantics",
"spindle_orient",
"cutter_comp_motion",
"threading_sync",
"nurbs_g5_semantics",
"nurbs_g6_semantics",
"state_tag_motion",
"canon_runtime_edges",
"tool_reload",
"program_end_modal_reset",
]) {
for (const fixtureName of INTERP_BROWSER_MDI_FIXTURES) {
const programText = await fetchText(`../fixtures/gcode/${fixtureName}.ngc`);
const expectedText = await fetchText(`../fixtures/canon/${fixtureName}.events`);
verifyExpectedOutput(fixtureName, interp.runProgram(programText), expectedText.trimEnd());
}
for (const errorFixtureName of [
"g1_zero_feed",
"arc_radius_mismatch",
"arc_zero_radius",
"g53_incremental",
"cutter_comp_plane_change",
"namedparam_readonly",
"numbered_param_readonly",
"tool_length_offset_not_found",
"tool_not_found",
]) {
for (const errorFixtureName of INTERP_ERROR_FIXTURES) {
verifyExpectedOutput(
errorFixtureName,
interp.runProgram(await fetchText(`../fixtures/gcode_errors/${errorFixtureName}.ngc`)),
@@ -97,16 +70,22 @@
);
}
const positionParamsText = await fetchText("../fixtures/gcode/position_params.ngc");
const positionParamsPath = "/work/position_params.ngc";
const positionParamsText = await fetchText(
`../fixtures/gcode/${INTERP_POSITION_PARAMS_FILE_FIXTURE}.ngc`,
);
const positionParamsPath = `/work/${INTERP_POSITION_PARAMS_FILE_FIXTURE}.ngc`;
interp.writeTextFile(positionParamsPath, positionParamsText);
verifyExpectedOutput(
"position_params_file",
`${INTERP_POSITION_PARAMS_FILE_FIXTURE}_file`,
interp.runFile(positionParamsPath),
(await fetchText("../fixtures/canon_file/position_params.events")).trimEnd(),
(
await fetchText(
`../fixtures/canon_file/${INTERP_POSITION_PARAMS_FILE_FIXTURE}.events`,
)
).trimEnd(),
);
for (const fileFixtureName of ["file_open_reset", "percent_file_finish", "oword_subroutine"]) {
for (const fileFixtureName of INTERP_BROWSER_FILE_FIXTURES) {
const programPath = `/work/${fileFixtureName}.ngc`;
interp.writeTextFile(programPath, await fetchText(`../fixtures/gcode/${fileFixtureName}.ngc`));
verifyExpectedOutput(
@@ -118,15 +97,15 @@
const namedParamIniPath = "/work/namedparams.ini";
interp.writeTextFile(namedParamIniPath, await fetchText("../fixtures/ini/namedparams.ini"));
const namedParamPath = "/work/namedparam_semantics.ngc";
const namedParamPath = `/work/${INTERP_INI_FIXTURE}.ngc`;
interp.writeTextFile(
namedParamPath,
await fetchText("../fixtures/gcode/namedparam_semantics.ngc"),
await fetchText(`../fixtures/gcode/${INTERP_INI_FIXTURE}.ngc`),
);
verifyExpectedOutput(
"namedparam_semantics_file",
`${INTERP_INI_FIXTURE}_file`,
interp.runFileWithIni(namedParamPath, namedParamIniPath),
(await fetchText("../fixtures/canon/namedparam_semantics.events")).trimEnd(),
(await fetchText(`../fixtures/canon/${INTERP_INI_FIXTURE}.events`)).trimEnd(),
);
status.textContent = "browser_interp_smoke=ok";

View File

@@ -0,0 +1,80 @@
export const INTERP_MDI_FIXTURES = [
"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",
"numbered_params",
"tool_semantics",
"tool_table_setup",
"tool_reload",
"canned_cycles",
"cutter_comp_motion",
"threading_sync",
"nurbs_g5_semantics",
"nurbs_g6_semantics",
"state_tag_motion",
"canon_runtime_edges",
"program_end_modal_reset",
];
export const INTERP_BROWSER_MDI_FIXTURES = INTERP_MDI_FIXTURES.filter(
(fixtureName) => fixtureName !== "position_params",
);
export const INTERP_ERROR_FIXTURES = [
"g1_zero_feed",
"arc_radius_mismatch",
"arc_zero_radius",
"cutter_comp_plane_change",
"g53_incremental",
"namedparam_readonly",
"numbered_param_readonly",
"tool_not_found",
"tool_length_offset_not_found",
];
export const INTERP_FILE_FIXTURES = [
"minimal_linear",
"arc_semantics",
"length_units",
"modal_incremental",
"plane_selection",
"coordinate_offsets",
"g53_machine_coordinates",
"feed_control_modes",
"probe_semantics",
"spindle_orient",
"comment_logging",
"numbered_params",
"tool_semantics",
"tool_table_setup",
"tool_reload",
"canned_cycles",
"cutter_comp_motion",
"threading_sync",
"nurbs_g5_semantics",
"nurbs_g6_semantics",
"state_tag_motion",
"canon_runtime_edges",
"program_end_modal_reset",
"file_open_reset",
"percent_file_finish",
"oword_subroutine",
];
export const INTERP_BROWSER_FILE_FIXTURES = [
"file_open_reset",
"percent_file_finish",
"oword_subroutine",
];
export const INTERP_INI_FIXTURE = "namedparam_semantics";
export const INTERP_POSITION_PARAMS_FILE_FIXTURE = "position_params";

View File

@@ -4,6 +4,13 @@ import { dirname, resolve } from "node:path";
import assert from "node:assert/strict";
import { createLinuxCncInterpSdk } from "../../../runtime/sdk/src/index.js";
import {
INTERP_ERROR_FIXTURES,
INTERP_FILE_FIXTURES,
INTERP_INI_FIXTURE,
INTERP_MDI_FIXTURES,
INTERP_POSITION_PARAMS_FILE_FIXTURE,
} from "../../fixtures/interp-fixture-matrix.mjs";
function verifyExpectedOutput(fixtureName, output, expectedText) {
const expectedLines = expectedText.split("\n").filter(Boolean);
@@ -40,34 +47,7 @@ const interp = await createLinuxCncInterpSdk({
},
});
const fixtureNames = [
"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",
"numbered_params",
"tool_semantics",
"tool_table_setup",
"tool_reload",
"canned_cycles",
"cutter_comp_motion",
"threading_sync",
"nurbs_g5_semantics",
"nurbs_g6_semantics",
"state_tag_motion",
"canon_runtime_edges",
"program_end_modal_reset",
];
for (const fixtureName of fixtureNames) {
for (const fixtureName of INTERP_MDI_FIXTURES) {
const programText = readFileSync(
resolve(rootDir, `tests/fixtures/gcode/${fixtureName}.ngc`),
"utf8",
@@ -86,32 +66,20 @@ interp.writeTextFile(
readFileSync(resolve(rootDir, "tests/fixtures/ini/namedparams.ini"), "utf8"),
);
const namedParamProgramText = readFileSync(
resolve(rootDir, "tests/fixtures/gcode/namedparam_semantics.ngc"),
resolve(rootDir, `tests/fixtures/gcode/${INTERP_INI_FIXTURE}.ngc`),
"utf8",
);
const namedParamExpected = readFileSync(
resolve(rootDir, "tests/fixtures/canon/namedparam_semantics.events"),
resolve(rootDir, `tests/fixtures/canon/${INTERP_INI_FIXTURE}.events`),
"utf8",
).trimEnd();
verifyExpectedOutput(
"namedparam_semantics",
INTERP_INI_FIXTURE,
interp.runProgramWithIni(namedParamProgramText, namedParamIniPath),
namedParamExpected,
);
const errorFixtureNames = [
"g1_zero_feed",
"arc_radius_mismatch",
"arc_zero_radius",
"cutter_comp_plane_change",
"g53_incremental",
"namedparam_readonly",
"numbered_param_readonly",
"tool_not_found",
"tool_length_offset_not_found",
];
for (const fixtureName of errorFixtureNames) {
for (const fixtureName of INTERP_ERROR_FIXTURES) {
const programText = readFileSync(
resolve(rootDir, `tests/fixtures/gcode_errors/${fixtureName}.ngc`),
"utf8",
@@ -124,36 +92,7 @@ for (const fixtureName of errorFixtureNames) {
verifyExpectedOutput(fixtureName, interp.runProgram(programText), expectedOutput);
}
const fileFixtureNames = [
"minimal_linear",
"arc_semantics",
"length_units",
"modal_incremental",
"plane_selection",
"coordinate_offsets",
"g53_machine_coordinates",
"feed_control_modes",
"probe_semantics",
"spindle_orient",
"comment_logging",
"numbered_params",
"tool_semantics",
"tool_table_setup",
"tool_reload",
"canned_cycles",
"cutter_comp_motion",
"threading_sync",
"nurbs_g5_semantics",
"nurbs_g6_semantics",
"state_tag_motion",
"canon_runtime_edges",
"program_end_modal_reset",
"file_open_reset",
"percent_file_finish",
"oword_subroutine",
];
for (const fixtureName of fileFixtureNames) {
for (const fixtureName of INTERP_FILE_FIXTURES) {
const programPath = `/work/${fixtureName}.ngc`;
const programText = readFileSync(
resolve(rootDir, `tests/fixtures/gcode/${fixtureName}.ngc`),
@@ -168,7 +107,7 @@ for (const fixtureName of fileFixtureNames) {
verifyExpectedOutput(fixtureName, interp.runFile(programPath), expectedEvents);
}
const namedParamFilePath = "/work/namedparam_semantics.ngc";
const namedParamFilePath = `/work/${INTERP_INI_FIXTURE}.ngc`;
interp.writeTextFile(namedParamFilePath, namedParamProgramText);
verifyExpectedOutput(
"namedparam_semantics_file",
@@ -179,13 +118,19 @@ verifyExpectedOutput(
const positionParamsFilePath = "/work/position_params.ngc";
interp.writeTextFile(
positionParamsFilePath,
readFileSync(resolve(rootDir, "tests/fixtures/gcode/position_params.ngc"), "utf8"),
readFileSync(
resolve(rootDir, `tests/fixtures/gcode/${INTERP_POSITION_PARAMS_FILE_FIXTURE}.ngc`),
"utf8",
),
);
verifyExpectedOutput(
"position_params_file",
`${INTERP_POSITION_PARAMS_FILE_FIXTURE}_file`,
interp.runFile(positionParamsFilePath),
readFileSync(
resolve(rootDir, "tests/fixtures/canon_file/position_params.events"),
resolve(
rootDir,
`tests/fixtures/canon_file/${INTERP_POSITION_PARAMS_FILE_FIXTURE}.events`,
),
"utf8",
).trimEnd(),
);