stream_framer_test.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. package quic
  2. import (
  3. "bytes"
  4. "github.com/golang/mock/gomock"
  5. "github.com/lucas-clemente/quic-go/internal/protocol"
  6. "github.com/lucas-clemente/quic-go/internal/wire"
  7. . "github.com/onsi/ginkgo"
  8. . "github.com/onsi/gomega"
  9. )
  10. var _ = Describe("Stream Framer", func() {
  11. const (
  12. id1 = protocol.StreamID(10)
  13. id2 = protocol.StreamID(11)
  14. )
  15. var (
  16. framer *streamFramer
  17. cryptoStream *MockCryptoStream
  18. stream1, stream2 *MockSendStreamI
  19. streamGetter *MockStreamGetter
  20. )
  21. BeforeEach(func() {
  22. streamGetter = NewMockStreamGetter(mockCtrl)
  23. stream1 = NewMockSendStreamI(mockCtrl)
  24. stream1.EXPECT().StreamID().Return(protocol.StreamID(5)).AnyTimes()
  25. stream2 = NewMockSendStreamI(mockCtrl)
  26. stream2.EXPECT().StreamID().Return(protocol.StreamID(6)).AnyTimes()
  27. cryptoStream = NewMockCryptoStream(mockCtrl)
  28. framer = newStreamFramer(cryptoStream, streamGetter, versionGQUICFrames)
  29. })
  30. Context("handling the crypto stream", func() {
  31. It("says if it has crypto stream data", func() {
  32. Expect(framer.HasCryptoStreamData()).To(BeFalse())
  33. framer.AddActiveStream(framer.version.CryptoStreamID())
  34. Expect(framer.HasCryptoStreamData()).To(BeTrue())
  35. })
  36. It("says that it doesn't have crypto stream data after popping all data", func() {
  37. streamID := framer.version.CryptoStreamID()
  38. f := &wire.StreamFrame{
  39. StreamID: streamID,
  40. Data: []byte("foobar"),
  41. }
  42. cryptoStream.EXPECT().popStreamFrame(protocol.ByteCount(1000)).Return(f, false)
  43. framer.AddActiveStream(streamID)
  44. Expect(framer.PopCryptoStreamFrame(1000)).To(Equal(f))
  45. Expect(framer.HasCryptoStreamData()).To(BeFalse())
  46. })
  47. It("says that it has more crypto stream data if not all data was popped", func() {
  48. streamID := framer.version.CryptoStreamID()
  49. f := &wire.StreamFrame{
  50. StreamID: streamID,
  51. Data: []byte("foobar"),
  52. }
  53. cryptoStream.EXPECT().popStreamFrame(protocol.ByteCount(1000)).Return(f, true)
  54. framer.AddActiveStream(streamID)
  55. Expect(framer.PopCryptoStreamFrame(1000)).To(Equal(f))
  56. Expect(framer.HasCryptoStreamData()).To(BeTrue())
  57. })
  58. })
  59. Context("Popping", func() {
  60. It("returns nil when popping an empty framer", func() {
  61. Expect(framer.PopStreamFrames(1000)).To(BeEmpty())
  62. })
  63. It("returns STREAM frames", func() {
  64. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
  65. f := &wire.StreamFrame{
  66. StreamID: id1,
  67. Data: []byte("foobar"),
  68. Offset: 42,
  69. }
  70. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f, false)
  71. framer.AddActiveStream(id1)
  72. fs := framer.PopStreamFrames(1000)
  73. Expect(fs).To(Equal([]*wire.StreamFrame{f}))
  74. })
  75. It("skips a stream that was reported active, but was completed shortly after", func() {
  76. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(nil, nil)
  77. streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
  78. f := &wire.StreamFrame{
  79. StreamID: id2,
  80. Data: []byte("foobar"),
  81. }
  82. stream2.EXPECT().popStreamFrame(gomock.Any()).Return(f, false)
  83. framer.AddActiveStream(id1)
  84. framer.AddActiveStream(id2)
  85. Expect(framer.PopStreamFrames(1000)).To(Equal([]*wire.StreamFrame{f}))
  86. })
  87. It("skips a stream that was reported active, but doesn't have any data", func() {
  88. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
  89. streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
  90. f := &wire.StreamFrame{
  91. StreamID: id2,
  92. Data: []byte("foobar"),
  93. }
  94. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(nil, false)
  95. stream2.EXPECT().popStreamFrame(gomock.Any()).Return(f, false)
  96. framer.AddActiveStream(id1)
  97. framer.AddActiveStream(id2)
  98. Expect(framer.PopStreamFrames(1000)).To(Equal([]*wire.StreamFrame{f}))
  99. })
  100. It("pops from a stream multiple times, if it has enough data", func() {
  101. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).Times(2)
  102. f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")}
  103. f2 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")}
  104. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f1, true)
  105. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f2, false)
  106. framer.AddActiveStream(id1) // only add it once
  107. Expect(framer.PopStreamFrames(protocol.MinStreamFrameSize)).To(Equal([]*wire.StreamFrame{f1}))
  108. Expect(framer.PopStreamFrames(protocol.MinStreamFrameSize)).To(Equal([]*wire.StreamFrame{f2}))
  109. // no further calls to popStreamFrame, after popStreamFrame said there's no more data
  110. Expect(framer.PopStreamFrames(protocol.MinStreamFrameSize)).To(BeNil())
  111. })
  112. It("re-queues a stream at the end, if it has enough data", func() {
  113. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).Times(2)
  114. streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
  115. f11 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")}
  116. f12 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")}
  117. f2 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")}
  118. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f11, true)
  119. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f12, false)
  120. stream2.EXPECT().popStreamFrame(gomock.Any()).Return(f2, false)
  121. framer.AddActiveStream(id1) // only add it once
  122. framer.AddActiveStream(id2)
  123. Expect(framer.PopStreamFrames(protocol.MinStreamFrameSize)).To(Equal([]*wire.StreamFrame{f11})) // first a frame from stream 1
  124. Expect(framer.PopStreamFrames(protocol.MinStreamFrameSize)).To(Equal([]*wire.StreamFrame{f2})) // then a frame from stream 2
  125. Expect(framer.PopStreamFrames(protocol.MinStreamFrameSize)).To(Equal([]*wire.StreamFrame{f12})) // then another frame from stream 1
  126. })
  127. It("only dequeues data from each stream once per packet", func() {
  128. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
  129. streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
  130. f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")}
  131. f2 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")}
  132. // both streams have more data, and will be re-queued
  133. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f1, true)
  134. stream2.EXPECT().popStreamFrame(gomock.Any()).Return(f2, true)
  135. framer.AddActiveStream(id1)
  136. framer.AddActiveStream(id2)
  137. Expect(framer.PopStreamFrames(1000)).To(Equal([]*wire.StreamFrame{f1, f2}))
  138. })
  139. It("returns multiple normal frames in the order they were reported active", func() {
  140. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
  141. streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
  142. f1 := &wire.StreamFrame{Data: []byte("foobar")}
  143. f2 := &wire.StreamFrame{Data: []byte("foobaz")}
  144. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f1, false)
  145. stream2.EXPECT().popStreamFrame(gomock.Any()).Return(f2, false)
  146. framer.AddActiveStream(id2)
  147. framer.AddActiveStream(id1)
  148. Expect(framer.PopStreamFrames(1000)).To(Equal([]*wire.StreamFrame{f2, f1}))
  149. })
  150. It("only asks a stream for data once, even if it was reported active multiple times", func() {
  151. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
  152. f := &wire.StreamFrame{Data: []byte("foobar")}
  153. stream1.EXPECT().popStreamFrame(gomock.Any()).Return(f, false) // only one call to this function
  154. framer.AddActiveStream(id1)
  155. framer.AddActiveStream(id1)
  156. Expect(framer.PopStreamFrames(1000)).To(HaveLen(1))
  157. })
  158. It("does not pop empty frames", func() {
  159. fs := framer.PopStreamFrames(500)
  160. Expect(fs).To(BeEmpty())
  161. })
  162. It("pops frames that have the minimum size", func() {
  163. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
  164. stream1.EXPECT().popStreamFrame(protocol.MinStreamFrameSize).Return(&wire.StreamFrame{Data: []byte("foobar")}, false)
  165. framer.AddActiveStream(id1)
  166. framer.PopStreamFrames(protocol.MinStreamFrameSize)
  167. })
  168. It("does not pop frames smaller than the minimum size", func() {
  169. // don't expect a call to PopStreamFrame()
  170. framer.PopStreamFrames(protocol.MinStreamFrameSize - 1)
  171. })
  172. It("stops iterating when the remaining size is smaller than the minimum STREAM frame size", func() {
  173. streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
  174. // pop a frame such that the remaining size is one byte less than the minimum STREAM frame size
  175. f := &wire.StreamFrame{
  176. StreamID: id1,
  177. Data: bytes.Repeat([]byte("f"), int(500-protocol.MinStreamFrameSize)),
  178. }
  179. stream1.EXPECT().popStreamFrame(protocol.ByteCount(500)).Return(f, false)
  180. framer.AddActiveStream(id1)
  181. fs := framer.PopStreamFrames(500)
  182. Expect(fs).To(Equal([]*wire.StreamFrame{f}))
  183. })
  184. })
  185. })