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

105 lines
3.8 KiB
JavaScript

#!/usr/bin/env node
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { Worker } from "node:worker_threads";
import { fileURLToPath, pathToFileURL } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const buildDirectory = path.resolve(process.argv[2] || path.join(root, "freecad-source/build-web/configure/bin"));
const compileDirectory = path.resolve(process.argv[3] || "/tmp/freecad-p6-openscad-facade");
const workerPath = path.join(root, "tools/openscad-facade-smoke-worker.mjs");
const trace = [];
function receive(worker) {
return new Promise((resolve, reject) => {
const onMessage = (message) => { worker.off("error", reject); resolve(message); };
worker.once("message", onMessage);
worker.once("error", reject);
});
}
function createWorker() {
return new Worker(workerPath, {
workerData: {
buildDirectory,
facadePath: pathToFileURL(path.join(compileDirectory, "openscad-inspect-facade.js")).href,
envelopePath: pathToFileURL(path.join(compileDirectory, "facade-envelope.js")).href,
},
});
}
const worker = createWorker();
const ready = await receive(worker);
trace.push({ direction: "worker->host", message: ready });
const facade = await import(pathToFileURL(path.join(compileDirectory, "openscad-inspect-facade.js")));
const envelope = await import(pathToFileURL(path.join(compileDirectory, "facade-envelope.js")));
const successRequest = facade.createOpenScadInspectRequest("openscad-success-1");
worker.postMessage(successRequest);
const success = await receive(worker);
trace.push({ direction: "worker->host", message: success });
const errorRequest = facade.createOpenScadInspectRequest("openscad-error-1", {
...facade.OPENSCAD_INSPECT_FIXTURE,
sourceRevision: "wrong-revision",
});
worker.postMessage(errorRequest);
const expectedError = await receive(worker);
trace.push({ direction: "worker->host", message: expectedError });
worker.postMessage(successRequest);
const duplicate = await receive(worker);
trace.push({ direction: "worker->host", message: duplicate });
const cancelRequest = facade.createOpenScadInspectRequest("openscad-cancel-1");
const cancelResponse = new Promise((resolve, reject) => {
const onMessage = (message) => {
if (message.requestId === cancelRequest.requestId) {
worker.off("error", reject);
resolve(message);
}
};
worker.on("message", onMessage);
worker.once("error", reject);
});
worker.postMessage(cancelRequest);
worker.postMessage(envelope.createCancel("openscad-cancel-control", cancelRequest.requestId));
const cancelled = await cancelResponse;
trace.push({ direction: "worker->host", message: cancelled });
await worker.terminate();
const result = {
schema: "freecad-web-openscad-facade-smoke/v1",
envelopeSchema: envelope.FACADE_SCHEMA,
success,
expectedError,
duplicate,
cancelled,
trace,
};
result.traceSha256 = crypto.createHash("sha256").update(JSON.stringify(trace)).digest("hex");
const valid = result.envelopeSchema === "freecad-web-facade/v1"
&& ready.kind === "ready"
&& success.kind === "result"
&& success.requestId === "openscad-success-1"
&& success.result.module === "OpenSCAD"
&& success.result.action === "inspect/source-inventory"
&& success.result.readOnly === true
&& success.result.resourcesReleased === true
&& expectedError.kind === "error"
&& expectedError.error.code === "revision_mismatch"
&& duplicate.kind === "error"
&& duplicate.error.code === "duplicate_request"
&& cancelled.kind === "error"
&& cancelled.error.code === "cancelled"
&& result.traceSha256.length === 64;
if (!valid) throw new Error(JSON.stringify(result));
const outputPath = process.env.P6_FACADE_OUTPUT;
if (outputPath) fs.writeFileSync(outputPath, `${JSON.stringify(result, null, 2)}\n`);
console.log(JSON.stringify(result));