test/daemon/bridge-routing-test.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
import { test, describe } from "node:test";
import assert from "node:assert/strict";
import { createEventRouter, createIdMultiplexer, type InFlight } from "../../src/daemon/bridge";
import type { SendToClient } from "../../src/daemon/bridge";
import type { WireEvent } from "../../src/daemon/protocol";
const noSend: SendToClient = () => {};
const entry = (clientId: string, localId: number): Omit<InFlight, "timer"> => ({
clientId,
localId,
send: noSend,
isAttach: false,
});
const inertTimer = (): ReturnType<typeof setTimeout> => setTimeout(() => {}, 60_000);
describe("daemon id multiplexer", () => {
test("two clients using the same local id get distinct daemon ids", () => {
const mux = createIdMultiplexer();
const a = mux.allocate(entry("client-a", 1), inertTimer);
const b = mux.allocate(entry("client-b", 1), inertTimer);
assert.notEqual(a, b);
});
test("a response is routed back to the client that asked, with its own id", () => {
const mux = createIdMultiplexer();
const a = mux.allocate(entry("client-a", 7), inertTimer);
const b = mux.allocate(entry("client-b", 7), inertTimer);
assert.equal(mux.take(b)?.clientId, "client-b");
const takenA = mux.take(a);
assert.equal(takenA?.clientId, "client-a");
assert.equal(takenA?.localId, 7);
});
test("taking the same daemon id twice yields nothing the second time", () => {
const mux = createIdMultiplexer();
const id = mux.allocate(entry("client-a", 1), inertTimer);
assert.ok(mux.take(id));
assert.equal(mux.take(id), undefined);
});
test("an unknown daemon id is not mistaken for an in-flight request", () => {
const mux = createIdMultiplexer();
assert.equal(mux.take(999), undefined);
});
test("clearClient drops only that client's in-flight requests", () => {
const mux = createIdMultiplexer();
const a = mux.allocate(entry("client-a", 1), inertTimer);
const b = mux.allocate(entry("client-b", 1), inertTimer);
mux.clearClient("client-a");
assert.equal(mux.take(a), undefined);
assert.equal(mux.take(b)?.clientId, "client-b");
});
test("clearClient cancels the pending timeout so a gone client is never answered", () => {
const mux = createIdMultiplexer();
let fired = false;
mux.allocate(entry("client-a", 1), () => setTimeout(() => { fired = true; }, 1));
mux.clearClient("client-a");
return new Promise<void>((resolve) => setTimeout(() => {
assert.equal(fired, false);
resolve();
}, 30));
});
test("takeAll drains every in-flight request exactly once", () => {
const mux = createIdMultiplexer();
mux.allocate(entry("client-a", 1), inertTimer);
mux.allocate(entry("client-b", 2), inertTimer);
assert.equal(mux.takeAll().length, 2);
assert.equal(mux.takeAll().length, 0);
});
});
const ev = (sessionId?: string): WireEvent => ({
type: "event",
method: "Page.loadEventFired",
...(sessionId !== undefined ? { sessionId } : {}),
});
describe("daemon event router", () => {
test("a session-scoped event goes only to the client owning that session", () => {
const router = createEventRouter();
router.record("client-a", "S1");
router.record("client-b", "S2");
assert.deepEqual(router.route(ev("S1")), ["client-a"]);
assert.deepEqual(router.route(ev("S2")), ["client-b"]);
});
test("an event for an unknown session goes nowhere rather than to everyone", () => {
const router = createEventRouter();
router.record("client-a", "S1");
assert.deepEqual(router.route(ev("S9")), []);
});
test("a session-less event goes to every client that holds a session", () => {
const router = createEventRouter();
router.record("client-a", "S1");
router.record("client-b", "S2");
assert.deepEqual(router.route(ev()).sort(), ["client-a", "client-b"]);
});
test("re-recording a session moves ownership and does not leave it with the old client", () => {
const router = createEventRouter();
router.record("client-a", "S1");
router.record("client-b", "S1");
assert.equal(router.getOwner("S1"), "client-b");
assert.deepEqual(router.route(ev("S1")), ["client-b"]);
});
test("releasing a session leaves its events unrouted", () => {
const router = createEventRouter();
router.record("client-a", "S1");
router.release("S1");
assert.equal(router.getOwner("S1"), undefined);
assert.deepEqual(router.route(ev("S1")), []);
});
test("removing a client releases every session it owned", () => {
const router = createEventRouter();
router.record("client-a", "S1");
router.record("client-a", "S2");
router.record("client-b", "S3");
router.removeClient("client-a");
assert.equal(router.getOwner("S1"), undefined);
assert.equal(router.getOwner("S2"), undefined);
assert.equal(router.getOwner("S3"), "client-b");
assert.deepEqual(router.route(ev()), ["client-b"]);
});
});
|