Files
quic-go/internal/flowcontrol/connection_flow_controller_test.go
Marten Seemann 741dc28d74 move the RTTStats to the utils package
The RTTStats are used by the logging package. In order to instrument the
congestion package, the RTTStats can't be part of that package any more
(to avoid an import loop).
2020-07-23 11:53:08 +07:00

133 lines
4.2 KiB
Go

package flowcontrol
import (
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Connection Flow controller", func() {
var (
controller *connectionFlowController
queuedWindowUpdate bool
)
// update the congestion such that it returns a given value for the smoothed RTT
setRtt := func(t time.Duration) {
controller.rttStats.UpdateRTT(t, 0, time.Now())
Expect(controller.rttStats.SmoothedRTT()).To(Equal(t)) // make sure it worked
}
BeforeEach(func() {
queuedWindowUpdate = false
controller = &connectionFlowController{}
controller.rttStats = &utils.RTTStats{}
controller.logger = utils.DefaultLogger
controller.queueWindowUpdate = func() { queuedWindowUpdate = true }
})
Context("Constructor", func() {
rttStats := &utils.RTTStats{}
It("sets the send and receive windows", func() {
receiveWindow := protocol.ByteCount(2000)
maxReceiveWindow := protocol.ByteCount(3000)
fc := NewConnectionFlowController(receiveWindow, maxReceiveWindow, nil, rttStats, utils.DefaultLogger).(*connectionFlowController)
Expect(fc.receiveWindow).To(Equal(receiveWindow))
Expect(fc.maxReceiveWindowSize).To(Equal(maxReceiveWindow))
})
})
Context("receive flow control", func() {
It("increases the highestReceived by a given window size", func() {
controller.highestReceived = 1337
controller.IncrementHighestReceived(123)
Expect(controller.highestReceived).To(Equal(protocol.ByteCount(1337 + 123)))
})
Context("getting window updates", func() {
BeforeEach(func() {
controller.receiveWindow = 100
controller.receiveWindowSize = 60
controller.maxReceiveWindowSize = 1000
controller.bytesRead = 100 - 60
})
It("queues window updates", func() {
controller.AddBytesRead(1)
Expect(queuedWindowUpdate).To(BeFalse())
controller.AddBytesRead(29)
Expect(queuedWindowUpdate).To(BeTrue())
Expect(controller.GetWindowUpdate()).ToNot(BeZero())
queuedWindowUpdate = false
controller.AddBytesRead(1)
Expect(queuedWindowUpdate).To(BeFalse())
})
It("gets a window update", func() {
windowSize := controller.receiveWindowSize
oldOffset := controller.bytesRead
dataRead := windowSize/2 - 1 // make sure not to trigger auto-tuning
controller.AddBytesRead(dataRead)
offset := controller.GetWindowUpdate()
Expect(offset).To(Equal(oldOffset + dataRead + 60))
})
It("autotunes the window", func() {
oldOffset := controller.bytesRead
oldWindowSize := controller.receiveWindowSize
rtt := scaleDuration(20 * time.Millisecond)
setRtt(rtt)
controller.epochStartTime = time.Now().Add(-time.Millisecond)
controller.epochStartOffset = oldOffset
dataRead := oldWindowSize/2 + 1
controller.AddBytesRead(dataRead)
offset := controller.GetWindowUpdate()
newWindowSize := controller.receiveWindowSize
Expect(newWindowSize).To(Equal(2 * oldWindowSize))
Expect(offset).To(Equal(oldOffset + dataRead + newWindowSize))
})
})
})
Context("setting the minimum window size", func() {
var (
oldWindowSize protocol.ByteCount
receiveWindow protocol.ByteCount = 10000
receiveWindowSize protocol.ByteCount = 1000
)
BeforeEach(func() {
controller.receiveWindow = receiveWindow
controller.receiveWindowSize = receiveWindowSize
oldWindowSize = controller.receiveWindowSize
controller.maxReceiveWindowSize = 3000
})
It("sets the minimum window window size", func() {
controller.EnsureMinimumWindowSize(1800)
Expect(controller.receiveWindowSize).To(Equal(protocol.ByteCount(1800)))
})
It("doesn't reduce the window window size", func() {
controller.EnsureMinimumWindowSize(1)
Expect(controller.receiveWindowSize).To(Equal(oldWindowSize))
})
It("doens't increase the window size beyond the maxReceiveWindowSize", func() {
max := controller.maxReceiveWindowSize
controller.EnsureMinimumWindowSize(2 * max)
Expect(controller.receiveWindowSize).To(Equal(max))
})
It("starts a new epoch after the window size was increased", func() {
controller.EnsureMinimumWindowSize(1912)
Expect(controller.epochStartTime).To(BeTemporally("~", time.Now(), 100*time.Millisecond))
})
})
})