github.com/tumi8/quic-go@v0.37.4-tum/noninternal/flowcontrol/connection_flow_controller_test.go (about) 1 package flowcontrol 2 3 import ( 4 "time" 5 6 "github.com/tumi8/quic-go/noninternal/protocol" 7 "github.com/tumi8/quic-go/noninternal/utils" 8 . "github.com/onsi/ginkgo/v2" 9 . "github.com/onsi/gomega" 10 ) 11 12 var _ = Describe("Connection Flow controller", func() { 13 var ( 14 controller *connectionFlowController 15 queuedWindowUpdate bool 16 ) 17 18 // update the congestion such that it returns a given value for the smoothed RTT 19 setRtt := func(t time.Duration) { 20 controller.rttStats.UpdateRTT(t, 0, time.Now()) 21 Expect(controller.rttStats.SmoothedRTT()).To(Equal(t)) // make sure it worked 22 } 23 24 BeforeEach(func() { 25 queuedWindowUpdate = false 26 controller = &connectionFlowController{} 27 controller.rttStats = &utils.RTTStats{} 28 controller.logger = utils.DefaultLogger 29 controller.queueWindowUpdate = func() { queuedWindowUpdate = true } 30 controller.allowWindowIncrease = func(protocol.ByteCount) bool { return true } 31 }) 32 33 Context("Constructor", func() { 34 rttStats := &utils.RTTStats{} 35 36 It("sets the send and receive windows", func() { 37 receiveWindow := protocol.ByteCount(2000) 38 maxReceiveWindow := protocol.ByteCount(3000) 39 40 fc := NewConnectionFlowController( 41 receiveWindow, 42 maxReceiveWindow, 43 nil, 44 func(protocol.ByteCount) bool { return true }, 45 rttStats, 46 utils.DefaultLogger).(*connectionFlowController) 47 Expect(fc.receiveWindow).To(Equal(receiveWindow)) 48 Expect(fc.maxReceiveWindowSize).To(Equal(maxReceiveWindow)) 49 }) 50 }) 51 52 Context("receive flow control", func() { 53 It("increases the highestReceived by a given window size", func() { 54 controller.highestReceived = 1337 55 controller.IncrementHighestReceived(123) 56 Expect(controller.highestReceived).To(Equal(protocol.ByteCount(1337 + 123))) 57 }) 58 59 Context("getting window updates", func() { 60 BeforeEach(func() { 61 controller.receiveWindow = 100 62 controller.receiveWindowSize = 60 63 controller.maxReceiveWindowSize = 1000 64 controller.bytesRead = 100 - 60 65 }) 66 67 It("queues window updates", func() { 68 controller.AddBytesRead(1) 69 Expect(queuedWindowUpdate).To(BeFalse()) 70 controller.AddBytesRead(29) 71 Expect(queuedWindowUpdate).To(BeTrue()) 72 Expect(controller.GetWindowUpdate()).ToNot(BeZero()) 73 queuedWindowUpdate = false 74 controller.AddBytesRead(1) 75 Expect(queuedWindowUpdate).To(BeFalse()) 76 }) 77 78 It("gets a window update", func() { 79 windowSize := controller.receiveWindowSize 80 oldOffset := controller.bytesRead 81 dataRead := windowSize/2 - 1 // make sure not to trigger auto-tuning 82 controller.AddBytesRead(dataRead) 83 offset := controller.GetWindowUpdate() 84 Expect(offset).To(Equal(oldOffset + dataRead + 60)) 85 }) 86 87 It("auto-tunes the window", func() { 88 var allowed protocol.ByteCount 89 controller.allowWindowIncrease = func(size protocol.ByteCount) bool { 90 allowed = size 91 return true 92 } 93 oldOffset := controller.bytesRead 94 oldWindowSize := controller.receiveWindowSize 95 rtt := scaleDuration(20 * time.Millisecond) 96 setRtt(rtt) 97 controller.epochStartTime = time.Now().Add(-time.Millisecond) 98 controller.epochStartOffset = oldOffset 99 dataRead := oldWindowSize/2 + 1 100 controller.AddBytesRead(dataRead) 101 offset := controller.GetWindowUpdate() 102 newWindowSize := controller.receiveWindowSize 103 Expect(newWindowSize).To(Equal(2 * oldWindowSize)) 104 Expect(offset).To(Equal(oldOffset + dataRead + newWindowSize)) 105 Expect(allowed).To(Equal(oldWindowSize)) 106 }) 107 108 It("doesn't auto-tune the window if it's not allowed", func() { 109 controller.allowWindowIncrease = func(protocol.ByteCount) bool { return false } 110 oldOffset := controller.bytesRead 111 oldWindowSize := controller.receiveWindowSize 112 rtt := scaleDuration(20 * time.Millisecond) 113 setRtt(rtt) 114 controller.epochStartTime = time.Now().Add(-time.Millisecond) 115 controller.epochStartOffset = oldOffset 116 dataRead := oldWindowSize/2 + 1 117 controller.AddBytesRead(dataRead) 118 offset := controller.GetWindowUpdate() 119 newWindowSize := controller.receiveWindowSize 120 Expect(newWindowSize).To(Equal(oldWindowSize)) 121 Expect(offset).To(Equal(oldOffset + dataRead + newWindowSize)) 122 }) 123 }) 124 }) 125 126 Context("setting the minimum window size", func() { 127 var ( 128 oldWindowSize protocol.ByteCount 129 receiveWindow protocol.ByteCount = 10000 130 receiveWindowSize protocol.ByteCount = 1000 131 ) 132 133 BeforeEach(func() { 134 controller.receiveWindow = receiveWindow 135 controller.receiveWindowSize = receiveWindowSize 136 oldWindowSize = controller.receiveWindowSize 137 controller.maxReceiveWindowSize = 3000 138 }) 139 140 It("sets the minimum window window size", func() { 141 controller.EnsureMinimumWindowSize(1800) 142 Expect(controller.receiveWindowSize).To(Equal(protocol.ByteCount(1800))) 143 }) 144 145 It("doesn't reduce the window window size", func() { 146 controller.EnsureMinimumWindowSize(1) 147 Expect(controller.receiveWindowSize).To(Equal(oldWindowSize)) 148 }) 149 150 It("doesn't increase the window size beyond the maxReceiveWindowSize", func() { 151 max := controller.maxReceiveWindowSize 152 controller.EnsureMinimumWindowSize(2 * max) 153 Expect(controller.receiveWindowSize).To(Equal(max)) 154 }) 155 156 It("starts a new epoch after the window size was increased", func() { 157 controller.EnsureMinimumWindowSize(1912) 158 Expect(controller.epochStartTime).To(BeTemporally("~", time.Now(), 100*time.Millisecond)) 159 }) 160 }) 161 162 Context("resetting", func() { 163 It("resets", func() { 164 const initialWindow protocol.ByteCount = 1337 165 controller.UpdateSendWindow(initialWindow) 166 controller.AddBytesSent(1000) 167 Expect(controller.SendWindowSize()).To(Equal(initialWindow - 1000)) 168 Expect(controller.Reset()).To(Succeed()) 169 Expect(controller.SendWindowSize()).To(Equal(initialWindow)) 170 }) 171 172 It("says if is blocked after resetting", func() { 173 const initialWindow protocol.ByteCount = 1337 174 controller.UpdateSendWindow(initialWindow) 175 controller.AddBytesSent(initialWindow) 176 blocked, _ := controller.IsNewlyBlocked() 177 Expect(blocked).To(BeTrue()) 178 Expect(controller.Reset()).To(Succeed()) 179 controller.AddBytesSent(initialWindow) 180 blocked, blockedAt := controller.IsNewlyBlocked() 181 Expect(blocked).To(BeTrue()) 182 Expect(blockedAt).To(Equal(initialWindow)) 183 }) 184 }) 185 })