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

90 lines
4.5 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, "FreeCADWebReverseEngineeringRuntimeProbe.js")));
const kernel = await loader.default({
wasmBinary: fs.readFileSync(path.join(build, "FreeCADWebReverseEngineeringRuntimeProbe.wasm")),
print: () => {},
printErr: () => {}
});
const call = (name, returnType = "number", argTypes = [], args = []) => kernel.ccall(name, returnType, argTypes, args);
const run = () => ({
initialize: call("fc_web_reverseengineering_initialize"),
initializationCalls: call("fc_web_reverseengineering_initialization_calls"),
initializationRuns: call("fc_web_reverseengineering_initialization_runs"),
moduleAvailable: call("fc_web_reverseengineering_module_available"),
error: call("fc_web_reverseengineering_error", "string")
});
const first = run();
const repeated = run();
const sourceEntry = "src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp";
const apiValidation = call("fc_web_reverseengineering_python_api_validate", "number", ["string"], [sourceEntry]);
const apiExecution = call("fc_web_reverseengineering_python_api");
const second = run();
const invalidSource = call(
"fc_web_reverseengineering_python_api_validate",
"number",
["string"],
["src/Mod/ReverseEngineering/App/AppReverseEngineering.hxx"]
);
const invalidError = call("fc_web_reverseengineering_error", "string");
const semantic = value => ({
initialize: value.initialize,
initializationRuns: value.initializationRuns,
moduleAvailable: value.moduleAvailable,
error: value.error
});
const result = {
first,
repeated,
second,
apiValidation,
apiExecution,
apiNames: call("fc_web_reverseengineering_api_names", "string"),
apiCount: call("fc_web_reverseengineering_api_count"),
curveValid: call("fc_web_reverseengineering_curve_valid"),
invalidSource,
invalidError,
deterministic: JSON.stringify(semantic(first)) === JSON.stringify(semantic(second)),
pass: first.initialize === 1 && repeated.initialize === 1 && second.initialize === 1 &&
first.initializationRuns === 1 && repeated.initializationRuns === 1 && second.initializationRuns === 1 &&
repeated.initializationCalls === 2 && first.moduleAvailable === 1 && apiValidation === 1 &&
apiExecution === 1 && resultApiCountPlaceholder() && invalidSource === 0 &&
invalidError === "revision_mismatch"
};
function resultApiCountPlaceholder() {
return call("fc_web_reverseengineering_api_count") === 2 && call("fc_web_reverseengineering_curve_valid") === 1;
}
const wasmPath = path.join(build, "FreeCADWebReverseEngineeringRuntimeProbe.wasm");
const fixture = { module: "ReverseEngineering", sourceEntry, api: ["approxCurve", "approxSurface"] };
const hash = value => crypto.createHash("sha256").update(value).digest("hex");
const report = {
schema: "freecad-web-p6-reverseengineering-runtime/v1",
task_id: "FW-P6-REV-B-R1",
module: "ReverseEngineering",
status: result.pass && result.deterministic ? "pass" : "fail",
source_revision: "working-tree",
fixture: { ...fixture, input_sha256: hash(JSON.stringify(fixture)) },
result,
result_sha256: hash(JSON.stringify(result)),
artifacts: { wasm: { path: "freecad-source/build-web/configure/bin/FreeCADWebReverseEngineeringRuntimeProbe.wasm", sha256: hash(fs.readFileSync(wasmPath)) } },
boundaries: ["The Web target enables ReverseEngineering App only; ReverseEngineeringGui and PCL-only APIs remain outside this slice.", "The native probe registers Part and Mesh dependencies before the official ReverseEngineering Python module."]
};
fs.mkdirSync(docs, { recursive: true });
fs.writeFileSync(path.join(docs, "reverseengineering-runtime.json"), `${JSON.stringify(report, null, 2)}\n`);
fs.writeFileSync(path.join(root, "docs/freecad-p6-reverseengineering-b-runtime.log"), `${JSON.stringify({ status: report.status, initializationRuns: second.initializationRuns, apiCount: result.apiCount, invalidError })}\n`);
console.log(JSON.stringify({ status: report.status, initializationRuns: second.initializationRuns, apiCount: result.apiCount, apiExecution: result.apiExecution, invalidError }));
if (report.status !== "pass") process.exitCode = 1;