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

29 lines
3.8 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 build = path.resolve(process.argv[2] ?? path.join(root, "freecad-source/build-web/configure/bin"));
const docs = path.join(root, "docs/p6");
globalThis.__dirname = `${build}${path.sep}`;
globalThis.require = createRequire(import.meta.url);
const loader = await import(pathToFileURL(path.join(build, "FreeCADWebPlotRuntimeProbe.js")));
const kernel = await loader.default({ wasmBinary: fs.readFileSync(path.join(build, "FreeCADWebPlotRuntimeProbe.wasm")), print: () => {}, printErr: () => {} });
const call = (name, type = "number", argTypes = [], args = []) => kernel.ccall(name, type, argTypes, args);
const run = () => ({ run: call("fc_web_plot_python_api"), apiCount: call("fc_web_plot_api_count"), seriesCount: call("fc_web_plot_series_count"), svgSize: call("fc_web_plot_svg_size"), svgValid: call("fc_web_plot_svg_valid"), resourcesReleased: call("fc_web_plot_resources_released"), error: call("fc_web_plot_api_error", "string") });
const first = run();
const second = run();
const invalid = call("fc_web_plot_python_api_validate", "number", ["string"], ["src/Mod/Plot/Missing.py"]);
const invalidError = call("fc_web_plot_api_error", "string");
const semantic = value => ({ run: value.run, apiCount: value.apiCount, seriesCount: value.seriesCount, svgPositive: value.svgSize > 0, svgValid: value.svgValid, resourcesReleased: value.resourcesReleased, error: value.error });
const result = { first, second, semanticDeterministic: JSON.stringify(semantic(first)) === JSON.stringify(semantic(second)), invalid, invalidError, pass: first.run === 1 && second.run === 1 && first.apiCount === 15 && first.seriesCount === 1 && first.svgSize > 0 && first.svgValid === 1 && first.resourcesReleased === 1 && invalid === 0 && invalidError === "revision_mismatch" };
const fixture = { module: "Plot", action: "python-api", sourceEntry: "src/Mod/Plot/Plot.py", series: { x: [0, 1, 2], y: [1, 3, 2], name: "fixture" }, output: "/tmp/PlotWeb.svg" };
const hash = value => crypto.createHash("sha256").update(value).digest("hex");
const wasmPath = path.join(build, "FreeCADWebPlotRuntimeProbe.wasm");
const report = { schema: "freecad-web-p6-plot-action-02-kernel/v1", taskId: "FW-P6-PLT-ACT-02-C", module: "Plot", action: "python-api", result: result.pass && result.semanticDeterministic ? "pass" : "fail", sourceRevision: "0a2e7ce7f52ba71d54c62708c9ac5c76ca142231", fixture: { ...fixture, inputSha256: hash(JSON.stringify(fixture)) }, details: result, resultSha256: hash(JSON.stringify(result)), artifacts: { wasm: { path: "freecad-source/build-web/configure/bin/FreeCADWebPlotRuntimeProbe.wasm", sha256: hash(fs.readFileSync(wasmPath)) }, svg: { path: "/tmp/PlotWeb.svg", size: first.svgSize, valid: first.svgValid === 1 } }, commands: ["ninja -C freecad-source/build-web/configure FreeCADWebPlotRuntimeProbe -j8", "node tools/run_p6_plot_action02_kernel.mjs freecad-source/build-web/configure/bin"], boundaries: ["The native C++ probe loads and executes the official Plot.py source in the FreeCAD Web Python runtime.", "Plot has no document persistence; SVG output is the explicit save boundary."] };
fs.writeFileSync(path.join(docs, "plot-action-02-kernel.json"), `${JSON.stringify(report, null, 2)}\n`);
fs.writeFileSync(path.join(root, "docs/freecad-p6-plot-action-02-c-kernel.log"), `${JSON.stringify({ result: report.result, semanticDeterministic: result.semanticDeterministic, apiCount: first.apiCount, svgSize: first.svgSize, invalidError })}\n`);
console.log(JSON.stringify({ result: report.result, semanticDeterministic: result.semanticDeterministic, apiCount: first.apiCount, svgSize: first.svgSize, invalidError }));
if (report.result !== "pass") process.exitCode = 1;