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