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