github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/http3/body_test.go (about) 1 package http3 2 3 import ( 4 "bytes" 5 "errors" 6 "io" 7 8 "github.com/metacubex/quic-go" 9 mockquic "github.com/metacubex/quic-go/internal/mocks/quic" 10 11 . "github.com/onsi/ginkgo/v2" 12 . "github.com/onsi/gomega" 13 "go.uber.org/mock/gomock" 14 ) 15 16 var _ = Describe("Response Body", func() { 17 var reqDone chan struct{} 18 19 BeforeEach(func() { reqDone = make(chan struct{}) }) 20 21 It("closes the reqDone channel when Read errors", func() { 22 str := mockquic.NewMockStream(mockCtrl) 23 str.EXPECT().Read(gomock.Any()).Return(0, errors.New("test error")) 24 rb := newResponseBody(&stream{Stream: str}, -1, reqDone) 25 _, err := rb.Read([]byte{0}) 26 Expect(err).To(MatchError("test error")) 27 Expect(reqDone).To(BeClosed()) 28 }) 29 30 It("allows multiple calls to Read, when Read errors", func() { 31 str := mockquic.NewMockStream(mockCtrl) 32 str.EXPECT().Read(gomock.Any()).Return(0, errors.New("test error")).Times(2) 33 rb := newResponseBody(&stream{Stream: str}, -1, reqDone) 34 _, err := rb.Read([]byte{0}) 35 Expect(err).To(HaveOccurred()) 36 Expect(reqDone).To(BeClosed()) 37 _, err = rb.Read([]byte{0}) 38 Expect(err).To(HaveOccurred()) 39 }) 40 41 It("closes responses", func() { 42 str := mockquic.NewMockStream(mockCtrl) 43 rb := newResponseBody(&stream{Stream: str}, -1, reqDone) 44 str.EXPECT().CancelRead(quic.StreamErrorCode(ErrCodeRequestCanceled)) 45 Expect(rb.Close()).To(Succeed()) 46 }) 47 48 It("allows multiple calls to Close", func() { 49 str := mockquic.NewMockStream(mockCtrl) 50 rb := newResponseBody(&stream{Stream: str}, -1, reqDone) 51 str.EXPECT().CancelRead(quic.StreamErrorCode(ErrCodeRequestCanceled)).MaxTimes(2) 52 Expect(rb.Close()).To(Succeed()) 53 Expect(reqDone).To(BeClosed()) 54 Expect(rb.Close()).To(Succeed()) 55 }) 56 57 Context("length limiting", func() { 58 It("reads all frames", func() { 59 var buf bytes.Buffer 60 buf.Write(getDataFrame([]byte("foobar"))) 61 str := mockquic.NewMockStream(mockCtrl) 62 str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() 63 rb := newResponseBody(&stream{Stream: str}, 6, reqDone) 64 data, err := io.ReadAll(rb) 65 Expect(err).ToNot(HaveOccurred()) 66 Expect(data).To(Equal([]byte("foobar"))) 67 }) 68 69 It("errors if more data than the maximum length is sent, in the middle of a frame", func() { 70 var buf bytes.Buffer 71 buf.Write(getDataFrame([]byte("foo"))) 72 buf.Write(getDataFrame([]byte("bar"))) 73 str := mockquic.NewMockStream(mockCtrl) 74 str.EXPECT().CancelRead(quic.StreamErrorCode(ErrCodeMessageError)) 75 str.EXPECT().CancelWrite(quic.StreamErrorCode(ErrCodeMessageError)) 76 str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() 77 rb := newResponseBody(&stream{Stream: str}, 4, reqDone) 78 data, err := io.ReadAll(rb) 79 Expect(data).To(Equal([]byte("foob"))) 80 Expect(err).To(MatchError(errTooMuchData)) 81 // check that repeated calls to Read also return the right error 82 n, err := rb.Read([]byte{0}) 83 Expect(n).To(BeZero()) 84 Expect(err).To(MatchError(errTooMuchData)) 85 }) 86 87 It("errors if more data than the maximum length is sent, as an additional frame", func() { 88 var buf bytes.Buffer 89 buf.Write(getDataFrame([]byte("foo"))) 90 buf.Write(getDataFrame([]byte("bar"))) 91 str := mockquic.NewMockStream(mockCtrl) 92 str.EXPECT().CancelRead(quic.StreamErrorCode(ErrCodeMessageError)) 93 str.EXPECT().CancelWrite(quic.StreamErrorCode(ErrCodeMessageError)) 94 str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() 95 rb := newResponseBody(&stream{Stream: str}, 3, reqDone) 96 data, err := io.ReadAll(rb) 97 Expect(err).To(MatchError(errTooMuchData)) 98 Expect(data).To(Equal([]byte("foo"))) 99 }) 100 }) 101 })