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

33 lines
5.0 KiB
JavaScript

#!/usr/bin/env node
import assert from "node:assert/strict";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
const modulePath = process.argv[2];
if (!modulePath) throw new Error("compiled cam-inspect-facade module path is required");
const facade = await import(modulePath);
const envelope = await import(path.resolve(path.dirname(modulePath), "facade-envelope.js"));
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
const docsRoot = path.join(root, "docs");
const { CAM_INSPECT_SCHEMA, CAM_INSPECT_FIXTURE, createCamInspectRequest, handleCamInspect, isCamInspectRequest } = facade;
const { FacadeSerialQueue, createCancel, isFacadeResponse } = envelope;
const queue = new FacadeSerialQueue(); const trace = []; let active = 0; let maxActive = 0;
async function dispatch(request) {
trace.push({ direction: "request", requestId: request.requestId, command: request.command });
const response = await queue.dispatch(request, async (payload, signal) => { active += 1; maxActive = Math.max(maxActive, active); trace.push({ direction: "handler-start", requestId: request.requestId }); try { return handleCamInspect(payload, signal); } finally { active -= 1; trace.push({ direction: "handler-end", requestId: request.requestId }); } });
trace.push({ direction: "response", requestId: response.requestId, kind: response.kind, code: response.kind === "error" ? response.error.code : null }); return response;
}
const success = await dispatch(createCamInspectRequest("cam-action-03-success"));
const expectedError = await dispatch(createCamInspectRequest("cam-action-03-error", { ...CAM_INSPECT_FIXTURE, sourceRevision: "wrong-revision" }));
const duplicate = await dispatch(createCamInspectRequest("cam-action-03-success"));
const cancelRequest = createCamInspectRequest("cam-action-03-cancel"); const cancelPromise = dispatch(cancelRequest); trace.push({ direction: "cancel", cancelOf: cancelRequest.requestId }); const cancelAccepted = queue.cancel(createCancel("cam-action-03-cancel-message", cancelRequest.requestId, "cam-inspect-doc")); const cancelled = await cancelPromise;
const afterCancel = await dispatch(createCamInspectRequest("cam-action-03-after-cancel"));
assert.equal(isCamInspectRequest(createCamInspectRequest("schema-test")), true);
assert.equal(success.kind, "result"); assert.equal(success.result.schema, CAM_INSPECT_SCHEMA); assert.equal(success.result.readOnly, true);
assert.equal(expectedError.kind, "error"); assert.equal(expectedError.error.code, "revision_mismatch"); assert.equal(duplicate.kind, "error"); assert.equal(duplicate.error.code, "duplicate_request"); assert.equal(cancelAccepted, true); assert.equal(cancelled.kind, "error"); assert.equal(cancelled.error.code, "cancelled"); assert.equal(afterCancel.kind, "result"); assert.equal(afterCancel.result.stateSha256, success.result.stateSha256); assert.equal(maxActive, 1); assert.equal(active, 0);
for (const response of [success, expectedError, duplicate, cancelled, afterCancel]) assert.equal(isFacadeResponse(response), true);
const schema = JSON.parse(fs.readFileSync(path.join(docsRoot, "p6/cam-action-03-facade.schema.json"), "utf8")); assert.equal(schema.$id, "https://freecad.org/schemas/freecad-web-cam-inspect-source-inventory-v1.json");
const report = { schema: "freecad-web-p6-cam-action-03-facade/v1", task_id: "FW-P6-CAM-ACT-03-E", status: "pass", action: "cam.inspectSourceInventory", envelopeSchema: "freecad-web-facade/v1", typedSchema: CAM_INSPECT_SCHEMA, responses: { success, expectedError, duplicate, cancelled, afterCancel }, trace, sequencing: { maxActive, activeAfter: active, requestCount: 5, responseCount: 5, cancelAccepted }, state: { beforeCancel: success.result.stateSha256, afterCancel: afterCancel.result.stateSha256, unchangedAfterCancel: success.result.stateSha256 === afterCancel.result.stateSha256 }, schemaChecks: { request: true, result: true, expectedError: true, duplicate: true, cancel: true, noNativePointers: !JSON.stringify(trace).match(/pointer|native/i) }, inputSha256: crypto.createHash("sha256").update(JSON.stringify(CAM_INSPECT_FIXTURE)).digest("hex"), commands: ["npx tsc --target ES2022 --module ESNext --moduleResolution Bundler --strict --skipLibCheck --outDir /tmp/freecad-p6-cam-action-03 --declaration false --noEmit false src/facade-envelope.ts src/cam-inspect-facade.ts", "node tools/run_p6_cam_action03_facade_smoke.mjs /tmp/freecad-p6-cam-action-03/cam-inspect-facade.js"], artifacts: { schema: "docs/p6/cam-action-03-facade.schema.json", workerLog: "docs/freecad-p6-cam-action-03-e-facade.log" }, boundaries: ["Read-only source inventory exposes no native pointers or document mutation."] };
fs.writeFileSync(path.join(docsRoot, "p6/cam-action-03-facade.json"), `${JSON.stringify(report, null, 2)}\n`); fs.writeFileSync(path.join(docsRoot, "freecad-p6-cam-action-03-e-facade.log"), `${trace.map((event, index) => `${String(index + 1).padStart(2, "0")} ${JSON.stringify(event)}`).join("\n")}\nresult=pass\nmaxActive=${maxActive}\n`); console.log(JSON.stringify({ result: report.status, requests: 5, responses: 5, maxActive }));