From 29f8bf575eb9822e64584d14a0859b77aada8bb3 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 29 Sep 2026 21:35:44 +0200 Subject: [PATCH] Tests: a repeated Connect acknowledges what it carries (TS, Python, C#); fix the TS replaced-peer test The repeated-Connect answer applies its acknowledgement field in every runtime; no test failed when a runtime stopped doing so. The TS replaced-peer test now lets client A receive its Accept before A sends. Co-Authored-By: Claude Opus 5.5 --- packages/cultnet-py/tests/test_cultnet.py | 9 +++++++++ packages/cultnet-ts/test/cultnet.test.ts | 16 +++++++++++++++- .../GameCult.Networking.Tests/NetworkingTests.cs | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/cultnet-py/tests/test_cultnet.py b/packages/cultnet-py/tests/test_cultnet.py index 57c24421..7e78c48f 100644 --- a/packages/cultnet-py/tests/test_cultnet.py +++ b/packages/cultnet-py/tests/test_cultnet.py @@ -695,6 +695,15 @@ class CultNetTests(unittest.TestCase): self.assertTrue(client.check_timeout(91, 50)) self.assertFalse(client.connected) + def test_a_repeated_connect_acknowledges_what_it_carries(self) -> None: + client = CultNetRudpSession(CultNetRudpSessionOptions(connection_id=103, initial_sequence=1)) + server = CultNetRudpSession(CultNetRudpSessionOptions(connection_id=103, initial_sequence=100)) + connect = client.create_connect(0, b"join") + accept = server.accept_connect(connect, 0) + reply = server.answer_repeated_connect(replace(connect, ack=accept.sequence), 1) + self.assertEqual(reply.packet_type, CultNetRudpPacketType.ACK) + self.assertEqual(server.outstanding_reliable_packet_count, 0) + def test_cultnet_rudp_session_bounds_pending_reliable_packets_before_enqueue(self) -> None: session = CultNetRudpSession( CultNetRudpSessionOptions(connection_id=102, initial_sequence=1, max_pending_reliable_packets=2) diff --git a/packages/cultnet-ts/test/cultnet.test.ts b/packages/cultnet-ts/test/cultnet.test.ts index bdaa9509..093b49d6 100644 --- a/packages/cultnet-ts/test/cultnet.test.ts +++ b/packages/cultnet-ts/test/cultnet.test.ts @@ -2233,6 +2233,8 @@ test("server-mode transport replaces its peer when a Connect arrives from anothe connectionId, resendPollMs: 1000, }); + const receivedByA: CultNetRudpPacket[] = []; + socketA.on("message", (wire) => receivedByA.push(decodeRudpPacket(wire))); const receivedByB: CultNetRudpPacket[] = []; socketB.on("message", (wire) => receivedByB.push(decodeRudpPacket(wire))); const frames: string[] = []; @@ -2243,7 +2245,8 @@ test("server-mode transport replaces its peer when a Connect arrives from anothe socket.send(encodeRudpPacket(packet), udpPort(serverSocket), "127.0.0.1"); try { send(socketA, peerA.createConnect(0)); - await waitFor(() => server.connected, "A accepted"); + await waitFor(() => receivedByA.some((p) => p.packetType === "accept"), "A's Accept"); + peerA.receive(receivedByA.find((p) => p.packetType === "accept")!, 0); send(socketB, peerB.createConnect(0)); await waitFor(() => receivedByB.some((p) => p.packetType === "accept"), "B's Accept"); peerB.receive(receivedByB.find((p) => p.packetType === "accept")!, 0); @@ -2339,3 +2342,14 @@ test("a flush is bound to the session it started in, even when a disconnect list client.close(); } }); + +test("a repeated Connect acknowledges what it carries", () => { + const connectionId = 0x1020305a; + const client = new CultNetRudpSession({ connectionId }); + const server = new CultNetRudpSession({ connectionId }); + const connect = client.createConnect(0); + const accept = server.acceptConnect(connect, 0); + const reply = server.answerRepeatedConnect({ ...connect, ack: accept.sequence }, 1); + assert.equal(reply.packetType, "ack"); + assert.equal(server.outstandingReliablePacketCount, 0); +}); diff --git a/tests/GameCult.Networking.Tests/NetworkingTests.cs b/tests/GameCult.Networking.Tests/NetworkingTests.cs index ce39ea30..e32ca91a 100644 --- a/tests/GameCult.Networking.Tests/NetworkingTests.cs +++ b/tests/GameCult.Networking.Tests/NetworkingTests.cs @@ -900,6 +900,20 @@ namespace GameCult.Networking.Tests Assert.That(client.Connected, Is.False); } + [Test] + public void RudpSession_RepeatedConnectAcknowledgesWhatItCarries() + { + var client = new CultNetRudpSession(new CultNetRudpSessionOptions { ConnectionId = 103, InitialSequence = 1 }); + var server = new CultNetRudpSession(new CultNetRudpSessionOptions { ConnectionId = 103, InitialSequence = 100 }); + var connect = client.CreateConnect(0, Encoding.UTF8.GetBytes("join")); + var accept = server.AcceptConnect(connect, 0); + var repeat = CultNetRudpPacketCodec.Decode(CultNetRudpPacketCodec.Encode(connect)); + repeat.Ack = accept.Sequence; + var reply = server.AnswerRepeatedConnect(repeat, 1); + Assert.That(reply.PacketType, Is.EqualTo(CultNetRudpPacketType.Ack)); + Assert.That(server.OutstandingReliablePacketCount, Is.EqualTo(0)); + } + [Test] public void RudpSession_LossyPacketsCannotCreateReliableOrderedGaps() {