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.
5 #include "net/quic/quic_session.h"
10 #include "base/basictypes.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/rand_util.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "net/quic/crypto/crypto_protocol.h"
16 #include "net/quic/quic_crypto_stream.h"
17 #include "net/quic/quic_flags.h"
18 #include "net/quic/quic_protocol.h"
19 #include "net/quic/quic_utils.h"
20 #include "net/quic/reliable_quic_stream.h"
21 #include "net/quic/test_tools/quic_config_peer.h"
22 #include "net/quic/test_tools/quic_connection_peer.h"
23 #include "net/quic/test_tools/quic_data_stream_peer.h"
24 #include "net/quic/test_tools/quic_flow_controller_peer.h"
25 #include "net/quic/test_tools/quic_session_peer.h"
26 #include "net/quic/test_tools/quic_test_utils.h"
27 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
28 #include "net/spdy/spdy_framer.h"
29 #include "net/test/gtest_util.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gmock_mutant.h"
32 #include "testing/gtest/include/gtest/gtest.h"
37 using testing::CreateFunctor
;
38 using testing::InSequence
;
39 using testing::Invoke
;
40 using testing::Return
;
41 using testing::StrictMock
;
48 const QuicPriority kHighestPriority
= 0;
49 const QuicPriority kSomeMiddlePriority
= 3;
51 class TestCryptoStream
: public QuicCryptoStream
{
53 explicit TestCryptoStream(QuicSession
* session
)
54 : QuicCryptoStream(session
) {
57 virtual void OnHandshakeMessage(
58 const CryptoHandshakeMessage
& message
) override
{
59 encryption_established_
= true;
60 handshake_confirmed_
= true;
61 CryptoHandshakeMessage msg
;
63 session()->config()->SetInitialFlowControlWindowToSend(
64 kInitialSessionFlowControlWindowForTest
);
65 session()->config()->SetInitialStreamFlowControlWindowToSend(
66 kInitialStreamFlowControlWindowForTest
);
67 session()->config()->SetInitialSessionFlowControlWindowToSend(
68 kInitialSessionFlowControlWindowForTest
);
69 session()->config()->ToHandshakeMessage(&msg
);
70 const QuicErrorCode error
= session()->config()->ProcessPeerHello(
71 msg
, CLIENT
, &error_details
);
72 EXPECT_EQ(QUIC_NO_ERROR
, error
);
73 session()->OnConfigNegotiated();
74 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED
);
77 MOCK_METHOD0(OnCanWrite
, void());
80 class TestHeadersStream
: public QuicHeadersStream
{
82 explicit TestHeadersStream(QuicSession
* session
)
83 : QuicHeadersStream(session
) {
86 MOCK_METHOD0(OnCanWrite
, void());
89 class TestStream
: public QuicDataStream
{
91 TestStream(QuicStreamId id
, QuicSession
* session
)
92 : QuicDataStream(id
, session
) {
95 using ReliableQuicStream::CloseWriteSide
;
97 virtual uint32
ProcessData(const char* data
, uint32 data_len
) override
{
101 void SendBody(const string
& data
, bool fin
) {
102 WriteOrBufferData(data
, fin
, nullptr);
105 MOCK_METHOD0(OnCanWrite
, void());
108 // Poor man's functor for use as callback in a mock.
109 class StreamBlocker
{
111 StreamBlocker(QuicSession
* session
, QuicStreamId stream_id
)
113 stream_id_(stream_id
) {
116 void MarkWriteBlocked() {
117 session_
->MarkWriteBlocked(stream_id_
, kSomeMiddlePriority
);
121 QuicSession
* const session_
;
122 const QuicStreamId stream_id_
;
125 class TestSession
: public QuicSession
{
127 explicit TestSession(QuicConnection
* connection
)
128 : QuicSession(connection
,
129 DefaultQuicConfig()),
130 crypto_stream_(this),
131 writev_consumes_all_data_(false) {
135 virtual TestCryptoStream
* GetCryptoStream() override
{
136 return &crypto_stream_
;
139 virtual TestStream
* CreateOutgoingDataStream() override
{
140 TestStream
* stream
= new TestStream(GetNextStreamId(), this);
141 ActivateStream(stream
);
145 virtual TestStream
* CreateIncomingDataStream(QuicStreamId id
) override
{
146 return new TestStream(id
, this);
149 bool IsClosedStream(QuicStreamId id
) {
150 return QuicSession::IsClosedStream(id
);
153 QuicDataStream
* GetIncomingDataStream(QuicStreamId stream_id
) {
154 return QuicSession::GetIncomingDataStream(stream_id
);
157 virtual QuicConsumedData
WritevData(
159 const IOVector
& data
,
160 QuicStreamOffset offset
,
162 FecProtection fec_protection
,
163 QuicAckNotifier::DelegateInterface
* ack_notifier_delegate
) override
{
164 // Always consumes everything.
165 if (writev_consumes_all_data_
) {
166 return QuicConsumedData(data
.TotalBufferSize(), fin
);
168 return QuicSession::WritevData(id
, data
, offset
, fin
, fec_protection
,
169 ack_notifier_delegate
);
173 void set_writev_consumes_all_data(bool val
) {
174 writev_consumes_all_data_
= val
;
177 QuicConsumedData
SendStreamData(QuicStreamId id
) {
178 return WritevData(id
, IOVector(), 0, true, MAY_FEC_PROTECT
, nullptr);
181 using QuicSession::PostProcessAfterData
;
184 StrictMock
<TestCryptoStream
> crypto_stream_
;
186 bool writev_consumes_all_data_
;
189 class QuicSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
192 : connection_(new MockConnection(true, SupportedVersions(GetParam()))),
193 session_(connection_
) {
194 session_
.config()->SetInitialFlowControlWindowToSend(
195 kInitialSessionFlowControlWindowForTest
);
196 session_
.config()->SetInitialStreamFlowControlWindowToSend(
197 kInitialStreamFlowControlWindowForTest
);
198 session_
.config()->SetInitialSessionFlowControlWindowToSend(
199 kInitialSessionFlowControlWindowForTest
);
200 headers_
[":host"] = "www.google.com";
201 headers_
[":path"] = "/index.hml";
202 headers_
[":scheme"] = "http";
204 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
206 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
207 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
208 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
209 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
210 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
211 "1zFMi5vzcns38-8_Sns; "
212 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
213 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
214 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
215 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
216 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
217 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
218 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
219 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
220 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
221 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
222 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
223 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
224 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
225 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
226 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
229 void CheckClosedStreams() {
230 for (int i
= kCryptoStreamId
; i
< 100; i
++) {
231 if (!ContainsKey(closed_streams_
, i
)) {
232 EXPECT_FALSE(session_
.IsClosedStream(i
)) << " stream id: " << i
;
234 EXPECT_TRUE(session_
.IsClosedStream(i
)) << " stream id: " << i
;
239 void CloseStream(QuicStreamId id
) {
240 session_
.CloseStream(id
);
241 closed_streams_
.insert(id
);
244 QuicVersion
version() const { return connection_
->version(); }
246 MockConnection
* connection_
;
247 TestSession session_
;
248 set
<QuicStreamId
> closed_streams_
;
249 SpdyHeaderBlock headers_
;
252 INSTANTIATE_TEST_CASE_P(Tests
, QuicSessionTest
,
253 ::testing::ValuesIn(QuicSupportedVersions()));
255 TEST_P(QuicSessionTest
, PeerAddress
) {
256 EXPECT_EQ(IPEndPoint(Loopback4(), kTestPort
), session_
.peer_address());
259 TEST_P(QuicSessionTest
, IsCryptoHandshakeConfirmed
) {
260 EXPECT_FALSE(session_
.IsCryptoHandshakeConfirmed());
261 CryptoHandshakeMessage message
;
262 session_
.GetCryptoStream()->OnHandshakeMessage(message
);
263 EXPECT_TRUE(session_
.IsCryptoHandshakeConfirmed());
266 TEST_P(QuicSessionTest
, IsClosedStreamDefault
) {
267 // Ensure that no streams are initially closed.
268 for (int i
= kCryptoStreamId
; i
< 100; i
++) {
269 EXPECT_FALSE(session_
.IsClosedStream(i
)) << "stream id: " << i
;
273 TEST_P(QuicSessionTest
, ImplicitlyCreatedStreams
) {
274 ASSERT_TRUE(session_
.GetIncomingDataStream(7) != nullptr);
275 // Both 3 and 5 should be implicitly created.
276 EXPECT_FALSE(session_
.IsClosedStream(3));
277 EXPECT_FALSE(session_
.IsClosedStream(5));
278 ASSERT_TRUE(session_
.GetIncomingDataStream(5) != nullptr);
279 ASSERT_TRUE(session_
.GetIncomingDataStream(3) != nullptr);
282 TEST_P(QuicSessionTest
, IsClosedStreamLocallyCreated
) {
283 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
284 EXPECT_EQ(2u, stream2
->id());
285 TestStream
* stream4
= session_
.CreateOutgoingDataStream();
286 EXPECT_EQ(4u, stream4
->id());
288 CheckClosedStreams();
290 CheckClosedStreams();
292 CheckClosedStreams();
295 TEST_P(QuicSessionTest
, IsClosedStreamPeerCreated
) {
296 QuicStreamId stream_id1
= kClientDataStreamId1
;
297 QuicStreamId stream_id2
= kClientDataStreamId2
;
298 QuicDataStream
* stream1
= session_
.GetIncomingDataStream(stream_id1
);
299 QuicDataStreamPeer::SetHeadersDecompressed(stream1
, true);
300 QuicDataStream
* stream2
= session_
.GetIncomingDataStream(stream_id2
);
301 QuicDataStreamPeer::SetHeadersDecompressed(stream2
, true);
303 CheckClosedStreams();
304 CloseStream(stream_id1
);
305 CheckClosedStreams();
306 CloseStream(stream_id2
);
307 // Create a stream explicitly, and another implicitly.
308 QuicDataStream
* stream3
= session_
.GetIncomingDataStream(stream_id2
+ 4);
309 QuicDataStreamPeer::SetHeadersDecompressed(stream3
, true);
310 CheckClosedStreams();
311 // Close one, but make sure the other is still not closed
312 CloseStream(stream3
->id());
313 CheckClosedStreams();
316 TEST_P(QuicSessionTest
, StreamIdTooLarge
) {
317 QuicStreamId stream_id
= kClientDataStreamId1
;
318 session_
.GetIncomingDataStream(stream_id
);
319 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_INVALID_STREAM_ID
));
320 session_
.GetIncomingDataStream(stream_id
+ kMaxStreamIdDelta
+ 2);
323 TEST_P(QuicSessionTest
, DecompressionError
) {
324 QuicHeadersStream
* stream
= QuicSessionPeer::GetHeadersStream(&session_
);
325 const unsigned char data
[] = {
326 0x80, 0x03, 0x00, 0x01, // SPDY/3 SYN_STREAM frame
327 0x00, 0x00, 0x00, 0x25, // flags/length
328 0x00, 0x00, 0x00, 0x05, // stream id
329 0x00, 0x00, 0x00, 0x00, // associated stream id
331 'a', 'b', 'c', 'd' // invalid compressed data
333 EXPECT_CALL(*connection_
,
334 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA
,
335 "SPDY framing error."));
336 stream
->ProcessRawData(reinterpret_cast<const char*>(data
),
340 TEST_P(QuicSessionTest
, DebugDFatalIfMarkingClosedStreamWriteBlocked
) {
341 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
343 stream2
->Reset(QUIC_BAD_APPLICATION_PAYLOAD
);
344 // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL.
346 QuicStreamId kClosedStreamId = stream2->id();
348 session_.MarkWriteBlocked(kClosedStreamId, kSomeMiddlePriority),
349 "Marking unknown stream 2 blocked.");
353 TEST_P(QuicSessionTest
, DebugDFatalIfMarkWriteBlockedCalledWithWrongPriority
) {
354 const QuicPriority kDifferentPriority
= 0;
356 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
357 EXPECT_NE(kDifferentPriority
, stream2
->EffectivePriority());
358 // TODO(rtenneti): enable when chromium supports EXPECT_DEBUG_DFATAL.
361 session_.MarkWriteBlocked(stream2->id(), kDifferentPriority),
362 "Priorities do not match. Got: 0 Expected: 3");
366 TEST_P(QuicSessionTest
, OnCanWrite
) {
367 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
368 TestStream
* stream4
= session_
.CreateOutgoingDataStream();
369 TestStream
* stream6
= session_
.CreateOutgoingDataStream();
371 session_
.MarkWriteBlocked(stream2
->id(), kSomeMiddlePriority
);
372 session_
.MarkWriteBlocked(stream6
->id(), kSomeMiddlePriority
);
373 session_
.MarkWriteBlocked(stream4
->id(), kSomeMiddlePriority
);
376 StreamBlocker
stream2_blocker(&session_
, stream2
->id());
377 // Reregister, to test the loop limit.
378 EXPECT_CALL(*stream2
, OnCanWrite())
379 .WillOnce(Invoke(&stream2_blocker
, &StreamBlocker::MarkWriteBlocked
));
380 EXPECT_CALL(*stream6
, OnCanWrite());
381 EXPECT_CALL(*stream4
, OnCanWrite());
382 session_
.OnCanWrite();
383 EXPECT_TRUE(session_
.WillingAndAbleToWrite());
386 TEST_P(QuicSessionTest
, OnCanWriteBundlesStreams
) {
387 // Drive congestion control manually.
388 MockSendAlgorithm
* send_algorithm
= new StrictMock
<MockSendAlgorithm
>;
389 QuicConnectionPeer::SetSendAlgorithm(session_
.connection(), send_algorithm
);
391 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
392 TestStream
* stream4
= session_
.CreateOutgoingDataStream();
393 TestStream
* stream6
= session_
.CreateOutgoingDataStream();
395 session_
.MarkWriteBlocked(stream2
->id(), kSomeMiddlePriority
);
396 session_
.MarkWriteBlocked(stream6
->id(), kSomeMiddlePriority
);
397 session_
.MarkWriteBlocked(stream4
->id(), kSomeMiddlePriority
);
399 EXPECT_CALL(*send_algorithm
, TimeUntilSend(_
, _
, _
)).WillRepeatedly(
400 Return(QuicTime::Delta::Zero()));
401 EXPECT_CALL(*send_algorithm
, GetCongestionWindow())
402 .WillOnce(Return(kMaxPacketSize
* 10));
403 EXPECT_CALL(*stream2
, OnCanWrite())
404 .WillOnce(IgnoreResult(Invoke(CreateFunctor(
405 &session_
, &TestSession::SendStreamData
, stream2
->id()))));
406 EXPECT_CALL(*stream4
, OnCanWrite())
407 .WillOnce(IgnoreResult(Invoke(CreateFunctor(
408 &session_
, &TestSession::SendStreamData
, stream4
->id()))));
409 EXPECT_CALL(*stream6
, OnCanWrite())
410 .WillOnce(IgnoreResult(Invoke(CreateFunctor(
411 &session_
, &TestSession::SendStreamData
, stream6
->id()))));
413 // Expect that we only send one packet, the writes from different streams
414 // should be bundled together.
415 MockPacketWriter
* writer
=
416 static_cast<MockPacketWriter
*>(
417 QuicConnectionPeer::GetWriter(session_
.connection()));
418 EXPECT_CALL(*writer
, WritePacket(_
, _
, _
, _
)).WillOnce(
419 Return(WriteResult(WRITE_STATUS_OK
, 0)));
420 EXPECT_CALL(*send_algorithm
, OnPacketSent(_
, _
, _
, _
, _
)).Times(1);
421 session_
.OnCanWrite();
422 EXPECT_FALSE(session_
.WillingAndAbleToWrite());
425 TEST_P(QuicSessionTest
, OnCanWriteCongestionControlBlocks
) {
428 // Drive congestion control manually.
429 MockSendAlgorithm
* send_algorithm
= new StrictMock
<MockSendAlgorithm
>;
430 QuicConnectionPeer::SetSendAlgorithm(session_
.connection(), send_algorithm
);
432 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
433 TestStream
* stream4
= session_
.CreateOutgoingDataStream();
434 TestStream
* stream6
= session_
.CreateOutgoingDataStream();
436 session_
.MarkWriteBlocked(stream2
->id(), kSomeMiddlePriority
);
437 session_
.MarkWriteBlocked(stream6
->id(), kSomeMiddlePriority
);
438 session_
.MarkWriteBlocked(stream4
->id(), kSomeMiddlePriority
);
440 StreamBlocker
stream2_blocker(&session_
, stream2
->id());
441 EXPECT_CALL(*send_algorithm
, TimeUntilSend(_
, _
, _
)).WillOnce(Return(
442 QuicTime::Delta::Zero()));
443 EXPECT_CALL(*stream2
, OnCanWrite());
444 EXPECT_CALL(*send_algorithm
, TimeUntilSend(_
, _
, _
)).WillOnce(Return(
445 QuicTime::Delta::Zero()));
446 EXPECT_CALL(*stream6
, OnCanWrite());
447 EXPECT_CALL(*send_algorithm
, TimeUntilSend(_
, _
, _
)).WillOnce(Return(
448 QuicTime::Delta::Infinite()));
449 // stream4->OnCanWrite is not called.
451 session_
.OnCanWrite();
452 EXPECT_TRUE(session_
.WillingAndAbleToWrite());
454 // Still congestion-control blocked.
455 EXPECT_CALL(*send_algorithm
, TimeUntilSend(_
, _
, _
)).WillOnce(Return(
456 QuicTime::Delta::Infinite()));
457 session_
.OnCanWrite();
458 EXPECT_TRUE(session_
.WillingAndAbleToWrite());
460 // stream4->OnCanWrite is called once the connection stops being
461 // congestion-control blocked.
462 EXPECT_CALL(*send_algorithm
, TimeUntilSend(_
, _
, _
)).WillOnce(Return(
463 QuicTime::Delta::Zero()));
464 EXPECT_CALL(*stream4
, OnCanWrite());
465 session_
.OnCanWrite();
466 EXPECT_FALSE(session_
.WillingAndAbleToWrite());
469 TEST_P(QuicSessionTest
, BufferedHandshake
) {
470 EXPECT_FALSE(session_
.HasPendingHandshake()); // Default value.
472 // Test that blocking other streams does not change our status.
473 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
474 StreamBlocker
stream2_blocker(&session_
, stream2
->id());
475 stream2_blocker
.MarkWriteBlocked();
476 EXPECT_FALSE(session_
.HasPendingHandshake());
478 TestStream
* stream3
= session_
.CreateOutgoingDataStream();
479 StreamBlocker
stream3_blocker(&session_
, stream3
->id());
480 stream3_blocker
.MarkWriteBlocked();
481 EXPECT_FALSE(session_
.HasPendingHandshake());
483 // Blocking (due to buffering of) the Crypto stream is detected.
484 session_
.MarkWriteBlocked(kCryptoStreamId
, kHighestPriority
);
485 EXPECT_TRUE(session_
.HasPendingHandshake());
487 TestStream
* stream4
= session_
.CreateOutgoingDataStream();
488 StreamBlocker
stream4_blocker(&session_
, stream4
->id());
489 stream4_blocker
.MarkWriteBlocked();
490 EXPECT_TRUE(session_
.HasPendingHandshake());
493 // Force most streams to re-register, which is common scenario when we block
494 // the Crypto stream, and only the crypto stream can "really" write.
496 // Due to prioritization, we *should* be asked to write the crypto stream
498 // Don't re-register the crypto stream (which signals complete writing).
499 TestCryptoStream
* crypto_stream
= session_
.GetCryptoStream();
500 EXPECT_CALL(*crypto_stream
, OnCanWrite());
502 // Re-register all other streams, to show they weren't able to proceed.
503 EXPECT_CALL(*stream2
, OnCanWrite())
504 .WillOnce(Invoke(&stream2_blocker
, &StreamBlocker::MarkWriteBlocked
));
505 EXPECT_CALL(*stream3
, OnCanWrite())
506 .WillOnce(Invoke(&stream3_blocker
, &StreamBlocker::MarkWriteBlocked
));
507 EXPECT_CALL(*stream4
, OnCanWrite())
508 .WillOnce(Invoke(&stream4_blocker
, &StreamBlocker::MarkWriteBlocked
));
510 session_
.OnCanWrite();
511 EXPECT_TRUE(session_
.WillingAndAbleToWrite());
512 EXPECT_FALSE(session_
.HasPendingHandshake()); // Crypto stream wrote.
515 TEST_P(QuicSessionTest
, OnCanWriteWithClosedStream
) {
516 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
517 TestStream
* stream4
= session_
.CreateOutgoingDataStream();
518 TestStream
* stream6
= session_
.CreateOutgoingDataStream();
520 session_
.MarkWriteBlocked(stream2
->id(), kSomeMiddlePriority
);
521 session_
.MarkWriteBlocked(stream6
->id(), kSomeMiddlePriority
);
522 session_
.MarkWriteBlocked(stream4
->id(), kSomeMiddlePriority
);
523 CloseStream(stream6
->id());
526 EXPECT_CALL(*stream2
, OnCanWrite());
527 EXPECT_CALL(*stream4
, OnCanWrite());
528 session_
.OnCanWrite();
529 EXPECT_FALSE(session_
.WillingAndAbleToWrite());
532 TEST_P(QuicSessionTest
, OnCanWriteLimitsNumWritesIfFlowControlBlocked
) {
533 // Ensure connection level flow control blockage.
534 QuicFlowControllerPeer::SetSendWindowOffset(session_
.flow_controller(), 0);
535 EXPECT_TRUE(session_
.flow_controller()->IsBlocked());
536 EXPECT_TRUE(session_
.IsConnectionFlowControlBlocked());
537 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
539 // Mark the crypto and headers streams as write blocked, we expect them to be
540 // allowed to write later.
541 session_
.MarkWriteBlocked(kCryptoStreamId
, kHighestPriority
);
542 session_
.MarkWriteBlocked(kHeadersStreamId
, kHighestPriority
);
544 // Create a data stream, and although it is write blocked we never expect it
545 // to be allowed to write as we are connection level flow control blocked.
546 TestStream
* stream
= session_
.CreateOutgoingDataStream();
547 session_
.MarkWriteBlocked(stream
->id(), kSomeMiddlePriority
);
548 EXPECT_CALL(*stream
, OnCanWrite()).Times(0);
550 // The crypto and headers streams should be called even though we are
551 // connection flow control blocked.
552 TestCryptoStream
* crypto_stream
= session_
.GetCryptoStream();
553 EXPECT_CALL(*crypto_stream
, OnCanWrite()).Times(1);
554 TestHeadersStream
* headers_stream
= new TestHeadersStream(&session_
);
555 QuicSessionPeer::SetHeadersStream(&session_
, headers_stream
);
556 EXPECT_CALL(*headers_stream
, OnCanWrite()).Times(1);
558 session_
.OnCanWrite();
559 EXPECT_FALSE(session_
.WillingAndAbleToWrite());
562 TEST_P(QuicSessionTest
, SendGoAway
) {
563 EXPECT_CALL(*connection_
,
564 SendGoAway(QUIC_PEER_GOING_AWAY
, 0u, "Going Away."));
565 session_
.SendGoAway(QUIC_PEER_GOING_AWAY
, "Going Away.");
566 EXPECT_TRUE(session_
.goaway_sent());
568 EXPECT_CALL(*connection_
,
569 SendRstStream(3u, QUIC_STREAM_PEER_GOING_AWAY
, 0)).Times(0);
570 EXPECT_TRUE(session_
.GetIncomingDataStream(3u));
573 TEST_P(QuicSessionTest
, DoNotSendGoAwayTwice
) {
574 EXPECT_CALL(*connection_
,
575 SendGoAway(QUIC_PEER_GOING_AWAY
, 0u, "Going Away.")).Times(1);
576 session_
.SendGoAway(QUIC_PEER_GOING_AWAY
, "Going Away.");
577 EXPECT_TRUE(session_
.goaway_sent());
578 session_
.SendGoAway(QUIC_PEER_GOING_AWAY
, "Going Away.");
581 TEST_P(QuicSessionTest
, IncreasedTimeoutAfterCryptoHandshake
) {
582 EXPECT_EQ((FLAGS_quic_unified_timeouts
?
583 kInitialIdleTimeoutSecs
: kDefaultIdleTimeoutSecs
) + 3,
584 QuicConnectionPeer::GetNetworkTimeout(connection_
).ToSeconds());
585 CryptoHandshakeMessage msg
;
586 session_
.GetCryptoStream()->OnHandshakeMessage(msg
);
587 EXPECT_EQ(kMaximumIdleTimeoutSecs
+ 3,
588 QuicConnectionPeer::GetNetworkTimeout(connection_
).ToSeconds());
591 TEST_P(QuicSessionTest
, RstStreamBeforeHeadersDecompressed
) {
592 // Send two bytes of payload.
593 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, MakeIOVector("HT"));
594 vector
<QuicStreamFrame
> frames
;
595 frames
.push_back(data1
);
596 session_
.OnStreamFrames(frames
);
597 EXPECT_EQ(1u, session_
.GetNumOpenStreams());
599 QuicRstStreamFrame
rst1(kClientDataStreamId1
, QUIC_STREAM_NO_ERROR
, 0);
600 session_
.OnRstStream(rst1
);
601 EXPECT_EQ(0u, session_
.GetNumOpenStreams());
602 // Connection should remain alive.
603 EXPECT_TRUE(connection_
->connected());
606 TEST_P(QuicSessionTest
, MultipleRstStreamsCauseSingleConnectionClose
) {
607 // If multiple invalid reset stream frames arrive in a single packet, this
608 // should trigger a connection close. However there is no need to send
609 // multiple connection close frames.
611 // Create valid stream.
612 QuicStreamFrame
data1(kClientDataStreamId1
, false, 0, MakeIOVector("HT"));
613 vector
<QuicStreamFrame
> frames
;
614 frames
.push_back(data1
);
615 session_
.OnStreamFrames(frames
);
616 EXPECT_EQ(1u, session_
.GetNumOpenStreams());
618 // Process first invalid stream reset, resulting in the connection being
620 EXPECT_CALL(*connection_
, SendConnectionClose(QUIC_INVALID_STREAM_ID
))
622 QuicStreamId kLargeInvalidStreamId
= 99999999;
623 QuicRstStreamFrame
rst1(kLargeInvalidStreamId
, QUIC_STREAM_NO_ERROR
, 0);
624 session_
.OnRstStream(rst1
);
625 QuicConnectionPeer::CloseConnection(connection_
);
627 // Processing of second invalid stream reset should not result in the
628 // connection being closed for a second time.
629 QuicRstStreamFrame
rst2(kLargeInvalidStreamId
, QUIC_STREAM_NO_ERROR
, 0);
630 session_
.OnRstStream(rst2
);
633 TEST_P(QuicSessionTest
, HandshakeUnblocksFlowControlBlockedStream
) {
634 // Test that if a stream is flow control blocked, then on receipt of the SHLO
635 // containing a suitable send window offset, the stream becomes unblocked.
637 // Ensure that Writev consumes all the data it is given (simulate no socket
639 session_
.set_writev_consumes_all_data(true);
641 // Create a stream, and send enough data to make it flow control blocked.
642 TestStream
* stream2
= session_
.CreateOutgoingDataStream();
643 string
body(kDefaultFlowControlSendWindow
, '.');
644 EXPECT_FALSE(stream2
->flow_controller()->IsBlocked());
645 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
646 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
647 stream2
->SendBody(body
, false);
648 EXPECT_TRUE(stream2
->flow_controller()->IsBlocked());
649 EXPECT_TRUE(session_
.IsConnectionFlowControlBlocked());
650 EXPECT_TRUE(session_
.IsStreamFlowControlBlocked());
652 // The handshake message will call OnCanWrite, so the stream can resume
654 EXPECT_CALL(*stream2
, OnCanWrite());
655 // Now complete the crypto handshake, resulting in an increased flow control
657 CryptoHandshakeMessage msg
;
658 session_
.GetCryptoStream()->OnHandshakeMessage(msg
);
660 // Stream is now unblocked.
661 EXPECT_FALSE(stream2
->flow_controller()->IsBlocked());
662 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
663 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
666 TEST_P(QuicSessionTest
, HandshakeUnblocksFlowControlBlockedCryptoStream
) {
667 if (version() <= QUIC_VERSION_19
) {
670 // Test that if the crypto stream is flow control blocked, then if the SHLO
671 // contains a larger send window offset, the stream becomes unblocked.
672 session_
.set_writev_consumes_all_data(true);
673 TestCryptoStream
* crypto_stream
= session_
.GetCryptoStream();
674 EXPECT_FALSE(crypto_stream
->flow_controller()->IsBlocked());
675 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
676 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
677 QuicHeadersStream
* headers_stream
=
678 QuicSessionPeer::GetHeadersStream(&session_
);
679 EXPECT_FALSE(headers_stream
->flow_controller()->IsBlocked());
680 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
681 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
682 // Write until the crypto stream is flow control blocked.
684 while (!crypto_stream
->flow_controller()->IsBlocked() && i
< 1000) {
685 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
686 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
688 CryptoHandshakeMessage crypto_message
;
689 config
.ToHandshakeMessage(&crypto_message
);
690 crypto_stream
->SendHandshakeMessage(crypto_message
);
693 EXPECT_TRUE(crypto_stream
->flow_controller()->IsBlocked());
694 EXPECT_FALSE(headers_stream
->flow_controller()->IsBlocked());
695 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
696 EXPECT_TRUE(session_
.IsStreamFlowControlBlocked());
697 EXPECT_FALSE(session_
.HasDataToWrite());
698 EXPECT_TRUE(crypto_stream
->HasBufferedData());
700 // The handshake message will call OnCanWrite, so the stream can
702 EXPECT_CALL(*crypto_stream
, OnCanWrite());
703 // Now complete the crypto handshake, resulting in an increased flow control
705 CryptoHandshakeMessage msg
;
706 session_
.GetCryptoStream()->OnHandshakeMessage(msg
);
708 // Stream is now unblocked and will no longer have buffered data.
709 EXPECT_FALSE(crypto_stream
->flow_controller()->IsBlocked());
710 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
711 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
714 TEST_P(QuicSessionTest
, HandshakeUnblocksFlowControlBlockedHeadersStream
) {
715 if (version() <= QUIC_VERSION_19
) {
718 // Test that if the header stream is flow control blocked, then if the SHLO
719 // contains a larger send window offset, the stream becomes unblocked.
720 session_
.set_writev_consumes_all_data(true);
721 TestCryptoStream
* crypto_stream
= session_
.GetCryptoStream();
722 EXPECT_FALSE(crypto_stream
->flow_controller()->IsBlocked());
723 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
724 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
725 QuicHeadersStream
* headers_stream
=
726 QuicSessionPeer::GetHeadersStream(&session_
);
727 EXPECT_FALSE(headers_stream
->flow_controller()->IsBlocked());
728 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
729 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
730 QuicStreamId stream_id
= 5;
731 // Write until the header stream is flow control blocked.
732 SpdyHeaderBlock headers
;
733 while (!headers_stream
->flow_controller()->IsBlocked() && stream_id
< 2000) {
734 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
735 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
736 headers
["header"] = base::Uint64ToString(base::RandUint64()) +
737 base::Uint64ToString(base::RandUint64()) +
738 base::Uint64ToString(base::RandUint64());
739 headers_stream
->WriteHeaders(stream_id
, headers
, true, nullptr);
742 // Write one more to ensure that the headers stream has buffered data. The
743 // random headers may have exactly filled the flow control window.
744 headers_stream
->WriteHeaders(stream_id
, headers
, true, nullptr);
745 EXPECT_TRUE(headers_stream
->HasBufferedData());
747 EXPECT_TRUE(headers_stream
->flow_controller()->IsBlocked());
748 EXPECT_FALSE(crypto_stream
->flow_controller()->IsBlocked());
749 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
750 EXPECT_TRUE(session_
.IsStreamFlowControlBlocked());
751 EXPECT_FALSE(session_
.HasDataToWrite());
753 // Now complete the crypto handshake, resulting in an increased flow control
755 CryptoHandshakeMessage msg
;
756 session_
.GetCryptoStream()->OnHandshakeMessage(msg
);
758 // Stream is now unblocked and will no longer have buffered data.
759 EXPECT_FALSE(headers_stream
->flow_controller()->IsBlocked());
760 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
761 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
762 EXPECT_FALSE(headers_stream
->HasBufferedData());
765 TEST_P(QuicSessionTest
, InvalidFlowControlWindowInHandshake
) {
766 // TODO(rjshade): Remove this test when removing QUIC_VERSION_19.
767 // Test that receipt of an invalid (< default) flow control window from
768 // the peer results in the connection being torn down.
769 if (version() > QUIC_VERSION_19
) {
773 uint32 kInvalidWindow
= kDefaultFlowControlSendWindow
- 1;
774 QuicConfigPeer::SetReceivedInitialFlowControlWindow(session_
.config(),
777 EXPECT_CALL(*connection_
,
778 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW
)).Times(2);
779 session_
.OnConfigNegotiated();
782 TEST_P(QuicSessionTest
, ConnectionFlowControlAccountingRstOutOfOrder
) {
783 // Test that when we receive an out of order stream RST we correctly adjust
784 // our connection level flow control receive window.
785 // On close, the stream should mark as consumed all bytes between the highest
786 // byte consumed so far and the final byte offset from the RST frame.
787 TestStream
* stream
= session_
.CreateOutgoingDataStream();
789 const QuicStreamOffset kByteOffset
=
790 1 + kInitialSessionFlowControlWindowForTest
/ 2;
792 // Expect no stream WINDOW_UPDATE frames, as stream read side closed.
793 EXPECT_CALL(*connection_
, SendWindowUpdate(stream
->id(), _
)).Times(0);
794 // We do expect a connection level WINDOW_UPDATE when the stream is reset.
795 EXPECT_CALL(*connection_
,
796 SendWindowUpdate(0, kInitialSessionFlowControlWindowForTest
+
797 kByteOffset
)).Times(1);
799 QuicRstStreamFrame
rst_frame(stream
->id(), QUIC_STREAM_CANCELLED
,
801 session_
.OnRstStream(rst_frame
);
802 session_
.PostProcessAfterData();
803 EXPECT_EQ(kByteOffset
, session_
.flow_controller()->bytes_consumed());
806 TEST_P(QuicSessionTest
, ConnectionFlowControlAccountingFinAndLocalReset
) {
807 // Test the situation where we receive a FIN on a stream, and before we fully
808 // consume all the data from the sequencer buffer we locally RST the stream.
809 // The bytes between highest consumed byte, and the final byte offset that we
810 // determined when the FIN arrived, should be marked as consumed at the
811 // connection level flow controller when the stream is reset.
812 TestStream
* stream
= session_
.CreateOutgoingDataStream();
814 const QuicStreamOffset kByteOffset
=
815 1 + kInitialSessionFlowControlWindowForTest
/ 2;
816 QuicStreamFrame
frame(stream
->id(), true, kByteOffset
, IOVector());
817 vector
<QuicStreamFrame
> frames
;
818 frames
.push_back(frame
);
819 session_
.OnStreamFrames(frames
);
820 session_
.PostProcessAfterData();
822 EXPECT_EQ(0u, stream
->flow_controller()->bytes_consumed());
823 EXPECT_EQ(kByteOffset
,
824 stream
->flow_controller()->highest_received_byte_offset());
826 // We only expect to see a connection WINDOW_UPDATE when talking
827 // QUIC_VERSION_19, as in this case both stream and session flow control
828 // windows are the same size. In later versions we will not see a connection
829 // level WINDOW_UPDATE when exhausting a stream, as the stream flow control
830 // limit is much lower than the connection flow control limit.
831 if (version() == QUIC_VERSION_19
) {
832 // Expect no stream WINDOW_UPDATE frames, as stream read side closed.
833 EXPECT_CALL(*connection_
, SendWindowUpdate(stream
->id(), _
)).Times(0);
834 // We do expect a connection level WINDOW_UPDATE when the stream is reset.
835 EXPECT_CALL(*connection_
,
836 SendWindowUpdate(0, kInitialSessionFlowControlWindowForTest
+
837 kByteOffset
)).Times(1);
840 // Reset stream locally.
841 stream
->Reset(QUIC_STREAM_CANCELLED
);
842 EXPECT_EQ(kByteOffset
, session_
.flow_controller()->bytes_consumed());
845 TEST_P(QuicSessionTest
, ConnectionFlowControlAccountingFinAfterRst
) {
846 // Test that when we RST the stream (and tear down stream state), and then
847 // receive a FIN from the peer, we correctly adjust our connection level flow
848 // control receive window.
850 // Connection starts with some non-zero highest received byte offset,
851 // due to other active streams.
852 const uint64 kInitialConnectionBytesConsumed
= 567;
853 const uint64 kInitialConnectionHighestReceivedOffset
= 1234;
854 EXPECT_LT(kInitialConnectionBytesConsumed
,
855 kInitialConnectionHighestReceivedOffset
);
856 session_
.flow_controller()->UpdateHighestReceivedOffset(
857 kInitialConnectionHighestReceivedOffset
);
858 session_
.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed
);
860 // Reset our stream: this results in the stream being closed locally.
861 TestStream
* stream
= session_
.CreateOutgoingDataStream();
862 stream
->Reset(QUIC_STREAM_CANCELLED
);
864 // Now receive a response from the peer with a FIN. We should handle this by
865 // adjusting the connection level flow control receive window to take into
866 // account the total number of bytes sent by the peer.
867 const QuicStreamOffset kByteOffset
= 5678;
868 string body
= "hello";
869 IOVector data
= MakeIOVector(body
);
870 QuicStreamFrame
frame(stream
->id(), true, kByteOffset
, data
);
871 vector
<QuicStreamFrame
> frames
;
872 frames
.push_back(frame
);
873 session_
.OnStreamFrames(frames
);
875 QuicStreamOffset total_stream_bytes_sent_by_peer
=
876 kByteOffset
+ body
.length();
877 EXPECT_EQ(kInitialConnectionBytesConsumed
+ total_stream_bytes_sent_by_peer
,
878 session_
.flow_controller()->bytes_consumed());
880 kInitialConnectionHighestReceivedOffset
+ total_stream_bytes_sent_by_peer
,
881 session_
.flow_controller()->highest_received_byte_offset());
884 TEST_P(QuicSessionTest
, ConnectionFlowControlAccountingRstAfterRst
) {
885 // Test that when we RST the stream (and tear down stream state), and then
886 // receive a RST from the peer, we correctly adjust our connection level flow
887 // control receive window.
889 // Connection starts with some non-zero highest received byte offset,
890 // due to other active streams.
891 const uint64 kInitialConnectionBytesConsumed
= 567;
892 const uint64 kInitialConnectionHighestReceivedOffset
= 1234;
893 EXPECT_LT(kInitialConnectionBytesConsumed
,
894 kInitialConnectionHighestReceivedOffset
);
895 session_
.flow_controller()->UpdateHighestReceivedOffset(
896 kInitialConnectionHighestReceivedOffset
);
897 session_
.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed
);
899 // Reset our stream: this results in the stream being closed locally.
900 TestStream
* stream
= session_
.CreateOutgoingDataStream();
901 stream
->Reset(QUIC_STREAM_CANCELLED
);
903 // Now receive a RST from the peer. We should handle this by adjusting the
904 // connection level flow control receive window to take into account the total
905 // number of bytes sent by the peer.
906 const QuicStreamOffset kByteOffset
= 5678;
907 QuicRstStreamFrame
rst_frame(stream
->id(), QUIC_STREAM_CANCELLED
,
909 session_
.OnRstStream(rst_frame
);
911 EXPECT_EQ(kInitialConnectionBytesConsumed
+ kByteOffset
,
912 session_
.flow_controller()->bytes_consumed());
913 EXPECT_EQ(kInitialConnectionHighestReceivedOffset
+ kByteOffset
,
914 session_
.flow_controller()->highest_received_byte_offset());
917 TEST_P(QuicSessionTest
, InvalidStreamFlowControlWindowInHandshake
) {
918 // Test that receipt of an invalid (< default) stream flow control window from
919 // the peer results in the connection being torn down.
920 if (version() <= QUIC_VERSION_19
) {
924 uint32 kInvalidWindow
= kDefaultFlowControlSendWindow
- 1;
925 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_
.config(),
928 EXPECT_CALL(*connection_
,
929 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW
));
930 session_
.OnConfigNegotiated();
933 TEST_P(QuicSessionTest
, InvalidSessionFlowControlWindowInHandshake
) {
934 // Test that receipt of an invalid (< default) session flow control window
935 // from the peer results in the connection being torn down.
936 if (version() == QUIC_VERSION_19
) {
940 uint32 kInvalidWindow
= kDefaultFlowControlSendWindow
- 1;
941 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_
.config(),
944 EXPECT_CALL(*connection_
,
945 SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW
));
946 session_
.OnConfigNegotiated();
949 TEST_P(QuicSessionTest
, FlowControlWithInvalidFinalOffset
) {
950 // Test that if we receive a stream RST with a highest byte offset that
951 // violates flow control, that we close the connection.
952 const uint64 kLargeOffset
= kInitialSessionFlowControlWindowForTest
+ 1;
953 EXPECT_CALL(*connection_
,
954 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA
))
957 // Check that stream frame + FIN results in connection close.
958 TestStream
* stream
= session_
.CreateOutgoingDataStream();
959 stream
->Reset(QUIC_STREAM_CANCELLED
);
960 QuicStreamFrame
frame(stream
->id(), true, kLargeOffset
, IOVector());
961 vector
<QuicStreamFrame
> frames
;
962 frames
.push_back(frame
);
963 session_
.OnStreamFrames(frames
);
965 // Check that RST results in connection close.
966 QuicRstStreamFrame
rst_frame(stream
->id(), QUIC_STREAM_CANCELLED
,
968 session_
.OnRstStream(rst_frame
);
971 TEST_P(QuicSessionTest
, WindowUpdateUnblocksHeadersStream
) {
972 // Test that a flow control blocked headers stream gets unblocked on recipt of
973 // a WINDOW_UPDATE frame. Regression test for b/17413860.
974 if (version() < QUIC_VERSION_21
) {
978 // Set the headers stream to be flow control blocked.
979 QuicHeadersStream
* headers_stream
=
980 QuicSessionPeer::GetHeadersStream(&session_
);
981 QuicFlowControllerPeer::SetSendWindowOffset(headers_stream
->flow_controller(),
983 EXPECT_TRUE(headers_stream
->flow_controller()->IsBlocked());
984 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
985 EXPECT_TRUE(session_
.IsStreamFlowControlBlocked());
987 // Unblock the headers stream by supplying a WINDOW_UPDATE.
988 QuicWindowUpdateFrame
window_update_frame(headers_stream
->id(),
989 2 * kDefaultFlowControlSendWindow
);
990 vector
<QuicWindowUpdateFrame
> frames
;
991 frames
.push_back(window_update_frame
);
992 session_
.OnWindowUpdateFrames(frames
);
993 EXPECT_FALSE(headers_stream
->flow_controller()->IsBlocked());
994 EXPECT_FALSE(session_
.IsConnectionFlowControlBlocked());
995 EXPECT_FALSE(session_
.IsStreamFlowControlBlocked());
998 TEST_P(QuicSessionTest
, TooManyUnfinishedStreamsCauseConnectionClose
) {
999 // If a buggy/malicious peer creates too many streams that are not ended with
1000 // a FIN or RST then we send a connection close.
1001 ValueRestore
<bool> old_flag(&FLAGS_close_quic_connection_unfinished_streams_2
,
1004 EXPECT_CALL(*connection_
,
1005 SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS
)).Times(1);
1007 const int kMaxStreams
= 5;
1008 QuicSessionPeer::SetMaxOpenStreams(&session_
, kMaxStreams
);
1010 // Create kMaxStreams + 1 data streams, and close them all without receiving a
1011 // FIN or a RST from the client.
1012 const int kFirstStreamId
= kClientDataStreamId1
;
1013 const int kFinalStreamId
= kClientDataStreamId1
+ 2 * kMaxStreams
+ 1;
1014 for (int i
= kFirstStreamId
; i
< kFinalStreamId
; i
+= 2) {
1015 QuicStreamFrame
data1(i
, false, 0, MakeIOVector("HT"));
1016 vector
<QuicStreamFrame
> frames
;
1017 frames
.push_back(data1
);
1018 session_
.OnStreamFrames(frames
);
1019 EXPECT_EQ(1u, session_
.GetNumOpenStreams());
1020 session_
.CloseStream(i
);
1023 // Called after any new data is received by the session, and triggers the call
1024 // to close the connection.
1025 session_
.PostProcessAfterData();