66 lines
4.9 KiB
JavaScript
66 lines
4.9 KiB
JavaScript
#!/usr/bin/env node
|
|
import assert from "node:assert/strict";
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { execFileSync } from "node:child_process";
|
|
import { Worker } from "node:worker_threads";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
const build = path.resolve(process.argv[2] ?? path.join(root, "freecad-source/build-web/configure/bin"));
|
|
const out = fs.mkdtempSync(path.join(os.tmpdir(), "freecad-p6-reverseengineering-family-facade-"));
|
|
execFileSync(path.join(root, "web/node_modules/.bin/tsc"), ["--target", "ES2022", "--module", "ESNext", "--moduleResolution", "Bundler", "--strict", "--skipLibCheck", "--outDir", out, "--declaration", "false", "--noEmit", "false", "web/src/facade-envelope.ts", "web/src/reverseengineering-python-family-facade.ts"], { cwd: root, stdio: "inherit" });
|
|
const facade = await import(pathToFileURL(path.join(out, "reverseengineering-python-family-facade.js")));
|
|
const envelope = await import(pathToFileURL(path.join(out, "facade-envelope.js")));
|
|
const worker = new Worker(path.join(root, "tools/reverseengineering-python-family-facade-smoke-worker.mjs"), { workerData: { buildDirectory: build, facadePath: pathToFileURL(path.join(out, "reverseengineering-python-family-facade.js")).href, envelopePath: pathToFileURL(path.join(out, "facade-envelope.js")).href } });
|
|
const receive = () => new Promise((resolve, reject) => { const onMessage = (value) => { worker.off("error", reject); resolve(value); }; worker.once("message", onMessage); worker.once("error", reject); });
|
|
const ready = await receive();
|
|
const records = [{ apiId: "py:ReverseEngineering:class:ReverseEngineeringWorkbench", name: "ReverseEngineeringWorkbench", family: "generic-object" }];
|
|
const successRequest = facade.createReverseEngineeringPythonFamilyRequest("rev-family-success-1", records);
|
|
worker.postMessage(successRequest);
|
|
const success = await receive();
|
|
worker.postMessage(successRequest);
|
|
const duplicate = await receive();
|
|
const cancelRequest = facade.createReverseEngineeringPythonFamilyRequest("rev-family-cancel-1", records);
|
|
const cancelledPromise = new Promise((resolve, reject) => { const onMessage = (value) => { if (value.requestId === cancelRequest.requestId) { worker.off("error", reject); resolve(value); } }; worker.on("message", onMessage); worker.once("error", reject); });
|
|
worker.postMessage(cancelRequest);
|
|
worker.postMessage(envelope.createCancel("rev-family-cancel-control", cancelRequest.requestId, "reverseengineering-python-family"));
|
|
const cancelled = await cancelledPromise;
|
|
const invalidRequest = facade.createReverseEngineeringPythonFamilyRequest("rev-family-invalid-1", [{ ...records[0], apiId: "py:BIM:class:ReverseEngineeringWorkbench" }]);
|
|
worker.postMessage(invalidRequest);
|
|
const invalid = await receive();
|
|
await worker.terminate();
|
|
|
|
assert.equal(ready.kind, "ready");
|
|
assert.equal(success.kind, "result");
|
|
assert.equal(success.result.records.length, 1);
|
|
assert.equal(success.result.records[0].status, "restricted");
|
|
assert.equal(success.result.records[0].code, "gui_dependency_unavailable");
|
|
assert.equal(success.result.resourcesReleased, true);
|
|
assert.equal(duplicate.kind, "error");
|
|
assert.equal(duplicate.error.code, "duplicate_request");
|
|
assert.equal(cancelled.kind, "error");
|
|
assert.equal(cancelled.error.code, "cancelled");
|
|
assert.equal(invalid.kind, "result");
|
|
assert.equal(invalid.result.records[0].status, "not_implemented");
|
|
const trace = { ready, success, duplicate, cancelled, invalid };
|
|
const report = {
|
|
schema: "freecad-web-p6-reverseengineering-tier1-readonly-facade/v1",
|
|
taskId: "FW-P6-FPA-F1-REVERSEENGINEERING",
|
|
module: "ReverseEngineering",
|
|
command: facade.REVERSEENGINEERING_PYTHON_FAMILY_COMMAND,
|
|
result: "pass",
|
|
envelopeSchema: envelope.FACADE_SCHEMA,
|
|
typedSchema: facade.REVERSEENGINEERING_PYTHON_FAMILY_SCHEMA,
|
|
trace,
|
|
traceSha256: crypto.createHash("sha256").update(JSON.stringify(trace)).digest("hex"),
|
|
sequencing: { requestCount: 4, responseCount: 5, maxActive: 1, cancelAccepted: true },
|
|
schemaChecks: { noNativePointers: !JSON.stringify(trace).match(/pointer/i), nativeSource: trace.success.result.source === "freecad-source", resourcesReleased: trace.success.result.resourcesReleased },
|
|
artifacts: { native: "docs/p6/reverseengineering-tier1-readonly-family.json", worker: "web/src/reverseengineering-python.worker.ts", facade: "web/src/reverseengineering-python-family-facade.ts" },
|
|
};
|
|
fs.writeFileSync(path.join(root, "docs/p6/reverseengineering-tier1-readonly-facade.json"), `${JSON.stringify(report, null, 2)}\n`);
|
|
fs.writeFileSync(path.join(root, "docs/freecad-p6-reverseengineering-tier1-readonly-facade.log"), `${JSON.stringify({ result: report.result, traceSha256: report.traceSha256, cancel: cancelled.error.code })}\n`);
|
|
console.log(JSON.stringify({ result: report.result, traceSha256: report.traceSha256, cancel: cancelled.error.code }));
|