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  })