| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/quic_spdy_stream.h" | 5 #include "net/quic/quic_spdy_stream.h" |
| 6 | 6 |
| 7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 8 | 8 |
| 9 #include "net/quic/quic_connection.h" | 9 #include "net/quic/quic_connection.h" |
| 10 #include "net/quic/quic_utils.h" | 10 #include "net/quic/quic_utils.h" |
| (...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0); | 611 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0); |
| 612 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) | 612 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) |
| 613 .WillOnce(Return(QuicConsumedData(0, fin))); | 613 .WillOnce(Return(QuicConsumedData(0, fin))); |
| 614 | 614 |
| 615 stream_->WriteOrBufferData(body, fin, nullptr); | 615 stream_->WriteOrBufferData(body, fin, nullptr); |
| 616 } | 616 } |
| 617 | 617 |
| 618 TEST_P(QuicSpdyStreamTest, ReceivingTrailers) { | 618 TEST_P(QuicSpdyStreamTest, ReceivingTrailers) { |
| 619 // Test that receiving trailing headers from the peer works, and can be read | 619 // Test that receiving trailing headers from the peer works, and can be read |
| 620 // from the stream and consumed. | 620 // from the stream and consumed. |
| 621 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 622 Initialize(kShouldProcessData); | 621 Initialize(kShouldProcessData); |
| 623 | 622 |
| 624 // Receive initial headers. | 623 // Receive initial headers. |
| 625 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 624 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 626 stream_->OnStreamHeaders(headers); | 625 stream_->OnStreamHeaders(headers); |
| 627 stream_->OnStreamHeadersComplete(false, headers.size()); | 626 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 628 stream_->MarkHeadersConsumed(stream_->decompressed_headers().size()); | 627 stream_->MarkHeadersConsumed(stream_->decompressed_headers().size()); |
| 629 | 628 |
| 630 // Receive trailing headers. | 629 // Receive trailing headers. |
| 631 SpdyHeaderBlock trailers_block; | 630 SpdyHeaderBlock trailers_block; |
| 632 trailers_block["key1"] = "value1"; | 631 trailers_block["key1"] = "value1"; |
| 633 trailers_block["key2"] = "value2"; | 632 trailers_block["key2"] = "value2"; |
| 634 trailers_block["key3"] = "value3"; | 633 trailers_block["key3"] = "value3"; |
| 635 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); | 634 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); |
| 636 stream_->OnStreamHeaders(trailers); | 635 stream_->OnStreamHeaders(trailers); |
| 637 stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size()); | 636 stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size()); |
| 638 | 637 |
| 639 // The trailers should be decompressed, and readable from the stream. | 638 // The trailers should be decompressed, and readable from the stream. |
| 640 EXPECT_TRUE(stream_->trailers_decompressed()); | 639 EXPECT_TRUE(stream_->trailers_decompressed()); |
| 641 const string decompressed_trailers = stream_->decompressed_trailers(); | 640 const string decompressed_trailers = stream_->decompressed_trailers(); |
| 642 EXPECT_EQ(trailers, decompressed_trailers); | 641 EXPECT_EQ(trailers, decompressed_trailers); |
| 643 | 642 |
| 644 // Consuming the trailers erases them from the stream. | 643 // Consuming the trailers erases them from the stream. |
| 645 stream_->MarkTrailersConsumed(decompressed_trailers.size()); | 644 stream_->MarkTrailersConsumed(decompressed_trailers.size()); |
| 646 EXPECT_EQ("", stream_->decompressed_trailers()); | 645 EXPECT_EQ("", stream_->decompressed_trailers()); |
| 647 } | 646 } |
| 648 | 647 |
| 649 TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) { | 648 TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) { |
| 650 // Test that received Trailers must always have the FIN set. | 649 // Test that received Trailers must always have the FIN set. |
| 651 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 652 Initialize(kShouldProcessData); | 650 Initialize(kShouldProcessData); |
| 653 | 651 |
| 654 // Receive initial headers. | 652 // Receive initial headers. |
| 655 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 653 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 656 stream_->OnStreamHeaders(headers); | 654 stream_->OnStreamHeaders(headers); |
| 657 stream_->OnStreamHeadersComplete(false, headers.size()); | 655 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 658 | 656 |
| 659 // Receive trailing headers with FIN deliberately set to false. | 657 // Receive trailing headers with FIN deliberately set to false. |
| 660 SpdyHeaderBlock trailers_block; | 658 SpdyHeaderBlock trailers_block; |
| 661 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); | 659 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); |
| 662 stream_->OnStreamHeaders(trailers); | 660 stream_->OnStreamHeaders(trailers); |
| 663 | 661 |
| 664 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( | 662 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( |
| 665 QUIC_INVALID_HEADERS_STREAM_DATA, _)) | 663 QUIC_INVALID_HEADERS_STREAM_DATA, _)) |
| 666 .Times(1); | 664 .Times(1); |
| 667 stream_->OnStreamHeadersComplete(/*fin=*/false, trailers.size()); | 665 stream_->OnStreamHeadersComplete(/*fin=*/false, trailers.size()); |
| 668 } | 666 } |
| 669 | 667 |
| 670 TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterFin) { | 668 TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterFin) { |
| 671 // If Trailers are sent, neither Headers nor Body should contain a FIN. | 669 // If Trailers are sent, neither Headers nor Body should contain a FIN. |
| 672 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 673 Initialize(kShouldProcessData); | 670 Initialize(kShouldProcessData); |
| 674 | 671 |
| 675 // Receive initial headers with FIN set. | 672 // Receive initial headers with FIN set. |
| 676 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 673 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 677 stream_->OnStreamHeaders(headers); | 674 stream_->OnStreamHeaders(headers); |
| 678 stream_->OnStreamHeadersComplete(/*fin=*/true, headers.size()); | 675 stream_->OnStreamHeadersComplete(/*fin=*/true, headers.size()); |
| 679 | 676 |
| 680 // Receive trailing headers after FIN already received. | 677 // Receive trailing headers after FIN already received. |
| 681 SpdyHeaderBlock trailers_block; | 678 SpdyHeaderBlock trailers_block; |
| 682 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); | 679 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); |
| 683 stream_->OnStreamHeaders(trailers); | 680 stream_->OnStreamHeaders(trailers); |
| 684 | 681 |
| 685 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( | 682 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( |
| 686 QUIC_INVALID_HEADERS_STREAM_DATA, _)) | 683 QUIC_INVALID_HEADERS_STREAM_DATA, _)) |
| 687 .Times(1); | 684 .Times(1); |
| 688 stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size()); | 685 stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size()); |
| 689 } | 686 } |
| 690 | 687 |
| 691 TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) { | 688 TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) { |
| 692 // If body data are received with a FIN, no trailers should then arrive. | 689 // If body data are received with a FIN, no trailers should then arrive. |
| 693 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 694 Initialize(kShouldProcessData); | 690 Initialize(kShouldProcessData); |
| 695 | 691 |
| 696 // Receive initial headers without FIN set. | 692 // Receive initial headers without FIN set. |
| 697 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 693 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 698 stream_->OnStreamHeaders(headers); | 694 stream_->OnStreamHeaders(headers); |
| 699 stream_->OnStreamHeadersComplete(/*fin=*/false, headers.size()); | 695 stream_->OnStreamHeadersComplete(/*fin=*/false, headers.size()); |
| 700 | 696 |
| 701 // Receive body data, with FIN. | 697 // Receive body data, with FIN. |
| 702 QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/true, 0, "body"); | 698 QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/true, 0, "body"); |
| 703 stream_->OnStreamFrame(frame); | 699 stream_->OnStreamFrame(frame); |
| 704 | 700 |
| 705 // Receive trailing headers after FIN already received. | 701 // Receive trailing headers after FIN already received. |
| 706 SpdyHeaderBlock trailers_block; | 702 SpdyHeaderBlock trailers_block; |
| 707 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); | 703 string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block); |
| 708 stream_->OnStreamHeaders(trailers); | 704 stream_->OnStreamHeaders(trailers); |
| 709 | 705 |
| 710 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( | 706 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( |
| 711 QUIC_INVALID_HEADERS_STREAM_DATA, _)) | 707 QUIC_INVALID_HEADERS_STREAM_DATA, _)) |
| 712 .Times(1); | 708 .Times(1); |
| 713 stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size()); | 709 stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size()); |
| 714 } | 710 } |
| 715 | 711 |
| 716 TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) { | 712 TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) { |
| 717 // Verify that a stream receiving headers, body, and no trailers is correctly | 713 // Verify that a stream receiving headers, body, and no trailers is correctly |
| 718 // marked as done reading on consumption of headers and body. | 714 // marked as done reading on consumption of headers and body. |
| 719 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 720 Initialize(kShouldProcessData); | 715 Initialize(kShouldProcessData); |
| 721 | 716 |
| 722 // Receive and consume initial headers with FIN not set. | 717 // Receive and consume initial headers with FIN not set. |
| 723 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 718 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 724 stream_->OnStreamHeaders(headers); | 719 stream_->OnStreamHeaders(headers); |
| 725 stream_->OnStreamHeadersComplete(/*fin=*/false, headers.size()); | 720 stream_->OnStreamHeadersComplete(/*fin=*/false, headers.size()); |
| 726 stream_->MarkHeadersConsumed(headers.size()); | 721 stream_->MarkHeadersConsumed(headers.size()); |
| 727 | 722 |
| 728 // Receive and consume body with FIN set, and no trailers. | 723 // Receive and consume body with FIN set, and no trailers. |
| 729 const string kBody = string(1024, 'x'); | 724 const string kBody = string(1024, 'x'); |
| 730 QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/true, 0, kBody); | 725 QuicStreamFrame frame(kClientDataStreamId1, /*fin=*/true, 0, kBody); |
| 731 stream_->OnStreamFrame(frame); | 726 stream_->OnStreamFrame(frame); |
| 732 | 727 |
| 733 EXPECT_TRUE(stream_->IsDoneReading()); | 728 EXPECT_TRUE(stream_->IsDoneReading()); |
| 734 } | 729 } |
| 735 | 730 |
| 736 TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) { | 731 TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) { |
| 737 // Test that writing trailers will send a FIN, as Trailers are the last thing | 732 // Test that writing trailers will send a FIN, as Trailers are the last thing |
| 738 // to be sent on a stream. | 733 // to be sent on a stream. |
| 739 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 740 Initialize(kShouldProcessData); | 734 Initialize(kShouldProcessData); |
| 741 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) | 735 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) |
| 742 .Times(AnyNumber()) | 736 .Times(AnyNumber()) |
| 743 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); | 737 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); |
| 744 | 738 |
| 745 // Write the initial headers, without a FIN. | 739 // Write the initial headers, without a FIN. |
| 746 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); | 740 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); |
| 747 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); | 741 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); |
| 748 | 742 |
| 749 // Writing trailers implicitly sends a FIN. | 743 // Writing trailers implicitly sends a FIN. |
| 750 SpdyHeaderBlock trailers; | 744 SpdyHeaderBlock trailers; |
| 751 trailers["trailer key"] = "trailer value"; | 745 trailers["trailer key"] = "trailer value"; |
| 752 EXPECT_CALL(*session_, WriteHeaders(_, _, | 746 EXPECT_CALL(*session_, WriteHeaders(_, _, |
| 753 /*fin=*/true, _, _)); | 747 /*fin=*/true, _, _)); |
| 754 stream_->WriteTrailers(trailers, nullptr); | 748 stream_->WriteTrailers(trailers, nullptr); |
| 755 EXPECT_TRUE(stream_->fin_sent()); | 749 EXPECT_TRUE(stream_->fin_sent()); |
| 756 } | 750 } |
| 757 | 751 |
| 758 TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) { | 752 TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) { |
| 759 // Test that when writing trailers, the trailers that are actually sent to the | 753 // Test that when writing trailers, the trailers that are actually sent to the |
| 760 // peer contain the final offset field indicating last byte of data. | 754 // peer contain the final offset field indicating last byte of data. |
| 761 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 762 Initialize(kShouldProcessData); | 755 Initialize(kShouldProcessData); |
| 763 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) | 756 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) |
| 764 .Times(AnyNumber()) | 757 .Times(AnyNumber()) |
| 765 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); | 758 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); |
| 766 | 759 |
| 767 // Write the initial headers. | 760 // Write the initial headers. |
| 768 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); | 761 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); |
| 769 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); | 762 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); |
| 770 | 763 |
| 771 // Write non-zero body data to force a non-zero final offset. | 764 // Write non-zero body data to force a non-zero final offset. |
| 772 const int kBodySize = 1 * 1024; // 1 MB | 765 const int kBodySize = 1 * 1024; // 1 MB |
| 773 stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); | 766 stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); |
| 774 | 767 |
| 775 // The final offset field in the trailing headers is populated with the | 768 // The final offset field in the trailing headers is populated with the |
| 776 // number of body bytes written (including queued bytes). | 769 // number of body bytes written (including queued bytes). |
| 777 SpdyHeaderBlock trailers; | 770 SpdyHeaderBlock trailers; |
| 778 trailers["trailer key"] = "trailer value"; | 771 trailers["trailer key"] = "trailer value"; |
| 779 SpdyHeaderBlock trailers_with_offset = trailers; | 772 SpdyHeaderBlock trailers_with_offset = trailers; |
| 780 trailers_with_offset[kFinalOffsetHeaderKey] = base::IntToString(kBodySize); | 773 trailers_with_offset[kFinalOffsetHeaderKey] = base::IntToString(kBodySize); |
| 781 EXPECT_CALL(*session_, WriteHeaders(_, testing::Eq(trailers_with_offset), | 774 EXPECT_CALL(*session_, WriteHeaders(_, testing::Eq(trailers_with_offset), |
| 782 /*fin=*/true, _, _)); | 775 /*fin=*/true, _, _)); |
| 783 stream_->WriteTrailers(trailers, nullptr); | 776 stream_->WriteTrailers(trailers, nullptr); |
| 784 } | 777 } |
| 785 | 778 |
| 786 TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) { | 779 TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) { |
| 787 // Test that if trailers are written after all other data has been written | 780 // Test that if trailers are written after all other data has been written |
| 788 // (headers and body), that this closes the stream for writing. | 781 // (headers and body), that this closes the stream for writing. |
| 789 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 790 Initialize(kShouldProcessData); | 782 Initialize(kShouldProcessData); |
| 791 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) | 783 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) |
| 792 .Times(AnyNumber()) | 784 .Times(AnyNumber()) |
| 793 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); | 785 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); |
| 794 | 786 |
| 795 // Write the initial headers. | 787 // Write the initial headers. |
| 796 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); | 788 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); |
| 797 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); | 789 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); |
| 798 | 790 |
| 799 // Write non-zero body data. | 791 // Write non-zero body data. |
| 800 const int kBodySize = 1 * 1024; // 1 MB | 792 const int kBodySize = 1 * 1024; // 1 MB |
| 801 stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); | 793 stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); |
| 802 EXPECT_EQ(0u, stream_->queued_data_bytes()); | 794 EXPECT_EQ(0u, stream_->queued_data_bytes()); |
| 803 | 795 |
| 804 // Headers and body have been fully written, there is no queued data. Writing | 796 // Headers and body have been fully written, there is no queued data. Writing |
| 805 // trailers marks the end of this stream, and thus the write side is closed. | 797 // trailers marks the end of this stream, and thus the write side is closed. |
| 806 EXPECT_CALL(*session_, WriteHeaders(_, _, | 798 EXPECT_CALL(*session_, WriteHeaders(_, _, |
| 807 /*fin=*/true, _, _)); | 799 /*fin=*/true, _, _)); |
| 808 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr); | 800 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr); |
| 809 EXPECT_TRUE(stream_->write_side_closed()); | 801 EXPECT_TRUE(stream_->write_side_closed()); |
| 810 } | 802 } |
| 811 | 803 |
| 812 TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) { | 804 TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) { |
| 813 // Test that the stream is not closed for writing when trailers are sent | 805 // Test that the stream is not closed for writing when trailers are sent |
| 814 // while there are still body bytes queued. | 806 // while there are still body bytes queued. |
| 815 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 816 Initialize(kShouldProcessData); | 807 Initialize(kShouldProcessData); |
| 817 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) | 808 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) |
| 818 .Times(AnyNumber()) | 809 .Times(AnyNumber()) |
| 819 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); | 810 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); |
| 820 | 811 |
| 821 // Write the initial headers. | 812 // Write the initial headers. |
| 822 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); | 813 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); |
| 823 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); | 814 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); |
| 824 | 815 |
| 825 // Write non-zero body data, but only consume partially, ensuring queueing. | 816 // Write non-zero body data, but only consume partially, ensuring queueing. |
| 826 const int kBodySize = 1 * 1024; // 1 MB | 817 const int kBodySize = 1 * 1024; // 1 MB |
| 827 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) | 818 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) |
| 828 .WillOnce(Return(QuicConsumedData(kBodySize - 1, false))); | 819 .WillOnce(Return(QuicConsumedData(kBodySize - 1, false))); |
| 829 stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); | 820 stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); |
| 830 EXPECT_EQ(1u, stream_->queued_data_bytes()); | 821 EXPECT_EQ(1u, stream_->queued_data_bytes()); |
| 831 | 822 |
| 832 // Writing trailers will send a FIN, but not close the write side of the | 823 // Writing trailers will send a FIN, but not close the write side of the |
| 833 // stream as there are queued bytes. | 824 // stream as there are queued bytes. |
| 834 EXPECT_CALL(*session_, WriteHeaders(_, _, | 825 EXPECT_CALL(*session_, WriteHeaders(_, _, |
| 835 /*fin=*/true, _, _)); | 826 /*fin=*/true, _, _)); |
| 836 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr); | 827 stream_->WriteTrailers(SpdyHeaderBlock(), nullptr); |
| 837 EXPECT_TRUE(stream_->fin_sent()); | 828 EXPECT_TRUE(stream_->fin_sent()); |
| 838 EXPECT_FALSE(stream_->write_side_closed()); | 829 EXPECT_FALSE(stream_->write_side_closed()); |
| 839 } | 830 } |
| 840 | 831 |
| 841 TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) { | 832 TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) { |
| 842 // Test that it is not possible to write Trailers after a FIN has been sent. | 833 // Test that it is not possible to write Trailers after a FIN has been sent. |
| 843 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 844 Initialize(kShouldProcessData); | 834 Initialize(kShouldProcessData); |
| 845 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) | 835 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) |
| 846 .Times(AnyNumber()) | 836 .Times(AnyNumber()) |
| 847 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); | 837 .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); |
| 848 | 838 |
| 849 // Write the initial headers, with a FIN. | 839 // Write the initial headers, with a FIN. |
| 850 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); | 840 EXPECT_CALL(*session_, WriteHeaders(_, _, _, _, _)); |
| 851 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr); | 841 stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr); |
| 852 EXPECT_TRUE(stream_->fin_sent()); | 842 EXPECT_TRUE(stream_->fin_sent()); |
| 853 | 843 |
| 854 // Writing Trailers should fail, as the FIN has already been sent. | 844 // Writing Trailers should fail, as the FIN has already been sent. |
| 855 // populated with the number of body bytes written. | 845 // populated with the number of body bytes written. |
| 856 EXPECT_DFATAL(stream_->WriteTrailers(SpdyHeaderBlock(), nullptr), | 846 EXPECT_DFATAL(stream_->WriteTrailers(SpdyHeaderBlock(), nullptr), |
| 857 "Trailers cannot be sent after a FIN"); | 847 "Trailers cannot be sent after a FIN"); |
| 858 } | 848 } |
| 859 | 849 |
| 860 } // namespace | 850 } // namespace |
| 861 } // namespace test | 851 } // namespace test |
| 862 } // namespace net | 852 } // namespace net |
| OLD | NEW |