Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: net/quic/quic_session_test.cc

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_session.cc ('k') | net/quic/quic_simple_buffer_allocator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/quic/quic_session.h"
6
7 #include <set>
8 #include <utility>
9
10 #include "base/rand_util.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "build/build_config.h"
14 #include "net/quic/crypto/crypto_protocol.h"
15 #include "net/quic/quic_crypto_stream.h"
16 #include "net/quic/quic_flags.h"
17 #include "net/quic/quic_protocol.h"
18 #include "net/quic/quic_utils.h"
19 #include "net/quic/reliable_quic_stream.h"
20 #include "net/quic/test_tools/quic_config_peer.h"
21 #include "net/quic/test_tools/quic_connection_peer.h"
22 #include "net/quic/test_tools/quic_flow_controller_peer.h"
23 #include "net/quic/test_tools/quic_headers_stream_peer.h"
24 #include "net/quic/test_tools/quic_session_peer.h"
25 #include "net/quic/test_tools/quic_spdy_session_peer.h"
26 #include "net/quic/test_tools/quic_spdy_stream_peer.h"
27 #include "net/quic/test_tools/quic_test_utils.h"
28 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
29 #include "net/spdy/spdy_framer.h"
30 #include "net/test/gtest_util.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gmock_mutant.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34
35 using net::SpdyHeaderBlock;
36 using net::SpdyPriority;
37 using std::set;
38 using std::string;
39 using std::vector;
40 using testing::CreateFunctor;
41 using testing::AtLeast;
42 using testing::InSequence;
43 using testing::Invoke;
44 using testing::Return;
45 using testing::StrictMock;
46 using testing::_;
47
48 namespace net {
49 namespace test {
50 namespace {
51
52 const SpdyPriority kHighestPriority = kV3HighestPriority;
53
54 class TestCryptoStream : public QuicCryptoStream {
55 public:
56 explicit TestCryptoStream(QuicSession* session) : QuicCryptoStream(session) {}
57
58 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
59 encryption_established_ = true;
60 handshake_confirmed_ = true;
61 CryptoHandshakeMessage msg;
62 string error_details;
63 session()->config()->SetInitialStreamFlowControlWindowToSend(
64 kInitialStreamFlowControlWindowForTest);
65 session()->config()->SetInitialSessionFlowControlWindowToSend(
66 kInitialSessionFlowControlWindowForTest);
67 session()->config()->ToHandshakeMessage(&msg);
68 const QuicErrorCode error =
69 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
70 EXPECT_EQ(QUIC_NO_ERROR, error);
71 session()->OnConfigNegotiated();
72 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
73 }
74
75 MOCK_METHOD0(OnCanWrite, void());
76 };
77
78 class TestHeadersStream : public QuicHeadersStream {
79 public:
80 explicit TestHeadersStream(QuicSpdySession* session)
81 : QuicHeadersStream(session) {}
82
83 MOCK_METHOD0(OnCanWrite, void());
84 };
85
86 class TestStream : public QuicSpdyStream {
87 public:
88 TestStream(QuicStreamId id, QuicSpdySession* session)
89 : QuicSpdyStream(id, session) {}
90
91 using ReliableQuicStream::CloseWriteSide;
92
93 void OnDataAvailable() override {}
94
95 MOCK_METHOD0(OnCanWrite, void());
96 };
97
98 // Poor man's functor for use as callback in a mock.
99 class StreamBlocker {
100 public:
101 StreamBlocker(QuicSession* session, QuicStreamId stream_id)
102 : session_(session), stream_id_(stream_id) {}
103
104 void MarkConnectionLevelWriteBlocked() {
105 session_->MarkConnectionLevelWriteBlocked(stream_id_);
106 }
107
108 private:
109 QuicSession* const session_;
110 const QuicStreamId stream_id_;
111 };
112
113 class TestSession : public QuicSpdySession {
114 public:
115 explicit TestSession(QuicConnection* connection)
116 : QuicSpdySession(connection, DefaultQuicConfig()),
117 crypto_stream_(this),
118 writev_consumes_all_data_(false) {
119 Initialize();
120 }
121
122 TestCryptoStream* GetCryptoStream() override { return &crypto_stream_; }
123
124 TestStream* CreateOutgoingDynamicStream(SpdyPriority priority) override {
125 TestStream* stream = new TestStream(GetNextOutgoingStreamId(), this);
126 stream->SetPriority(priority);
127 ActivateStream(stream);
128 return stream;
129 }
130
131 TestStream* CreateIncomingDynamicStream(QuicStreamId id) override {
132 // Enforce the limit on the number of open streams.
133 if (GetNumOpenIncomingStreams() + 1 > max_open_incoming_streams()) {
134 connection()->CloseConnection(
135 QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
136 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
137 return nullptr;
138 } else {
139 TestStream* stream = new TestStream(id, this);
140 ActivateStream(stream);
141 return stream;
142 }
143 }
144
145 bool ShouldCreateIncomingDynamicStream(QuicStreamId /*id*/) override {
146 return true;
147 }
148
149 bool ShouldCreateOutgoingDynamicStream() override { return true; }
150
151 bool IsClosedStream(QuicStreamId id) {
152 return QuicSession::IsClosedStream(id);
153 }
154
155 ReliableQuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id) {
156 return QuicSpdySession::GetOrCreateDynamicStream(stream_id);
157 }
158
159 QuicConsumedData WritevData(
160 ReliableQuicStream* stream,
161 QuicStreamId id,
162 QuicIOVector data,
163 QuicStreamOffset offset,
164 bool fin,
165 QuicAckListenerInterface* ack_notifier_delegate) override {
166 QuicConsumedData consumed(data.total_length, fin);
167 if (!writev_consumes_all_data_) {
168 consumed = QuicSession::WritevData(stream, id, data, offset, fin,
169 ack_notifier_delegate);
170 }
171 QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
172 id, consumed.bytes_consumed);
173 return consumed;
174 }
175
176 void set_writev_consumes_all_data(bool val) {
177 writev_consumes_all_data_ = val;
178 }
179
180 QuicConsumedData SendStreamData(ReliableQuicStream* stream) {
181 struct iovec iov;
182 return WritevData(stream, stream->id(), MakeIOVector("not empty", &iov), 0,
183 true, nullptr);
184 }
185
186 QuicConsumedData SendLargeFakeData(ReliableQuicStream* stream, int bytes) {
187 DCHECK(writev_consumes_all_data_);
188 struct iovec iov;
189 iov.iov_base = nullptr; // should not be read.
190 iov.iov_len = static_cast<size_t>(bytes);
191 return WritevData(stream, stream->id(), QuicIOVector(&iov, 1, bytes), 0,
192 true, nullptr);
193 }
194
195 using QuicSession::PostProcessAfterData;
196
197 private:
198 StrictMock<TestCryptoStream> crypto_stream_;
199
200 bool writev_consumes_all_data_;
201 };
202
203 class QuicSessionTestBase : public ::testing::TestWithParam<QuicVersion> {
204 protected:
205 explicit QuicSessionTestBase(Perspective perspective)
206 : connection_(
207 new StrictMock<MockQuicConnection>(&helper_,
208 &alarm_factory_,
209 perspective,
210 SupportedVersions(GetParam()))),
211 session_(connection_) {
212 FLAGS_quic_always_log_bugs_for_tests = true;
213 session_.config()->SetInitialStreamFlowControlWindowToSend(
214 kInitialStreamFlowControlWindowForTest);
215 session_.config()->SetInitialSessionFlowControlWindowToSend(
216 kInitialSessionFlowControlWindowForTest);
217 headers_[":host"] = "www.google.com";
218 headers_[":path"] = "/index.hml";
219 headers_[":scheme"] = "http";
220 headers_["cookie"] =
221 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
222 "__utmc=160408618; "
223 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
224 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
225 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
226 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
227 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
228 "1zFMi5vzcns38-8_Sns; "
229 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
230 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
231 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
232 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
233 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
234 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
235 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
236 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
237 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
238 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
239 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
240 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
241 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
242 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
243 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
244 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
245 // TODO(ianswett): Fix QuicSessionTests so they don't attempt to write
246 // non-crypto stream data at ENCRYPTION_NONE.
247 FLAGS_quic_never_write_unencrypted_data = false;
248 }
249
250 void CheckClosedStreams() {
251 for (QuicStreamId i = kCryptoStreamId; i < 100; i++) {
252 if (!ContainsKey(closed_streams_, i)) {
253 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
254 } else {
255 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
256 }
257 }
258 }
259
260 void CloseStream(QuicStreamId id) {
261 EXPECT_CALL(*connection_, SendRstStream(id, _, _));
262 session_.CloseStream(id);
263 closed_streams_.insert(id);
264 }
265
266 QuicVersion version() const { return connection_->version(); }
267
268 MockQuicConnectionHelper helper_;
269 MockAlarmFactory alarm_factory_;
270 StrictMock<MockQuicConnection>* connection_;
271 TestSession session_;
272 set<QuicStreamId> closed_streams_;
273 SpdyHeaderBlock headers_;
274 };
275
276 class QuicSessionTestServer : public QuicSessionTestBase {
277 protected:
278 QuicSessionTestServer() : QuicSessionTestBase(Perspective::IS_SERVER) {}
279 };
280
281 INSTANTIATE_TEST_CASE_P(Tests,
282 QuicSessionTestServer,
283 ::testing::ValuesIn(QuicSupportedVersions()));
284
285 TEST_P(QuicSessionTestServer, PeerAddress) {
286 EXPECT_EQ(IPEndPoint(Loopback4(), kTestPort), session_.peer_address());
287 }
288
289 TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
290 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
291 CryptoHandshakeMessage message;
292 session_.GetCryptoStream()->OnHandshakeMessage(message);
293 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
294 }
295
296 TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
297 // Ensure that no streams are initially closed.
298 for (QuicStreamId i = kCryptoStreamId; i < 100; i++) {
299 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
300 }
301 }
302
303 TEST_P(QuicSessionTestServer, AvailableStreams) {
304 ASSERT_TRUE(session_.GetOrCreateDynamicStream(9) != nullptr);
305 // Both 5 and 7 should be available.
306 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5));
307 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 7));
308 ASSERT_TRUE(session_.GetOrCreateDynamicStream(7) != nullptr);
309 ASSERT_TRUE(session_.GetOrCreateDynamicStream(5) != nullptr);
310 }
311
312 TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) {
313 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
314 EXPECT_EQ(2u, stream2->id());
315 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
316 EXPECT_EQ(4u, stream4->id());
317
318 CheckClosedStreams();
319 CloseStream(4);
320 CheckClosedStreams();
321 CloseStream(2);
322 CheckClosedStreams();
323 }
324
325 TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) {
326 QuicStreamId stream_id1 = kClientDataStreamId1;
327 QuicStreamId stream_id2 = kClientDataStreamId2;
328 session_.GetOrCreateDynamicStream(stream_id1);
329 session_.GetOrCreateDynamicStream(stream_id2);
330
331 CheckClosedStreams();
332 CloseStream(stream_id1);
333 CheckClosedStreams();
334 CloseStream(stream_id2);
335 // Create a stream, and make another available.
336 ReliableQuicStream* stream3 =
337 session_.GetOrCreateDynamicStream(stream_id2 + 4);
338 CheckClosedStreams();
339 // Close one, but make sure the other is still not closed
340 CloseStream(stream3->id());
341 CheckClosedStreams();
342 }
343
344 TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) {
345 QuicStreamId stream_id = kClientDataStreamId1;
346 session_.GetOrCreateDynamicStream(stream_id);
347 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
348 EXPECT_NE(nullptr,
349 session_.GetOrCreateDynamicStream(
350 stream_id + 2 * (session_.max_open_incoming_streams() - 1)));
351 }
352
353 TEST_P(QuicSessionTestServer, TooManyAvailableStreams) {
354 QuicStreamId stream_id1 = kClientDataStreamId1;
355 QuicStreamId stream_id2;
356 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1));
357 // A stream ID which is too large to create.
358 stream_id2 = stream_id1 + 2 * session_.MaxAvailableStreams() + 4;
359 EXPECT_CALL(*connection_,
360 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
361 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2));
362 }
363
364 TEST_P(QuicSessionTestServer, ManyAvailableStreams) {
365 // When max_open_streams_ is 200, should be able to create 200 streams
366 // out-of-order, that is, creating the one with the largest stream ID first.
367 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
368 QuicStreamId stream_id = kClientDataStreamId1;
369 // Create one stream.
370 session_.GetOrCreateDynamicStream(stream_id);
371 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
372 // Create the largest stream ID of a threatened total of 200 streams.
373 session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1));
374 }
375
376 TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
377 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
378 QuicStreamId closed_stream_id = stream2->id();
379 // Close the stream.
380 EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _));
381 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
382 EXPECT_DEBUG_DFATAL(
383 session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
384 "Marking unknown stream 2 blocked.");
385 }
386
387 TEST_P(QuicSessionTestServer, OnCanWrite) {
388 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
389 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
390 TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
391
392 session_.MarkConnectionLevelWriteBlocked(stream2->id());
393 session_.MarkConnectionLevelWriteBlocked(stream6->id());
394 session_.MarkConnectionLevelWriteBlocked(stream4->id());
395
396 InSequence s;
397 StreamBlocker stream2_blocker(&session_, stream2->id());
398
399 // Reregister, to test the loop limit.
400 EXPECT_CALL(*stream2, OnCanWrite())
401 .WillOnce(Invoke(&stream2_blocker,
402 &StreamBlocker::MarkConnectionLevelWriteBlocked));
403 // 2 will get called a second time as it didn't finish its block
404 EXPECT_CALL(*stream2, OnCanWrite());
405 EXPECT_CALL(*stream6, OnCanWrite());
406 // 4 will not get called, as we exceeded the loop limit.
407 session_.OnCanWrite();
408 EXPECT_TRUE(session_.WillingAndAbleToWrite());
409 }
410
411 TEST_P(QuicSessionTestServer, TestBatchedWrites) {
412 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
413 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
414 TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
415
416 session_.set_writev_consumes_all_data(true);
417 session_.MarkConnectionLevelWriteBlocked(stream2->id());
418 session_.MarkConnectionLevelWriteBlocked(stream4->id());
419
420 StreamBlocker stream2_blocker(&session_, stream2->id());
421 StreamBlocker stream4_blocker(&session_, stream4->id());
422 StreamBlocker stream6_blocker(&session_, stream6->id());
423 // With two sessions blocked, we should get two write calls. They should both
424 // go to the first stream as it will only write 6k and mark itself blocked
425 // again.
426 InSequence s;
427 EXPECT_CALL(*stream2, OnCanWrite())
428 .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
429 &TestSession::SendLargeFakeData,
430 base::Unretained(&session_), stream2, 6000))),
431 Invoke(&stream2_blocker,
432 &StreamBlocker::MarkConnectionLevelWriteBlocked)));
433 EXPECT_CALL(*stream2, OnCanWrite())
434 .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
435 &TestSession::SendLargeFakeData,
436 base::Unretained(&session_), stream2, 6000))),
437 Invoke(&stream2_blocker,
438 &StreamBlocker::MarkConnectionLevelWriteBlocked)));
439 session_.OnCanWrite();
440
441 // We should get one more call for stream2, at which point it has used its
442 // write quota and we move over to stream 4.
443 EXPECT_CALL(*stream2, OnCanWrite())
444 .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
445 &TestSession::SendLargeFakeData,
446 base::Unretained(&session_), stream2, 6000))),
447 Invoke(&stream2_blocker,
448 &StreamBlocker::MarkConnectionLevelWriteBlocked)));
449 EXPECT_CALL(*stream4, OnCanWrite())
450 .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
451 &TestSession::SendLargeFakeData,
452 base::Unretained(&session_), stream4, 6000))),
453 Invoke(&stream4_blocker,
454 &StreamBlocker::MarkConnectionLevelWriteBlocked)));
455 session_.OnCanWrite();
456
457 // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
458 // priority stream 6. 4 should be preempted. 6 will write but *not* block so
459 // will cede back to 4.
460 stream6->SetPriority(kHighestPriority);
461 EXPECT_CALL(*stream4, OnCanWrite())
462 .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
463 &TestSession::SendLargeFakeData,
464 base::Unretained(&session_), stream4, 6000))),
465 Invoke(&stream4_blocker,
466 &StreamBlocker::MarkConnectionLevelWriteBlocked),
467 Invoke(&stream6_blocker,
468 &StreamBlocker::MarkConnectionLevelWriteBlocked)));
469 EXPECT_CALL(*stream6, OnCanWrite())
470 .WillOnce(testing::IgnoreResult(
471 Invoke(CreateFunctor(&TestSession::SendLargeFakeData,
472 base::Unretained(&session_), stream4, 6000))));
473 session_.OnCanWrite();
474
475 // Stream4 alread did 6k worth of writes, so after doing another 12k it should
476 // cede and 2 should resume.
477 EXPECT_CALL(*stream4, OnCanWrite())
478 .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
479 &TestSession::SendLargeFakeData,
480 base::Unretained(&session_), stream4, 12000))),
481 Invoke(&stream4_blocker,
482 &StreamBlocker::MarkConnectionLevelWriteBlocked)));
483 EXPECT_CALL(*stream2, OnCanWrite())
484 .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor(
485 &TestSession::SendLargeFakeData,
486 base::Unretained(&session_), stream2, 6000))),
487 Invoke(&stream2_blocker,
488 &StreamBlocker::MarkConnectionLevelWriteBlocked)));
489 session_.OnCanWrite();
490 }
491
492 TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
493 // Encryption needs to be established before data can be sent.
494 CryptoHandshakeMessage msg;
495 session_.GetCryptoStream()->OnHandshakeMessage(msg);
496
497 // Drive congestion control manually.
498 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
499 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), kDefaultPathId,
500 send_algorithm);
501
502 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
503 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
504 TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
505
506 session_.MarkConnectionLevelWriteBlocked(stream2->id());
507 session_.MarkConnectionLevelWriteBlocked(stream6->id());
508 session_.MarkConnectionLevelWriteBlocked(stream4->id());
509
510 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
511 .WillRepeatedly(Return(QuicTime::Delta::Zero()));
512 EXPECT_CALL(*send_algorithm, GetCongestionWindow())
513 .WillRepeatedly(Return(kMaxPacketSize * 10));
514 EXPECT_CALL(*stream2, OnCanWrite())
515 .WillOnce(testing::IgnoreResult(
516 Invoke(CreateFunctor(&TestSession::SendStreamData,
517 base::Unretained(&session_), stream2))));
518 EXPECT_CALL(*stream4, OnCanWrite())
519 .WillOnce(testing::IgnoreResult(
520 Invoke(CreateFunctor(&TestSession::SendStreamData,
521 base::Unretained(&session_), stream4))));
522 EXPECT_CALL(*stream6, OnCanWrite())
523 .WillOnce(testing::IgnoreResult(
524 Invoke(CreateFunctor(&TestSession::SendStreamData,
525 base::Unretained(&session_), stream6))));
526
527 // Expect that we only send one packet, the writes from different streams
528 // should be bundled together.
529 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
530 QuicConnectionPeer::GetWriter(session_.connection()));
531 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
532 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
533 EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
534 session_.OnCanWrite();
535 EXPECT_FALSE(session_.WillingAndAbleToWrite());
536 }
537
538 TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
539 InSequence s;
540
541 // Drive congestion control manually.
542 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
543 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), kDefaultPathId,
544 send_algorithm);
545
546 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
547 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
548 TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
549
550 session_.MarkConnectionLevelWriteBlocked(stream2->id());
551 session_.MarkConnectionLevelWriteBlocked(stream6->id());
552 session_.MarkConnectionLevelWriteBlocked(stream4->id());
553
554 StreamBlocker stream2_blocker(&session_, stream2->id());
555 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
556 .WillOnce(Return(QuicTime::Delta::Zero()));
557 EXPECT_CALL(*stream2, OnCanWrite());
558 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
559 .WillOnce(Return(QuicTime::Delta::Zero()));
560 EXPECT_CALL(*stream6, OnCanWrite());
561 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
562 .WillOnce(Return(QuicTime::Delta::Infinite()));
563 // stream4->OnCanWrite is not called.
564
565 session_.OnCanWrite();
566 EXPECT_TRUE(session_.WillingAndAbleToWrite());
567
568 // Still congestion-control blocked.
569 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
570 .WillOnce(Return(QuicTime::Delta::Infinite()));
571 session_.OnCanWrite();
572 EXPECT_TRUE(session_.WillingAndAbleToWrite());
573
574 // stream4->OnCanWrite is called once the connection stops being
575 // congestion-control blocked.
576 EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
577 .WillOnce(Return(QuicTime::Delta::Zero()));
578 EXPECT_CALL(*stream4, OnCanWrite());
579 session_.OnCanWrite();
580 EXPECT_FALSE(session_.WillingAndAbleToWrite());
581 }
582
583 TEST_P(QuicSessionTestServer, BufferedHandshake) {
584 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
585
586 // Test that blocking other streams does not change our status.
587 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
588 StreamBlocker stream2_blocker(&session_, stream2->id());
589 stream2_blocker.MarkConnectionLevelWriteBlocked();
590 EXPECT_FALSE(session_.HasPendingHandshake());
591
592 TestStream* stream3 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
593 StreamBlocker stream3_blocker(&session_, stream3->id());
594 stream3_blocker.MarkConnectionLevelWriteBlocked();
595 EXPECT_FALSE(session_.HasPendingHandshake());
596
597 // Blocking (due to buffering of) the Crypto stream is detected.
598 session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId);
599 EXPECT_TRUE(session_.HasPendingHandshake());
600
601 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
602 StreamBlocker stream4_blocker(&session_, stream4->id());
603 stream4_blocker.MarkConnectionLevelWriteBlocked();
604 EXPECT_TRUE(session_.HasPendingHandshake());
605
606 InSequence s;
607 // Force most streams to re-register, which is common scenario when we block
608 // the Crypto stream, and only the crypto stream can "really" write.
609
610 // Due to prioritization, we *should* be asked to write the crypto stream
611 // first.
612 // Don't re-register the crypto stream (which signals complete writing).
613 TestCryptoStream* crypto_stream = session_.GetCryptoStream();
614 EXPECT_CALL(*crypto_stream, OnCanWrite());
615
616 EXPECT_CALL(*stream2, OnCanWrite());
617 EXPECT_CALL(*stream3, OnCanWrite());
618 EXPECT_CALL(*stream4, OnCanWrite())
619 .WillOnce(Invoke(&stream4_blocker,
620 &StreamBlocker::MarkConnectionLevelWriteBlocked));
621
622 session_.OnCanWrite();
623 EXPECT_TRUE(session_.WillingAndAbleToWrite());
624 EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
625 }
626
627 TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
628 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
629 TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
630 TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
631
632 session_.MarkConnectionLevelWriteBlocked(stream2->id());
633 session_.MarkConnectionLevelWriteBlocked(stream6->id());
634 session_.MarkConnectionLevelWriteBlocked(stream4->id());
635 CloseStream(stream6->id());
636
637 InSequence s;
638 EXPECT_CALL(*stream2, OnCanWrite());
639 EXPECT_CALL(*stream4, OnCanWrite());
640 session_.OnCanWrite();
641 EXPECT_FALSE(session_.WillingAndAbleToWrite());
642 }
643
644 TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
645 // Ensure connection level flow control blockage.
646 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
647 EXPECT_TRUE(session_.flow_controller()->IsBlocked());
648 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
649 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
650
651 // Mark the crypto and headers streams as write blocked, we expect them to be
652 // allowed to write later.
653 session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId);
654 session_.MarkConnectionLevelWriteBlocked(kHeadersStreamId);
655
656 // Create a data stream, and although it is write blocked we never expect it
657 // to be allowed to write as we are connection level flow control blocked.
658 TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
659 session_.MarkConnectionLevelWriteBlocked(stream->id());
660 EXPECT_CALL(*stream, OnCanWrite()).Times(0);
661
662 // The crypto and headers streams should be called even though we are
663 // connection flow control blocked.
664 TestCryptoStream* crypto_stream = session_.GetCryptoStream();
665 EXPECT_CALL(*crypto_stream, OnCanWrite());
666 TestHeadersStream* headers_stream = new TestHeadersStream(&session_);
667 QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
668 EXPECT_CALL(*headers_stream, OnCanWrite());
669
670 session_.OnCanWrite();
671 EXPECT_FALSE(session_.WillingAndAbleToWrite());
672 }
673
674 TEST_P(QuicSessionTestServer, SendGoAway) {
675 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
676 QuicConnectionPeer::GetWriter(session_.connection()));
677 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
678 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
679 EXPECT_CALL(*connection_, SendGoAway(_, _, _))
680 .WillOnce(Invoke(connection_, &MockQuicConnection::ReallySendGoAway));
681 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
682 EXPECT_TRUE(session_.goaway_sent());
683
684 const QuicStreamId kTestStreamId = 5u;
685 EXPECT_CALL(*connection_,
686 SendRstStream(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY, 0))
687 .Times(0);
688 EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId));
689 }
690
691 TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
692 EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
693 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
694 CryptoHandshakeMessage msg;
695 session_.GetCryptoStream()->OnHandshakeMessage(msg);
696 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
697 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
698 }
699
700 TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) {
701 // Send two bytes of payload.
702 QuicStreamFrame data1(kClientDataStreamId1, false, 0, StringPiece("HT"));
703 session_.OnStreamFrame(data1);
704 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
705
706 EXPECT_CALL(*connection_, SendRstStream(kClientDataStreamId1, _, _));
707 QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM,
708 0);
709 session_.OnRstStream(rst1);
710 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
711 // Connection should remain alive.
712 EXPECT_TRUE(connection_->connected());
713 }
714
715 TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
716 // Test that if a stream is flow control blocked, then on receipt of the SHLO
717 // containing a suitable send window offset, the stream becomes unblocked.
718
719 // Ensure that Writev consumes all the data it is given (simulate no socket
720 // blocking).
721 session_.set_writev_consumes_all_data(true);
722
723 // Create a stream, and send enough data to make it flow control blocked.
724 TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority);
725 string body(kMinimumFlowControlSendWindow, '.');
726 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
727 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
728 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
729 EXPECT_CALL(*connection_, SendBlocked(_)).Times(AtLeast(1));
730 EXPECT_CALL(*connection_, SendBlocked(0));
731 stream2->WriteOrBufferBody(body, false, nullptr);
732 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
733 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
734 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
735
736 // The handshake message will call OnCanWrite, so the stream can resume
737 // writing.
738 EXPECT_CALL(*stream2, OnCanWrite());
739 // Now complete the crypto handshake, resulting in an increased flow control
740 // send window.
741 CryptoHandshakeMessage msg;
742 session_.GetCryptoStream()->OnHandshakeMessage(msg);
743
744 // Stream is now unblocked.
745 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
746 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
747 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
748 }
749
750 TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
751 // Test that if the crypto stream is flow control blocked, then if the SHLO
752 // contains a larger send window offset, the stream becomes unblocked.
753 session_.set_writev_consumes_all_data(true);
754 TestCryptoStream* crypto_stream = session_.GetCryptoStream();
755 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
756 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
757 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
758 QuicHeadersStream* headers_stream =
759 QuicSpdySessionPeer::GetHeadersStream(&session_);
760 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
761 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
762 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
763 // Write until the crypto stream is flow control blocked.
764 EXPECT_CALL(*connection_, SendBlocked(kCryptoStreamId));
765 for (QuicStreamId i = 0;
766 !crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
767 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
768 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
769 QuicConfig config;
770 CryptoHandshakeMessage crypto_message;
771 config.ToHandshakeMessage(&crypto_message);
772 crypto_stream->SendHandshakeMessage(crypto_message);
773 }
774 EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
775 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
776 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
777 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
778 EXPECT_FALSE(session_.HasDataToWrite());
779 EXPECT_TRUE(crypto_stream->HasBufferedData());
780
781 // The handshake message will call OnCanWrite, so the stream can
782 // resume writing.
783 EXPECT_CALL(*crypto_stream, OnCanWrite());
784 // Now complete the crypto handshake, resulting in an increased flow control
785 // send window.
786 CryptoHandshakeMessage msg;
787 session_.GetCryptoStream()->OnHandshakeMessage(msg);
788
789 // Stream is now unblocked and will no longer have buffered data.
790 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
791 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
792 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
793 }
794
795 #if !defined(OS_IOS)
796 // This test is failing flakily for iOS bots.
797 // http://crbug.com/425050
798 // NOTE: It's not possible to use the standard MAYBE_ convention to disable
799 // this test on iOS because when this test gets instantiated it ends up with
800 // various names that are dependent on the parameters passed.
801 TEST_P(QuicSessionTestServer,
802 HandshakeUnblocksFlowControlBlockedHeadersStream) {
803 // Test that if the header stream is flow control blocked, then if the SHLO
804 // contains a larger send window offset, the stream becomes unblocked.
805 session_.set_writev_consumes_all_data(true);
806 TestCryptoStream* crypto_stream = session_.GetCryptoStream();
807 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
808 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
809 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
810 QuicHeadersStream* headers_stream =
811 QuicSpdySessionPeer::GetHeadersStream(&session_);
812 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
813 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
814 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
815 QuicStreamId stream_id = 5;
816 // Write until the header stream is flow control blocked.
817 EXPECT_CALL(*connection_, SendBlocked(kHeadersStreamId));
818 SpdyHeaderBlock headers;
819 while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2000) {
820 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
821 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
822 headers["header"] = base::Uint64ToString(base::RandUint64()) +
823 base::Uint64ToString(base::RandUint64()) +
824 base::Uint64ToString(base::RandUint64());
825 headers_stream->WriteHeaders(stream_id, headers.Clone(), true, 0, nullptr);
826 stream_id += 2;
827 }
828 // Write once more to ensure that the headers stream has buffered data. The
829 // random headers may have exactly filled the flow control window.
830 headers_stream->WriteHeaders(stream_id, std::move(headers), true, 0, nullptr);
831 EXPECT_TRUE(headers_stream->HasBufferedData());
832
833 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked());
834 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
835 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
836 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
837 EXPECT_FALSE(session_.HasDataToWrite());
838
839 // Now complete the crypto handshake, resulting in an increased flow control
840 // send window.
841 CryptoHandshakeMessage msg;
842 session_.GetCryptoStream()->OnHandshakeMessage(msg);
843
844 // Stream is now unblocked and will no longer have buffered data.
845 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
846 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
847 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
848 EXPECT_FALSE(headers_stream->HasBufferedData());
849 }
850 #endif // !defined(OS_IOS)
851
852 TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
853 // Test that when we receive an out of order stream RST we correctly adjust
854 // our connection level flow control receive window.
855 // On close, the stream should mark as consumed all bytes between the highest
856 // byte consumed so far and the final byte offset from the RST frame.
857 TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
858
859 const QuicStreamOffset kByteOffset =
860 1 + kInitialSessionFlowControlWindowForTest / 2;
861
862 // Expect no stream WINDOW_UPDATE frames, as stream read side closed.
863 EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0);
864 // We do expect a connection level WINDOW_UPDATE when the stream is reset.
865 EXPECT_CALL(*connection_,
866 SendWindowUpdate(
867 0, kInitialSessionFlowControlWindowForTest + kByteOffset));
868
869 EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
870 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED,
871 kByteOffset);
872 session_.OnRstStream(rst_frame);
873 session_.PostProcessAfterData();
874 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
875 }
876
877 TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
878 // Test the situation where we receive a FIN on a stream, and before we fully
879 // consume all the data from the sequencer buffer we locally RST the stream.
880 // The bytes between highest consumed byte, and the final byte offset that we
881 // determined when the FIN arrived, should be marked as consumed at the
882 // connection level flow controller when the stream is reset.
883 TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
884
885 const QuicStreamOffset kByteOffset =
886 kInitialSessionFlowControlWindowForTest / 2 - 1;
887 QuicStreamFrame frame(stream->id(), true, kByteOffset, ".");
888 session_.OnStreamFrame(frame);
889 session_.PostProcessAfterData();
890 EXPECT_TRUE(connection_->connected());
891
892 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
893 EXPECT_EQ(kByteOffset + frame.data_length,
894 stream->flow_controller()->highest_received_byte_offset());
895
896 // Reset stream locally.
897 EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
898 stream->Reset(QUIC_STREAM_CANCELLED);
899 EXPECT_EQ(kByteOffset + frame.data_length,
900 session_.flow_controller()->bytes_consumed());
901 }
902
903 TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
904 // Test that when we RST the stream (and tear down stream state), and then
905 // receive a FIN from the peer, we correctly adjust our connection level flow
906 // control receive window.
907
908 // Connection starts with some non-zero highest received byte offset,
909 // due to other active streams.
910 const uint64_t kInitialConnectionBytesConsumed = 567;
911 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
912 EXPECT_LT(kInitialConnectionBytesConsumed,
913 kInitialConnectionHighestReceivedOffset);
914 session_.flow_controller()->UpdateHighestReceivedOffset(
915 kInitialConnectionHighestReceivedOffset);
916 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
917
918 // Reset our stream: this results in the stream being closed locally.
919 TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
920 EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
921 stream->Reset(QUIC_STREAM_CANCELLED);
922
923 // Now receive a response from the peer with a FIN. We should handle this by
924 // adjusting the connection level flow control receive window to take into
925 // account the total number of bytes sent by the peer.
926 const QuicStreamOffset kByteOffset = 5678;
927 string body = "hello";
928 QuicStreamFrame frame(stream->id(), true, kByteOffset, StringPiece(body));
929 session_.OnStreamFrame(frame);
930
931 QuicStreamOffset total_stream_bytes_sent_by_peer =
932 kByteOffset + body.length();
933 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer,
934 session_.flow_controller()->bytes_consumed());
935 EXPECT_EQ(
936 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer,
937 session_.flow_controller()->highest_received_byte_offset());
938 }
939
940 TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
941 // Test that when we RST the stream (and tear down stream state), and then
942 // receive a RST from the peer, we correctly adjust our connection level flow
943 // control receive window.
944
945 // Connection starts with some non-zero highest received byte offset,
946 // due to other active streams.
947 const uint64_t kInitialConnectionBytesConsumed = 567;
948 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
949 EXPECT_LT(kInitialConnectionBytesConsumed,
950 kInitialConnectionHighestReceivedOffset);
951 session_.flow_controller()->UpdateHighestReceivedOffset(
952 kInitialConnectionHighestReceivedOffset);
953 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
954
955 // Reset our stream: this results in the stream being closed locally.
956 TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
957 EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
958 stream->Reset(QUIC_STREAM_CANCELLED);
959 EXPECT_TRUE(ReliableQuicStreamPeer::read_side_closed(stream));
960
961 // Now receive a RST from the peer. We should handle this by adjusting the
962 // connection level flow control receive window to take into account the total
963 // number of bytes sent by the peer.
964 const QuicStreamOffset kByteOffset = 5678;
965 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED,
966 kByteOffset);
967 session_.OnRstStream(rst_frame);
968
969 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset,
970 session_.flow_controller()->bytes_consumed());
971 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset,
972 session_.flow_controller()->highest_received_byte_offset());
973 }
974
975 TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
976 // Test that receipt of an invalid (< default) stream flow control window from
977 // the peer results in the connection being torn down.
978 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
979 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
980 kInvalidWindow);
981
982 EXPECT_CALL(*connection_,
983 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
984 session_.OnConfigNegotiated();
985 }
986
987 TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
988 // Test that receipt of an invalid (< default) session flow control window
989 // from the peer results in the connection being torn down.
990 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
991 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
992 kInvalidWindow);
993
994 EXPECT_CALL(*connection_,
995 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
996 session_.OnConfigNegotiated();
997 }
998
999 TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
1000 // Test that if we receive a stream RST with a highest byte offset that
1001 // violates flow control, that we close the connection.
1002 const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
1003 EXPECT_CALL(*connection_,
1004 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
1005 .Times(2);
1006
1007 // Check that stream frame + FIN results in connection close.
1008 TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
1009 EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
1010 stream->Reset(QUIC_STREAM_CANCELLED);
1011 QuicStreamFrame frame(stream->id(), true, kLargeOffset, StringPiece());
1012 session_.OnStreamFrame(frame);
1013
1014 // Check that RST results in connection close.
1015 QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED,
1016 kLargeOffset);
1017 session_.OnRstStream(rst_frame);
1018 }
1019
1020 TEST_P(QuicSessionTestServer, WindowUpdateUnblocksHeadersStream) {
1021 // Test that a flow control blocked headers stream gets unblocked on recipt of
1022 // a WINDOW_UPDATE frame.
1023
1024 // Set the headers stream to be flow control blocked.
1025 QuicHeadersStream* headers_stream =
1026 QuicSpdySessionPeer::GetHeadersStream(&session_);
1027 QuicFlowControllerPeer::SetSendWindowOffset(headers_stream->flow_controller(),
1028 0);
1029 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked());
1030 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1031 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1032
1033 // Unblock the headers stream by supplying a WINDOW_UPDATE.
1034 QuicWindowUpdateFrame window_update_frame(headers_stream->id(),
1035 2 * kMinimumFlowControlSendWindow);
1036 session_.OnWindowUpdateFrame(window_update_frame);
1037 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
1038 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1039 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1040 }
1041
1042 TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
1043 // If a buggy/malicious peer creates too many streams that are not ended
1044 // with a FIN or RST then we send an RST to refuse streams.
1045 const QuicStreamId kMaxStreams = 5;
1046 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1047 const QuicStreamId kFirstStreamId = kClientDataStreamId1;
1048 const QuicStreamId kFinalStreamId = kClientDataStreamId1 + 2 * kMaxStreams;
1049
1050 // Create kMaxStreams data streams, and close them all without receiving a
1051 // FIN or a RST_STREAM from the client.
1052 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) {
1053 QuicStreamFrame data1(i, false, 0, StringPiece("HT"));
1054 session_.OnStreamFrame(data1);
1055 // EXPECT_EQ(1u, session_.GetNumOpenStreams());
1056 EXPECT_CALL(*connection_, SendRstStream(i, _, _));
1057 session_.CloseStream(i);
1058 }
1059
1060 EXPECT_CALL(*connection_,
1061 SendRstStream(kFinalStreamId, QUIC_REFUSED_STREAM, _))
1062 .Times(1);
1063 // Create one more data streams to exceed limit of open stream.
1064 QuicStreamFrame data1(kFinalStreamId, false, 0, StringPiece("HT"));
1065 session_.OnStreamFrame(data1);
1066
1067 // Called after any new data is received by the session, and triggers the
1068 // call to close the connection.
1069 session_.PostProcessAfterData();
1070 }
1071
1072 TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
1073 // Verify that a draining stream (which has received a FIN but not consumed
1074 // it) does not count against the open quota (because it is closed from the
1075 // protocol point of view).
1076 EXPECT_CALL(*connection_, SendRstStream(_, QUIC_REFUSED_STREAM, _)).Times(0);
1077 const QuicStreamId kMaxStreams = 5;
1078 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1079
1080 // Create kMaxStreams + 1 data streams, and mark them draining.
1081 const QuicStreamId kFirstStreamId = kClientDataStreamId1;
1082 const QuicStreamId kFinalStreamId =
1083 kClientDataStreamId1 + 2 * kMaxStreams + 1;
1084 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) {
1085 QuicStreamFrame data1(i, true, 0, StringPiece("HT"));
1086 session_.OnStreamFrame(data1);
1087 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
1088 session_.StreamDraining(i);
1089 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1090 }
1091
1092 // Called after any new data is received by the session, and triggers the call
1093 // to close the connection.
1094 session_.PostProcessAfterData();
1095 }
1096
1097 TEST_P(QuicSessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) {
1098 // Tests that on server side, the value of max_open_incoming/outgoing streams
1099 // are setup correctly during negotiation.
1100 // The value for outgoing stream is limited to negotiated value and for
1101 // incoming stream it is set to be larger than that.
1102 session_.OnConfigNegotiated();
1103 // The max number of open outgoing streams is less than that of incoming
1104 // streams, and it should be same as negotiated value.
1105 EXPECT_LT(session_.max_open_outgoing_streams(),
1106 session_.max_open_incoming_streams());
1107 EXPECT_EQ(session_.max_open_outgoing_streams(),
1108 kDefaultMaxStreamsPerConnection);
1109 EXPECT_GT(session_.max_open_incoming_streams(),
1110 kDefaultMaxStreamsPerConnection);
1111 }
1112
1113 TEST_P(QuicSessionTestServer, EnableFHOLThroughConfigOption) {
1114 QuicConfigPeer::SetReceivedForceHolBlocking(session_.config());
1115 session_.OnConfigNegotiated();
1116 if (version() <= QUIC_VERSION_35) {
1117 EXPECT_FALSE(session_.force_hol_blocking());
1118 } else {
1119 EXPECT_TRUE(session_.force_hol_blocking());
1120 }
1121 }
1122
1123 class QuicSessionTestClient : public QuicSessionTestBase {
1124 protected:
1125 QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {}
1126 };
1127
1128 INSTANTIATE_TEST_CASE_P(Tests,
1129 QuicSessionTestClient,
1130 ::testing::ValuesIn(QuicSupportedVersions()));
1131
1132 TEST_P(QuicSessionTestClient, AvailableStreamsClient) {
1133 ASSERT_TRUE(session_.GetOrCreateDynamicStream(6) != nullptr);
1134 // Both 2 and 4 should be available.
1135 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 2));
1136 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 4));
1137 ASSERT_TRUE(session_.GetOrCreateDynamicStream(2) != nullptr);
1138 ASSERT_TRUE(session_.GetOrCreateDynamicStream(4) != nullptr);
1139 // And 5 should be not available.
1140 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(&session_, 5));
1141 }
1142
1143 TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
1144 // Verify that an incoming FIN is recorded in a stream object even if the read
1145 // side has been closed. This prevents an entry from being made in
1146 // locally_closed_streams_highest_offset_ (which will never be deleted).
1147 TestStream* stream = session_.CreateOutgoingDynamicStream(kDefaultPriority);
1148 QuicStreamId stream_id = stream->id();
1149
1150 // Close the read side manually.
1151 ReliableQuicStreamPeer::CloseReadSide(stream);
1152
1153 // Receive a stream data frame with FIN.
1154 QuicStreamFrame frame(stream_id, true, 0, StringPiece());
1155 session_.OnStreamFrame(frame);
1156 EXPECT_TRUE(stream->fin_received());
1157
1158 // Reset stream locally.
1159 EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
1160 stream->Reset(QUIC_STREAM_CANCELLED);
1161 EXPECT_TRUE(ReliableQuicStreamPeer::read_side_closed(stream));
1162
1163 // Allow the session to delete the stream object.
1164 session_.PostProcessAfterData();
1165 EXPECT_TRUE(connection_->connected());
1166 EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
1167 EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
1168
1169 // The stream is not waiting for the arrival of the peer's final offset as it
1170 // was received with the FIN earlier.
1171 EXPECT_EQ(
1172 0u,
1173 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
1174 }
1175
1176 TEST_P(QuicSessionTestClient, TestMaxIncomingAndOutgoingStreamsAllowed) {
1177 // Tests that on client side, the value of max_open_incoming/outgoing streams
1178 // are setup correctly during negotiation.
1179 // When flag is true, the value for outgoing stream is limited to negotiated
1180 // value and for incoming stream it is set to be larger than that.
1181 session_.OnConfigNegotiated();
1182 EXPECT_LT(session_.max_open_outgoing_streams(),
1183 session_.max_open_incoming_streams());
1184 EXPECT_EQ(session_.max_open_outgoing_streams(),
1185 kDefaultMaxStreamsPerConnection);
1186 }
1187
1188 TEST_P(QuicSessionTestClient, EnableDHDTThroughConnectionOption) {
1189 FLAGS_quic_disable_hpack_dynamic_table = true;
1190
1191 QuicTagVector copt;
1192 copt.push_back(kDHDT);
1193 QuicConfigPeer::SetConnectionOptionsToSend(session_.config(), copt);
1194 session_.OnConfigNegotiated();
1195 EXPECT_EQ(QuicHeadersStreamPeer::GetSpdyFramer(session_.headers_stream())
1196 .header_encoder_table_size(),
1197 0UL);
1198 }
1199
1200 TEST_P(QuicSessionTestClient, EnableFHOLThroughConfigOption) {
1201 session_.config()->SetForceHolBlocking();
1202 session_.OnConfigNegotiated();
1203 if (version() <= QUIC_VERSION_35) {
1204 EXPECT_FALSE(session_.force_hol_blocking());
1205 } else {
1206 EXPECT_TRUE(session_.force_hol_blocking());
1207 }
1208 }
1209
1210 } // namespace
1211 } // namespace test
1212 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_session.cc ('k') | net/quic/quic_simple_buffer_allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698