import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import createModule from "../../build-wasm/linuxcnc-sim-core.js"; import { WorkspaceRuntime } from "../workspace/runtime.mjs"; import { startConfiguration } from "../workspace/configuration.mjs"; import { ConfigurationBatchRuntime } from "../workspace/configuration-batch.mjs"; import { SimSession, CONTEXT_ID } from "./sim-session.mjs"; const matrix = JSON.parse(await readFile(new URL("../../coverage/full-configuration-startup-matrix.report.json", import.meta.url))); const batch = new ConfigurationBatchRuntime({ context_id: CONTEXT_ID }); assert.equal(batch.load(matrix.matrix, { context_id: CONTEXT_ID }).status, "verified"); assert.deepEqual(batch.state.counts, { total: 264, ready: 56, blocked: 208, startup_preflight: { blocked_resource: 194, blocked_unindexed_resource_graph: 11, blocked_unregistered_kinematics: 3, static_ready: 56 }, resource_status: { blocked_missing: 147, blocked_missing_and_unresolved: 49, ready: 9, unindexed: 59 }, }); assert.equal(batch.state.diagnostics.length, 208); assert.equal(batch.state.diagnostics.find((row) => row.config_id === matrix.matrix[0].config_id).code, "resource_missing"); assert.equal(batch.load([matrix.matrix[0], matrix.matrix[0]], { context_id: CONTEXT_ID }).code, "configuration_batch_duplicate"); assert.equal(batch.load([{ ...matrix.matrix[0], status: "ready" }], { context_id: CONTEXT_ID }).code, "configuration_batch_status"); assert.equal(batch.load(matrix.matrix, { context_id: CONTEXT_ID }).status, "verified"); const saved = batch.export(); const restored = new ConfigurationBatchRuntime({ context_id: CONTEXT_ID }); assert.deepEqual(restored.restore(saved), saved); const files = { "config/main.ini": "[HAL]\nHALFILE = machine.hal\n[RS274NGC]\nPROGRAM = main.ngc\n", "config/machine.hal": "setp sim.x 1\n", "config/main.ngc": "G0 X1\n" }; const native = startConfiguration({ workspace: new WorkspaceRuntime({ files }), entrypoint: "config/main.ini", core: { _sim_create() { return 0; }, _sim_load_workspace() { return 0; } }, halManifest: [{ component: "sim" }] }); const wasm = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) }); const wasmStartup = startConfiguration({ workspace: new WorkspaceRuntime({ files }), entrypoint: "config/main.ini", core: wasm, halManifest: [{ component: "sim" }] }); assert.equal(native.status, "ready"); assert.equal(wasmStartup.state_hash, native.state_hash); let sequence = 0; const core = { _sim_protocol_reset() {}, _sim_protocol_accept() { return 0; }, _sim_create() { return 0; }, _sim_load_workspace() { return 0; }, _sim_step() { return 0; }, _sim_protocol_set_tick() { return 0; } }; const session = new SimSession(core, { sessionId: "configuration-batch" }); const base = { schema_version: 1, context_id: CONTEXT_ID, session_id: "configuration-batch" }; const send = (kind, operation_id, payload = {}) => { sequence += 1; return session.accept({ ...base, kind, seq: sequence, operation_id, payload }); }; send("HELLO"); send("SESSION_ATTACH", "attach"); send("LOAD_WORKSPACE", "workspace", { root_path: "/workspace" }); const readyRow = matrix.matrix.find((row) => row.status === "ready"); const blockedRows = matrix.matrix.filter((row) => row.status === "blocked"); const sample = [blockedRows[0], readyRow, blockedRows.at(-1)]; const response = send("CONFIGURATION_BATCH", "batch", { entries: sample }); assert.equal(response.kind, "COMMAND_RESULT"); assert.equal(response.payload.configuration_batch.counts.total, 3); assert.equal(response.payload.configuration_batch.counts.ready, 1); const checkpoint = send("CHECKPOINT", "checkpoint").payload.checkpoint; assert.equal(checkpoint.state.configuration_batch.schema, "configuration-startup-batch.v1"); console.log(JSON.stringify({ schema: "configuration-batch-s2-sample.v1", status: "verified", total: batch.state.counts.total, ready: 56, blocked: 208, batch_hash: saved.state_hash, native_state_hash: native.state_hash, wasm_state_hash: wasmStartup.state_hash, worker_hash: response.payload.configuration_batch.state_hash, checkpoint_hash: checkpoint.checkpoint_hash }));