github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/ackhandler/packet_number_generator_test.go (about) 1 package ackhandler 2 3 import ( 4 "fmt" 5 "math" 6 7 "github.com/metacubex/quic-go/internal/protocol" 8 9 . "github.com/onsi/ginkgo/v2" 10 . "github.com/onsi/gomega" 11 ) 12 13 var _ = Describe("Sequential Packet Number Generator", func() { 14 It("generates sequential packet numbers", func() { 15 const initialPN protocol.PacketNumber = 123 16 png := newSequentialPacketNumberGenerator(initialPN) 17 18 for i := initialPN; i < initialPN+1000; i++ { 19 Expect(png.Peek()).To(Equal(i)) 20 Expect(png.Peek()).To(Equal(i)) 21 skipNext, pn := png.Pop() 22 Expect(skipNext).To(BeFalse()) 23 Expect(pn).To(Equal(i)) 24 } 25 }) 26 }) 27 28 var _ = Describe("Skipping Packet Number Generator", func() { 29 const initialPN protocol.PacketNumber = 8 30 const initialPeriod protocol.PacketNumber = 25 31 const maxPeriod protocol.PacketNumber = 300 32 33 It("uses a maximum period that is sufficiently small such that using a 32-bit random number is ok", func() { 34 Expect(2 * protocol.SkipPacketMaxPeriod).To(BeNumerically("<", math.MaxInt32)) 35 }) 36 37 It("can be initialized to return any first packet number", func() { 38 png := newSkippingPacketNumberGenerator(12345, initialPeriod, maxPeriod) 39 _, pn := png.Pop() 40 Expect(pn).To(Equal(protocol.PacketNumber(12345))) 41 }) 42 43 It("allows peeking", func() { 44 png := newSkippingPacketNumberGenerator(initialPN, initialPeriod, maxPeriod).(*skippingPacketNumberGenerator) 45 Expect(png.Peek()).To(Equal(initialPN)) 46 Expect(png.Peek()).To(Equal(initialPN)) 47 skipped, pn := png.Pop() 48 Expect(pn).To(Equal(initialPN)) 49 next := initialPN + 1 50 if skipped { 51 next++ 52 } 53 Expect(png.Peek()).To(Equal(next)) 54 Expect(png.Peek()).To(Equal(next)) 55 }) 56 57 It("skips a packet number", func() { 58 png := newSkippingPacketNumberGenerator(initialPN, initialPeriod, maxPeriod) 59 var last protocol.PacketNumber 60 var skipped bool 61 for i := 0; i < int(maxPeriod); i++ { 62 didSkip, num := png.Pop() 63 if didSkip { 64 skipped = true 65 _, nextNum := png.Pop() 66 Expect(nextNum).To(Equal(num + 1)) 67 break 68 } 69 if i != 0 { 70 Expect(num).To(Equal(last + 1)) 71 } 72 last = num 73 } 74 Expect(skipped).To(BeTrue()) 75 }) 76 77 It("generates a new packet number to skip", func() { 78 const rep = 2500 79 periods := make([][]protocol.PacketNumber, rep) 80 expectedPeriods := []protocol.PacketNumber{25, 50, 100, 200, 300, 300, 300} 81 82 for i := 0; i < rep; i++ { 83 png := newSkippingPacketNumberGenerator(initialPN, initialPeriod, maxPeriod) 84 lastSkip := initialPN 85 for len(periods[i]) < len(expectedPeriods) { 86 skipNext, next := png.Pop() 87 if skipNext { 88 skipped := next + 1 89 Expect(skipped).To(BeNumerically(">", lastSkip+1)) 90 periods[i] = append(periods[i], skipped-lastSkip-1) 91 lastSkip = skipped 92 } 93 } 94 } 95 96 for j := 0; j < len(expectedPeriods); j++ { 97 var average float64 98 for i := 0; i < rep; i++ { 99 average += float64(periods[i][j]) / float64(len(periods)) 100 } 101 fmt.Fprintf(GinkgoWriter, "Period %d: %.2f (expected %d)\n", j, average, expectedPeriods[j]) 102 tolerance := protocol.PacketNumber(5) 103 if t := expectedPeriods[j] / 10; t > tolerance { 104 tolerance = t 105 } 106 Expect(average).To(BeNumerically("~", expectedPeriods[j]+1 /* we never skip two packet numbers at the same time */, tolerance)) 107 } 108 }) 109 })