github.com/tumi8/quic-go@v0.37.4-tum/noninternal/ackhandler/received_packet_history_test.go (about)

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