all repos — sz-chrome-remote-cdp @ master

pi-browser-harness, patched to drive a Chrome on another host over CDP, with castle_cdp_search web search

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"]);
  });
});