From 9d0701d4a71dba88ad1d6acf8838ce537e99fe2f Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 30 Sep 2026 06:15:12 +0200 Subject: [PATCH] Ack Cut 1c tests (cultmesh-ts): the document server replaces a restarted client and keeps a retransmitted Connect's session Co-Authored-By: Claude Sonnet 5.5 --- .../test/provider-rudp-transport.test.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/cultmesh-ts/test/provider-rudp-transport.test.ts b/packages/cultmesh-ts/test/provider-rudp-transport.test.ts index 5b44c84b..4e17eee9 100644 --- a/packages/cultmesh-ts/test/provider-rudp-transport.test.ts +++ b/packages/cultmesh-ts/test/provider-rudp-transport.test.ts @@ -8,6 +8,7 @@ import { decodeRudpPacket, encodeRudpPacket, type CultNetOperationRequestMessage, + type CultNetRudpPacket, } from "cultnet-ts"; import { @@ -320,6 +321,45 @@ test("a replaced RUDP generation drops operations queued behind an active handle } }); +test("a client restarted on the same address with the same Connect payload replaces its RUDP session, and a retransmitted Connect does not", async () => { + const connectionId = 0x43554c54; + let closedSessions = 0; + const server = CultMesh.createRudpDocumentServer("odin-restart-test", connectionId, { + bindPort: 0, + documents: new CultNetDocumentRegistry(), + onSessionClosed: () => { closedSessions += 1; }, + onError: () => undefined, + }); + await server.start(); + const socket = createSocket("udp4"); + const received: CultNetRudpPacket[] = []; + socket.on("message", wire => received.push(decodeRudpPacket(wire))); + const toServer = (packet: CultNetRudpPacket) => + socket.send(encodeRudpPacket(packet), server.bind.port, "127.0.0.1"); + const evidence = Buffer.from("same connect payload"); + try { + const first = new CultNetRudpSession({ connectionId, initialSequence: 50 }); + const connect = first.createConnect(Date.now(), evidence); + toServer(connect); + await waitFor(() => received.some(packet => packet.packetType === "accept"), "the first Accept"); + + // A retransmitted Connect repeats: the session stays. + toServer(connect); + await new Promise(resolve => setTimeout(resolve, 100)); + assert.equal(closedSessions, 0, "a retransmitted Connect closed the session"); + + // The same client restarted: another sequence, the same payload. + received.length = 0; + const second = new CultNetRudpSession({ connectionId, initialSequence: 7 }); + toServer(second.createConnect(Date.now(), evidence)); + await waitFor(() => closedSessions === 1, "the old RUDP session to close"); + await waitFor(() => received.some(packet => packet.packetType === "accept"), "the restarted client's Accept"); + } finally { + socket.close(); + server.close(); + } +}); + function deferred(): { promise: Promise; resolve(value: T): void } { let resolve!: (value: T) => void; return { promise: new Promise(done => resolve = done), resolve };