uquic/http3/frames_test.go

183 lines
5.7 KiB
Go

package http3
import (
"bytes"
"fmt"
"io"
"github.com/lucas-clemente/quic-go/quicvarint"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Frames", func() {
appendVarInt := func(b []byte, val uint64) []byte {
buf := &bytes.Buffer{}
quicvarint.Write(buf, val)
return append(b, buf.Bytes()...)
}
It("skips unknown frames", func() {
data := appendVarInt(nil, 0xdeadbeef) // type byte
data = appendVarInt(data, 0x42)
data = append(data, make([]byte, 0x42)...)
buf := bytes.NewBuffer(data)
(&dataFrame{Length: 0x1234}).Write(buf)
frame, err := parseNextFrame(buf)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
Expect(frame.(*dataFrame).Length).To(Equal(uint64(0x1234)))
})
Context("DATA frames", func() {
It("parses", func() {
data := appendVarInt(nil, 0) // type byte
data = appendVarInt(data, 0x1337)
frame, err := parseNextFrame(bytes.NewReader(data))
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
Expect(frame.(*dataFrame).Length).To(Equal(uint64(0x1337)))
})
It("writes", func() {
buf := &bytes.Buffer{}
(&dataFrame{Length: 0xdeadbeef}).Write(buf)
frame, err := parseNextFrame(buf)
Expect(err).ToNot(HaveOccurred())
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(BeAssignableToTypeOf(&dataFrame{}))
Expect(frame.(*dataFrame).Length).To(Equal(uint64(0xdeadbeef)))
})
})
Context("HEADERS frames", func() {
It("parses", func() {
data := appendVarInt(nil, 1) // type byte
data = appendVarInt(data, 0x1337)
frame, err := parseNextFrame(bytes.NewReader(data))
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(BeAssignableToTypeOf(&headersFrame{}))
Expect(frame.(*headersFrame).Length).To(Equal(uint64(0x1337)))
})
It("writes", func() {
buf := &bytes.Buffer{}
(&headersFrame{Length: 0xdeadbeef}).Write(buf)
frame, err := parseNextFrame(buf)
Expect(err).ToNot(HaveOccurred())
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(BeAssignableToTypeOf(&headersFrame{}))
Expect(frame.(*headersFrame).Length).To(Equal(uint64(0xdeadbeef)))
})
})
Context("SETTINGS frames", func() {
It("parses", func() {
settings := appendVarInt(nil, 13)
settings = appendVarInt(settings, 37)
settings = appendVarInt(settings, 0xdead)
settings = appendVarInt(settings, 0xbeef)
data := appendVarInt(nil, 4) // type byte
data = appendVarInt(data, uint64(len(settings)))
data = append(data, settings...)
frame, err := parseNextFrame(bytes.NewReader(data))
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(BeAssignableToTypeOf(&settingsFrame{}))
sf := frame.(*settingsFrame)
Expect(sf.other).To(HaveKeyWithValue(uint64(13), uint64(37)))
Expect(sf.other).To(HaveKeyWithValue(uint64(0xdead), uint64(0xbeef)))
})
It("rejects duplicate settings", func() {
settings := appendVarInt(nil, 13)
settings = appendVarInt(settings, 37)
settings = appendVarInt(settings, 13)
settings = appendVarInt(settings, 38)
data := appendVarInt(nil, 4) // type byte
data = appendVarInt(data, uint64(len(settings)))
data = append(data, settings...)
_, err := parseNextFrame(bytes.NewReader(data))
Expect(err).To(MatchError("duplicate setting: 13"))
})
It("writes", func() {
sf := &settingsFrame{other: map[uint64]uint64{
1: 2,
99: 999,
13: 37,
}}
buf := &bytes.Buffer{}
sf.Write(buf)
frame, err := parseNextFrame(buf)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(sf))
})
It("errors on EOF", func() {
sf := &settingsFrame{other: map[uint64]uint64{
13: 37,
0xdeadbeef: 0xdecafbad,
}}
buf := &bytes.Buffer{}
sf.Write(buf)
data := buf.Bytes()
_, err := parseNextFrame(bytes.NewReader(data))
Expect(err).ToNot(HaveOccurred())
for i := range data {
b := make([]byte, i)
copy(b, data[:i])
_, err := parseNextFrame(bytes.NewReader(b))
Expect(err).To(MatchError(io.EOF))
}
})
Context("H3_DATAGRAM", func() {
It("reads the H3_DATAGRAM value", func() {
settings := appendVarInt(nil, settingDatagram)
settings = appendVarInt(settings, 1)
data := appendVarInt(nil, 4) // type byte
data = appendVarInt(data, uint64(len(settings)))
data = append(data, settings...)
f, err := parseNextFrame(bytes.NewReader(data))
Expect(err).ToNot(HaveOccurred())
Expect(f).To(BeAssignableToTypeOf(&settingsFrame{}))
sf := f.(*settingsFrame)
Expect(sf.Datagram).To(BeTrue())
})
It("rejects duplicate H3_DATAGRAM entries", func() {
settings := appendVarInt(nil, settingDatagram)
settings = appendVarInt(settings, 1)
settings = appendVarInt(settings, settingDatagram)
settings = appendVarInt(settings, 1)
data := appendVarInt(nil, 4) // type byte
data = appendVarInt(data, uint64(len(settings)))
data = append(data, settings...)
_, err := parseNextFrame(bytes.NewReader(data))
Expect(err).To(MatchError(fmt.Sprintf("duplicate setting: %d", settingDatagram)))
})
It("rejects invalid values for the H3_DATAGRAM entry", func() {
settings := appendVarInt(nil, settingDatagram)
settings = appendVarInt(settings, 1337)
data := appendVarInt(nil, 4) // type byte
data = appendVarInt(data, uint64(len(settings)))
data = append(data, settings...)
_, err := parseNextFrame(bytes.NewReader(data))
Expect(err).To(MatchError("invalid value for H3_DATAGRAM: 1337"))
})
It("writes the H3_DATAGRAM setting", func() {
sf := &settingsFrame{Datagram: true}
buf := &bytes.Buffer{}
sf.Write(buf)
frame, err := parseNextFrame(buf)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(sf))
})
})
})
})