github.com/quic-go/quic-go@v0.44.0/internal/ackhandler/received_packet_history_test.go (about)

     1  package ackhandler
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"sort"
     7  
     8  	"github.com/quic-go/quic-go/internal/protocol"
     9  	"github.com/quic-go/quic-go/internal/wire"
    10  
    11  	. "github.com/onsi/ginkgo/v2"
    12  	. "github.com/onsi/gomega"
    13  )
    14  
    15  var _ = Describe("receivedPacketHistory", func() {
    16  	var hist *receivedPacketHistory
    17  
    18  	BeforeEach(func() {
    19  		hist = newReceivedPacketHistory()
    20  	})
    21  
    22  	Context("ranges", func() {
    23  		It("adds the first packet", func() {
    24  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    25  			Expect(hist.ranges.Len()).To(Equal(1))
    26  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 4}))
    27  		})
    28  
    29  		It("doesn't care about duplicate packets", func() {
    30  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    31  			Expect(hist.ReceivedPacket(4)).To(BeFalse())
    32  			Expect(hist.ranges.Len()).To(Equal(1))
    33  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 4}))
    34  		})
    35  
    36  		It("adds a few consecutive packets", func() {
    37  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    38  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
    39  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
    40  			Expect(hist.ranges.Len()).To(Equal(1))
    41  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 6}))
    42  		})
    43  
    44  		It("doesn't care about a duplicate packet contained in an existing range", func() {
    45  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    46  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
    47  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
    48  			Expect(hist.ReceivedPacket(5)).To(BeFalse())
    49  			Expect(hist.ranges.Len()).To(Equal(1))
    50  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 6}))
    51  		})
    52  
    53  		It("extends a range at the front", func() {
    54  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    55  			Expect(hist.ReceivedPacket(3)).To(BeTrue())
    56  			Expect(hist.ranges.Len()).To(Equal(1))
    57  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 3, End: 4}))
    58  		})
    59  
    60  		It("creates a new range when a packet is lost", func() {
    61  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    62  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
    63  			Expect(hist.ranges.Len()).To(Equal(2))
    64  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 4}))
    65  			Expect(hist.ranges.Back().Value).To(Equal(interval{Start: 6, End: 6}))
    66  		})
    67  
    68  		It("creates a new range in between two ranges", func() {
    69  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    70  			Expect(hist.ReceivedPacket(10)).To(BeTrue())
    71  			Expect(hist.ranges.Len()).To(Equal(2))
    72  			Expect(hist.ReceivedPacket(7)).To(BeTrue())
    73  			Expect(hist.ranges.Len()).To(Equal(3))
    74  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 4}))
    75  			Expect(hist.ranges.Front().Next().Value).To(Equal(interval{Start: 7, End: 7}))
    76  			Expect(hist.ranges.Back().Value).To(Equal(interval{Start: 10, End: 10}))
    77  		})
    78  
    79  		It("creates a new range before an existing range for a belated packet", func() {
    80  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
    81  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    82  			Expect(hist.ranges.Len()).To(Equal(2))
    83  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 4}))
    84  			Expect(hist.ranges.Back().Value).To(Equal(interval{Start: 6, End: 6}))
    85  		})
    86  
    87  		It("extends a previous range at the end", func() {
    88  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    89  			Expect(hist.ReceivedPacket(7)).To(BeTrue())
    90  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
    91  			Expect(hist.ranges.Len()).To(Equal(2))
    92  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 5}))
    93  			Expect(hist.ranges.Back().Value).To(Equal(interval{Start: 7, End: 7}))
    94  		})
    95  
    96  		It("extends a range at the front", func() {
    97  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
    98  			Expect(hist.ReceivedPacket(7)).To(BeTrue())
    99  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
   100  			Expect(hist.ranges.Len()).To(Equal(2))
   101  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 4}))
   102  			Expect(hist.ranges.Back().Value).To(Equal(interval{Start: 6, End: 7}))
   103  		})
   104  
   105  		It("closes a range", func() {
   106  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
   107  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   108  			Expect(hist.ranges.Len()).To(Equal(2))
   109  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   110  			Expect(hist.ranges.Len()).To(Equal(1))
   111  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 6}))
   112  		})
   113  
   114  		It("closes a range in the middle", func() {
   115  			Expect(hist.ReceivedPacket(1)).To(BeTrue())
   116  			Expect(hist.ReceivedPacket(10)).To(BeTrue())
   117  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   118  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
   119  			Expect(hist.ranges.Len()).To(Equal(4))
   120  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   121  			Expect(hist.ranges.Len()).To(Equal(3))
   122  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 1, End: 1}))
   123  			Expect(hist.ranges.Front().Next().Value).To(Equal(interval{Start: 4, End: 6}))
   124  			Expect(hist.ranges.Back().Value).To(Equal(interval{Start: 10, End: 10}))
   125  		})
   126  	})
   127  
   128  	Context("deleting", func() {
   129  		It("does nothing when the history is empty", func() {
   130  			hist.DeleteBelow(5)
   131  			Expect(hist.ranges.Len()).To(BeZero())
   132  		})
   133  
   134  		It("deletes a range", func() {
   135  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   136  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   137  			Expect(hist.ReceivedPacket(10)).To(BeTrue())
   138  			hist.DeleteBelow(6)
   139  			Expect(hist.ranges.Len()).To(Equal(1))
   140  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 10, End: 10}))
   141  		})
   142  
   143  		It("deletes multiple ranges", func() {
   144  			Expect(hist.ReceivedPacket(1)).To(BeTrue())
   145  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   146  			Expect(hist.ReceivedPacket(10)).To(BeTrue())
   147  			hist.DeleteBelow(8)
   148  			Expect(hist.ranges.Len()).To(Equal(1))
   149  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 10, End: 10}))
   150  		})
   151  
   152  		It("adjusts a range, if packets are delete from an existing range", func() {
   153  			Expect(hist.ReceivedPacket(3)).To(BeTrue())
   154  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   155  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   156  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
   157  			Expect(hist.ReceivedPacket(7)).To(BeTrue())
   158  			hist.DeleteBelow(5)
   159  			Expect(hist.ranges.Len()).To(Equal(1))
   160  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 5, End: 7}))
   161  		})
   162  
   163  		It("adjusts a range, if only one packet remains in the range", func() {
   164  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   165  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   166  			Expect(hist.ReceivedPacket(10)).To(BeTrue())
   167  			hist.DeleteBelow(5)
   168  			Expect(hist.ranges.Len()).To(Equal(2))
   169  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 5, End: 5}))
   170  			Expect(hist.ranges.Back().Value).To(Equal(interval{Start: 10, End: 10}))
   171  		})
   172  
   173  		It("keeps a one-packet range, if deleting up to the packet directly below", func() {
   174  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   175  			hist.DeleteBelow(4)
   176  			Expect(hist.ranges.Len()).To(Equal(1))
   177  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 4, End: 4}))
   178  		})
   179  
   180  		It("doesn't add delayed packets below deleted ranges", func() {
   181  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   182  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   183  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
   184  			hist.DeleteBelow(5)
   185  			Expect(hist.ranges.Len()).To(Equal(1))
   186  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 5, End: 6}))
   187  			Expect(hist.ReceivedPacket(2)).To(BeFalse())
   188  			Expect(hist.ranges.Len()).To(Equal(1))
   189  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 5, End: 6}))
   190  		})
   191  
   192  		It("doesn't create more than MaxNumAckRanges ranges", func() {
   193  			for i := protocol.PacketNumber(0); i < protocol.MaxNumAckRanges; i++ {
   194  				Expect(hist.ReceivedPacket(2 * i)).To(BeTrue())
   195  			}
   196  			Expect(hist.ranges.Len()).To(Equal(protocol.MaxNumAckRanges))
   197  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 0, End: 0}))
   198  			hist.ReceivedPacket(2*protocol.MaxNumAckRanges + 1000)
   199  			// check that the oldest ACK range was deleted
   200  			Expect(hist.ranges.Len()).To(Equal(protocol.MaxNumAckRanges))
   201  			Expect(hist.ranges.Front().Value).To(Equal(interval{Start: 2, End: 2}))
   202  		})
   203  	})
   204  
   205  	Context("ACK range export", func() {
   206  		It("returns nil if there are no ranges", func() {
   207  			Expect(hist.AppendAckRanges(nil)).To(BeEmpty())
   208  		})
   209  
   210  		It("gets a single ACK range", func() {
   211  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   212  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   213  			ackRanges := hist.AppendAckRanges(nil)
   214  			Expect(ackRanges).To(HaveLen(1))
   215  			Expect(ackRanges[0]).To(Equal(wire.AckRange{Smallest: 4, Largest: 5}))
   216  		})
   217  
   218  		It("appends ACK ranges", func() {
   219  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   220  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   221  			ackRanges := hist.AppendAckRanges([]wire.AckRange{{Smallest: 1, Largest: 2}})
   222  			Expect(ackRanges).To(HaveLen(2))
   223  			Expect(ackRanges[0]).To(Equal(wire.AckRange{Smallest: 1, Largest: 2}))
   224  			Expect(ackRanges[1]).To(Equal(wire.AckRange{Smallest: 4, Largest: 5}))
   225  		})
   226  
   227  		It("gets multiple ACK ranges", func() {
   228  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   229  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   230  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
   231  			Expect(hist.ReceivedPacket(1)).To(BeTrue())
   232  			Expect(hist.ReceivedPacket(11)).To(BeTrue())
   233  			Expect(hist.ReceivedPacket(10)).To(BeTrue())
   234  			Expect(hist.ReceivedPacket(2)).To(BeTrue())
   235  			ackRanges := hist.AppendAckRanges(nil)
   236  			Expect(ackRanges).To(HaveLen(3))
   237  			Expect(ackRanges[0]).To(Equal(wire.AckRange{Smallest: 10, Largest: 11}))
   238  			Expect(ackRanges[1]).To(Equal(wire.AckRange{Smallest: 4, Largest: 6}))
   239  			Expect(ackRanges[2]).To(Equal(wire.AckRange{Smallest: 1, Largest: 2}))
   240  		})
   241  	})
   242  
   243  	Context("Getting the highest ACK range", func() {
   244  		It("returns the zero value if there are no ranges", func() {
   245  			Expect(hist.GetHighestAckRange()).To(BeZero())
   246  		})
   247  
   248  		It("gets a single ACK range", func() {
   249  			Expect(hist.ReceivedPacket(4)).To(BeTrue())
   250  			Expect(hist.ReceivedPacket(5)).To(BeTrue())
   251  			Expect(hist.GetHighestAckRange()).To(Equal(wire.AckRange{Smallest: 4, Largest: 5}))
   252  		})
   253  
   254  		It("gets the highest of multiple ACK ranges", func() {
   255  			Expect(hist.ReceivedPacket(3)).To(BeTrue())
   256  			Expect(hist.ReceivedPacket(6)).To(BeTrue())
   257  			Expect(hist.ReceivedPacket(7)).To(BeTrue())
   258  			Expect(hist.GetHighestAckRange()).To(Equal(wire.AckRange{Smallest: 6, Largest: 7}))
   259  		})
   260  	})
   261  
   262  	Context("duplicate detection", func() {
   263  		It("doesn't declare the first packet a duplicate", func() {
   264  			Expect(hist.IsPotentiallyDuplicate(5)).To(BeFalse())
   265  		})
   266  
   267  		It("detects a duplicate in a range", func() {
   268  			hist.ReceivedPacket(4)
   269  			hist.ReceivedPacket(5)
   270  			hist.ReceivedPacket(6)
   271  			Expect(hist.IsPotentiallyDuplicate(3)).To(BeFalse())
   272  			Expect(hist.IsPotentiallyDuplicate(4)).To(BeTrue())
   273  			Expect(hist.IsPotentiallyDuplicate(5)).To(BeTrue())
   274  			Expect(hist.IsPotentiallyDuplicate(6)).To(BeTrue())
   275  			Expect(hist.IsPotentiallyDuplicate(7)).To(BeFalse())
   276  		})
   277  
   278  		It("detects a duplicate in multiple ranges", func() {
   279  			hist.ReceivedPacket(4)
   280  			hist.ReceivedPacket(5)
   281  			hist.ReceivedPacket(8)
   282  			hist.ReceivedPacket(9)
   283  			Expect(hist.IsPotentiallyDuplicate(3)).To(BeFalse())
   284  			Expect(hist.IsPotentiallyDuplicate(4)).To(BeTrue())
   285  			Expect(hist.IsPotentiallyDuplicate(5)).To(BeTrue())
   286  			Expect(hist.IsPotentiallyDuplicate(6)).To(BeFalse())
   287  			Expect(hist.IsPotentiallyDuplicate(7)).To(BeFalse())
   288  			Expect(hist.IsPotentiallyDuplicate(8)).To(BeTrue())
   289  			Expect(hist.IsPotentiallyDuplicate(9)).To(BeTrue())
   290  			Expect(hist.IsPotentiallyDuplicate(10)).To(BeFalse())
   291  		})
   292  
   293  		It("says a packet is a potentially duplicate if the ranges were already deleted", func() {
   294  			hist.ReceivedPacket(4)
   295  			hist.ReceivedPacket(5)
   296  			hist.ReceivedPacket(8)
   297  			hist.ReceivedPacket(9)
   298  			hist.ReceivedPacket(11)
   299  			hist.DeleteBelow(8)
   300  			Expect(hist.IsPotentiallyDuplicate(3)).To(BeTrue())
   301  			Expect(hist.IsPotentiallyDuplicate(4)).To(BeTrue())
   302  			Expect(hist.IsPotentiallyDuplicate(5)).To(BeTrue())
   303  			Expect(hist.IsPotentiallyDuplicate(6)).To(BeTrue())
   304  			Expect(hist.IsPotentiallyDuplicate(7)).To(BeTrue())
   305  			Expect(hist.IsPotentiallyDuplicate(8)).To(BeTrue())
   306  			Expect(hist.IsPotentiallyDuplicate(9)).To(BeTrue())
   307  			Expect(hist.IsPotentiallyDuplicate(10)).To(BeFalse())
   308  			Expect(hist.IsPotentiallyDuplicate(11)).To(BeTrue())
   309  			Expect(hist.IsPotentiallyDuplicate(12)).To(BeFalse())
   310  		})
   311  	})
   312  
   313  	Context("randomized receiving", func() {
   314  		It("receiving packets in a random order, with gaps", func() {
   315  			packets := make(map[protocol.PacketNumber]int)
   316  			// Make sure we never end up with more than protocol.MaxNumAckRanges ACK ranges, even
   317  			// when we're receiving packets in a random order.
   318  			const num = 2 * protocol.MaxNumAckRanges
   319  			numLostPackets := rand.Intn(protocol.MaxNumAckRanges)
   320  			numRcvdPackets := num - numLostPackets
   321  
   322  			for i := 0; i < num; i++ {
   323  				packets[protocol.PacketNumber(i)] = 0
   324  			}
   325  			lostPackets := make([]protocol.PacketNumber, 0, numLostPackets)
   326  			for len(lostPackets) < numLostPackets {
   327  				p := protocol.PacketNumber(rand.Intn(num))
   328  				if _, ok := packets[p]; ok {
   329  					lostPackets = append(lostPackets, p)
   330  					delete(packets, p)
   331  				}
   332  			}
   333  			sort.Slice(lostPackets, func(i, j int) bool { return lostPackets[i] < lostPackets[j] })
   334  			fmt.Fprintf(GinkgoWriter, "Losing packets: %v\n", lostPackets)
   335  
   336  			ordered := make([]protocol.PacketNumber, 0, numRcvdPackets)
   337  			for p := range packets {
   338  				ordered = append(ordered, p)
   339  			}
   340  			rand.Shuffle(len(ordered), func(i, j int) { ordered[i], ordered[j] = ordered[j], ordered[i] })
   341  
   342  			fmt.Fprintf(GinkgoWriter, "Receiving packets: %v\n", ordered)
   343  			for i, p := range ordered {
   344  				Expect(hist.ReceivedPacket(p)).To(BeTrue())
   345  				// sometimes receive a duplicate
   346  				if i > 0 && rand.Int()%5 == 0 {
   347  					Expect(hist.ReceivedPacket(ordered[rand.Intn(i)])).To(BeFalse())
   348  				}
   349  			}
   350  			var counter int
   351  			ackRanges := hist.AppendAckRanges(nil)
   352  			fmt.Fprintf(GinkgoWriter, "ACK ranges: %v\n", ackRanges)
   353  			Expect(len(ackRanges)).To(BeNumerically("<=", numLostPackets+1))
   354  			for _, ackRange := range ackRanges {
   355  				for p := ackRange.Smallest; p <= ackRange.Largest; p++ {
   356  					counter++
   357  					Expect(packets).To(HaveKey(p))
   358  				}
   359  			}
   360  			Expect(counter).To(Equal(numRcvdPackets))
   361  		})
   362  	})
   363  })