ackhandler: migrate received packet tracker tests away from Ginkgo (#4864)

This commit is contained in:
Marten Seemann
2025-01-12 05:28:26 -08:00
committed by GitHub
parent 9d1c1d4e7f
commit 3f0f399540

View File

@@ -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",
)
}