63 lines
3.0 KiB
TypeScript
63 lines
3.0 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
import { test } from "node:test";
|
|
import { compoundCrdtPlan } from "./compound-crdt-fixture.js";
|
|
import { compileCapabilityResourceSource, compileCapabilitySource } from "../src/capability-language/parser.js";
|
|
import { compileKernelProgram } from "../src/execution-world/index.js";
|
|
import { generatePortableTypeScriptBindings } from "../src/bindings/portable.js";
|
|
const source = { repository: "https://example.test/change.git", commit: "a".repeat(40) };
|
|
test("compound captured changes survive planning, transport lowering and typed edit ports", async () => {
|
|
const plan = await compoundCrdtPlan();
|
|
const kernel = compileKernelProgram(plan) as {
|
|
operations: { operation: string; input: { fields: { change: { kind: string } } } }[];
|
|
};
|
|
const operation = kernel.operations.find((op) => op.operation === "compound:update:call")!;
|
|
assert.equal(operation.input.fields.change.kind, "record");
|
|
const code = generatePortableTypeScriptBindings(plan.definition.bindingSchema, "compound:runtime@1", {
|
|
target: "browser",
|
|
});
|
|
assert.ok(code.includes("PreparedChange<"));
|
|
assert.ok(code.includes('"edit"'));
|
|
assert.ok(!code.includes('"compound:runtime:check"'));
|
|
});
|
|
test("prepared changes require one storable materialized type", () => {
|
|
for (const shape of ["change<string, bool>", "change<atom N>", "change<atom-ref<N>>", "change<change<string>>"]) {
|
|
const result = compileCapabilityResourceSource(
|
|
`external atom N id "n"; package P id "p" revision "p@1" {
|
|
function f id "f" : ${shape} -> unit execution transaction targets [browser, server];
|
|
}`,
|
|
{ source },
|
|
);
|
|
assert.equal(result.ok, false, shape);
|
|
}
|
|
});
|
|
test("captured changes cannot be persisted in a register or CRDT", async () => {
|
|
const iface = compileCapabilityResourceSource(await readFile("test/fixtures/compound-crdt/NoteData.qx", "utf8"), {
|
|
source,
|
|
});
|
|
assert.ok(iface.ok && iface.resource.kind === "interface", JSON.stringify(iface.diagnostics));
|
|
const pkg = compileCapabilityResourceSource(await readFile("test/fixtures/compound-crdt/EditRuntime.qx", "utf8"), {
|
|
source,
|
|
});
|
|
assert.ok(pkg.ok && pkg.resource.kind === "package", JSON.stringify(pkg.diagnostics));
|
|
const workspace = await readFile("test/fixtures/compound-crdt/workspace.qx", "utf8");
|
|
for (const policy of ["register", "crdt(change<Content>)"]) {
|
|
const result = compileCapabilitySource(
|
|
workspace.replace(
|
|
"private state Allowed",
|
|
`private state Captured id "captured" on Note : record { captured: change<Content>; } policy ${policy};\n private state Allowed`,
|
|
),
|
|
"workspace.qx",
|
|
{
|
|
interfaces: new Map([["NoteData", iface.resource.revision]]),
|
|
packages: new Map([["EditRuntime", pkg.resource.revision]]),
|
|
},
|
|
);
|
|
assert.equal(result.ok, false);
|
|
assert.ok(
|
|
result.diagnostics.some((d) => d.code === "invalid-attachment"),
|
|
JSON.stringify(result.diagnostics),
|
|
);
|
|
}
|
|
});
|