38 lines
5.5 KiB
JavaScript
38 lines
5.5 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 { execFileSync } from "node:child_process";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const root = "/home/mes123456/FreeCADWasmDev/working/FreeCAD";
|
|
const build = process.argv[2] ?? path.join(root, "freecad-source/build-web/configure/bin");
|
|
const batch = JSON.parse(fs.readFileSync(path.join(root, "docs/current/module-batch-manifest.json"), "utf8"));
|
|
if (batch.status !== "ready" || batch.selected?.module !== "Sketcher" || batch.selected?.tier !== "tier-1-readonly" || batch.selected?.family !== "geometry-value" || batch.records.length !== 3) throw Error("unexpected Sketcher geometry-value batch");
|
|
const records = batch.records.map(([apiId, name, disposition, sourcePath]) => ({ apiId, name, family: "geometry-value", sourcePath, disposition }));
|
|
const out = fs.mkdtempSync("/tmp/freecad-sketcher-geometry-value-");
|
|
execFileSync(path.join(root, "web/node_modules/.bin/tsc"), ["--target", "ES2022", "--module", "ESNext", "--moduleResolution", "Bundler", "--strict", "--skipLibCheck", "--outDir", out, "--declaration", "false", "--noEmit", "false", path.join(root, "web/src/facade-envelope.ts"), path.join(root, "web/src/sketcher-python-family-facade.ts")], { cwd: root, stdio: "inherit" });
|
|
const facade = await import(pathToFileURL(path.join(out, "sketcher-python-family-facade.js")));
|
|
const envelope = await import(pathToFileURL(path.join(out, "facade-envelope.js")));
|
|
const worker = new Worker(path.join(root, "tools/sketcher-python-family-facade-smoke-worker.mjs"), { workerData: { buildDirectory: build, facadePath: pathToFileURL(path.join(out, "sketcher-python-family-facade.js")).href, envelopePath: pathToFileURL(path.join(out, "facade-envelope.js")).href } });
|
|
const next = () => new Promise((resolve, reject) => { worker.once("message", resolve); worker.once("error", reject); });
|
|
const ready = await next();
|
|
const request = facade.createSketcherPythonFamilyRequest("sketcher-geometry-value-success", records);
|
|
worker.postMessage(request); const success = await next();
|
|
worker.postMessage(facade.createSketcherPythonFamilyRequest("sketcher-geometry-value-repeat", records)); const repeat = await next();
|
|
worker.postMessage(facade.createSketcherPythonFamilyRequest("sketcher-geometry-value-cross", [{ ...records[0], apiId: "py:BIM:method:SketchObject.getPoint" }])); const cross = await next();
|
|
worker.postMessage({ ...facade.createSketcherPythonFamilyRequest("sketcher-geometry-value-invalid", records), payload: { ...request.payload, tier: "tier-unsupported" } }); const malformed = await next();
|
|
const cancelRequest = facade.createSketcherPythonFamilyRequest("sketcher-family-cancel-1", records); worker.postMessage(cancelRequest); worker.postMessage(envelope.createCancel("geometry-value-cancel", cancelRequest.requestId, facade.SKETCHER_PYTHON_FAMILY_COMMAND)); const cancelled = await next();
|
|
worker.postMessage({ kind: "reset", requestId: "geometry-value-reset" }); const reset = await next(); await worker.terminate();
|
|
console.log(JSON.stringify({ready, success, repeat, malformed, cancelled, reset}));
|
|
if (ready.kind !== "ready" || success.kind !== "result" || repeat.kind !== "result" || malformed.kind !== "error" || cancelled.kind !== "error" || reset.requestId !== "geometry-value-reset") throw Error("Sketcher geometry-value sequencing failed");
|
|
if (success.result.count !== 3 || success.result.resourcesReleased !== true || success.result.records.some(r => r.status !== "exposed" || r.code !== "native_method_fixture" || r.native !== true || r.resourcesReleased !== true)) throw Error("unexpected native geometry-value result");
|
|
if (JSON.stringify(success.result) !== JSON.stringify(repeat.result) || (cross.kind !== "error" && cross.result.records[0].code !== "unmatched_source_record") || cancelled.error.code !== "cancelled") throw Error("Sketcher geometry-value boundary failed");
|
|
const hash = v => crypto.createHash("sha256").update(JSON.stringify(v)).digest("hex");
|
|
const fileHash = f => crypto.createHash("sha256").update(fs.readFileSync(f)).digest("hex");
|
|
const evidence = { schema: "freecad-web-sketcher-geometry-value-module-batch-runtime/v1", taskId: "FW-P6-FPA-Y", batchId: batch.batchId, module: "Sketcher", tier: "tier-1-readonly", family: "geometry-value", status: "pass_with_boundaries", sourceRevision: success.result.records[0].sourceRevision, route: { command: "sketcher.pythonFamilyBatch", native: "freecad-source/src/WebAssembly/FreeCADCoreProbe/SketcherProbe.cpp:fc_web_dispatch_json", facade: "web/src/sketcher-python-family-facade.ts", worker: "web/src/sketcher-python-family-facade-smoke-worker.mjs" }, input: request, inputSha256: hash(request), result: success.result, resultSha256: hash(success.result), replay: { equal: true, resultSha256: hash(repeat.result) }, boundaries: { crossModule: cross, malformed, cancelled, reset }, resources: { resourcesReleased: true, documentMutation: false }, artifacts: { module: "Sketcher", revision: success.result.records[0].sourceRevision, runtimeUrl: "/kernel/FreeCADWebSketcherProbe.js", wasmUrl: "/kernel/FreeCADWebSketcherProbe.wasm", dataUrl: null, assetBaseUrl: "/kernel/", wasmSha256: fileHash(path.join(root, "web/public/kernel/FreeCADWebSketcherProbe.wasm")) } };
|
|
const evidencePath = path.join(root, `docs/p6/sketcher-geometry-value-module-batch-${batch.batchId}-runtime.json`);
|
|
fs.writeFileSync(evidencePath, JSON.stringify(evidence, null, 2) + "\n");
|
|
console.log(JSON.stringify({ status: evidence.status, batchId: batch.batchId, count: 3, resultSha256: evidence.resultSha256 }));
|