Implement AXIS parity UI and execution baseline
This commit is contained in:
88
web/worker/test_configuration_startup_runtime.mjs
Normal file
88
web/worker/test_configuration_startup_runtime.mjs
Normal file
@@ -0,0 +1,88 @@
|
||||
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 { ConfigurationStartupStateMachine, startConfiguration } from "../workspace/configuration.mjs";
|
||||
import { SimSession, CONTEXT_ID } from "./sim-session.mjs";
|
||||
|
||||
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 manifest = [{ component: "sim" }];
|
||||
const nativeCalls = [];
|
||||
let nativeSeq = 0;
|
||||
const nativeCore = {
|
||||
_sim_create() { nativeCalls.push("create"); return 0; },
|
||||
_sim_load_workspace(path) { nativeCalls.push(`load:${path}`); return 0; },
|
||||
};
|
||||
const native = startConfiguration({ workspace: new WorkspaceRuntime({ files }), entrypoint: "config/main.ini", core: nativeCore, halManifest: manifest });
|
||||
const nativeAgain = startConfiguration({ workspace: new WorkspaceRuntime({ files }), entrypoint: "config/main.ini", core: nativeCore, halManifest: manifest });
|
||||
assert.equal(native.state, "TASK_READY");
|
||||
assert.equal(native.status, "ready");
|
||||
assert.equal(native.state_hash, nativeAgain.state_hash);
|
||||
assert.deepEqual(native.transitions.map((row) => row.to), ["NEW", "MOUNTED", "PARSED", "RESOLVED", "CORE_CREATED", "HAL_READY", "TASK_READY"]);
|
||||
assert.deepEqual(nativeCalls, ["create", "load:/workspace", "create", "load:/workspace"]);
|
||||
|
||||
const wasm = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) });
|
||||
const wasmReport = startConfiguration({ workspace: new WorkspaceRuntime({ files }), entrypoint: "config/main.ini", core: wasm, halManifest: manifest });
|
||||
assert.equal(wasmReport.state, "TASK_READY");
|
||||
assert.equal(wasmReport.state_hash, native.state_hash);
|
||||
|
||||
const missing = startConfiguration({ workspace: new WorkspaceRuntime({ files: { "config/main.ini": "[HAL]\nHALFILE = missing.hal\n" } }), entrypoint: "config/main.ini", core: nativeCore });
|
||||
assert.equal(missing.status, "blocked");
|
||||
assert.equal(missing.state, "BLOCKED");
|
||||
assert.equal(missing.diagnostics[0].source, "config/main.ini");
|
||||
assert.equal(missing.diagnostics[0].line, 2);
|
||||
assert.equal(missing.resources.resources[0].code, "resource_missing");
|
||||
|
||||
const duplicate = startConfiguration({ workspace: new WorkspaceRuntime({ files: { ...files, "config/duplicate.ini": "[HAL]\nHALFILE = machine.hal\nHALFILE = machine.hal\n" } }), entrypoint: "config/duplicate.ini", core: nativeCore });
|
||||
assert.equal(duplicate.status, "blocked");
|
||||
assert.ok(duplicate.resources.resources.some((row) => row.code === "resource_duplicate"));
|
||||
|
||||
const hostPath = startConfiguration({ workspace: new WorkspaceRuntime({ files: { "config/main.ini": "[HAL]\nHALFILE = /tmp/machine.hal\n" } }), entrypoint: "config/main.ini", core: nativeCore });
|
||||
assert.equal(hostPath.status, "blocked");
|
||||
assert.equal(hostPath.resources.resources[0].code, "resource_host_path");
|
||||
|
||||
const ambiguous = startConfiguration({ workspace: new WorkspaceRuntime({ files: {
|
||||
"config/main.ini": "[HAL]\nHALFILE = LIB:machine.hal\n",
|
||||
"linuxcnc/lib/machine.hal": "setp sim.x 1\n",
|
||||
"linuxcnc/lib/hallib/machine.hal": "setp sim.x 2\n",
|
||||
} }), entrypoint: "config/main.ini", core: nativeCore });
|
||||
assert.equal(ambiguous.status, "blocked");
|
||||
assert.equal(ambiguous.resources.resources[0].code, "resource_ambiguous");
|
||||
|
||||
const unsupportedHal = startConfiguration({ workspace: new WorkspaceRuntime({ files: { "config/main.ini": "[HAL]\nHALFILE = machine.hal\n", "config/machine.hal": "loadrt unknown names=u\n" } }), entrypoint: "config/main.ini", core: nativeCore, halManifest: [] });
|
||||
assert.equal(unsupportedHal.status, "blocked");
|
||||
assert.equal(unsupportedHal.diagnostics[0].source, "config/machine.hal");
|
||||
assert.equal(unsupportedHal.diagnostics[0].line, 1);
|
||||
assert.equal(unsupportedHal.diagnostics[0].hal.records[0].code, "hal_component_undeclared");
|
||||
|
||||
let workerSeq = 0;
|
||||
const workerCore = {
|
||||
_sim_protocol_reset() {},
|
||||
_sim_protocol_accept(...args) { if (args[1] !== workerSeq + 1) return -101; workerSeq = args[1]; return 0; },
|
||||
_sim_create() { return 0; },
|
||||
_sim_load_workspace() { return 0; },
|
||||
};
|
||||
const session = new SimSession(workerCore, { sessionId: "startup-session" });
|
||||
const base = { schema_version: 1, context_id: CONTEXT_ID, session_id: "startup-session" };
|
||||
assert.equal(session.accept({ ...base, kind: "HELLO", seq: 1, payload: {} }).kind, "CAPABILITIES");
|
||||
assert.equal(session.accept({ ...base, kind: "SESSION_ATTACH", seq: 2, operation_id: "attach", payload: {} }).kind, "SESSION_READY");
|
||||
const workerResult = session.accept({ ...base, kind: "LOAD_WORKSPACE", seq: 3, operation_id: "startup", payload: {
|
||||
root_path: "/workspace",
|
||||
configuration: { entrypoint: "config/main.ini", files, halManifest: manifest },
|
||||
} });
|
||||
assert.equal(workerResult.kind, "COMMAND_RESULT");
|
||||
assert.equal(workerResult.payload.configuration.state, "TASK_READY");
|
||||
assert.equal(workerResult.payload.configuration.state_hash, native.state_hash);
|
||||
const workerBlocked = session.accept({ ...base, kind: "LOAD_WORKSPACE", seq: 4, operation_id: "blocked", payload: {
|
||||
root_path: "/workspace",
|
||||
configuration: { entrypoint: "config/main.ini", files: { "config/main.ini": "[HAL]\nHALFILE = missing.hal\n" } },
|
||||
} });
|
||||
assert.equal(workerBlocked.kind, "ERROR");
|
||||
assert.equal(workerBlocked.payload.code, "configuration_startup");
|
||||
assert.equal(workerBlocked.payload.startup.state, "BLOCKED");
|
||||
|
||||
console.log(`configuration_startup_runtime=passed state_hash=${native.state_hash} resource_hash=${native.resources.state_hash}`);
|
||||
Reference in New Issue
Block a user