88 lines
4.4 KiB
JavaScript
88 lines
4.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { createHash } from "node:crypto";
|
|
import { readFile } from "node:fs/promises";
|
|
import createModule from "../../build-wasm/linuxcnc-sim-core.js";
|
|
import { compareEndpoints, createEndpoint, endpointHash } from "./endpoint-replay.mjs";
|
|
import { SimSession, CONTEXT_ID } from "./sim-session.mjs";
|
|
|
|
const ROOT = new URL("../../", import.meta.url);
|
|
const SOURCE_REPORTS = [
|
|
"coverage/linuxcnc-source-test-s5.report.json",
|
|
"coverage/linuxcnc-source-test-execution-s5.report.json",
|
|
"coverage/linuxcnc-source-unit-execution-s5.report.json",
|
|
"coverage/linuxcnc-source-interp-s5.report.json",
|
|
"coverage/linuxcnc-source-hal-s5.report.json",
|
|
"coverage/linuxcnc-source-io-s5.report.json",
|
|
"coverage/linuxcnc-source-config-s5.report.json",
|
|
];
|
|
|
|
async function loadReports() {
|
|
const reports = [];
|
|
for (const path of SOURCE_REPORTS) {
|
|
const bytes = await readFile(new URL(path, ROOT));
|
|
const report = JSON.parse(bytes);
|
|
assert.equal(report.status, "verified", path);
|
|
reports.push({ path, task_id: report.task_id, schema: report.schema, sha256: createHash("sha256").update(bytes).digest("hex") });
|
|
}
|
|
return reports;
|
|
}
|
|
|
|
async function sessionWithPlan(id, fast = false) {
|
|
const wasmBinary = await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url));
|
|
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 sequence = 0;
|
|
const send = (kind, operationId, payload = {}) => {
|
|
sequence += 1;
|
|
const response = session.accept({ ...base, kind, seq: sequence, operation_id: operationId, payload });
|
|
assert.notEqual(response.kind, "ERROR", `${id}:${kind}:${response.payload?.code ?? "error"}`);
|
|
return response;
|
|
};
|
|
send("HELLO", "hello");
|
|
send("SESSION_ATTACH", "attach");
|
|
send("LOAD_WORKSPACE", "workspace", { root_path: "/workspace" });
|
|
send("PROGRAM_LOAD", "program", { source: "G0 X1\nG1 X2\n", path: "parity.ngc" });
|
|
send("PROGRAM_RUN", "run");
|
|
if (fast) send("SIM_STEP", "fast-step", { cycles: 4 });
|
|
else for (let index = 0; index < 4; index += 1) send("SIM_STEP", `step-${index}`, { cycles: 1 });
|
|
return { session, send };
|
|
}
|
|
|
|
const sourceReports = await loadReports();
|
|
const oneX = await sessionWithPlan("source-parity-1x", false);
|
|
const fast = await sessionWithPlan("source-parity-fast", true);
|
|
const oneEndpoint = createEndpoint({ session: oneX.session });
|
|
const fastEndpoint = createEndpoint({ session: fast.session });
|
|
const modeParity = compareEndpoints(oneEndpoint, fastEndpoint);
|
|
assert.equal(modeParity.equal, true);
|
|
|
|
const recovering = await sessionWithPlan("source-parity-recover", false);
|
|
const checkpoint = recovering.send("CHECKPOINT", "checkpoint").payload.checkpoint;
|
|
recovering.send("SIM_STEP", "post-checkpoint", { cycles: 2 });
|
|
const continuousEndpoint = createEndpoint({ session: recovering.session });
|
|
const recovery = recovering.session.restoreCheckpoint(checkpoint, recovering.session.timeline.export(), (operation) => operation);
|
|
assert.equal(recovery.status, "recovered");
|
|
const recoveredEndpoint = createEndpoint({ session: recovering.session });
|
|
const recoveryParity = compareEndpoints(continuousEndpoint, recoveredEndpoint);
|
|
assert.equal(recoveryParity.equal, true);
|
|
|
|
const trace = recovering.session.exportTrace();
|
|
const traceCore = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) });
|
|
const traceSession = new SimSession(traceCore, { sessionId: "source-parity-recover" });
|
|
const imported = traceSession.importTrace(trace);
|
|
assert.equal(imported.trace_hash, trace.trace_hash);
|
|
const traceParity = compareEndpoints(recoveredEndpoint, createEndpoint({ session: traceSession }));
|
|
assert.equal(traceParity.equal, true);
|
|
|
|
const output = {
|
|
schema: "linuxcnc-source-parity-s5.v1",
|
|
context_id: CONTEXT_ID,
|
|
source_reports: sourceReports,
|
|
modes: { one_x: endpointHash(oneEndpoint), fast: endpointHash(fastEndpoint) },
|
|
differences: { first_divergence: null, mode: modeParity, recovery: recoveryParity, trace_import: traceParity },
|
|
recovery: { checkpoint_hash: checkpoint.checkpoint_hash, continuous_hash: endpointHash(continuousEndpoint), recovered_hash: endpointHash(recoveredEndpoint), trace_hash: trace.trace_hash, status: recovery.status },
|
|
status: "verified",
|
|
};
|
|
console.log(JSON.stringify(output));
|