Implement AXIS parity UI and execution baseline

This commit is contained in:
2026-08-23 07:28:37 +08:00
parent 1325504544
commit 06f96f85e5
463 changed files with 84893 additions and 692 deletions

View File

@@ -0,0 +1,54 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import createModule from "../../build-wasm/linuxcnc-sim-core.js";
import { SimSession, CONTEXT_ID } from "./sim-session.mjs";
const core = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) });
const session = new SimSession(core, { sessionId: "runner-session" });
const base = { schema_version: 1, context_id: CONTEXT_ID, session_id: "runner-session" };
const send = (kind, seq, operation_id, payload = {}) => session.accept({ ...base, kind, seq, operation_id, payload });
send("HELLO", 1);
send("SESSION_ATTACH", 2, "attach");
send("LOAD_WORKSPACE", 3, "load", { root_path: "/workspace" });
const mdi = send("MDI_EXECUTE", 4, "mdi", { block: "G21 G90 G1 X3 Y4 F60" });
assert.equal(mdi.payload.state.x, 3);
assert.equal(mdi.payload.runner.canonical.includes('"x":3'), true);
assert.match(mdi.payload.runner.modal_hash, /^fnv1a64:/);
assert.equal(mdi.payload.runner.state.line, 1);
assert.equal(mdi.payload.runner.program_status, "idle");
const offset = send("MDI_EXECUTE", 5, "mdi-offset", { block: "G10 L2 P1 X10 Y20 Z30" });
assert.equal(offset.payload.runner.state.x, 3);
const offsetMove = send("MDI_EXECUTE", 6, "mdi-offset-move", { block: "G54 G90 X1 Y2 Z3" });
assert.equal(offsetMove.payload.state.x, 11);
assert.equal(offsetMove.payload.state.y, 22);
assert.equal(offsetMove.payload.state.z, 33);
const loaded = send("PROGRAM_LOAD", 7, "program-load", { source: "G21 G90\nG1 X2 F60\nM2\n", path: "runner.ngc" });
assert.equal(loaded.payload.canonical.includes('"units":21'), true);
send("PROGRAM_RUN", 8, "program-run");
const tick = send("SIM_STEP", 9, "tick", { cycles: 1 });
assert.equal(tick.payload.program.state.line, 1);
assert.equal(tick.payload.task.current_line, 1);
send("PROGRAM_PAUSE", 10, "pause");
send("PROGRAM_RESUME", 11, "resume");
const abort = send("PROGRAM_ABORT", 12, "abort");
assert.equal(abort.payload.task.program_status, "aborted");
const checkpoint = send("CHECKPOINT", 13, "checkpoint").payload.checkpoint;
const recovered = session.restoreCheckpoint(checkpoint, null, (operation) => operation);
assert.equal(recovered.status, "recovered");
assert.equal(recovered.state.task.program_status, "aborted");
const errorCore = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) });
const errorSession = new SimSession(errorCore, { sessionId: "runner-error" });
const errorBase = { schema_version: 1, context_id: CONTEXT_ID, session_id: "runner-error" };
const errorSend = (kind, seq, operation_id, payload = {}) => errorSession.accept({ ...errorBase, kind, seq, operation_id, payload });
errorSend("HELLO", 1); errorSend("SESSION_ATTACH", 2, "a"); errorSend("LOAD_WORKSPACE", 3, "l", { root_path: "/workspace" });
errorSend("PROGRAM_LOAD", 4, "bad-load", { source: "G999\n" });
errorSend("PROGRAM_RUN", 5, "bad-run");
const error = errorSend("PROGRAM_STEP", 6, "bad-step");
assert.equal(error.kind, "ERROR");
assert.equal(error.payload.code, "program_interpreter");
assert.equal(error.payload.line, 1);
assert.equal(error.payload.column, 1);
assert.equal(error.payload.error_code, -504);
console.log(`sim_runner=passed mdi_x=${mdi.payload.state.x} tick_line=${tick.payload.task.current_line} recovery=${recovered.state.task.program_status}`);