#!/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-python-facade"); const workerPath = path.join(root, "tools/openscad-python-facade-smoke-worker.mjs"); 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); }); } const worker = new Worker(workerPath, { workerData: { buildDirectory, facadePath: pathToFileURL(path.join(compileDirectory, "openscad-python-facade.js")).href, envelopePath: pathToFileURL(path.join(compileDirectory, "facade-envelope.js")).href, }, }); const facade = await import(pathToFileURL(path.join(compileDirectory, "openscad-python-facade.js"))); const envelope = await import(pathToFileURL(path.join(compileDirectory, "facade-envelope.js"))); const ready = await receive(worker); const successRequest = facade.createOpenScadPythonRequest("openscad-python-success-1"); worker.postMessage(successRequest); const success = await receive(worker); const errorRequest = facade.createOpenScadPythonRequest("openscad-python-error-1", { ...facade.OPENSCAD_PYTHON_FIXTURE, sourceEntry: "src/Mod/OpenSCAD/Missing.py", }); worker.postMessage(errorRequest); const expectedError = await receive(worker); worker.postMessage(successRequest); const duplicate = await receive(worker); const cancelRequest = facade.createOpenScadPythonRequest("openscad-python-cancel-1"); const cancelResult = 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-python-cancel-control", cancelRequest.requestId)); const cancelled = await cancelResult; await worker.terminate(); const trace = [ready, success, expectedError, duplicate, cancelled]; const result = { schema: "freecad-web-openscad-python-facade-smoke/v1", envelopeSchema: envelope.FACADE_SCHEMA, ready, success, expectedError, duplicate, cancelled, traceSha256: crypto.createHash("sha256").update(JSON.stringify(trace)).digest("hex"), }; const valid = ready.kind === "ready" && result.envelopeSchema === "freecad-web-facade/v1" && success.kind === "result" && success.result.action === "python-api" && success.result.apiCount === 11 && 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"; 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));