60 lines
5.4 KiB
JavaScript
60 lines
5.4 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 inspection-inspect-facade module path is required");
|
|
const facade = await import(path.resolve(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 queue = new envelope.FacadeSerialQueue();
|
|
const trace = [];
|
|
let active = 0;
|
|
let maxActive = 0;
|
|
const kernel = {
|
|
ccall(name, returnType) {
|
|
const values = { fc_web_inspection_initialize: 1, fc_web_inspection_type_probe: 1, fc_web_inspection_last_type: "Inspection::Group", fc_web_inspection_error_code: "", fc_web_inspection_error_message: "" };
|
|
return values[name] ?? (returnType === "string" ? "" : 0);
|
|
},
|
|
};
|
|
async function dispatch(request, source = kernel) {
|
|
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 await facade.handleInspectionInspect(payload, signal, source); } 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(facade.createInspectionInspectRequest("inspection-action-02-success"));
|
|
const expectedError = await dispatch(facade.createInspectionInspectRequest("inspection-action-02-error", { ...facade.INSPECTION_INSPECT_FIXTURE, sourceRevision: "wrong-revision" }));
|
|
const duplicate = await dispatch(facade.createInspectionInspectRequest("inspection-action-02-success"));
|
|
const cancelRequest = facade.createInspectionInspectRequest("inspection-action-02-cancel");
|
|
let resolveKernel;
|
|
const delayedKernel = new Promise((resolve) => { resolveKernel = resolve; });
|
|
const cancelPromise = dispatch(cancelRequest, delayedKernel);
|
|
const cancelAccepted = queue.cancel(envelope.createCancel("inspection-action-02-cancel-message", cancelRequest.requestId, "inspection-inspect-doc"));
|
|
resolveKernel(kernel);
|
|
const cancelled = await cancelPromise;
|
|
const afterCancel = await dispatch(facade.createInspectionInspectRequest("inspection-action-02-after-cancel"));
|
|
assert.equal(facade.isInspectionInspectRequest(facade.createInspectionInspectRequest("schema-test")), true);
|
|
assert.equal(success.kind, "result");
|
|
assert.equal(success.result.registeredTypes.length, 3);
|
|
assert.equal(success.result.readOnly, true);
|
|
assert.equal(expectedError.kind, "error");
|
|
assert.equal(expectedError.error.code, "revision_mismatch");
|
|
assert.equal(duplicate.error.code, "duplicate_request");
|
|
assert.equal(cancelAccepted, true);
|
|
assert.equal(cancelled.error.code, "cancelled");
|
|
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(envelope.isFacadeResponse(response), true);
|
|
const schemaPath = path.join(root, "docs/p6/inspection-action-02-facade.schema.json");
|
|
const schema = JSON.parse(fs.readFileSync(schemaPath, "utf8"));
|
|
assert.equal(schema.$defs.request.properties.command.const, facade.INSPECTION_INSPECT_COMMAND);
|
|
assert.equal(schema.$defs.payload.properties.entry.const, facade.INSPECTION_INSPECT_ENTRY);
|
|
const report = { schema: "freecad-web-p6-inspection-action-02-facade/v1", taskId: "FW-P6-INS-ACT-02-E", module: "Inspection", action: facade.INSPECTION_INSPECT_COMMAND, result: "pass", envelopeSchema: "freecad-web-facade/v1", typedSchema: facade.INSPECTION_INSPECT_SCHEMA, fixture: { ...facade.INSPECTION_INSPECT_FIXTURE, inputSha256: crypto.createHash("sha256").update(JSON.stringify(facade.INSPECTION_INSPECT_FIXTURE)).digest("hex") }, 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: true }, schemaChecks: { request: true, result: true, expectedError: true, duplicate: true, cancel: true, noNativePointers: !JSON.stringify(trace).match(/pointer|native/i) }, artifacts: { schema: "docs/p6/inspection-action-02-facade.schema.json", workerLog: "docs/freecad-p6-inspection-action-02-e-facade.log" }, commands: ["npx tsc --target ES2022 --module ESNext --moduleResolution Bundler --strict --skipLibCheck --outDir <tmp> --declaration false --noEmit false src/facade-envelope.ts src/inspection-inspect-facade.ts", "node tools/run_p6_inspection_action02_facade_smoke.mjs <tmp>/inspection-inspect-facade.js"] };
|
|
fs.writeFileSync(path.join(root, "docs/p6/inspection-action-02-facade.json"), `${JSON.stringify(report, null, 2)}\n`);
|
|
fs.writeFileSync(path.join(root, "docs/freecad-p6-inspection-action-02-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.result, requests: 5, responses: 5, maxActive }));
|