Support captured CRDT changes in compound transaction contracts
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
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),
|
||||
);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user