github.com/daeuniverse/quic-go@v0.0.0-20240413031024-943f218e0810/internal/ackhandler/sent_packet_history_test.go (about) 1 package ackhandler 2 3 import ( 4 "errors" 5 "time" 6 7 "github.com/daeuniverse/quic-go/internal/protocol" 8 9 . "github.com/onsi/ginkgo/v2" 10 . "github.com/onsi/gomega" 11 ) 12 13 var _ = Describe("SentPacketHistory", func() { 14 var hist *sentPacketHistory 15 16 expectInHistory := func(expected []protocol.PacketNumber) { 17 pns := make([]protocol.PacketNumber, 0, len(expected)) 18 for _, p := range hist.packets { 19 if p != nil && !p.skippedPacket { 20 pns = append(pns, p.PacketNumber) 21 } 22 } 23 if len(expected) == 0 { 24 Expect(pns).To(BeEmpty()) 25 return 26 } 27 Expect(pns).To(Equal(expected)) 28 } 29 30 expectSkippedInHistory := func(expected []protocol.PacketNumber) { 31 pns := make([]protocol.PacketNumber, 0, len(expected)) 32 for _, p := range hist.packets { 33 if p != nil && p.skippedPacket { 34 pns = append(pns, p.PacketNumber) 35 } 36 } 37 if len(expected) == 0 { 38 Expect(pns).To(BeEmpty()) 39 return 40 } 41 Expect(pns).To(Equal(expected)) 42 } 43 44 BeforeEach(func() { 45 hist = newSentPacketHistory() 46 }) 47 48 It("saves sent packets", func() { 49 hist.SentAckElicitingPacket(&packet{PacketNumber: 0}) 50 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 51 hist.SentAckElicitingPacket(&packet{PacketNumber: 2}) 52 expectInHistory([]protocol.PacketNumber{0, 1, 2}) 53 expectSkippedInHistory(nil) 54 }) 55 56 It("saves non-ack-eliciting packets", func() { 57 now := time.Now() 58 hist.SentNonAckElicitingPacket(0) 59 hist.SentAckElicitingPacket(&packet{PacketNumber: 1, SendTime: now}) 60 hist.SentNonAckElicitingPacket(2) 61 hist.SentAckElicitingPacket(&packet{PacketNumber: 3, SendTime: now}) 62 expectInHistory([]protocol.PacketNumber{1, 3}) 63 }) 64 65 It("saves sent packets, with skipped packet number", func() { 66 hist.SkippedPacket(0) 67 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 68 hist.SkippedPacket(2) 69 hist.SentAckElicitingPacket(&packet{PacketNumber: 3}) 70 hist.SentAckElicitingPacket(&packet{PacketNumber: 4}) 71 expectInHistory([]protocol.PacketNumber{1, 3, 4}) 72 expectSkippedInHistory([]protocol.PacketNumber{0, 2}) 73 }) 74 75 It("doesn't save non-ack-eliciting packets", func() { 76 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 77 hist.SkippedPacket(2) 78 hist.SentNonAckElicitingPacket(3) 79 hist.SentAckElicitingPacket(&packet{PacketNumber: 4}) 80 expectInHistory([]protocol.PacketNumber{1, 4}) 81 }) 82 83 It("gets the length", func() { 84 hist.SentAckElicitingPacket(&packet{PacketNumber: 0}) 85 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 86 hist.SentAckElicitingPacket(&packet{PacketNumber: 2}) 87 Expect(hist.Len()).To(Equal(3)) 88 }) 89 90 Context("getting the first outstanding packet", func() { 91 It("gets nil, if there are no packets", func() { 92 Expect(hist.FirstOutstanding()).To(BeNil()) 93 }) 94 95 It("gets the first outstanding packet", func() { 96 hist.SentAckElicitingPacket(&packet{PacketNumber: 2}) 97 hist.SentAckElicitingPacket(&packet{PacketNumber: 3}) 98 front := hist.FirstOutstanding() 99 Expect(front).ToNot(BeNil()) 100 Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(2))) 101 hist.Remove(2) 102 front = hist.FirstOutstanding() 103 Expect(front).ToNot(BeNil()) 104 Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(3))) 105 }) 106 107 It("doesn't regard path MTU packets as outstanding", func() { 108 hist.SentAckElicitingPacket(&packet{PacketNumber: 2}) 109 hist.SkippedPacket(3) 110 hist.SentAckElicitingPacket(&packet{PacketNumber: 4, IsPathMTUProbePacket: true}) 111 front := hist.FirstOutstanding() 112 Expect(front).ToNot(BeNil()) 113 Expect(front.PacketNumber).To(Equal(protocol.PacketNumber(2))) 114 }) 115 }) 116 117 It("removes packets", func() { 118 hist.SentAckElicitingPacket(&packet{PacketNumber: 0}) 119 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 120 hist.SentAckElicitingPacket(&packet{PacketNumber: 2}) 121 hist.SentAckElicitingPacket(&packet{PacketNumber: 3}) 122 Expect(hist.Remove(2)).To(Succeed()) 123 expectInHistory([]protocol.PacketNumber{0, 1, 3}) 124 }) 125 126 It("also removes skipped packets before the removed packet", func() { 127 hist.SkippedPacket(0) 128 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 129 hist.SkippedPacket(2) 130 hist.SkippedPacket(3) 131 hist.SentAckElicitingPacket(&packet{PacketNumber: 4}) 132 expectSkippedInHistory([]protocol.PacketNumber{0, 2, 3}) 133 Expect(hist.Remove(4)).To(Succeed()) 134 expectSkippedInHistory([]protocol.PacketNumber{0}) 135 expectInHistory([]protocol.PacketNumber{1}) 136 Expect(hist.Remove(1)).To(Succeed()) 137 expectInHistory(nil) 138 expectSkippedInHistory(nil) 139 }) 140 141 It("panics on non-sequential packet number use", func() { 142 hist.SentAckElicitingPacket(&packet{PacketNumber: 100}) 143 Expect(func() { hist.SentAckElicitingPacket(&packet{PacketNumber: 102}) }).To(Panic()) 144 }) 145 146 It("removes and adds packets", func() { 147 hist.SentAckElicitingPacket(&packet{PacketNumber: 0}) 148 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 149 hist.SkippedPacket(2) 150 hist.SkippedPacket(3) 151 hist.SentAckElicitingPacket(&packet{PacketNumber: 4}) 152 hist.SkippedPacket(5) 153 hist.SentAckElicitingPacket(&packet{PacketNumber: 6}) 154 Expect(hist.Remove(0)).To(Succeed()) 155 Expect(hist.Remove(1)).To(Succeed()) 156 hist.SentAckElicitingPacket(&packet{PacketNumber: 7}) 157 expectInHistory([]protocol.PacketNumber{4, 6, 7}) 158 }) 159 160 It("removes the last packet, then adds more", func() { 161 hist.SentAckElicitingPacket(&packet{PacketNumber: 0}) 162 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 163 Expect(hist.Remove(0)).To(Succeed()) 164 Expect(hist.Remove(1)).To(Succeed()) 165 expectInHistory([]protocol.PacketNumber{}) 166 hist.SentAckElicitingPacket(&packet{PacketNumber: 2}) 167 expectInHistory([]protocol.PacketNumber{2}) 168 Expect(hist.Remove(2)).To(Succeed()) 169 expectInHistory(nil) 170 }) 171 172 It("errors when trying to remove a non existing packet", func() { 173 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 174 Expect(hist.Remove(2)).To(MatchError("packet 2 not found in sent packet history")) 175 }) 176 177 Context("iterating", func() { 178 BeforeEach(func() { 179 hist.SkippedPacket(0) 180 hist.SentAckElicitingPacket(&packet{PacketNumber: 1}) 181 hist.SkippedPacket(2) 182 hist.SkippedPacket(3) 183 hist.SentAckElicitingPacket(&packet{PacketNumber: 4}) 184 hist.SkippedPacket(5) 185 hist.SkippedPacket(6) 186 hist.SkippedPacket(7) 187 hist.SentAckElicitingPacket(&packet{PacketNumber: 8}) 188 }) 189 190 It("iterates over all packets", func() { 191 var iterations []protocol.PacketNumber 192 Expect(hist.Iterate(func(p *packet) (bool, error) { 193 if p.skippedPacket { 194 return true, nil 195 } 196 iterations = append(iterations, p.PacketNumber) 197 return true, nil 198 })).To(Succeed()) 199 Expect(iterations).To(Equal([]protocol.PacketNumber{1, 4, 8})) 200 }) 201 202 It("also iterates over skipped packets", func() { 203 var packets, skippedPackets, allPackets []protocol.PacketNumber 204 Expect(hist.Iterate(func(p *packet) (bool, error) { 205 if p.skippedPacket { 206 skippedPackets = append(skippedPackets, p.PacketNumber) 207 } else { 208 packets = append(packets, p.PacketNumber) 209 } 210 allPackets = append(allPackets, p.PacketNumber) 211 return true, nil 212 })).To(Succeed()) 213 Expect(packets).To(Equal([]protocol.PacketNumber{1, 4, 8})) 214 Expect(skippedPackets).To(Equal([]protocol.PacketNumber{0, 2, 3, 5, 6, 7})) 215 Expect(allPackets).To(Equal([]protocol.PacketNumber{0, 1, 2, 3, 4, 5, 6, 7, 8})) 216 }) 217 218 It("stops iterating", func() { 219 var iterations []protocol.PacketNumber 220 Expect(hist.Iterate(func(p *packet) (bool, error) { 221 if p.skippedPacket { 222 return true, nil 223 } 224 iterations = append(iterations, p.PacketNumber) 225 return p.PacketNumber != 4, nil 226 })).To(Succeed()) 227 Expect(iterations).To(Equal([]protocol.PacketNumber{1, 4})) 228 }) 229 230 It("returns the error", func() { 231 testErr := errors.New("test error") 232 var iterations []protocol.PacketNumber 233 Expect(hist.Iterate(func(p *packet) (bool, error) { 234 if p.skippedPacket { 235 return true, nil 236 } 237 iterations = append(iterations, p.PacketNumber) 238 if p.PacketNumber == 4 { 239 return false, testErr 240 } 241 return true, nil 242 })).To(MatchError(testErr)) 243 Expect(iterations).To(Equal([]protocol.PacketNumber{1, 4})) 244 }) 245 246 It("doesn't iterate over deleted packets", func() { 247 hist.Remove(4) 248 var iterations []protocol.PacketNumber 249 Expect(hist.Iterate(func(p *packet) (bool, error) { 250 if p.skippedPacket { 251 return true, nil 252 } 253 iterations = append(iterations, p.PacketNumber) 254 if p.PacketNumber == 4 { 255 Expect(hist.Remove(4)).To(Succeed()) 256 } 257 return true, nil 258 })).To(Succeed()) 259 Expect(iterations).To(Equal([]protocol.PacketNumber{1, 8})) 260 }) 261 262 It("allows deletions", func() { 263 var iterations []protocol.PacketNumber 264 Expect(hist.Iterate(func(p *packet) (bool, error) { 265 if p.skippedPacket { 266 return true, nil 267 } 268 iterations = append(iterations, p.PacketNumber) 269 if p.PacketNumber == 4 { 270 Expect(hist.Remove(4)).To(Succeed()) 271 } 272 return true, nil 273 })).To(Succeed()) 274 expectInHistory([]protocol.PacketNumber{1, 8}) 275 Expect(iterations).To(Equal([]protocol.PacketNumber{1, 4, 8})) 276 }) 277 }) 278 279 Context("outstanding packets", func() { 280 It("says if it has outstanding packets", func() { 281 Expect(hist.HasOutstandingPackets()).To(BeFalse()) 282 hist.SentAckElicitingPacket(&packet{EncryptionLevel: protocol.Encryption1RTT, PacketNumber: 0}) 283 Expect(hist.HasOutstandingPackets()).To(BeTrue()) 284 }) 285 286 It("accounts for deleted packets", func() { 287 hist.SentAckElicitingPacket(&packet{ 288 PacketNumber: 10, 289 EncryptionLevel: protocol.Encryption1RTT, 290 }) 291 Expect(hist.HasOutstandingPackets()).To(BeTrue()) 292 Expect(hist.Remove(10)).To(Succeed()) 293 Expect(hist.HasOutstandingPackets()).To(BeFalse()) 294 }) 295 296 It("counts the number of packets", func() { 297 hist.SentAckElicitingPacket(&packet{ 298 PacketNumber: 10, 299 EncryptionLevel: protocol.Encryption1RTT, 300 }) 301 hist.SentAckElicitingPacket(&packet{ 302 PacketNumber: 11, 303 EncryptionLevel: protocol.Encryption1RTT, 304 }) 305 Expect(hist.Remove(11)).To(Succeed()) 306 Expect(hist.HasOutstandingPackets()).To(BeTrue()) 307 Expect(hist.Remove(10)).To(Succeed()) 308 Expect(hist.HasOutstandingPackets()).To(BeFalse()) 309 }) 310 }) 311 })