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  })