github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/framer_test.go (about)

     1  package quic
     2  
     3  import (
     4  	"bytes"
     5  
     6  	"golang.org/x/exp/rand"
     7  
     8  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/ackhandler"
     9  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol"
    10  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/wire"
    11  
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  	"go.uber.org/mock/gomock"
    15  )
    16  
    17  var _ = Describe("Framer", func() {
    18  	const (
    19  		id1 = protocol.StreamID(10)
    20  		id2 = protocol.StreamID(11)
    21  	)
    22  
    23  	var (
    24  		framer           framer
    25  		stream1, stream2 *MockSendStreamI
    26  		streamGetter     *MockStreamGetter
    27  		version          protocol.Version
    28  	)
    29  
    30  	BeforeEach(func() {
    31  		streamGetter = NewMockStreamGetter(mockCtrl)
    32  		stream1 = NewMockSendStreamI(mockCtrl)
    33  		stream1.EXPECT().StreamID().Return(protocol.StreamID(5)).AnyTimes()
    34  		stream2 = NewMockSendStreamI(mockCtrl)
    35  		stream2.EXPECT().StreamID().Return(protocol.StreamID(6)).AnyTimes()
    36  		framer = newFramer(streamGetter)
    37  	})
    38  
    39  	Context("handling control frames", func() {
    40  		It("adds control frames", func() {
    41  			mdf := &wire.MaxDataFrame{MaximumData: 0x42}
    42  			msf := &wire.MaxStreamsFrame{MaxStreamNum: 0x1337}
    43  			framer.QueueControlFrame(mdf)
    44  			framer.QueueControlFrame(msf)
    45  			frames, length := framer.AppendControlFrames(nil, 1000, protocol.Version1)
    46  			Expect(frames).To(HaveLen(2))
    47  			fs := []wire.Frame{frames[0].Frame, frames[1].Frame}
    48  			Expect(fs).To(ContainElement(mdf))
    49  			Expect(fs).To(ContainElement(msf))
    50  			Expect(length).To(Equal(mdf.Length(version) + msf.Length(version)))
    51  		})
    52  
    53  		It("says if it has data", func() {
    54  			Expect(framer.HasData()).To(BeFalse())
    55  			f := &wire.MaxDataFrame{MaximumData: 0x42}
    56  			framer.QueueControlFrame(f)
    57  			Expect(framer.HasData()).To(BeTrue())
    58  			frames, _ := framer.AppendControlFrames(nil, 1000, protocol.Version1)
    59  			Expect(frames).To(HaveLen(1))
    60  			Expect(framer.HasData()).To(BeFalse())
    61  		})
    62  
    63  		It("appends to the slice given", func() {
    64  			ping := &wire.PingFrame{}
    65  			mdf := &wire.MaxDataFrame{MaximumData: 0x42}
    66  			framer.QueueControlFrame(mdf)
    67  			frames, length := framer.AppendControlFrames([]ackhandler.Frame{{Frame: ping}}, 1000, protocol.Version1)
    68  			Expect(frames).To(HaveLen(2))
    69  			Expect(frames[0].Frame).To(Equal(ping))
    70  			Expect(frames[1].Frame).To(Equal(mdf))
    71  			Expect(length).To(Equal(mdf.Length(version)))
    72  		})
    73  
    74  		It("adds the right number of frames", func() {
    75  			maxSize := protocol.ByteCount(1000)
    76  			bf := &wire.DataBlockedFrame{MaximumData: 0x1337}
    77  			bfLen := bf.Length(version)
    78  			numFrames := int(maxSize / bfLen) // max number of frames that fit into maxSize
    79  			for i := 0; i < numFrames+1; i++ {
    80  				framer.QueueControlFrame(bf)
    81  			}
    82  			frames, length := framer.AppendControlFrames(nil, maxSize, protocol.Version1)
    83  			Expect(frames).To(HaveLen(numFrames))
    84  			Expect(length).To(BeNumerically(">", maxSize-bfLen))
    85  			frames, length = framer.AppendControlFrames(nil, maxSize, protocol.Version1)
    86  			Expect(frames).To(HaveLen(1))
    87  			Expect(length).To(Equal(bfLen))
    88  		})
    89  
    90  		It("drops *_BLOCKED frames when 0-RTT is rejected", func() {
    91  			ping := &wire.PingFrame{}
    92  			ncid := &wire.NewConnectionIDFrame{
    93  				SequenceNumber: 10,
    94  				ConnectionID:   protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}),
    95  			}
    96  			frames := []wire.Frame{
    97  				&wire.DataBlockedFrame{MaximumData: 1337},
    98  				&wire.StreamDataBlockedFrame{StreamID: 42, MaximumStreamData: 1337},
    99  				&wire.StreamsBlockedFrame{StreamLimit: 13},
   100  				ping,
   101  				ncid,
   102  			}
   103  			rand.Shuffle(len(frames), func(i, j int) { frames[i], frames[j] = frames[j], frames[i] })
   104  			for _, f := range frames {
   105  				framer.QueueControlFrame(f)
   106  			}
   107  			Expect(framer.Handle0RTTRejection()).To(Succeed())
   108  			fs, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1)
   109  			Expect(fs).To(HaveLen(2))
   110  			Expect(length).To(Equal(ping.Length(version) + ncid.Length(version)))
   111  		})
   112  	})
   113  
   114  	Context("handling PATH_RESPONSE frames", func() {
   115  		It("packs a single PATH_RESPONSE per packet", func() {
   116  			f1 := &wire.PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}
   117  			f2 := &wire.PathResponseFrame{Data: [8]byte{2, 3, 4, 5, 6, 7, 8, 9}}
   118  			cf1 := &wire.DataBlockedFrame{MaximumData: 1337}
   119  			cf2 := &wire.HandshakeDoneFrame{}
   120  			framer.QueueControlFrame(f1)
   121  			framer.QueueControlFrame(f2)
   122  			framer.QueueControlFrame(cf1)
   123  			framer.QueueControlFrame(cf2)
   124  			// the first packet should contain a single PATH_RESPONSE frame, but all the other control frames
   125  			Expect(framer.HasData()).To(BeTrue())
   126  			frames, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1)
   127  			Expect(frames).To(HaveLen(3))
   128  			Expect(frames[0].Frame).To(Equal(f1))
   129  			Expect([]wire.Frame{frames[1].Frame, frames[2].Frame}).To(ContainElement(cf1))
   130  			Expect([]wire.Frame{frames[1].Frame, frames[2].Frame}).To(ContainElement(cf2))
   131  			Expect(length).To(Equal(f1.Length(protocol.Version1) + cf1.Length(protocol.Version1) + cf2.Length(protocol.Version1)))
   132  			// the second packet should contain the other PATH_RESPONSE frame
   133  			Expect(framer.HasData()).To(BeTrue())
   134  			frames, length = framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1)
   135  			Expect(frames).To(HaveLen(1))
   136  			Expect(frames[0].Frame).To(Equal(f2))
   137  			Expect(length).To(Equal(f2.Length(protocol.Version1)))
   138  			Expect(framer.HasData()).To(BeFalse())
   139  		})
   140  
   141  		It("limits the number of queued PATH_RESPONSE frames", func() {
   142  			var pathResponses []*wire.PathResponseFrame
   143  			for i := 0; i < 2*maxPathResponses; i++ {
   144  				var f wire.PathResponseFrame
   145  				rand.Read(f.Data[:])
   146  				pathResponses = append(pathResponses, &f)
   147  				framer.QueueControlFrame(&f)
   148  			}
   149  			for i := 0; i < maxPathResponses; i++ {
   150  				Expect(framer.HasData()).To(BeTrue())
   151  				frames, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1)
   152  				Expect(frames).To(HaveLen(1))
   153  				Expect(frames[0].Frame).To(Equal(pathResponses[i]))
   154  				Expect(length).To(Equal(pathResponses[i].Length(protocol.Version1)))
   155  			}
   156  			Expect(framer.HasData()).To(BeFalse())
   157  			frames, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1)
   158  			Expect(frames).To(BeEmpty())
   159  			Expect(length).To(BeZero())
   160  		})
   161  	})
   162  
   163  	Context("popping STREAM frames", func() {
   164  		It("returns nil when popping an empty framer", func() {
   165  			Expect(framer.AppendStreamFrames(nil, 1000, protocol.Version1)).To(BeEmpty())
   166  		})
   167  
   168  		It("returns STREAM frames", func() {
   169  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   170  			f := &wire.StreamFrame{
   171  				StreamID:       id1,
   172  				Data:           []byte("foobar"),
   173  				Offset:         42,
   174  				DataLenPresent: true,
   175  			}
   176  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false)
   177  			framer.AddActiveStream(id1)
   178  			fs, length := framer.AppendStreamFrames(nil, 1000, protocol.Version1)
   179  			Expect(fs).To(HaveLen(1))
   180  			Expect(fs[0].Frame.DataLenPresent).To(BeFalse())
   181  			Expect(length).To(Equal(f.Length(version)))
   182  		})
   183  
   184  		It("says if it has data", func() {
   185  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).Times(2)
   186  			Expect(framer.HasData()).To(BeFalse())
   187  			framer.AddActiveStream(id1)
   188  			Expect(framer.HasData()).To(BeTrue())
   189  			f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foo")}
   190  			f2 := &wire.StreamFrame{StreamID: id1, Data: []byte("bar")}
   191  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, true)
   192  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false)
   193  			frames, _ := framer.AppendStreamFrames(nil, protocol.MaxByteCount, protocol.Version1)
   194  			Expect(frames).To(HaveLen(1))
   195  			Expect(frames[0].Frame).To(Equal(f1))
   196  			Expect(framer.HasData()).To(BeTrue())
   197  			frames, _ = framer.AppendStreamFrames(nil, protocol.MaxByteCount, protocol.Version1)
   198  			Expect(frames).To(HaveLen(1))
   199  			Expect(frames[0].Frame).To(Equal(f2))
   200  			Expect(framer.HasData()).To(BeFalse())
   201  		})
   202  
   203  		It("appends to a frame slice", func() {
   204  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   205  			f := &wire.StreamFrame{
   206  				StreamID:       id1,
   207  				Data:           []byte("foobar"),
   208  				DataLenPresent: true,
   209  			}
   210  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false)
   211  			framer.AddActiveStream(id1)
   212  			f0 := ackhandler.StreamFrame{Frame: &wire.StreamFrame{StreamID: 9999}}
   213  			frames := []ackhandler.StreamFrame{f0}
   214  			fs, length := framer.AppendStreamFrames(frames, 1000, protocol.Version1)
   215  			Expect(fs).To(HaveLen(2))
   216  			Expect(fs[0]).To(Equal(f0))
   217  			Expect(fs[1].Frame.Data).To(Equal([]byte("foobar")))
   218  			Expect(fs[1].Frame.DataLenPresent).To(BeFalse())
   219  			Expect(length).To(Equal(f.Length(version)))
   220  		})
   221  
   222  		It("skips a stream that was reported active, but was completed shortly after", func() {
   223  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(nil, nil)
   224  			streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
   225  			f := &wire.StreamFrame{
   226  				StreamID:       id2,
   227  				Data:           []byte("foobar"),
   228  				DataLenPresent: true,
   229  			}
   230  			stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false)
   231  			framer.AddActiveStream(id1)
   232  			framer.AddActiveStream(id2)
   233  			frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1)
   234  			Expect(frames).To(HaveLen(1))
   235  			Expect(frames[0].Frame).To(Equal(f))
   236  		})
   237  
   238  		It("skips a stream that was reported active, but doesn't have any data", func() {
   239  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   240  			streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
   241  			f := &wire.StreamFrame{
   242  				StreamID:       id2,
   243  				Data:           []byte("foobar"),
   244  				DataLenPresent: true,
   245  			}
   246  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{}, false, false)
   247  			stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false)
   248  			framer.AddActiveStream(id1)
   249  			framer.AddActiveStream(id2)
   250  			frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1)
   251  			Expect(frames).To(HaveLen(1))
   252  			Expect(frames[0].Frame).To(Equal(f))
   253  		})
   254  
   255  		It("pops from a stream multiple times, if it has enough data", func() {
   256  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).Times(2)
   257  			f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")}
   258  			f2 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")}
   259  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, true)
   260  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false)
   261  			framer.AddActiveStream(id1) // only add it once
   262  			frames, _ := framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1)
   263  			Expect(frames).To(HaveLen(1))
   264  			Expect(frames[0].Frame).To(Equal(f1))
   265  			frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1)
   266  			Expect(frames).To(HaveLen(1))
   267  			Expect(frames[0].Frame).To(Equal(f2))
   268  			// no further calls to popStreamFrame, after popStreamFrame said there's no more data
   269  			frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1)
   270  			Expect(frames).To(BeNil())
   271  		})
   272  
   273  		It("re-queues a stream at the end, if it has enough data", func() {
   274  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).Times(2)
   275  			streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
   276  			f11 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")}
   277  			f12 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")}
   278  			f2 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")}
   279  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f11}, true, true)
   280  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f12}, true, false)
   281  			stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false)
   282  			framer.AddActiveStream(id1) // only add it once
   283  			framer.AddActiveStream(id2)
   284  			// first a frame from stream 1
   285  			frames, _ := framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1)
   286  			Expect(frames).To(HaveLen(1))
   287  			Expect(frames[0].Frame).To(Equal(f11))
   288  			// then a frame from stream 2
   289  			frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1)
   290  			Expect(frames).To(HaveLen(1))
   291  			Expect(frames[0].Frame).To(Equal(f2))
   292  			// then another frame from stream 1
   293  			frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1)
   294  			Expect(frames).To(HaveLen(1))
   295  			Expect(frames[0].Frame).To(Equal(f12))
   296  		})
   297  
   298  		It("only dequeues data from each stream once per packet", func() {
   299  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   300  			streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
   301  			f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")}
   302  			f2 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")}
   303  			// both streams have more data, and will be re-queued
   304  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, true)
   305  			stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, true)
   306  			framer.AddActiveStream(id1)
   307  			framer.AddActiveStream(id2)
   308  			frames, length := framer.AppendStreamFrames(nil, 1000, protocol.Version1)
   309  			Expect(frames).To(HaveLen(2))
   310  			Expect(frames[0].Frame).To(Equal(f1))
   311  			Expect(frames[1].Frame).To(Equal(f2))
   312  			Expect(length).To(Equal(f1.Length(version) + f2.Length(version)))
   313  		})
   314  
   315  		It("returns multiple normal frames in the order they were reported active", func() {
   316  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   317  			streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
   318  			f1 := &wire.StreamFrame{Data: []byte("foobar")}
   319  			f2 := &wire.StreamFrame{Data: []byte("foobaz")}
   320  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, false)
   321  			stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false)
   322  			framer.AddActiveStream(id2)
   323  			framer.AddActiveStream(id1)
   324  			frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1)
   325  			Expect(frames).To(HaveLen(2))
   326  			Expect(frames[0].Frame).To(Equal(f2))
   327  			Expect(frames[1].Frame).To(Equal(f1))
   328  		})
   329  
   330  		It("only asks a stream for data once, even if it was reported active multiple times", func() {
   331  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   332  			f := &wire.StreamFrame{Data: []byte("foobar")}
   333  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) // only one call to this function
   334  			framer.AddActiveStream(id1)
   335  			framer.AddActiveStream(id1)
   336  			frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1)
   337  			Expect(frames).To(HaveLen(1))
   338  		})
   339  
   340  		It("does not pop empty frames", func() {
   341  			fs, length := framer.AppendStreamFrames(nil, 500, protocol.Version1)
   342  			Expect(fs).To(BeEmpty())
   343  			Expect(length).To(BeZero())
   344  		})
   345  
   346  		It("pops maximum size STREAM frames", func() {
   347  			for i := protocol.MinStreamFrameSize; i < 2000; i++ {
   348  				streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   349  				stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) {
   350  					f := &wire.StreamFrame{
   351  						StreamID:       id1,
   352  						DataLenPresent: true,
   353  					}
   354  					f.Data = make([]byte, f.MaxDataLen(size, v))
   355  					Expect(f.Length(version)).To(Equal(size))
   356  					return ackhandler.StreamFrame{Frame: f}, true, false
   357  				})
   358  				framer.AddActiveStream(id1)
   359  				frames, _ := framer.AppendStreamFrames(nil, i, protocol.Version1)
   360  				Expect(frames).To(HaveLen(1))
   361  				f := frames[0].Frame
   362  				Expect(f.DataLenPresent).To(BeFalse())
   363  				Expect(f.Length(version)).To(Equal(i))
   364  			}
   365  		})
   366  
   367  		It("pops multiple STREAM frames", func() {
   368  			for i := 2 * protocol.MinStreamFrameSize; i < 2000; i++ {
   369  				streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   370  				streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
   371  				stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) {
   372  					f := &wire.StreamFrame{
   373  						StreamID:       id2,
   374  						DataLenPresent: true,
   375  					}
   376  					f.Data = make([]byte, f.MaxDataLen(protocol.MinStreamFrameSize, v))
   377  					return ackhandler.StreamFrame{Frame: f}, true, false
   378  				})
   379  				stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) {
   380  					f := &wire.StreamFrame{
   381  						StreamID:       id2,
   382  						DataLenPresent: true,
   383  					}
   384  					f.Data = make([]byte, f.MaxDataLen(size, v))
   385  					Expect(f.Length(version)).To(Equal(size))
   386  					return ackhandler.StreamFrame{Frame: f}, true, false
   387  				})
   388  				framer.AddActiveStream(id1)
   389  				framer.AddActiveStream(id2)
   390  				frames, _ := framer.AppendStreamFrames(nil, i, protocol.Version1)
   391  				Expect(frames).To(HaveLen(2))
   392  				f1 := frames[0].Frame
   393  				f2 := frames[1].Frame
   394  				Expect(f1.DataLenPresent).To(BeTrue())
   395  				Expect(f2.DataLenPresent).To(BeFalse())
   396  				Expect(f1.Length(version) + f2.Length(version)).To(Equal(i))
   397  			}
   398  		})
   399  
   400  		It("pops frames that when asked for the the minimum STREAM frame size", func() {
   401  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   402  			f := &wire.StreamFrame{Data: []byte("foobar")}
   403  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false)
   404  			framer.AddActiveStream(id1)
   405  			framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1)
   406  		})
   407  
   408  		It("does not pop frames smaller than the minimum size", func() {
   409  			// don't expect a call to PopStreamFrame()
   410  			framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize-1, protocol.Version1)
   411  		})
   412  
   413  		It("stops iterating when the remaining size is smaller than the minimum STREAM frame size", func() {
   414  			streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
   415  			// pop a frame such that the remaining size is one byte less than the minimum STREAM frame size
   416  			f := &wire.StreamFrame{
   417  				StreamID:       id1,
   418  				Data:           bytes.Repeat([]byte("f"), int(500-protocol.MinStreamFrameSize)),
   419  				DataLenPresent: true,
   420  			}
   421  			stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false)
   422  			framer.AddActiveStream(id1)
   423  			fs, length := framer.AppendStreamFrames(nil, 500, protocol.Version1)
   424  			Expect(fs).To(HaveLen(1))
   425  			Expect(fs[0].Frame).To(Equal(f))
   426  			Expect(length).To(Equal(f.Length(version)))
   427  		})
   428  
   429  		It("drops all STREAM frames when 0-RTT is rejected", func() {
   430  			framer.AddActiveStream(id1)
   431  			Expect(framer.Handle0RTTRejection()).To(Succeed())
   432  			fs, length := framer.AppendStreamFrames(nil, protocol.MaxByteCount, protocol.Version1)
   433  			Expect(fs).To(BeEmpty())
   434  			Expect(length).To(BeZero())
   435  		})
   436  	})
   437  })