47 lines
3.0 KiB
JavaScript
47 lines
3.0 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
import createModule from "../../build-wasm/linuxcnc-sim-core.js";
|
|
import { compareEndpoints, createEndpoint, endpointHash } from "./endpoint-replay.mjs";
|
|
import { loadSimulationCase, toWorkerConfiguration } from "../workspace/sim-case-loader.mjs";
|
|
import { SimSession, CONTEXT_ID } from "./sim-session.mjs";
|
|
|
|
const CASE = "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.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 });
|
|
const wasmBinary = await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url));
|
|
|
|
async function create(id) {
|
|
const core = await createModule({ wasmBinary });
|
|
const session = new SimSession(core, { sessionId: id });
|
|
const base = { schema_version: 1, context_id: CONTEXT_ID, session_id: id };
|
|
let seq = 0;
|
|
const send = (kind, operationId, payload = {}) => session.accept({ ...base, kind, seq: ++seq, operation_id: operationId, payload });
|
|
send("HELLO", "hello"); send("SESSION_ATTACH", "attach");
|
|
const loaded = send("LOAD_WORKSPACE", "load", { root_path: "/workspace", configuration: toWorkerConfiguration(bundle) });
|
|
assert.equal(loaded.payload.configuration.state, "TASK_READY");
|
|
send("PROGRAM_LOAD", "program", { path: "persist.ngc", source: "G21 G90\nG0 X0 Y0 Z0\nG1 X2 Y1 F60\nG1 Z-1\nM2\n" });
|
|
send("PROGRAM_RUN", "run");
|
|
return { session, send };
|
|
}
|
|
|
|
const continuous = await create("axis3-tutorial-persistence");
|
|
const checkpoint = continuous.send("CHECKPOINT", "checkpoint").payload.checkpoint;
|
|
continuous.send("SIM_STEP", "step-a", { cycles: 3 });
|
|
const continuousEndpoint = createEndpoint({ session: continuous.session });
|
|
|
|
const recovered = await create("axis3-tutorial-persistence");
|
|
const recovery = recovered.session.restoreCheckpoint(checkpoint, continuous.session.timeline.export(), (operation) => operation);
|
|
assert.equal(recovery.status, "recovered");
|
|
const recoveredEndpoint = createEndpoint({ session: recovered.session });
|
|
const parity = compareEndpoints(continuousEndpoint, recoveredEndpoint);
|
|
assert.equal(parity.equal, true);
|
|
|
|
const bad = structuredClone(checkpoint);
|
|
bad.state_hash = "fnv1a64:bad";
|
|
const blocked = recovered.session.restoreCheckpoint(bad, null, (operation) => operation);
|
|
assert.equal(blocked.status, "blocked");
|
|
|
|
const continuousHash = endpointHash(continuousEndpoint);
|
|
const recoveredHash = endpointHash(recoveredEndpoint);
|
|
console.log(JSON.stringify({ schema: "axis3-tutorial-persistence.v1", status: "verified", case: CASE, exact_runtime_files: ["3axis-tutorial_mm.var", "tool.tbl", "position_mm.txt"], checkpoint_hash: checkpoint.checkpoint_hash, continuous_hash: continuousHash, recovered_hash: recoveredHash, endpoint_equal: parity.equal, blocked_bad_checkpoint: blocked.status, event_cursor: checkpoint.event_cursor }));
|