3 lines
4.1 KiB
JavaScript
3 lines
4.1 KiB
JavaScript
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 docs = path.join(root, "docs/p6"); 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, "FreeCADWebReverseEngineeringRuntimeProbe.js"))); const kernel = await loader.default({ wasmBinary: fs.readFileSync(path.join(build, "FreeCADWebReverseEngineeringRuntimeProbe.wasm")), print: () => {}, printErr: () => {} }); const c = (name, type = "number", argTypes = [], args = []) => kernel.ccall(name, type, argTypes, args); const validPath = "/tmp/ReverseEngineeringRecovery.FCStd"; const invalidPath = "/tmp/reverseengineering-missing-directory/Recovery.FCStd"; const snapshot = () => ({ run: c("fc_web_reverseengineering_save_reopen"), error: c("fc_web_reverseengineering_persistence_error", "string"), path: c("fc_web_reverseengineering_persistence_path", "string"), objectType: c("fc_web_reverseengineering_persistence_object_type", "string"), beforeLength: c("fc_web_reverseengineering_persistence_before_length"), afterLength: c("fc_web_reverseengineering_persistence_after_length"), size: c("fc_web_reverseengineering_persistence_size"), objectCount: c("fc_web_reverseengineering_persistence_object_count") }); c("fc_web_reverseengineering_persistence_set_path", "number", ["string"], [validPath]); const before = snapshot(); c("fc_web_reverseengineering_persistence_set_path", "number", ["string"], [invalidPath]); const rejected = snapshot(); c("fc_web_reverseengineering_persistence_set_path", "number", ["string"], [validPath]); const repeatedReject = snapshot(); const after = snapshot(); const hash = value => crypto.createHash("sha256").update(JSON.stringify(value)).digest("hex"); const beforeSemantic = { objectType: before.objectType, beforeLength: before.beforeLength, afterLength: before.afterLength, objectCount: before.objectCount, sizePositive: before.size > 0 }; const afterSemantic = { objectType: after.objectType, beforeLength: after.beforeLength, afterLength: after.afterLength, objectCount: after.objectCount, sizePositive: after.size > 0 }; const report = { schema: "freecad-web-p6-reverseengineering-action-04-recovery/v1", taskId: "FW-P6-REV-ACT-04-D", module: "ReverseEngineering", action: "save/reopen", result: before.run === 1 && rejected.run === 0 && repeatedReject.run === 0 && rejected.error.length > 0 && after.run === 1 && hash(beforeSemantic) === hash(afterSemantic) ? "pass" : "fail", invalidInput: { field: "path", value: invalidPath, inputSha256: hash(invalidPath) }, before, rejected, repeatedReject, after, recovery: { beforeSha256: hash(beforeSemantic), afterSha256: hash(afterSemantic), unchangedAfterReject: hash(beforeSemantic) === hash(afterSemantic), repeatedErrorStable: repeatedReject.error === rejected.error, resourcesReleased: after.objectCount === 1 }, commands: ["node tools/run_p6_reverseengineering_action04_recovery.mjs freecad-source/build-web/configure/bin"], artifacts: { kernel: "docs/p6/reverseengineering-action-04-kernel.json", workerLog: "docs/freecad-p6-reverseengineering-action-04-d-recovery.log" }, boundaries: ["Invalid output path is rejected by native Document::saveAs; valid FCStd round-trip remains usable afterward."] }; fs.writeFileSync(path.join(docs, "reverseengineering-action-04-recovery.json"), `${JSON.stringify(report, null, 2)}\n`); fs.writeFileSync(path.join(root, "docs/freecad-p6-reverseengineering-action-04-d-recovery.log"), `${JSON.stringify({ result: report.result, rejectedError: rejected.error, unchangedAfterReject: report.recovery.unchangedAfterReject, repeatedErrorStable: report.recovery.repeatedErrorStable })}\n`); console.log(JSON.stringify({ result: report.result, rejectedError: rejected.error, unchangedAfterReject: report.recovery.unchangedAfterReject })); if (report.result !== "pass") process.exitCode = 1;
|