Files
linuxcncWebWASM/web/worker/test_xyzac_session.mjs

72 lines
3.8 KiB
JavaScript

import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import createModule from "../../build-wasm/linuxcnc-sim-core.js";
import { XyzacSession, CONTEXT_ID } from "./xyzac-session.mjs";
import { XyzacCommandLedger } from "./xyzac-command-ledger.mjs";
import { XYZAC_SCHEDULER_PHASES } from "./xyzac-scheduler.mjs";
import { loadSimulationCase, toWorkerConfiguration } from "../workspace/sim-case-loader.mjs";
const CASE = "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini";
const fetchImpl = async (url) => {
try { const body = await readFile(new URL(`../../${String(url).replace(/^\//, "")}`, import.meta.url)); return { ok: true, text: async () => body.toString("utf8") }; }
catch { return { ok: false, text: async () => "" }; }
};
const bundle = await loadSimulationCase({ path: CASE, fetchImpl });
assert.equal(bundle.status, "ready");
const core = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) });
const session = new XyzacSession(core, { sessionId: "xyzac-rtcp-01" });
const base = { schema_version: 1, context_id: CONTEXT_ID, session_id: session.sessionId };
let seq = 0;
const send = (kind, operation_id, payload = {}) => session.accept({ ...base, kind, seq: ++seq, operation_id, payload });
const hello = send("HELLO", "hello");
assert.equal(hello.kind, "CAPABILITIES");
assert.equal(hello.payload.xyzac_session.scope, "selected_xyzac_simulation");
assert.equal(hello.payload.xyzac_session.machine.joint_count, 5);
assert.deepEqual(hello.payload.xyzac_scheduler.phase_trace, XYZAC_SCHEDULER_PHASES);
assert.equal(hello.payload.xyzac_ledger.pending_count, 0);
const attached = send("SESSION_ATTACH", "attach");
assert.equal(attached.kind, "SESSION_READY");
const loaded = send("LOAD_WORKSPACE", "workspace", { root_path: "/workspace", configuration: toWorkerConfiguration(bundle) });
assert.equal(loaded.payload.status, "verified");
assert.equal(loaded.payload.xyzac_session.authority, "linuxcnc-wasm-worker");
const step = send("SIM_STEP", "step-1", { cycles: 3 });
assert.equal(step.payload.status, "verified");
assert.equal(step.payload.xyzac_scheduler.tick, 3);
assert.equal(step.payload.xyzac_scheduler.clock, "logical_tick");
assert.equal(session.ledger.reconcile("step-1").status, "committed");
const replay = session.accept({ ...base, kind: "SIM_STEP", seq: ++seq, operation_id: "step-1", payload: { cycles: 99 } });
assert.equal(replay.replayed, true);
assert.equal(session.scheduler.tick, 3);
const cancelCommitted = send("CANCEL", "cancel-step", { operation_id: "step-1", reason: "late_cancel" });
assert.equal(cancelCommitted.payload.retry_allowed, false);
assert.equal(cancelCommitted.payload.ledger.status, "too_late");
const gap = session.accept({ ...base, kind: "SNAPSHOT_REQUEST", seq: ++seq + 1, payload: {} });
assert.equal(gap.kind, "ERROR");
assert.equal(gap.payload.code, "protocol_sequence");
const ledger = new XyzacCommandLedger();
ledger.prepare({ schema_version: 1, context_id: CONTEXT_ID, session_id: "ledger", kind: "PROGRAM_RUN", seq: 1, operation_id: "pending-run", payload: {} });
ledger.execute("pending-run");
assert.equal(ledger.pending().length, 1);
assert.equal(ledger.reconcileAll()[0].status, "executing");
assert.equal(ledger.timeoutReconcile("pending-run").retry_allowed, false);
assert.equal(ledger.abort("pending-run").status, "aborted");
assert.equal(ledger.pending().length, 0);
assert.equal(ledger.audit().scope, "selected_xyzac_simulation");
console.log(JSON.stringify({
schema: "xyzac-session-rtcp-01.v1",
status: "verified",
case: CASE,
authority: session.authority(),
tick: session.scheduler.tick,
replayed: replay.replayed === true,
committed: session.ledger.reconcile("step-1").status,
pending_after_abort: ledger.pending().length,
state_hash: step.payload.xyzac_scheduler.state_hash,
}));