Files
FreeCADWasmDev/tools/run_p6_jtreader_action03_recovery_smoke.mjs
wangdequan 9a7c4f0335 Save FreeCAD Web workspace sources and user validation evidence
IFC native binding remains incomplete; preserve accurate test results.
2026-09-15 22:01:58 +08:00

102 lines
4.5 KiB
JavaScript

#!/usr/bin/env node
import assert from "node:assert/strict";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { createRequire } from "node:module";
import { pathToFileURL } from "node:url";
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
const build = path.resolve(process.argv[2] ?? path.join(root, "freecad-source/build-web/configure/bin"));
globalThis.__dirname = `${build}${path.sep}`;
globalThis.require = createRequire(import.meta.url);
const loader = await import(pathToFileURL(path.join(build, "FreeCADWebJtReaderRuntimeProbe.js")));
const kernel = await loader.default({
wasmBinary: fs.readFileSync(path.join(build, "FreeCADWebJtReaderRuntimeProbe.wasm")),
});
const call = (name, type = "number") => kernel.ccall(name, type);
const sha256 = (value) => crypto.createHash("sha256").update(value).digest("hex");
const run = () => {
const result = call("fc_web_jtreader_save_reopen_recovery");
const state = {
before: call("fc_web_jtreader_recovery_state_before", "string"),
afterReject: call("fc_web_jtreader_recovery_state_after_reject", "string"),
afterRecovery: call("fc_web_jtreader_recovery_state_after_recovery", "string"),
};
return {
run: result,
invalid: {
return: call("fc_web_jtreader_recovery_invalid_return"),
path: call("fc_web_jtreader_recovery_invalid_path", "string"),
code: call("fc_web_jtreader_recovery_error_code", "string"),
message: call("fc_web_jtreader_recovery_invalid_diagnostic", "string"),
},
state,
unchangedAfterReject: call("fc_web_jtreader_recovery_unchanged_after_reject"),
replayEqual: call("fc_web_jtreader_recovery_replay_equal"),
documentCountAfterClose: call("fc_web_jtreader_recovery_document_count_after_close"),
};
};
const first = run();
const second = run();
assert.equal(first.run, 1);
assert.equal(first.invalid.return, 0);
assert.equal(first.invalid.code, "missing_resource");
assert.match(first.invalid.message, /Unable to open project file/);
assert.match(first.invalid.message, new RegExp(first.invalid.path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
assert.equal(first.unchangedAfterReject, 1);
assert.equal(first.replayEqual, 1);
assert.equal(first.documentCountAfterClose, 0);
assert.equal(first.state.before, first.state.afterReject);
assert.equal(first.state.before, first.state.afterRecovery);
assert.deepEqual(second, first);
const report = {
schema: "freecad-web-p6-jtreader-action-03-recovery/v1",
taskId: "FW-P6-JTR-ACT-03-D",
module: "JtReader",
action: "save/reopen",
result: "pass",
invalidInput: {
kind: "missing_resource",
path: first.invalid.path,
inputSha256: sha256(JSON.stringify({ kind: "missing_resource", path: first.invalid.path })),
},
baseline: first.state.before,
rejected: first.invalid,
recovered: first.state.afterRecovery,
recovery: {
unchangedAfterReject: first.unchangedAfterReject === 1,
repeatedErrorStable: first.replayEqual === 1,
repeatedRunStable: JSON.stringify(first) === JSON.stringify(second),
resourcesReleased: first.documentCountAfterClose === 0,
},
state: {
beforeSha256: sha256(first.state.before),
afterRejectSha256: sha256(first.state.afterReject),
afterRecoverySha256: sha256(first.state.afterRecovery),
unchanged: first.state.before === first.state.afterReject,
recovered: first.state.before === first.state.afterRecovery,
},
commands: [
"cmake --build freecad-source/build-web/configure --target FreeCADWebJtReaderRuntimeProbe -j 8",
"node tools/run_p6_jtreader_action03_recovery_smoke.mjs freecad-source/build-web/configure/bin",
],
artifacts: {
kernel: "docs/p6/jtreader-action-03-kernel.json",
wasm: "freecad-source/build-web/configure/bin/FreeCADWebJtReaderRuntimeProbe.wasm",
workerLog: "docs/freecad-p6-jtreader-action-03-d-recovery.log",
},
boundaries: [
"Only missing FCStd resource recovery is covered; no other JtReader actions or cross-version migration are included.",
],
};
fs.writeFileSync(path.join(root, "docs/p6/jtreader-action-03-recovery.json"), `${JSON.stringify(report, null, 2)}\n`);
fs.writeFileSync(
path.join(root, "docs/freecad-p6-jtreader-action-03-d-recovery.log"),
`${JSON.stringify({ result: report.result, invalidCode: first.invalid.code, unchangedAfterReject: report.recovery.unchangedAfterReject, repeatedErrorStable: report.recovery.repeatedErrorStable })}\n`,
);
console.log(JSON.stringify({ result: report.result, invalidCode: first.invalid.code, unchangedAfterReject: report.recovery.unchangedAfterReject }));