github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/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/metacubex/quic-go/internal/protocol" 9 "github.com/metacubex/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 })