| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/bidirectional_stream_quic_impl.h" | 5 #include "net/quic/bidirectional_stream_quic_impl.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 int read_buf_len, | 68 int read_buf_len, |
| 69 std::unique_ptr<base::Timer> timer) | 69 std::unique_ptr<base::Timer> timer) |
| 70 : read_buf_(read_buf), | 70 : read_buf_(read_buf), |
| 71 read_buf_len_(read_buf_len), | 71 read_buf_len_(read_buf_len), |
| 72 timer_(std::move(timer)), | 72 timer_(std::move(timer)), |
| 73 loop_(nullptr), | 73 loop_(nullptr), |
| 74 error_(OK), | 74 error_(OK), |
| 75 on_data_read_count_(0), | 75 on_data_read_count_(0), |
| 76 on_data_sent_count_(0), | 76 on_data_sent_count_(0), |
| 77 not_expect_callback_(false), | 77 not_expect_callback_(false), |
| 78 disable_auto_flush_(false) { | 78 send_request_headers_automatically_(true) { |
| 79 loop_.reset(new base::RunLoop); | 79 loop_.reset(new base::RunLoop); |
| 80 } | 80 } |
| 81 | 81 |
| 82 ~TestDelegateBase() override {} | 82 ~TestDelegateBase() override {} |
| 83 | 83 |
| 84 void OnStreamReady() override { | 84 void OnStreamReady(bool request_headers_sent) override { |
| 85 EXPECT_EQ(send_request_headers_automatically_, request_headers_sent); |
| 85 CHECK(!not_expect_callback_); | 86 CHECK(!not_expect_callback_); |
| 86 loop_->Quit(); | 87 loop_->Quit(); |
| 87 } | 88 } |
| 88 | 89 |
| 89 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override { | 90 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override { |
| 90 CHECK(!not_expect_callback_); | 91 CHECK(!not_expect_callback_); |
| 91 | 92 |
| 92 response_headers_ = response_headers; | 93 response_headers_ = response_headers; |
| 93 loop_->Quit(); | 94 loop_->Quit(); |
| 94 } | 95 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 122 CHECK_EQ(OK, error_); | 123 CHECK_EQ(OK, error_); |
| 123 CHECK_NE(OK, error); | 124 CHECK_NE(OK, error); |
| 124 | 125 |
| 125 error_ = error; | 126 error_ = error; |
| 126 loop_->Quit(); | 127 loop_->Quit(); |
| 127 } | 128 } |
| 128 | 129 |
| 129 void Start(const BidirectionalStreamRequestInfo* request_info, | 130 void Start(const BidirectionalStreamRequestInfo* request_info, |
| 130 const BoundNetLog& net_log, | 131 const BoundNetLog& net_log, |
| 131 const base::WeakPtr<QuicChromiumClientSession> session) { | 132 const base::WeakPtr<QuicChromiumClientSession> session) { |
| 132 stream_job_.reset(new BidirectionalStreamQuicImpl(session)); | 133 stream_.reset(new BidirectionalStreamQuicImpl(session)); |
| 133 stream_job_->Start(request_info, net_log, disable_auto_flush_, this, | 134 stream_->Start(request_info, net_log, send_request_headers_automatically_, |
| 134 nullptr); | 135 this, nullptr); |
| 135 } | 136 } |
| 136 | 137 |
| 138 void SendRequestHeaders() { stream_->SendRequestHeaders(); } |
| 139 |
| 137 void SendData(const scoped_refptr<IOBuffer>& data, | 140 void SendData(const scoped_refptr<IOBuffer>& data, |
| 138 int length, | 141 int length, |
| 139 bool end_of_stream) { | 142 bool end_of_stream) { |
| 140 not_expect_callback_ = true; | 143 not_expect_callback_ = true; |
| 141 stream_job_->SendData(data, length, end_of_stream); | 144 stream_->SendData(data, length, end_of_stream); |
| 142 not_expect_callback_ = false; | 145 not_expect_callback_ = false; |
| 143 } | 146 } |
| 144 | 147 |
| 145 void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data, | 148 void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data, |
| 146 const std::vector<int>& lengths, | 149 const std::vector<int>& lengths, |
| 147 bool end_of_stream) { | 150 bool end_of_stream) { |
| 148 not_expect_callback_ = true; | 151 not_expect_callback_ = true; |
| 149 stream_job_->SendvData(data, lengths, end_of_stream); | 152 stream_->SendvData(data, lengths, end_of_stream); |
| 150 not_expect_callback_ = false; | 153 not_expect_callback_ = false; |
| 151 } | 154 } |
| 152 | 155 |
| 153 // Waits until next Delegate callback. | 156 // Waits until next Delegate callback. |
| 154 void WaitUntilNextCallback() { | 157 void WaitUntilNextCallback() { |
| 155 loop_->Run(); | 158 loop_->Run(); |
| 156 loop_.reset(new base::RunLoop); | 159 loop_.reset(new base::RunLoop); |
| 157 } | 160 } |
| 158 | 161 |
| 159 // Calls ReadData on the |stream_| and updates |data_received_|. | 162 // Calls ReadData on the |stream_| and updates |data_received_|. |
| 160 int ReadData(const CompletionCallback& callback) { | 163 int ReadData(const CompletionCallback& callback) { |
| 161 not_expect_callback_ = true; | 164 not_expect_callback_ = true; |
| 162 int rv = stream_job_->ReadData(read_buf_.get(), read_buf_len_); | 165 int rv = stream_->ReadData(read_buf_.get(), read_buf_len_); |
| 163 not_expect_callback_ = false; | 166 not_expect_callback_ = false; |
| 164 if (rv > 0) | 167 if (rv > 0) |
| 165 data_received_.append(read_buf_->data(), rv); | 168 data_received_.append(read_buf_->data(), rv); |
| 166 if (rv == ERR_IO_PENDING) | 169 if (rv == ERR_IO_PENDING) |
| 167 callback_ = callback; | 170 callback_ = callback; |
| 168 return rv; | 171 return rv; |
| 169 } | 172 } |
| 170 | 173 |
| 171 // Cancels |stream_|. | 174 // Cancels |stream_|. |
| 172 void CancelStream() { stream_job_->Cancel(); } | 175 void CancelStream() { stream_->Cancel(); } |
| 173 | 176 |
| 174 NextProto GetProtocol() const { return stream_job_->GetProtocol(); } | 177 NextProto GetProtocol() const { return stream_->GetProtocol(); } |
| 175 | 178 |
| 176 int64_t GetTotalReceivedBytes() const { | 179 int64_t GetTotalReceivedBytes() const { |
| 177 return stream_job_->GetTotalReceivedBytes(); | 180 return stream_->GetTotalReceivedBytes(); |
| 178 } | 181 } |
| 179 | 182 |
| 180 int64_t GetTotalSentBytes() const { return stream_job_->GetTotalSentBytes(); } | 183 int64_t GetTotalSentBytes() const { return stream_->GetTotalSentBytes(); } |
| 181 | 184 |
| 182 void DisableAutoFlush() { disable_auto_flush_ = true; } | 185 void DoNotSendRequestHeadersAutomatically() { |
| 186 send_request_headers_automatically_ = false; |
| 187 } |
| 183 | 188 |
| 184 // Const getters for internal states. | 189 // Const getters for internal states. |
| 185 const std::string& data_received() const { return data_received_; } | 190 const std::string& data_received() const { return data_received_; } |
| 186 int error() const { return error_; } | 191 int error() const { return error_; } |
| 187 const SpdyHeaderBlock& response_headers() const { return response_headers_; } | 192 const SpdyHeaderBlock& response_headers() const { return response_headers_; } |
| 188 const SpdyHeaderBlock& trailers() const { return trailers_; } | 193 const SpdyHeaderBlock& trailers() const { return trailers_; } |
| 189 int on_data_read_count() const { return on_data_read_count_; } | 194 int on_data_read_count() const { return on_data_read_count_; } |
| 190 int on_data_sent_count() const { return on_data_sent_count_; } | 195 int on_data_sent_count() const { return on_data_sent_count_; } |
| 191 | 196 |
| 192 protected: | 197 protected: |
| 193 // Quits |loop_|. | 198 // Quits |loop_|. |
| 194 void QuitLoop() { loop_->Quit(); } | 199 void QuitLoop() { loop_->Quit(); } |
| 195 | 200 |
| 196 // Deletes |stream_|. | 201 // Deletes |stream_|. |
| 197 void DeleteStream() { stream_job_.reset(); } | 202 void DeleteStream() { stream_.reset(); } |
| 198 | 203 |
| 199 private: | 204 private: |
| 200 std::unique_ptr<BidirectionalStreamQuicImpl> stream_job_; | 205 std::unique_ptr<BidirectionalStreamQuicImpl> stream_; |
| 201 scoped_refptr<IOBuffer> read_buf_; | 206 scoped_refptr<IOBuffer> read_buf_; |
| 202 int read_buf_len_; | 207 int read_buf_len_; |
| 203 std::unique_ptr<base::Timer> timer_; | 208 std::unique_ptr<base::Timer> timer_; |
| 204 std::string data_received_; | 209 std::string data_received_; |
| 205 std::unique_ptr<base::RunLoop> loop_; | 210 std::unique_ptr<base::RunLoop> loop_; |
| 206 SpdyHeaderBlock response_headers_; | 211 SpdyHeaderBlock response_headers_; |
| 207 SpdyHeaderBlock trailers_; | 212 SpdyHeaderBlock trailers_; |
| 208 int error_; | 213 int error_; |
| 209 int on_data_read_count_; | 214 int on_data_read_count_; |
| 210 int on_data_sent_count_; | 215 int on_data_sent_count_; |
| 211 // This is to ensure that delegate callback is not invoked synchronously when | 216 // This is to ensure that delegate callback is not invoked synchronously when |
| 212 // calling into |stream_|. | 217 // calling into |stream_|. |
| 213 bool not_expect_callback_; | 218 bool not_expect_callback_; |
| 214 CompletionCallback callback_; | 219 CompletionCallback callback_; |
| 215 bool disable_auto_flush_; | 220 bool send_request_headers_automatically_; |
| 216 | 221 |
| 217 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase); | 222 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase); |
| 218 }; | 223 }; |
| 219 | 224 |
| 220 // A delegate that deletes the stream in a particular callback. | 225 // A delegate that deletes the stream in a particular callback. |
| 221 class DeleteStreamDelegate : public TestDelegateBase { | 226 class DeleteStreamDelegate : public TestDelegateBase { |
| 222 public: | 227 public: |
| 223 // Specifies in which callback the stream can be deleted. | 228 // Specifies in which callback the stream can be deleted. |
| 224 enum Phase { | 229 enum Phase { |
| 225 ON_HEADERS_RECEIVED, | 230 ON_HEADERS_RECEIVED, |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 pos = ExpectLogContainsSomewhere( | 673 pos = ExpectLogContainsSomewhere( |
| 669 entries, /*min_offset=*/pos, | 674 entries, /*min_offset=*/pos, |
| 670 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS, | 675 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS, |
| 671 NetLog::PHASE_NONE); | 676 NetLog::PHASE_NONE); |
| 672 ExpectLogContainsSomewhere( | 677 ExpectLogContainsSomewhere( |
| 673 entries, /*min_offset=*/pos, | 678 entries, /*min_offset=*/pos, |
| 674 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS, | 679 NetLog::TYPE_QUIC_CHROMIUM_CLIENT_STREAM_SEND_REQUEST_HEADERS, |
| 675 NetLog::PHASE_NONE); | 680 NetLog::PHASE_NONE); |
| 676 } | 681 } |
| 677 | 682 |
| 678 TEST_P(BidirectionalStreamQuicImplTest, CoalesceSmallBuffers) { | 683 // Tests that when request headers are not delayed, only data buffers are |
| 684 // coalesced. |
| 685 TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) { |
| 679 SetRequest("POST", "/", DEFAULT_PRIORITY); | 686 SetRequest("POST", "/", DEFAULT_PRIORITY); |
| 680 size_t spdy_request_headers_frame_length; | 687 size_t spdy_request_headers_frame_length; |
| 681 | 688 |
| 689 const char kBody1[] = "here are some data"; |
| 690 const char kBody2[] = "data keep coming"; |
| 691 std::vector<std::string> two_writes = {kBody1, kBody2}; |
| 692 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY, |
| 693 &spdy_request_headers_frame_length)); |
| 694 AddWrite(ConstructClientMultipleDataFramesPacket(2, kIncludeVersion, !kFin, 0, |
| 695 {kBody1, kBody2})); |
| 696 // Ack server's data packet. |
| 697 AddWrite(ConstructClientAckPacket(3, 3, 1)); |
| 698 const char kBody3[] = "hello there"; |
| 699 const char kBody4[] = "another piece of small data"; |
| 700 const char kBody5[] = "really small"; |
| 701 QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2); |
| 702 AddWrite(ConstructClientMultipleDataFramesPacket( |
| 703 4, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5})); |
| 704 |
| 705 Initialize(); |
| 706 |
| 707 BidirectionalStreamRequestInfo request; |
| 708 request.method = "POST"; |
| 709 request.url = GURL("http://www.google.com/"); |
| 710 request.end_stream_on_headers = false; |
| 711 request.priority = DEFAULT_PRIORITY; |
| 712 |
| 713 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); |
| 714 std::unique_ptr<TestDelegateBase> delegate( |
| 715 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); |
| 716 delegate->DoNotSendRequestHeadersAutomatically(); |
| 717 delegate->Start(&request, net_log().bound(), session()->GetWeakPtr()); |
| 718 delegate->WaitUntilNextCallback(); // OnStreamReady |
| 719 |
| 720 // Sends request headers separately, which causes them to be sent in a |
| 721 // separate packet. |
| 722 delegate->SendRequestHeaders(); |
| 723 // Send a Data packet. |
| 724 scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody1)); |
| 725 scoped_refptr<StringIOBuffer> buf2(new StringIOBuffer(kBody2)); |
| 726 |
| 727 std::vector<int> lengths = {buf1->size(), buf2->size()}; |
| 728 delegate->SendvData({buf1, buf2}, lengths, !kFin); |
| 729 delegate->WaitUntilNextCallback(); // OnDataSent |
| 730 |
| 731 // Server acks the request. |
| 732 ProcessPacket(ConstructServerAckPacket(1, 0, 0)); |
| 733 |
| 734 // Server sends the response headers. |
| 735 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); |
| 736 size_t spdy_response_headers_frame_length; |
| 737 QuicStreamOffset offset = 0; |
| 738 ProcessPacket(ConstructResponseHeadersPacket( |
| 739 2, !kFin, response_headers, &spdy_response_headers_frame_length, |
| 740 &offset)); |
| 741 |
| 742 delegate->WaitUntilNextCallback(); // OnHeadersReceived |
| 743 TestCompletionCallback cb; |
| 744 int rv = delegate->ReadData(cb.callback()); |
| 745 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 746 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); |
| 747 const char kResponseBody[] = "Hello world!"; |
| 748 // Server sends data. |
| 749 ProcessPacket( |
| 750 ConstructServerDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody)); |
| 751 |
| 752 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult()); |
| 753 |
| 754 // Send a second Data packet. |
| 755 scoped_refptr<StringIOBuffer> buf3(new StringIOBuffer(kBody3)); |
| 756 scoped_refptr<StringIOBuffer> buf4(new StringIOBuffer(kBody4)); |
| 757 scoped_refptr<StringIOBuffer> buf5(new StringIOBuffer(kBody5)); |
| 758 |
| 759 delegate->SendvData({buf3, buf4, buf5}, |
| 760 {buf3->size(), buf4->size(), buf5->size()}, kFin); |
| 761 delegate->WaitUntilNextCallback(); // OnDataSent |
| 762 |
| 763 size_t spdy_trailers_frame_length; |
| 764 SpdyHeaderBlock trailers; |
| 765 trailers["foo"] = "bar"; |
| 766 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody)); |
| 767 // Server sends trailers. |
| 768 ProcessPacket(ConstructResponseTrailersPacket( |
| 769 4, kFin, trailers, &spdy_trailers_frame_length, &offset)); |
| 770 |
| 771 delegate->WaitUntilNextCallback(); // OnTrailersReceived |
| 772 trailers.erase(kFinalOffsetHeaderKey); |
| 773 EXPECT_EQ(trailers, delegate->trailers()); |
| 774 EXPECT_EQ(OK, delegate->ReadData(cb.callback())); |
| 775 |
| 776 EXPECT_EQ(1, delegate->on_data_read_count()); |
| 777 EXPECT_EQ(2, delegate->on_data_sent_count()); |
| 778 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); |
| 779 EXPECT_EQ( |
| 780 static_cast<int64_t>(spdy_request_headers_frame_length + strlen(kBody1) + |
| 781 strlen(kBody2) + strlen(kBody3) + strlen(kBody4) + |
| 782 strlen(kBody5)), |
| 783 delegate->GetTotalSentBytes()); |
| 784 EXPECT_EQ( |
| 785 static_cast<int64_t>(spdy_response_headers_frame_length + |
| 786 strlen(kResponseBody) + spdy_trailers_frame_length), |
| 787 delegate->GetTotalReceivedBytes()); |
| 788 } |
| 789 |
| 790 // Tests that when request headers are delayed, SendData triggers coalescing of |
| 791 // request headers with data buffers. |
| 792 TEST_P(BidirectionalStreamQuicImplTest, |
| 793 SendDataCoalesceDataBufferAndHeaderFrame) { |
| 794 SetRequest("POST", "/", DEFAULT_PRIORITY); |
| 795 size_t spdy_request_headers_frame_length; |
| 796 |
| 797 const char kBody1[] = "here are some data"; |
| 798 AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket( |
| 799 1, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length, |
| 800 {kBody1})); |
| 801 // Ack server's data packet. |
| 802 AddWrite(ConstructClientAckPacket(2, 3, 1)); |
| 803 const char kBody2[] = "really small"; |
| 804 QuicStreamOffset data_offset = strlen(kBody1); |
| 805 AddWrite(ConstructClientMultipleDataFramesPacket(3, !kIncludeVersion, kFin, |
| 806 data_offset, {kBody2})); |
| 807 |
| 808 Initialize(); |
| 809 |
| 810 BidirectionalStreamRequestInfo request; |
| 811 request.method = "POST"; |
| 812 request.url = GURL("http://www.google.com/"); |
| 813 request.end_stream_on_headers = false; |
| 814 request.priority = DEFAULT_PRIORITY; |
| 815 |
| 816 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); |
| 817 std::unique_ptr<TestDelegateBase> delegate( |
| 818 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); |
| 819 delegate->DoNotSendRequestHeadersAutomatically(); |
| 820 delegate->Start(&request, net_log().bound(), session()->GetWeakPtr()); |
| 821 delegate->WaitUntilNextCallback(); // OnStreamReady |
| 822 |
| 823 // Send a Data packet. |
| 824 scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody1)); |
| 825 |
| 826 delegate->SendData(buf1, buf1->size(), false); |
| 827 delegate->WaitUntilNextCallback(); // OnDataSent |
| 828 |
| 829 // Server acks the request. |
| 830 ProcessPacket(ConstructServerAckPacket(1, 0, 0)); |
| 831 |
| 832 // Server sends the response headers. |
| 833 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); |
| 834 size_t spdy_response_headers_frame_length; |
| 835 QuicStreamOffset offset = 0; |
| 836 ProcessPacket(ConstructResponseHeadersPacket( |
| 837 2, !kFin, response_headers, &spdy_response_headers_frame_length, |
| 838 &offset)); |
| 839 |
| 840 delegate->WaitUntilNextCallback(); // OnHeadersReceived |
| 841 TestCompletionCallback cb; |
| 842 int rv = delegate->ReadData(cb.callback()); |
| 843 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 844 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); |
| 845 const char kResponseBody[] = "Hello world!"; |
| 846 // Server sends data. |
| 847 ProcessPacket( |
| 848 ConstructServerDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody)); |
| 849 |
| 850 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult()); |
| 851 |
| 852 // Send a second Data packet. |
| 853 scoped_refptr<StringIOBuffer> buf2(new StringIOBuffer(kBody2)); |
| 854 |
| 855 delegate->SendData(buf2, buf2->size(), true); |
| 856 delegate->WaitUntilNextCallback(); // OnDataSent |
| 857 |
| 858 size_t spdy_trailers_frame_length; |
| 859 SpdyHeaderBlock trailers; |
| 860 trailers["foo"] = "bar"; |
| 861 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody)); |
| 862 // Server sends trailers. |
| 863 ProcessPacket(ConstructResponseTrailersPacket( |
| 864 4, kFin, trailers, &spdy_trailers_frame_length, &offset)); |
| 865 |
| 866 delegate->WaitUntilNextCallback(); // OnTrailersReceived |
| 867 trailers.erase(kFinalOffsetHeaderKey); |
| 868 EXPECT_EQ(trailers, delegate->trailers()); |
| 869 EXPECT_EQ(OK, delegate->ReadData(cb.callback())); |
| 870 |
| 871 EXPECT_EQ(1, delegate->on_data_read_count()); |
| 872 EXPECT_EQ(2, delegate->on_data_sent_count()); |
| 873 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); |
| 874 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length + |
| 875 strlen(kBody1) + strlen(kBody2)), |
| 876 delegate->GetTotalSentBytes()); |
| 877 EXPECT_EQ( |
| 878 static_cast<int64_t>(spdy_response_headers_frame_length + |
| 879 strlen(kResponseBody) + spdy_trailers_frame_length), |
| 880 delegate->GetTotalReceivedBytes()); |
| 881 } |
| 882 |
| 883 // Tests that when request headers are delayed, SendvData triggers coalescing of |
| 884 // request headers with data buffers. |
| 885 TEST_P(BidirectionalStreamQuicImplTest, |
| 886 SendvDataCoalesceDataBuffersAndHeaderFrame) { |
| 887 SetRequest("POST", "/", DEFAULT_PRIORITY); |
| 888 size_t spdy_request_headers_frame_length; |
| 889 |
| 682 const char kBody1[] = "here are some data"; | 890 const char kBody1[] = "here are some data"; |
| 683 const char kBody2[] = "data keep coming"; | 891 const char kBody2[] = "data keep coming"; |
| 684 std::vector<std::string> two_writes = {kBody1, kBody2}; | 892 std::vector<std::string> two_writes = {kBody1, kBody2}; |
| 685 AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket( | 893 AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket( |
| 686 1, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length, | 894 1, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length, |
| 687 two_writes)); | 895 two_writes)); |
| 688 // Ack server's data packet. | 896 // Ack server's data packet. |
| 689 AddWrite(ConstructClientAckPacket(2, 3, 1)); | 897 AddWrite(ConstructClientAckPacket(2, 3, 1)); |
| 690 const char kBody3[] = "hello there"; | 898 const char kBody3[] = "hello there"; |
| 691 const char kBody4[] = "another piece of small data"; | 899 const char kBody4[] = "another piece of small data"; |
| 692 const char kBody5[] = "really small"; | 900 const char kBody5[] = "really small"; |
| 693 QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2); | 901 QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2); |
| 694 AddWrite(ConstructClientMultipleDataFramesPacket( | 902 AddWrite(ConstructClientMultipleDataFramesPacket( |
| 695 3, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5})); | 903 3, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5})); |
| 696 | 904 |
| 697 Initialize(); | 905 Initialize(); |
| 698 | 906 |
| 699 BidirectionalStreamRequestInfo request; | 907 BidirectionalStreamRequestInfo request; |
| 700 request.method = "POST"; | 908 request.method = "POST"; |
| 701 request.url = GURL("http://www.google.com/"); | 909 request.url = GURL("http://www.google.com/"); |
| 702 request.end_stream_on_headers = false; | 910 request.end_stream_on_headers = false; |
| 703 request.priority = DEFAULT_PRIORITY; | 911 request.priority = DEFAULT_PRIORITY; |
| 704 | 912 |
| 705 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | 913 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); |
| 706 std::unique_ptr<TestDelegateBase> delegate( | 914 std::unique_ptr<TestDelegateBase> delegate( |
| 707 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | 915 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); |
| 708 delegate->DisableAutoFlush(); | 916 delegate->DoNotSendRequestHeadersAutomatically(); |
| 709 delegate->Start(&request, net_log().bound(), session()->GetWeakPtr()); | 917 delegate->Start(&request, net_log().bound(), session()->GetWeakPtr()); |
| 710 delegate->WaitUntilNextCallback(); // OnStreamReady | 918 delegate->WaitUntilNextCallback(); // OnStreamReady |
| 711 | 919 |
| 712 // Send a Data packet. | 920 // Send a Data packet. |
| 713 scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody1)); | 921 scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody1)); |
| 714 scoped_refptr<StringIOBuffer> buf2(new StringIOBuffer(kBody2)); | 922 scoped_refptr<StringIOBuffer> buf2(new StringIOBuffer(kBody2)); |
| 715 | 923 |
| 716 std::vector<int> lengths = {buf1->size(), buf2->size()}; | 924 std::vector<int> lengths = {buf1->size(), buf2->size()}; |
| 717 delegate->SendvData({buf1, buf2}, lengths, !kFin); | 925 delegate->SendvData({buf1, buf2}, lengths, !kFin); |
| 718 delegate->WaitUntilNextCallback(); // OnDataSent | 926 delegate->WaitUntilNextCallback(); // OnDataSent |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 | 1550 |
| 1343 base::MessageLoop::current()->RunUntilIdle(); | 1551 base::MessageLoop::current()->RunUntilIdle(); |
| 1344 | 1552 |
| 1345 EXPECT_EQ(1, delegate->on_data_read_count()); | 1553 EXPECT_EQ(1, delegate->on_data_read_count()); |
| 1346 EXPECT_EQ(0, delegate->on_data_sent_count()); | 1554 EXPECT_EQ(0, delegate->on_data_sent_count()); |
| 1347 } | 1555 } |
| 1348 | 1556 |
| 1349 } // namespace test | 1557 } // namespace test |
| 1350 | 1558 |
| 1351 } // namespace net | 1559 } // namespace net |
| OLD | NEW |