github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/internal/wire/crypto_frame_test.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "io" 6 7 "github.com/apernet/quic-go/internal/protocol" 8 "github.com/apernet/quic-go/quicvarint" 9 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 ) 13 14 var _ = Describe("CRYPTO frame", func() { 15 Context("when parsing", func() { 16 It("parses", func() { 17 data := encodeVarInt(0xdecafbad) // offset 18 data = append(data, encodeVarInt(6)...) // length 19 data = append(data, []byte("foobar")...) 20 r := bytes.NewReader(data) 21 frame, err := parseCryptoFrame(r, protocol.Version1) 22 Expect(err).ToNot(HaveOccurred()) 23 Expect(frame.Offset).To(Equal(protocol.ByteCount(0xdecafbad))) 24 Expect(frame.Data).To(Equal([]byte("foobar"))) 25 Expect(r.Len()).To(BeZero()) 26 }) 27 28 It("errors on EOFs", func() { 29 data := encodeVarInt(0xdecafbad) // offset 30 data = append(data, encodeVarInt(6)...) // data length 31 data = append(data, []byte("foobar")...) 32 r := bytes.NewReader(data) 33 _, err := parseCryptoFrame(r, protocol.Version1) 34 Expect(err).NotTo(HaveOccurred()) 35 for i := range data { 36 _, err := parseCryptoFrame(bytes.NewReader(data[:i]), protocol.Version1) 37 Expect(err).To(MatchError(io.EOF)) 38 } 39 }) 40 }) 41 42 Context("when writing", func() { 43 It("writes a frame", func() { 44 f := &CryptoFrame{ 45 Offset: 0x123456, 46 Data: []byte("foobar"), 47 } 48 b, err := f.Append(nil, protocol.Version1) 49 Expect(err).ToNot(HaveOccurred()) 50 expected := []byte{cryptoFrameType} 51 expected = append(expected, encodeVarInt(0x123456)...) // offset 52 expected = append(expected, encodeVarInt(6)...) // length 53 expected = append(expected, []byte("foobar")...) 54 Expect(b).To(Equal(expected)) 55 }) 56 }) 57 58 Context("max data length", func() { 59 const maxSize = 3000 60 61 It("always returns a data length such that the resulting frame has the right size", func() { 62 data := make([]byte, maxSize) 63 f := &CryptoFrame{ 64 Offset: 0xdeadbeef, 65 } 66 var frameOneByteTooSmallCounter int 67 for i := 1; i < maxSize; i++ { 68 f.Data = nil 69 maxDataLen := f.MaxDataLen(protocol.ByteCount(i)) 70 if maxDataLen == 0 { // 0 means that no valid CRYTPO frame can be written 71 // check that writing a minimal size CRYPTO frame (i.e. with 1 byte data) is actually larger than the desired size 72 f.Data = []byte{0} 73 b, err := f.Append(nil, protocol.Version1) 74 Expect(err).ToNot(HaveOccurred()) 75 Expect(len(b)).To(BeNumerically(">", i)) 76 continue 77 } 78 f.Data = data[:int(maxDataLen)] 79 b, err := f.Append(nil, protocol.Version1) 80 Expect(err).ToNot(HaveOccurred()) 81 // There's *one* pathological case, where a data length of x can be encoded into 1 byte 82 // but a data lengths of x+1 needs 2 bytes 83 // In that case, it's impossible to create a STREAM frame of the desired size 84 if len(b) == i-1 { 85 frameOneByteTooSmallCounter++ 86 continue 87 } 88 Expect(len(b)).To(Equal(i)) 89 } 90 Expect(frameOneByteTooSmallCounter).To(Equal(1)) 91 }) 92 }) 93 94 Context("length", func() { 95 It("has the right length for a frame without offset and data length", func() { 96 f := &CryptoFrame{ 97 Offset: 0x1337, 98 Data: []byte("foobar"), 99 } 100 Expect(f.Length(protocol.Version1)).To(BeEquivalentTo(1 + quicvarint.Len(0x1337) + quicvarint.Len(6) + 6)) 101 }) 102 }) 103 104 Context("splitting", func() { 105 It("splits a frame", func() { 106 f := &CryptoFrame{ 107 Offset: 0x1337, 108 Data: []byte("foobar"), 109 } 110 hdrLen := f.Length(protocol.Version1) - 6 111 new, needsSplit := f.MaybeSplitOffFrame(hdrLen+3, protocol.Version1) 112 Expect(needsSplit).To(BeTrue()) 113 Expect(new.Data).To(Equal([]byte("foo"))) 114 Expect(new.Offset).To(Equal(protocol.ByteCount(0x1337))) 115 Expect(f.Data).To(Equal([]byte("bar"))) 116 Expect(f.Offset).To(Equal(protocol.ByteCount(0x1337 + 3))) 117 }) 118 119 It("doesn't split if there's enough space in the frame", func() { 120 f := &CryptoFrame{ 121 Offset: 0x1337, 122 Data: []byte("foobar"), 123 } 124 f, needsSplit := f.MaybeSplitOffFrame(f.Length(protocol.Version1), protocol.Version1) 125 Expect(needsSplit).To(BeFalse()) 126 Expect(f).To(BeNil()) 127 }) 128 129 It("doesn't split if the size is too small", func() { 130 f := &CryptoFrame{ 131 Offset: 0x1337, 132 Data: []byte("foobar"), 133 } 134 length := f.Length(protocol.Version1) - 6 135 for i := protocol.ByteCount(0); i <= length; i++ { 136 f, needsSplit := f.MaybeSplitOffFrame(i, protocol.Version1) 137 Expect(needsSplit).To(BeTrue()) 138 Expect(f).To(BeNil()) 139 } 140 f, needsSplit := f.MaybeSplitOffFrame(length+1, protocol.Version1) 141 Expect(needsSplit).To(BeTrue()) 142 Expect(f).ToNot(BeNil()) 143 }) 144 }) 145 })