按规划继续工作
结论:补齐通用会话快照 envelope 的格式、版本、会话 ID 与对象形状拒绝验证,覆盖 Node OPFS 与 Chromium OPFS 路径,并通过 host/WASM/browser 聚合验证。
This commit is contained in:
@@ -99,8 +99,10 @@ directory creation, text save/load, missing file behavior, invalid relative
|
||||
paths, unavailable OPFS storage, and the host-side OPFS path model for INI,
|
||||
tool table, parameter, G-code, preview-cache, and session-snapshot storage
|
||||
targets. It also validates the host-side session snapshot JSON envelope and
|
||||
round-trip store plus pure-text machine file and G-code stores without
|
||||
defining CNC machine-state or file-format semantics. It now also validates the
|
||||
round-trip store, including unsupported format/version, session-id mismatch,
|
||||
and non-object metadata/payload rejection, plus pure-text machine file and
|
||||
G-code stores without defining CNC machine-state or file-format semantics. It
|
||||
now also validates the
|
||||
OPFS-to-WASM parameter-file bridge with a mock interpreter SDK to ensure the
|
||||
host boundary copies text into and out of the WASM filesystem without defining
|
||||
parameter semantics, and that INI-derived machine file names are still
|
||||
@@ -112,8 +114,8 @@ keeping host override policy outside CNC semantics.
|
||||
The browser INI/OPFS smoke script serves `wasm-port/` over localhost and runs
|
||||
Chromium headless against a test page that imports the JS SDK, loads the INI
|
||||
WASM module, queries vendored LinuxCNC INI parsing through the SDK, and
|
||||
performs an OPFS text-file, generic session snapshot, machine file, and G-code
|
||||
text round trip.
|
||||
performs an OPFS text-file, generic session snapshot, invalid snapshot
|
||||
envelope, machine file, and G-code text round trip.
|
||||
|
||||
The browser interpreter smoke script serves `wasm-port/` over localhost and
|
||||
runs Chromium headless against a test page that loads the interpreter-core
|
||||
@@ -184,8 +186,8 @@ The validation fails if:
|
||||
| --- | --- |
|
||||
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI. |
|
||||
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the initial interpreter-core WASM module can be built from vendored LinuxCNC interpreter source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
|
||||
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store, machine file store, G-code text store, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
|
||||
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, OPFS text-file round trip, generic session snapshot round trip, machine file text round trip, G-code text round trip, and the INI panel UI's machine-session load, G-code run, and canonical-event display paths in a real browser runtime. |
|
||||
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including envelope rejection paths, machine file store, G-code text store, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
|
||||
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, OPFS text-file round trip, generic session snapshot round trip plus envelope rejection paths, machine file text round trip, G-code text round trip, and the INI panel UI's machine-session load, G-code run, and canonical-event display paths in a real browser runtime. |
|
||||
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including OPFS-backed parameter-file restore/save and tool-table load/save through vendored LinuxCNC source. |
|
||||
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, OPFS, and browser smoke validation with shared WASM builds. |
|
||||
|
||||
@@ -268,9 +270,10 @@ derived from vendored LinuxCNC INI boolean parsing, INI-derived
|
||||
`[RS274NGC]PARAMETER_FILE` and `[EMCIO]TOOL_TABLE` file names mapped to OPFS
|
||||
machine files, OPFS path-model rejection of invalid INI-derived file names,
|
||||
explicit host session file-name overrides taking precedence over INI-derived
|
||||
names, and a browser interpreter smoke that uses the same session bridge with
|
||||
real LinuxCNC INI WASM parsing before saving OPFS-backed parameter and
|
||||
tool-table text through vendored LinuxCNC file APIs.
|
||||
names, session snapshot envelope rejection for unsupported format/version and
|
||||
wrong session id, and a browser interpreter smoke that uses the same session
|
||||
bridge with real LinuxCNC INI WASM parsing before saving OPFS-backed parameter
|
||||
and tool-table text through vendored LinuxCNC file APIs.
|
||||
Full browser coverage, full SDK coverage, and richer machine-state validation
|
||||
remain future work.
|
||||
|
||||
|
||||
@@ -70,8 +70,9 @@ semantic rewrites:
|
||||
host-side path model, generic session snapshot storage, pure-text machine
|
||||
file and G-code storage, parameter/tool-table bridge copying into the
|
||||
interpreter SDK filesystem, grouped machine-session loading, explicit
|
||||
session file-name overrides, invalid INI-derived machine file names, and a
|
||||
Chromium localhost round trip for those persistence paths.
|
||||
session file-name overrides, invalid INI-derived machine file names, generic
|
||||
session snapshot envelope rejection paths, and a Chromium localhost round
|
||||
trip for those persistence paths.
|
||||
- Host-side smoke validation is aggregated by
|
||||
`tests/host/verify_host_smokes.sh` so Node, WASM, OPFS, and browser checks
|
||||
run from one command.
|
||||
|
||||
@@ -83,7 +83,8 @@ Current validation is intentionally mechanical:
|
||||
`runtime/opfs/file-service.js` adapter. `runtime/opfs/path-model.js` now
|
||||
defines paths for INI, tool table, parameter file, G-code program,
|
||||
preview-cache, and session-snapshot targets. `runtime/opfs/snapshot-store.js`
|
||||
adds a generic JSON session snapshot envelope.
|
||||
adds a generic JSON session snapshot envelope and validates its format,
|
||||
version, session id, metadata, and payload shape.
|
||||
`runtime/opfs/machine-file-store.js` adds pure-text storage for INI, tool
|
||||
table, parameter file, and G-code program content.
|
||||
`runtime/opfs/linuxcnc-parameter-bridge.js` copies OPFS-backed parameter
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<script type="module">
|
||||
import { createLinuxCncIniSdk } from "../../runtime/sdk/src/index.js";
|
||||
import { loadTextFile, saveTextFile } from "../../runtime/opfs/file-service.js";
|
||||
import { machineIniPath } from "../../runtime/opfs/path-model.js";
|
||||
import { machineIniPath, sessionSnapshotPath } from "../../runtime/opfs/path-model.js";
|
||||
import {
|
||||
loadSessionSnapshot,
|
||||
saveSessionSnapshot,
|
||||
@@ -29,6 +29,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function assertRejects(label, operation, expectedPattern) {
|
||||
try {
|
||||
await operation();
|
||||
} catch (error) {
|
||||
if (!expectedPattern.test(error.message)) {
|
||||
throw new Error(`${label}: unexpected error ${error.message}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new Error(`${label}: expected rejection`);
|
||||
}
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
@@ -104,6 +116,44 @@ JOINTS = 3
|
||||
assertEqual(loadedSnapshot.createdAt, savedSnapshot.createdAt, "snapshot timestamp");
|
||||
assertEqual(loadedSnapshot.payload.files.ini, opfsPath, "snapshot payload");
|
||||
assertEqual(loadedSnapshot.metadata.source, "browser-smoke", "snapshot metadata");
|
||||
await saveTextFile(
|
||||
sessionSnapshotPath("browser-bad-format"),
|
||||
JSON.stringify({
|
||||
...loadedSnapshot,
|
||||
format: "other-format",
|
||||
sessionId: "browser-bad-format",
|
||||
}),
|
||||
);
|
||||
await assertRejects(
|
||||
"browser snapshot bad format",
|
||||
() => loadSessionSnapshot("browser-bad-format"),
|
||||
/Unsupported session snapshot format/,
|
||||
);
|
||||
await saveTextFile(
|
||||
sessionSnapshotPath("browser-bad-version"),
|
||||
JSON.stringify({
|
||||
...loadedSnapshot,
|
||||
version: 99,
|
||||
sessionId: "browser-bad-version",
|
||||
}),
|
||||
);
|
||||
await assertRejects(
|
||||
"browser snapshot bad version",
|
||||
() => loadSessionSnapshot("browser-bad-version"),
|
||||
/Unsupported session snapshot version/,
|
||||
);
|
||||
await saveTextFile(
|
||||
sessionSnapshotPath("browser-bad-session-id"),
|
||||
JSON.stringify({
|
||||
...loadedSnapshot,
|
||||
sessionId: "other-browser-session",
|
||||
}),
|
||||
);
|
||||
await assertRejects(
|
||||
"browser snapshot id mismatch",
|
||||
() => loadSessionSnapshot("browser-bad-session-id"),
|
||||
/Session snapshot id mismatch/,
|
||||
);
|
||||
|
||||
await saveMachineTextFiles("browser-smoke", {
|
||||
ini: iniText,
|
||||
|
||||
@@ -130,6 +130,26 @@ assert.deepEqual(snapshot, {
|
||||
payload: snapshotPayload,
|
||||
});
|
||||
assert.equal(validateSessionSnapshot(snapshot, "session-1"), snapshot);
|
||||
assert.throws(
|
||||
() => validateSessionSnapshot({ ...snapshot, format: "other-format" }, "session-1"),
|
||||
/Unsupported session snapshot format/,
|
||||
);
|
||||
assert.throws(
|
||||
() => validateSessionSnapshot({ ...snapshot, version: 99 }, "session-1"),
|
||||
/Unsupported session snapshot version/,
|
||||
);
|
||||
assert.throws(
|
||||
() => validateSessionSnapshot({ ...snapshot, sessionId: "other-session" }, "session-1"),
|
||||
/Session snapshot id mismatch/,
|
||||
);
|
||||
assert.throws(
|
||||
() => validateSessionSnapshot({ ...snapshot, metadata: null }, "session-1"),
|
||||
/snapshot metadata must be a plain object/,
|
||||
);
|
||||
assert.throws(
|
||||
() => validateSessionSnapshot({ ...snapshot, payload: [] }, "session-1"),
|
||||
/snapshot payload must be a plain object/,
|
||||
);
|
||||
|
||||
await saveTextFile(
|
||||
"linuxcnc/machines/xyzab.ini",
|
||||
@@ -558,6 +578,33 @@ await assert.rejects(
|
||||
() => loadSessionSnapshot("bad-json", { storage }),
|
||||
/Invalid session snapshot JSON/,
|
||||
);
|
||||
await saveTextFile(
|
||||
sessionSnapshotPath("bad-format"),
|
||||
JSON.stringify({ ...snapshot, sessionId: "bad-format", format: "other-format" }),
|
||||
storage,
|
||||
);
|
||||
await assert.rejects(
|
||||
() => loadSessionSnapshot("bad-format", { storage }),
|
||||
/Unsupported session snapshot format/,
|
||||
);
|
||||
await saveTextFile(
|
||||
sessionSnapshotPath("bad-version"),
|
||||
JSON.stringify({ ...snapshot, sessionId: "bad-version", version: 99 }),
|
||||
storage,
|
||||
);
|
||||
await assert.rejects(
|
||||
() => loadSessionSnapshot("bad-version", { storage }),
|
||||
/Unsupported session snapshot version/,
|
||||
);
|
||||
await saveTextFile(
|
||||
sessionSnapshotPath("bad-session-id"),
|
||||
JSON.stringify({ ...snapshot, sessionId: "other-session" }),
|
||||
storage,
|
||||
);
|
||||
await assert.rejects(
|
||||
() => loadSessionSnapshot("bad-session-id", { storage }),
|
||||
/Session snapshot id mismatch/,
|
||||
);
|
||||
await assert.rejects(
|
||||
() => loadSessionSnapshot("missing-session", { storage }),
|
||||
/missing directory|missing file/,
|
||||
|
||||
Reference in New Issue
Block a user