Files
quic-go/handshake/connection_parameters_manager_test.go
2016-05-18 14:03:04 +07:00

229 lines
8.1 KiB
Go

package handshake
import (
"time"
"github.com/lucas-clemente/quic-go/protocol"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("ConnectionsParameterManager", func() {
var cpm *ConnectionParametersManager
BeforeEach(func() {
cpm = NewConnectionParamatersManager()
})
It("stores and retrieves a value", func() {
tcid := []byte{0x13, 0x37}
values := map[Tag][]byte{
TagTCID: tcid,
}
cpm.SetFromMap(values)
val, err := cpm.getRawValue(TagTCID)
Expect(err).ToNot(HaveOccurred())
Expect(val).To(Equal(tcid))
})
It("returns an error for a tag that is not set", func() {
_, err := cpm.getRawValue(TagKEXS)
Expect(err).To(MatchError(errTagNotInConnectionParameterMap))
})
Context("SHLO", func() {
It("returns all parameters necessary for the SHLO", func() {
entryMap := cpm.GetSHLOMap()
Expect(entryMap).To(HaveKey(TagICSL))
Expect(entryMap).To(HaveKey(TagMSPC))
})
It("sets the stream-level flow control windows in SHLO", func() {
cpm.receiveStreamFlowControlWindow = 0xDEADBEEF
entryMap := cpm.GetSHLOMap()
Expect(entryMap).To(HaveKey(TagSFCW))
Expect(entryMap[TagSFCW]).To(Equal([]byte{0xEF, 0xBE, 0xAD, 0xDE}))
})
It("sets the connection-level flow control windows in SHLO", func() {
cpm.receiveConnectionFlowControlWindow = 0xDECAFBAD
entryMap := cpm.GetSHLOMap()
Expect(entryMap).To(HaveKey(TagCFCW))
Expect(entryMap[TagCFCW]).To(Equal([]byte{0xAD, 0xFB, 0xCA, 0xDE}))
})
It("sets the connection-level flow control windows in SHLO", func() {
cpm.idleConnectionStateLifetime = 0xDECAFBAD * time.Second
entryMap := cpm.GetSHLOMap()
Expect(entryMap).To(HaveKey(TagICSL))
Expect(entryMap[TagICSL]).To(Equal([]byte{0xAD, 0xFB, 0xCA, 0xDE}))
})
It("sets the maximum streams per connection in SHLO", func() {
cpm.maxStreamsPerConnection = 0xDEADBEEF
entryMap := cpm.GetSHLOMap()
Expect(entryMap).To(HaveKey(TagMSPC))
Expect(entryMap[TagMSPC]).To(Equal([]byte{0xEF, 0xBE, 0xAD, 0xDE}))
})
})
Context("Truncated connection IDs", func() {
It("does not send truncated connection IDs if the TCID tag is missing", func() {
Expect(cpm.TruncateConnectionID()).To(BeFalse())
})
It("reads the tag for truncated connection IDs", func() {
values := map[Tag][]byte{
TagTCID: {0, 0, 0, 0},
}
cpm.SetFromMap(values)
Expect(cpm.TruncateConnectionID()).To(BeTrue())
})
})
Context("flow control", func() {
It("has the correct default stream-level flow control window for sending", func() {
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.InitialStreamFlowControlWindow))
})
It("has the correct default connection-level flow control window for sending", func() {
Expect(cpm.GetSendConnectionFlowControlWindow()).To(Equal(protocol.InitialConnectionFlowControlWindow))
})
It("has the correct default stream-level flow control window for receiving", func() {
Expect(cpm.GetReceiveStreamFlowControlWindow()).To(Equal(protocol.ReceiveStreamFlowControlWindow))
})
It("has the correct default connection-level flow control window for receiving", func() {
Expect(cpm.GetReceiveConnectionFlowControlWindow()).To(Equal(protocol.ReceiveConnectionFlowControlWindow))
})
It("sets a new stream-level flow control window for sending", func() {
values := map[Tag][]byte{
TagSFCW: {0xDE, 0xAD, 0xBE, 0xEF},
}
err := cpm.SetFromMap(values)
Expect(err).ToNot(HaveOccurred())
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE)))
})
It("does not change the stream-level flow control window when given an invalid value", func() {
values := map[Tag][]byte{
TagSFCW: {0xDE, 0xAD, 0xBE}, // 1 byte too short
}
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.InitialStreamFlowControlWindow))
})
It("sets a new connection-level flow control window for sending", func() {
values := map[Tag][]byte{
TagCFCW: {0xDE, 0xAD, 0xBE, 0xEF},
}
err := cpm.SetFromMap(values)
Expect(err).ToNot(HaveOccurred())
Expect(cpm.GetSendConnectionFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE)))
})
It("does not change the connection-level flow control window when given an invalid value", func() {
values := map[Tag][]byte{
TagSFCW: {0xDE, 0xAD, 0xBE}, // 1 byte too short
}
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.InitialConnectionFlowControlWindow))
})
It("does not allow renegotiation of flow control parameters", func() {
values := map[Tag][]byte{
TagCFCW: {0xDE, 0xAD, 0xBE, 0xEF},
TagSFCW: {0xDE, 0xAD, 0xBE, 0xEF},
}
err := cpm.SetFromMap(values)
Expect(err).ToNot(HaveOccurred())
values = map[Tag][]byte{
TagCFCW: {0x13, 0x37, 0x13, 0x37},
TagSFCW: {0x13, 0x37, 0x13, 0x37},
}
err = cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrFlowControlRenegotiationNotSupported))
Expect(cpm.GetSendStreamFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE)))
Expect(cpm.GetSendConnectionFlowControlWindow()).To(Equal(protocol.ByteCount(0xEFBEADDE)))
})
})
Context("idle connection state lifetime", func() {
It("has initial idle conneciton state lifetime", func() {
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(protocol.InitialIdleConnectionStateLifetime))
})
It("negotiates correctly when the client wants a longer lifetime", func() {
Expect(cpm.negotiateIdleConnectionStateLifetime(protocol.MaxIdleConnectionStateLifetime + 10*time.Second)).To(Equal(protocol.MaxIdleConnectionStateLifetime))
})
It("negotiates correctly when the client wants a shorter lifetime", func() {
Expect(cpm.negotiateIdleConnectionStateLifetime(protocol.MaxIdleConnectionStateLifetime - 1*time.Second)).To(Equal(protocol.MaxIdleConnectionStateLifetime - 1*time.Second))
})
It("sets the negotiated lifetime", func() {
// this test only works if the value given here is smaller than protocol.MaxIdleConnectionStateLifetime
values := map[Tag][]byte{
TagICSL: {10, 0, 0, 0},
}
err := cpm.SetFromMap(values)
Expect(err).ToNot(HaveOccurred())
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(10 * time.Second))
})
It("does not change the idle connection state lifetime when given an invalid value", func() {
values := map[Tag][]byte{
TagSFCW: {0xDE, 0xAD, 0xBE}, // 1 byte too short
}
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(protocol.InitialIdleConnectionStateLifetime))
})
It("gets idle connection state lifetime", func() {
value := 0xDECAFBAD * time.Second
cpm.idleConnectionStateLifetime = value
Expect(cpm.GetIdleConnectionStateLifetime()).To(Equal(value))
})
})
Context("max streams per connection", func() {
It("negotiates correctly when the client wants a larger number", func() {
Expect(cpm.negotiateMaxStreamsPerConnection(protocol.MaxStreamsPerConnection + 10)).To(Equal(protocol.MaxStreamsPerConnection))
})
It("negotiates correctly when the client wants a smaller number", func() {
Expect(cpm.negotiateMaxStreamsPerConnection(protocol.MaxStreamsPerConnection - 1)).To(Equal(protocol.MaxStreamsPerConnection - 1))
})
It("sets the negotiated max streams per connection value", func() {
// this test only works if the value given here is smaller than protocol.MaxStreamsPerConnection
values := map[Tag][]byte{
TagMSPC: {2, 0, 0, 0},
}
err := cpm.SetFromMap(values)
Expect(err).ToNot(HaveOccurred())
Expect(cpm.GetMaxStreamsPerConnection()).To(Equal(uint32(2)))
})
It("errors when given an invalid max streams per connection value", func() {
values := map[Tag][]byte{
TagMSPC: {2, 0, 0}, // 1 byte too short
}
err := cpm.SetFromMap(values)
Expect(err).To(MatchError(ErrMalformedTag))
})
It("gets the max streams per connection value", func() {
var value uint32 = 0xDECAFBAD
cpm.maxStreamsPerConnection = value
Expect(cpm.GetMaxStreamsPerConnection()).To(Equal(value))
})
})
})