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_headers_stream.h" | 5 #include "net/quic/quic_headers_stream.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "net/quic/quic_bug_tracker.h" |
10 #include "net/quic/quic_utils.h" | 11 #include "net/quic/quic_utils.h" |
11 #include "net/quic/spdy_utils.h" | 12 #include "net/quic/spdy_utils.h" |
12 #include "net/quic/test_tools/quic_connection_peer.h" | 13 #include "net/quic/test_tools/quic_connection_peer.h" |
13 #include "net/quic/test_tools/quic_headers_stream_peer.h" | 14 #include "net/quic/test_tools/quic_headers_stream_peer.h" |
14 #include "net/quic/test_tools/quic_spdy_session_peer.h" | 15 #include "net/quic/test_tools/quic_spdy_session_peer.h" |
15 #include "net/quic/test_tools/quic_test_utils.h" | 16 #include "net/quic/test_tools/quic_test_utils.h" |
16 #include "net/quic/test_tools/reliable_quic_stream_peer.h" | 17 #include "net/quic/test_tools/reliable_quic_stream_peer.h" |
17 #include "net/spdy/spdy_alt_svc_wire_format.h" | 18 #include "net/spdy/spdy_alt_svc_wire_format.h" |
18 #include "net/spdy/spdy_flags.h" | 19 #include "net/spdy/spdy_flags.h" |
19 #include "net/spdy/spdy_protocol.h" | 20 #include "net/spdy/spdy_protocol.h" |
20 #include "net/spdy/spdy_test_utils.h" | 21 #include "net/spdy/spdy_test_utils.h" |
21 #include "net/test/gtest_util.h" | 22 #include "net/test/gtest_util.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
23 | 24 |
24 using base::StringPiece; | 25 using base::StringPiece; |
25 using std::ostream; | 26 using std::ostream; |
26 using std::string; | 27 using std::string; |
27 using std::vector; | 28 using std::vector; |
28 using testing::ElementsAre; | 29 using testing::ElementsAre; |
| 30 using testing::_; |
| 31 using testing::AtLeast; |
| 32 using testing::HasSubstr; |
29 using testing::InSequence; | 33 using testing::InSequence; |
30 using testing::Invoke; | 34 using testing::Invoke; |
31 using testing::Return; | 35 using testing::Return; |
32 using testing::StrictMock; | 36 using testing::StrictMock; |
33 using testing::WithArgs; | 37 using testing::WithArgs; |
34 using testing::_; | 38 using testing::_; |
35 | 39 |
36 namespace net { | 40 namespace net { |
37 namespace test { | 41 namespace test { |
38 | 42 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 int weight, | 111 int weight, |
108 bool exclusive)); | 112 bool exclusive)); |
109 MOCK_METHOD3(OnAltSvc, | 113 MOCK_METHOD3(OnAltSvc, |
110 void(SpdyStreamId stream_id, | 114 void(SpdyStreamId stream_id, |
111 StringPiece origin, | 115 StringPiece origin, |
112 const SpdyAltSvcWireFormat::AlternativeServiceVector& | 116 const SpdyAltSvcWireFormat::AlternativeServiceVector& |
113 altsvc_vector)); | 117 altsvc_vector)); |
114 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type)); | 118 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type)); |
115 }; | 119 }; |
116 | 120 |
| 121 class ForceHolAckListener : public QuicAckListenerInterface { |
| 122 public: |
| 123 ForceHolAckListener() : total_acked_bytes_(0) {} |
| 124 |
| 125 void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override { |
| 126 total_acked_bytes_ += acked_bytes; |
| 127 } |
| 128 |
| 129 void OnPacketRetransmitted(int retransmitted_bytes) override {} |
| 130 |
| 131 size_t total_acked_bytes() { return total_acked_bytes_; } |
| 132 |
| 133 private: |
| 134 ~ForceHolAckListener() override {} |
| 135 |
| 136 size_t total_acked_bytes_; |
| 137 |
| 138 DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener); |
| 139 }; |
| 140 |
117 // Run all tests with each version, perspective (client or server), | 141 // Run all tests with each version, perspective (client or server), |
118 // and relevant flag options (false or true) | 142 // and relevant flag options (false or true) |
119 struct TestParams { | 143 struct TestParams { |
120 TestParams(QuicVersion version, Perspective perspective) | 144 TestParams(QuicVersion version, Perspective perspective) |
121 : version(version), perspective(perspective) {} | 145 : version(version), perspective(perspective) {} |
122 | 146 |
123 friend ostream& operator<<(ostream& os, const TestParams& p) { | 147 friend ostream& operator<<(ostream& os, const TestParams& p) { |
124 os << "{ version: " << QuicVersionToString(p.version); | 148 os << "{ version: " << QuicVersionToString(p.version); |
125 os << ", perspective: " << p.perspective << " }"; | 149 os << ", perspective: " << p.perspective << " }"; |
126 return os; | 150 return os; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 framer_->set_visitor(&visitor_); | 188 framer_->set_visitor(&visitor_); |
165 EXPECT_EQ(version(), session_.connection()->version()); | 189 EXPECT_EQ(version(), session_.connection()->version()); |
166 EXPECT_TRUE(headers_stream_ != nullptr); | 190 EXPECT_TRUE(headers_stream_ != nullptr); |
167 VLOG(1) << GetParam(); | 191 VLOG(1) << GetParam(); |
168 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); | 192 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); |
169 } | 193 } |
170 | 194 |
171 QuicConsumedData SaveIov(const QuicIOVector& data) { | 195 QuicConsumedData SaveIov(const QuicIOVector& data) { |
172 const iovec* iov = data.iov; | 196 const iovec* iov = data.iov; |
173 int count = data.iov_count; | 197 int count = data.iov_count; |
| 198 int consumed = 0; |
174 for (int i = 0; i < count; ++i) { | 199 for (int i = 0; i < count; ++i) { |
175 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len); | 200 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len); |
| 201 consumed += iov[i].iov_len; |
176 } | 202 } |
177 return QuicConsumedData(saved_data_.length(), false); | 203 return QuicConsumedData(consumed, false); |
| 204 } |
| 205 |
| 206 QuicConsumedData SaveIovAndNotifyAckListener( |
| 207 const QuicIOVector& data, |
| 208 QuicAckListenerInterface* ack_listener) { |
| 209 QuicConsumedData result = SaveIov(data); |
| 210 if (ack_listener) { |
| 211 ack_listener->OnPacketAcked(result.bytes_consumed, |
| 212 QuicTime::Delta::Zero()); |
| 213 } |
| 214 return result; |
| 215 } |
| 216 |
| 217 void SavePayload(const char* data, size_t len) { |
| 218 saved_payloads_.append(data, len); |
178 } | 219 } |
179 | 220 |
180 bool SaveHeaderData(const char* data, int len) { | 221 bool SaveHeaderData(const char* data, int len) { |
181 saved_header_data_.append(data, len); | 222 saved_header_data_.append(data, len); |
182 return true; | 223 return true; |
183 } | 224 } |
184 | 225 |
185 void SaveHeaderDataStringPiece(StringPiece data) { | 226 void SaveHeaderDataStringPiece(StringPiece data) { |
186 saved_header_data_.append(data.data(), data.length()); | 227 saved_header_data_.append(data.data(), data.length()); |
187 } | 228 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 MockQuicConnectionHelper helper_; | 327 MockQuicConnectionHelper helper_; |
287 MockAlarmFactory alarm_factory_; | 328 MockAlarmFactory alarm_factory_; |
288 StrictMock<MockQuicConnection>* connection_; | 329 StrictMock<MockQuicConnection>* connection_; |
289 StrictMock<MockQuicSpdySession> session_; | 330 StrictMock<MockQuicSpdySession> session_; |
290 QuicHeadersStream* headers_stream_; | 331 QuicHeadersStream* headers_stream_; |
291 SpdyHeaderBlock headers_; | 332 SpdyHeaderBlock headers_; |
292 std::unique_ptr<TestHeadersHandler> headers_handler_; | 333 std::unique_ptr<TestHeadersHandler> headers_handler_; |
293 string body_; | 334 string body_; |
294 string saved_data_; | 335 string saved_data_; |
295 string saved_header_data_; | 336 string saved_header_data_; |
| 337 string saved_payloads_; |
296 std::unique_ptr<SpdyFramer> framer_; | 338 std::unique_ptr<SpdyFramer> framer_; |
297 StrictMock<MockVisitor> visitor_; | 339 StrictMock<MockVisitor> visitor_; |
298 std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_encoder_visitor_; | 340 std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_encoder_visitor_; |
299 std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_decoder_visitor_; | 341 std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_decoder_visitor_; |
300 QuicStreamFrame stream_frame_; | 342 QuicStreamFrame stream_frame_; |
301 QuicStreamId next_promised_stream_id_; | 343 QuicStreamId next_promised_stream_id_; |
302 }; | 344 }; |
303 | 345 |
304 INSTANTIATE_TEST_CASE_P(Tests, | 346 INSTANTIATE_TEST_CASE_P(Tests, |
305 QuicHeadersStreamTest, | 347 QuicHeadersStreamTest, |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 .Times(1); | 490 .Times(1); |
449 stream_frame_.data_buffer = frame.data(); | 491 stream_frame_.data_buffer = frame.data(); |
450 stream_frame_.data_length = frame.size(); | 492 stream_frame_.data_length = frame.size(); |
451 headers_stream_->OnStreamFrame(stream_frame_); | 493 headers_stream_->OnStreamFrame(stream_frame_); |
452 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); | 494 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); |
453 stream_frame_.offset += frame.size(); | 495 stream_frame_.offset += frame.size(); |
454 } | 496 } |
455 } | 497 } |
456 | 498 |
457 TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { | 499 TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { |
458 if (!FLAGS_quic_measure_headers_hol_blocking_time) { | |
459 return; | |
460 } | |
461 QuicStreamId stream_id; | 500 QuicStreamId stream_id; |
462 bool fin = true; | 501 bool fin = true; |
463 QuicStreamFrame stream_frames[10]; | 502 QuicStreamFrame stream_frames[10]; |
464 SpdySerializedFrame frames[10]; | 503 SpdySerializedFrame frames[10]; |
465 // First create all the frames in order | 504 // First create all the frames in order |
466 { | 505 { |
467 InSequence seq; | 506 InSequence seq; |
468 for (int stream_num = 0; stream_num < 10; ++stream_num) { | 507 for (int stream_num = 0; stream_num < 10; ++stream_num) { |
469 stream_id = QuicClientDataStreamId(stream_num); | 508 stream_id = QuicClientDataStreamId(stream_num); |
470 if (perspective() == Perspective::IS_SERVER) { | 509 if (perspective() == Perspective::IS_SERVER) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 const char kBadData[] = "blah blah blah"; | 582 const char kBadData[] = "blah blah blah"; |
544 EXPECT_CALL(*connection_, | 583 EXPECT_CALL(*connection_, |
545 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _)) | 584 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _)) |
546 .Times(::testing::AnyNumber()); | 585 .Times(::testing::AnyNumber()); |
547 stream_frame_.data_buffer = kBadData; | 586 stream_frame_.data_buffer = kBadData; |
548 stream_frame_.data_length = strlen(kBadData); | 587 stream_frame_.data_length = strlen(kBadData); |
549 headers_stream_->OnStreamFrame(stream_frame_); | 588 headers_stream_->OnStreamFrame(stream_frame_); |
550 } | 589 } |
551 | 590 |
552 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) { | 591 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) { |
553 SpdyDataIR data(2, ""); | 592 SpdyDataIR data(2, "ping"); |
554 SpdySerializedFrame frame(framer_->SerializeFrame(data)); | 593 SpdySerializedFrame frame(framer_->SerializeFrame(data)); |
| 594 |
555 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, | 595 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, |
556 "SPDY DATA frame received.", _)) | 596 "SPDY DATA frame received.", _)) |
557 .WillOnce(InvokeWithoutArgs( | 597 .WillOnce(InvokeWithoutArgs( |
558 this, &QuicHeadersStreamTest::TearDownLocalConnectionState)); | 598 this, &QuicHeadersStreamTest::TearDownLocalConnectionState)); |
559 stream_frame_.data_buffer = frame.data(); | 599 stream_frame_.data_buffer = frame.data(); |
560 stream_frame_.data_length = frame.size(); | 600 stream_frame_.data_length = frame.size(); |
561 headers_stream_->OnStreamFrame(stream_frame_); | 601 headers_stream_->OnStreamFrame(stream_frame_); |
562 } | 602 } |
563 | 603 |
| 604 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameForceHolBlocking) { |
| 605 if (version() <= QUIC_VERSION_35) { |
| 606 return; |
| 607 } |
| 608 QuicSpdySessionPeer::SetForceHolBlocking(&session_, true); |
| 609 SpdyDataIR data(2, "ping"); |
| 610 SpdySerializedFrame frame(framer_->SerializeFrame(data)); |
| 611 EXPECT_CALL(session_, OnStreamFrameData(2, _, 4, false)); |
| 612 stream_frame_.data_buffer = frame.data(); |
| 613 stream_frame_.data_length = frame.size(); |
| 614 headers_stream_->OnStreamFrame(stream_frame_); |
| 615 } |
| 616 |
| 617 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameEmptyWithFin) { |
| 618 if (version() <= QUIC_VERSION_35) { |
| 619 return; |
| 620 } |
| 621 QuicSpdySessionPeer::SetForceHolBlocking(&session_, true); |
| 622 SpdyDataIR data(2, ""); |
| 623 data.set_fin(true); |
| 624 SpdySerializedFrame frame(framer_->SerializeFrame(data)); |
| 625 EXPECT_CALL(session_, OnStreamFrameData(2, _, 0, true)); |
| 626 stream_frame_.data_buffer = frame.data(); |
| 627 stream_frame_.data_length = frame.size(); |
| 628 headers_stream_->OnStreamFrame(stream_frame_); |
| 629 } |
| 630 |
564 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) { | 631 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) { |
565 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR); | 632 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR); |
566 SpdySerializedFrame frame(framer_->SerializeFrame(data)); | 633 SpdySerializedFrame frame(framer_->SerializeFrame(data)); |
567 EXPECT_CALL(*connection_, | 634 EXPECT_CALL(*connection_, |
568 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, | 635 CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, |
569 "SPDY RST_STREAM frame received.", _)) | 636 "SPDY RST_STREAM frame received.", _)) |
570 .WillOnce(InvokeWithoutArgs( | 637 .WillOnce(InvokeWithoutArgs( |
571 this, &QuicHeadersStreamTest::TearDownLocalConnectionState)); | 638 this, &QuicHeadersStreamTest::TearDownLocalConnectionState)); |
572 stream_frame_.data_buffer = frame.data(); | 639 stream_frame_.data_buffer = frame.data(); |
573 stream_frame_.data_length = frame.size(); | 640 stream_frame_.data_length = frame.size(); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 for (SpdyPriority priority = 0; priority < 7; ++priority) { | 841 for (SpdyPriority priority = 0; priority < 7; ++priority) { |
775 // TODO(rch): implement priorities correctly. | 842 // TODO(rch): implement priorities correctly. |
776 WriteHeadersAndExpectSynStream(stream_id, fin, 0); | 843 WriteHeadersAndExpectSynStream(stream_id, fin, 0); |
777 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); | 844 connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); |
778 } | 845 } |
779 } | 846 } |
780 } | 847 } |
781 } | 848 } |
782 } | 849 } |
783 | 850 |
| 851 TEST_P(QuicHeadersStreamTest, WritevStreamData) { |
| 852 QuicStreamId id = kClientDataStreamId1; |
| 853 QuicStreamOffset offset = 0; |
| 854 struct iovec iov; |
| 855 string data; |
| 856 |
| 857 // This test will issue a write that will require fragmenting into |
| 858 // multiple HTTP/2 DATA frames. |
| 859 const int kMinDataFrames = 4; |
| 860 const size_t data_len = |
| 861 SpdyConstants::GetFrameMaximumSize(HTTP2) * kMinDataFrames + 1024; |
| 862 // Set headers stream send window large enough for data written below. |
| 863 headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4); |
| 864 test::GenerateBody(&data, data_len); |
| 865 |
| 866 for (bool fin : {true, false}) { |
| 867 for (bool use_ack_listener : {true, false}) { |
| 868 scoped_refptr<ForceHolAckListener> ack_listener; |
| 869 if (use_ack_listener) { |
| 870 ack_listener = new ForceHolAckListener(); |
| 871 } |
| 872 EXPECT_CALL(session_, |
| 873 WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) |
| 874 .WillRepeatedly(WithArgs<2, 5>(Invoke( |
| 875 this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener))); |
| 876 |
| 877 QuicConsumedData consumed_data = headers_stream_->WritevStreamData( |
| 878 id, MakeIOVector(data, &iov), offset, fin, ack_listener.get()); |
| 879 |
| 880 EXPECT_EQ(consumed_data.bytes_consumed, data_len); |
| 881 EXPECT_EQ(consumed_data.fin_consumed, fin); |
| 882 // Now process the written data with the SPDY framer, and verify |
| 883 // that the original data is unchanged. |
| 884 EXPECT_CALL(visitor_, OnDataFrameHeader(id, _, _)) |
| 885 .Times(AtLeast(kMinDataFrames)); |
| 886 EXPECT_CALL(visitor_, OnStreamFrameData(id, _, _)) |
| 887 .WillRepeatedly(WithArgs<1, 2>( |
| 888 Invoke(this, &QuicHeadersStreamTest::SavePayload))); |
| 889 if (fin) { |
| 890 EXPECT_CALL(visitor_, OnStreamEnd(id)); |
| 891 } |
| 892 framer_->ProcessInput(saved_data_.data(), saved_data_.length()); |
| 893 EXPECT_EQ(saved_payloads_, data); |
| 894 |
| 895 if (use_ack_listener) { |
| 896 // Notice, acked bytes doesn't include extra bytes used by |
| 897 // HTTP/2 DATA frame headers. |
| 898 EXPECT_EQ(ack_listener->total_acked_bytes(), data_len); |
| 899 } |
| 900 saved_data_.clear(); |
| 901 saved_payloads_.clear(); |
| 902 } |
| 903 } |
| 904 } |
| 905 |
784 } // namespace | 906 } // namespace |
785 } // namespace test | 907 } // namespace test |
786 } // namespace net | 908 } // namespace net |
OLD | NEW |