Files
FreeCADWasmDev/tools/run_p6_show_runtime.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

31 lines
5.3 KiB
JavaScript

import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { createRequire } from "node:module";
import { execFileSync } from "node:child_process";
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"));
const wasmPath = path.join(build, "FreeCADWebShowRuntimeProbe.wasm");
const sourceFiles = ["src/Mod/Show/CMakeLists.txt", "src/Mod/Show/__init__.py", "src/Mod/Show/mTempoVis.py", "src/Mod/Show/TVStack.py", "src/Mod/Show/SceneDetail.py", "src/WebAssembly/FreeCADCoreProbe/ShowRuntimeProbe.cpp"];
const sourceSha256 = Object.fromEntries(sourceFiles.map(file => [file, crypto.createHash("sha256").update(fs.readFileSync(path.join(root, "freecad-source", file))).digest("hex")]));
const fixture = { module: "Show", sourceEntry: "src/Mod/Show/__init__.py", pythonApi: ["TempoVis", "DepGraphTools"], guiUp: false };
const inputSha256 = crypto.createHash("sha256").update(JSON.stringify({ fixture, sourceSha256 })).digest("hex");
globalThis.__dirname = `${build}${path.sep}`; globalThis.require = createRequire(import.meta.url);
const loader = await import(pathToFileURL(path.join(build, "FreeCADWebShowRuntimeProbe.js")));
const probe = await loader.default({ wasmBinary: fs.readFileSync(wasmPath), print: () => {}, printErr: () => {} });
const c = (name, type = "number", argTypes = [], args = []) => probe.ccall(name, type, argTypes, args);
const first = { initialize: c("fc_web_show_initialize"), calls: c("fc_web_show_initialization_calls"), runs: c("fc_web_show_initialization_runs"), available: c("fc_web_show_module_available"), error: c("fc_web_show_last_error", "string") };
const second = { initialize: c("fc_web_show_initialize"), calls: c("fc_web_show_initialization_calls"), runs: c("fc_web_show_initialization_runs"), available: c("fc_web_show_module_available"), error: c("fc_web_show_last_error", "string") };
const sourceValid = c("fc_web_show_source_inventory_validate", "number", ["string"], [fixture.sourceEntry]);
const sourceInvalid = { valid: c("fc_web_show_source_inventory_validate", "number", ["string"], ["src/Mod/Show/Missing.py"]), error: c("fc_web_show_last_error", "string") };
const apiValid = c("fc_web_show_python_api_validate", "number", ["string"], [fixture.sourceEntry]);
const api = { run: c("fc_web_show_python_api"), count: c("fc_web_show_python_api_count"), tempoState: c("fc_web_show_tempo_state"), resourcesReleased: c("fc_web_show_resources_released"), dependencyAvailable: c("fc_web_show_dependency_available"), error: c("fc_web_show_api_error", "string") };
const unknown = { run: c("fc_web_show_dependency_probe", "number", ["string"], ["Show::MissingType"]), error: c("fc_web_show_last_error", "string") };
const known = { run: c("fc_web_show_dependency_probe", "number", ["string"], ["TempoVis"]), available: c("fc_web_show_dependency_available"), error: c("fc_web_show_last_error", "string") };
const details = { first, second, sourceValid, sourceInvalid, apiValid, api, unknown, known, deterministic: first.runs === 1 && second.runs === 1 && first.available === 1 && second.available === 1 && api.run === 1 && api.count === 2 && api.resourcesReleased === 1 && unknown.run === 0 && unknown.error === "type_not_found" && known.run === 1 };
const report = { schema: "freecad-web-p6-show-runtime/v2", taskId: "FW-P6-SHW-B", module: "Show", result: details.deterministic ? "pass" : "fail", fixture: { ...fixture, inputSha256 }, sourceRevision: execFileSync("git", ["-C", path.join(root, "freecad-source"), "rev-parse", "HEAD"], { encoding: "utf8" }).trim(), sourceSha256, details, resultSha256: crypto.createHash("sha256").update(JSON.stringify(details)).digest("hex"), artifacts: { js: "freecad-source/build-web/configure/bin/FreeCADWebShowRuntimeProbe.js", wasm: { path: "freecad-source/build-web/configure/bin/FreeCADWebShowRuntimeProbe.wasm", sha256: crypto.createHash("sha256").update(fs.readFileSync(wasmPath)).digest("hex") }, log: "docs/freecad-p6-show-b-runtime.log" }, commands: ["cmake -S freecad-source -B freecad-source/build-web/configure -DFREECAD_WEB=ON -DFREECAD_WEB_ENABLE_SHOW=ON", "EM_CACHE=/tmp/freecad-p6-emcache ninja -C freecad-source/build-web/configure FreeCADWebShowRuntimeProbe -j8", "node tools/run_p6_show_runtime.mjs freecad-source/build-web/configure/bin"], boundaries: ["The probe embeds the official Show Python source closure and runs TempoVis/TVStack with FreeCAD.GuiUp=False; GUI-only Camera, ClipPlane, Pickability and Workbench paths remain excluded.", "No FreeCADGui, PySide or pivy dependency is linked into the Web probe."] };
fs.mkdirSync(docs, { recursive: true }); fs.writeFileSync(path.join(docs, "show-runtime.json"), `${JSON.stringify(report, null, 2)}\n`); fs.writeFileSync(path.join(root, "docs/freecad-p6-show-b-runtime.log"), `${JSON.stringify({ result: report.result, calls: second.calls, runs: second.runs, sourceValid, sourceInvalid: sourceInvalid.error, api: api.run, apiCount: api.count, unknown: unknown.error, resourcesReleased: api.resourcesReleased })}\n`); console.log(JSON.stringify({ result: report.result, calls: second.calls, runs: second.runs, api: api.run, unknown: unknown.error, resourcesReleased: api.resourcesReleased })); if (report.result !== "pass") process.exitCode = 1;