diff --git a/tests/testTransport.cpp b/tests/testTransport.cpp index 1806829..05a1a62 100644 --- a/tests/testTransport.cpp +++ b/tests/testTransport.cpp @@ -321,3 +321,77 @@ VF_TEST(smoothedRoundTripTimeConvergesOnTheLinkLatency) { CHECK_EQ(sender.stats().datagramsLost, static_cast(0)); } +VF_TEST(theAckBitfieldConfirmsDatagramsWhoseOwnAckWasLost) { + LinkQuality quality; + quality.latencyTicks = 1; + quality.seed = 0x4242424242424242ull; + LoopbackLink link(quality); + + TransportConfig config; + config.mtu = 96; + config.sendWindow = 32; + config.retransmitTimeoutTicks = 1000; + Transport sender(link, 0, config); + Transport receiver(link, 1, config); + + for (uint32_t i = 0; i < 12; ++i) sender.sendReliable(messageOf(i, 50)); + + // Twelve datagrams leave, and the sender never pumps, so not a single ack + // has been seen when the burst is complete. + sender.flush(0); + CHECK_EQ(sender.inFlightDatagramCount(), static_cast(12)); + CHECK_EQ(sender.stats().datagramsSent, static_cast(12)); + CHECK_EQ(sender.stats().smoothedRttTicks, 0.0); + + // A single hand-built ack: latest is sequence 11, and the history bitfield + // covers sequences 10 down to 0. Nothing else ever reaches the sender. + receiver.pump(1); + Datagram carrier; + carrier.sequence = 0; + carrier.ackLatest = 11; + carrier.ackHistory = 0x7ffu; + carrier.ackValid = true; + ByteWriter wire; + carrier.encode(wire); + link.send(1, wire.bytes(), 1); + + sender.pump(2); + CHECK_EQ(sender.inFlightDatagramCount(), static_cast(0)); + CHECK_EQ(sender.unackedFragmentCount(), static_cast(0)); + CHECK_EQ(sender.stats().retransmitted, static_cast(0)); + CHECK(sender.stats().smoothedRttTicks > 0.0); + + // The whole burst still arrived exactly once, in order. + std::vector order; + for (uint64_t tick = 2; tick < 30; ++tick) { + receiver.pump(tick); + ByteBuffer got; + while (receiver.popReliable(got)) order.push_back(indexOf(got)); + } + CHECK_EQ(order.size(), static_cast(12)); + for (std::size_t i = 0; i < order.size(); ++i) CHECK_EQ(order[i], static_cast(i)); +} + +VF_TEST(aTransportWithNothingToSendStillAcknowledgesWithoutAnAckStorm) { + LinkQuality quality; + quality.latencyTicks = 1; + quality.seed = 0x0f0f0f0f0f0f0f0full; + LoopbackLink link(quality); + + TransportConfig config; + config.mtu = 256; + config.retransmitTimeoutTicks = 20; + Transport sender(link, 0, config); + Transport receiver(link, 1, config); + + sender.sendReliable(messageOf(0, 40)); + for (uint64_t tick = 0; tick < 30; ++tick) stepPair(sender, receiver, tick); + + ByteBuffer got; + CHECK(receiver.popReliable(got)); + CHECK_EQ(indexOf(got), 0u); + CHECK_EQ(sender.unackedFragmentCount(), static_cast(0)); + // One payload datagram plus at most a handful of bare acks, not one per tick. + CHECK(receiver.stats().datagramsSent <= 3u); + CHECK(sender.stats().datagramsSent <= 3u); +}