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