From 3f0f3995405e2a345adab912970e8ed6d819caef Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Sun, 12 Jan 2025 05:28:26 -0800 Subject: [PATCH] ackhandler: migrate received packet tracker tests away from Ginkgo (#4864) --- .../received_packet_tracker_test.go | 497 +++++------------- 1 file changed, 146 insertions(+), 351 deletions(-) diff --git a/internal/ackhandler/received_packet_tracker_test.go b/internal/ackhandler/received_packet_tracker_test.go index c970fbf1..1e9e7873 100644 --- a/internal/ackhandler/received_packet_tracker_test.go +++ b/internal/ackhandler/received_packet_tracker_test.go @@ -1,391 +1,186 @@ package ackhandler import ( + "testing" "time" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/utils" "github.com/quic-go/quic-go/internal/wire" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" + "github.com/stretchr/testify/require" ) -var _ = Describe("Received Packet Tracker", func() { - var tracker *receivedPacketTracker +func TestReceivedPacketTrackerGenerateACKs(t *testing.T) { + tracker := newReceivedPacketTracker() + baseTime := time.Now().Add(-10 * time.Second) - BeforeEach(func() { - tracker = newReceivedPacketTracker() - }) + require.NoError(t, tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, baseTime, true)) + ack := tracker.GetAckFrame() + require.NotNil(t, ack) + require.Equal(t, []wire.AckRange{{Smallest: 3, Largest: 3}}, ack.AckRanges) + require.Zero(t, ack.DelayTime) - It("acknowledges packets", func() { - t := time.Now().Add(-10 * time.Second) - Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, true)).To(Succeed()) - ack := tracker.GetAckFrame() - Expect(ack).ToNot(BeNil()) - Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 3, Largest: 3}})) - Expect(ack.DelayTime).To(BeZero()) - // now receive another packet - Expect(tracker.ReceivedPacket(protocol.PacketNumber(4), protocol.ECNNon, t.Add(time.Second), true)).To(Succeed()) - ack = tracker.GetAckFrame() - Expect(ack).ToNot(BeNil()) - Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 3, Largest: 4}})) - Expect(ack.DelayTime).To(BeZero()) - }) + require.NoError(t, tracker.ReceivedPacket(protocol.PacketNumber(4), protocol.ECNNon, baseTime.Add(time.Second), true)) + ack = tracker.GetAckFrame() + require.NotNil(t, ack) + require.Equal(t, []wire.AckRange{{Smallest: 3, Largest: 4}}, ack.AckRanges) + require.Zero(t, ack.DelayTime) - It("also acknowledges delayed packets", func() { - t := time.Now().Add(-10 * time.Second) - Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, true)).To(Succeed()) - ack := tracker.GetAckFrame() - Expect(ack).ToNot(BeNil()) - Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(3))) - Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(3))) - Expect(ack.DelayTime).To(BeZero()) - // now receive another packet - Expect(tracker.ReceivedPacket(protocol.PacketNumber(1), protocol.ECNNon, t.Add(time.Second), true)).To(Succeed()) - ack = tracker.GetAckFrame() - Expect(ack).ToNot(BeNil()) - Expect(ack.AckRanges).To(HaveLen(2)) - Expect(ack.AckRanges).To(ContainElement(wire.AckRange{Smallest: 1, Largest: 1})) - Expect(ack.AckRanges).To(ContainElement(wire.AckRange{Smallest: 3, Largest: 3})) - Expect(ack.DelayTime).To(BeZero()) - }) + require.NoError(t, tracker.ReceivedPacket(protocol.PacketNumber(1), protocol.ECNNon, baseTime.Add(time.Second), true)) + ack = tracker.GetAckFrame() + require.NotNil(t, ack) + require.Equal(t, []wire.AckRange{ + {Smallest: 3, Largest: 4}, + {Smallest: 1, Largest: 1}, + }, ack.AckRanges) + require.Zero(t, ack.DelayTime) - It("doesn't trigger ACKs for non-ack-eliciting packets", func() { - t := time.Now().Add(-10 * time.Second) - Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, false)).To(Succeed()) - Expect(tracker.GetAckFrame()).To(BeNil()) - Expect(tracker.ReceivedPacket(protocol.PacketNumber(4), protocol.ECNNon, t.Add(5*time.Second), false)).To(Succeed()) - Expect(tracker.GetAckFrame()).To(BeNil()) - Expect(tracker.ReceivedPacket(protocol.PacketNumber(5), protocol.ECNNon, t.Add(10*time.Second), true)).To(Succeed()) - ack := tracker.GetAckFrame() - Expect(ack).ToNot(BeNil()) - Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 3, Largest: 5}})) - }) -}) + // non-ack-eliciting packets don't trigger ACKs + require.NoError(t, tracker.ReceivedPacket(protocol.PacketNumber(10), protocol.ECNNon, baseTime.Add(5*time.Second), false)) + require.Nil(t, tracker.GetAckFrame()) -var _ = Describe("Application Data Received Packet Tracker", func() { - var tracker *appDataReceivedPacketTracker + require.NoError(t, tracker.ReceivedPacket(protocol.PacketNumber(11), protocol.ECNNon, baseTime.Add(10*time.Second), true)) + ack = tracker.GetAckFrame() + require.NotNil(t, ack) + require.Equal(t, []wire.AckRange{ + {Smallest: 10, Largest: 11}, + {Smallest: 3, Largest: 4}, + {Smallest: 1, Largest: 1}, + }, ack.AckRanges) +} - BeforeEach(func() { - tracker = newAppDataReceivedPacketTracker(utils.DefaultLogger) - }) +func TestAppDataReceivedPacketTrackerECN(t *testing.T) { + tr := newAppDataReceivedPacketTracker(utils.DefaultLogger) - Context("accepting packets", func() { - It("saves the time when each packet arrived", func() { - t := time.Now() - Expect(tracker.ReceivedPacket(protocol.PacketNumber(3), protocol.ECNNon, t, true)).To(Succeed()) - Expect(tracker.largestObservedRcvdTime).To(Equal(t)) - }) + require.NoError(t, tr.ReceivedPacket(0, protocol.ECT0, time.Now(), true)) + pn := protocol.PacketNumber(1) + for i := 0; i < 2; i++ { + require.NoError(t, tr.ReceivedPacket(pn, protocol.ECT1, time.Now(), true)) + pn++ + } + for i := 0; i < 3; i++ { + require.NoError(t, tr.ReceivedPacket(pn, protocol.ECNCE, time.Now(), true)) + pn++ + } + ack := tr.GetAckFrame(false) + require.Equal(t, uint64(1), ack.ECT0) + require.Equal(t, uint64(2), ack.ECT1) + require.Equal(t, uint64(3), ack.ECNCE) +} - It("updates the largestObserved and the largestObservedRcvdTime", func() { - now := time.Now() - tracker.largestObserved = 3 - tracker.largestObservedRcvdTime = now.Add(-1 * time.Second) - Expect(tracker.ReceivedPacket(5, protocol.ECNNon, now, true)).To(Succeed()) - Expect(tracker.largestObserved).To(Equal(protocol.PacketNumber(5))) - Expect(tracker.largestObservedRcvdTime).To(Equal(now)) - }) +func TestAppDataReceivedPacketTrackerAckEverySecondPacket(t *testing.T) { + tr := newAppDataReceivedPacketTracker(utils.DefaultLogger) + // the first packet is always acknowledged + require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)) + require.NotNil(t, tr.GetAckFrame(true)) + for p := protocol.PacketNumber(1); p <= 20; p++ { + require.NoError(t, tr.ReceivedPacket(p, protocol.ECNNon, time.Now(), true)) + switch p % 2 { + case 0: + require.NotNil(t, tr.GetAckFrame(true)) + case 1: + require.Nil(t, tr.GetAckFrame(true)) + } + } +} - It("doesn't update the largestObserved and the largestObservedRcvdTime for a belated packet", func() { - now := time.Now() - timestamp := now.Add(-1 * time.Second) - tracker.largestObserved = 5 - tracker.largestObservedRcvdTime = timestamp - Expect(tracker.ReceivedPacket(4, protocol.ECNNon, now, true)).To(Succeed()) - Expect(tracker.largestObserved).To(Equal(protocol.PacketNumber(5))) - Expect(tracker.largestObservedRcvdTime).To(Equal(timestamp)) - }) - }) +func TestAppDataReceivedPacketTrackerAlarmTimeout(t *testing.T) { + tr := newAppDataReceivedPacketTracker(utils.DefaultLogger) - Context("ACKs", func() { - Context("queueing ACKs", func() { - // receives and gets ACKs for packet numbers 1 to 10 (including) - receiveAndAck10Packets := func() { - for i := 1; i <= 10; i++ { - Expect(tracker.ReceivedPacket(protocol.PacketNumber(i), protocol.ECNNon, time.Time{}, true)).To(Succeed()) - } - Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) - Expect(tracker.ackQueued).To(BeFalse()) - } + // the first packet is always acknowledged + require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)) + require.NotNil(t, tr.GetAckFrame(true)) - It("always queues an ACK for the first packet", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ackQueued).To(BeTrue()) - Expect(tracker.GetAlarmTimeout()).To(BeZero()) - Expect(tracker.GetAckFrame(true).DelayTime).To(BeNumerically("~", 0, time.Second)) - }) + now := time.Now() + require.NoError(t, tr.ReceivedPacket(1, protocol.ECNNon, now, false)) + require.Nil(t, tr.GetAckFrame(true)) + require.Zero(t, tr.GetAlarmTimeout()) - It("works with packet number 0", func() { - Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ackQueued).To(BeTrue()) - Expect(tracker.GetAlarmTimeout()).To(BeZero()) - Expect(tracker.GetAckFrame(true).DelayTime).To(BeNumerically("~", 0, time.Second)) - }) + rcvTime := now.Add(10 * time.Millisecond) + require.NoError(t, tr.ReceivedPacket(2, protocol.ECNNon, rcvTime, true)) + require.Equal(t, rcvTime.Add(protocol.MaxAckDelay), tr.GetAlarmTimeout()) + require.Nil(t, tr.GetAckFrame(true)) - It("sets ECN flags", func() { - Expect(tracker.ReceivedPacket(0, protocol.ECT0, time.Now(), true)).To(Succeed()) - pn := protocol.PacketNumber(1) - for i := 0; i < 2; i++ { - Expect(tracker.ReceivedPacket(pn, protocol.ECT1, time.Now(), true)).To(Succeed()) - pn++ - } - for i := 0; i < 3; i++ { - Expect(tracker.ReceivedPacket(pn, protocol.ECNCE, time.Now(), true)).To(Succeed()) - pn++ - } - ack := tracker.GetAckFrame(false) - Expect(ack.ECT0).To(BeEquivalentTo(1)) - Expect(ack.ECT1).To(BeEquivalentTo(2)) - Expect(ack.ECNCE).To(BeEquivalentTo(3)) - }) + // no timeout after the ACK has been dequeued + require.NotNil(t, tr.GetAckFrame(false)) + require.Zero(t, tr.GetAlarmTimeout()) +} - It("queues an ACK for every second ack-eliciting packet", func() { - receiveAndAck10Packets() - p := protocol.PacketNumber(11) - for i := 0; i <= 20; i++ { - Expect(tracker.ReceivedPacket(p, protocol.ECNNon, time.Time{}, true)).To(Succeed()) - Expect(tracker.ackQueued).To(BeFalse()) - p++ - Expect(tracker.ReceivedPacket(p, protocol.ECNNon, time.Time{}, true)).To(Succeed()) - Expect(tracker.ackQueued).To(BeTrue()) - p++ - // dequeue the ACK frame - Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) - } - }) +func TestAppDataReceivedPacketTrackerQueuesECNCE(t *testing.T) { + tr := newAppDataReceivedPacketTracker(utils.DefaultLogger) - It("resets the counter when a non-queued ACK frame is generated", func() { - receiveAndAck10Packets() - rcvTime := time.Now() - Expect(tracker.ReceivedPacket(11, protocol.ECNNon, rcvTime, true)).To(Succeed()) - Expect(tracker.GetAckFrame(false)).ToNot(BeNil()) - Expect(tracker.ReceivedPacket(12, protocol.ECNNon, rcvTime, true)).To(Succeed()) - Expect(tracker.GetAckFrame(true)).To(BeNil()) - Expect(tracker.ReceivedPacket(13, protocol.ECNNon, rcvTime, true)).To(Succeed()) - Expect(tracker.GetAckFrame(false)).ToNot(BeNil()) - }) + // the first packet is always acknowledged + require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)) + require.NotNil(t, tr.GetAckFrame(true)) - It("only sets the timer when receiving a ack-eliciting packets", func() { - receiveAndAck10Packets() - Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), false)).To(Succeed()) - Expect(tracker.ackQueued).To(BeFalse()) - Expect(tracker.GetAlarmTimeout()).To(BeZero()) - rcvTime := time.Now().Add(10 * time.Millisecond) - Expect(tracker.ReceivedPacket(12, protocol.ECNNon, rcvTime, true)).To(Succeed()) - Expect(tracker.ackQueued).To(BeFalse()) - Expect(tracker.GetAlarmTimeout()).To(Equal(rcvTime.Add(protocol.MaxAckDelay))) - }) + require.NoError(t, tr.ReceivedPacket(1, protocol.ECNCE, time.Now(), true)) + ack := tr.GetAckFrame(true) + require.NotNil(t, ack) + require.Equal(t, protocol.PacketNumber(1), ack.LargestAcked()) + require.EqualValues(t, 1, ack.ECNCE) +} - It("queues an ACK if the packet was ECN-CE marked", func() { - receiveAndAck10Packets() - Expect(tracker.ReceivedPacket(11, protocol.ECNCE, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.AckRanges).To(HaveLen(1)) - Expect(ack.AckRanges[0].Largest).To(Equal(protocol.PacketNumber(11))) - Expect(ack.ECNCE).To(BeEquivalentTo(1)) - }) +func TestAppDataReceivedPacketTrackerMissingPackets(t *testing.T) { + tr := newAppDataReceivedPacketTracker(utils.DefaultLogger) - It("queues an ACK if it was reported missing before", func() { - receiveAndAck10Packets() - Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ReceivedPacket(13, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) // ACK: 1-11 and 13, missing: 12 - Expect(ack).ToNot(BeNil()) - Expect(ack.HasMissingRanges()).To(BeTrue()) - Expect(tracker.ackQueued).To(BeFalse()) - Expect(tracker.ReceivedPacket(12, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ackQueued).To(BeTrue()) - }) + // the first packet is always acknowledged + require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)) + require.NotNil(t, tr.GetAckFrame(true)) - It("doesn't recognize in-order packets as out-of-order after raising the threshold", func() { - receiveAndAck10Packets() - Expect(tracker.lastAck.LargestAcked()).To(Equal(protocol.PacketNumber(10))) - Expect(tracker.ackQueued).To(BeFalse()) - tracker.IgnoreBelow(11) - Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.GetAckFrame(true)).To(BeNil()) - }) + require.NoError(t, tr.ReceivedPacket(5, protocol.ECNNon, time.Now(), true)) + ack := tr.GetAckFrame(true) // ACK: 0 and 5, missing: 1, 2, 3, 4 + require.NotNil(t, ack) + require.Equal(t, []wire.AckRange{{Smallest: 5, Largest: 5}, {Smallest: 0, Largest: 0}}, ack.AckRanges) - It("recognizes out-of-order packets after raising the threshold", func() { - receiveAndAck10Packets() - Expect(tracker.lastAck.LargestAcked()).To(Equal(protocol.PacketNumber(10))) - Expect(tracker.ackQueued).To(BeFalse()) - tracker.IgnoreBelow(11) - Expect(tracker.ReceivedPacket(12, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.AckRanges).To(Equal([]wire.AckRange{{Smallest: 12, Largest: 12}})) - }) + // now receive one of the missing packets + require.NoError(t, tr.ReceivedPacket(3, protocol.ECNNon, time.Now(), true)) + require.NotNil(t, tr.GetAckFrame(true)) +} - It("doesn't queue an ACK if for non-ack-eliciting packets arriving out-of-order", func() { - receiveAndAck10Packets() - Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.GetAckFrame(true)).To(BeNil()) - Expect(tracker.ReceivedPacket(13, protocol.ECNNon, time.Now(), false)).To(Succeed()) // receive a non-ack-eliciting packet out-of-order - Expect(tracker.GetAckFrame(true)).To(BeNil()) - }) +func TestAppDataReceivedPacketTrackerDelayTime(t *testing.T) { + tr := newAppDataReceivedPacketTracker(utils.DefaultLogger) - It("doesn't queue an ACK if packets arrive out-of-order, but haven't been acknowledged yet", func() { - receiveAndAck10Packets() - Expect(tracker.lastAck).ToNot(BeNil()) - Expect(tracker.ReceivedPacket(12, protocol.ECNNon, time.Now(), false)).To(Succeed()) - Expect(tracker.GetAckFrame(true)).To(BeNil()) - // 11 is received out-of-order, but this hasn't been reported in an ACK frame yet - Expect(tracker.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.GetAckFrame(true)).To(BeNil()) - }) - }) + now := time.Now() + require.NoError(t, tr.ReceivedPacket(1, protocol.ECNNon, now, true)) + require.NoError(t, tr.ReceivedPacket(2, protocol.ECNNon, now.Add(-1337*time.Millisecond), true)) + ack := tr.GetAckFrame(true) + require.NotNil(t, ack) + require.InDelta(t, 1337*time.Millisecond, ack.DelayTime, float64(50*time.Millisecond)) - Context("ACK generation", func() { - It("generates an ACK for an ack-eliciting packet, if no ACK is queued yet", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - // The first packet is always acknowledged. - Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) - }) + // don't use a negative delay time + require.NoError(t, tr.ReceivedPacket(3, protocol.ECNNon, now.Add(time.Hour), true)) + ack = tr.GetAckFrame(false) + require.NotNil(t, ack) + require.Zero(t, ack.DelayTime) +} - It("doesn't generate ACK for a non-ack-eliciting packet, if no ACK is queued yet", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - // The first packet is always acknowledged. - Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) +func TestAppDataReceivedPacketTrackerIgnoreBelow(t *testing.T) { + tr := newAppDataReceivedPacketTracker(utils.DefaultLogger) - Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now(), false)).To(Succeed()) - Expect(tracker.GetAckFrame(false)).To(BeNil()) - Expect(tracker.ReceivedPacket(3, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(false) - Expect(ack).ToNot(BeNil()) - Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(1))) - Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(3))) - }) + tr.IgnoreBelow(4) + // check that packets below 7 are considered duplicates + require.True(t, tr.IsPotentiallyDuplicate(3)) + require.False(t, tr.IsPotentiallyDuplicate(4)) - Context("for queued ACKs", func() { - BeforeEach(func() { - tracker.ackQueued = true - }) + for i := 5; i <= 10; i++ { + require.NoError(t, tr.ReceivedPacket(protocol.PacketNumber(i), protocol.ECNNon, time.Now(), true)) + } + ack := tr.GetAckFrame(true) + require.NotNil(t, ack) + require.Equal(t, []wire.AckRange{{Smallest: 5, Largest: 10}}, ack.AckRanges) - It("generates a simple ACK frame", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(2))) - Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(1))) - Expect(ack.HasMissingRanges()).To(BeFalse()) - }) + tr.IgnoreBelow(7) - It("generates an ACK for packet number 0", func() { - Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(0))) - Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(0))) - Expect(ack.HasMissingRanges()).To(BeFalse()) - }) + require.NoError(t, tr.ReceivedPacket(11, protocol.ECNNon, time.Now(), true)) + require.NoError(t, tr.ReceivedPacket(12, protocol.ECNNon, time.Now(), true)) + ack = tr.GetAckFrame(true) + require.NotNil(t, ack) + require.Equal(t, []wire.AckRange{{Smallest: 7, Largest: 12}}, ack.AckRanges) - It("sets the delay time", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now().Add(-1337*time.Millisecond), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.DelayTime).To(BeNumerically("~", 1337*time.Millisecond, 50*time.Millisecond)) - }) - - It("uses a 0 delay time if the delay would be negative", func() { - Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now().Add(time.Hour), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.DelayTime).To(BeZero()) - }) - - It("saves the last sent ACK", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(tracker.lastAck).To(Equal(ack)) - Expect(tracker.ReceivedPacket(2, protocol.ECNNon, time.Now(), true)).To(Succeed()) - tracker.ackQueued = true - ack = tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(tracker.lastAck).To(Equal(ack)) - }) - - It("generates an ACK frame with missing packets", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ReceivedPacket(4, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(4))) - Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(1))) - Expect(ack.AckRanges).To(Equal([]wire.AckRange{ - {Smallest: 4, Largest: 4}, - {Smallest: 1, Largest: 1}, - })) - }) - - It("generates an ACK for packet number 0 and other packets", func() { - Expect(tracker.ReceivedPacket(0, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - Expect(tracker.ReceivedPacket(3, protocol.ECNNon, time.Now(), true)).To(Succeed()) - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(3))) - Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(0))) - Expect(ack.AckRanges).To(Equal([]wire.AckRange{ - {Smallest: 3, Largest: 3}, - {Smallest: 0, Largest: 1}, - })) - }) - - It("errors when called with an old packet", func() { - tracker.IgnoreBelow(7) - Expect(tracker.IsPotentiallyDuplicate(4)).To(BeTrue()) - Expect(tracker.ReceivedPacket(4, protocol.ECNNon, time.Now(), true)).To(MatchError("recevedPacketTracker BUG: ReceivedPacket called for old / duplicate packet 4")) - }) - - It("deletes packets from the packetHistory when a lower limit is set", func() { - for i := 1; i <= 12; i++ { - Expect(tracker.ReceivedPacket(protocol.PacketNumber(i), protocol.ECNNon, time.Now(), true)).To(Succeed()) - } - tracker.IgnoreBelow(7) - // check that the packets were deleted from the receivedPacketHistory by checking the values in an ACK frame - ack := tracker.GetAckFrame(true) - Expect(ack).ToNot(BeNil()) - Expect(ack.LargestAcked()).To(Equal(protocol.PacketNumber(12))) - Expect(ack.LowestAcked()).To(Equal(protocol.PacketNumber(7))) - Expect(ack.HasMissingRanges()).To(BeFalse()) - }) - - It("resets all counters needed for the ACK queueing decision when sending an ACK", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - tracker.ackAlarm = time.Now().Add(-time.Minute) - Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) - Expect(tracker.GetAlarmTimeout()).To(BeZero()) - Expect(tracker.ackElicitingPacketsReceivedSinceLastAck).To(BeZero()) - Expect(tracker.ackQueued).To(BeFalse()) - }) - - It("doesn't generate an ACK when none is queued and the timer is not set", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - tracker.ackQueued = false - tracker.ackAlarm = time.Time{} - Expect(tracker.GetAckFrame(true)).To(BeNil()) - }) - - It("doesn't generate an ACK when none is queued and the timer has not yet expired", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - tracker.ackQueued = false - tracker.ackAlarm = time.Now().Add(time.Minute) - Expect(tracker.GetAckFrame(true)).To(BeNil()) - }) - - It("generates an ACK when the timer has expired", func() { - Expect(tracker.ReceivedPacket(1, protocol.ECNNon, time.Now(), true)).To(Succeed()) - tracker.ackQueued = false - tracker.ackAlarm = time.Now().Add(-time.Minute) - Expect(tracker.GetAckFrame(true)).ToNot(BeNil()) - }) - }) - }) - }) -}) + // make sure that old packets are not accepted + require.ErrorContains(t, + tr.ReceivedPacket(4, protocol.ECNNon, time.Now(), true), + "recevedPacketTracker BUG: ReceivedPacket called for old / duplicate packet 4", + ) +}