github.com/TugasAkhir-QUIC/quic-go@v0.0.2-0.20240215011318-d20e25a9054c/send_stream_test.go (about)

     1  package quic
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"io"
     8  	mrand "math/rand"
     9  	"runtime"
    10  	"time"
    11  
    12  	"golang.org/x/exp/rand"
    13  
    14  	"github.com/TugasAkhir-QUIC/quic-go/internal/ackhandler"
    15  	"github.com/TugasAkhir-QUIC/quic-go/internal/mocks"
    16  	"github.com/TugasAkhir-QUIC/quic-go/internal/protocol"
    17  	"github.com/TugasAkhir-QUIC/quic-go/internal/wire"
    18  
    19  	. "github.com/onsi/ginkgo/v2"
    20  	. "github.com/onsi/gomega"
    21  	"github.com/onsi/gomega/gbytes"
    22  	"go.uber.org/mock/gomock"
    23  )
    24  
    25  var _ = Describe("Send Stream", func() {
    26  	const streamID protocol.StreamID = 1337
    27  
    28  	var (
    29  		str            *sendStream
    30  		strWithTimeout io.Writer // str wrapped with gbytes.TimeoutWriter
    31  		mockFC         *mocks.MockStreamFlowController
    32  		mockSender     *MockStreamSender
    33  	)
    34  
    35  	BeforeEach(func() {
    36  		mockSender = NewMockStreamSender(mockCtrl)
    37  		mockFC = mocks.NewMockStreamFlowController(mockCtrl)
    38  		str = newSendStream(streamID, mockSender, mockFC)
    39  
    40  		timeout := scaleDuration(250 * time.Millisecond)
    41  		strWithTimeout = gbytes.TimeoutWriter(str, timeout)
    42  	})
    43  
    44  	expectedFrameHeaderLen := func(offset protocol.ByteCount) protocol.ByteCount {
    45  		return (&wire.StreamFrame{
    46  			StreamID:       streamID,
    47  			Offset:         offset,
    48  			DataLenPresent: true,
    49  		}).Length(protocol.Version1)
    50  	}
    51  
    52  	waitForWrite := func() {
    53  		EventuallyWithOffset(0, func() bool {
    54  			str.mutex.Lock()
    55  			hasData := str.dataForWriting != nil || str.nextFrame != nil
    56  			str.mutex.Unlock()
    57  			return hasData
    58  		}).Should(BeTrue())
    59  	}
    60  
    61  	getDataAtOffset := func(offset, length protocol.ByteCount) []byte {
    62  		b := make([]byte, length)
    63  		for i := protocol.ByteCount(0); i < length; i++ {
    64  			b[i] = uint8(offset + i)
    65  		}
    66  		return b
    67  	}
    68  
    69  	getData := func(length protocol.ByteCount) []byte {
    70  		return getDataAtOffset(0, length)
    71  	}
    72  
    73  	It("gets stream id", func() {
    74  		Expect(str.StreamID()).To(Equal(protocol.StreamID(1337)))
    75  	})
    76  
    77  	Context("writing", func() {
    78  		It("writes and gets all data at once", func() {
    79  			done := make(chan struct{})
    80  			go func() {
    81  				defer GinkgoRecover()
    82  				defer close(done)
    83  				mockSender.EXPECT().onHasStreamData(streamID)
    84  				n, err := strWithTimeout.Write([]byte("foobar"))
    85  				Expect(err).ToNot(HaveOccurred())
    86  				Expect(n).To(Equal(6))
    87  			}()
    88  			waitForWrite()
    89  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
    90  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(6))
    91  			frame, ok, _ := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
    92  			Expect(ok).To(BeTrue())
    93  			f := frame.Frame
    94  			Expect(f.Data).To(Equal([]byte("foobar")))
    95  			Expect(f.Fin).To(BeFalse())
    96  			Expect(f.Offset).To(BeZero())
    97  			Expect(f.DataLenPresent).To(BeTrue())
    98  			Expect(str.writeOffset).To(Equal(protocol.ByteCount(6)))
    99  			Expect(str.dataForWriting).To(BeNil())
   100  			Eventually(done).Should(BeClosed())
   101  		})
   102  
   103  		It("writes and gets data in two turns", func() {
   104  			done := make(chan struct{})
   105  			go func() {
   106  				defer GinkgoRecover()
   107  				mockSender.EXPECT().onHasStreamData(streamID)
   108  				n, err := strWithTimeout.Write([]byte("foobar"))
   109  				Expect(err).ToNot(HaveOccurred())
   110  				Expect(n).To(Equal(6))
   111  				close(done)
   112  			}()
   113  			waitForWrite()
   114  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).Times(2)
   115  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(3)).Times(2)
   116  			frame, ok, _ := str.popStreamFrame(expectedFrameHeaderLen(0)+3, protocol.Version1)
   117  			Expect(ok).To(BeTrue())
   118  			f := frame.Frame
   119  			Expect(f.Offset).To(BeZero())
   120  			Expect(f.Fin).To(BeFalse())
   121  			Expect(f.Data).To(Equal([]byte("foo")))
   122  			Expect(f.DataLenPresent).To(BeTrue())
   123  			frame, ok, _ = str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   124  			Expect(ok).To(BeTrue())
   125  			f = frame.Frame
   126  			Expect(f.Data).To(Equal([]byte("bar")))
   127  			Expect(f.Fin).To(BeFalse())
   128  			Expect(f.Offset).To(Equal(protocol.ByteCount(3)))
   129  			Expect(f.DataLenPresent).To(BeTrue())
   130  			_, ok, _ = str.popStreamFrame(1000, protocol.Version1)
   131  			Expect(ok).To(BeFalse())
   132  			Eventually(done).Should(BeClosed())
   133  		})
   134  
   135  		It("bundles small writes", func() {
   136  			done := make(chan struct{})
   137  			go func() {
   138  				defer GinkgoRecover()
   139  				mockSender.EXPECT().onHasStreamData(streamID).Times(2)
   140  				n, err := strWithTimeout.Write([]byte("foo"))
   141  				Expect(err).ToNot(HaveOccurred())
   142  				Expect(n).To(Equal(3))
   143  				n, err = strWithTimeout.Write([]byte("bar"))
   144  				Expect(err).ToNot(HaveOccurred())
   145  				Expect(n).To(Equal(3))
   146  				close(done)
   147  			}()
   148  			Eventually(done).Should(BeClosed()) // both Write calls returned without any data having been dequeued yet
   149  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
   150  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(6))
   151  			frame, ok, _ := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   152  			Expect(ok).To(BeTrue())
   153  			f := frame.Frame
   154  			Expect(f.Offset).To(BeZero())
   155  			Expect(f.Fin).To(BeFalse())
   156  			Expect(f.Data).To(Equal([]byte("foobar")))
   157  		})
   158  
   159  		It("writes and gets data in multiple turns, for large writes", func() {
   160  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).Times(5)
   161  			var totalBytesSent protocol.ByteCount
   162  			mockFC.EXPECT().AddBytesSent(gomock.Any()).Do(func(l protocol.ByteCount) { totalBytesSent += l }).Times(5)
   163  			done := make(chan struct{})
   164  			go func() {
   165  				defer GinkgoRecover()
   166  				mockSender.EXPECT().onHasStreamData(streamID)
   167  				n, err := strWithTimeout.Write(getData(5000))
   168  				Expect(err).ToNot(HaveOccurred())
   169  				Expect(n).To(Equal(5000))
   170  				close(done)
   171  			}()
   172  			waitForWrite()
   173  			for i := 0; i < 5; i++ {
   174  				frame, ok, _ := str.popStreamFrame(1100, protocol.Version1)
   175  				Expect(ok).To(BeTrue())
   176  				f := frame.Frame
   177  				Expect(f.Offset).To(BeNumerically("~", 1100*i, 10*i))
   178  				Expect(f.Fin).To(BeFalse())
   179  				Expect(f.Data).To(Equal(getDataAtOffset(f.Offset, f.DataLen())))
   180  				Expect(f.DataLenPresent).To(BeTrue())
   181  			}
   182  			Expect(totalBytesSent).To(Equal(protocol.ByteCount(5000)))
   183  			Eventually(done).Should(BeClosed())
   184  		})
   185  
   186  		It("unblocks Write as soon as a STREAM frame can be buffered", func() {
   187  			done := make(chan struct{})
   188  			go func() {
   189  				defer GinkgoRecover()
   190  				defer close(done)
   191  				mockSender.EXPECT().onHasStreamData(streamID)
   192  				_, err := strWithTimeout.Write(getData(protocol.MaxPacketBufferSize + 3))
   193  				Expect(err).ToNot(HaveOccurred())
   194  			}()
   195  			waitForWrite()
   196  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).Times(2)
   197  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(2))
   198  			frame, ok, hasMoreData := str.popStreamFrame(expectedFrameHeaderLen(0)+2, protocol.Version1)
   199  			Expect(ok).To(BeTrue())
   200  			Expect(hasMoreData).To(BeTrue())
   201  			f := frame.Frame
   202  			Expect(f.DataLen()).To(Equal(protocol.ByteCount(2)))
   203  			Consistently(done).ShouldNot(BeClosed())
   204  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(1))
   205  			frame, ok, hasMoreData = str.popStreamFrame(expectedFrameHeaderLen(1)+1, protocol.Version1)
   206  			Expect(ok).To(BeTrue())
   207  			Expect(hasMoreData).To(BeTrue())
   208  			f = frame.Frame
   209  			Expect(f.DataLen()).To(Equal(protocol.ByteCount(1)))
   210  			Eventually(done).Should(BeClosed())
   211  		})
   212  
   213  		It("only unblocks Write once a previously buffered STREAM frame has been fully dequeued", func() {
   214  			mockSender.EXPECT().onHasStreamData(streamID)
   215  			_, err := strWithTimeout.Write([]byte("foobar"))
   216  			Expect(err).ToNot(HaveOccurred())
   217  			done := make(chan struct{})
   218  			go func() {
   219  				defer GinkgoRecover()
   220  				defer close(done)
   221  				mockSender.EXPECT().onHasStreamData(streamID)
   222  				_, err := str.Write(getData(protocol.MaxPacketBufferSize))
   223  				Expect(err).ToNot(HaveOccurred())
   224  			}()
   225  			waitForWrite()
   226  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).Times(2)
   227  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(2))
   228  			frame, ok, hasMoreData := str.popStreamFrame(expectedFrameHeaderLen(0)+2, protocol.Version1)
   229  			Expect(ok).To(BeTrue())
   230  			Expect(hasMoreData).To(BeTrue())
   231  			f := frame.Frame
   232  			Expect(f.Data).To(Equal([]byte("fo")))
   233  			Consistently(done).ShouldNot(BeClosed())
   234  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(4))
   235  			frame, ok, hasMoreData = str.popStreamFrame(expectedFrameHeaderLen(2)+4, protocol.Version1)
   236  			Expect(ok).To(BeTrue())
   237  			Expect(hasMoreData).To(BeTrue())
   238  			f = frame.Frame
   239  			Expect(f.Data).To(Equal([]byte("obar")))
   240  			Eventually(done).Should(BeClosed())
   241  		})
   242  
   243  		It("popStreamFrame returns nil if no data is available", func() {
   244  			_, ok, hasMoreData := str.popStreamFrame(1000, protocol.Version1)
   245  			Expect(ok).To(BeFalse())
   246  			Expect(hasMoreData).To(BeFalse())
   247  		})
   248  
   249  		It("says if it has more data for writing", func() {
   250  			done := make(chan struct{})
   251  			go func() {
   252  				defer GinkgoRecover()
   253  				defer close(done)
   254  				mockSender.EXPECT().onHasStreamData(streamID)
   255  				n, err := strWithTimeout.Write(bytes.Repeat([]byte{0}, 100))
   256  				Expect(err).ToNot(HaveOccurred())
   257  				Expect(n).To(Equal(100))
   258  			}()
   259  			waitForWrite()
   260  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).Times(2)
   261  			mockFC.EXPECT().AddBytesSent(gomock.Any()).Times(2)
   262  			frame, ok, hasMoreData := str.popStreamFrame(50, protocol.Version1)
   263  			Expect(ok).To(BeTrue())
   264  			Expect(frame.Frame.Fin).To(BeFalse())
   265  			Expect(hasMoreData).To(BeTrue())
   266  			frame, ok, hasMoreData = str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   267  			Expect(ok).To(BeTrue())
   268  			Expect(frame.Frame.Fin).To(BeFalse())
   269  			Expect(hasMoreData).To(BeFalse())
   270  			_, ok, _ = str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   271  			Expect(ok).To(BeFalse())
   272  			Eventually(done).Should(BeClosed())
   273  		})
   274  
   275  		It("copies the slice while writing", func() {
   276  			frameHeaderSize := protocol.ByteCount(4)
   277  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).Times(2)
   278  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(1))
   279  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(2))
   280  			s := []byte("foo")
   281  			done := make(chan struct{})
   282  			go func() {
   283  				defer GinkgoRecover()
   284  				defer close(done)
   285  				mockSender.EXPECT().onHasStreamData(streamID)
   286  				n, err := strWithTimeout.Write(s)
   287  				Expect(err).ToNot(HaveOccurred())
   288  				Expect(n).To(Equal(3))
   289  			}()
   290  			waitForWrite()
   291  			frame, ok, _ := str.popStreamFrame(frameHeaderSize+1, protocol.Version1)
   292  			Expect(ok).To(BeTrue())
   293  			f := frame.Frame
   294  			Expect(f.Data).To(Equal([]byte("f")))
   295  			frame, ok, _ = str.popStreamFrame(100, protocol.Version1)
   296  			Expect(ok).To(BeTrue())
   297  			Expect(frame).ToNot(BeNil())
   298  			f = frame.Frame
   299  			Expect(f.Data).To(Equal([]byte("oo")))
   300  			s[1] = 'e'
   301  			Expect(f.Data).To(Equal([]byte("oo")))
   302  			Eventually(done).Should(BeClosed())
   303  		})
   304  
   305  		It("returns when given a nil input", func() {
   306  			n, err := strWithTimeout.Write(nil)
   307  			Expect(n).To(BeZero())
   308  			Expect(err).ToNot(HaveOccurred())
   309  		})
   310  
   311  		It("returns when given an empty slice", func() {
   312  			n, err := strWithTimeout.Write([]byte(""))
   313  			Expect(n).To(BeZero())
   314  			Expect(err).ToNot(HaveOccurred())
   315  		})
   316  
   317  		It("cancels the context when Close is called", func() {
   318  			mockSender.EXPECT().onHasStreamData(streamID)
   319  			Expect(str.Context().Done()).ToNot(BeClosed())
   320  			Expect(str.Close()).To(Succeed())
   321  			Expect(str.Context().Done()).To(BeClosed())
   322  			Expect(context.Cause(str.Context())).To(MatchError(context.Canceled))
   323  		})
   324  
   325  		Context("flow control blocking", func() {
   326  			It("queues a BLOCKED frame if the stream is flow control blocked", func() {
   327  				mockFC.EXPECT().SendWindowSize().Return(protocol.ByteCount(0))
   328  				mockFC.EXPECT().IsNewlyBlocked().Return(true, protocol.ByteCount(12))
   329  				mockSender.EXPECT().queueControlFrame(&wire.StreamDataBlockedFrame{
   330  					StreamID:          streamID,
   331  					MaximumStreamData: 12,
   332  				})
   333  				done := make(chan struct{})
   334  				go func() {
   335  					defer GinkgoRecover()
   336  					defer close(done)
   337  					mockSender.EXPECT().onHasStreamData(streamID)
   338  					_, err := str.Write([]byte("foobar"))
   339  					Expect(err).ToNot(HaveOccurred())
   340  				}()
   341  				waitForWrite()
   342  				_, ok, hasMoreData := str.popStreamFrame(1000, protocol.Version1)
   343  				Expect(ok).To(BeFalse())
   344  				Expect(hasMoreData).To(BeFalse())
   345  				// make the Write go routine return
   346  				str.closeForShutdown(nil)
   347  				Eventually(done).Should(BeClosed())
   348  			})
   349  
   350  			It("says that it doesn't have any more data, when it is flow control blocked", func() {
   351  				done := make(chan struct{})
   352  				go func() {
   353  					defer GinkgoRecover()
   354  					defer close(done)
   355  					mockSender.EXPECT().onHasStreamData(streamID)
   356  					_, err := str.Write([]byte("foobar"))
   357  					Expect(err).ToNot(HaveOccurred())
   358  				}()
   359  				waitForWrite()
   360  
   361  				// first pop a STREAM frame of the maximum size allowed by flow control
   362  				mockFC.EXPECT().SendWindowSize().Return(protocol.ByteCount(3))
   363  				mockFC.EXPECT().AddBytesSent(protocol.ByteCount(3))
   364  				f, ok, hasMoreData := str.popStreamFrame(expectedFrameHeaderLen(0)+3, protocol.Version1)
   365  				Expect(ok).To(BeTrue())
   366  				Expect(f).ToNot(BeNil())
   367  				Expect(hasMoreData).To(BeTrue())
   368  
   369  				// try to pop again, this time noticing that we're blocked
   370  				mockFC.EXPECT().SendWindowSize()
   371  				// don't use offset 3 here, to make sure the BLOCKED frame contains the number returned by the flow controller
   372  				mockFC.EXPECT().IsNewlyBlocked().Return(true, protocol.ByteCount(10))
   373  				mockSender.EXPECT().queueControlFrame(&wire.StreamDataBlockedFrame{
   374  					StreamID:          streamID,
   375  					MaximumStreamData: 10,
   376  				})
   377  				_, ok, hasMoreData = str.popStreamFrame(1000, protocol.Version1)
   378  				Expect(ok).To(BeFalse())
   379  				Expect(hasMoreData).To(BeFalse())
   380  				// make the Write go routine return
   381  				str.closeForShutdown(nil)
   382  				Eventually(done).Should(BeClosed())
   383  			})
   384  		})
   385  
   386  		Context("deadlines", func() {
   387  			It("returns an error when Write is called after the deadline", func() {
   388  				str.SetWriteDeadline(time.Now().Add(-time.Second))
   389  				n, err := strWithTimeout.Write([]byte("foobar"))
   390  				Expect(err).To(MatchError(errDeadline))
   391  				Expect(n).To(BeZero())
   392  			})
   393  
   394  			It("unblocks after the deadline", func() {
   395  				mockSender.EXPECT().onHasStreamData(streamID)
   396  				deadline := time.Now().Add(scaleDuration(50 * time.Millisecond))
   397  				str.SetWriteDeadline(deadline)
   398  				n, err := strWithTimeout.Write(getData(5000))
   399  				Expect(err).To(MatchError(errDeadline))
   400  				Expect(n).To(BeZero())
   401  				Expect(time.Now()).To(BeTemporally("~", deadline, scaleDuration(20*time.Millisecond)))
   402  			})
   403  
   404  			It("unblocks when the deadline is changed to the past", func() {
   405  				mockSender.EXPECT().onHasStreamData(streamID)
   406  				str.SetWriteDeadline(time.Now().Add(time.Hour))
   407  				done := make(chan struct{})
   408  				go func() {
   409  					defer GinkgoRecover()
   410  					_, err := str.Write(getData(5000))
   411  					Expect(err).To(MatchError(errDeadline))
   412  					close(done)
   413  				}()
   414  				Consistently(done).ShouldNot(BeClosed())
   415  				str.SetWriteDeadline(time.Now().Add(-time.Hour))
   416  				Eventually(done).Should(BeClosed())
   417  			})
   418  
   419  			It("returns the number of bytes written, when the deadline expires", func() {
   420  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).AnyTimes()
   421  				mockFC.EXPECT().AddBytesSent(gomock.Any())
   422  				deadline := time.Now().Add(scaleDuration(50 * time.Millisecond))
   423  				str.SetWriteDeadline(deadline)
   424  				var n int
   425  				writeReturned := make(chan struct{})
   426  				go func() {
   427  					defer GinkgoRecover()
   428  					defer close(writeReturned)
   429  					mockSender.EXPECT().onHasStreamData(streamID)
   430  					var err error
   431  					n, err = strWithTimeout.Write(getData(5000))
   432  					Expect(err).To(MatchError(errDeadline))
   433  					Expect(time.Now()).To(BeTemporally("~", deadline, scaleDuration(20*time.Millisecond)))
   434  				}()
   435  				waitForWrite()
   436  				frame, ok, hasMoreData := str.popStreamFrame(50, protocol.Version1)
   437  				Expect(ok).To(BeTrue())
   438  				Expect(frame).ToNot(BeNil())
   439  				Expect(hasMoreData).To(BeTrue())
   440  				Eventually(writeReturned, scaleDuration(80*time.Millisecond)).Should(BeClosed())
   441  				Expect(n).To(BeEquivalentTo(frame.Frame.DataLen()))
   442  			})
   443  
   444  			It("doesn't pop any data after the deadline expired", func() {
   445  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).AnyTimes()
   446  				mockFC.EXPECT().AddBytesSent(gomock.Any())
   447  				deadline := time.Now().Add(scaleDuration(50 * time.Millisecond))
   448  				str.SetWriteDeadline(deadline)
   449  				writeReturned := make(chan struct{})
   450  				go func() {
   451  					defer GinkgoRecover()
   452  					defer close(writeReturned)
   453  					mockSender.EXPECT().onHasStreamData(streamID)
   454  					_, err := strWithTimeout.Write(getData(5000))
   455  					Expect(err).To(MatchError(errDeadline))
   456  				}()
   457  				waitForWrite()
   458  				frame, ok, hasMoreData := str.popStreamFrame(50, protocol.Version1)
   459  				Expect(ok).To(BeTrue())
   460  				Expect(frame).ToNot(BeNil())
   461  				Expect(hasMoreData).To(BeTrue())
   462  				Eventually(writeReturned, scaleDuration(80*time.Millisecond)).Should(BeClosed())
   463  				_, ok, hasMoreData = str.popStreamFrame(50, protocol.Version1)
   464  				Expect(ok).To(BeFalse())
   465  				Expect(hasMoreData).To(BeFalse())
   466  			})
   467  
   468  			It("doesn't unblock if the deadline is changed before the first one expires", func() {
   469  				mockSender.EXPECT().onHasStreamData(streamID)
   470  				deadline1 := time.Now().Add(scaleDuration(50 * time.Millisecond))
   471  				deadline2 := time.Now().Add(scaleDuration(100 * time.Millisecond))
   472  				str.SetWriteDeadline(deadline1)
   473  				done := make(chan struct{})
   474  				go func() {
   475  					defer GinkgoRecover()
   476  					time.Sleep(scaleDuration(20 * time.Millisecond))
   477  					str.SetWriteDeadline(deadline2)
   478  					// make sure that this was actually execute before the deadline expires
   479  					Expect(time.Now()).To(BeTemporally("<", deadline1))
   480  					close(done)
   481  				}()
   482  				runtime.Gosched()
   483  				n, err := strWithTimeout.Write(getData(5000))
   484  				Expect(err).To(MatchError(errDeadline))
   485  				Expect(n).To(BeZero())
   486  				Expect(time.Now()).To(BeTemporally("~", deadline2, scaleDuration(20*time.Millisecond)))
   487  				Eventually(done).Should(BeClosed())
   488  			})
   489  
   490  			It("unblocks earlier, when a new deadline is set", func() {
   491  				mockSender.EXPECT().onHasStreamData(streamID)
   492  				deadline1 := time.Now().Add(scaleDuration(200 * time.Millisecond))
   493  				deadline2 := time.Now().Add(scaleDuration(50 * time.Millisecond))
   494  				done := make(chan struct{})
   495  				go func() {
   496  					defer GinkgoRecover()
   497  					time.Sleep(scaleDuration(10 * time.Millisecond))
   498  					str.SetWriteDeadline(deadline2)
   499  					// make sure that this was actually execute before the deadline expires
   500  					Expect(time.Now()).To(BeTemporally("<", deadline2))
   501  					close(done)
   502  				}()
   503  				str.SetWriteDeadline(deadline1)
   504  				runtime.Gosched()
   505  				_, err := strWithTimeout.Write(getData(5000))
   506  				Expect(err).To(MatchError(errDeadline))
   507  				Expect(time.Now()).To(BeTemporally("~", deadline2, scaleDuration(20*time.Millisecond)))
   508  				Eventually(done).Should(BeClosed())
   509  			})
   510  
   511  			It("doesn't unblock if the deadline is removed", func() {
   512  				mockSender.EXPECT().onHasStreamData(streamID)
   513  				deadline := time.Now().Add(scaleDuration(50 * time.Millisecond))
   514  				str.SetWriteDeadline(deadline)
   515  				deadlineUnset := make(chan struct{})
   516  				go func() {
   517  					defer GinkgoRecover()
   518  					time.Sleep(scaleDuration(20 * time.Millisecond))
   519  					str.SetWriteDeadline(time.Time{})
   520  					// make sure that this was actually execute before the deadline expires
   521  					Expect(time.Now()).To(BeTemporally("<", deadline))
   522  					close(deadlineUnset)
   523  				}()
   524  				done := make(chan struct{})
   525  				go func() {
   526  					defer GinkgoRecover()
   527  					_, err := strWithTimeout.Write(getData(5000))
   528  					Expect(err).To(MatchError("test done"))
   529  					close(done)
   530  				}()
   531  				runtime.Gosched()
   532  				Eventually(deadlineUnset).Should(BeClosed())
   533  				Consistently(done, scaleDuration(100*time.Millisecond)).ShouldNot(BeClosed())
   534  				// make the go routine return
   535  				str.closeForShutdown(errors.New("test done"))
   536  				Eventually(done).Should(BeClosed())
   537  			})
   538  		})
   539  
   540  		Context("closing", func() {
   541  			It("doesn't allow writes after it has been closed", func() {
   542  				mockSender.EXPECT().onHasStreamData(streamID)
   543  				str.Close()
   544  				_, err := strWithTimeout.Write([]byte("foobar"))
   545  				Expect(err).To(MatchError("write on closed stream 1337"))
   546  			})
   547  
   548  			It("allows FIN", func() {
   549  				mockSender.EXPECT().onHasStreamData(streamID)
   550  				str.Close()
   551  				frame, ok, hasMoreData := str.popStreamFrame(1000, protocol.Version1)
   552  				Expect(ok).To(BeTrue())
   553  				Expect(frame).ToNot(BeNil())
   554  				f := frame.Frame
   555  				Expect(f.Data).To(BeEmpty())
   556  				Expect(f.Fin).To(BeTrue())
   557  				Expect(f.DataLenPresent).To(BeTrue())
   558  				Expect(hasMoreData).To(BeFalse())
   559  			})
   560  
   561  			It("doesn't send a FIN when there's still data", func() {
   562  				const frameHeaderLen protocol.ByteCount = 4
   563  				mockSender.EXPECT().onHasStreamData(streamID).Times(2)
   564  				_, err := strWithTimeout.Write([]byte("foobar"))
   565  				Expect(err).ToNot(HaveOccurred())
   566  				Expect(str.Close()).To(Succeed())
   567  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).Times(2)
   568  				mockFC.EXPECT().AddBytesSent(gomock.Any()).Times(2)
   569  				frame, ok, _ := str.popStreamFrame(3+frameHeaderLen, protocol.Version1)
   570  				Expect(ok).To(BeTrue())
   571  				Expect(frame).ToNot(BeNil())
   572  				f := frame.Frame
   573  				Expect(f.Data).To(Equal([]byte("foo")))
   574  				Expect(f.Fin).To(BeFalse())
   575  				frame, ok, _ = str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   576  				Expect(ok).To(BeTrue())
   577  				f = frame.Frame
   578  				Expect(f.Data).To(Equal([]byte("bar")))
   579  				Expect(f.Fin).To(BeTrue())
   580  			})
   581  
   582  			It("doesn't send a FIN when there's still data, for long writes", func() {
   583  				done := make(chan struct{})
   584  				go func() {
   585  					defer GinkgoRecover()
   586  					defer close(done)
   587  					mockSender.EXPECT().onHasStreamData(streamID)
   588  					_, err := strWithTimeout.Write(getData(5000))
   589  					Expect(err).ToNot(HaveOccurred())
   590  					mockSender.EXPECT().onHasStreamData(streamID)
   591  					Expect(str.Close()).To(Succeed())
   592  				}()
   593  				waitForWrite()
   594  				for i := 1; i <= 5; i++ {
   595  					mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
   596  					mockFC.EXPECT().AddBytesSent(gomock.Any())
   597  					if i == 5 {
   598  						Eventually(done).Should(BeClosed())
   599  					}
   600  					frame, ok, _ := str.popStreamFrame(1100, protocol.Version1)
   601  					Expect(ok).To(BeTrue())
   602  					Expect(frame).ToNot(BeNil())
   603  					f := frame.Frame
   604  					Expect(f.Data).To(Equal(getDataAtOffset(f.Offset, f.DataLen())))
   605  					Expect(f.Fin).To(Equal(i == 5)) // the last frame should have the FIN bit set
   606  				}
   607  			})
   608  
   609  			It("doesn't allow FIN after it is closed for shutdown", func() {
   610  				str.closeForShutdown(errors.New("test"))
   611  				_, ok, hasMoreData := str.popStreamFrame(1000, protocol.Version1)
   612  				Expect(ok).To(BeFalse())
   613  				Expect(hasMoreData).To(BeFalse())
   614  
   615  				Expect(str.Close()).To(Succeed())
   616  				_, ok, hasMoreData = str.popStreamFrame(1000, protocol.Version1)
   617  				Expect(ok).To(BeFalse())
   618  				Expect(hasMoreData).To(BeFalse())
   619  			})
   620  
   621  			It("doesn't allow FIN twice", func() {
   622  				mockSender.EXPECT().onHasStreamData(streamID)
   623  				str.Close()
   624  				frame, ok, _ := str.popStreamFrame(1000, protocol.Version1)
   625  				Expect(ok).To(BeTrue())
   626  				Expect(frame).ToNot(BeNil())
   627  				f := frame.Frame
   628  				Expect(f.Data).To(BeEmpty())
   629  				Expect(f.Fin).To(BeTrue())
   630  				_, ok, hasMoreData := str.popStreamFrame(1000, protocol.Version1)
   631  				Expect(ok).To(BeFalse())
   632  				Expect(hasMoreData).To(BeFalse())
   633  			})
   634  		})
   635  
   636  		Context("closing for shutdown", func() {
   637  			testErr := errors.New("test")
   638  
   639  			It("returns errors when the stream is cancelled", func() {
   640  				str.closeForShutdown(testErr)
   641  				n, err := strWithTimeout.Write([]byte("foo"))
   642  				Expect(n).To(BeZero())
   643  				Expect(err).To(MatchError(testErr))
   644  			})
   645  
   646  			It("doesn't get data for writing if an error occurred", func() {
   647  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
   648  				mockFC.EXPECT().AddBytesSent(gomock.Any())
   649  				mockSender.EXPECT().onHasStreamData(streamID)
   650  				done := make(chan struct{})
   651  				go func() {
   652  					defer GinkgoRecover()
   653  					_, err := strWithTimeout.Write(getData(5000))
   654  					Expect(err).To(MatchError(testErr))
   655  					close(done)
   656  				}()
   657  				waitForWrite()
   658  				frame, ok, hasMoreData := str.popStreamFrame(50, protocol.Version1) // get a STREAM frame containing some data, but not all
   659  				Expect(ok).To(BeTrue())
   660  				Expect(frame).ToNot(BeNil())
   661  				Expect(hasMoreData).To(BeTrue())
   662  				str.closeForShutdown(testErr)
   663  				_, ok, hasMoreData = str.popStreamFrame(1000, protocol.Version1)
   664  				Expect(ok).To(BeFalse())
   665  				Expect(hasMoreData).To(BeFalse())
   666  				Eventually(done).Should(BeClosed())
   667  			})
   668  
   669  			It("cancels the context", func() {
   670  				Expect(str.Context().Done()).ToNot(BeClosed())
   671  				str.closeForShutdown(testErr)
   672  				Expect(str.Context().Done()).To(BeClosed())
   673  				Expect(context.Cause(str.Context())).To(MatchError(testErr))
   674  			})
   675  		})
   676  	})
   677  
   678  	Context("handling MAX_STREAM_DATA frames", func() {
   679  		It("informs the flow controller", func() {
   680  			mockFC.EXPECT().UpdateSendWindow(protocol.ByteCount(0x1337))
   681  			str.updateSendWindow(0x1337)
   682  		})
   683  
   684  		It("says when it has data for sending", func() {
   685  			mockFC.EXPECT().UpdateSendWindow(gomock.Any()).Return(true)
   686  			mockSender.EXPECT().onHasStreamData(streamID)
   687  			done := make(chan struct{})
   688  			go func() {
   689  				defer GinkgoRecover()
   690  				_, err := str.Write([]byte("foobar"))
   691  				Expect(err).ToNot(HaveOccurred())
   692  				close(done)
   693  			}()
   694  			waitForWrite()
   695  			mockSender.EXPECT().onHasStreamData(streamID)
   696  			str.updateSendWindow(42)
   697  			// make sure the Write go routine returns
   698  			str.closeForShutdown(nil)
   699  			Eventually(done).Should(BeClosed())
   700  		})
   701  
   702  		It("doesn't say it has data for sending if the MAX_STREAM_DATA frame was reordered", func() {
   703  			mockFC.EXPECT().UpdateSendWindow(gomock.Any()).Return(false) // reordered frame
   704  			mockSender.EXPECT().onHasStreamData(streamID)
   705  			done := make(chan struct{})
   706  			go func() {
   707  				defer GinkgoRecover()
   708  				_, err := str.Write([]byte("foobar"))
   709  				Expect(err).ToNot(HaveOccurred())
   710  				close(done)
   711  			}()
   712  			waitForWrite()
   713  			// don't expect any calls to onHasStreamData
   714  			str.updateSendWindow(42)
   715  			// make sure the Write go routine returns
   716  			str.closeForShutdown(nil)
   717  			Eventually(done).Should(BeClosed())
   718  		})
   719  	})
   720  
   721  	Context("stream cancellations", func() {
   722  		Context("canceling writing", func() {
   723  			It("queues a RESET_STREAM frame", func() {
   724  				gomock.InOrder(
   725  					mockSender.EXPECT().queueControlFrame(&wire.ResetStreamFrame{
   726  						StreamID:  streamID,
   727  						FinalSize: 1234,
   728  						ErrorCode: 9876,
   729  					}),
   730  					mockSender.EXPECT().onStreamCompleted(streamID),
   731  				)
   732  				str.writeOffset = 1234
   733  				str.CancelWrite(9876)
   734  			})
   735  
   736  			// This test is inherently racy, as it tests a concurrent call to Write() and CancelRead().
   737  			// A single successful run of this test therefore doesn't mean a lot,
   738  			// for reliable results it has to be run many times.
   739  			It("returns a nil error when the whole slice has been sent out", func() {
   740  				mockSender.EXPECT().queueControlFrame(gomock.Any()).MaxTimes(1)
   741  				mockSender.EXPECT().onHasStreamData(streamID).MaxTimes(1)
   742  				mockSender.EXPECT().onStreamCompleted(streamID).MaxTimes(1)
   743  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).MaxTimes(1)
   744  				mockFC.EXPECT().AddBytesSent(gomock.Any()).MaxTimes(1)
   745  				errChan := make(chan error)
   746  				go func() {
   747  					defer GinkgoRecover()
   748  					n, err := strWithTimeout.Write(getData(100))
   749  					if n == 0 {
   750  						errChan <- nil
   751  						return
   752  					}
   753  					errChan <- err
   754  				}()
   755  
   756  				runtime.Gosched()
   757  				go str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   758  				go str.CancelWrite(1234)
   759  				Eventually(errChan).Should(Receive(Not(HaveOccurred())))
   760  			})
   761  
   762  			It("unblocks Write", func() {
   763  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   764  				mockSender.EXPECT().onHasStreamData(streamID)
   765  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
   766  				mockFC.EXPECT().AddBytesSent(gomock.Any())
   767  				writeReturned := make(chan struct{})
   768  				var n int
   769  				go func() {
   770  					defer GinkgoRecover()
   771  					var err error
   772  					n, err = strWithTimeout.Write(getData(5000))
   773  					Expect(err).To(Equal(&StreamError{
   774  						StreamID:  streamID,
   775  						ErrorCode: 1234,
   776  						Remote:    false,
   777  					}))
   778  					close(writeReturned)
   779  				}()
   780  				waitForWrite()
   781  				frame, ok, _ := str.popStreamFrame(50, protocol.Version1)
   782  				Expect(ok).To(BeTrue())
   783  				Expect(frame).ToNot(BeNil())
   784  				mockSender.EXPECT().onStreamCompleted(streamID)
   785  				str.CancelWrite(1234)
   786  				Eventually(writeReturned).Should(BeClosed())
   787  				Expect(n).To(BeEquivalentTo(frame.Frame.DataLen()))
   788  			})
   789  
   790  			It("doesn't pop STREAM frames after being canceled", func() {
   791  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   792  				mockSender.EXPECT().onHasStreamData(streamID)
   793  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
   794  				mockFC.EXPECT().AddBytesSent(gomock.Any())
   795  				writeReturned := make(chan struct{})
   796  				go func() {
   797  					defer GinkgoRecover()
   798  					strWithTimeout.Write(getData(100))
   799  					close(writeReturned)
   800  				}()
   801  				waitForWrite()
   802  				frame, ok, hasMoreData := str.popStreamFrame(50, protocol.Version1)
   803  				Expect(ok).To(BeTrue())
   804  				Expect(hasMoreData).To(BeTrue())
   805  				Expect(frame).ToNot(BeNil())
   806  				mockSender.EXPECT().onStreamCompleted(streamID)
   807  				str.CancelWrite(1234)
   808  				_, ok, hasMoreData = str.popStreamFrame(10, protocol.Version1)
   809  				Expect(ok).To(BeFalse())
   810  				Expect(hasMoreData).To(BeFalse())
   811  				Eventually(writeReturned).Should(BeClosed())
   812  			})
   813  
   814  			It("doesn't pop STREAM frames after being canceled, for large writes", func() {
   815  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   816  				mockSender.EXPECT().onHasStreamData(streamID)
   817  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
   818  				mockFC.EXPECT().AddBytesSent(gomock.Any())
   819  				writeReturned := make(chan struct{})
   820  				go func() {
   821  					defer GinkgoRecover()
   822  					_, err := strWithTimeout.Write(getData(5000))
   823  					Expect(err).To(Equal(&StreamError{
   824  						StreamID:  streamID,
   825  						ErrorCode: 1234,
   826  						Remote:    false,
   827  					}))
   828  					close(writeReturned)
   829  				}()
   830  				waitForWrite()
   831  				frame, ok, hasMoreData := str.popStreamFrame(50, protocol.Version1)
   832  				Expect(ok).To(BeTrue())
   833  				Expect(hasMoreData).To(BeTrue())
   834  				Expect(frame).ToNot(BeNil())
   835  				mockSender.EXPECT().onStreamCompleted(streamID)
   836  				str.CancelWrite(1234)
   837  				_, ok, hasMoreData = str.popStreamFrame(10, protocol.Version1)
   838  				Expect(ok).To(BeFalse())
   839  				Expect(hasMoreData).To(BeFalse())
   840  				Eventually(writeReturned).Should(BeClosed())
   841  			})
   842  
   843  			It("ignores acknowledgements for STREAM frames after it was cancelled", func() {
   844  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   845  				mockSender.EXPECT().onHasStreamData(streamID)
   846  				mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
   847  				mockFC.EXPECT().AddBytesSent(gomock.Any())
   848  				writeReturned := make(chan struct{})
   849  				go func() {
   850  					defer GinkgoRecover()
   851  					strWithTimeout.Write(getData(100))
   852  					close(writeReturned)
   853  				}()
   854  				waitForWrite()
   855  				frame, ok, hasMoreData := str.popStreamFrame(50, protocol.Version1)
   856  				Expect(ok).To(BeTrue())
   857  				Expect(hasMoreData).To(BeTrue())
   858  				Expect(frame).ToNot(BeNil())
   859  				mockSender.EXPECT().onStreamCompleted(streamID)
   860  				str.CancelWrite(1234)
   861  				frame.Handler.OnAcked(frame.Frame)
   862  			})
   863  
   864  			It("cancels the context", func() {
   865  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   866  				mockSender.EXPECT().onStreamCompleted(gomock.Any())
   867  				Expect(str.Context().Done()).ToNot(BeClosed())
   868  				str.CancelWrite(1234)
   869  				Expect(str.Context().Done()).To(BeClosed())
   870  				Expect(context.Cause(str.Context())).To(BeAssignableToTypeOf(&StreamError{}))
   871  				Expect(context.Cause(str.Context()).(*StreamError).ErrorCode).To(Equal(StreamErrorCode(1234)))
   872  			})
   873  
   874  			It("doesn't allow further calls to Write", func() {
   875  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   876  				mockSender.EXPECT().onStreamCompleted(gomock.Any())
   877  				str.CancelWrite(1234)
   878  				_, err := strWithTimeout.Write([]byte("foobar"))
   879  				Expect(err).To(MatchError(&StreamError{
   880  					StreamID:  streamID,
   881  					ErrorCode: 1234,
   882  					Remote:    false,
   883  				}))
   884  			})
   885  
   886  			It("only cancels once", func() {
   887  				mockSender.EXPECT().queueControlFrame(&wire.ResetStreamFrame{StreamID: streamID, ErrorCode: 1234})
   888  				mockSender.EXPECT().onStreamCompleted(gomock.Any())
   889  				str.CancelWrite(1234)
   890  				str.CancelWrite(4321)
   891  			})
   892  
   893  			It("queues a RESET_STREAM frame, even if the stream was already closed", func() {
   894  				mockSender.EXPECT().onHasStreamData(streamID)
   895  				mockSender.EXPECT().queueControlFrame(gomock.Any()).Do(func(f wire.Frame) {
   896  					Expect(f).To(BeAssignableToTypeOf(&wire.ResetStreamFrame{}))
   897  				})
   898  				mockSender.EXPECT().onStreamCompleted(gomock.Any())
   899  				Expect(str.Close()).To(Succeed())
   900  				// don't EXPECT any calls to queueControlFrame
   901  				str.CancelWrite(123)
   902  			})
   903  		})
   904  
   905  		Context("receiving STOP_SENDING frames", func() {
   906  			It("queues a RESET_STREAM frames, and copies the error code from the STOP_SENDING frame", func() {
   907  				mockSender.EXPECT().queueControlFrame(&wire.ResetStreamFrame{
   908  					StreamID:  streamID,
   909  					ErrorCode: 101,
   910  				})
   911  				mockSender.EXPECT().onStreamCompleted(gomock.Any())
   912  
   913  				str.handleStopSendingFrame(&wire.StopSendingFrame{
   914  					StreamID:  streamID,
   915  					ErrorCode: 101,
   916  				})
   917  			})
   918  
   919  			It("unblocks Write", func() {
   920  				mockSender.EXPECT().onHasStreamData(streamID)
   921  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   922  				mockSender.EXPECT().onStreamCompleted(gomock.Any())
   923  				done := make(chan struct{})
   924  				go func() {
   925  					defer GinkgoRecover()
   926  					_, err := str.Write(getData(5000))
   927  					Expect(err).To(Equal(&StreamError{
   928  						StreamID:  streamID,
   929  						ErrorCode: 123,
   930  						Remote:    true,
   931  					}))
   932  					close(done)
   933  				}()
   934  				waitForWrite()
   935  				str.handleStopSendingFrame(&wire.StopSendingFrame{
   936  					StreamID:  streamID,
   937  					ErrorCode: 123,
   938  				})
   939  				Eventually(done).Should(BeClosed())
   940  			})
   941  
   942  			It("doesn't allow further calls to Write", func() {
   943  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   944  				mockSender.EXPECT().onStreamCompleted(gomock.Any())
   945  				str.handleStopSendingFrame(&wire.StopSendingFrame{
   946  					StreamID:  streamID,
   947  					ErrorCode: 123,
   948  				})
   949  				_, err := str.Write([]byte("foobar"))
   950  				Expect(err).To(Equal(&StreamError{
   951  					StreamID:  streamID,
   952  					ErrorCode: 123,
   953  					Remote:    true,
   954  				}))
   955  			})
   956  		})
   957  	})
   958  
   959  	Context("retransmissions", func() {
   960  		It("queues and retrieves frames", func() {
   961  			str.numOutstandingFrames = 1
   962  			f := &wire.StreamFrame{
   963  				Data:           []byte("foobar"),
   964  				Offset:         0x42,
   965  				DataLenPresent: false,
   966  			}
   967  			mockSender.EXPECT().onHasStreamData(streamID)
   968  			(*sendStreamAckHandler)(str).OnLost(f)
   969  			frame, ok, _ := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   970  			Expect(ok).To(BeTrue())
   971  			Expect(frame).ToNot(BeNil())
   972  			f = frame.Frame
   973  			Expect(f.Offset).To(Equal(protocol.ByteCount(0x42)))
   974  			Expect(f.Data).To(Equal([]byte("foobar")))
   975  			Expect(f.DataLenPresent).To(BeTrue())
   976  		})
   977  
   978  		It("splits a retransmission", func() {
   979  			str.numOutstandingFrames = 1
   980  			sf := &wire.StreamFrame{
   981  				Data:           []byte("foobar"),
   982  				Offset:         0x42,
   983  				DataLenPresent: false,
   984  			}
   985  			mockSender.EXPECT().onHasStreamData(streamID)
   986  			(*sendStreamAckHandler)(str).OnLost(sf)
   987  			frame, ok, hasMoreData := str.popStreamFrame(sf.Length(protocol.Version1)-3, protocol.Version1)
   988  			Expect(ok).To(BeTrue())
   989  			Expect(frame).ToNot(BeNil())
   990  			f := frame.Frame
   991  			Expect(hasMoreData).To(BeTrue())
   992  			Expect(f.Offset).To(Equal(protocol.ByteCount(0x42)))
   993  			Expect(f.Data).To(Equal([]byte("foo")))
   994  			Expect(f.DataLenPresent).To(BeTrue())
   995  			frame, ok, _ = str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
   996  			Expect(ok).To(BeTrue())
   997  			Expect(frame).ToNot(BeNil())
   998  			f = frame.Frame
   999  			Expect(f.Offset).To(Equal(protocol.ByteCount(0x45)))
  1000  			Expect(f.Data).To(Equal([]byte("bar")))
  1001  			Expect(f.DataLenPresent).To(BeTrue())
  1002  		})
  1003  
  1004  		It("returns nil if the size is too small", func() {
  1005  			str.numOutstandingFrames = 1
  1006  			f := &wire.StreamFrame{
  1007  				Data:           []byte("foobar"),
  1008  				Offset:         0x42,
  1009  				DataLenPresent: false,
  1010  			}
  1011  			mockSender.EXPECT().onHasStreamData(streamID)
  1012  			(*sendStreamAckHandler)(str).OnLost(f)
  1013  			_, ok, hasMoreData := str.popStreamFrame(2, protocol.Version1)
  1014  			Expect(ok).To(BeFalse())
  1015  			Expect(hasMoreData).To(BeTrue())
  1016  		})
  1017  
  1018  		It("queues lost STREAM frames", func() {
  1019  			mockSender.EXPECT().onHasStreamData(streamID)
  1020  			mockFC.EXPECT().SendWindowSize().Return(protocol.ByteCount(9999))
  1021  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(6))
  1022  			done := make(chan struct{})
  1023  			go func() {
  1024  				defer GinkgoRecover()
  1025  				_, err := strWithTimeout.Write([]byte("foobar"))
  1026  				Expect(err).ToNot(HaveOccurred())
  1027  				close(done)
  1028  			}()
  1029  			waitForWrite()
  1030  			frame, ok, _ := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
  1031  			Expect(ok).To(BeTrue())
  1032  			Eventually(done).Should(BeClosed())
  1033  			Expect(frame).ToNot(BeNil())
  1034  			Expect(frame.Frame.Data).To(Equal([]byte("foobar")))
  1035  
  1036  			// now lose the frame
  1037  			mockSender.EXPECT().onHasStreamData(streamID)
  1038  			frame.Handler.OnLost(frame.Frame)
  1039  			newFrame, ok, _ := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
  1040  			Expect(ok).To(BeTrue())
  1041  			Expect(newFrame).ToNot(BeNil())
  1042  			Expect(newFrame.Frame.Data).To(Equal([]byte("foobar")))
  1043  		})
  1044  
  1045  		It("doesn't queue retransmissions for a stream that was canceled", func() {
  1046  			mockSender.EXPECT().onHasStreamData(streamID)
  1047  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount)
  1048  			mockFC.EXPECT().AddBytesSent(protocol.ByteCount(6))
  1049  			done := make(chan struct{})
  1050  			go func() {
  1051  				defer GinkgoRecover()
  1052  				_, err := str.Write([]byte("foobar"))
  1053  				Expect(err).ToNot(HaveOccurred())
  1054  				close(done)
  1055  			}()
  1056  			waitForWrite()
  1057  			f, ok, _ := str.popStreamFrame(100, protocol.Version1)
  1058  			Expect(ok).To(BeTrue())
  1059  			Eventually(done).Should(BeClosed())
  1060  			Expect(f).ToNot(BeNil())
  1061  			gomock.InOrder(
  1062  				mockSender.EXPECT().queueControlFrame(gomock.Any()),
  1063  				mockSender.EXPECT().onStreamCompleted(streamID),
  1064  			)
  1065  			str.CancelWrite(9876)
  1066  			// don't EXPECT any calls to onHasStreamData
  1067  			f.Handler.OnLost(f.Frame)
  1068  			Expect(str.retransmissionQueue).To(BeEmpty())
  1069  		})
  1070  	})
  1071  
  1072  	Context("determining when a stream is completed", func() {
  1073  		BeforeEach(func() {
  1074  			mockFC.EXPECT().SendWindowSize().Return(protocol.MaxByteCount).AnyTimes()
  1075  			mockFC.EXPECT().AddBytesSent(gomock.Any()).AnyTimes()
  1076  		})
  1077  
  1078  		It("says when a stream is completed", func() {
  1079  			mockSender.EXPECT().onHasStreamData(streamID)
  1080  			done := make(chan struct{})
  1081  			go func() {
  1082  				defer GinkgoRecover()
  1083  				_, err := strWithTimeout.Write(make([]byte, 100))
  1084  				Expect(err).ToNot(HaveOccurred())
  1085  				close(done)
  1086  			}()
  1087  			waitForWrite()
  1088  
  1089  			// get a bunch of small frames (max. 20 bytes)
  1090  			var frames []ackhandler.StreamFrame
  1091  			for {
  1092  				frame, ok, hasMoreData := str.popStreamFrame(20, protocol.Version1)
  1093  				if !ok {
  1094  					continue
  1095  				}
  1096  				frames = append(frames, frame)
  1097  				if !hasMoreData {
  1098  					break
  1099  				}
  1100  			}
  1101  			Eventually(done).Should(BeClosed())
  1102  
  1103  			// Acknowledge all frames.
  1104  			// We don't expect the stream to be completed, since we still need to send the FIN.
  1105  			for _, f := range frames {
  1106  				f.Handler.OnAcked(f.Frame)
  1107  			}
  1108  
  1109  			// Now close the stream and acknowledge the FIN.
  1110  			mockSender.EXPECT().onHasStreamData(streamID)
  1111  			Expect(str.Close()).To(Succeed())
  1112  			frame, ok, _ := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
  1113  			Expect(ok).To(BeTrue())
  1114  			Expect(frame).ToNot(BeNil())
  1115  			mockSender.EXPECT().onStreamCompleted(streamID)
  1116  			frame.Handler.OnAcked(frame.Frame)
  1117  		})
  1118  
  1119  		It("says when a stream is completed, if Close() is called before popping the frame", func() {
  1120  			mockSender.EXPECT().onHasStreamData(streamID).Times(2)
  1121  			done := make(chan struct{})
  1122  			go func() {
  1123  				defer GinkgoRecover()
  1124  				_, err := strWithTimeout.Write(make([]byte, 100))
  1125  				Expect(err).ToNot(HaveOccurred())
  1126  				close(done)
  1127  			}()
  1128  			waitForWrite()
  1129  			Eventually(done).Should(BeClosed())
  1130  			Expect(str.Close()).To(Succeed())
  1131  
  1132  			frame, ok, hasMoreData := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
  1133  			Expect(ok).To(BeTrue())
  1134  			Expect(hasMoreData).To(BeFalse())
  1135  			Expect(frame).ToNot(BeNil())
  1136  			Expect(frame.Frame.Fin).To(BeTrue())
  1137  
  1138  			mockSender.EXPECT().onStreamCompleted(streamID)
  1139  			frame.Handler.OnAcked(frame.Frame)
  1140  		})
  1141  
  1142  		It("doesn't say it's completed when there are frames waiting to be retransmitted", func() {
  1143  			mockSender.EXPECT().onHasStreamData(streamID)
  1144  			done := make(chan struct{})
  1145  			go func() {
  1146  				defer GinkgoRecover()
  1147  				_, err := strWithTimeout.Write(getData(100))
  1148  				Expect(err).ToNot(HaveOccurred())
  1149  				mockSender.EXPECT().onHasStreamData(streamID)
  1150  				Expect(str.Close()).To(Succeed())
  1151  				close(done)
  1152  			}()
  1153  			waitForWrite()
  1154  
  1155  			// get a bunch of small frames (max. 20 bytes)
  1156  			var frames []ackhandler.StreamFrame
  1157  			for {
  1158  				frame, ok, _ := str.popStreamFrame(20, protocol.Version1)
  1159  				if !ok {
  1160  					continue
  1161  				}
  1162  				frames = append(frames, frame)
  1163  				if frame.Frame.Fin {
  1164  					break
  1165  				}
  1166  			}
  1167  			Eventually(done).Should(BeClosed())
  1168  
  1169  			// lose the first frame, acknowledge all others
  1170  			for _, f := range frames[1:] {
  1171  				f.Handler.OnAcked(f.Frame)
  1172  			}
  1173  			mockSender.EXPECT().onHasStreamData(streamID)
  1174  			frames[0].Handler.OnLost(frames[0].Frame)
  1175  
  1176  			// get the retransmission and acknowledge it
  1177  			ret, ok, _ := str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
  1178  			Expect(ok).To(BeTrue())
  1179  			Expect(ret).ToNot(BeNil())
  1180  			mockSender.EXPECT().onStreamCompleted(streamID)
  1181  			ret.Handler.OnAcked(ret.Frame)
  1182  		})
  1183  
  1184  		// This test is kind of an integration test.
  1185  		// It writes 4 MB of data, and pops STREAM frames that sometimes are and sometimes aren't limited by flow control.
  1186  		// Half of these STREAM frames are then received and their content saved, while the other half is reported lost
  1187  		// and has to be retransmitted.
  1188  		It("retransmits data until everything has been acknowledged", func() {
  1189  			const dataLen = 1 << 22 // 4 MB
  1190  			mockSender.EXPECT().onHasStreamData(streamID).AnyTimes()
  1191  			mockFC.EXPECT().SendWindowSize().DoAndReturn(func() protocol.ByteCount {
  1192  				return protocol.ByteCount(mrand.Intn(500)) + 50
  1193  			}).AnyTimes()
  1194  			mockFC.EXPECT().AddBytesSent(gomock.Any()).AnyTimes()
  1195  
  1196  			data := make([]byte, dataLen)
  1197  			_, err := rand.Read(data)
  1198  			Expect(err).ToNot(HaveOccurred())
  1199  			done := make(chan struct{})
  1200  			go func() {
  1201  				defer GinkgoRecover()
  1202  				defer close(done)
  1203  				_, err := str.Write(data)
  1204  				Expect(err).ToNot(HaveOccurred())
  1205  				str.Close()
  1206  			}()
  1207  
  1208  			var completed bool
  1209  			mockSender.EXPECT().onStreamCompleted(streamID).Do(func(protocol.StreamID) { completed = true })
  1210  
  1211  			received := make([]byte, dataLen)
  1212  			for {
  1213  				if completed {
  1214  					break
  1215  				}
  1216  				f, ok, _ := str.popStreamFrame(protocol.ByteCount(mrand.Intn(300)+100), protocol.Version1)
  1217  				if !ok {
  1218  					continue
  1219  				}
  1220  				sf := f.Frame
  1221  				// 50%: acknowledge the frame and save the data
  1222  				// 50%: lose the frame
  1223  				if mrand.Intn(100) < 50 {
  1224  					copy(received[sf.Offset:sf.Offset+sf.DataLen()], sf.Data)
  1225  					f.Handler.OnAcked(f.Frame)
  1226  				} else {
  1227  					f.Handler.OnLost(f.Frame)
  1228  				}
  1229  			}
  1230  			Expect(received).To(Equal(data))
  1231  		})
  1232  	})
  1233  })