Expand WASM sim-config staging coverage

This commit is contained in:
2026-06-09 07:32:15 +08:00
parent 2658ee3b72
commit 5116b9894d
26 changed files with 5989 additions and 141 deletions

View File

@@ -10,6 +10,7 @@
import {
createLinuxCncIniSdk,
createLinuxCncInterpSdk,
planSimConfigStaging,
} from "../../runtime/sdk/src/index.js";
import {
saveMachineParametersToOpfs,
@@ -101,21 +102,27 @@
}
}
async function loadSimMachineFiles(machineRel, files, executableFiles = []) {
const sourceDir = `../../vendor/linuxcnc/configs/sim/${machineRel}`;
const wasmDir = `/work/browser-sim/${machineRel}`;
const executableSet = new Set(executableFiles);
const machineFiles = [];
async function loadSimMachineFiles(machineRel, iniFile, programFile = null) {
const iniText = await fetchText(
`../../vendor/linuxcnc/configs/sim/${machineRel}/${iniFile}`,
);
const plan = planSimConfigStaging({
manifestText: await fetchText("../../tools/source-manifest.txt"),
machineRel,
iniFile,
iniText,
programFile,
wasmDir: `/work/browser-sim/${machineRel}`,
});
for (const filename of files) {
machineFiles.push({
path: `${wasmDir}/${filename}`,
text: await fetchText(`${sourceDir}/${filename}`),
executable: executableSet.has(filename),
});
}
return { wasmDir, files: machineFiles };
return {
...plan,
files: await Promise.all(plan.files.map(async (file) => ({
path: file.path,
text: await fetchText(`../../vendor/linuxcnc/${file.sourceRel}`),
executable: file.executable,
}))),
};
}
async function writeFiveAxisTrtMachineFiles(interp) {
@@ -275,6 +282,36 @@
return interp.runFile(wasmPath);
}
async function runVendorNcFileWithToolTable(interp, filename) {
const wasmDir = "/work/browser-nc-files-context";
const wasmPath = `${wasmDir}/${filename}`;
const iniPath = `${wasmDir}/nc_files_context.ini`;
await writeFetchedTextFile(
interp,
`../../vendor/linuxcnc/nc_files/${filename}`,
wasmPath,
);
interp.writeTextFile(
`${wasmDir}/tool.tbl`,
"T1 P1 D10.000000 Z+0.000000 ; nc_files representative context tool\n",
);
interp.writeTextFile(
iniPath,
[
"[RS274NGC]",
"SUBROUTINE_PATH = .",
"",
"[TRAJ]",
"COORDINATES = X Y Z A B C U V W",
"",
"[EMCIO]",
"TOOL_TABLE = tool.tbl",
"",
].join("\n"),
);
return interp.runFileWithIni(wasmPath, iniPath);
}
async function verifyRejects(fixtureName, operation, expectedPattern) {
try {
await operation();
@@ -507,6 +544,18 @@
);
}
verifyExpectedOutput(
"browser_minimal_linear_run_steps",
interp.runFile("/work/minimal_linear.ngc"),
[
"run_step phase=read step=1 rc=0 line=1",
"run_step phase=execute step=1 rc=0 line=1 x=1 y=2 z=0",
"statement_uri=G0%20X1.0%20Y2.0%20%28Comment%29",
"run_step phase=execute step=2 rc=0 line=2 x=3 y=4 z=0",
"statement_uri=G1%20X3.0%20Y4.0%20F120.0",
].join("\n"),
);
const namedParamPath = `/work/${INTERP_INI_FIXTURE}.ngc`;
interp.writeTextFile(namedParamPath, namedParamProgramText);
verifyExpectedOutput(
@@ -564,6 +613,28 @@
].join("\n"),
);
verifyExpectedOutput(
"browser_nc_files_3d_chips_context",
await runVendorNcFileWithToolTable(interp, "3D_Chips.ngc"),
[
"file_open=0",
"file_read_count=4706",
"file_execute_count=4706",
"file_saw_error=0",
"run_step phase=execute step=18 rc=2 line=18",
"statement_uri=N50T%23%3Ctoolno%3EM6",
"run_step phase=execute step=19 rc=0 line=19",
"statement_uri=N60M8",
"canon_event=CHANGE_TOOL",
"canon_event=START_SPINDLE_CLOCKWISE spindle=0",
"canon_event=STRAIGHT_TRAVERSE line=21 x=0 y=0 z=10",
"canon_event=STRAIGHT_FEED line=23 x=53 y=-56.128 z=-25.372",
"canon_event=PROGRAM_END",
"absent=file_error_text=",
"absent=Requested tool 1 not found",
].join("\n"),
);
verifyExpectedOutput(
"browser_nc_files_arcspiral",
await runVendorNcFile(interp, "arcspiral.ngc"),
@@ -622,16 +693,13 @@
].join("\n"),
);
const foam = await loadSimMachineFiles("axis/foam", [
"axis_foam.ini",
"foam.ngc",
]);
const foam = await loadSimMachineFiles("axis/foam", "axis_foam.ini", "foam.ngc");
verifyExpectedOutput(
"browser_sim_axis_foam_uv",
interp.runSimConfigProgram({
files: foam.files,
programPath: `${foam.wasmDir}/foam.ngc`,
iniPath: `${foam.wasmDir}/axis_foam.ini`,
programPath: foam.programPath,
iniPath: foam.iniPath,
}),
[
"file_open=0",
@@ -644,21 +712,15 @@
const bridgeMillSim = await loadSimMachineFiles(
"axis/vismach/5axis/bridgemill",
[
"5axis.ini",
"5axis.tbl",
"5axisgui.ngc",
"remap_subs/428remap.ngc",
"remap_subs/429remap.ngc",
"remap_subs/430remap.ngc",
],
"5axis.ini",
"5axisgui.ngc",
);
verifyExpectedOutput(
"browser_sim_axis_bridgemill_w",
interp.runSimConfigProgram({
files: bridgeMillSim.files,
programPath: `${bridgeMillSim.wasmDir}/5axisgui.ngc`,
iniPath: `${bridgeMillSim.wasmDir}/5axis.ini`,
programPath: bridgeMillSim.programPath,
iniPath: bridgeMillSim.iniPath,
executionMode: "fiveAxisRemap",
}),
[
@@ -682,19 +744,15 @@
const geometry = await loadSimMachineFiles(
"axis/geometry",
[
"M110",
"xyzc.ini",
"xyzc.ngc",
],
["M110"],
"xyzc.ini",
"xyzc.ngc",
);
verifyExpectedOutput(
"browser_sim_axis_geometry_xyzc_user_m110",
interp.runSimConfigProgram({
files: geometry.files,
programPath: `${geometry.wasmDir}/xyzc.ngc`,
iniPath: `${geometry.wasmDir}/xyzc.ini`,
programPath: geometry.programPath,
iniPath: geometry.iniPath,
}),
[
"file_open=0",
@@ -706,30 +764,67 @@
].join("\n"),
);
const externalOffsets = await loadSimMachineFiles(
"axis/external_offsets",
[
"M111",
"dyn_demo.ngc",
"dynamic_offsets.ini",
],
["M111"],
);
verifyExpectedOutput(
"browser_sim_axis_external_offsets_user_m111",
interp.runSimConfigProgram({
files: externalOffsets.files,
programPath: `${externalOffsets.wasmDir}/dyn_demo.ngc`,
iniPath: `${externalOffsets.wasmDir}/dynamic_offsets.ini`,
}),
[
"file_open=0",
"file_saw_error=0",
"canon_event=USER_M_COMMAND code=M111",
"canon_event=PROGRAM_END",
"absent=Unknown m code used: M111",
].join("\n"),
);
for (const externalOffsetCase of [
{
name: "dyn_demo",
program: "dyn_demo.ngc",
ini: "dynamic_offsets.ini",
readCount: 833,
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=21 x=0 y=0 z=0",
firstFeed: "canon_event=STRAIGHT_FEED line=26 x=9 y=0 z=1.5",
},
{
name: "eoffsets",
program: "eoffsets.ngc",
ini: "eoffsets.ini",
readCount: 35,
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=24 x=0 y=0 z=0",
firstFeed: "canon_event=STRAIGHT_FEED line=27 x=2.25 y=2.64 z=0",
},
{
name: "jwp_z",
program: "jwp_z.ngc",
ini: "jwp_z.ini",
readCount: 35,
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=17 x=0 y=0 z=0.5",
firstFeed: "canon_event=STRAIGHT_FEED line=24 x=2.5 y=3.3 z=0",
},
{
name: "opa_demo",
program: "opa_demo.ngc",
ini: "opa.ini",
readCount: 58,
firstTraverse: "canon_event=STRAIGHT_TRAVERSE line=13 x=1 y=0 z=0",
firstFeed: "canon_event=STRAIGHT_FEED line=35 x=1 y=0 z=0",
},
]) {
const externalOffsets = await loadSimMachineFiles(
"axis/external_offsets",
externalOffsetCase.ini,
externalOffsetCase.program,
);
verifyExpectedOutput(
`browser_sim_axis_external_offsets_${externalOffsetCase.name}_user_m111`,
interp.runSimConfigProgram({
files: externalOffsets.files,
programPath: externalOffsets.programPath,
iniPath: externalOffsets.iniPath,
}),
[
"file_open=0",
`file_read_count=${externalOffsetCase.readCount}`,
`file_execute_count=${externalOffsetCase.readCount}`,
"file_saw_error=0",
"canon_event=USER_M_COMMAND code=M111",
externalOffsetCase.firstTraverse,
externalOffsetCase.firstFeed,
"canon_event=PROGRAM_END",
"absent=Unknown m code used: M111",
"absent=Bad character",
"absent=Cannot use axis values",
].join("\n"),
);
}
const fiveAxisTrtDir = await writeFiveAxisTrtMachineFiles(interp);
verifyExpectedOutput(