github.com/TugasAkhir-QUIC/quic-go@v0.0.2-0.20240215011318-d20e25a9054c/framer_test.go (about) 1 package quic 2 3 import ( 4 "bytes" 5 6 "golang.org/x/exp/rand" 7 8 "github.com/TugasAkhir-QUIC/quic-go/internal/ackhandler" 9 "github.com/TugasAkhir-QUIC/quic-go/internal/protocol" 10 "github.com/TugasAkhir-QUIC/quic-go/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 id3 = protocol.StreamID(12) 22 ) 23 24 var ( 25 framer framer 26 stream1, stream2, stream3 *MockSendStreamI 27 streamGetter *MockStreamGetter 28 version protocol.Version 29 ) 30 31 BeforeEach(func() { 32 streamGetter = NewMockStreamGetter(mockCtrl) 33 stream1 = NewMockSendStreamI(mockCtrl) 34 stream1.EXPECT().StreamID().Return(id1).AnyTimes() 35 stream2 = NewMockSendStreamI(mockCtrl) 36 stream2.EXPECT().StreamID().Return(id2).AnyTimes() 37 stream3 = NewMockSendStreamI(mockCtrl) 38 stream3.EXPECT().StreamID().Return(id3).AnyTimes() 39 framer = newFramer(streamGetter) 40 }) 41 42 Context("handling control frames", func() { 43 It("adds control frames", func() { 44 mdf := &wire.MaxDataFrame{MaximumData: 0x42} 45 msf := &wire.MaxStreamsFrame{MaxStreamNum: 0x1337} 46 framer.QueueControlFrame(mdf) 47 framer.QueueControlFrame(msf) 48 frames, length := framer.AppendControlFrames(nil, 1000, protocol.Version1) 49 Expect(frames).To(HaveLen(2)) 50 fs := []wire.Frame{frames[0].Frame, frames[1].Frame} 51 Expect(fs).To(ContainElement(mdf)) 52 Expect(fs).To(ContainElement(msf)) 53 Expect(length).To(Equal(mdf.Length(version) + msf.Length(version))) 54 }) 55 56 It("says if it has data", func() { 57 Expect(framer.HasData()).To(BeFalse()) 58 f := &wire.MaxDataFrame{MaximumData: 0x42} 59 framer.QueueControlFrame(f) 60 Expect(framer.HasData()).To(BeTrue()) 61 frames, _ := framer.AppendControlFrames(nil, 1000, protocol.Version1) 62 Expect(frames).To(HaveLen(1)) 63 Expect(framer.HasData()).To(BeFalse()) 64 }) 65 66 It("appends to the slice given", func() { 67 ping := &wire.PingFrame{} 68 mdf := &wire.MaxDataFrame{MaximumData: 0x42} 69 framer.QueueControlFrame(mdf) 70 frames, length := framer.AppendControlFrames([]ackhandler.Frame{{Frame: ping}}, 1000, protocol.Version1) 71 Expect(frames).To(HaveLen(2)) 72 Expect(frames[0].Frame).To(Equal(ping)) 73 Expect(frames[1].Frame).To(Equal(mdf)) 74 Expect(length).To(Equal(mdf.Length(version))) 75 }) 76 77 It("adds the right number of frames", func() { 78 maxSize := protocol.ByteCount(1000) 79 bf := &wire.DataBlockedFrame{MaximumData: 0x1337} 80 bfLen := bf.Length(version) 81 numFrames := int(maxSize / bfLen) // max number of frames that fit into maxSize 82 for i := 0; i < numFrames+1; i++ { 83 framer.QueueControlFrame(bf) 84 } 85 frames, length := framer.AppendControlFrames(nil, maxSize, protocol.Version1) 86 Expect(frames).To(HaveLen(numFrames)) 87 Expect(length).To(BeNumerically(">", maxSize-bfLen)) 88 frames, length = framer.AppendControlFrames(nil, maxSize, protocol.Version1) 89 Expect(frames).To(HaveLen(1)) 90 Expect(length).To(Equal(bfLen)) 91 }) 92 93 It("drops *_BLOCKED frames when 0-RTT is rejected", func() { 94 ping := &wire.PingFrame{} 95 ncid := &wire.NewConnectionIDFrame{ 96 SequenceNumber: 10, 97 ConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}), 98 } 99 frames := []wire.Frame{ 100 &wire.DataBlockedFrame{MaximumData: 1337}, 101 &wire.StreamDataBlockedFrame{StreamID: 42, MaximumStreamData: 1337}, 102 &wire.StreamsBlockedFrame{StreamLimit: 13}, 103 ping, 104 ncid, 105 } 106 rand.Shuffle(len(frames), func(i, j int) { frames[i], frames[j] = frames[j], frames[i] }) 107 for _, f := range frames { 108 framer.QueueControlFrame(f) 109 } 110 Expect(framer.Handle0RTTRejection()).To(Succeed()) 111 fs, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1) 112 Expect(fs).To(HaveLen(2)) 113 Expect(length).To(Equal(ping.Length(version) + ncid.Length(version))) 114 }) 115 }) 116 117 Context("handling PATH_RESPONSE frames", func() { 118 It("packs a single PATH_RESPONSE per packet", func() { 119 f1 := &wire.PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}} 120 f2 := &wire.PathResponseFrame{Data: [8]byte{2, 3, 4, 5, 6, 7, 8, 9}} 121 cf1 := &wire.DataBlockedFrame{MaximumData: 1337} 122 cf2 := &wire.HandshakeDoneFrame{} 123 framer.QueueControlFrame(f1) 124 framer.QueueControlFrame(f2) 125 framer.QueueControlFrame(cf1) 126 framer.QueueControlFrame(cf2) 127 // the first packet should contain a single PATH_RESPONSE frame, but all the other control frames 128 Expect(framer.HasData()).To(BeTrue()) 129 frames, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1) 130 Expect(frames).To(HaveLen(3)) 131 Expect(frames[0].Frame).To(Equal(f1)) 132 Expect([]wire.Frame{frames[1].Frame, frames[2].Frame}).To(ContainElement(cf1)) 133 Expect([]wire.Frame{frames[1].Frame, frames[2].Frame}).To(ContainElement(cf2)) 134 Expect(length).To(Equal(f1.Length(protocol.Version1) + cf1.Length(protocol.Version1) + cf2.Length(protocol.Version1))) 135 // the second packet should contain the other PATH_RESPONSE frame 136 Expect(framer.HasData()).To(BeTrue()) 137 frames, length = framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1) 138 Expect(frames).To(HaveLen(1)) 139 Expect(frames[0].Frame).To(Equal(f2)) 140 Expect(length).To(Equal(f2.Length(protocol.Version1))) 141 Expect(framer.HasData()).To(BeFalse()) 142 }) 143 144 It("limits the number of queued PATH_RESPONSE frames", func() { 145 var pathResponses []*wire.PathResponseFrame 146 for i := 0; i < 2*maxPathResponses; i++ { 147 var f wire.PathResponseFrame 148 rand.Read(f.Data[:]) 149 pathResponses = append(pathResponses, &f) 150 framer.QueueControlFrame(&f) 151 } 152 for i := 0; i < maxPathResponses; i++ { 153 Expect(framer.HasData()).To(BeTrue()) 154 frames, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1) 155 Expect(frames).To(HaveLen(1)) 156 Expect(frames[0].Frame).To(Equal(pathResponses[i])) 157 Expect(length).To(Equal(pathResponses[i].Length(protocol.Version1))) 158 } 159 Expect(framer.HasData()).To(BeFalse()) 160 frames, length := framer.AppendControlFrames(nil, protocol.MaxByteCount, protocol.Version1) 161 Expect(frames).To(BeEmpty()) 162 Expect(length).To(BeZero()) 163 }) 164 }) 165 166 Context("popping STREAM frames", func() { 167 It("returns nil when popping an empty framer", func() { 168 Expect(framer.AppendStreamFrames(nil, 1000, protocol.Version1)).To(BeEmpty()) 169 }) 170 171 It("returns STREAM frames", func() { 172 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil) 173 f := &wire.StreamFrame{ 174 StreamID: id1, 175 Data: []byte("foobar"), 176 Offset: 42, 177 DataLenPresent: true, 178 } 179 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 180 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) 181 framer.AddActiveStream(id1) 182 fs, length := framer.AppendStreamFrames(nil, 1000, protocol.Version1) 183 Expect(fs).To(HaveLen(1)) 184 Expect(fs[0].Frame.DataLenPresent).To(BeFalse()) 185 Expect(length).To(Equal(f.Length(version))) 186 }) 187 188 It("says if it has data", func() { 189 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).Times(2) 190 Expect(framer.HasData()).To(BeFalse()) 191 framer.AddActiveStream(id1) 192 Expect(framer.HasData()).To(BeTrue()) 193 f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foo")} 194 f2 := &wire.StreamFrame{StreamID: id1, Data: []byte("bar")} 195 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 196 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, true) 197 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false) 198 frames, _ := framer.AppendStreamFrames(nil, protocol.MaxByteCount, protocol.Version1) 199 Expect(frames).To(HaveLen(1)) 200 Expect(frames[0].Frame).To(Equal(f1)) 201 Expect(framer.HasData()).To(BeTrue()) 202 frames, _ = framer.AppendStreamFrames(nil, protocol.MaxByteCount, protocol.Version1) 203 Expect(frames).To(HaveLen(1)) 204 Expect(frames[0].Frame).To(Equal(f2)) 205 Expect(framer.HasData()).To(BeFalse()) 206 }) 207 208 It("appends to a frame slice", func() { 209 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil) 210 f := &wire.StreamFrame{ 211 StreamID: id1, 212 Data: []byte("foobar"), 213 DataLenPresent: true, 214 } 215 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 216 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) 217 framer.AddActiveStream(id1) 218 f0 := ackhandler.StreamFrame{Frame: &wire.StreamFrame{StreamID: 9999}} 219 frames := []ackhandler.StreamFrame{f0} 220 fs, length := framer.AppendStreamFrames(frames, 1000, protocol.Version1) 221 Expect(fs).To(HaveLen(2)) 222 Expect(fs[0]).To(Equal(f0)) 223 Expect(fs[1].Frame.Data).To(Equal([]byte("foobar"))) 224 Expect(fs[1].Frame.DataLenPresent).To(BeFalse()) 225 Expect(length).To(Equal(f.Length(version))) 226 }) 227 228 It("skips a stream that was reported active, but was completed shortly after", func() { 229 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(nil, nil).MinTimes(1) 230 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 231 f := &wire.StreamFrame{ 232 StreamID: id2, 233 Data: []byte("foobar"), 234 DataLenPresent: true, 235 } 236 stream2.EXPECT().getPriority().Return(0) 237 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) 238 framer.AddActiveStream(id1) 239 framer.AddActiveStream(id2) 240 frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1) 241 Expect(frames).To(HaveLen(1)) 242 Expect(frames[0].Frame).To(Equal(f)) 243 }) 244 245 It("skips a stream that was reported active, but doesn't have any data", func() { 246 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).MinTimes(1) 247 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 248 f := &wire.StreamFrame{ 249 StreamID: id2, 250 Data: []byte("foobar"), 251 DataLenPresent: true, 252 } 253 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 254 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{}, false, false) 255 stream2.EXPECT().getPriority().Return(0).MinTimes(1) 256 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) 257 framer.AddActiveStream(id1) 258 framer.AddActiveStream(id2) 259 frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1) 260 Expect(frames).To(HaveLen(1)) 261 Expect(frames[0].Frame).To(Equal(f)) 262 }) 263 264 It("pops from a stream multiple times, if it has enough data", func() { 265 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).Times(2) 266 f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")} 267 f2 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")} 268 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 269 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, true) 270 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false) 271 framer.AddActiveStream(id1) // only add it once 272 frames, _ := framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 273 Expect(frames).To(HaveLen(1)) 274 Expect(frames[0].Frame).To(Equal(f1)) 275 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 276 Expect(frames).To(HaveLen(1)) 277 Expect(frames[0].Frame).To(Equal(f2)) 278 // no further calls to popStreamFrame, after popStreamFrame said there's no more data 279 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 280 Expect(frames).To(BeNil()) 281 }) 282 283 It("re-queues a stream at the end, if it has enough data", func() { 284 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).MinTimes(1) 285 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 286 f11 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")} 287 f12 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")} 288 f2 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")} 289 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 290 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f11}, true, true) 291 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f12}, true, false) 292 stream2.EXPECT().getPriority().Return(0).MinTimes(1) 293 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false) 294 framer.AddActiveStream(id1) // only add it once 295 framer.AddActiveStream(id2) 296 // first a frame from stream 1 297 frames, _ := framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 298 Expect(frames).To(HaveLen(1)) 299 Expect(frames[0].Frame).To(Equal(f11)) 300 // then a frame from stream 2 301 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 302 Expect(frames).To(HaveLen(1)) 303 Expect(frames[0].Frame).To(Equal(f2)) 304 // then another frame from stream 1 305 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 306 Expect(frames).To(HaveLen(1)) 307 Expect(frames[0].Frame).To(Equal(f12)) 308 }) 309 310 It("only dequeues data from each stream once per packet", func() { 311 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).MinTimes(1) 312 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 313 f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")} 314 f2 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")} 315 // both streams have more data, and will be re-queued 316 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 317 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, true) 318 stream2.EXPECT().getPriority().Return(0).MinTimes(1) 319 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, true) 320 framer.AddActiveStream(id1) 321 framer.AddActiveStream(id2) 322 frames, length := framer.AppendStreamFrames(nil, 1000, protocol.Version1) 323 Expect(frames).To(HaveLen(2)) 324 Expect(frames[0].Frame).To(Equal(f1)) 325 Expect(frames[1].Frame).To(Equal(f2)) 326 Expect(length).To(Equal(f1.Length(version) + f2.Length(version))) 327 }) 328 329 It("returns multiple normal frames in the order they were reported active", func() { 330 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).MinTimes(1) 331 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 332 f1 := &wire.StreamFrame{Data: []byte("foobar")} 333 f2 := &wire.StreamFrame{Data: []byte("foobaz")} 334 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 335 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, false) 336 stream2.EXPECT().getPriority().Return(0).MinTimes(1) 337 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false) 338 framer.AddActiveStream(id2) 339 framer.AddActiveStream(id1) 340 frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1) 341 Expect(frames).To(HaveLen(2)) 342 Expect(frames[0].Frame).To(Equal(f2)) 343 Expect(frames[1].Frame).To(Equal(f1)) 344 }) 345 346 It("only asks a stream for data once, even if it was reported active multiple times", func() { 347 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil) 348 f := &wire.StreamFrame{Data: []byte("foobar")} 349 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 350 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) // only one call to this function 351 framer.AddActiveStream(id1) 352 framer.AddActiveStream(id1) 353 frames, _ := framer.AppendStreamFrames(nil, 1000, protocol.Version1) 354 Expect(frames).To(HaveLen(1)) 355 }) 356 357 It("does not pop empty frames", func() { 358 fs, length := framer.AppendStreamFrames(nil, 500, protocol.Version1) 359 Expect(fs).To(BeEmpty()) 360 Expect(length).To(BeZero()) 361 }) 362 363 It("pops maximum size STREAM frames", func() { 364 for i := protocol.MinStreamFrameSize; i < 2000; i++ { 365 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil) 366 stream1.EXPECT().getPriority().Return(0) 367 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) { 368 f := &wire.StreamFrame{ 369 StreamID: id1, 370 DataLenPresent: true, 371 } 372 f.Data = make([]byte, f.MaxDataLen(size, v)) 373 Expect(f.Length(version)).To(Equal(size)) 374 return ackhandler.StreamFrame{Frame: f}, true, false 375 }) 376 framer.AddActiveStream(id1) 377 frames, _ := framer.AppendStreamFrames(nil, i, protocol.Version1) 378 Expect(frames).To(HaveLen(1)) 379 f := frames[0].Frame 380 Expect(f.DataLenPresent).To(BeFalse()) 381 Expect(f.Length(version)).To(Equal(i)) 382 } 383 }) 384 385 It("pops multiple STREAM frames", func() { 386 for i := 2 * protocol.MinStreamFrameSize; i < 2000; i++ { 387 // TODO I'm not sure why AnyTimes is needed instead of MinTimes 388 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).AnyTimes() 389 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).AnyTimes() 390 stream1.EXPECT().getPriority().Return(0).AnyTimes() 391 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) { 392 f := &wire.StreamFrame{ 393 StreamID: id2, 394 DataLenPresent: true, 395 } 396 f.Data = make([]byte, f.MaxDataLen(protocol.MinStreamFrameSize, v)) 397 return ackhandler.StreamFrame{Frame: f}, true, false 398 }) 399 stream2.EXPECT().getPriority().Return(0).AnyTimes() 400 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) { 401 f := &wire.StreamFrame{ 402 StreamID: id2, 403 DataLenPresent: true, 404 } 405 f.Data = make([]byte, f.MaxDataLen(size, v)) 406 Expect(f.Length(version)).To(Equal(size)) 407 return ackhandler.StreamFrame{Frame: f}, true, false 408 }) 409 framer.AddActiveStream(id1) 410 framer.AddActiveStream(id2) 411 frames, _ := framer.AppendStreamFrames(nil, i, protocol.Version1) 412 Expect(frames).To(HaveLen(2)) 413 f1 := frames[0].Frame 414 f2 := frames[1].Frame 415 Expect(f1.DataLenPresent).To(BeTrue()) 416 Expect(f2.DataLenPresent).To(BeFalse()) 417 Expect(f1.Length(version) + f2.Length(version)).To(Equal(i)) 418 } 419 }) 420 421 It("pops frames that when asked for the the minimum STREAM frame size", func() { 422 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil) 423 f := &wire.StreamFrame{Data: []byte("foobar")} 424 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 425 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) 426 framer.AddActiveStream(id1) 427 framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 428 }) 429 430 It("does not pop frames smaller than the minimum size", func() { 431 // don't expect a call to PopStreamFrame() 432 framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize-1, protocol.Version1) 433 }) 434 435 It("stops iterating when the remaining size is smaller than the minimum STREAM frame size", func() { 436 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil) 437 // pop a frame such that the remaining size is one byte less than the minimum STREAM frame size 438 f := &wire.StreamFrame{ 439 StreamID: id1, 440 Data: bytes.Repeat([]byte("f"), int(500-protocol.MinStreamFrameSize)), 441 DataLenPresent: true, 442 } 443 stream1.EXPECT().getPriority().Return(0).MinTimes(1) 444 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, true, false) 445 framer.AddActiveStream(id1) 446 fs, length := framer.AppendStreamFrames(nil, 500, protocol.Version1) 447 Expect(fs).To(HaveLen(1)) 448 Expect(fs[0].Frame).To(Equal(f)) 449 Expect(length).To(Equal(f.Length(version))) 450 }) 451 452 It("drops all STREAM frames when 0-RTT is rejected", func() { 453 framer.AddActiveStream(id1) 454 Expect(framer.Handle0RTTRejection()).To(Succeed()) 455 fs, length := framer.AppendStreamFrames(nil, protocol.MaxByteCount, protocol.Version1) 456 Expect(fs).To(BeEmpty()) 457 Expect(length).To(BeZero()) 458 }) 459 460 It("pops streams in priority order", func() { 461 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).MinTimes(1) 462 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 463 streamGetter.EXPECT().GetOrOpenSendStream(id3).Return(stream3, nil).MinTimes(1) 464 465 f1 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")} 466 f2 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")} 467 f3 := &wire.StreamFrame{StreamID: id3, Data: []byte("kixel4")} 468 469 stream1.EXPECT().getPriority().Return(1).MinTimes(1) // lowest priority 470 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f1}, true, false) 471 472 stream2.EXPECT().getPriority().Return(3).MinTimes(1) // highest priority 473 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f2}, true, false) 474 475 stream3.EXPECT().getPriority().Return(2).MinTimes(1) // middle priority 476 stream3.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f3}, true, false) 477 478 framer.AddActiveStream(id1) 479 framer.AddActiveStream(id2) 480 framer.AddActiveStream(id3) 481 482 // stream 2 483 frames, _ := framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 484 Expect(frames).To(HaveLen(1)) 485 Expect(frames[0].Frame).To(Equal(f2)) 486 487 // stream 3 488 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 489 Expect(frames).To(HaveLen(1)) 490 Expect(frames[0].Frame).To(Equal(f3)) 491 492 // stream 1 493 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 494 Expect(frames).To(HaveLen(1)) 495 Expect(frames[0].Frame).To(Equal(f1)) 496 }) 497 498 It("reorders when priority is changed", func() { 499 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).MinTimes(1) 500 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 501 502 f11 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")} 503 f12 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")} 504 f21 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")} 505 f22 := &wire.StreamFrame{StreamID: id2, Data: []byte("zaboof")} 506 507 stream1.EXPECT().getPriority().Return(2).MinTimes(2) // lowest priority 508 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f11}, true, true) 509 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f12}, true, false) 510 511 priority := 3 512 stream2.EXPECT().getPriority().DoAndReturn(func() int { return priority }).MinTimes(1) // highest priority... for now 513 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f21}, true, true) 514 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f22}, true, false) 515 516 framer.AddActiveStream(id1) 517 framer.AddActiveStream(id2) 518 519 // stream 2 520 frames, _ := framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 521 Expect(frames).To(HaveLen(1)) 522 Expect(frames[0].Frame).To(Equal(f21)) 523 524 priority = 1 // now stream 2 is the lowest priority 525 526 // stream 1 527 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 528 Expect(frames).To(HaveLen(1)) 529 Expect(frames[0].Frame).To(Equal(f11)) 530 531 // stream 1 532 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 533 Expect(frames).To(HaveLen(1)) 534 Expect(frames[0].Frame).To(Equal(f12)) 535 536 // stream 2 537 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 538 Expect(frames).To(HaveLen(1)) 539 Expect(frames[0].Frame).To(Equal(f22)) 540 }) 541 542 It("round-robins when priority is equal", func() { 543 streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil).MinTimes(1) 544 streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil).MinTimes(1) 545 streamGetter.EXPECT().GetOrOpenSendStream(id3).Return(stream3, nil).MinTimes(1) 546 547 f11 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobar")} 548 f12 := &wire.StreamFrame{StreamID: id1, Data: []byte("foobaz")} 549 f21 := &wire.StreamFrame{StreamID: id2, Data: []byte("raboof")} 550 f22 := &wire.StreamFrame{StreamID: id2, Data: []byte("zaboof")} 551 f31 := &wire.StreamFrame{StreamID: id3, Data: []byte("kixel4")} 552 f32 := &wire.StreamFrame{StreamID: id3, Data: []byte("pogger")} 553 554 stream1.EXPECT().getPriority().Return(2).MinTimes(2) // highest priority 555 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f11}, true, true) 556 stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f12}, true, false) 557 558 stream2.EXPECT().getPriority().Return(1).MinTimes(1) // lowest priority 559 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f21}, true, true) 560 stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f22}, true, false) 561 562 stream3.EXPECT().getPriority().Return(2).MinTimes(1) // highest priority 563 stream3.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f31}, true, true) 564 stream3.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f32}, true, false) 565 566 framer.AddActiveStream(id1) 567 framer.AddActiveStream(id2) 568 framer.AddActiveStream(id3) 569 570 // stream 1 was added first 571 frames, _ := framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 572 Expect(frames).To(HaveLen(1)) 573 Expect(frames[0].Frame).To(Equal(f11)) 574 575 // stream 3 is equal priority so it goes next 576 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 577 Expect(frames).To(HaveLen(1)) 578 Expect(frames[0].Frame).To(Equal(f31)) 579 580 // stream 1 is equal priority so it goes next 581 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 582 Expect(frames).To(HaveLen(1)) 583 Expect(frames[0].Frame).To(Equal(f12)) 584 585 // stream 3 is highest priority 586 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 587 Expect(frames).To(HaveLen(1)) 588 Expect(frames[0].Frame).To(Equal(f32)) 589 590 // stream 2 finally gets a chance 591 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 592 Expect(frames).To(HaveLen(1)) 593 Expect(frames[0].Frame).To(Equal(f21)) 594 595 // stream 2 finishes 596 frames, _ = framer.AppendStreamFrames(nil, protocol.MinStreamFrameSize, protocol.Version1) 597 Expect(frames).To(HaveLen(1)) 598 Expect(frames[0].Frame).To(Equal(f22)) 599 }) 600 }) 601 })