github.com/tumi8/quic-go@v0.37.4-tum/receive_stream_test.go (about)

     1  package quic
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"runtime"
     7  	"sync"
     8  	"sync/atomic"
     9  	"time"
    10  
    11  
    12  	"github.com/tumi8/quic-go/noninternal/mocks"
    13  	"github.com/tumi8/quic-go/noninternal/protocol"
    14  	"github.com/tumi8/quic-go/noninternal/wire"
    15  
    16  	"github.com/golang/mock/gomock"
    17  	. "github.com/onsi/ginkgo/v2"
    18  	. "github.com/onsi/gomega"
    19  	"github.com/onsi/gomega/gbytes"
    20  )
    21  
    22  var _ = Describe("Receive Stream", func() {
    23  	const streamID protocol.StreamID = 1337
    24  
    25  	var (
    26  		str            *receiveStream
    27  		strWithTimeout io.Reader // str wrapped with gbytes.TimeoutReader
    28  		mockFC         *mocks.MockStreamFlowController
    29  		mockSender     *MockStreamSender
    30  	)
    31  
    32  	BeforeEach(func() {
    33  		mockSender = NewMockStreamSender(mockCtrl)
    34  		mockFC = mocks.NewMockStreamFlowController(mockCtrl)
    35  		str = newReceiveStream(streamID, mockSender, mockFC)
    36  
    37  		timeout := scaleDuration(250 * time.Millisecond)
    38  		strWithTimeout = gbytes.TimeoutReader(str, timeout)
    39  	})
    40  
    41  	It("gets stream id", func() {
    42  		Expect(str.StreamID()).To(Equal(protocol.StreamID(1337)))
    43  	})
    44  
    45  	Context("reading", func() {
    46  		It("reads a single STREAM frame", func() {
    47  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false)
    48  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(4))
    49  			frame := wire.StreamFrame{
    50  				Offset: 0,
    51  				Data:   []byte{0xDE, 0xAD, 0xBE, 0xEF},
    52  			}
    53  			err := str.handleStreamFrame(&frame)
    54  			Expect(err).ToNot(HaveOccurred())
    55  			b := make([]byte, 4)
    56  			n, err := strWithTimeout.Read(b)
    57  			Expect(err).ToNot(HaveOccurred())
    58  			Expect(n).To(Equal(4))
    59  			Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
    60  		})
    61  
    62  		It("reads a single STREAM frame in multiple goes", func() {
    63  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false)
    64  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2))
    65  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2))
    66  			frame := wire.StreamFrame{
    67  				Offset: 0,
    68  				Data:   []byte{0xDE, 0xAD, 0xBE, 0xEF},
    69  			}
    70  			err := str.handleStreamFrame(&frame)
    71  			Expect(err).ToNot(HaveOccurred())
    72  			b := make([]byte, 2)
    73  			n, err := strWithTimeout.Read(b)
    74  			Expect(err).ToNot(HaveOccurred())
    75  			Expect(n).To(Equal(2))
    76  			Expect(b).To(Equal([]byte{0xDE, 0xAD}))
    77  			n, err = strWithTimeout.Read(b)
    78  			Expect(err).ToNot(HaveOccurred())
    79  			Expect(n).To(Equal(2))
    80  			Expect(b).To(Equal([]byte{0xBE, 0xEF}))
    81  		})
    82  
    83  		It("reads all data available", func() {
    84  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false)
    85  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false)
    86  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2)).Times(2)
    87  			frame1 := wire.StreamFrame{
    88  				Offset: 0,
    89  				Data:   []byte{0xDE, 0xAD},
    90  			}
    91  			frame2 := wire.StreamFrame{
    92  				Offset: 2,
    93  				Data:   []byte{0xBE, 0xEF},
    94  			}
    95  			err := str.handleStreamFrame(&frame1)
    96  			Expect(err).ToNot(HaveOccurred())
    97  			err = str.handleStreamFrame(&frame2)
    98  			Expect(err).ToNot(HaveOccurred())
    99  			b := make([]byte, 6)
   100  			n, err := strWithTimeout.Read(b)
   101  			Expect(err).ToNot(HaveOccurred())
   102  			Expect(n).To(Equal(4))
   103  			Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00}))
   104  		})
   105  
   106  		It("assembles multiple STREAM frames", func() {
   107  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false)
   108  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false)
   109  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2)).Times(2)
   110  			frame1 := wire.StreamFrame{
   111  				Offset: 0,
   112  				Data:   []byte{0xDE, 0xAD},
   113  			}
   114  			frame2 := wire.StreamFrame{
   115  				Offset: 2,
   116  				Data:   []byte{0xBE, 0xEF},
   117  			}
   118  			err := str.handleStreamFrame(&frame1)
   119  			Expect(err).ToNot(HaveOccurred())
   120  			err = str.handleStreamFrame(&frame2)
   121  			Expect(err).ToNot(HaveOccurred())
   122  			b := make([]byte, 4)
   123  			n, err := strWithTimeout.Read(b)
   124  			Expect(err).ToNot(HaveOccurred())
   125  			Expect(n).To(Equal(4))
   126  			Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
   127  		})
   128  
   129  		It("waits until data is available", func() {
   130  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false)
   131  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2))
   132  			go func() {
   133  				defer GinkgoRecover()
   134  				frame := wire.StreamFrame{Data: []byte{0xDE, 0xAD}}
   135  				time.Sleep(10 * time.Millisecond)
   136  				err := str.handleStreamFrame(&frame)
   137  				Expect(err).ToNot(HaveOccurred())
   138  			}()
   139  			b := make([]byte, 2)
   140  			n, err := strWithTimeout.Read(b)
   141  			Expect(err).ToNot(HaveOccurred())
   142  			Expect(n).To(Equal(2))
   143  		})
   144  
   145  		It("handles STREAM frames in wrong order", func() {
   146  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false)
   147  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false)
   148  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2)).Times(2)
   149  			frame1 := wire.StreamFrame{
   150  				Offset: 2,
   151  				Data:   []byte{0xBE, 0xEF},
   152  			}
   153  			frame2 := wire.StreamFrame{
   154  				Offset: 0,
   155  				Data:   []byte{0xDE, 0xAD},
   156  			}
   157  			err := str.handleStreamFrame(&frame1)
   158  			Expect(err).ToNot(HaveOccurred())
   159  			err = str.handleStreamFrame(&frame2)
   160  			Expect(err).ToNot(HaveOccurred())
   161  			b := make([]byte, 4)
   162  			n, err := strWithTimeout.Read(b)
   163  			Expect(err).ToNot(HaveOccurred())
   164  			Expect(n).To(Equal(4))
   165  			Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
   166  		})
   167  
   168  		It("ignores duplicate STREAM frames", func() {
   169  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false)
   170  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false)
   171  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false)
   172  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2)).Times(2)
   173  			frame1 := wire.StreamFrame{
   174  				Offset: 0,
   175  				Data:   []byte{0xDE, 0xAD},
   176  			}
   177  			frame2 := wire.StreamFrame{
   178  				Offset: 0,
   179  				Data:   []byte{0x13, 0x37},
   180  			}
   181  			frame3 := wire.StreamFrame{
   182  				Offset: 2,
   183  				Data:   []byte{0xBE, 0xEF},
   184  			}
   185  			err := str.handleStreamFrame(&frame1)
   186  			Expect(err).ToNot(HaveOccurred())
   187  			err = str.handleStreamFrame(&frame2)
   188  			Expect(err).ToNot(HaveOccurred())
   189  			err = str.handleStreamFrame(&frame3)
   190  			Expect(err).ToNot(HaveOccurred())
   191  			b := make([]byte, 4)
   192  			n, err := strWithTimeout.Read(b)
   193  			Expect(err).ToNot(HaveOccurred())
   194  			Expect(n).To(Equal(4))
   195  			Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
   196  		})
   197  
   198  		It("doesn't rejects a STREAM frames with an overlapping data range", func() {
   199  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false)
   200  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false)
   201  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2))
   202  			mockFC.EXPECT().AddBytesRead(protocol.ByteCount(4))
   203  			frame1 := wire.StreamFrame{
   204  				Offset: 0,
   205  				Data:   []byte("foob"),
   206  			}
   207  			frame2 := wire.StreamFrame{
   208  				Offset: 2,
   209  				Data:   []byte("obar"),
   210  			}
   211  			err := str.handleStreamFrame(&frame1)
   212  			Expect(err).ToNot(HaveOccurred())
   213  			err = str.handleStreamFrame(&frame2)
   214  			Expect(err).ToNot(HaveOccurred())
   215  			b := make([]byte, 6)
   216  			n, err := strWithTimeout.Read(b)
   217  			Expect(err).ToNot(HaveOccurred())
   218  			Expect(n).To(Equal(6))
   219  			Expect(b).To(Equal([]byte("foobar")))
   220  		})
   221  
   222  		Context("deadlines", func() {
   223  			It("the deadline error has the right net.Error properties", func() {
   224  				Expect(errDeadline.Timeout()).To(BeTrue())
   225  				Expect(errDeadline).To(MatchError("deadline exceeded"))
   226  			})
   227  
   228  			It("returns an error when Read is called after the deadline", func() {
   229  				mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false).AnyTimes()
   230  				f := &wire.StreamFrame{Data: []byte("foobar")}
   231  				err := str.handleStreamFrame(f)
   232  				Expect(err).ToNot(HaveOccurred())
   233  				str.SetReadDeadline(time.Now().Add(-time.Second))
   234  				b := make([]byte, 6)
   235  				n, err := strWithTimeout.Read(b)
   236  				Expect(err).To(MatchError(errDeadline))
   237  				Expect(n).To(BeZero())
   238  			})
   239  
   240  			It("unblocks when the deadline is changed to the past", func() {
   241  				str.SetReadDeadline(time.Now().Add(time.Hour))
   242  				done := make(chan struct{})
   243  				go func() {
   244  					defer GinkgoRecover()
   245  					_, err := str.Read(make([]byte, 6))
   246  					Expect(err).To(MatchError(errDeadline))
   247  					close(done)
   248  				}()
   249  				Consistently(done).ShouldNot(BeClosed())
   250  				str.SetReadDeadline(time.Now().Add(-time.Hour))
   251  				Eventually(done).Should(BeClosed())
   252  			})
   253  
   254  			It("unblocks after the deadline", func() {
   255  				deadline := time.Now().Add(scaleDuration(50 * time.Millisecond))
   256  				str.SetReadDeadline(deadline)
   257  				b := make([]byte, 6)
   258  				n, err := strWithTimeout.Read(b)
   259  				Expect(err).To(MatchError(errDeadline))
   260  				Expect(n).To(BeZero())
   261  				Expect(time.Now()).To(BeTemporally("~", deadline, scaleDuration(20*time.Millisecond)))
   262  			})
   263  
   264  			It("doesn't unblock if the deadline is changed before the first one expires", func() {
   265  				deadline1 := time.Now().Add(scaleDuration(50 * time.Millisecond))
   266  				deadline2 := time.Now().Add(scaleDuration(100 * time.Millisecond))
   267  				str.SetReadDeadline(deadline1)
   268  				go func() {
   269  					defer GinkgoRecover()
   270  					time.Sleep(scaleDuration(20 * time.Millisecond))
   271  					str.SetReadDeadline(deadline2)
   272  					// make sure that this was actually execute before the deadline expires
   273  					Expect(time.Now()).To(BeTemporally("<", deadline1))
   274  				}()
   275  				runtime.Gosched()
   276  				b := make([]byte, 10)
   277  				n, err := strWithTimeout.Read(b)
   278  				Expect(err).To(MatchError(errDeadline))
   279  				Expect(n).To(BeZero())
   280  				Expect(time.Now()).To(BeTemporally("~", deadline2, scaleDuration(20*time.Millisecond)))
   281  			})
   282  
   283  			It("unblocks earlier, when a new deadline is set", func() {
   284  				deadline1 := time.Now().Add(scaleDuration(200 * time.Millisecond))
   285  				deadline2 := time.Now().Add(scaleDuration(50 * time.Millisecond))
   286  				go func() {
   287  					defer GinkgoRecover()
   288  					time.Sleep(scaleDuration(10 * time.Millisecond))
   289  					str.SetReadDeadline(deadline2)
   290  					// make sure that this was actually execute before the deadline expires
   291  					Expect(time.Now()).To(BeTemporally("<", deadline2))
   292  				}()
   293  				str.SetReadDeadline(deadline1)
   294  				runtime.Gosched()
   295  				b := make([]byte, 10)
   296  				_, err := strWithTimeout.Read(b)
   297  				Expect(err).To(MatchError(errDeadline))
   298  				Expect(time.Now()).To(BeTemporally("~", deadline2, scaleDuration(25*time.Millisecond)))
   299  			})
   300  
   301  			It("doesn't unblock if the deadline is removed", func() {
   302  				deadline := time.Now().Add(scaleDuration(50 * time.Millisecond))
   303  				str.SetReadDeadline(deadline)
   304  				deadlineUnset := make(chan struct{})
   305  				go func() {
   306  					defer GinkgoRecover()
   307  					time.Sleep(scaleDuration(20 * time.Millisecond))
   308  					str.SetReadDeadline(time.Time{})
   309  					// make sure that this was actually execute before the deadline expires
   310  					Expect(time.Now()).To(BeTemporally("<", deadline))
   311  					close(deadlineUnset)
   312  				}()
   313  				done := make(chan struct{})
   314  				go func() {
   315  					defer GinkgoRecover()
   316  					_, err := strWithTimeout.Read(make([]byte, 1))
   317  					Expect(err).To(MatchError("test done"))
   318  					close(done)
   319  				}()
   320  				runtime.Gosched()
   321  				Eventually(deadlineUnset).Should(BeClosed())
   322  				Consistently(done, scaleDuration(100*time.Millisecond)).ShouldNot(BeClosed())
   323  				// make the go routine return
   324  				str.closeForShutdown(errors.New("test done"))
   325  				Eventually(done).Should(BeClosed())
   326  			})
   327  		})
   328  
   329  		Context("closing", func() {
   330  			Context("with FIN bit", func() {
   331  				It("returns EOFs", func() {
   332  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), true)
   333  					mockFC.EXPECT().AddBytesRead(protocol.ByteCount(4))
   334  					str.handleStreamFrame(&wire.StreamFrame{
   335  						Offset: 0,
   336  						Data:   []byte{0xDE, 0xAD, 0xBE, 0xEF},
   337  						Fin:    true,
   338  					})
   339  					mockSender.EXPECT().onStreamCompleted(streamID)
   340  					b := make([]byte, 4)
   341  					n, err := strWithTimeout.Read(b)
   342  					Expect(err).To(MatchError(io.EOF))
   343  					Expect(n).To(Equal(4))
   344  					Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
   345  					n, err = strWithTimeout.Read(b)
   346  					Expect(n).To(BeZero())
   347  					Expect(err).To(MatchError(io.EOF))
   348  				})
   349  
   350  				It("handles out-of-order frames", func() {
   351  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false)
   352  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), true)
   353  					mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2)).Times(2)
   354  					frame1 := wire.StreamFrame{
   355  						Offset: 2,
   356  						Data:   []byte{0xBE, 0xEF},
   357  						Fin:    true,
   358  					}
   359  					frame2 := wire.StreamFrame{
   360  						Offset: 0,
   361  						Data:   []byte{0xDE, 0xAD},
   362  					}
   363  					err := str.handleStreamFrame(&frame1)
   364  					Expect(err).ToNot(HaveOccurred())
   365  					err = str.handleStreamFrame(&frame2)
   366  					Expect(err).ToNot(HaveOccurred())
   367  					mockSender.EXPECT().onStreamCompleted(streamID)
   368  					b := make([]byte, 4)
   369  					n, err := strWithTimeout.Read(b)
   370  					Expect(err).To(MatchError(io.EOF))
   371  					Expect(n).To(Equal(4))
   372  					Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
   373  					n, err = strWithTimeout.Read(b)
   374  					Expect(n).To(BeZero())
   375  					Expect(err).To(MatchError(io.EOF))
   376  				})
   377  
   378  				It("returns EOFs with partial read", func() {
   379  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), true)
   380  					mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2))
   381  					err := str.handleStreamFrame(&wire.StreamFrame{
   382  						Offset: 0,
   383  						Data:   []byte{0xde, 0xad},
   384  						Fin:    true,
   385  					})
   386  					Expect(err).ToNot(HaveOccurred())
   387  					mockSender.EXPECT().onStreamCompleted(streamID)
   388  					b := make([]byte, 4)
   389  					n, err := strWithTimeout.Read(b)
   390  					Expect(err).To(MatchError(io.EOF))
   391  					Expect(n).To(Equal(2))
   392  					Expect(b[:n]).To(Equal([]byte{0xde, 0xad}))
   393  				})
   394  
   395  				It("handles immediate FINs", func() {
   396  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(0), true)
   397  					mockFC.EXPECT().AddBytesRead(protocol.ByteCount(0))
   398  					err := str.handleStreamFrame(&wire.StreamFrame{
   399  						Offset: 0,
   400  						Fin:    true,
   401  					})
   402  					Expect(err).ToNot(HaveOccurred())
   403  					mockSender.EXPECT().onStreamCompleted(streamID)
   404  					b := make([]byte, 4)
   405  					n, err := strWithTimeout.Read(b)
   406  					Expect(n).To(BeZero())
   407  					Expect(err).To(MatchError(io.EOF))
   408  				})
   409  
   410  				// Calling Read concurrently doesn't make any sense (and is forbidden),
   411  				// but we still want to make sure that we don't complete the stream more than once
   412  				// if the user misuses our API.
   413  				// This would lead to an INTERNAL_ERROR ("tried to delete unknown outgoing stream"),
   414  				// which can be hard to debug.
   415  				// Note that even without the protection built into the receiveStream, this test
   416  				// is very timing-dependent, and would need to run a few hundred times to trigger the failure.
   417  				It("handles concurrent reads", func() {
   418  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), gomock.Any()).AnyTimes()
   419  					var bytesRead protocol.ByteCount
   420  					mockFC.EXPECT().AddBytesRead(gomock.Any()).Do(func(n protocol.ByteCount) { bytesRead += n }).AnyTimes()
   421  
   422  					var numCompleted int32
   423  					mockSender.EXPECT().onStreamCompleted(streamID).Do(func(protocol.StreamID) {
   424  						atomic.AddInt32(&numCompleted, 1)
   425  					}).AnyTimes()
   426  					const num = 3
   427  					var wg sync.WaitGroup
   428  					wg.Add(num)
   429  					for i := 0; i < num; i++ {
   430  						go func() {
   431  							defer wg.Done()
   432  							defer GinkgoRecover()
   433  							_, err := str.Read(make([]byte, 8))
   434  							Expect(err).To(MatchError(io.EOF))
   435  						}()
   436  					}
   437  					str.handleStreamFrame(&wire.StreamFrame{
   438  						Offset: 0,
   439  						Data:   []byte("foobar"),
   440  						Fin:    true,
   441  					})
   442  					wg.Wait()
   443  					Expect(bytesRead).To(BeEquivalentTo(6))
   444  					Expect(atomic.LoadInt32(&numCompleted)).To(BeEquivalentTo(1))
   445  				})
   446  			})
   447  
   448  			It("closes when CloseRemote is called", func() {
   449  				mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(0), true)
   450  				mockFC.EXPECT().AddBytesRead(protocol.ByteCount(0))
   451  				str.CloseRemote(0)
   452  				mockSender.EXPECT().onStreamCompleted(streamID)
   453  				b := make([]byte, 8)
   454  				n, err := strWithTimeout.Read(b)
   455  				Expect(n).To(BeZero())
   456  				Expect(err).To(MatchError(io.EOF))
   457  			})
   458  		})
   459  
   460  		Context("closing for shutdown", func() {
   461  			testErr := errors.New("test error")
   462  
   463  			It("immediately returns all reads", func() {
   464  				done := make(chan struct{})
   465  				b := make([]byte, 4)
   466  				go func() {
   467  					defer GinkgoRecover()
   468  					n, err := strWithTimeout.Read(b)
   469  					Expect(n).To(BeZero())
   470  					Expect(err).To(MatchError(testErr))
   471  					close(done)
   472  				}()
   473  				Consistently(done).ShouldNot(BeClosed())
   474  				str.closeForShutdown(testErr)
   475  				Eventually(done).Should(BeClosed())
   476  			})
   477  
   478  			It("errors for all following reads", func() {
   479  				str.closeForShutdown(testErr)
   480  				b := make([]byte, 1)
   481  				n, err := strWithTimeout.Read(b)
   482  				Expect(n).To(BeZero())
   483  				Expect(err).To(MatchError(testErr))
   484  			})
   485  		})
   486  	})
   487  
   488  	Context("stream cancellations", func() {
   489  		Context("canceling read", func() {
   490  			It("unblocks Read", func() {
   491  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   492  				done := make(chan struct{})
   493  				go func() {
   494  					defer GinkgoRecover()
   495  					_, err := strWithTimeout.Read([]byte{0})
   496  					Expect(err).To(Equal(&StreamError{
   497  						StreamID:  streamID,
   498  						ErrorCode: 1234,
   499  						Remote:    false,
   500  					}))
   501  					close(done)
   502  				}()
   503  				Consistently(done).ShouldNot(BeClosed())
   504  				str.CancelRead(1234)
   505  				Eventually(done).Should(BeClosed())
   506  			})
   507  
   508  			It("doesn't allow further calls to Read", func() {
   509  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   510  				str.CancelRead(1234)
   511  				_, err := strWithTimeout.Read([]byte{0})
   512  				Expect(err).To(Equal(&StreamError{
   513  					StreamID:  streamID,
   514  					ErrorCode: 1234,
   515  					Remote:    false,
   516  				}))
   517  			})
   518  
   519  			It("does nothing when CancelRead is called twice", func() {
   520  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   521  				str.CancelRead(1234)
   522  				str.CancelRead(1234)
   523  				_, err := strWithTimeout.Read([]byte{0})
   524  				Expect(err).To(Equal(&StreamError{
   525  					StreamID:  streamID,
   526  					ErrorCode: 1234,
   527  					Remote:    false,
   528  				}))
   529  			})
   530  
   531  			It("queues a STOP_SENDING frame", func() {
   532  				mockSender.EXPECT().queueControlFrame(&wire.StopSendingFrame{
   533  					StreamID:  streamID,
   534  					ErrorCode: 1234,
   535  				})
   536  				str.CancelRead(1234)
   537  			})
   538  
   539  			It("doesn't send a STOP_SENDING frame, if the FIN was already read", func() {
   540  				mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), true)
   541  				mockFC.EXPECT().AddBytesRead(protocol.ByteCount(6))
   542  				// no calls to mockSender.queueControlFrame
   543  				Expect(str.handleStreamFrame(&wire.StreamFrame{
   544  					StreamID: streamID,
   545  					Data:     []byte("foobar"),
   546  					Fin:      true,
   547  				})).To(Succeed())
   548  				mockSender.EXPECT().onStreamCompleted(streamID)
   549  				_, err := strWithTimeout.Read(make([]byte, 100))
   550  				Expect(err).To(MatchError(io.EOF))
   551  				str.CancelRead(1234)
   552  			})
   553  
   554  			It("doesn't send a STOP_SENDING frame, if the stream was already reset", func() {
   555  				gomock.InOrder(
   556  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true),
   557  					mockFC.EXPECT().Abandon(),
   558  				)
   559  				mockSender.EXPECT().onStreamCompleted(streamID)
   560  				Expect(str.handleResetStreamFrame(&wire.ResetStreamFrame{
   561  					StreamID:  streamID,
   562  					FinalSize: 42,
   563  				})).To(Succeed())
   564  				str.CancelRead(1234)
   565  			})
   566  
   567  			It("sends a STOP_SENDING and completes the stream after receiving the final offset", func() {
   568  				mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(1000), true)
   569  				Expect(str.handleStreamFrame(&wire.StreamFrame{
   570  					Offset: 1000,
   571  					Fin:    true,
   572  				})).To(Succeed())
   573  				mockFC.EXPECT().Abandon()
   574  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   575  				mockSender.EXPECT().onStreamCompleted(streamID)
   576  				str.CancelRead(1234)
   577  			})
   578  
   579  			It("completes the stream when receiving the Fin after the stream was canceled", func() {
   580  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   581  				str.CancelRead(1234)
   582  				gomock.InOrder(
   583  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(1000), true),
   584  					mockFC.EXPECT().Abandon(),
   585  				)
   586  				mockSender.EXPECT().onStreamCompleted(streamID)
   587  				Expect(str.handleStreamFrame(&wire.StreamFrame{
   588  					Offset: 1000,
   589  					Fin:    true,
   590  				})).To(Succeed())
   591  			})
   592  
   593  			It("handles duplicate FinBits after the stream was canceled", func() {
   594  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   595  				str.CancelRead(1234)
   596  				gomock.InOrder(
   597  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(1000), true),
   598  					mockFC.EXPECT().Abandon(),
   599  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(1000), true),
   600  				)
   601  				mockSender.EXPECT().onStreamCompleted(streamID)
   602  				Expect(str.handleStreamFrame(&wire.StreamFrame{
   603  					Offset: 1000,
   604  					Fin:    true,
   605  				})).To(Succeed())
   606  				Expect(str.handleStreamFrame(&wire.StreamFrame{
   607  					Offset: 1000,
   608  					Fin:    true,
   609  				})).To(Succeed())
   610  			})
   611  		})
   612  
   613  		Context("receiving RESET_STREAM frames", func() {
   614  			rst := &wire.ResetStreamFrame{
   615  				StreamID:  streamID,
   616  				FinalSize: 42,
   617  				ErrorCode: 1234,
   618  			}
   619  
   620  			It("unblocks Read", func() {
   621  				done := make(chan struct{})
   622  				go func() {
   623  					defer GinkgoRecover()
   624  					_, err := strWithTimeout.Read([]byte{0})
   625  					Expect(err).To(Equal(&StreamError{
   626  						StreamID:  streamID,
   627  						ErrorCode: 1234,
   628  						Remote:    true,
   629  					}))
   630  					close(done)
   631  				}()
   632  				Consistently(done).ShouldNot(BeClosed())
   633  				mockSender.EXPECT().onStreamCompleted(streamID)
   634  				gomock.InOrder(
   635  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true),
   636  					mockFC.EXPECT().Abandon(),
   637  				)
   638  				Expect(str.handleResetStreamFrame(rst)).To(Succeed())
   639  				Eventually(done).Should(BeClosed())
   640  			})
   641  
   642  			It("doesn't allow further calls to Read", func() {
   643  				mockSender.EXPECT().onStreamCompleted(streamID)
   644  				gomock.InOrder(
   645  					mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true),
   646  					mockFC.EXPECT().Abandon(),
   647  				)
   648  				Expect(str.handleResetStreamFrame(rst)).To(Succeed())
   649  				_, err := strWithTimeout.Read([]byte{0})
   650  				Expect(err).To(MatchError(&StreamError{
   651  					StreamID:  streamID,
   652  					ErrorCode: 1234,
   653  				}))
   654  			})
   655  
   656  			It("errors when receiving a RESET_STREAM with an inconsistent offset", func() {
   657  				testErr := errors.New("already received a different final offset before")
   658  				mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true).Return(testErr)
   659  				err := str.handleResetStreamFrame(rst)
   660  				Expect(err).To(MatchError(testErr))
   661  			})
   662  
   663  			It("ignores duplicate RESET_STREAM frames", func() {
   664  				mockSender.EXPECT().onStreamCompleted(streamID)
   665  				mockFC.EXPECT().Abandon()
   666  				mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true).Times(2)
   667  				Expect(str.handleResetStreamFrame(rst)).To(Succeed())
   668  				Expect(str.handleResetStreamFrame(rst)).To(Succeed())
   669  			})
   670  
   671  			It("doesn't call onStreamCompleted again when the final offset was already received via Fin", func() {
   672  				mockSender.EXPECT().queueControlFrame(gomock.Any())
   673  				str.CancelRead(1234)
   674  				mockSender.EXPECT().onStreamCompleted(streamID)
   675  				mockFC.EXPECT().Abandon()
   676  				mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true).Times(2)
   677  				Expect(str.handleStreamFrame(&wire.StreamFrame{
   678  					StreamID: streamID,
   679  					Offset:   rst.FinalSize,
   680  					Fin:      true,
   681  				})).To(Succeed())
   682  				Expect(str.handleResetStreamFrame(rst)).To(Succeed())
   683  			})
   684  
   685  			It("doesn't do anything when it was closed for shutdown", func() {
   686  				str.closeForShutdown(errors.New("shutdown"))
   687  				err := str.handleResetStreamFrame(rst)
   688  				Expect(err).ToNot(HaveOccurred())
   689  			})
   690  		})
   691  	})
   692  
   693  	Context("flow control", func() {
   694  		It("errors when a STREAM frame causes a flow control violation", func() {
   695  			testErr := errors.New("flow control violation")
   696  			mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(8), false).Return(testErr)
   697  			frame := wire.StreamFrame{
   698  				Offset: 2,
   699  				Data:   []byte("foobar"),
   700  			}
   701  			err := str.handleStreamFrame(&frame)
   702  			Expect(err).To(MatchError(testErr))
   703  		})
   704  
   705  		It("gets a window update", func() {
   706  			mockFC.EXPECT().GetWindowUpdate().Return(protocol.ByteCount(0x100))
   707  			Expect(str.getWindowUpdate()).To(Equal(protocol.ByteCount(0x100)))
   708  		})
   709  	})
   710  })