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