github.com/mikelsr/quic-go@v0.36.1-0.20230701132136-1d9415b66898/http3/http_stream_test.go (about)

     1  package http3
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  
     7  	mockquic "github.com/mikelsr/quic-go/internal/mocks/quic"
     8  
     9  	"github.com/golang/mock/gomock"
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  )
    13  
    14  var _ = Describe("Stream", func() {
    15  	Context("reading", func() {
    16  		var (
    17  			str           Stream
    18  			qstr          *mockquic.MockStream
    19  			buf           *bytes.Buffer
    20  			errorCbCalled bool
    21  		)
    22  
    23  		errorCb := func() { errorCbCalled = true }
    24  		getDataFrame := func(data []byte) []byte {
    25  			b := (&dataFrame{Length: uint64(len(data))}).Append(nil)
    26  			return append(b, data...)
    27  		}
    28  
    29  		BeforeEach(func() {
    30  			buf = &bytes.Buffer{}
    31  			errorCbCalled = false
    32  			qstr = mockquic.NewMockStream(mockCtrl)
    33  			qstr.EXPECT().Write(gomock.Any()).DoAndReturn(buf.Write).AnyTimes()
    34  			qstr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
    35  			str = newStream(qstr, errorCb)
    36  		})
    37  
    38  		It("reads DATA frames in a single run", func() {
    39  			buf.Write(getDataFrame([]byte("foobar")))
    40  			b := make([]byte, 6)
    41  			n, err := str.Read(b)
    42  			Expect(err).ToNot(HaveOccurred())
    43  			Expect(n).To(Equal(6))
    44  			Expect(b).To(Equal([]byte("foobar")))
    45  		})
    46  
    47  		It("reads DATA frames in multiple runs", func() {
    48  			buf.Write(getDataFrame([]byte("foobar")))
    49  			b := make([]byte, 3)
    50  			n, err := str.Read(b)
    51  			Expect(err).ToNot(HaveOccurred())
    52  			Expect(n).To(Equal(3))
    53  			Expect(b).To(Equal([]byte("foo")))
    54  			n, err = str.Read(b)
    55  			Expect(err).ToNot(HaveOccurred())
    56  			Expect(n).To(Equal(3))
    57  			Expect(b).To(Equal([]byte("bar")))
    58  		})
    59  
    60  		It("reads DATA frames into too large buffers", func() {
    61  			buf.Write(getDataFrame([]byte("foobar")))
    62  			b := make([]byte, 10)
    63  			n, err := str.Read(b)
    64  			Expect(err).ToNot(HaveOccurred())
    65  			Expect(n).To(Equal(6))
    66  			Expect(b[:n]).To(Equal([]byte("foobar")))
    67  		})
    68  
    69  		It("reads DATA frames into too large buffers, in multiple runs", func() {
    70  			buf.Write(getDataFrame([]byte("foobar")))
    71  			b := make([]byte, 4)
    72  			n, err := str.Read(b)
    73  			Expect(err).ToNot(HaveOccurred())
    74  			Expect(n).To(Equal(4))
    75  			Expect(b).To(Equal([]byte("foob")))
    76  			n, err = str.Read(b)
    77  			Expect(err).ToNot(HaveOccurred())
    78  			Expect(n).To(Equal(2))
    79  			Expect(b[:n]).To(Equal([]byte("ar")))
    80  		})
    81  
    82  		It("reads multiple DATA frames", func() {
    83  			buf.Write(getDataFrame([]byte("foo")))
    84  			buf.Write(getDataFrame([]byte("bar")))
    85  			b := make([]byte, 6)
    86  			n, err := str.Read(b)
    87  			Expect(err).ToNot(HaveOccurred())
    88  			Expect(n).To(Equal(3))
    89  			Expect(b[:n]).To(Equal([]byte("foo")))
    90  			n, err = str.Read(b)
    91  			Expect(err).ToNot(HaveOccurred())
    92  			Expect(n).To(Equal(3))
    93  			Expect(b[:n]).To(Equal([]byte("bar")))
    94  		})
    95  
    96  		It("skips HEADERS frames", func() {
    97  			b := getDataFrame([]byte("foo"))
    98  			b = (&headersFrame{Length: 10}).Append(b)
    99  			b = append(b, make([]byte, 10)...)
   100  			b = append(b, getDataFrame([]byte("bar"))...)
   101  			buf.Write(b)
   102  			r := make([]byte, 6)
   103  			n, err := io.ReadFull(str, r)
   104  			Expect(err).ToNot(HaveOccurred())
   105  			Expect(n).To(Equal(6))
   106  			Expect(r).To(Equal([]byte("foobar")))
   107  		})
   108  
   109  		It("errors when it can't parse the frame", func() {
   110  			buf.Write([]byte("invalid"))
   111  			_, err := str.Read([]byte{0})
   112  			Expect(err).To(HaveOccurred())
   113  		})
   114  
   115  		It("errors on unexpected frames, and calls the error callback", func() {
   116  			b := (&settingsFrame{}).Append(nil)
   117  			buf.Write(b)
   118  			_, err := str.Read([]byte{0})
   119  			Expect(err).To(MatchError("peer sent an unexpected frame: *http3.settingsFrame"))
   120  			Expect(errorCbCalled).To(BeTrue())
   121  		})
   122  	})
   123  
   124  	Context("writing", func() {
   125  		It("writes data frames", func() {
   126  			buf := &bytes.Buffer{}
   127  			qstr := mockquic.NewMockStream(mockCtrl)
   128  			qstr.EXPECT().Write(gomock.Any()).DoAndReturn(buf.Write).AnyTimes()
   129  			str := newStream(qstr, nil)
   130  			str.Write([]byte("foo"))
   131  			str.Write([]byte("foobar"))
   132  
   133  			f, err := parseNextFrame(buf, nil)
   134  			Expect(err).ToNot(HaveOccurred())
   135  			Expect(f).To(Equal(&dataFrame{Length: 3}))
   136  			b := make([]byte, 3)
   137  			_, err = io.ReadFull(buf, b)
   138  			Expect(err).ToNot(HaveOccurred())
   139  			Expect(b).To(Equal([]byte("foo")))
   140  
   141  			f, err = parseNextFrame(buf, nil)
   142  			Expect(err).ToNot(HaveOccurred())
   143  			Expect(f).To(Equal(&dataFrame{Length: 6}))
   144  			b = make([]byte, 6)
   145  			_, err = io.ReadFull(buf, b)
   146  			Expect(err).ToNot(HaveOccurred())
   147  			Expect(b).To(Equal([]byte("foobar")))
   148  		})
   149  	})
   150  })