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/tools/quic/quic_simple_server_session.h" | 5 #include "net/tools/quic/quic_simple_server_session.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 |
7 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/string_number_conversions.h" |
8 #include "net/quic/crypto/quic_crypto_server_config.h" | 11 #include "net/quic/crypto/quic_crypto_server_config.h" |
9 #include "net/quic/crypto/quic_random.h" | 12 #include "net/quic/crypto/quic_random.h" |
10 #include "net/quic/proto/cached_network_parameters.pb.h" | 13 #include "net/quic/proto/cached_network_parameters.pb.h" |
11 #include "net/quic/quic_connection.h" | 14 #include "net/quic/quic_connection.h" |
12 #include "net/quic/quic_crypto_server_stream.h" | 15 #include "net/quic/quic_crypto_server_stream.h" |
13 #include "net/quic/quic_utils.h" | 16 #include "net/quic/quic_utils.h" |
14 #include "net/quic/test_tools/crypto_test_utils.h" | 17 #include "net/quic/test_tools/crypto_test_utils.h" |
15 #include "net/quic/test_tools/quic_config_peer.h" | 18 #include "net/quic/test_tools/quic_config_peer.h" |
16 #include "net/quic/test_tools/quic_connection_peer.h" | 19 #include "net/quic/test_tools/quic_connection_peer.h" |
17 #include "net/quic/test_tools/quic_sent_packet_manager_peer.h" | 20 #include "net/quic/test_tools/quic_sent_packet_manager_peer.h" |
18 #include "net/quic/test_tools/quic_session_peer.h" | 21 #include "net/quic/test_tools/quic_session_peer.h" |
19 #include "net/quic/test_tools/quic_spdy_session_peer.h" | 22 #include "net/quic/test_tools/quic_spdy_session_peer.h" |
20 #include "net/quic/test_tools/quic_spdy_stream_peer.h" | 23 #include "net/quic/test_tools/quic_spdy_stream_peer.h" |
21 #include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h" | 24 #include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h" |
22 #include "net/quic/test_tools/quic_test_utils.h" | 25 #include "net/quic/test_tools/quic_test_utils.h" |
23 #include "net/test/gtest_util.h" | 26 #include "net/test/gtest_util.h" |
24 #include "net/tools/quic/quic_simple_server_stream.h" | 27 #include "net/tools/quic/quic_simple_server_stream.h" |
25 #include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h" | 28 #include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h" |
| 29 #include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h" |
26 #include "testing/gmock/include/gmock/gmock.h" | 30 #include "testing/gmock/include/gmock/gmock.h" |
27 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
28 | 32 |
29 using __gnu_cxx::vector; | 33 using __gnu_cxx::vector; |
30 using net::test::CryptoTestUtils; | 34 using net::test::CryptoTestUtils; |
31 using net::test::MockConnection; | 35 using net::test::MockConnection; |
32 using net::test::MockConnectionHelper; | 36 using net::test::MockConnectionHelper; |
33 using net::test::QuicConfigPeer; | 37 using net::test::QuicConfigPeer; |
34 using net::test::QuicConnectionPeer; | 38 using net::test::QuicConnectionPeer; |
35 using net::test::QuicSpdyStreamPeer; | 39 using net::test::QuicSpdyStreamPeer; |
36 using net::test::QuicSentPacketManagerPeer; | 40 using net::test::QuicSentPacketManagerPeer; |
37 using net::test::QuicSessionPeer; | 41 using net::test::QuicSessionPeer; |
38 using net::test::QuicSpdySessionPeer; | 42 using net::test::QuicSpdySessionPeer; |
39 using net::test::QuicSustainedBandwidthRecorderPeer; | 43 using net::test::QuicSustainedBandwidthRecorderPeer; |
40 using net::test::SupportedVersions; | 44 using net::test::SupportedVersions; |
41 using net::test::ValueRestore; | 45 using net::test::ValueRestore; |
42 using net::test::kClientDataStreamId1; | 46 using net::test::kClientDataStreamId1; |
43 using net::test::kClientDataStreamId2; | 47 using net::test::kClientDataStreamId2; |
44 using net::test::kClientDataStreamId3; | 48 using net::test::kClientDataStreamId3; |
45 using net::test::kInitialSessionFlowControlWindowForTest; | 49 using net::test::kInitialSessionFlowControlWindowForTest; |
46 using net::test::kInitialStreamFlowControlWindowForTest; | 50 using net::test::kInitialStreamFlowControlWindowForTest; |
47 using std::string; | 51 using std::string; |
48 using testing::StrictMock; | 52 using testing::StrictMock; |
49 using testing::_; | 53 using testing::_; |
| 54 using testing::InSequence; |
| 55 using testing::Return; |
50 | 56 |
51 namespace net { | 57 namespace net { |
52 namespace tools { | 58 namespace tools { |
53 namespace test { | 59 namespace test { |
| 60 namespace { |
| 61 typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo; |
| 62 } // namespace |
| 63 |
| 64 class MockQuicHeadersStream : public QuicHeadersStream { |
| 65 public: |
| 66 explicit MockQuicHeadersStream(QuicSpdySession* session) |
| 67 : QuicHeadersStream(session) {} |
| 68 |
| 69 MOCK_METHOD4(WritePushPromise, |
| 70 size_t(QuicStreamId original_stream_id, |
| 71 QuicStreamId promised_stream_id, |
| 72 const SpdyHeaderBlock& headers, |
| 73 QuicAckListenerInterface* ack_listener)); |
| 74 |
| 75 MOCK_METHOD5(WriteHeaders, |
| 76 size_t(QuicStreamId stream_id, |
| 77 const SpdyHeaderBlock& headers, |
| 78 bool fin, |
| 79 SpdyPriority priority, |
| 80 QuicAckListenerInterface* ack_listener)); |
| 81 }; |
| 82 |
| 83 class MockQuicCryptoServerStream : public QuicCryptoServerStream { |
| 84 public: |
| 85 explicit MockQuicCryptoServerStream( |
| 86 const QuicCryptoServerConfig* crypto_config, |
| 87 QuicSession* session) |
| 88 : QuicCryptoServerStream(crypto_config, session) {} |
| 89 ~MockQuicCryptoServerStream() override {} |
| 90 |
| 91 MOCK_METHOD1(SendServerConfigUpdate, |
| 92 void(const CachedNetworkParameters* cached_network_parameters)); |
| 93 |
| 94 void set_encryption_established(bool has_established) { |
| 95 encryption_established_ = has_established; |
| 96 } |
| 97 |
| 98 private: |
| 99 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream); |
| 100 }; |
| 101 |
| 102 class MockConnectionWithSendStreamData : public MockConnection { |
| 103 public: |
| 104 MockConnectionWithSendStreamData(MockConnectionHelper* helper, |
| 105 Perspective perspective, |
| 106 const QuicVersionVector& supported_versions) |
| 107 : MockConnection(helper, perspective, supported_versions) {} |
| 108 |
| 109 MOCK_METHOD6(SendStreamData, |
| 110 QuicConsumedData(QuicStreamId id, |
| 111 QuicIOVector iov, |
| 112 QuicStreamOffset offset, |
| 113 bool fin, |
| 114 FecProtection fec_protection, |
| 115 QuicAckListenerInterface* listern)); |
| 116 }; |
54 | 117 |
55 class QuicSimpleServerSessionPeer { | 118 class QuicSimpleServerSessionPeer { |
56 public: | 119 public: |
57 static void SetCryptoStream(QuicSimpleServerSession* s, | 120 static void SetCryptoStream(QuicSimpleServerSession* s, |
58 QuicCryptoServerStream* crypto_stream) { | 121 QuicCryptoServerStream* crypto_stream) { |
59 s->crypto_stream_.reset(crypto_stream); | 122 s->crypto_stream_.reset(crypto_stream); |
60 s->static_streams()[kCryptoStreamId] = crypto_stream; | 123 s->static_streams()[kCryptoStreamId] = crypto_stream; |
61 } | 124 } |
62 | 125 |
63 static QuicSpdyStream* CreateIncomingDynamicStream(QuicSimpleServerSession* s, | 126 static QuicSpdyStream* CreateIncomingDynamicStream(QuicSimpleServerSession* s, |
64 QuicStreamId id) { | 127 QuicStreamId id) { |
65 return s->CreateIncomingDynamicStream(id); | 128 return s->CreateIncomingDynamicStream(id); |
66 } | 129 } |
67 | 130 |
68 static QuicSimpleServerStream* CreateOutgoingDynamicStream( | 131 static QuicSimpleServerStream* CreateOutgoingDynamicStream( |
69 QuicSimpleServerSession* s, | 132 QuicSimpleServerSession* s, |
70 SpdyPriority priority) { | 133 SpdyPriority priority) { |
71 return s->CreateOutgoingDynamicStream(priority); | 134 return s->CreateOutgoingDynamicStream(priority); |
72 } | 135 } |
| 136 |
| 137 static std::deque<PromisedStreamInfo>* promised_streams( |
| 138 QuicSimpleServerSession* s) { |
| 139 return &(s->promised_streams_); |
| 140 } |
| 141 |
| 142 static QuicStreamId hightest_promised_stream_id(QuicSimpleServerSession* s) { |
| 143 return s->highest_promised_stream_id_; |
| 144 } |
73 }; | 145 }; |
74 | 146 |
75 namespace { | 147 namespace { |
76 | 148 |
77 const size_t kMaxStreamsForTest = 10; | 149 const size_t kMaxStreamsForTest = 10; |
78 | 150 |
79 class QuicSimpleServerSessionTest | 151 class QuicSimpleServerSessionTest |
80 : public ::testing::TestWithParam<QuicVersion> { | 152 : public ::testing::TestWithParam<QuicVersion> { |
81 protected: | 153 protected: |
82 QuicSimpleServerSessionTest() | 154 QuicSimpleServerSessionTest() |
83 : crypto_config_(QuicCryptoServerConfig::TESTING, | 155 : crypto_config_(QuicCryptoServerConfig::TESTING, |
84 QuicRandom::GetInstance(), | 156 QuicRandom::GetInstance(), |
85 CryptoTestUtils::ProofSourceForTesting()) { | 157 CryptoTestUtils::ProofSourceForTesting()) { |
86 config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); | 158 config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); |
87 config_.SetInitialStreamFlowControlWindowToSend( | 159 config_.SetInitialStreamFlowControlWindowToSend( |
88 kInitialStreamFlowControlWindowForTest); | 160 kInitialStreamFlowControlWindowForTest); |
89 config_.SetInitialSessionFlowControlWindowToSend( | 161 config_.SetInitialSessionFlowControlWindowToSend( |
90 kInitialSessionFlowControlWindowForTest); | 162 kInitialSessionFlowControlWindowForTest); |
91 | 163 |
92 connection_ = new StrictMock<MockConnection>( | 164 connection_ = new StrictMock<MockConnectionWithSendStreamData>( |
93 &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam())); | 165 &helper_, Perspective::IS_SERVER, SupportedVersions(GetParam())); |
94 session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_, | 166 session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_, |
95 &crypto_config_)); | 167 &crypto_config_)); |
96 MockClock clock; | 168 MockClock clock; |
97 handshake_message_.reset(crypto_config_.AddDefaultConfig( | 169 handshake_message_.reset(crypto_config_.AddDefaultConfig( |
98 QuicRandom::GetInstance(), &clock, | 170 QuicRandom::GetInstance(), &clock, |
99 QuicCryptoServerConfig::ConfigOptions())); | 171 QuicCryptoServerConfig::ConfigOptions())); |
100 session_->Initialize(); | 172 session_->Initialize(); |
101 visitor_ = QuicConnectionPeer::GetVisitor(connection_); | 173 visitor_ = QuicConnectionPeer::GetVisitor(connection_); |
| 174 headers_stream_ = new MockQuicHeadersStream(session_.get()); |
| 175 QuicSpdySessionPeer::SetHeadersStream(session_.get(), headers_stream_); |
| 176 } |
| 177 |
| 178 // Given |num_resources|, create this number of fake push resources and push |
| 179 // them by sending PUSH_PROMISE for all and sending push responses for as much |
| 180 // as possible(limited by kMaxStreamsForTest). |
| 181 // If |num_resources| > kMaxStreamsForTest, the left over will be queued. |
| 182 void PromisePushResources(size_t num_resources) { |
| 183 // Assume encryption already established. |
| 184 MockQuicCryptoServerStream* crypto_stream = |
| 185 new MockQuicCryptoServerStream(&crypto_config_, session_.get()); |
| 186 crypto_stream->set_encryption_established(true); |
| 187 QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream); |
| 188 |
| 189 QuicInMemoryCachePeer::ResetForTests(); |
| 190 |
| 191 string request_url = "mail.google.com/"; |
| 192 SpdyHeaderBlock request_headers; |
| 193 string resource_host = "www.google.com"; |
| 194 string partial_push_resource_path = "/server_push_src"; |
| 195 string partial_push_response_body = |
| 196 "Push resource body " + partial_push_resource_path; |
| 197 list<QuicInMemoryCache::ServerPushInfo> push_resources; |
| 198 string scheme = "http"; |
| 199 for (unsigned int i = 1; i <= num_resources; ++i) { |
| 200 string path = partial_push_resource_path + base::UintToString(i); |
| 201 string url = scheme + "://" + resource_host + "/" + path; |
| 202 GURL resource_url = GURL(url); |
| 203 string body = partial_push_response_body + base::UintToString(i); |
| 204 SpdyHeaderBlock response_headers; |
| 205 QuicInMemoryCache::GetInstance()->AddSimpleResponse(resource_host, path, |
| 206 200, body); |
| 207 push_resources.push_back(QuicInMemoryCache::ServerPushInfo( |
| 208 resource_url, response_headers, kDefaultPriority, body)); |
| 209 // PUSH_PROMISED are sent for all the resources. |
| 210 EXPECT_CALL(*headers_stream_, |
| 211 WritePushPromise(kClientDataStreamId1, i * 2, _, nullptr)); |
| 212 if (i <= kMaxStreamsForTest) { |
| 213 // |kMaxStreamsForTest| promised responses should be sent. |
| 214 EXPECT_CALL(*headers_stream_, |
| 215 WriteHeaders(i * 2, _, false, kDefaultPriority, nullptr)); |
| 216 // Mock that SendStreamData() returns less than supposed to send to keep |
| 217 // the stream open. |
| 218 EXPECT_CALL(*connection_, SendStreamData(i * 2, _, 0, true, _, nullptr)) |
| 219 .WillOnce(Return(QuicConsumedData(0, false))); |
| 220 } |
| 221 } |
| 222 session_->PromisePushResources(request_url, push_resources, |
| 223 kClientDataStreamId1, request_headers); |
102 } | 224 } |
103 | 225 |
104 StrictMock<MockQuicServerSessionVisitor> owner_; | 226 StrictMock<MockQuicServerSessionVisitor> owner_; |
105 MockConnectionHelper helper_; | 227 MockConnectionHelper helper_; |
106 StrictMock<MockConnection>* connection_; | 228 StrictMock<MockConnectionWithSendStreamData>* connection_; |
107 QuicConfig config_; | 229 QuicConfig config_; |
108 QuicCryptoServerConfig crypto_config_; | 230 QuicCryptoServerConfig crypto_config_; |
109 scoped_ptr<QuicSimpleServerSession> session_; | 231 scoped_ptr<QuicSimpleServerSession> session_; |
110 scoped_ptr<CryptoHandshakeMessage> handshake_message_; | 232 scoped_ptr<CryptoHandshakeMessage> handshake_message_; |
111 QuicConnectionVisitorInterface* visitor_; | 233 QuicConnectionVisitorInterface* visitor_; |
| 234 MockQuicHeadersStream* headers_stream_; |
112 }; | 235 }; |
113 | 236 |
114 INSTANTIATE_TEST_CASE_P(Tests, | 237 INSTANTIATE_TEST_CASE_P(Tests, |
115 QuicSimpleServerSessionTest, | 238 QuicSimpleServerSessionTest, |
116 ::testing::ValuesIn(QuicSupportedVersions())); | 239 ::testing::ValuesIn(QuicSupportedVersions())); |
117 | 240 |
118 TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) { | 241 TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) { |
119 // Open a stream, then reset it. | 242 // Open a stream, then reset it. |
120 // Send two bytes of payload to open it. | 243 // Send two bytes of payload to open it. |
121 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT")); | 244 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT")); |
122 session_->OnStreamFrame(data1); | 245 session_->OnStreamFrame(data1); |
123 EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); | 246 EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); |
124 | 247 |
125 // Send a reset (and expect the peer to send a RST in response). | 248 // Receive a reset (and send a RST in response). |
126 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, | 249 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM, |
127 0); | 250 0); |
128 EXPECT_CALL(*connection_, | 251 EXPECT_CALL(*connection_, |
129 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); | 252 SendRstStream(kClientDataStreamId1, QUIC_RST_ACKNOWLEDGEMENT, 0)); |
130 visitor_->OnRstStream(rst1); | 253 visitor_->OnRstStream(rst1); |
131 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); | 254 EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); |
132 | 255 |
133 // Send the same two bytes of payload in a new packet. | 256 // Send the same two bytes of payload in a new packet. |
134 visitor_->OnStreamFrame(data1); | 257 visitor_->OnStreamFrame(data1); |
135 | 258 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 } | 328 } |
206 | 329 |
207 TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStream) { | 330 TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStream) { |
208 std::unique_ptr<QuicSpdyStream> stream( | 331 std::unique_ptr<QuicSpdyStream> stream( |
209 QuicSimpleServerSessionPeer::CreateIncomingDynamicStream( | 332 QuicSimpleServerSessionPeer::CreateIncomingDynamicStream( |
210 session_.get(), kClientDataStreamId1)); | 333 session_.get(), kClientDataStreamId1)); |
211 EXPECT_NE(nullptr, stream); | 334 EXPECT_NE(nullptr, stream); |
212 EXPECT_EQ(kClientDataStreamId1, stream->id()); | 335 EXPECT_EQ(kClientDataStreamId1, stream->id()); |
213 } | 336 } |
214 | 337 |
215 class MockQuicCryptoServerStream : public QuicCryptoServerStream { | |
216 public: | |
217 explicit MockQuicCryptoServerStream( | |
218 const QuicCryptoServerConfig* crypto_config, | |
219 QuicSession* session) | |
220 : QuicCryptoServerStream(crypto_config, session) {} | |
221 ~MockQuicCryptoServerStream() override {} | |
222 | |
223 MOCK_METHOD1(SendServerConfigUpdate, | |
224 void(const CachedNetworkParameters* cached_network_parameters)); | |
225 | |
226 void set_encryption_established(bool has_established) { | |
227 encryption_established_ = has_established; | |
228 } | |
229 | |
230 private: | |
231 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream); | |
232 }; | |
233 | |
234 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) { | 338 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) { |
235 // Tests that outgoing stream creation fails when connection is not connected. | 339 // Tests that outgoing stream creation fails when connection is not connected. |
236 size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams(); | 340 size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams(); |
237 QuicConnectionPeer::CloseConnection(connection_); | 341 QuicConnectionPeer::CloseConnection(connection_); |
238 EXPECT_DFATAL(QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream( | 342 EXPECT_DFATAL(QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream( |
239 session_.get(), kDefaultPriority), | 343 session_.get(), kDefaultPriority), |
240 "ShouldCreateOutgoingDynamicStream called when disconnected"); | 344 "ShouldCreateOutgoingDynamicStream called when disconnected"); |
241 | 345 |
242 EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams()); | 346 EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams()); |
243 } | 347 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 EXPECT_EQ(nullptr, QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream( | 387 EXPECT_EQ(nullptr, QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream( |
284 session_.get(), kDefaultPriority)); | 388 session_.get(), kDefaultPriority)); |
285 EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); | 389 EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); |
286 | 390 |
287 // Create peer initiated stream should have no problem. | 391 // Create peer initiated stream should have no problem. |
288 QuicStreamFrame data2(kClientDataStreamId2, false, 0, StringPiece("HT")); | 392 QuicStreamFrame data2(kClientDataStreamId2, false, 0, StringPiece("HT")); |
289 session_->OnStreamFrame(data2); | 393 session_->OnStreamFrame(data2); |
290 EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); | 394 EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); |
291 } | 395 } |
292 | 396 |
| 397 TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) { |
| 398 QuicStreamFrame frame(2, false, 0, StringPiece()); |
| 399 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( |
| 400 QUIC_INVALID_STREAM_ID, |
| 401 "Client sent data on server push stream")); |
| 402 session_->OnStreamFrame(frame); |
| 403 } |
| 404 |
| 405 TEST_P(QuicSimpleServerSessionTest, TestPromisePushResources) { |
| 406 // Tests that given more than kMaxOpenStreamForTest resources, all their |
| 407 // PUSH_PROMISE's will be sent out and only |kMaxOpenStreamForTest| streams |
| 408 // will be opened and send push response. |
| 409 size_t num_resources = kMaxStreamsForTest + 5; |
| 410 PromisePushResources(num_resources); |
| 411 EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); |
| 412 } |
| 413 |
| 414 TEST_P(QuicSimpleServerSessionTest, |
| 415 HandlePromisedPushRequestsAfterStreamDraining) { |
| 416 // Tests that after promised stream queued up, when an opened stream is marked |
| 417 // draining, a queued promised stream will become open and send push response. |
| 418 size_t num_resources = kMaxStreamsForTest + 1; |
| 419 PromisePushResources(num_resources); |
| 420 QuicStreamId next_out_going_stream_id = num_resources * 2; |
| 421 |
| 422 // After an open stream is marked draining, a new stream is expected to be |
| 423 // created and a response sent on the stream. |
| 424 EXPECT_CALL(*headers_stream_, WriteHeaders(next_out_going_stream_id, _, false, |
| 425 kDefaultPriority, nullptr)); |
| 426 EXPECT_CALL(*connection_, |
| 427 SendStreamData(next_out_going_stream_id, _, 0, true, _, nullptr)) |
| 428 .WillOnce(Return(QuicConsumedData(0, false))); |
| 429 session_->StreamDraining(2); |
| 430 // Number of open outgoing streams should still be the same, because a new |
| 431 // stream is opened. And the queue should be empty. |
| 432 EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); |
| 433 } |
| 434 |
| 435 TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) { |
| 436 // Tests that calling GetOrCreateDynamicStream() on an outgoing stream not |
| 437 // promised yet should result close connection. |
| 438 EXPECT_CALL(*connection_, |
| 439 SendConnectionCloseWithDetails(QUIC_INVALID_STREAM_ID, |
| 440 "Data for nonexistent stream")); |
| 441 EXPECT_EQ(nullptr, |
| 442 QuicSessionPeer::GetOrCreateDynamicStream(session_.get(), 4)); |
| 443 } |
| 444 |
| 445 TEST_P(QuicSimpleServerSessionTest, ResetPromisedStreamToCancelServerPush) { |
| 446 // Tests that after all resources are promised, a RST frame from client can |
| 447 // prevent a promised resource to be send out. |
| 448 |
| 449 // Having two extra resources to be send later. One of them will be reset, so |
| 450 // when opened stream become close, only one will become open. |
| 451 size_t num_resources = kMaxStreamsForTest + 2; |
| 452 PromisePushResources(num_resources); |
| 453 |
| 454 // Reset the last stream in the queue. It should be marked cancelled. |
| 455 QuicStreamId stream_got_reset = num_resources * 2; |
| 456 QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0); |
| 457 EXPECT_CALL(*connection_, |
| 458 SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, 0)); |
| 459 visitor_->OnRstStream(rst); |
| 460 |
| 461 // When the first 2 streams becomes draining, the two queued up stream could |
| 462 // be created. But since one of them was marked cancelled due to RST frame, |
| 463 // only one queued resource will be sent out. |
| 464 QuicStreamId stream_not_reset = (kMaxStreamsForTest + 1) * 2; |
| 465 InSequence s; |
| 466 EXPECT_CALL(*headers_stream_, WriteHeaders(stream_not_reset, _, false, |
| 467 kDefaultPriority, nullptr)); |
| 468 EXPECT_CALL(*connection_, |
| 469 SendStreamData(stream_not_reset, _, 0, true, _, nullptr)) |
| 470 .WillOnce(Return(QuicConsumedData(0, false))); |
| 471 EXPECT_CALL(*headers_stream_, WriteHeaders(stream_got_reset, _, false, |
| 472 kDefaultPriority, nullptr)) |
| 473 .Times(0); |
| 474 |
| 475 session_->StreamDraining(2); |
| 476 session_->StreamDraining(4); |
| 477 } |
| 478 |
| 479 TEST_P(QuicSimpleServerSessionTest, CloseStreamToHandleMorePromisedStream) { |
| 480 // Tests that closing a open outgoing stream can trigger a promised resource |
| 481 // in the queue to be send out. |
| 482 size_t num_resources = kMaxStreamsForTest + 1; |
| 483 PromisePushResources(num_resources); |
| 484 QuicStreamId stream_to_open = num_resources * 2; |
| 485 |
| 486 // Resetting 1st open stream will close the stream and give space for extra |
| 487 // stream to be opened. |
| 488 QuicStreamId stream_got_reset = 2; |
| 489 EXPECT_CALL(*connection_, |
| 490 SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, _)); |
| 491 EXPECT_CALL(*headers_stream_, WriteHeaders(stream_to_open, _, false, |
| 492 kDefaultPriority, nullptr)); |
| 493 EXPECT_CALL(*connection_, |
| 494 SendStreamData(stream_to_open, _, 0, true, _, nullptr)) |
| 495 .WillOnce(Return(QuicConsumedData(0, false))); |
| 496 |
| 497 QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0); |
| 498 visitor_->OnRstStream(rst); |
| 499 } |
| 500 |
293 } // namespace | 501 } // namespace |
294 } // namespace test | 502 } // namespace test |
295 } // namespace tools | 503 } // namespace tools |
296 } // namespace net | 504 } // namespace net |
OLD | NEW |