blob: deb6643425266283327905a3d0f0cc4cf9b645a0 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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/third_party/quiche/src/quic/core/quic_session.h"
6
7#include <cstdint>
8#include <set>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include <utility>
11
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
13#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
14#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
15#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
16#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
17#include "net/third_party/quiche/src/quic/core/quic_packets.h"
18#include "net/third_party/quiche/src/quic/core/quic_stream.h"
19#include "net/third_party/quiche/src/quic/core/quic_utils.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
24#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
26#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050027#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
28#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
29#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
30#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
31#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
35#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
36#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
37#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
38
39using spdy::kV3HighestPriority;
40using spdy::SpdyPriority;
41using testing::_;
42using testing::AtLeast;
43using testing::InSequence;
44using testing::Invoke;
45using testing::NiceMock;
46using testing::Return;
47using testing::StrictMock;
48using testing::WithArg;
49
50namespace quic {
51namespace test {
52namespace {
53
54class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
55 public:
56 explicit TestCryptoStream(QuicSession* session)
57 : QuicCryptoStream(session),
58 QuicCryptoHandshaker(this, session),
59 encryption_established_(false),
60 handshake_confirmed_(false),
61 params_(new QuicCryptoNegotiatedParameters) {}
62
63 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
64 encryption_established_ = true;
65 handshake_confirmed_ = true;
66 CryptoHandshakeMessage msg;
vasilvvc48c8712019-03-11 13:38:16 -070067 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 session()->config()->SetInitialStreamFlowControlWindowToSend(
69 kInitialStreamFlowControlWindowForTest);
70 session()->config()->SetInitialSessionFlowControlWindowToSend(
71 kInitialSessionFlowControlWindowForTest);
fkastenholzd3a1de92019-05-15 07:00:07 -070072 session()->config()->ToHandshakeMessage(
73 &msg, session()->connection()->transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -050074 const QuicErrorCode error =
75 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
76 EXPECT_EQ(QUIC_NO_ERROR, error);
77 session()->OnConfigNegotiated();
78 session()->connection()->SetDefaultEncryptionLevel(
79 ENCRYPTION_FORWARD_SECURE);
80 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
81 }
82
83 // QuicCryptoStream implementation
84 bool encryption_established() const override {
85 return encryption_established_;
86 }
87 bool handshake_confirmed() const override { return handshake_confirmed_; }
88 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
89 const override {
90 return *params_;
91 }
92 CryptoMessageParser* crypto_message_parser() override {
93 return QuicCryptoHandshaker::crypto_message_parser();
94 }
95
96 MOCK_METHOD0(OnCanWrite, void());
nharper46833c32019-05-15 21:33:05 -070097 bool HasPendingCryptoRetransmission() const override { return false; }
QUICHE teama6ef0a62019-03-07 20:34:33 -050098
99 MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
100
101 private:
102 using QuicCryptoStream::session;
103
104 bool encryption_established_;
105 bool handshake_confirmed_;
106 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
107};
108
109class TestStream : public QuicStream {
110 public:
111 TestStream(QuicStreamId id, QuicSession* session, StreamType type)
nharper46833c32019-05-15 21:33:05 -0700112 : TestStream(id, session, /*is_static=*/false, type) {}
113
114 TestStream(QuicStreamId id,
115 QuicSession* session,
116 bool is_static,
117 StreamType type)
118 : QuicStream(id, session, is_static, type) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119
120 TestStream(PendingStream pending, StreamType type)
renjietang35448992019-05-08 17:08:57 -0700121 : QuicStream(std::move(pending), type, /*is_static=*/false) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122
123 using QuicStream::CloseReadSide;
124 using QuicStream::CloseWriteSide;
125 using QuicStream::WriteMemSlices;
126 using QuicStream::WritevData;
127
128 void OnDataAvailable() override {}
129
130 MOCK_METHOD0(OnCanWrite, void());
131 MOCK_METHOD3(RetransmitStreamData,
132 bool(QuicStreamOffset, QuicByteCount, bool));
133
134 MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
135 MOCK_METHOD1(OnStopSending, void(uint16_t code));
136};
137
138class TestSession : public QuicSession {
139 public:
140 explicit TestSession(QuicConnection* connection,
141 MockQuicSessionVisitor* session_visitor)
142 : QuicSession(connection,
143 session_visitor,
144 DefaultQuicConfig(),
145 CurrentSupportedVersions()),
146 crypto_stream_(this),
147 writev_consumes_all_data_(false),
renjietange76b2da2019-05-13 14:50:23 -0700148 uses_pending_streams_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149 num_incoming_streams_created_(0) {
150 Initialize();
151 this->connection()->SetEncrypter(
152 ENCRYPTION_FORWARD_SECURE,
153 QuicMakeUnique<NullEncrypter>(connection->perspective()));
154 }
155
156 ~TestSession() override { delete connection(); }
157
158 TestCryptoStream* GetMutableCryptoStream() override {
159 return &crypto_stream_;
160 }
161
162 const TestCryptoStream* GetCryptoStream() const override {
163 return &crypto_stream_;
164 }
165
166 TestStream* CreateOutgoingBidirectionalStream() {
167 QuicStreamId id = GetNextOutgoingBidirectionalStreamId();
168 if (id ==
169 QuicUtils::GetInvalidStreamId(connection()->transport_version())) {
170 return nullptr;
171 }
172 TestStream* stream = new TestStream(id, this, BIDIRECTIONAL);
173 ActivateStream(QuicWrapUnique(stream));
174 return stream;
175 }
176
177 TestStream* CreateOutgoingUnidirectionalStream() {
178 TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
179 this, WRITE_UNIDIRECTIONAL);
180 ActivateStream(QuicWrapUnique(stream));
181 return stream;
182 }
183
184 TestStream* CreateIncomingStream(QuicStreamId id) override {
185 // Enforce the limit on the number of open streams.
186 if (GetNumOpenIncomingStreams() + 1 >
187 max_open_incoming_bidirectional_streams() &&
188 connection()->transport_version() != QUIC_VERSION_99) {
189 // No need to do this test for version 99; it's done by
190 // QuicSession::GetOrCreateDynamicStream.
191 connection()->CloseConnection(
192 QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
193 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
194 return nullptr;
195 }
196
197 TestStream* stream =
198 new TestStream(id, this,
199 DetermineStreamType(
200 id, connection()->transport_version(), perspective(),
201 /*is_incoming=*/true, BIDIRECTIONAL));
202 ActivateStream(QuicWrapUnique(stream));
203 ++num_incoming_streams_created_;
204 return stream;
205 }
206
207 TestStream* CreateIncomingStream(PendingStream pending) override {
208 QuicStreamId id = pending.id();
209 TestStream* stream =
210 new TestStream(std::move(pending),
211 DetermineStreamType(
212 id, connection()->transport_version(), perspective(),
213 /*is_incoming=*/true, BIDIRECTIONAL));
214 ActivateStream(QuicWrapUnique(stream));
215 ++num_incoming_streams_created_;
216 return stream;
217 }
218
renjietange76b2da2019-05-13 14:50:23 -0700219 // QuicSession doesn't do anything in this method. So it's overridden here to
220 // test that the session handles pending streams correctly in terms of
221 // receiving stream frames.
222 void ProcessPendingStream(PendingStream* pending) override {
223 struct iovec iov;
224 if (pending->sequencer()->GetReadableRegion(&iov)) {
225 // Create TestStream once the first byte is received.
226 CreateIncomingStream(std::move(*pending));
227 }
228 }
229
QUICHE teama6ef0a62019-03-07 20:34:33 -0500230 bool IsClosedStream(QuicStreamId id) {
231 return QuicSession::IsClosedStream(id);
232 }
233
234 QuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id) {
235 return QuicSession::GetOrCreateDynamicStream(stream_id);
236 }
237
238 bool ShouldKeepConnectionAlive() const override {
239 return GetNumOpenDynamicStreams() > 0;
240 }
241
242 QuicConsumedData WritevData(QuicStream* stream,
243 QuicStreamId id,
244 size_t write_length,
245 QuicStreamOffset offset,
246 StreamSendingState state) override {
247 bool fin = state != NO_FIN;
248 QuicConsumedData consumed(write_length, fin);
249 if (!writev_consumes_all_data_) {
250 consumed =
251 QuicSession::WritevData(stream, id, write_length, offset, state);
252 }
253 if (fin && consumed.fin_consumed) {
254 stream->set_fin_sent(true);
255 }
256 QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
257 id, consumed.bytes_consumed);
258 return consumed;
259 }
260
261 MOCK_METHOD0(OnCanCreateNewOutgoingStream, void());
262
263 void set_writev_consumes_all_data(bool val) {
264 writev_consumes_all_data_ = val;
265 }
266
267 QuicConsumedData SendStreamData(QuicStream* stream) {
268 struct iovec iov;
nharper46833c32019-05-15 21:33:05 -0700269 if (!QuicUtils::IsCryptoStreamId(connection()->transport_version(),
270 stream->id()) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500271 this->connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
272 this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
273 }
274 MakeIOVector("not empty", &iov);
275 QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
276 QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
277 QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
278 consumed.bytes_consumed);
279 return consumed;
280 }
281
282 bool ClearControlFrame(const QuicFrame& frame) {
283 DeleteFrame(&const_cast<QuicFrame&>(frame));
284 return true;
285 }
286
287 bool SaveFrame(const QuicFrame& frame) {
288 save_frame_ = frame;
289 DeleteFrame(&const_cast<QuicFrame&>(frame));
290 return true;
291 }
292
293 const QuicFrame& save_frame() { return save_frame_; }
294
295 QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
296 DCHECK(writev_consumes_all_data_);
297 return WritevData(stream, stream->id(), bytes, 0, FIN);
298 }
299
renjietange76b2da2019-05-13 14:50:23 -0700300 bool UsesPendingStreams() const override { return uses_pending_streams_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500301
renjietange76b2da2019-05-13 14:50:23 -0700302 void set_uses_pending_streams(bool uses_pending_streams) {
303 uses_pending_streams_ = uses_pending_streams;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 }
305
306 int num_incoming_streams_created() const {
307 return num_incoming_streams_created_;
308 }
309
310 using QuicSession::ActivateStream;
311 using QuicSession::closed_streams;
312 using QuicSession::zombie_streams;
313
314 private:
315 StrictMock<TestCryptoStream> crypto_stream_;
316
317 bool writev_consumes_all_data_;
renjietange76b2da2019-05-13 14:50:23 -0700318 bool uses_pending_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500319 QuicFrame save_frame_;
320 int num_incoming_streams_created_;
321};
322
323class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
324 protected:
325 explicit QuicSessionTestBase(Perspective perspective)
326 : connection_(
327 new StrictMock<MockQuicConnection>(&helper_,
328 &alarm_factory_,
329 perspective,
330 SupportedVersions(GetParam()))),
331 session_(connection_, &session_visitor_) {
332 session_.config()->SetInitialStreamFlowControlWindowToSend(
333 kInitialStreamFlowControlWindowForTest);
334 session_.config()->SetInitialSessionFlowControlWindowToSend(
335 kInitialSessionFlowControlWindowForTest);
336 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
337 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
338 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
339 .Times(testing::AnyNumber());
340 }
341
342 void CheckClosedStreams() {
QUICHE teamdc41bf12019-03-20 12:58:42 -0700343 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
344 connection_->transport_version(), Perspective::IS_CLIENT);
345 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
346 first_stream_id =
347 QuicUtils::GetCryptoStreamId(connection_->transport_version());
348 }
349 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500350 if (!QuicContainsKey(closed_streams_, i)) {
351 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
352 } else {
353 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
354 }
355 }
356 }
357
358 void CloseStream(QuicStreamId id) {
359 if (session_.connection()->transport_version() == QUIC_VERSION_99 &&
360 QuicUtils::GetStreamType(id, session_.perspective(),
361 session_.IsIncomingStream(id)) ==
362 READ_UNIDIRECTIONAL) {
363 // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
364 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
365 EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
366 } else {
367 // Verify reset IS sent for BIDIRECTIONAL streams.
368 if (session_.connection()->transport_version() == QUIC_VERSION_99) {
369 // Once for the RST_STREAM, Once for the STOP_SENDING
370 EXPECT_CALL(*connection_, SendControlFrame(_))
371 .Times(2)
372 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
373 } else {
374 EXPECT_CALL(*connection_, SendControlFrame(_))
375 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
376 }
377 EXPECT_CALL(*connection_, OnStreamReset(id, _));
378 }
379 session_.CloseStream(id);
380 closed_streams_.insert(id);
381 }
382
383 QuicTransportVersion transport_version() const {
384 return connection_->transport_version();
385 }
386
387 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
388 return QuicUtils::GetFirstBidirectionalStreamId(
389 connection_->transport_version(), Perspective::IS_CLIENT) +
390 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
391 }
392
393 QuicStreamId GetNthClientInitiatedUnidirectionalId(int n) {
394 return QuicUtils::GetFirstUnidirectionalStreamId(
395 connection_->transport_version(), Perspective::IS_CLIENT) +
396 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
397 }
398
399 QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
400 return QuicUtils::GetFirstBidirectionalStreamId(
401 connection_->transport_version(), Perspective::IS_SERVER) +
402 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
403 }
404
405 QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
406 return QuicUtils::GetFirstUnidirectionalStreamId(
407 connection_->transport_version(), Perspective::IS_SERVER) +
408 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
409 }
410
fkastenholz3c4eabf2019-04-22 07:49:59 -0700411 QuicStreamId StreamCountToId(QuicStreamCount stream_count,
412 Perspective perspective,
413 bool bidirectional) {
414 // Calculate and build up stream ID rather than use
415 // GetFirst... because tests that rely on this method
416 // needs to do the stream count where #1 is 0/1/2/3, and not
417 // take into account that stream 0 is special.
418 QuicStreamId id =
419 ((stream_count - 1) * QuicUtils::StreamIdDelta(QUIC_VERSION_99));
420 if (!bidirectional) {
421 id |= 0x2;
422 }
423 if (perspective == Perspective::IS_SERVER) {
424 id |= 0x1;
425 }
nharper46833c32019-05-15 21:33:05 -0700426 if (QuicVersionUsesCryptoFrames(connection_->transport_version()) &&
427 bidirectional && perspective == Perspective::IS_CLIENT) {
428 id += 4;
429 }
fkastenholz3c4eabf2019-04-22 07:49:59 -0700430 return id;
431 }
432
QUICHE teama6ef0a62019-03-07 20:34:33 -0500433 MockQuicConnectionHelper helper_;
434 MockAlarmFactory alarm_factory_;
435 NiceMock<MockQuicSessionVisitor> session_visitor_;
436 StrictMock<MockQuicConnection>* connection_;
437 TestSession session_;
438 std::set<QuicStreamId> closed_streams_;
439};
440
441class QuicSessionTestServer : public QuicSessionTestBase {
442 public:
443 // CheckMultiPathResponse validates that a written packet
444 // contains both expected path responses.
445 WriteResult CheckMultiPathResponse(const char* buffer,
446 size_t buf_len,
447 const QuicIpAddress& self_address,
448 const QuicSocketAddress& peer_address,
449 PerPacketOptions* options) {
450 QuicEncryptedPacket packet(buffer, buf_len);
451 {
452 InSequence s;
453 EXPECT_CALL(framer_visitor_, OnPacket());
454 EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
455 EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
456 EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
457 EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
458 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
459 .WillOnce(
460 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
461 EXPECT_EQ(path_frame_buffer1_, frame.data_buffer);
462 return true;
463 })));
464 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
465 .WillOnce(
466 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
467 EXPECT_EQ(path_frame_buffer2_, frame.data_buffer);
468 return true;
469 })));
470 EXPECT_CALL(framer_visitor_, OnPacketComplete());
471 }
472 client_framer_.ProcessPacket(packet);
473 return WriteResult(WRITE_STATUS_OK, 0);
474 }
475
476 protected:
477 QuicSessionTestServer()
478 : QuicSessionTestBase(Perspective::IS_SERVER),
479 path_frame_buffer1_({0, 1, 2, 3, 4, 5, 6, 7}),
480 path_frame_buffer2_({8, 9, 10, 11, 12, 13, 14, 15}),
481 client_framer_(SupportedVersions(GetParam()),
482 QuicTime::Zero(),
483 Perspective::IS_CLIENT,
484 kQuicDefaultConnectionIdLength) {
485 client_framer_.set_visitor(&framer_visitor_);
486 }
487
488 QuicPathFrameBuffer path_frame_buffer1_;
489 QuicPathFrameBuffer path_frame_buffer2_;
490 StrictMock<MockFramerVisitor> framer_visitor_;
491 // Framer used to process packets sent by server.
492 QuicFramer client_framer_;
493};
494
495INSTANTIATE_TEST_SUITE_P(Tests,
496 QuicSessionTestServer,
497 ::testing::ValuesIn(AllSupportedVersions()));
498
499TEST_P(QuicSessionTestServer, PeerAddress) {
500 EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
501 session_.peer_address());
502}
503
504TEST_P(QuicSessionTestServer, SelfAddress) {
505 EXPECT_TRUE(session_.self_address().IsInitialized());
506}
507
508TEST_P(QuicSessionTestServer, DontCallOnWriteBlockedForDisconnectedConnection) {
509 EXPECT_CALL(*connection_, CloseConnection(_, _, _))
510 .WillOnce(
511 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
512 connection_->CloseConnection(QUIC_NO_ERROR, "Everything is fine.",
513 ConnectionCloseBehavior::SILENT_CLOSE);
514 ASSERT_FALSE(connection_->connected());
515
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700516 EXPECT_CALL(session_visitor_, OnWriteBlocked(_)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500517 session_.OnWriteBlocked();
518}
519
520TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
521 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
522 CryptoHandshakeMessage message;
523 session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
524 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
525}
526
527TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
528 // Ensure that no streams are initially closed.
QUICHE teamdc41bf12019-03-20 12:58:42 -0700529 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
530 connection_->transport_version(), Perspective::IS_CLIENT);
531 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
532 first_stream_id =
533 QuicUtils::GetCryptoStreamId(connection_->transport_version());
534 }
535 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500536 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
537 }
538}
539
540TEST_P(QuicSessionTestServer, AvailableBidirectionalStreams) {
541 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
542 GetNthClientInitiatedBidirectionalId(3)) != nullptr);
543 // Smaller bidirectional streams should be available.
544 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
545 &session_, GetNthClientInitiatedBidirectionalId(1)));
546 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
547 &session_, GetNthClientInitiatedBidirectionalId(2)));
548 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
549 GetNthClientInitiatedBidirectionalId(2)) != nullptr);
550 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
551 GetNthClientInitiatedBidirectionalId(1)) != nullptr);
552}
553
554TEST_P(QuicSessionTestServer, AvailableUnidirectionalStreams) {
555 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
556 GetNthClientInitiatedUnidirectionalId(3)) != nullptr);
557 // Smaller unidirectional streams should be available.
558 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
559 &session_, GetNthClientInitiatedUnidirectionalId(1)));
560 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
561 &session_, GetNthClientInitiatedUnidirectionalId(2)));
562 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
563 GetNthClientInitiatedUnidirectionalId(2)) != nullptr);
564 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
565 GetNthClientInitiatedUnidirectionalId(1)) != nullptr);
566}
567
568TEST_P(QuicSessionTestServer, MaxAvailableBidirectionalStreams) {
569 if (transport_version() == QUIC_VERSION_99) {
570 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams(),
571 session_.MaxAvailableBidirectionalStreams());
572 } else {
573 // The protocol specification requires that there can be at least 10 times
574 // as many available streams as the connection's maximum open streams.
575 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams() *
576 kMaxAvailableStreamsMultiplier,
577 session_.MaxAvailableBidirectionalStreams());
578 }
579}
580
581TEST_P(QuicSessionTestServer, MaxAvailableUnidirectionalStreams) {
582 if (transport_version() == QUIC_VERSION_99) {
583 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams(),
584 session_.MaxAvailableUnidirectionalStreams());
585 } else {
586 // The protocol specification requires that there can be at least 10 times
587 // as many available streams as the connection's maximum open streams.
588 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams() *
589 kMaxAvailableStreamsMultiplier,
590 session_.MaxAvailableUnidirectionalStreams());
591 }
592}
593
594TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamLocallyCreated) {
595 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
596 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id());
597 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
598 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(1), stream4->id());
599
600 CheckClosedStreams();
601 CloseStream(GetNthServerInitiatedBidirectionalId(0));
602 CheckClosedStreams();
603 CloseStream(GetNthServerInitiatedBidirectionalId(1));
604 CheckClosedStreams();
605}
606
607TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamLocallyCreated) {
608 TestStream* stream2 = session_.CreateOutgoingUnidirectionalStream();
609 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(0), stream2->id());
610 TestStream* stream4 = session_.CreateOutgoingUnidirectionalStream();
611 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(1), stream4->id());
612
613 CheckClosedStreams();
614 CloseStream(GetNthServerInitiatedUnidirectionalId(0));
615 CheckClosedStreams();
616 CloseStream(GetNthServerInitiatedUnidirectionalId(1));
617 CheckClosedStreams();
618}
619
620TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamPeerCreated) {
621 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
622 QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
623 session_.GetOrCreateDynamicStream(stream_id1);
624 session_.GetOrCreateDynamicStream(stream_id2);
625
626 CheckClosedStreams();
627 CloseStream(stream_id1);
628 CheckClosedStreams();
629 CloseStream(stream_id2);
630 // Create a stream, and make another available.
631 QuicStream* stream3 = session_.GetOrCreateDynamicStream(
632 stream_id2 +
633 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
634 CheckClosedStreams();
635 // Close one, but make sure the other is still not closed
636 CloseStream(stream3->id());
637 CheckClosedStreams();
638}
639
640TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamPeerCreated) {
641 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
642 QuicStreamId stream_id2 = GetNthClientInitiatedUnidirectionalId(1);
643 session_.GetOrCreateDynamicStream(stream_id1);
644 session_.GetOrCreateDynamicStream(stream_id2);
645
646 CheckClosedStreams();
647 CloseStream(stream_id1);
648 CheckClosedStreams();
649 CloseStream(stream_id2);
650 // Create a stream, and make another available.
651 QuicStream* stream3 = session_.GetOrCreateDynamicStream(
652 stream_id2 +
653 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
654 CheckClosedStreams();
655 // Close one, but make sure the other is still not closed
656 CloseStream(stream3->id());
657 CheckClosedStreams();
658}
659
660TEST_P(QuicSessionTestServer, MaximumAvailableOpenedBidirectionalStreams) {
661 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
662 session_.GetOrCreateDynamicStream(stream_id);
663 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
664 EXPECT_NE(
665 nullptr,
666 session_.GetOrCreateDynamicStream(GetNthClientInitiatedBidirectionalId(
667 session_.max_open_incoming_bidirectional_streams() - 1)));
668}
669
670TEST_P(QuicSessionTestServer, MaximumAvailableOpenedUnidirectionalStreams) {
671 QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
672 session_.GetOrCreateDynamicStream(stream_id);
673 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
674 EXPECT_NE(
675 nullptr,
676 session_.GetOrCreateDynamicStream(GetNthClientInitiatedUnidirectionalId(
677 session_.max_open_incoming_unidirectional_streams() - 1)));
678}
679
680TEST_P(QuicSessionTestServer, TooManyAvailableBidirectionalStreams) {
681 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
682 QuicStreamId stream_id2;
683 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1));
684 // A stream ID which is too large to create.
685 stream_id2 = GetNthClientInitiatedBidirectionalId(
686 session_.MaxAvailableBidirectionalStreams() + 2);
687 if (transport_version() == QUIC_VERSION_99) {
688 // V99 terminates the connection with invalid stream id
689 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
690 } else {
691 // other versions terminate the connection with
692 // QUIC_TOO_MANY_AVAILABLE_STREAMS.
693 EXPECT_CALL(*connection_,
694 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
695 }
696 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2));
697}
698
699TEST_P(QuicSessionTestServer, TooManyAvailableUnidirectionalStreams) {
700 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
701 QuicStreamId stream_id2;
702 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1));
703 // A stream ID which is too large to create.
704 stream_id2 = GetNthClientInitiatedUnidirectionalId(
705 session_.MaxAvailableUnidirectionalStreams() + 2);
706 if (transport_version() == QUIC_VERSION_99) {
707 // V99 terminates the connection with invalid stream id
708 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
709 } else {
710 // other versions terminate the connection with
711 // QUIC_TOO_MANY_AVAILABLE_STREAMS.
712 EXPECT_CALL(*connection_,
713 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
714 }
715 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2));
716}
717
718TEST_P(QuicSessionTestServer, ManyAvailableBidirectionalStreams) {
719 // When max_open_streams_ is 200, should be able to create 200 streams
720 // out-of-order, that is, creating the one with the largest stream ID first.
fkastenholzd3a1de92019-05-15 07:00:07 -0700721 if (transport_version() == QUIC_VERSION_99) {
722 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
723 // Smaller limit on unidirectional streams to help detect crossed wires.
724 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 50);
725 } else {
726 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
727 }
728 // Create a stream at the start of the range.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500729 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500730 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500731
732 // Create the largest stream ID of a threatened total of 200 streams.
733 // GetNth... starts at 0, so for 200 streams, get the 199th.
fkastenholzd3a1de92019-05-15 07:00:07 -0700734 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500735 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
736 GetNthClientInitiatedBidirectionalId(199)));
fkastenholzd3a1de92019-05-15 07:00:07 -0700737
738 if (transport_version() == QUIC_VERSION_99) {
739 // If IETF QUIC, check to make sure that creating bidirectional
740 // streams does not mess up the unidirectional streams.
741 stream_id = GetNthClientInitiatedUnidirectionalId(0);
742 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
743 // Now try to get the last possible unidirectional stream.
744 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
745 GetNthClientInitiatedUnidirectionalId(49)));
746 // and this should fail because it exceeds the unidirectional limit
747 // (but not the bi-)
748 EXPECT_CALL(
749 *connection_,
750 CloseConnection(QUIC_INVALID_STREAM_ID,
751 "Stream id 798 would exceed stream count limit 50",
752 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
753
754 ))
755 .Times(1);
756 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(
757 GetNthClientInitiatedUnidirectionalId(199)));
758 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500759}
760
761TEST_P(QuicSessionTestServer, ManyAvailableUnidirectionalStreams) {
762 // When max_open_streams_ is 200, should be able to create 200 streams
763 // out-of-order, that is, creating the one with the largest stream ID first.
fkastenholzd3a1de92019-05-15 07:00:07 -0700764 if (transport_version() == QUIC_VERSION_99) {
765 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 200);
766 // Smaller limit on unidirectional streams to help detect crossed wires.
767 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 50);
768 } else {
769 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
770 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500771 // Create one stream.
fkastenholzd3a1de92019-05-15 07:00:07 -0700772 QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500773 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500774
775 // Create the largest stream ID of a threatened total of 200 streams.
776 // GetNth... starts at 0, so for 200 streams, get the 199th.
fkastenholzd3a1de92019-05-15 07:00:07 -0700777 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500778 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
779 GetNthClientInitiatedUnidirectionalId(199)));
fkastenholzd3a1de92019-05-15 07:00:07 -0700780 if (transport_version() == QUIC_VERSION_99) {
781 // If IETF QUIC, check to make sure that creating unidirectional
782 // streams does not mess up the bidirectional streams.
783 stream_id = GetNthClientInitiatedBidirectionalId(0);
784 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
785 // Now try to get the last possible bidirectional stream.
786 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
787 GetNthClientInitiatedBidirectionalId(49)));
788 // and this should fail because it exceeds the bnidirectional limit
789 // (but not the uni-)
790 EXPECT_CALL(
791 *connection_,
792 CloseConnection(QUIC_INVALID_STREAM_ID,
nharper46833c32019-05-15 21:33:05 -0700793 "Stream id 800 would exceed stream count limit 50",
fkastenholzd3a1de92019-05-15 07:00:07 -0700794 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
795
796 ))
797 .Times(1);
798 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(
799 GetNthClientInitiatedBidirectionalId(199)));
800 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500801}
802
803TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
804 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
805 if (GetParam() != AllSupportedVersions()[0]) {
806 return;
807 }
808
809 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
810 QuicStreamId closed_stream_id = stream2->id();
811 // Close the stream.
812 EXPECT_CALL(*connection_, SendControlFrame(_));
813 EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
814 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
vasilvvc48c8712019-03-11 13:38:16 -0700815 std::string msg =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500816 QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
817 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
818 msg);
819}
820
821TEST_P(QuicSessionTestServer, OnCanWrite) {
822 session_.set_writev_consumes_all_data(true);
823 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
824 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
825 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
826
827 session_.MarkConnectionLevelWriteBlocked(stream2->id());
828 session_.MarkConnectionLevelWriteBlocked(stream6->id());
829 session_.MarkConnectionLevelWriteBlocked(stream4->id());
830
831 InSequence s;
832
833 // Reregister, to test the loop limit.
834 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
835 session_.SendStreamData(stream2);
836 session_.MarkConnectionLevelWriteBlocked(stream2->id());
837 }));
838 // 2 will get called a second time as it didn't finish its block
839 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
840 session_.SendStreamData(stream2);
841 }));
842 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
843 session_.SendStreamData(stream6);
844 }));
845 // 4 will not get called, as we exceeded the loop limit.
846 session_.OnCanWrite();
847 EXPECT_TRUE(session_.WillingAndAbleToWrite());
848}
849
850TEST_P(QuicSessionTestServer, TestBatchedWrites) {
851 session_.set_writev_consumes_all_data(true);
852 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
853 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
854 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
855
856 session_.set_writev_consumes_all_data(true);
857 session_.MarkConnectionLevelWriteBlocked(stream2->id());
858 session_.MarkConnectionLevelWriteBlocked(stream4->id());
859
860 // With two sessions blocked, we should get two write calls. They should both
861 // go to the first stream as it will only write 6k and mark itself blocked
862 // again.
863 InSequence s;
864 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
865 session_.SendLargeFakeData(stream2, 6000);
866 session_.MarkConnectionLevelWriteBlocked(stream2->id());
867 }));
868 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
869 session_.SendLargeFakeData(stream2, 6000);
870 session_.MarkConnectionLevelWriteBlocked(stream2->id());
871 }));
872 session_.OnCanWrite();
873
874 // We should get one more call for stream2, at which point it has used its
875 // write quota and we move over to stream 4.
876 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
877 session_.SendLargeFakeData(stream2, 6000);
878 session_.MarkConnectionLevelWriteBlocked(stream2->id());
879 }));
880 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
881 session_.SendLargeFakeData(stream4, 6000);
882 session_.MarkConnectionLevelWriteBlocked(stream4->id());
883 }));
884 session_.OnCanWrite();
885
886 // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
887 // priority stream 6. 4 should be preempted. 6 will write but *not* block so
888 // will cede back to 4.
889 stream6->SetPriority(kV3HighestPriority);
890 EXPECT_CALL(*stream4, OnCanWrite())
891 .WillOnce(Invoke([this, stream4, stream6]() {
892 session_.SendLargeFakeData(stream4, 6000);
893 session_.MarkConnectionLevelWriteBlocked(stream4->id());
894 session_.MarkConnectionLevelWriteBlocked(stream6->id());
895 }));
896 EXPECT_CALL(*stream6, OnCanWrite())
897 .WillOnce(Invoke([this, stream4, stream6]() {
898 session_.SendStreamData(stream6);
899 session_.SendLargeFakeData(stream4, 6000);
900 }));
901 session_.OnCanWrite();
902
903 // Stream4 alread did 6k worth of writes, so after doing another 12k it should
904 // cede and 2 should resume.
905 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
906 session_.SendLargeFakeData(stream4, 12000);
907 session_.MarkConnectionLevelWriteBlocked(stream4->id());
908 }));
909 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
910 session_.SendLargeFakeData(stream2, 6000);
911 session_.MarkConnectionLevelWriteBlocked(stream2->id());
912 }));
913 session_.OnCanWrite();
914}
915
916TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
917 // Encryption needs to be established before data can be sent.
918 CryptoHandshakeMessage msg;
919 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
920 QuicConnectionPeer::GetWriter(session_.connection()));
921 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
922
923 // Drive congestion control manually.
924 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
925 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
926
927 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
928 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
929 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
930
931 session_.MarkConnectionLevelWriteBlocked(stream2->id());
932 session_.MarkConnectionLevelWriteBlocked(stream6->id());
933 session_.MarkConnectionLevelWriteBlocked(stream4->id());
934
935 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
936 EXPECT_CALL(*send_algorithm, GetCongestionWindow())
dschinazi66dea072019-04-09 11:41:06 -0700937 .WillRepeatedly(Return(kMaxOutgoingPacketSize * 10));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500938 EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
939 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
940 session_.SendStreamData(stream2);
941 }));
942 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
943 session_.SendStreamData(stream4);
944 }));
945 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
946 session_.SendStreamData(stream6);
947 }));
948
949 // Expect that we only send one packet, the writes from different streams
950 // should be bundled together.
951 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
952 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
953 EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
954 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
955 session_.OnCanWrite();
956 EXPECT_FALSE(session_.WillingAndAbleToWrite());
957}
958
959TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
960 session_.set_writev_consumes_all_data(true);
961 InSequence s;
962
963 // Drive congestion control manually.
964 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
965 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
966
967 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
968 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
969 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
970
971 session_.MarkConnectionLevelWriteBlocked(stream2->id());
972 session_.MarkConnectionLevelWriteBlocked(stream6->id());
973 session_.MarkConnectionLevelWriteBlocked(stream4->id());
974
975 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
976 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
977 session_.SendStreamData(stream2);
978 }));
979 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
980 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
981 session_.SendStreamData(stream6);
982 }));
983 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
984 // stream4->OnCanWrite is not called.
985
986 session_.OnCanWrite();
987 EXPECT_TRUE(session_.WillingAndAbleToWrite());
988
989 // Still congestion-control blocked.
990 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
991 session_.OnCanWrite();
992 EXPECT_TRUE(session_.WillingAndAbleToWrite());
993
994 // stream4->OnCanWrite is called once the connection stops being
995 // congestion-control blocked.
996 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
997 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
998 session_.SendStreamData(stream4);
999 }));
1000 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1001 session_.OnCanWrite();
1002 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1003}
1004
1005TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
1006 // Drive congestion control manually in order to ensure that
1007 // application-limited signaling is handled correctly.
1008 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1009 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1010 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1011
1012 // Drive packet writer manually.
1013 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1014 QuicConnectionPeer::GetWriter(session_.connection()));
1015 EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
1016 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
1017
1018 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1019
1020 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1021
1022 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
1023 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)).Times(0);
1024
1025 session_.OnCanWrite();
1026 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1027}
1028
1029TEST_P(QuicSessionTestServer, BufferedHandshake) {
nharperd5c4a932019-05-13 13:58:49 -07001030 // This test is testing behavior of crypto stream flow control, but when
1031 // CRYPTO frames are used, there is no flow control for the crypto handshake.
1032 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1033 return;
1034 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001035 session_.set_writev_consumes_all_data(true);
1036 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
1037
1038 // Test that blocking other streams does not change our status.
1039 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1040 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1041 EXPECT_FALSE(session_.HasPendingHandshake());
1042
1043 TestStream* stream3 = session_.CreateOutgoingBidirectionalStream();
1044 session_.MarkConnectionLevelWriteBlocked(stream3->id());
1045 EXPECT_FALSE(session_.HasPendingHandshake());
1046
1047 // Blocking (due to buffering of) the Crypto stream is detected.
1048 session_.MarkConnectionLevelWriteBlocked(
1049 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1050 EXPECT_TRUE(session_.HasPendingHandshake());
1051
1052 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1053 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1054 EXPECT_TRUE(session_.HasPendingHandshake());
1055
1056 InSequence s;
1057 // Force most streams to re-register, which is common scenario when we block
1058 // the Crypto stream, and only the crypto stream can "really" write.
1059
1060 // Due to prioritization, we *should* be asked to write the crypto stream
1061 // first.
1062 // Don't re-register the crypto stream (which signals complete writing).
1063 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1064 EXPECT_CALL(*crypto_stream, OnCanWrite());
1065
1066 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1067 session_.SendStreamData(stream2);
1068 }));
1069 EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(Invoke([this, stream3]() {
1070 session_.SendStreamData(stream3);
1071 }));
1072 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1073 session_.SendStreamData(stream4);
1074 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1075 }));
1076
1077 session_.OnCanWrite();
1078 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1079 EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
1080}
1081
1082TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
1083 session_.set_writev_consumes_all_data(true);
1084 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1085 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1086 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1087
1088 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1089 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1090 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1091 CloseStream(stream6->id());
1092
1093 InSequence s;
1094 EXPECT_CALL(*connection_, SendControlFrame(_))
1095 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
1096 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1097 session_.SendStreamData(stream2);
1098 }));
1099 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1100 session_.SendStreamData(stream4);
1101 }));
1102 session_.OnCanWrite();
1103 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1104}
1105
1106TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
1107 // Drive congestion control manually in order to ensure that
1108 // application-limited signaling is handled correctly.
1109 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1110 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1111 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1112
1113 // Ensure connection level flow control blockage.
1114 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
1115 EXPECT_TRUE(session_.flow_controller()->IsBlocked());
1116 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1117 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1118
1119 // Mark the crypto and headers streams as write blocked, we expect them to be
1120 // allowed to write later.
nharperd5c4a932019-05-13 13:58:49 -07001121 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1122 session_.MarkConnectionLevelWriteBlocked(
1123 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1124 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001125
1126 // Create a data stream, and although it is write blocked we never expect it
1127 // to be allowed to write as we are connection level flow control blocked.
1128 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1129 session_.MarkConnectionLevelWriteBlocked(stream->id());
1130 EXPECT_CALL(*stream, OnCanWrite()).Times(0);
1131
1132 // The crypto and headers streams should be called even though we are
1133 // connection flow control blocked.
nharperd5c4a932019-05-13 13:58:49 -07001134 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1135 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1136 EXPECT_CALL(*crypto_stream, OnCanWrite());
1137 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001138
1139 // After the crypto and header streams perform a write, the connection will be
1140 // blocked by the flow control, hence it should become application-limited.
1141 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1142
1143 session_.OnCanWrite();
1144 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1145}
1146
1147TEST_P(QuicSessionTestServer, SendGoAway) {
1148 if (transport_version() == QUIC_VERSION_99) {
1149 // GoAway frames are not in version 99
1150 return;
1151 }
1152 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1153 QuicConnectionPeer::GetWriter(session_.connection()));
1154 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
1155 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1156
1157 EXPECT_CALL(*connection_, SendControlFrame(_))
1158 .WillOnce(
1159 Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
1160 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1161 EXPECT_TRUE(session_.goaway_sent());
1162
1163 const QuicStreamId kTestStreamId = 5u;
1164 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1165 EXPECT_CALL(*connection_,
1166 OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
1167 .Times(0);
1168 EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId));
1169}
1170
1171TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
1172 if (transport_version() == QUIC_VERSION_99) {
1173 // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
1174 // supported.
1175 return;
1176 }
1177 EXPECT_CALL(*connection_, SendControlFrame(_))
1178 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1179 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1180 EXPECT_TRUE(session_.goaway_sent());
1181 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1182}
1183
1184TEST_P(QuicSessionTestServer, InvalidGoAway) {
1185 if (transport_version() == QUIC_VERSION_99) {
1186 // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
1187 // supported.
1188 return;
1189 }
1190 QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
1191 session_.next_outgoing_bidirectional_stream_id(), "");
1192 session_.OnGoAway(go_away);
1193}
1194
1195// Test that server session will send a connectivity probe in response to a
1196// connectivity probe on the same path.
1197TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbe) {
1198 QuicSocketAddress old_peer_address =
1199 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1200 EXPECT_EQ(old_peer_address, session_.peer_address());
1201
1202 QuicSocketAddress new_peer_address =
1203 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort + 1);
1204
1205 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1206 QuicConnectionPeer::GetWriter(session_.connection()));
1207 EXPECT_CALL(*writer, WritePacket(_, _, _, new_peer_address, _))
1208 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1209 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1210 .WillOnce(Invoke(
1211 connection_,
1212 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
1213 if (transport_version() == QUIC_VERSION_99) {
1214 // Need to explicitly do this to emulate the reception of a PathChallenge,
1215 // which stores its payload for use in generating the response.
1216 connection_->OnPathChallengeFrame(
1217 QuicPathChallengeFrame(0, path_frame_buffer1_));
1218 }
1219 session_.OnConnectivityProbeReceived(session_.self_address(),
1220 new_peer_address);
1221 EXPECT_EQ(old_peer_address, session_.peer_address());
1222}
1223
1224// Same as above, but check that if there are two PATH_CHALLENGE frames in the
1225// packet, the response has both of them AND we do not do migration. This for
1226// V99 only.
1227TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbes) {
1228 if (transport_version() != QUIC_VERSION_99) {
1229 return;
1230 }
1231 QuicSocketAddress old_peer_address =
1232 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1233 EXPECT_EQ(old_peer_address, session_.peer_address());
1234
1235 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1236 QuicConnectionPeer::GetWriter(session_.connection()));
1237 // CheckMultiPathResponse validates that the written packet
1238 // contains both path responses.
1239 EXPECT_CALL(*writer, WritePacket(_, _, _, old_peer_address, _))
1240 .WillOnce(Invoke(this, &QuicSessionTestServer::CheckMultiPathResponse));
1241
1242 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1243 .WillOnce(Invoke(
1244 connection_,
1245 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
QUICHE team8c1daa22019-03-13 08:33:41 -07001246 QuicConnectionPeer::SetLastHeaderFormat(connection_,
1247 IETF_QUIC_SHORT_HEADER_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001248 // Need to explicitly do this to emulate the reception of a PathChallenge,
1249 // which stores its payload for use in generating the response.
1250 connection_->OnPathChallengeFrame(
1251 QuicPathChallengeFrame(0, path_frame_buffer1_));
1252 connection_->OnPathChallengeFrame(
1253 QuicPathChallengeFrame(0, path_frame_buffer2_));
1254 session_.OnConnectivityProbeReceived(session_.self_address(),
1255 old_peer_address);
1256}
1257
1258TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
1259 EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
1260 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1261 CryptoHandshakeMessage msg;
1262 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1263 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
1264 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1265}
1266
1267TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
nharper46833c32019-05-15 21:33:05 -07001268 QuicStreamId headers_stream_id =
1269 QuicUtils::GetHeadersStreamId(connection_->transport_version());
1270 std::unique_ptr<TestStream> fake_headers_stream = QuicMakeUnique<TestStream>(
1271 headers_stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
1272 if (GetQuicReloadableFlag(quic_eliminate_static_stream_map_2)) {
1273 QuicSessionPeer::RegisterStaticStreamNew(&session_,
1274 std::move(fake_headers_stream));
1275 } else {
1276 QuicSessionPeer::RegisterStaticStream(&session_, headers_stream_id,
1277 fake_headers_stream.get());
1278 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001279 // Send two bytes of payload.
nharper46833c32019-05-15 21:33:05 -07001280 QuicStreamFrame data1(headers_stream_id, true, 0, QuicStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001281 EXPECT_CALL(*connection_,
1282 CloseConnection(
1283 QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
1284 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1285 session_.OnStreamFrame(data1);
1286}
1287
1288TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
nharper46833c32019-05-15 21:33:05 -07001289 QuicStreamId headers_stream_id =
1290 QuicUtils::GetHeadersStreamId(connection_->transport_version());
1291 std::unique_ptr<TestStream> fake_headers_stream = QuicMakeUnique<TestStream>(
1292 headers_stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
1293 if (GetQuicReloadableFlag(quic_eliminate_static_stream_map_2)) {
1294 QuicSessionPeer::RegisterStaticStreamNew(&session_,
1295 std::move(fake_headers_stream));
1296 } else {
1297 QuicSessionPeer::RegisterStaticStream(&session_, headers_stream_id,
1298 fake_headers_stream.get());
1299 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001300 // Send two bytes of payload.
nharper46833c32019-05-15 21:33:05 -07001301 QuicRstStreamFrame rst1(kInvalidControlFrameId, headers_stream_id,
1302 QUIC_ERROR_PROCESSING_STREAM, 0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001303 EXPECT_CALL(*connection_,
1304 CloseConnection(
1305 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
1306 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1307 session_.OnRstStream(rst1);
1308}
1309
1310TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
1311 // Send two bytes of payload.
1312 QuicStreamFrame data1(
1313 QuicUtils::GetInvalidStreamId(connection_->transport_version()), true, 0,
1314 QuicStringPiece("HT"));
1315 EXPECT_CALL(*connection_,
1316 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001317 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001318 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1319 session_.OnStreamFrame(data1);
1320}
1321
1322TEST_P(QuicSessionTestServer, OnRstStreamInvalidStreamId) {
1323 // Send two bytes of payload.
1324 QuicRstStreamFrame rst1(
1325 kInvalidControlFrameId,
1326 QuicUtils::GetInvalidStreamId(connection_->transport_version()),
1327 QUIC_ERROR_PROCESSING_STREAM, 0);
1328 EXPECT_CALL(*connection_,
1329 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001330 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001331 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1332 session_.OnRstStream(rst1);
1333}
1334
1335TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
1336 // Test that if a stream is flow control blocked, then on receipt of the SHLO
1337 // containing a suitable send window offset, the stream becomes unblocked.
1338
1339 // Ensure that Writev consumes all the data it is given (simulate no socket
1340 // blocking).
1341 session_.set_writev_consumes_all_data(true);
1342
1343 // Create a stream, and send enough data to make it flow control blocked.
1344 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07001345 std::string body(kMinimumFlowControlSendWindow, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001346 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1347 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1348 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1349 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
1350 stream2->WriteOrBufferData(body, false, nullptr);
1351 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
1352 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1353 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1354
1355 // Now complete the crypto handshake, resulting in an increased flow control
1356 // send window.
1357 CryptoHandshakeMessage msg;
1358 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1359 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
1360 // Stream is now unblocked.
1361 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1362 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1363 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1364}
1365
1366TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
QUICHE teamea740082019-03-11 17:58:43 -07001367 if (QuicVersionUsesCryptoFrames(GetParam().transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001368 // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
1369 // test doesn't make sense for those versions since CRYPTO frames aren't
1370 // flow controlled.
1371 return;
1372 }
1373 // Test that if the crypto stream is flow control blocked, then if the SHLO
1374 // contains a larger send window offset, the stream becomes unblocked.
1375 session_.set_writev_consumes_all_data(true);
1376 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1377 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1378 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1379 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1380 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1381 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1382 EXPECT_CALL(*connection_, SendControlFrame(_))
1383 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1384 for (QuicStreamId i = 0;
1385 !crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
1386 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1387 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1388 QuicStreamOffset offset = crypto_stream->stream_bytes_written();
1389 QuicConfig config;
1390 CryptoHandshakeMessage crypto_message;
fkastenholzd3a1de92019-05-15 07:00:07 -07001391 config.ToHandshakeMessage(&crypto_message, transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001392 crypto_stream->SendHandshakeMessage(crypto_message);
1393 char buf[1000];
1394 QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
1395 crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
1396 }
1397 EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
1398 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1399 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1400 EXPECT_FALSE(session_.HasDataToWrite());
1401 EXPECT_TRUE(crypto_stream->HasBufferedData());
1402
1403 // Now complete the crypto handshake, resulting in an increased flow control
1404 // send window.
1405 CryptoHandshakeMessage msg;
1406 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1407 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
1408 &session_,
1409 QuicUtils::GetCryptoStreamId(connection_->transport_version())));
1410 // Stream is now unblocked and will no longer have buffered data.
1411 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1412 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1413 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1414}
1415
1416TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
1417 // Test that when we receive an out of order stream RST we correctly adjust
1418 // our connection level flow control receive window.
1419 // On close, the stream should mark as consumed all bytes between the highest
1420 // byte consumed so far and the final byte offset from the RST frame.
1421 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1422
1423 const QuicStreamOffset kByteOffset =
1424 1 + kInitialSessionFlowControlWindowForTest / 2;
1425
1426 EXPECT_CALL(*connection_, SendControlFrame(_))
1427 .Times(2)
1428 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
1429 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1430
1431 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1432 QUIC_STREAM_CANCELLED, kByteOffset);
1433 session_.OnRstStream(rst_frame);
1434 if (transport_version() == QUIC_VERSION_99) {
1435 // The test is predicated on the stream being fully closed. For V99, the
1436 // RST_STREAM only does one side (the read side from the perspective of the
1437 // node receiving the RST_STREAM). This is needed to fully close the
1438 // stream and therefore fulfill all of the expects.
1439 QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
1440 QUIC_STREAM_CANCELLED);
1441 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
1442 }
1443 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
1444}
1445
1446TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
1447 // Test the situation where we receive a FIN on a stream, and before we fully
1448 // consume all the data from the sequencer buffer we locally RST the stream.
1449 // The bytes between highest consumed byte, and the final byte offset that we
1450 // determined when the FIN arrived, should be marked as consumed at the
1451 // connection level flow controller when the stream is reset.
1452 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1453
1454 const QuicStreamOffset kByteOffset =
1455 kInitialSessionFlowControlWindowForTest / 2 - 1;
1456 QuicStreamFrame frame(stream->id(), true, kByteOffset, ".");
1457 session_.OnStreamFrame(frame);
1458 EXPECT_TRUE(connection_->connected());
1459
1460 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
1461 EXPECT_EQ(kByteOffset + frame.data_length,
1462 stream->flow_controller()->highest_received_byte_offset());
1463
1464 // Reset stream locally.
1465 EXPECT_CALL(*connection_, SendControlFrame(_));
1466 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1467 stream->Reset(QUIC_STREAM_CANCELLED);
1468 EXPECT_EQ(kByteOffset + frame.data_length,
1469 session_.flow_controller()->bytes_consumed());
1470}
1471
1472TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
1473 // Test that when we RST the stream (and tear down stream state), and then
1474 // receive a FIN from the peer, we correctly adjust our connection level flow
1475 // control receive window.
1476
1477 // Connection starts with some non-zero highest received byte offset,
1478 // due to other active streams.
1479 const uint64_t kInitialConnectionBytesConsumed = 567;
1480 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1481 EXPECT_LT(kInitialConnectionBytesConsumed,
1482 kInitialConnectionHighestReceivedOffset);
1483 session_.flow_controller()->UpdateHighestReceivedOffset(
1484 kInitialConnectionHighestReceivedOffset);
1485 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1486
1487 // Reset our stream: this results in the stream being closed locally.
1488 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1489 EXPECT_CALL(*connection_, SendControlFrame(_));
1490 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1491 stream->Reset(QUIC_STREAM_CANCELLED);
1492
1493 // Now receive a response from the peer with a FIN. We should handle this by
1494 // adjusting the connection level flow control receive window to take into
1495 // account the total number of bytes sent by the peer.
1496 const QuicStreamOffset kByteOffset = 5678;
vasilvvc48c8712019-03-11 13:38:16 -07001497 std::string body = "hello";
QUICHE teama6ef0a62019-03-07 20:34:33 -05001498 QuicStreamFrame frame(stream->id(), true, kByteOffset, QuicStringPiece(body));
1499 session_.OnStreamFrame(frame);
1500
1501 QuicStreamOffset total_stream_bytes_sent_by_peer =
1502 kByteOffset + body.length();
1503 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer,
1504 session_.flow_controller()->bytes_consumed());
1505 EXPECT_EQ(
1506 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer,
1507 session_.flow_controller()->highest_received_byte_offset());
1508}
1509
1510TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
1511 // Test that when we RST the stream (and tear down stream state), and then
1512 // receive a RST from the peer, we correctly adjust our connection level flow
1513 // control receive window.
1514
1515 // Connection starts with some non-zero highest received byte offset,
1516 // due to other active streams.
1517 const uint64_t kInitialConnectionBytesConsumed = 567;
1518 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1519 EXPECT_LT(kInitialConnectionBytesConsumed,
1520 kInitialConnectionHighestReceivedOffset);
1521 session_.flow_controller()->UpdateHighestReceivedOffset(
1522 kInitialConnectionHighestReceivedOffset);
1523 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1524
1525 // Reset our stream: this results in the stream being closed locally.
1526 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1527 EXPECT_CALL(*connection_, SendControlFrame(_));
1528 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1529 stream->Reset(QUIC_STREAM_CANCELLED);
1530 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1531
1532 // Now receive a RST from the peer. We should handle this by adjusting the
1533 // connection level flow control receive window to take into account the total
1534 // number of bytes sent by the peer.
1535 const QuicStreamOffset kByteOffset = 5678;
1536 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1537 QUIC_STREAM_CANCELLED, kByteOffset);
1538 session_.OnRstStream(rst_frame);
1539
1540 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset,
1541 session_.flow_controller()->bytes_consumed());
1542 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset,
1543 session_.flow_controller()->highest_received_byte_offset());
1544}
1545
1546TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
1547 // Test that receipt of an invalid (< default) stream flow control window from
1548 // the peer results in the connection being torn down.
1549 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1550 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
1551 kInvalidWindow);
1552
dschinazic7036122019-04-30 12:46:34 -07001553 if (!connection_->version().AllowsLowFlowControlLimits()) {
1554 EXPECT_CALL(*connection_,
1555 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1556 } else {
1557 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1558 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001559 session_.OnConfigNegotiated();
1560}
1561
1562TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
1563 // Test that receipt of an invalid (< default) session flow control window
1564 // from the peer results in the connection being torn down.
1565 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1566 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
1567 kInvalidWindow);
dschinazic7036122019-04-30 12:46:34 -07001568 if (!connection_->version().AllowsLowFlowControlLimits()) {
1569 EXPECT_CALL(*connection_,
1570 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1571 } else {
1572 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1573 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001574 session_.OnConfigNegotiated();
1575}
1576
1577// Test negotiation of custom server initial flow control window.
1578TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
1579 QuicTagVector copt;
1580 copt.push_back(kIFW7);
1581 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
1582
1583 session_.OnConfigNegotiated();
1584 EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
1585 session_.flow_controller()));
1586}
1587
1588TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
1589 // Test that if we receive a stream RST with a highest byte offset that
1590 // violates flow control, that we close the connection.
1591 const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
1592 EXPECT_CALL(*connection_,
1593 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
1594 .Times(2);
1595
1596 // Check that stream frame + FIN results in connection close.
1597 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1598 EXPECT_CALL(*connection_, SendControlFrame(_));
1599 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1600 stream->Reset(QUIC_STREAM_CANCELLED);
1601 QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
1602 session_.OnStreamFrame(frame);
1603
1604 // Check that RST results in connection close.
1605 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1606 QUIC_STREAM_CANCELLED, kLargeOffset);
1607 session_.OnRstStream(rst_frame);
1608}
1609
1610TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
1611 // If a buggy/malicious peer creates too many streams that are not ended
1612 // with a FIN or RST then we send an RST to refuse streams. For V99 the
1613 // connection is closed.
1614 const QuicStreamId kMaxStreams = 5;
fkastenholzd3a1de92019-05-15 07:00:07 -07001615 if (transport_version() == QUIC_VERSION_99) {
1616 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1617 kMaxStreams);
1618 } else {
1619 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1620 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001621 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1622 const QuicStreamId kFinalStreamId =
1623 GetNthClientInitiatedBidirectionalId(kMaxStreams);
1624 // Create kMaxStreams data streams, and close them all without receiving a
1625 // FIN or a RST_STREAM from the client.
1626 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
1627 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
1628 QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
1629 session_.OnStreamFrame(data1);
1630 // EXPECT_EQ(1u, session_.GetNumOpenStreams());
1631 if (transport_version() == QUIC_VERSION_99) {
1632 // Expect two control frames, RST STREAM and STOP SENDING
1633 EXPECT_CALL(*connection_, SendControlFrame(_))
1634 .Times(2)
1635 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
1636 } else {
1637 // Expect one control frame, just RST STREAM
1638 EXPECT_CALL(*connection_, SendControlFrame(_))
1639 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1640 }
1641 // Close stream. Should not make new streams available since
1642 // the stream is not finished.
1643 EXPECT_CALL(*connection_, OnStreamReset(i, _));
1644 session_.CloseStream(i);
1645 }
1646
1647 if (transport_version() == QUIC_VERSION_99) {
fkastenholz3c4eabf2019-04-22 07:49:59 -07001648 EXPECT_CALL(
1649 *connection_,
1650 CloseConnection(QUIC_INVALID_STREAM_ID,
nharper46833c32019-05-15 21:33:05 -07001651 "Stream id 24 would exceed stream count limit 5", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001652 } else {
1653 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1654 EXPECT_CALL(*connection_,
1655 OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
1656 .Times(1);
1657 }
1658 // Create one more data streams to exceed limit of open stream.
1659 QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
1660 session_.OnStreamFrame(data1);
1661}
1662
1663TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpenedOutgoing) {
1664 // Verify that a draining stream (which has received a FIN but not consumed
1665 // it) does not count against the open quota (because it is closed from the
1666 // protocol point of view).
1667 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1668 QuicStreamId stream_id = stream->id();
1669 QuicStreamFrame data1(stream_id, true, 0, QuicStringPiece("HT"));
1670 session_.OnStreamFrame(data1);
1671 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream()).Times(1);
1672 session_.StreamDraining(stream_id);
1673}
1674
1675TEST_P(QuicSessionTestServer, NoPendingStreams) {
renjietange76b2da2019-05-13 14:50:23 -07001676 session_.set_uses_pending_streams(false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001677
1678 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1679 transport_version(), Perspective::IS_CLIENT);
1680 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1681 session_.OnStreamFrame(data1);
1682 EXPECT_EQ(1, session_.num_incoming_streams_created());
1683
1684 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1685 session_.OnStreamFrame(data2);
1686 EXPECT_EQ(1, session_.num_incoming_streams_created());
1687}
1688
1689TEST_P(QuicSessionTestServer, PendingStreams) {
1690 if (connection_->transport_version() != QUIC_VERSION_99) {
1691 return;
1692 }
renjietange76b2da2019-05-13 14:50:23 -07001693 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001694
1695 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1696 transport_version(), Perspective::IS_CLIENT);
1697 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1698 session_.OnStreamFrame(data1);
1699 EXPECT_EQ(0, session_.num_incoming_streams_created());
1700
1701 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1702 session_.OnStreamFrame(data2);
1703 EXPECT_EQ(1, session_.num_incoming_streams_created());
1704}
1705
1706TEST_P(QuicSessionTestServer, RstPendingStreams) {
1707 if (connection_->transport_version() != QUIC_VERSION_99) {
1708 return;
1709 }
renjietange76b2da2019-05-13 14:50:23 -07001710 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001711
1712 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1713 transport_version(), Perspective::IS_CLIENT);
1714 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1715 session_.OnStreamFrame(data1);
1716 EXPECT_EQ(0, session_.num_incoming_streams_created());
1717
1718 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream()).Times(1);
1719 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1720 EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_RST_ACKNOWLEDGEMENT))
1721 .Times(1);
1722 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream_id,
1723 QUIC_ERROR_PROCESSING_STREAM, 12);
1724 session_.OnRstStream(rst1);
1725 EXPECT_EQ(0, session_.num_incoming_streams_created());
1726
1727 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1728 session_.OnStreamFrame(data2);
1729 EXPECT_EQ(0, session_.num_incoming_streams_created());
1730}
1731
1732TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
1733 // Verify that a draining stream (which has received a FIN but not consumed
1734 // it) does not count against the open quota (because it is closed from the
1735 // protocol point of view).
1736 if (transport_version() == QUIC_VERSION_99) {
fkastenholz3c4eabf2019-04-22 07:49:59 -07001737 // On v99, we will expect to see a MAX_STREAMS go out when there are not
QUICHE teama6ef0a62019-03-07 20:34:33 -05001738 // enough streams to create the next one.
1739 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1740 } else {
1741 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1742 }
1743 EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
1744 const QuicStreamId kMaxStreams = 5;
fkastenholzd3a1de92019-05-15 07:00:07 -07001745 if (transport_version() == QUIC_VERSION_99) {
1746 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1747 kMaxStreams);
1748 } else {
1749 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1750 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001751
1752 // Create kMaxStreams + 1 data streams, and mark them draining.
1753 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1754 const QuicStreamId kFinalStreamId =
1755 GetNthClientInitiatedBidirectionalId(2 * kMaxStreams + 1);
1756 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
1757 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
1758 QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT"));
1759 session_.OnStreamFrame(data1);
1760 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
1761 session_.StreamDraining(i);
1762 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1763 }
1764}
1765
1766class QuicSessionTestClient : public QuicSessionTestBase {
1767 protected:
1768 QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {}
1769};
1770
1771INSTANTIATE_TEST_SUITE_P(Tests,
1772 QuicSessionTestClient,
1773 ::testing::ValuesIn(AllSupportedVersions()));
1774
1775TEST_P(QuicSessionTestClient, AvailableBidirectionalStreamsClient) {
1776 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1777 GetNthServerInitiatedBidirectionalId(2)) != nullptr);
1778 // Smaller bidirectional streams should be available.
1779 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1780 &session_, GetNthServerInitiatedBidirectionalId(0)));
1781 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1782 &session_, GetNthServerInitiatedBidirectionalId(1)));
1783 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1784 GetNthServerInitiatedBidirectionalId(0)) != nullptr);
1785 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1786 GetNthServerInitiatedBidirectionalId(1)) != nullptr);
1787 // And 5 should be not available.
1788 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
1789 &session_, GetNthClientInitiatedBidirectionalId(1)));
1790}
1791
1792TEST_P(QuicSessionTestClient, AvailableUnidirectionalStreamsClient) {
1793 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1794 GetNthServerInitiatedUnidirectionalId(2)) != nullptr);
1795 // Smaller unidirectional streams should be available.
1796 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1797 &session_, GetNthServerInitiatedUnidirectionalId(0)));
1798 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1799 &session_, GetNthServerInitiatedUnidirectionalId(1)));
1800 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1801 GetNthServerInitiatedUnidirectionalId(0)) != nullptr);
1802 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1803 GetNthServerInitiatedUnidirectionalId(1)) != nullptr);
1804 // And 5 should be not available.
1805 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
1806 &session_, GetNthClientInitiatedUnidirectionalId(1)));
1807}
1808
1809TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
1810 // Verify that an incoming FIN is recorded in a stream object even if the read
1811 // side has been closed. This prevents an entry from being made in
1812 // locally_closed_streams_highest_offset_ (which will never be deleted).
1813 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1814 QuicStreamId stream_id = stream->id();
1815
1816 // Close the read side manually.
1817 QuicStreamPeer::CloseReadSide(stream);
1818
1819 // Receive a stream data frame with FIN.
1820 QuicStreamFrame frame(stream_id, true, 0, QuicStringPiece());
1821 session_.OnStreamFrame(frame);
1822 EXPECT_TRUE(stream->fin_received());
1823
1824 // Reset stream locally.
1825 EXPECT_CALL(*connection_, SendControlFrame(_));
1826 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1827 stream->Reset(QUIC_STREAM_CANCELLED);
1828 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1829
1830 EXPECT_TRUE(connection_->connected());
1831 EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
1832 EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
1833
1834 // The stream is not waiting for the arrival of the peer's final offset as it
1835 // was received with the FIN earlier.
1836 EXPECT_EQ(
1837 0u,
1838 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
1839}
1840
1841TEST_P(QuicSessionTestServer, ZombieStreams) {
1842 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1843 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
1844 EXPECT_TRUE(stream2->IsWaitingForAcks());
1845
1846 EXPECT_CALL(*connection_, SendControlFrame(_));
1847 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
1848 session_.CloseStream(stream2->id());
1849 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
1850 ASSERT_EQ(1u, session_.closed_streams()->size());
1851 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
1852 session_.OnStreamDoneWaitingForAcks(stream2->id());
1853 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
1854 EXPECT_EQ(1u, session_.closed_streams()->size());
1855 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
1856}
1857
1858TEST_P(QuicSessionTestServer, RstStreamReceivedAfterRstStreamSent) {
1859 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1860 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
1861 EXPECT_TRUE(stream2->IsWaitingForAcks());
1862
1863 EXPECT_CALL(*connection_, SendControlFrame(_));
1864 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
1865 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream()).Times(0);
1866 stream2->Reset(quic::QUIC_STREAM_CANCELLED);
1867
1868 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream2->id(),
1869 QUIC_ERROR_PROCESSING_STREAM, 0);
1870 if (transport_version() != QUIC_VERSION_99) {
1871 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream()).Times(1);
1872 }
1873 session_.OnRstStream(rst1);
1874}
1875
1876// Regression test of b/71548958.
1877TEST_P(QuicSessionTestServer, TestZombieStreams) {
1878 session_.set_writev_consumes_all_data(true);
1879
1880 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07001881 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001882 stream2->WriteOrBufferData(body, false, nullptr);
1883 EXPECT_TRUE(stream2->IsWaitingForAcks());
1884 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream2).size());
1885
1886 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream2->id(),
1887 QUIC_STREAM_CANCELLED, 1234);
1888 // Just for the RST_STREAM
1889 EXPECT_CALL(*connection_, SendControlFrame(_))
1890 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1891 if (transport_version() == QUIC_VERSION_99) {
1892 EXPECT_CALL(*connection_,
1893 OnStreamReset(stream2->id(), QUIC_STREAM_CANCELLED));
1894 } else {
1895 EXPECT_CALL(*connection_,
1896 OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT));
1897 }
1898 stream2->OnStreamReset(rst_frame);
1899
1900 if (transport_version() == QUIC_VERSION_99) {
1901 // The test is predicated on the stream being fully closed. For V99, the
1902 // RST_STREAM only does one side (the read side from the perspective of the
1903 // node receiving the RST_STREAM). This is needed to fully close the
1904 // stream and therefore fulfill all of the expects.
1905 QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
1906 QUIC_STREAM_CANCELLED);
1907 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
1908 }
1909 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
1910 ASSERT_EQ(1u, session_.closed_streams()->size());
1911 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
1912
1913 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1914 if (transport_version() == QUIC_VERSION_99) {
1915 // Once for the RST_STREAM, once for the STOP_SENDING
1916 EXPECT_CALL(*connection_, SendControlFrame(_))
1917 .Times(2)
1918 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
1919 } else {
1920 // Just for the RST_STREAM
1921 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1922 }
1923 EXPECT_CALL(*connection_,
1924 OnStreamReset(stream4->id(), QUIC_STREAM_CANCELLED));
1925 stream4->WriteOrBufferData(body, false, nullptr);
1926 // Note well: Reset() actually closes the stream in both directions. For
1927 // GOOGLE QUIC it sends a RST_STREAM (which does a 2-way close), for IETF
1928 // QUIC/V99 it sends both a RST_STREAM and a STOP_SENDING (each of which
1929 // closes in only one direction).
1930 stream4->Reset(QUIC_STREAM_CANCELLED);
1931 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
1932 EXPECT_EQ(2u, session_.closed_streams()->size());
1933}
1934
1935TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
1936 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
1937 InSequence s;
1938
1939 // Drive congestion control manually.
1940 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1941 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1942
1943 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1944 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1945 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1946
nharper46833c32019-05-15 21:33:05 -07001947 QuicStreamFrame frame1;
1948 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1949 frame1 = QuicStreamFrame(
1950 QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
1951 0, 1300);
1952 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001953 QuicStreamFrame frame2(stream2->id(), false, 0, 9);
1954 QuicStreamFrame frame3(stream4->id(), false, 0, 9);
1955
1956 // Lost data on cryption stream, streams 2 and 4.
1957 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
QUICHE teamea740082019-03-11 17:58:43 -07001958 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001959 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
1960 .WillOnce(Return(true));
1961 }
1962 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
1963 session_.OnFrameLost(QuicFrame(frame3));
QUICHE teamea740082019-03-11 17:58:43 -07001964 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001965 session_.OnFrameLost(QuicFrame(frame1));
1966 } else {
QUICHE team6987b4a2019-03-15 16:23:04 -07001967 QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001968 session_.OnFrameLost(QuicFrame(&crypto_frame));
1969 }
1970 session_.OnFrameLost(QuicFrame(frame2));
1971 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1972
1973 // Mark streams 2 and 4 write blocked.
1974 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1975 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1976
1977 // Lost data is retransmitted before new data, and retransmissions for crypto
1978 // stream go first.
1979 // Do not check congestion window when crypto stream has lost data.
1980 EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
QUICHE teamea740082019-03-11 17:58:43 -07001981 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001982 EXPECT_CALL(*crypto_stream, OnCanWrite());
1983 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
1984 .WillOnce(Return(false));
1985 }
1986 // Check congestion window for non crypto streams.
1987 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1988 EXPECT_CALL(*stream4, OnCanWrite());
1989 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(false));
1990 // Connection is blocked.
1991 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(false));
1992
1993 session_.OnCanWrite();
1994 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1995
1996 // Unblock connection.
1997 // Stream 2 retransmits lost data.
1998 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1999 EXPECT_CALL(*stream2, OnCanWrite());
2000 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2001 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2002 // Stream 2 sends new data.
2003 EXPECT_CALL(*stream2, OnCanWrite());
2004 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2005 EXPECT_CALL(*stream4, OnCanWrite());
2006 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2007
2008 session_.OnCanWrite();
2009 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2010}
2011
2012TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
2013 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2014 InSequence s;
2015
2016 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2017 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2018 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2019
2020 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2021 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2022 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2023
2024 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(true));
2025 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
2026 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2027 session_.OnFrameLost(QuicFrame(frame3));
2028 session_.OnFrameLost(QuicFrame(frame2));
2029 session_.OnFrameLost(QuicFrame(frame1));
2030
2031 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2032 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2033 session_.MarkConnectionLevelWriteBlocked(stream6->id());
2034
2035 // Reset stream 4 locally.
2036 EXPECT_CALL(*connection_, SendControlFrame(_));
2037 EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
2038 stream4->Reset(QUIC_STREAM_CANCELLED);
2039
2040 // Verify stream 4 is removed from streams with lost data list.
2041 EXPECT_CALL(*stream6, OnCanWrite());
2042 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
2043 EXPECT_CALL(*stream2, OnCanWrite());
2044 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2045 EXPECT_CALL(*connection_, SendControlFrame(_))
2046 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
2047 EXPECT_CALL(*stream2, OnCanWrite());
2048 EXPECT_CALL(*stream6, OnCanWrite());
2049 session_.OnCanWrite();
2050}
2051
2052TEST_P(QuicSessionTestServer, RetransmitFrames) {
2053 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2054 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2055 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2056 InSequence s;
2057
2058 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2059 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2060 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2061 EXPECT_CALL(*connection_, SendControlFrame(_))
2062 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
2063 session_.SendWindowUpdate(stream2->id(), 9);
2064
2065 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2066 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2067 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2068 QuicWindowUpdateFrame window_update(1, stream2->id(), 9);
2069 QuicFrames frames;
2070 frames.push_back(QuicFrame(frame1));
2071 frames.push_back(QuicFrame(&window_update));
2072 frames.push_back(QuicFrame(frame2));
2073 frames.push_back(QuicFrame(frame3));
2074 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2075
2076 EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2077 EXPECT_CALL(*connection_, SendControlFrame(_))
2078 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
2079 EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2080 EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2081 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2082 session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
2083}
2084
2085// Regression test of b/110082001.
2086TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) {
2087 // This test mimics the scenario when a dynamic stream retransmits lost data
2088 // and causes connection close.
2089 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2090 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2091 QuicStreamFrame frame(stream->id(), false, 0, 9);
2092
2093 EXPECT_CALL(*stream, HasPendingRetransmission())
2094 .Times(2)
2095 .WillOnce(Return(true))
2096 .WillOnce(Return(false));
2097 session_.OnFrameLost(QuicFrame(frame));
2098 // Retransmit stream data causes connection close. Stream has not sent fin
2099 // yet, so an RST is sent.
2100 EXPECT_CALL(*stream, OnCanWrite())
2101 .WillOnce(Invoke(stream, &QuicStream::OnClose));
2102 if (transport_version() == QUIC_VERSION_99) {
2103 // Once for the RST_STREAM, once for the STOP_SENDING
2104 EXPECT_CALL(*connection_, SendControlFrame(_))
2105 .Times(2)
2106 .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
2107 } else {
2108 // Just for the RST_STREAM
2109 EXPECT_CALL(*connection_, SendControlFrame(_))
2110 .WillOnce(Invoke(&session_, &TestSession::SaveFrame));
2111 }
2112 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
2113 session_.OnCanWrite();
2114}
2115
2116TEST_P(QuicSessionTestServer, SendMessage) {
2117 // Cannot send message when encryption is not established.
2118 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
2119 quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
2120 EXPECT_EQ(MessageResult(MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0),
2121 session_.SendMessage(
2122 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2123 "", &storage)));
2124
2125 // Finish handshake.
2126 CryptoHandshakeMessage handshake_message;
2127 session_.GetMutableCryptoStream()->OnHandshakeMessage(handshake_message);
2128 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
2129
2130 QuicStringPiece message;
2131 EXPECT_CALL(*connection_, SendMessage(1, _))
2132 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2133 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
2134 session_.SendMessage(
2135 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2136 message, &storage)));
2137 // Verify message_id increases.
2138 EXPECT_CALL(*connection_, SendMessage(2, _))
2139 .WillOnce(Return(MESSAGE_STATUS_TOO_LARGE));
2140 EXPECT_EQ(MessageResult(MESSAGE_STATUS_TOO_LARGE, 0),
2141 session_.SendMessage(
2142 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2143 message, &storage)));
2144 // Verify unsent message does not consume a message_id.
2145 EXPECT_CALL(*connection_, SendMessage(2, _))
2146 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2147 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 2),
2148 session_.SendMessage(
2149 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2150 message, &storage)));
2151
2152 QuicMessageFrame frame(1);
2153 QuicMessageFrame frame2(2);
2154 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2155 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2156
2157 // Lost message 2.
2158 session_.OnMessageLost(2);
2159 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2160
2161 // message 1 gets acked.
2162 session_.OnMessageAcked(1);
2163 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2164}
2165
2166// Regression test of b/115323618.
2167TEST_P(QuicSessionTestServer, LocallyResetZombieStreams) {
2168 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2169
2170 session_.set_writev_consumes_all_data(true);
2171 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07002172 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002173 stream2->CloseReadSide();
2174 stream2->WriteOrBufferData(body, true, nullptr);
2175 EXPECT_TRUE(stream2->IsWaitingForAcks());
2176 // Verify stream2 is a zombie streams.
2177 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2178
2179 QuicStreamFrame frame(stream2->id(), true, 0, 100);
2180 EXPECT_CALL(*stream2, HasPendingRetransmission())
2181 .WillRepeatedly(Return(true));
2182 session_.OnFrameLost(QuicFrame(frame));
2183
2184 // Reset stream2 locally.
2185 EXPECT_CALL(*connection_, SendControlFrame(_))
2186 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
2187 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2188 stream2->Reset(QUIC_STREAM_CANCELLED);
2189
2190 // Verify stream 2 gets closed.
2191 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2192 EXPECT_TRUE(session_.IsClosedStream(stream2->id()));
2193 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
2194 session_.OnCanWrite();
2195}
2196
2197TEST_P(QuicSessionTestServer, CleanUpClosedStreamsAlarm) {
2198 EXPECT_FALSE(
2199 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2200
2201 session_.set_writev_consumes_all_data(true);
2202 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2203 EXPECT_FALSE(stream2->IsWaitingForAcks());
2204
2205 EXPECT_CALL(*connection_, SendControlFrame(_));
2206 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2207 session_.CloseStream(stream2->id());
2208 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2209 EXPECT_EQ(1u, session_.closed_streams()->size());
2210 EXPECT_TRUE(
2211 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2212
2213 alarm_factory_.FireAlarm(
2214 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_));
2215 EXPECT_TRUE(session_.closed_streams()->empty());
2216}
2217
2218TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
2219 session_.set_writev_consumes_all_data(true);
2220 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2221 &session_, WRITE_UNIDIRECTIONAL);
2222 session_.ActivateStream(QuicWrapUnique(stream4));
vasilvvc48c8712019-03-11 13:38:16 -07002223 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002224 stream4->WriteOrBufferData(body, false, nullptr);
2225 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2226 stream4->WriteOrBufferData(body, true, nullptr);
2227 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2228}
2229
2230TEST_P(QuicSessionTestServer, ReceivedDataOnWriteUnidirectionalStream) {
2231 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2232 &session_, WRITE_UNIDIRECTIONAL);
2233 session_.ActivateStream(QuicWrapUnique(stream4));
2234
2235 EXPECT_CALL(
2236 *connection_,
2237 CloseConnection(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM, _, _))
2238 .Times(1);
2239 QuicStreamFrame stream_frame(GetNthServerInitiatedUnidirectionalId(1), false,
2240 0, 2);
2241 session_.OnStreamFrame(stream_frame);
2242}
2243
2244TEST_P(QuicSessionTestServer, ReadUnidirectionalStream) {
2245 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2246 &session_, READ_UNIDIRECTIONAL);
2247 session_.ActivateStream(QuicWrapUnique(stream4));
2248 EXPECT_FALSE(stream4->IsWaitingForAcks());
2249 // Discard all incoming data.
2250 stream4->StopReading();
2251
vasilvvc48c8712019-03-11 13:38:16 -07002252 std::string data(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002253 QuicStreamFrame stream_frame(GetNthClientInitiatedUnidirectionalId(1), false,
2254 0, data);
2255 stream4->OnStreamFrame(stream_frame);
2256 EXPECT_TRUE(session_.closed_streams()->empty());
2257
2258 QuicStreamFrame stream_frame2(GetNthClientInitiatedUnidirectionalId(1), true,
2259 100, data);
2260 stream4->OnStreamFrame(stream_frame2);
2261 EXPECT_EQ(1u, session_.closed_streams()->size());
2262}
2263
2264TEST_P(QuicSessionTestServer, WriteOrBufferDataOnReadUnidirectionalStream) {
2265 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2266 &session_, READ_UNIDIRECTIONAL);
2267 session_.ActivateStream(QuicWrapUnique(stream4));
2268
2269 EXPECT_CALL(*connection_,
2270 CloseConnection(
2271 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2272 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002273 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002274 stream4->WriteOrBufferData(body, false, nullptr);
2275}
2276
2277TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
2278 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2279 &session_, READ_UNIDIRECTIONAL);
2280 session_.ActivateStream(QuicWrapUnique(stream4));
2281
2282 EXPECT_CALL(*connection_,
2283 CloseConnection(
2284 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2285 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002286 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002287 struct iovec iov = {const_cast<char*>(body.data()), body.length()};
2288 QuicMemSliceStorage storage(
2289 &iov, 1, session_.connection()->helper()->GetStreamSendBufferAllocator(),
2290 1024);
2291 stream4->WriteMemSlices(storage.ToSpan(), false);
2292}
2293
2294TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
2295 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2296 &session_, READ_UNIDIRECTIONAL);
2297 session_.ActivateStream(QuicWrapUnique(stream4));
2298
2299 EXPECT_CALL(*connection_,
2300 CloseConnection(
2301 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2302 .Times(1);
2303 char data[1024];
2304 std::vector<std::pair<char*, size_t>> buffers;
2305 buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
2306 buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
2307 QuicTestMemSliceVector vector(buffers);
2308 stream4->WriteMemSlices(vector.span(), false);
2309}
2310
2311// Test code that tests that an incoming stream frame with a new (not previously
2312// seen) stream id is acceptable. The ID must not be larger than has been
2313// advertised. It may be equal to what has been advertised. These tests
2314// invoke QuicStreamIdManager::MaybeIncreaseLargestPeerStreamId by calling
2315// QuicSession::OnStreamFrame in order to check that all the steps are connected
2316// properly and that nothing in the call path interferes with the check.
2317// First test make sure that streams with ids below the limit are accepted.
2318TEST_P(QuicSessionTestServer, NewStreamIdBelowLimit) {
2319 if (transport_version() != QUIC_VERSION_99) {
2320 // Applicable only to V99
2321 return;
2322 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002323 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002324 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002325 ->advertised_max_allowed_incoming_bidirectional_streams() -
2326 1,
2327 Perspective::IS_CLIENT,
2328 /*bidirectional=*/true);
2329
QUICHE teama6ef0a62019-03-07 20:34:33 -05002330 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2331 "Random String");
2332 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2333 session_.OnStreamFrame(bidirectional_stream_frame);
2334
fkastenholz3c4eabf2019-04-22 07:49:59 -07002335 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002336 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002337 ->advertised_max_allowed_incoming_unidirectional_streams() -
2338 1,
2339 Perspective::IS_CLIENT,
2340 /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002341 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2342 0, "Random String");
2343 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2344 session_.OnStreamFrame(unidirectional_stream_frame);
2345}
2346
2347// Accept a stream with an ID that equals the limit.
2348TEST_P(QuicSessionTestServer, NewStreamIdAtLimit) {
2349 if (transport_version() != QUIC_VERSION_99) {
2350 // Applicable only to V99
2351 return;
2352 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002353 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002354 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002355 ->advertised_max_allowed_incoming_bidirectional_streams(),
2356 Perspective::IS_CLIENT, /*bidirectional=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002357 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2358 "Random String");
2359 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2360 session_.OnStreamFrame(bidirectional_stream_frame);
2361
fkastenholz3c4eabf2019-04-22 07:49:59 -07002362 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002363 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002364 ->advertised_max_allowed_incoming_unidirectional_streams(),
2365 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002366 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2367 0, "Random String");
2368 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2369 session_.OnStreamFrame(unidirectional_stream_frame);
2370}
2371
2372// Close the connection if the id exceeds the limit.
2373TEST_P(QuicSessionTestServer, NewStreamIdAboveLimit) {
2374 if (transport_version() != QUIC_VERSION_99) {
2375 // Applicable only to V99
2376 return;
2377 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002378 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002379 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002380 ->advertised_max_allowed_incoming_bidirectional_streams() +
2381 1,
2382 Perspective::IS_CLIENT, /*bidirectional=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002383 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2384 "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002385 EXPECT_CALL(
2386 *connection_,
2387 CloseConnection(QUIC_INVALID_STREAM_ID,
nharper46833c32019-05-15 21:33:05 -07002388 "Stream id 404 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002389 session_.OnStreamFrame(bidirectional_stream_frame);
2390
fkastenholz3c4eabf2019-04-22 07:49:59 -07002391 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002392 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002393 ->advertised_max_allowed_incoming_unidirectional_streams() +
2394 1,
2395 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002396 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2397 0, "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002398 EXPECT_CALL(
2399 *connection_,
2400 CloseConnection(QUIC_INVALID_STREAM_ID,
2401 "Stream id 402 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002402 session_.OnStreamFrame(unidirectional_stream_frame);
2403}
2404
2405// Check that the OnStopSendingFrame upcall handles bad input properly
2406// First test checks that invalid stream ids are handled.
2407TEST_P(QuicSessionTestServer, OnStopSendingInputInvalidStreamId) {
2408 if (transport_version() != QUIC_VERSION_99) {
2409 // Applicable only to V99
2410 return;
2411 }
2412 // Check that "invalid" stream ids are rejected.
2413 // Note that the notion of an invalid stream id is Google-specific.
2414 QuicStopSendingFrame frame(1, -1, 123);
2415 EXPECT_CALL(
2416 *connection_,
2417 CloseConnection(QUIC_INVALID_STREAM_ID,
2418 "Received STOP_SENDING for an invalid stream", _));
2419 EXPECT_FALSE(session_.OnStopSendingFrame(frame));
2420}
2421
2422// Second test, streams in the static stream map are not subject to
2423// STOP_SENDING; it's ignored.
2424TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
2425 if (transport_version() != QUIC_VERSION_99) {
2426 // Applicable only to V99
2427 return;
2428 }
nharper46833c32019-05-15 21:33:05 -07002429 QuicStreamId stream_id = 0;
2430 std::unique_ptr<TestStream> fake_static_stream = QuicMakeUnique<TestStream>(
2431 stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
2432 if (GetQuicReloadableFlag(quic_eliminate_static_stream_map_2)) {
2433 QuicSessionPeer::RegisterStaticStreamNew(&session_,
2434 std::move(fake_static_stream));
2435 } else {
2436 QuicSessionPeer::RegisterStaticStream(&session_, stream_id,
2437 fake_static_stream.get());
2438 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002439 // Check that a stream id in the static stream map is ignored.
2440 // Note that the notion of a static stream is Google-specific.
nharper46833c32019-05-15 21:33:05 -07002441 QuicStopSendingFrame frame(1, stream_id, 123);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002442 EXPECT_CALL(*connection_,
2443 CloseConnection(QUIC_INVALID_STREAM_ID,
2444 "Received STOP_SENDING for a static stream", _));
2445 EXPECT_FALSE(session_.OnStopSendingFrame(frame));
2446}
2447
2448// Third test, if stream id specifies a closed stream:
2449// return true and do not close the connection.
2450TEST_P(QuicSessionTestServer, OnStopSendingInputClosedStream) {
2451 if (transport_version() != QUIC_VERSION_99) {
2452 // Applicable only to V99
2453 return;
2454 }
2455
2456 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2457 QuicStreamId stream_id = stream->id();
2458 // Expect these as side effect of the close operations.
2459 EXPECT_CALL(*connection_, SendControlFrame(_));
2460 EXPECT_CALL(*connection_, OnStreamReset(_, _));
2461 stream->CloseWriteSide();
2462 stream->CloseReadSide();
2463 QuicStopSendingFrame frame(1, stream_id, 123);
2464 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2465 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
2466}
2467
2468// Fourth test, if stream id specifies a nonexistent stream, return false and
2469// close the connection
2470TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentStream) {
2471 if (transport_version() != QUIC_VERSION_99) {
2472 // Applicable only to V99
2473 return;
2474 }
2475
2476 QuicStopSendingFrame frame(1, GetNthServerInitiatedBidirectionalId(123456),
2477 123);
2478 EXPECT_CALL(
2479 *connection_,
2480 CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
2481 "Received STOP_SENDING for a non-existent stream", _))
2482 .Times(1);
2483 EXPECT_FALSE(session_.OnStopSendingFrame(frame));
2484}
2485
2486// For a valid stream, ensure that all works
2487TEST_P(QuicSessionTestServer, OnStopSendingInputValidStream) {
2488 if (transport_version() != QUIC_VERSION_99) {
2489 // Applicable only to V99
2490 return;
2491 }
2492
2493 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2494
2495 // Ensure that the stream starts out open in both directions.
bncc7d9e0c2019-04-16 10:22:15 -07002496 EXPECT_FALSE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002497 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
2498
2499 QuicStreamId stream_id = stream->id();
2500 QuicStopSendingFrame frame(1, stream_id, 123);
2501 EXPECT_CALL(*stream, OnStopSending(123));
2502 // Expect a reset to come back out.
2503 EXPECT_CALL(*connection_, SendControlFrame(_));
2504 EXPECT_CALL(
2505 *connection_,
2506 OnStreamReset(stream_id, static_cast<QuicRstStreamErrorCode>(123)));
2507 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
2508 // When the STOP_SENDING is received, the node generates a RST_STREAM,
2509 // which closes the stream in the write direction. Ensure this.
2510 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
bncc7d9e0c2019-04-16 10:22:15 -07002511 EXPECT_TRUE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002512}
2513
2514} // namespace
2515} // namespace test
2516} // namespace quic