Files
dev/third_party/pi/packages/chord/test/links-review.test.ts
alexion 6081e3e325 chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
2026-10-15 17:58:48 -04:00

554 lines
19 KiB
TypeScript

// Regression tests for Astra's phase 1b review (findings #1-#11) and the shared-worker test gap.
import assert from "node:assert/strict";
import { Type } from "typebox";
import { describe, it } from "vitest";
import {
type Ctx,
createHost,
type Facet,
type FacetLoader,
type Frame,
type Host,
hostNamed,
isChordError,
type Link,
local,
memoryLinkPair,
method,
PROTOCOL_VERSION,
remote,
} from "../src/index.ts";
const tick = () => new Promise<void>((resolve) => setImmediate(resolve));
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
async function until(check: () => boolean, attempts = 100): Promise<void> {
for (let i = 0; i < attempts && !check(); i++) await sleep(2);
assert.ok(check(), "condition not reached");
}
function latch() {
let open = () => {};
const promise = new Promise<void>((resolve) => {
open = resolve;
});
return { promise, open };
}
/** A link that logs what it sends and can drop a frame by closing instead. */
class WatchedLink implements Link {
readonly inner: Link;
readonly sent: Frame[] = [];
closeOn: ((frame: Frame) => boolean) | undefined;
constructor(inner: Link) {
this.inner = inner;
}
get closed(): boolean {
return this.inner.closed;
}
send(frame: Frame): number | undefined {
this.sent.push(frame);
if (this.closeOn?.(frame)) {
this.inner.close("dropped");
return undefined;
}
return this.inner.send(frame);
}
receive(handler: (frame: Frame) => void): void {
this.inner.receive(handler);
}
onClose(handler: (reason: string) => void): void {
this.inner.onClose(handler);
}
close(reason?: string): void {
this.inner.close(reason);
}
}
const Counter = remote("t.counter", {
version: 1,
input: Type.Object({ name: Type.String() }),
host: hostNamed("session:S1"),
variants: {
main: {
state: { count: Type.Object({ n: Type.Number() }) },
methods: {
add: method(Type.Number(), Type.Number()),
who: method(undefined, Type.Unknown()),
slow: method(),
},
},
},
});
/** A server routing `session:*` to workers it spawns once per name; the server→worker link is watched. */
function cluster() {
const log: string[] = [];
const principals: unknown[] = [];
const server = createHost({ self: { kind: "host" }, name: "server", onError: () => {} });
const workers = new Map<string, { host: Host; link: WatchedLink }>();
const state = {
server,
log,
principals,
workers,
resolveGate: undefined as Promise<void> | undefined,
slowGate: latch(),
browser(principal: unknown, restamp?: (p: unknown) => unknown | undefined) {
const [down, up] = memoryLinkPair();
server.accept(down, { principal, restamp });
return {
host: createHost({
self: { kind: "host" },
name: "browser",
kind: "client",
upstream: { link: up, principal: { kind: "server" } },
onError: () => {},
}),
up,
};
},
raw(principal: unknown) {
const [down, raw] = memoryLinkPair();
server.accept(down, { principal });
const frames: Frame[] = [];
raw.receive((frame) => frames.push(frame));
raw.send({ t: "hello", protocol: PROTOCOL_VERSION, name: "raw", kind: "client", codeVersion: 0 });
return { raw, frames };
},
};
server.route("session:", {
principal: (name) => ({ host: name }),
authorize: () => true,
resolve: async (name) => {
await state.resolveGate;
const existing = workers.get(name);
if (existing !== undefined) return existing.link;
const [down, up] = memoryLinkPair();
const link = new WatchedLink(down);
const worker = createHost({
self: { kind: "host" },
name,
upstream: { link: up, principal: { kind: "server" } },
onError: () => {},
});
worker.serve(Counter, (input, principal, self) => {
principals.push(principal);
self.resource("probe", {
version: 1,
open: () => void log.push(`open ${input.name}`),
close: () => void log.push(`close ${input.name}`),
});
const count = self.state("count", Type.Object({ n: Type.Number() }), { n: 0 });
return {
variant: "main",
count,
add: (delta: number, ctx: Ctx) => {
count.change(ctx, (draft) => {
draft.n += delta;
});
return count.value.n;
},
who: () => principal,
slow: async (ctx: Ctx) => {
ctx.signal.addEventListener("abort", () => log.push("slow aborted"));
await state.slowGate.promise;
},
};
});
workers.set(name, { host: worker, link });
return link;
},
});
return state;
}
const internals = (host: Host) =>
host as unknown as {
connections: Set<{
role: string;
peer: { kind: string; name?: string };
relayedRefs: Map<number, unknown>;
relayedSubs: Map<number, unknown>;
relayedCalls: Map<number, unknown>;
}>;
reloading: boolean;
};
describe("links review: identity and stamping", () => {
it("#1 the acceptor decides what a peer is: a client announcing itself as a host is cut off", async () => {
const c = cluster();
const [down, raw] = memoryLinkPair();
c.server.accept(down, { principal: { guest: "g" } });
raw.receive(() => {});
raw.send({ t: "hello", name: "session:S9", kind: "host", codeVersion: 1 });
await until(() => raw.closed);
// A host link must have a name and its hello must match it.
assert.throws(() => c.server.accept(memoryLinkPair()[0], { principal: {}, kind: "host" }), /needs its name/);
});
it("#1 root_end is honored only from the link the root came over", async () => {
const server = createHost({ self: { kind: "host" }, name: "server", onError: () => {} });
const Echo = remote("t.echo", {
version: 1,
input: Type.Object({}),
host: hostNamed("server"),
variants: { main: { methods: { root: method(undefined, Type.String()) } } },
});
const facet = (version: number): Facet => ({
name: "echo",
setup: (api) =>
api.serve(Echo, (_input, _principal, self) => {
self.state("n", Type.Number(), 0, { version });
return { variant: "main", root: (ctx: Ctx) => ctx.rootId };
}),
});
server.install(facet(1));
const [down, up] = memoryLinkPair();
server.accept(down, { principal: { worker: "w" }, kind: "host", name: "w" });
const worker = createHost({
self: { kind: "host" },
name: "w",
upstream: { link: up, principal: { kind: "server" } },
onError: () => {},
});
const go = latch();
let rootId = "";
const pinned = worker.root(async (ctx) => {
rootId = (await (await ctx.get(Echo, {})).root(ctx)) as string;
await go.promise;
});
await until(() => rootId !== "");
// A client forging the worker root's end must not release its lease.
const [clientDown, raw] = memoryLinkPair();
server.accept(clientDown, { principal: { guest: "g" } });
raw.receive(() => {});
raw.send({ t: "hello", protocol: PROTOCOL_VERSION, name: "raw", kind: "client", codeVersion: 0 });
raw.send({ t: "root_end", rootId });
await sleep(10);
await assert.rejects(server.reload([facet(2)], { gateDeadline: 40 }), (error) => {
assert.ok(isChordError(error, "aborted") && error.reason === "gate_deadline");
assert.ok(error.message.includes(rootId));
return true;
});
go.open();
await pinned;
});
it("#2 a revocation while the route is still resolving closes the relay; no worker object is made", async () => {
const c = cluster();
const gate = latch();
c.resolveGate = gate.promise;
const browser = c.browser({ guest: "g", revision: 1 }, (p) => ({ ...(p as object), revision: 2 }));
const counter = browser.host.hold(Counter, { name: "a" });
await sleep(5);
await c.server.invalidatePrincipal({ guest: "g" });
await until(() => counter.status === "gone");
gate.open();
await sleep(10);
assert.deepEqual(c.principals, []);
const again = browser.host.hold(Counter, { name: "a" });
assert.deepEqual(await again.who(), { guest: "g", revision: 2 });
});
it("#10 malformed frames and duplicate ids close the link", async () => {
const c = cluster();
const first = c.raw({ guest: "g" });
first.raw.send({ t: "call", hold: 1 } as never);
await until(() => first.raw.closed);
const second = c.raw({ guest: "g" });
const token = Counter.description;
second.raw.send({ t: "hold", id: 1, at: "session:S1", token, input: { name: "a" } });
second.raw.send({ t: "hold", id: 1, at: "session:S1", token, input: { name: "b" } });
await until(() => second.raw.closed);
});
});
describe("links review: relay ownership", () => {
it("#7 a browser disconnect cancels its call downstream", async () => {
const c = cluster();
const browser = c.browser({ guest: "g" });
const counter = browser.host.hold(Counter, { name: "a" });
await counter.ready;
void counter.slow().catch(() => {});
await sleep(10);
browser.up.close();
await until(() => c.log.includes("slow aborted"));
const down = [...internals(c.server).connections].find((connection) => connection.peer.name === "session:S1")!;
assert.equal(down.relayedCalls.size, 0);
});
it("#9 state stopped while the route resolves is forwarded as a hold without state", async () => {
const c = cluster();
const gate = latch();
c.resolveGate = gate.promise;
const { raw } = c.raw({ guest: "g" });
raw.send({ t: "hold", id: 1, at: "session:S1", token: Counter.description, input: { name: "a" } });
raw.send({ t: "unsub", hold: 1 });
await sleep(5);
gate.open();
await until(() => c.workers.get("session:S1")?.link.sent.some((frame) => frame.t === "hold") === true);
await sleep(10);
const sent = c.workers.get("session:S1")!.link.sent;
const hold = sent.find((frame) => frame.t === "hold");
assert.ok(hold?.t === "hold" && hold.state === false);
assert.ok(!sent.some((frame) => frame.t === "sub" || frame.t === "unsub"));
});
it("#9 a release while the route resolves settles waiting calls and forwards nothing", async () => {
const c = cluster();
const gate = latch();
c.resolveGate = gate.promise;
const { raw, frames } = c.raw({ guest: "g" });
raw.send({ t: "hold", id: 1, at: "session:S1", token: Counter.description, input: { name: "a" } });
raw.send({ t: "call", id: 2, hold: 1, member: "add", args: 1 });
await sleep(5);
raw.send({ t: "release", id: 1 });
await until(() => frames.some((frame) => frame.t === "result" && frame.id === 2));
const result = frames.find((frame) => frame.t === "result" && frame.id === 2);
assert.ok(result?.t === "result" && result.error !== undefined);
gate.open();
await sleep(10);
assert.ok(!(c.workers.get("session:S1")?.link.sent ?? []).some((frame) => frame.t === "hold"));
});
it("#9 an origin disconnect removes its relayed holds and subscriptions downstream", async () => {
const c = cluster();
const browser = c.browser({ guest: "g" });
const counter = browser.host.hold(Counter, { name: "a" });
counter.count.subscribe(() => {});
await counter.add(1);
const down = [...internals(c.server).connections].find((connection) => connection.peer.name === "session:S1")!;
assert.equal(down.relayedRefs.size, 1);
browser.up.close();
await until(() => down.relayedRefs.size === 0);
await until(() => c.log.includes("close a"));
});
it("two browsers share one worker connection; one leaving releases only its own holds", async () => {
const c = cluster();
const one = c.browser({ guest: "g1" });
const two = c.browser({ guest: "g2" });
const a = one.host.hold(Counter, { name: "same" });
const b = two.host.hold(Counter, { name: "same" });
assert.equal(await a.add(1), 1);
assert.equal(await b.add(5), 5);
assert.equal(c.workers.size, 1);
assert.deepEqual(c.principals, [{ guest: "g1" }, { guest: "g2" }]);
one.up.close();
await until(() => c.log.filter((entry) => entry === "close same").length === 1);
assert.equal(await b.add(1), 6);
});
it("#11 snapshots through an accepts adapter are validated against the consumer's schema", async () => {
const DocV1 = remote("t.doc", {
version: 1,
input: Type.Object({}),
host: hostNamed("server"),
variants: { main: { state: { view: Type.Object({ text: Type.String() }) } } },
});
const DocV2 = remote("t.doc", {
version: 2,
input: Type.Object({}),
host: hostNamed("server"),
variants: { main: { state: { view: Type.Object({ body: Type.String() }) } } },
});
const server = createHost({ self: { kind: "host" }, name: "server", onError: () => {} });
server.serve(
DocV2,
(_input, _principal, self) => ({
variant: "main",
view: self.state("view", Type.Object({ body: Type.String() }), { body: "hi" }),
}),
{
accepts: {
1: (current) => {
const view = current.view as {
value: { body: string };
events: (fn: (event: never) => void) => () => void;
};
const map = (value: { body: string }) => ({ text: value.body });
return {
variant: "main",
view: {
get value() {
return map(view.value);
},
subscribe: (fn: (value: unknown) => void) => view.events(() => fn(map(view.value))),
events: (fn: (event: unknown) => void) =>
view.events((event: { type: string }) =>
fn({ type: event.type === "ops" ? "reset" : event.type, value: map(view.value) }),
),
},
};
},
},
},
);
const [down, up] = memoryLinkPair();
server.accept(down, { principal: { guest: "g" } });
const browser = createHost({
self: { kind: "host" },
name: "browser",
kind: "client",
upstream: { link: up, principal: { kind: "server" } },
onError: () => {},
});
const doc = browser.hold(DocV1, {});
await doc.ready;
assert.deepEqual(doc.view.value, { text: "hi" });
});
});
describe("links review: cross-host reload", () => {
const Greeter = remote("t.greeter", {
version: 1,
input: Type.Object({}),
host: hostNamed("session:S1"),
variants: { main: { methods: { greet: method(Type.String(), Type.String()) } } },
});
const greeterFacet = (greeting: string): Facet => ({
name: "greeter",
setup: (api) => api.serve(Greeter, () => ({ variant: "main", greet: (name: string) => `${greeting} ${name}` })),
});
function setup(options: { slowLoad?: Promise<void> } = {}) {
const modules = new Map<string, Facet>([["greeter", greeterFacet("v1")]]);
const loader: FacetLoader = async (names) => {
await options.slowLoad;
return names.map((name) => modules.get(String(name))!);
};
const server = createHost({ self: { kind: "host" }, name: "server", onError: () => {} });
const connect = () => {
const [down, up] = memoryLinkPair();
const watched = new WatchedLink(down);
server.accept(watched, { principal: { worker: "w" }, kind: "host", name: "session:S1" });
return { watched, up };
};
const first = connect();
const worker = createHost({
self: { kind: "host" },
name: "session:S1",
upstream: { link: first.up, principal: { kind: "server" } },
loader,
onError: () => {},
});
worker.install(modules.get("greeter")!);
return { server, worker, modules, link: first.watched, connect };
}
it("#3 an abort while the child is still loading modules frees its reload slot; a later reload works", async () => {
const gate = latch();
const { server, worker, modules } = setup({ slowLoad: gate.promise });
await tick();
modules.set("greeter", greeterFacet("v2"));
await assert.rejects(server.reload([], { remote: { "session:": ["greeter"] }, voteDeadline: 30 }), (error) =>
isChordError(error, "aborted"),
);
gate.open();
await until(() => !internals(worker).reloading);
await server.reload([], { remote: { "session:": ["greeter"] } });
assert.equal(await server.hold(Greeter, {}).greet("x"), "v2 x");
});
it("#3 the parent link dying while the child prepares unwinds the child", async () => {
const gate = latch();
const { server, worker, modules, link } = setup({ slowLoad: gate.promise });
await tick();
modules.set("greeter", greeterFacet("v2"));
const reload = server.reload([], { remote: { "session:": ["greeter"] } });
await sleep(5);
link.close("gone");
await assert.rejects(reload);
gate.open();
await until(() => !internals(worker).reloading);
assert.equal(worker.codeVersion, 1);
});
it("#4 tasks the commit starts cannot reach a child before the child's commit", async () => {
const { server, modules } = setup();
await tick();
const results: unknown[] = [];
const Caller = local("t.caller", { version: 1, input: Type.Object({}) });
const callerFacet = (active: boolean): Facet => ({
name: "caller",
setup: (api) =>
api.serve(
Caller,
(_input, _principal, self) => {
const greeter = self.get(Greeter, {});
if (active) {
self.task(async (ctx) => {
results.push(
await greeter.greet("t", ctx).catch((error: unknown) => (error as { code: string }).code),
);
});
}
return {};
},
{ lifetime: "host" },
),
});
server.install(callerFacet(false));
await sleep(10);
modules.set("greeter", greeterFacet("v2"));
await server.reload([callerFacet(true)], { remote: { "session:": ["greeter"] } });
await until(() => results.length === 1);
assert.deepEqual(results, ["v2 t"]);
});
it("#5 a child that missed a commit is reconciled on reconnect, never relabeled", async () => {
const { server, worker, modules, link, connect } = setup();
await tick();
modules.set("greeter", greeterFacet("v2"));
// The commit frame is lost: the link dies right after the child voted.
link.closeOn = (frame) => frame.t === "commit";
await server.reload([], { remote: { "session:": ["greeter"] } });
await until(() => !internals(worker).reloading);
assert.notEqual(worker.codeVersion, server.codeVersion);
const next = connect();
worker.connect(next.up, { principal: { kind: "server" } });
const greeter = server.hold(Greeter, {});
assert.equal(await greeter.greet("x"), "v2 x");
assert.equal(worker.codeVersion, server.codeVersion);
});
it("#6 a server root that bounces through a worker and back ends normally (no leaked lease)", async () => {
const { server, worker } = setup();
await tick();
const Echo = remote("t.echo2", {
version: 1,
input: Type.Object({}),
host: hostNamed("server"),
variants: { main: { methods: { ping: method() } } },
});
const Bouncer = remote("t.bouncer", {
version: 1,
input: Type.Object({}),
host: hostNamed("session:S1"),
variants: { main: { methods: { bounce: method() } } },
});
const echoFacet = (version: number): Facet => ({
name: "echo",
setup: (api) =>
api.serve(Echo, (_input, _principal, self) => {
self.state("n", Type.Number(), 0, { version });
return { variant: "main", ping: () => {} };
}),
});
server.install(echoFacet(1));
// Keeps the Echo object the bounced call reaches (it acts as the worker's principal) alive, so the reload gate
// must decide about the bounced root's lease.
const echo = server.hold(Echo, {}, { principal: { worker: "w" } });
await echo.ready;
worker.serve(Bouncer, () => ({
variant: "main",
bounce: async (ctx: Ctx) => {
await (await ctx.get(Echo, {})).ping(ctx);
},
}));
await server.root((ctx) => server.hold(Bouncer, {}).bounce(ctx));
await sleep(10);
await server.reload([echoFacet(2)], { gateDeadline: 200 });
});
});