89 lines
4.4 KiB
JavaScript
89 lines
4.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { createRequire } from "node:module";
|
|
import { Worker } from "node:worker_threads";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
|
|
const facadePath = path.resolve(process.argv[2] ?? path.join(root, "web/src/spreadsheet-facade.ts"));
|
|
const buildDirectory = path.resolve(process.argv[3] ?? path.join(root, "freecad-source/build-web/configure/bin"));
|
|
const facade = await import(pathToFileURL(facadePath));
|
|
const envelope = await import(pathToFileURL(path.join(path.dirname(facadePath), "facade-envelope.js")));
|
|
const worker = new Worker(new URL("./spreadsheet-facade-smoke-worker.mjs", import.meta.url), {
|
|
workerData: { facadePath, envelopePath: path.join(path.dirname(facadePath), "facade-envelope.js"), buildDirectory },
|
|
});
|
|
const events = [];
|
|
const pending = new Map();
|
|
worker.on("message", (message) => {
|
|
events.push(message.kind === "ready" ? "ready" : `${message.kind}:${message.requestId}`);
|
|
if (message.requestId && pending.has(message.requestId)) {
|
|
pending.get(message.requestId)(message);
|
|
pending.delete(message.requestId);
|
|
}
|
|
});
|
|
const waitFor = (requestId) => new Promise((resolve) => pending.set(requestId, resolve));
|
|
const ready = await new Promise((resolve) => worker.once("message", resolve));
|
|
assert.equal(ready.kind, "ready");
|
|
const send = (request) => { const response = waitFor(request.requestId); worker.postMessage(request); return response; };
|
|
|
|
const success = await send(facade.createSpreadsheetCreateRequest("spr-e-success"));
|
|
const expectedError = await send(facade.createSpreadsheetCreateRequest("spr-e-error", {
|
|
...facade.SPREADSHEET_CREATE_FIXTURE,
|
|
b1: "=A1+",
|
|
}));
|
|
const duplicate = await send(facade.createSpreadsheetCreateRequest("spr-e-success"));
|
|
const cancelRequest = facade.createSpreadsheetCreateRequest("spr-e-cancel");
|
|
const cancelledPromise = send(cancelRequest);
|
|
worker.postMessage(envelope.createCancel("spr-e-cancel-message", cancelRequest.requestId, "spreadsheet-create"));
|
|
const cancelAccepted = await new Promise((resolve) => {
|
|
const timer = setInterval(() => {
|
|
if (events.includes("error:spr-e-cancel-message")) { clearInterval(timer); resolve(false); }
|
|
if (events.includes("error:spr-e-cancel")) { clearInterval(timer); resolve(true); }
|
|
}, 1);
|
|
});
|
|
const cancelled = await cancelledPromise;
|
|
const after = await send(facade.createSpreadsheetCreateRequest("spr-e-after"));
|
|
await worker.terminate();
|
|
|
|
assert.equal(success.kind, "result");
|
|
assert.equal(success.result.objectType, "Spreadsheet::Sheet");
|
|
assert.equal(success.result.cellA1, "21");
|
|
assert.equal(success.result.cellB1, "=A1*2");
|
|
assert.equal(expectedError.kind, "error");
|
|
assert.equal(expectedError.error.code, "invalid_fixture");
|
|
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(after.kind, "result");
|
|
assert.deepEqual(after.result, success.result);
|
|
|
|
const responses = { success, expectedError, duplicate, cancelled, after };
|
|
const report = {
|
|
schema: "freecad-web-p6-spreadsheet-facade/v1",
|
|
taskId: "FW-P6-SPR-E",
|
|
module: "Spreadsheet",
|
|
action: "create/recompute",
|
|
result: "pass",
|
|
responses,
|
|
sequencing: { requestCount: 5, responseCount: 5, cancelAccepted, events },
|
|
schemaChecks: {
|
|
responses: Object.values(responses).every((response) => envelope.isFacadeResponse(response)),
|
|
noNativePointers: !JSON.stringify(responses).match(/pointer|native|handle/i),
|
|
},
|
|
fixture: {
|
|
...facade.SPREADSHEET_CREATE_FIXTURE,
|
|
inputSha256: crypto.createHash("sha256").update(JSON.stringify(facade.SPREADSHEET_CREATE_FIXTURE)).digest("hex"),
|
|
},
|
|
boundaries: [
|
|
"Success responses come from the native Spreadsheet WASM C ABI; the facade exposes typed values only.",
|
|
"Cancellation is issued before the delayed kernel source resolves and the next request replays successfully.",
|
|
],
|
|
};
|
|
fs.writeFileSync(path.join(root, "docs/p6/spreadsheet-facade.json"), `${JSON.stringify(report, null, 2)}\n`);
|
|
fs.writeFileSync(path.join(root, "docs/freecad-p6-spreadsheet-e-facade.log"), `${JSON.stringify({ result: report.result, requests: 5, cancelAccepted, events })}\n`);
|
|
console.log(JSON.stringify({ result: report.result, requests: 5, cancelAccepted, events }));
|