blob: a75d9485240c997b0cf2ced457e9fb927c045a71 [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);
renjietangd1d00852019-09-06 10:43:12 -070072 session()->config()->ToHandshakeMessage(&msg,
73 session()->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
renjietangbaea59c2019-05-29 15:08:14 -0700120 TestStream(PendingStream* pending, StreamType type)
121 : QuicStream(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(),
renjietang216dc012019-08-27 11:28:27 -0700145 CurrentSupportedVersions(),
146 /*num_expected_unidirectional_static_streams = */ 0),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147 crypto_stream_(this),
148 writev_consumes_all_data_(false),
renjietange76b2da2019-05-13 14:50:23 -0700149 uses_pending_streams_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500150 num_incoming_streams_created_(0) {
151 Initialize();
152 this->connection()->SetEncrypter(
153 ENCRYPTION_FORWARD_SECURE,
vasilvv0fc587f2019-09-06 13:33:08 -0700154 std::make_unique<NullEncrypter>(connection->perspective()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155 }
156
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700157 ~TestSession() override {
158 EXPECT_TRUE(is_configured());
159 delete connection();
160 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500161
162 TestCryptoStream* GetMutableCryptoStream() override {
163 return &crypto_stream_;
164 }
165
166 const TestCryptoStream* GetCryptoStream() const override {
167 return &crypto_stream_;
168 }
169
170 TestStream* CreateOutgoingBidirectionalStream() {
171 QuicStreamId id = GetNextOutgoingBidirectionalStreamId();
172 if (id ==
173 QuicUtils::GetInvalidStreamId(connection()->transport_version())) {
174 return nullptr;
175 }
176 TestStream* stream = new TestStream(id, this, BIDIRECTIONAL);
177 ActivateStream(QuicWrapUnique(stream));
178 return stream;
179 }
180
181 TestStream* CreateOutgoingUnidirectionalStream() {
182 TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
183 this, WRITE_UNIDIRECTIONAL);
184 ActivateStream(QuicWrapUnique(stream));
185 return stream;
186 }
187
188 TestStream* CreateIncomingStream(QuicStreamId id) override {
189 // Enforce the limit on the number of open streams.
190 if (GetNumOpenIncomingStreams() + 1 >
191 max_open_incoming_bidirectional_streams() &&
fkastenholz305e1732019-06-18 05:01:22 -0700192 !VersionHasIetfQuicFrames(connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 // No need to do this test for version 99; it's done by
renjietang880d2432019-07-16 13:14:37 -0700194 // QuicSession::GetOrCreateStream.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 connection()->CloseConnection(
196 QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
197 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
198 return nullptr;
199 }
200
201 TestStream* stream =
202 new TestStream(id, this,
203 DetermineStreamType(
204 id, connection()->transport_version(), perspective(),
205 /*is_incoming=*/true, BIDIRECTIONAL));
206 ActivateStream(QuicWrapUnique(stream));
207 ++num_incoming_streams_created_;
208 return stream;
209 }
210
renjietangbaea59c2019-05-29 15:08:14 -0700211 TestStream* CreateIncomingStream(PendingStream* pending) override {
212 QuicStreamId id = pending->id();
213 TestStream* stream = new TestStream(
214 pending, DetermineStreamType(id, connection()->transport_version(),
215 perspective(),
216 /*is_incoming=*/true, BIDIRECTIONAL));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500217 ActivateStream(QuicWrapUnique(stream));
218 ++num_incoming_streams_created_;
219 return stream;
220 }
221
renjietange76b2da2019-05-13 14:50:23 -0700222 // QuicSession doesn't do anything in this method. So it's overridden here to
223 // test that the session handles pending streams correctly in terms of
224 // receiving stream frames.
renjietangbb1c4892019-05-24 15:58:44 -0700225 bool ProcessPendingStream(PendingStream* pending) override {
renjietange76b2da2019-05-13 14:50:23 -0700226 struct iovec iov;
227 if (pending->sequencer()->GetReadableRegion(&iov)) {
228 // Create TestStream once the first byte is received.
renjietangbaea59c2019-05-29 15:08:14 -0700229 CreateIncomingStream(pending);
renjietangbb1c4892019-05-24 15:58:44 -0700230 return true;
renjietange76b2da2019-05-13 14:50:23 -0700231 }
renjietangbb1c4892019-05-24 15:58:44 -0700232 return false;
renjietange76b2da2019-05-13 14:50:23 -0700233 }
234
QUICHE teama6ef0a62019-03-07 20:34:33 -0500235 bool IsClosedStream(QuicStreamId id) {
236 return QuicSession::IsClosedStream(id);
237 }
238
renjietang880d2432019-07-16 13:14:37 -0700239 QuicStream* GetOrCreateStream(QuicStreamId stream_id) {
240 return QuicSession::GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 }
242
243 bool ShouldKeepConnectionAlive() const override {
renjietang17e29932019-08-08 10:04:31 -0700244 return GetNumActiveStreams() > 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500245 }
246
247 QuicConsumedData WritevData(QuicStream* stream,
248 QuicStreamId id,
249 size_t write_length,
250 QuicStreamOffset offset,
251 StreamSendingState state) override {
252 bool fin = state != NO_FIN;
253 QuicConsumedData consumed(write_length, fin);
254 if (!writev_consumes_all_data_) {
255 consumed =
256 QuicSession::WritevData(stream, id, write_length, offset, state);
257 }
258 if (fin && consumed.fin_consumed) {
259 stream->set_fin_sent(true);
260 }
261 QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
262 id, consumed.bytes_consumed);
263 return consumed;
264 }
265
fkastenholz8556dc22019-07-18 12:42:38 -0700266 MOCK_METHOD1(OnCanCreateNewOutgoingStream, void(bool unidirectional));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267
268 void set_writev_consumes_all_data(bool val) {
269 writev_consumes_all_data_ = val;
270 }
271
272 QuicConsumedData SendStreamData(QuicStream* stream) {
273 struct iovec iov;
nharper46833c32019-05-15 21:33:05 -0700274 if (!QuicUtils::IsCryptoStreamId(connection()->transport_version(),
275 stream->id()) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500276 this->connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
277 this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
278 }
279 MakeIOVector("not empty", &iov);
280 QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
281 QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
282 QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
283 consumed.bytes_consumed);
284 return consumed;
285 }
286
QUICHE teama6ef0a62019-03-07 20:34:33 -0500287 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);
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700336
337 QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
338 session_.config(), kDefaultMaxStreamsPerConnection);
339 QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
340 session_.config(), kDefaultMaxStreamsPerConnection);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500341 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700342 session_.OnConfigNegotiated();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
344 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
345 .Times(testing::AnyNumber());
346 }
347
348 void CheckClosedStreams() {
QUICHE teamdc41bf12019-03-20 12:58:42 -0700349 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
350 connection_->transport_version(), Perspective::IS_CLIENT);
351 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
352 first_stream_id =
353 QuicUtils::GetCryptoStreamId(connection_->transport_version());
354 }
355 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500356 if (!QuicContainsKey(closed_streams_, i)) {
357 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
358 } else {
359 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
360 }
361 }
362 }
363
364 void CloseStream(QuicStreamId id) {
renjietangd1d00852019-09-06 10:43:12 -0700365 if (VersionHasIetfQuicFrames(session_.transport_version()) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500366 QuicUtils::GetStreamType(id, session_.perspective(),
367 session_.IsIncomingStream(id)) ==
368 READ_UNIDIRECTIONAL) {
369 // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
370 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
371 EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
372 } else {
373 // Verify reset IS sent for BIDIRECTIONAL streams.
renjietangd1d00852019-09-06 10:43:12 -0700374 if (VersionHasIetfQuicFrames(session_.transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500375 // Once for the RST_STREAM, Once for the STOP_SENDING
376 EXPECT_CALL(*connection_, SendControlFrame(_))
377 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -0700378 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500379 } else {
380 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -0700381 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500382 }
383 EXPECT_CALL(*connection_, OnStreamReset(id, _));
384 }
385 session_.CloseStream(id);
386 closed_streams_.insert(id);
387 }
388
389 QuicTransportVersion transport_version() const {
390 return connection_->transport_version();
391 }
392
393 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
394 return QuicUtils::GetFirstBidirectionalStreamId(
395 connection_->transport_version(), Perspective::IS_CLIENT) +
396 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
397 }
398
399 QuicStreamId GetNthClientInitiatedUnidirectionalId(int n) {
400 return QuicUtils::GetFirstUnidirectionalStreamId(
401 connection_->transport_version(), Perspective::IS_CLIENT) +
402 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
403 }
404
405 QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
406 return QuicUtils::GetFirstBidirectionalStreamId(
407 connection_->transport_version(), Perspective::IS_SERVER) +
408 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
409 }
410
411 QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
412 return QuicUtils::GetFirstUnidirectionalStreamId(
413 connection_->transport_version(), Perspective::IS_SERVER) +
414 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
415 }
416
fkastenholz3c4eabf2019-04-22 07:49:59 -0700417 QuicStreamId StreamCountToId(QuicStreamCount stream_count,
418 Perspective perspective,
419 bool bidirectional) {
420 // Calculate and build up stream ID rather than use
421 // GetFirst... because tests that rely on this method
422 // needs to do the stream count where #1 is 0/1/2/3, and not
423 // take into account that stream 0 is special.
424 QuicStreamId id =
fkastenholz305e1732019-06-18 05:01:22 -0700425 ((stream_count - 1) * QuicUtils::StreamIdDelta(transport_version()));
fkastenholz3c4eabf2019-04-22 07:49:59 -0700426 if (!bidirectional) {
427 id |= 0x2;
428 }
429 if (perspective == Perspective::IS_SERVER) {
430 id |= 0x1;
431 }
432 return id;
433 }
434
QUICHE teama6ef0a62019-03-07 20:34:33 -0500435 MockQuicConnectionHelper helper_;
436 MockAlarmFactory alarm_factory_;
437 NiceMock<MockQuicSessionVisitor> session_visitor_;
438 StrictMock<MockQuicConnection>* connection_;
439 TestSession session_;
440 std::set<QuicStreamId> closed_streams_;
441};
442
443class QuicSessionTestServer : public QuicSessionTestBase {
444 public:
445 // CheckMultiPathResponse validates that a written packet
446 // contains both expected path responses.
447 WriteResult CheckMultiPathResponse(const char* buffer,
448 size_t buf_len,
dschinazi17d42422019-06-18 16:35:07 -0700449 const QuicIpAddress& /*self_address*/,
450 const QuicSocketAddress& /*peer_address*/,
451 PerPacketOptions* /*options*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500452 QuicEncryptedPacket packet(buffer, buf_len);
453 {
454 InSequence s;
455 EXPECT_CALL(framer_visitor_, OnPacket());
456 EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
457 EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
458 EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
459 EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
460 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
461 .WillOnce(
462 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
463 EXPECT_EQ(path_frame_buffer1_, frame.data_buffer);
464 return true;
465 })));
466 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
467 .WillOnce(
468 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
469 EXPECT_EQ(path_frame_buffer2_, frame.data_buffer);
470 return true;
471 })));
472 EXPECT_CALL(framer_visitor_, OnPacketComplete());
473 }
474 client_framer_.ProcessPacket(packet);
475 return WriteResult(WRITE_STATUS_OK, 0);
476 }
477
478 protected:
479 QuicSessionTestServer()
480 : QuicSessionTestBase(Perspective::IS_SERVER),
481 path_frame_buffer1_({0, 1, 2, 3, 4, 5, 6, 7}),
482 path_frame_buffer2_({8, 9, 10, 11, 12, 13, 14, 15}),
483 client_framer_(SupportedVersions(GetParam()),
484 QuicTime::Zero(),
485 Perspective::IS_CLIENT,
486 kQuicDefaultConnectionIdLength) {
487 client_framer_.set_visitor(&framer_visitor_);
488 }
489
490 QuicPathFrameBuffer path_frame_buffer1_;
491 QuicPathFrameBuffer path_frame_buffer2_;
492 StrictMock<MockFramerVisitor> framer_visitor_;
493 // Framer used to process packets sent by server.
494 QuicFramer client_framer_;
495};
496
497INSTANTIATE_TEST_SUITE_P(Tests,
498 QuicSessionTestServer,
499 ::testing::ValuesIn(AllSupportedVersions()));
500
501TEST_P(QuicSessionTestServer, PeerAddress) {
502 EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
503 session_.peer_address());
504}
505
506TEST_P(QuicSessionTestServer, SelfAddress) {
507 EXPECT_TRUE(session_.self_address().IsInitialized());
508}
509
510TEST_P(QuicSessionTestServer, DontCallOnWriteBlockedForDisconnectedConnection) {
511 EXPECT_CALL(*connection_, CloseConnection(_, _, _))
512 .WillOnce(
513 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
514 connection_->CloseConnection(QUIC_NO_ERROR, "Everything is fine.",
515 ConnectionCloseBehavior::SILENT_CLOSE);
516 ASSERT_FALSE(connection_->connected());
517
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700518 EXPECT_CALL(session_visitor_, OnWriteBlocked(_)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500519 session_.OnWriteBlocked();
520}
521
522TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
523 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
524 CryptoHandshakeMessage message;
525 session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
526 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
527}
528
529TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
530 // Ensure that no streams are initially closed.
QUICHE teamdc41bf12019-03-20 12:58:42 -0700531 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
532 connection_->transport_version(), Perspective::IS_CLIENT);
533 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
534 first_stream_id =
535 QuicUtils::GetCryptoStreamId(connection_->transport_version());
536 }
537 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500538 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
539 }
540}
541
542TEST_P(QuicSessionTestServer, AvailableBidirectionalStreams) {
renjietang880d2432019-07-16 13:14:37 -0700543 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500544 GetNthClientInitiatedBidirectionalId(3)) != nullptr);
545 // Smaller bidirectional streams should be available.
546 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
547 &session_, GetNthClientInitiatedBidirectionalId(1)));
548 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
549 &session_, GetNthClientInitiatedBidirectionalId(2)));
renjietang880d2432019-07-16 13:14:37 -0700550 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500551 GetNthClientInitiatedBidirectionalId(2)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -0700552 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500553 GetNthClientInitiatedBidirectionalId(1)) != nullptr);
554}
555
556TEST_P(QuicSessionTestServer, AvailableUnidirectionalStreams) {
renjietang880d2432019-07-16 13:14:37 -0700557 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500558 GetNthClientInitiatedUnidirectionalId(3)) != nullptr);
559 // Smaller unidirectional streams should be available.
560 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
561 &session_, GetNthClientInitiatedUnidirectionalId(1)));
562 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
563 &session_, GetNthClientInitiatedUnidirectionalId(2)));
renjietang880d2432019-07-16 13:14:37 -0700564 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500565 GetNthClientInitiatedUnidirectionalId(2)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -0700566 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500567 GetNthClientInitiatedUnidirectionalId(1)) != nullptr);
568}
569
570TEST_P(QuicSessionTestServer, MaxAvailableBidirectionalStreams) {
fkastenholz305e1732019-06-18 05:01:22 -0700571 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500572 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams(),
573 session_.MaxAvailableBidirectionalStreams());
574 } else {
575 // The protocol specification requires that there can be at least 10 times
576 // as many available streams as the connection's maximum open streams.
577 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams() *
578 kMaxAvailableStreamsMultiplier,
579 session_.MaxAvailableBidirectionalStreams());
580 }
581}
582
583TEST_P(QuicSessionTestServer, MaxAvailableUnidirectionalStreams) {
fkastenholz305e1732019-06-18 05:01:22 -0700584 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500585 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams(),
586 session_.MaxAvailableUnidirectionalStreams());
587 } else {
588 // The protocol specification requires that there can be at least 10 times
589 // as many available streams as the connection's maximum open streams.
590 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams() *
591 kMaxAvailableStreamsMultiplier,
592 session_.MaxAvailableUnidirectionalStreams());
593 }
594}
595
596TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamLocallyCreated) {
597 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
598 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id());
599 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
600 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(1), stream4->id());
601
602 CheckClosedStreams();
603 CloseStream(GetNthServerInitiatedBidirectionalId(0));
604 CheckClosedStreams();
605 CloseStream(GetNthServerInitiatedBidirectionalId(1));
606 CheckClosedStreams();
607}
608
609TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamLocallyCreated) {
610 TestStream* stream2 = session_.CreateOutgoingUnidirectionalStream();
611 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(0), stream2->id());
612 TestStream* stream4 = session_.CreateOutgoingUnidirectionalStream();
613 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(1), stream4->id());
614
615 CheckClosedStreams();
616 CloseStream(GetNthServerInitiatedUnidirectionalId(0));
617 CheckClosedStreams();
618 CloseStream(GetNthServerInitiatedUnidirectionalId(1));
619 CheckClosedStreams();
620}
621
622TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamPeerCreated) {
623 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
624 QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
renjietang880d2432019-07-16 13:14:37 -0700625 session_.GetOrCreateStream(stream_id1);
626 session_.GetOrCreateStream(stream_id2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500627
628 CheckClosedStreams();
629 CloseStream(stream_id1);
630 CheckClosedStreams();
631 CloseStream(stream_id2);
632 // Create a stream, and make another available.
renjietang880d2432019-07-16 13:14:37 -0700633 QuicStream* stream3 = session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500634 stream_id2 +
635 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
636 CheckClosedStreams();
637 // Close one, but make sure the other is still not closed
638 CloseStream(stream3->id());
639 CheckClosedStreams();
640}
641
642TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamPeerCreated) {
643 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
644 QuicStreamId stream_id2 = GetNthClientInitiatedUnidirectionalId(1);
renjietang880d2432019-07-16 13:14:37 -0700645 session_.GetOrCreateStream(stream_id1);
646 session_.GetOrCreateStream(stream_id2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500647
648 CheckClosedStreams();
649 CloseStream(stream_id1);
650 CheckClosedStreams();
651 CloseStream(stream_id2);
652 // Create a stream, and make another available.
renjietang880d2432019-07-16 13:14:37 -0700653 QuicStream* stream3 = session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500654 stream_id2 +
655 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
656 CheckClosedStreams();
657 // Close one, but make sure the other is still not closed
658 CloseStream(stream3->id());
659 CheckClosedStreams();
660}
661
662TEST_P(QuicSessionTestServer, MaximumAvailableOpenedBidirectionalStreams) {
663 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700664 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500665 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700666 EXPECT_NE(nullptr,
667 session_.GetOrCreateStream(GetNthClientInitiatedBidirectionalId(
668 session_.max_open_incoming_bidirectional_streams() - 1)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500669}
670
671TEST_P(QuicSessionTestServer, MaximumAvailableOpenedUnidirectionalStreams) {
672 QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700673 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500674 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700675 EXPECT_NE(nullptr,
676 session_.GetOrCreateStream(GetNthClientInitiatedUnidirectionalId(
677 session_.max_open_incoming_unidirectional_streams() - 1)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500678}
679
680TEST_P(QuicSessionTestServer, TooManyAvailableBidirectionalStreams) {
681 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
682 QuicStreamId stream_id2;
renjietang880d2432019-07-16 13:14:37 -0700683 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500684 // A stream ID which is too large to create.
685 stream_id2 = GetNthClientInitiatedBidirectionalId(
686 session_.MaxAvailableBidirectionalStreams() + 2);
fkastenholz305e1732019-06-18 05:01:22 -0700687 if (VersionHasIetfQuicFrames(transport_version())) {
688 // IETF QUIC terminates the connection with invalid stream id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500689 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 }
renjietang880d2432019-07-16 13:14:37 -0700696 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500697}
698
699TEST_P(QuicSessionTestServer, TooManyAvailableUnidirectionalStreams) {
700 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
701 QuicStreamId stream_id2;
renjietang880d2432019-07-16 13:14:37 -0700702 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500703 // A stream ID which is too large to create.
704 stream_id2 = GetNthClientInitiatedUnidirectionalId(
705 session_.MaxAvailableUnidirectionalStreams() + 2);
fkastenholz305e1732019-06-18 05:01:22 -0700706 if (VersionHasIetfQuicFrames(transport_version())) {
707 // IETF QUIC terminates the connection with invalid stream id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500708 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 }
renjietang880d2432019-07-16 13:14:37 -0700715 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500716}
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.
fkastenholz305e1732019-06-18 05:01:22 -0700721 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700722 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);
renjietang880d2432019-07-16 13:14:37 -0700730 EXPECT_NE(nullptr, session_.GetOrCreateStream(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);
renjietang880d2432019-07-16 13:14:37 -0700735 EXPECT_NE(nullptr, session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500736 GetNthClientInitiatedBidirectionalId(199)));
fkastenholzd3a1de92019-05-15 07:00:07 -0700737
fkastenholz305e1732019-06-18 05:01:22 -0700738 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700739 // If IETF QUIC, check to make sure that creating bidirectional
740 // streams does not mess up the unidirectional streams.
741 stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700742 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholzd3a1de92019-05-15 07:00:07 -0700743 // Now try to get the last possible unidirectional stream.
renjietang880d2432019-07-16 13:14:37 -0700744 EXPECT_NE(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700745 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);
renjietang880d2432019-07-16 13:14:37 -0700756 EXPECT_EQ(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700757 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.
fkastenholz305e1732019-06-18 05:01:22 -0700764 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700765 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);
renjietang880d2432019-07-16 13:14:37 -0700773 EXPECT_NE(nullptr, session_.GetOrCreateStream(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);
renjietang880d2432019-07-16 13:14:37 -0700778 EXPECT_NE(nullptr, session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500779 GetNthClientInitiatedUnidirectionalId(199)));
fkastenholz305e1732019-06-18 05:01:22 -0700780 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700781 // If IETF QUIC, check to make sure that creating unidirectional
782 // streams does not mess up the bidirectional streams.
783 stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700784 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholzd3a1de92019-05-15 07:00:07 -0700785 // Now try to get the last possible bidirectional stream.
renjietang880d2432019-07-16 13:14:37 -0700786 EXPECT_NE(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700787 GetNthClientInitiatedBidirectionalId(49)));
788 // and this should fail because it exceeds the bnidirectional limit
789 // (but not the uni-)
nharpercd820e02019-05-16 15:12:07 -0700790 std::string error_detail;
791 if (QuicVersionUsesCryptoFrames(transport_version())) {
792 error_detail = "Stream id 796 would exceed stream count limit 50";
793 } else {
794 error_detail = "Stream id 800 would exceed stream count limit 50";
795 }
fkastenholzd3a1de92019-05-15 07:00:07 -0700796 EXPECT_CALL(
797 *connection_,
nharpercd820e02019-05-16 15:12:07 -0700798 CloseConnection(QUIC_INVALID_STREAM_ID, error_detail,
799 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
fkastenholzd3a1de92019-05-15 07:00:07 -0700800 .Times(1);
renjietang880d2432019-07-16 13:14:37 -0700801 EXPECT_EQ(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700802 GetNthClientInitiatedBidirectionalId(199)));
803 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500804}
805
806TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
807 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
808 if (GetParam() != AllSupportedVersions()[0]) {
809 return;
810 }
811
812 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
813 QuicStreamId closed_stream_id = stream2->id();
814 // Close the stream.
815 EXPECT_CALL(*connection_, SendControlFrame(_));
816 EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
817 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
vasilvvc48c8712019-03-11 13:38:16 -0700818 std::string msg =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500819 QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
820 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
821 msg);
822}
823
824TEST_P(QuicSessionTestServer, OnCanWrite) {
nharperf5e68452019-05-29 17:24:18 -0700825 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
826 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
827 // enabled and fix it.
828 return;
829 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500830 session_.set_writev_consumes_all_data(true);
831 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
832 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
833 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
834
835 session_.MarkConnectionLevelWriteBlocked(stream2->id());
836 session_.MarkConnectionLevelWriteBlocked(stream6->id());
837 session_.MarkConnectionLevelWriteBlocked(stream4->id());
838
839 InSequence s;
840
841 // Reregister, to test the loop limit.
842 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
843 session_.SendStreamData(stream2);
844 session_.MarkConnectionLevelWriteBlocked(stream2->id());
845 }));
846 // 2 will get called a second time as it didn't finish its block
847 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
848 session_.SendStreamData(stream2);
849 }));
850 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
851 session_.SendStreamData(stream6);
852 }));
853 // 4 will not get called, as we exceeded the loop limit.
854 session_.OnCanWrite();
855 EXPECT_TRUE(session_.WillingAndAbleToWrite());
856}
857
858TEST_P(QuicSessionTestServer, TestBatchedWrites) {
nharperf5e68452019-05-29 17:24:18 -0700859 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
860 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
861 // enabled and fix it.
862 return;
863 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500864 session_.set_writev_consumes_all_data(true);
865 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
866 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
867 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
868
869 session_.set_writev_consumes_all_data(true);
870 session_.MarkConnectionLevelWriteBlocked(stream2->id());
871 session_.MarkConnectionLevelWriteBlocked(stream4->id());
872
873 // With two sessions blocked, we should get two write calls. They should both
874 // go to the first stream as it will only write 6k and mark itself blocked
875 // again.
876 InSequence s;
877 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
878 session_.SendLargeFakeData(stream2, 6000);
879 session_.MarkConnectionLevelWriteBlocked(stream2->id());
880 }));
881 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
882 session_.SendLargeFakeData(stream2, 6000);
883 session_.MarkConnectionLevelWriteBlocked(stream2->id());
884 }));
885 session_.OnCanWrite();
886
887 // We should get one more call for stream2, at which point it has used its
888 // write quota and we move over to stream 4.
889 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
890 session_.SendLargeFakeData(stream2, 6000);
891 session_.MarkConnectionLevelWriteBlocked(stream2->id());
892 }));
893 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
894 session_.SendLargeFakeData(stream4, 6000);
895 session_.MarkConnectionLevelWriteBlocked(stream4->id());
896 }));
897 session_.OnCanWrite();
898
899 // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
900 // priority stream 6. 4 should be preempted. 6 will write but *not* block so
901 // will cede back to 4.
fayang476683a2019-07-25 12:42:16 -0700902 stream6->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500903 EXPECT_CALL(*stream4, OnCanWrite())
904 .WillOnce(Invoke([this, stream4, stream6]() {
905 session_.SendLargeFakeData(stream4, 6000);
906 session_.MarkConnectionLevelWriteBlocked(stream4->id());
907 session_.MarkConnectionLevelWriteBlocked(stream6->id());
908 }));
909 EXPECT_CALL(*stream6, OnCanWrite())
910 .WillOnce(Invoke([this, stream4, stream6]() {
911 session_.SendStreamData(stream6);
912 session_.SendLargeFakeData(stream4, 6000);
913 }));
914 session_.OnCanWrite();
915
916 // Stream4 alread did 6k worth of writes, so after doing another 12k it should
917 // cede and 2 should resume.
918 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
919 session_.SendLargeFakeData(stream4, 12000);
920 session_.MarkConnectionLevelWriteBlocked(stream4->id());
921 }));
922 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
923 session_.SendLargeFakeData(stream2, 6000);
924 session_.MarkConnectionLevelWriteBlocked(stream2->id());
925 }));
926 session_.OnCanWrite();
927}
928
fayang944cfbc2019-07-31 09:15:00 -0700929TEST_P(QuicSessionTestServer, Http2Priority) {
930 if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
931 return;
932 }
933 SetQuicReloadableFlag(quic_use_http2_priority_write_scheduler, true);
934 QuicTagVector copt;
935 copt.push_back(kH2PR);
936 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
937 session_.OnConfigNegotiated();
938 ASSERT_TRUE(session_.use_http2_priority_write_scheduler());
939
940 session_.set_writev_consumes_all_data(true);
941 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
942 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
943 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
944
945 session_.set_writev_consumes_all_data(true);
946 /*
947 0
948 /|\
949 2 4 6
950 */
951 session_.MarkConnectionLevelWriteBlocked(stream2->id());
952 session_.MarkConnectionLevelWriteBlocked(stream4->id());
953 session_.MarkConnectionLevelWriteBlocked(stream6->id());
954
955 // Verify streams are scheduled round robin.
956 InSequence s;
957 EXPECT_CALL(*stream2, OnCanWrite());
958 EXPECT_CALL(*stream4, OnCanWrite());
959 EXPECT_CALL(*stream6, OnCanWrite());
960 session_.OnCanWrite();
961
962 /*
963 0
964 |
965 4
966 / \
967 2 6
968 */
969 // Update stream 4's priority.
970 stream4->SetPriority(
971 spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, true));
972 session_.MarkConnectionLevelWriteBlocked(stream2->id());
973 session_.MarkConnectionLevelWriteBlocked(stream4->id());
974 session_.MarkConnectionLevelWriteBlocked(stream6->id());
975
976 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
977 session_.MarkConnectionLevelWriteBlocked(stream4->id());
978 }));
979 EXPECT_CALL(*stream4, OnCanWrite());
980 EXPECT_CALL(*stream2, OnCanWrite());
981 session_.OnCanWrite();
982 EXPECT_CALL(*stream6, OnCanWrite());
983 session_.OnCanWrite();
984
985 /*
986 0
987 |
988 6
989 |
990 4
991 |
992 2
993 */
994 // Update stream 6's priority.
995 stream6->SetPriority(
996 spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, true));
997 session_.MarkConnectionLevelWriteBlocked(stream2->id());
998 session_.MarkConnectionLevelWriteBlocked(stream4->id());
999 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1000
1001 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1002 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1003 }));
1004 EXPECT_CALL(*stream6, OnCanWrite());
1005 EXPECT_CALL(*stream4, OnCanWrite());
1006 session_.OnCanWrite();
1007 EXPECT_CALL(*stream2, OnCanWrite());
1008 session_.OnCanWrite();
1009}
1010
QUICHE teama6ef0a62019-03-07 20:34:33 -05001011TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
1012 // Encryption needs to be established before data can be sent.
1013 CryptoHandshakeMessage msg;
1014 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1015 QuicConnectionPeer::GetWriter(session_.connection()));
1016 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1017
1018 // Drive congestion control manually.
1019 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1020 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1021
1022 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1023 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1024 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1025
1026 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1027 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1028 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1029
1030 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1031 EXPECT_CALL(*send_algorithm, GetCongestionWindow())
dschinazi66dea072019-04-09 11:41:06 -07001032 .WillRepeatedly(Return(kMaxOutgoingPacketSize * 10));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001033 EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
1034 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1035 session_.SendStreamData(stream2);
1036 }));
1037 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1038 session_.SendStreamData(stream4);
1039 }));
1040 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1041 session_.SendStreamData(stream6);
1042 }));
1043
1044 // Expect that we only send one packet, the writes from different streams
1045 // should be bundled together.
1046 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
1047 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1048 EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
1049 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1050 session_.OnCanWrite();
1051 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1052}
1053
1054TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
nharperf5e68452019-05-29 17:24:18 -07001055 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1056 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1057 // enabled and fix it.
1058 return;
1059 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001060 session_.set_writev_consumes_all_data(true);
1061 InSequence s;
1062
1063 // Drive congestion control manually.
1064 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1065 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1066
1067 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1068 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1069 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1070
1071 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1072 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1073 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1074
1075 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1076 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1077 session_.SendStreamData(stream2);
1078 }));
1079 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1080 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1081 session_.SendStreamData(stream6);
1082 }));
1083 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
1084 // stream4->OnCanWrite is not called.
1085
1086 session_.OnCanWrite();
1087 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1088
1089 // Still congestion-control blocked.
1090 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
1091 session_.OnCanWrite();
1092 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1093
1094 // stream4->OnCanWrite is called once the connection stops being
1095 // congestion-control blocked.
1096 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1097 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1098 session_.SendStreamData(stream4);
1099 }));
1100 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1101 session_.OnCanWrite();
1102 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1103}
1104
1105TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
nharperf5e68452019-05-29 17:24:18 -07001106 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1107 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1108 // enabled and fix it.
1109 return;
1110 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001111 // Drive congestion control manually in order to ensure that
1112 // application-limited signaling is handled correctly.
1113 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1114 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1115 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1116
1117 // Drive packet writer manually.
1118 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1119 QuicConnectionPeer::GetWriter(session_.connection()));
1120 EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
1121 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
1122
1123 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1124
1125 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1126
1127 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
1128 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)).Times(0);
1129
1130 session_.OnCanWrite();
1131 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1132}
1133
1134TEST_P(QuicSessionTestServer, BufferedHandshake) {
nharperd5c4a932019-05-13 13:58:49 -07001135 // This test is testing behavior of crypto stream flow control, but when
1136 // CRYPTO frames are used, there is no flow control for the crypto handshake.
1137 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1138 return;
1139 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001140 session_.set_writev_consumes_all_data(true);
1141 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
1142
1143 // Test that blocking other streams does not change our status.
1144 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1145 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1146 EXPECT_FALSE(session_.HasPendingHandshake());
1147
1148 TestStream* stream3 = session_.CreateOutgoingBidirectionalStream();
1149 session_.MarkConnectionLevelWriteBlocked(stream3->id());
1150 EXPECT_FALSE(session_.HasPendingHandshake());
1151
1152 // Blocking (due to buffering of) the Crypto stream is detected.
1153 session_.MarkConnectionLevelWriteBlocked(
1154 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1155 EXPECT_TRUE(session_.HasPendingHandshake());
1156
1157 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1158 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1159 EXPECT_TRUE(session_.HasPendingHandshake());
1160
1161 InSequence s;
1162 // Force most streams to re-register, which is common scenario when we block
1163 // the Crypto stream, and only the crypto stream can "really" write.
1164
1165 // Due to prioritization, we *should* be asked to write the crypto stream
1166 // first.
1167 // Don't re-register the crypto stream (which signals complete writing).
1168 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1169 EXPECT_CALL(*crypto_stream, OnCanWrite());
1170
1171 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1172 session_.SendStreamData(stream2);
1173 }));
1174 EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(Invoke([this, stream3]() {
1175 session_.SendStreamData(stream3);
1176 }));
1177 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1178 session_.SendStreamData(stream4);
1179 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1180 }));
1181
1182 session_.OnCanWrite();
1183 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1184 EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
1185}
1186
1187TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
nharperf5e68452019-05-29 17:24:18 -07001188 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1189 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1190 // enabled and fix it.
1191 return;
1192 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001193 session_.set_writev_consumes_all_data(true);
1194 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1195 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1196 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1197
1198 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1199 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1200 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1201 CloseStream(stream6->id());
1202
1203 InSequence s;
1204 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001205 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001206 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1207 session_.SendStreamData(stream2);
1208 }));
1209 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1210 session_.SendStreamData(stream4);
1211 }));
1212 session_.OnCanWrite();
1213 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1214}
1215
1216TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
1217 // Drive congestion control manually in order to ensure that
1218 // application-limited signaling is handled correctly.
1219 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1220 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1221 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1222
1223 // Ensure connection level flow control blockage.
1224 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
1225 EXPECT_TRUE(session_.flow_controller()->IsBlocked());
1226 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1227 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1228
1229 // Mark the crypto and headers streams as write blocked, we expect them to be
1230 // allowed to write later.
nharperd5c4a932019-05-13 13:58:49 -07001231 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1232 session_.MarkConnectionLevelWriteBlocked(
1233 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1234 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001235
1236 // Create a data stream, and although it is write blocked we never expect it
1237 // to be allowed to write as we are connection level flow control blocked.
1238 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1239 session_.MarkConnectionLevelWriteBlocked(stream->id());
1240 EXPECT_CALL(*stream, OnCanWrite()).Times(0);
1241
1242 // The crypto and headers streams should be called even though we are
1243 // connection flow control blocked.
nharperd5c4a932019-05-13 13:58:49 -07001244 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1245 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1246 EXPECT_CALL(*crypto_stream, OnCanWrite());
1247 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001248
1249 // After the crypto and header streams perform a write, the connection will be
1250 // blocked by the flow control, hence it should become application-limited.
1251 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1252
1253 session_.OnCanWrite();
1254 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1255}
1256
1257TEST_P(QuicSessionTestServer, SendGoAway) {
fkastenholz305e1732019-06-18 05:01:22 -07001258 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001259 // GoAway frames are not in version 99
1260 return;
1261 }
fayang93cc53a2019-08-22 12:47:30 -07001262 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001263 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1264 QuicConnectionPeer::GetWriter(session_.connection()));
1265 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
1266 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1267
1268 EXPECT_CALL(*connection_, SendControlFrame(_))
1269 .WillOnce(
1270 Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
1271 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1272 EXPECT_TRUE(session_.goaway_sent());
1273
1274 const QuicStreamId kTestStreamId = 5u;
1275 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1276 EXPECT_CALL(*connection_,
1277 OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
1278 .Times(0);
renjietang880d2432019-07-16 13:14:37 -07001279 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001280}
1281
1282TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
fkastenholz305e1732019-06-18 05:01:22 -07001283 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001284 // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
1285 // supported.
1286 return;
1287 }
1288 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001289 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001290 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1291 EXPECT_TRUE(session_.goaway_sent());
1292 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1293}
1294
1295TEST_P(QuicSessionTestServer, InvalidGoAway) {
fkastenholz305e1732019-06-18 05:01:22 -07001296 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001297 // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
1298 // supported.
1299 return;
1300 }
1301 QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
1302 session_.next_outgoing_bidirectional_stream_id(), "");
1303 session_.OnGoAway(go_away);
1304}
1305
1306// Test that server session will send a connectivity probe in response to a
1307// connectivity probe on the same path.
1308TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbe) {
1309 QuicSocketAddress old_peer_address =
1310 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1311 EXPECT_EQ(old_peer_address, session_.peer_address());
1312
1313 QuicSocketAddress new_peer_address =
1314 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort + 1);
1315
1316 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1317 QuicConnectionPeer::GetWriter(session_.connection()));
1318 EXPECT_CALL(*writer, WritePacket(_, _, _, new_peer_address, _))
1319 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1320 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1321 .WillOnce(Invoke(
1322 connection_,
1323 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
fkastenholz305e1732019-06-18 05:01:22 -07001324 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001325 // Need to explicitly do this to emulate the reception of a PathChallenge,
1326 // which stores its payload for use in generating the response.
1327 connection_->OnPathChallengeFrame(
1328 QuicPathChallengeFrame(0, path_frame_buffer1_));
1329 }
zhongyi83161e42019-08-19 09:06:25 -07001330 session_.OnPacketReceived(session_.self_address(), new_peer_address,
1331 /*is_connectivity_probe=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001332 EXPECT_EQ(old_peer_address, session_.peer_address());
1333}
1334
1335// Same as above, but check that if there are two PATH_CHALLENGE frames in the
1336// packet, the response has both of them AND we do not do migration. This for
fkastenholz305e1732019-06-18 05:01:22 -07001337// IETF QUIC only.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001338TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbes) {
fkastenholz305e1732019-06-18 05:01:22 -07001339 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001340 return;
1341 }
nharperf5e68452019-05-29 17:24:18 -07001342 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1343 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1344 // enabled and fix it.
1345 return;
1346 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001347 QuicSocketAddress old_peer_address =
1348 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1349 EXPECT_EQ(old_peer_address, session_.peer_address());
1350
1351 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1352 QuicConnectionPeer::GetWriter(session_.connection()));
1353 // CheckMultiPathResponse validates that the written packet
1354 // contains both path responses.
1355 EXPECT_CALL(*writer, WritePacket(_, _, _, old_peer_address, _))
1356 .WillOnce(Invoke(this, &QuicSessionTestServer::CheckMultiPathResponse));
1357
1358 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1359 .WillOnce(Invoke(
1360 connection_,
1361 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
QUICHE team8c1daa22019-03-13 08:33:41 -07001362 QuicConnectionPeer::SetLastHeaderFormat(connection_,
1363 IETF_QUIC_SHORT_HEADER_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001364 // Need to explicitly do this to emulate the reception of a PathChallenge,
1365 // which stores its payload for use in generating the response.
1366 connection_->OnPathChallengeFrame(
1367 QuicPathChallengeFrame(0, path_frame_buffer1_));
1368 connection_->OnPathChallengeFrame(
1369 QuicPathChallengeFrame(0, path_frame_buffer2_));
zhongyi83161e42019-08-19 09:06:25 -07001370 session_.OnPacketReceived(session_.self_address(), old_peer_address,
1371 /*is_connectivity_probe=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001372}
1373
1374TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
1375 EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
1376 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1377 CryptoHandshakeMessage msg;
1378 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1379 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
1380 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1381}
1382
1383TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
renjietang118c8ac2019-07-30 11:43:59 -07001384 if (VersionUsesQpack(connection_->transport_version())) {
dschinazi552accc2019-06-17 17:07:34 -07001385 return;
1386 }
nharper46833c32019-05-15 21:33:05 -07001387 QuicStreamId headers_stream_id =
1388 QuicUtils::GetHeadersStreamId(connection_->transport_version());
vasilvv0fc587f2019-09-06 13:33:08 -07001389 std::unique_ptr<TestStream> fake_headers_stream =
1390 std::make_unique<TestStream>(headers_stream_id, &session_,
1391 /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07001392 QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001393 // Send two bytes of payload.
nharper46833c32019-05-15 21:33:05 -07001394 QuicStreamFrame data1(headers_stream_id, true, 0, QuicStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001395 EXPECT_CALL(*connection_,
1396 CloseConnection(
1397 QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
1398 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1399 session_.OnStreamFrame(data1);
1400}
1401
1402TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
renjietang118c8ac2019-07-30 11:43:59 -07001403 if (VersionUsesQpack(connection_->transport_version())) {
dschinazi552accc2019-06-17 17:07:34 -07001404 return;
1405 }
nharper46833c32019-05-15 21:33:05 -07001406 QuicStreamId headers_stream_id =
1407 QuicUtils::GetHeadersStreamId(connection_->transport_version());
vasilvv0fc587f2019-09-06 13:33:08 -07001408 std::unique_ptr<TestStream> fake_headers_stream =
1409 std::make_unique<TestStream>(headers_stream_id, &session_,
1410 /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07001411 QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001412 // Send two bytes of payload.
nharper46833c32019-05-15 21:33:05 -07001413 QuicRstStreamFrame rst1(kInvalidControlFrameId, headers_stream_id,
1414 QUIC_ERROR_PROCESSING_STREAM, 0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001415 EXPECT_CALL(*connection_,
1416 CloseConnection(
1417 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
1418 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1419 session_.OnRstStream(rst1);
1420}
1421
1422TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
1423 // Send two bytes of payload.
1424 QuicStreamFrame data1(
1425 QuicUtils::GetInvalidStreamId(connection_->transport_version()), true, 0,
1426 QuicStringPiece("HT"));
1427 EXPECT_CALL(*connection_,
1428 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001429 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001430 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1431 session_.OnStreamFrame(data1);
1432}
1433
1434TEST_P(QuicSessionTestServer, OnRstStreamInvalidStreamId) {
1435 // Send two bytes of payload.
1436 QuicRstStreamFrame rst1(
1437 kInvalidControlFrameId,
1438 QuicUtils::GetInvalidStreamId(connection_->transport_version()),
1439 QUIC_ERROR_PROCESSING_STREAM, 0);
1440 EXPECT_CALL(*connection_,
1441 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001442 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001443 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1444 session_.OnRstStream(rst1);
1445}
1446
1447TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
nharperf5e68452019-05-29 17:24:18 -07001448 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
1449 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
1450 // enabled and fix it.
1451 return;
1452 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001453 // Test that if a stream is flow control blocked, then on receipt of the SHLO
1454 // containing a suitable send window offset, the stream becomes unblocked.
1455
1456 // Ensure that Writev consumes all the data it is given (simulate no socket
1457 // blocking).
1458 session_.set_writev_consumes_all_data(true);
1459
1460 // Create a stream, and send enough data to make it flow control blocked.
1461 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07001462 std::string body(kMinimumFlowControlSendWindow, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001463 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1464 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1465 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1466 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
1467 stream2->WriteOrBufferData(body, false, nullptr);
1468 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
1469 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1470 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1471
1472 // Now complete the crypto handshake, resulting in an increased flow control
1473 // send window.
1474 CryptoHandshakeMessage msg;
1475 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1476 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
1477 // Stream is now unblocked.
1478 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1479 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1480 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1481}
1482
1483TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
QUICHE teamea740082019-03-11 17:58:43 -07001484 if (QuicVersionUsesCryptoFrames(GetParam().transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001485 // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
1486 // test doesn't make sense for those versions since CRYPTO frames aren't
1487 // flow controlled.
1488 return;
1489 }
1490 // Test that if the crypto stream is flow control blocked, then if the SHLO
1491 // contains a larger send window offset, the stream becomes unblocked.
1492 session_.set_writev_consumes_all_data(true);
1493 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1494 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1495 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1496 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1497 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1498 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1499 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001500 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001501 for (QuicStreamId i = 0;
1502 !crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
1503 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1504 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1505 QuicStreamOffset offset = crypto_stream->stream_bytes_written();
1506 QuicConfig config;
1507 CryptoHandshakeMessage crypto_message;
fkastenholzd3a1de92019-05-15 07:00:07 -07001508 config.ToHandshakeMessage(&crypto_message, transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001509 crypto_stream->SendHandshakeMessage(crypto_message);
1510 char buf[1000];
1511 QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
1512 crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
1513 }
1514 EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
1515 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1516 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1517 EXPECT_FALSE(session_.HasDataToWrite());
1518 EXPECT_TRUE(crypto_stream->HasBufferedData());
1519
1520 // Now complete the crypto handshake, resulting in an increased flow control
1521 // send window.
1522 CryptoHandshakeMessage msg;
1523 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1524 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
1525 &session_,
1526 QuicUtils::GetCryptoStreamId(connection_->transport_version())));
1527 // Stream is now unblocked and will no longer have buffered data.
1528 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1529 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1530 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1531}
1532
1533TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
1534 // Test that when we receive an out of order stream RST we correctly adjust
1535 // our connection level flow control receive window.
1536 // On close, the stream should mark as consumed all bytes between the highest
1537 // byte consumed so far and the final byte offset from the RST frame.
1538 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1539
1540 const QuicStreamOffset kByteOffset =
1541 1 + kInitialSessionFlowControlWindowForTest / 2;
1542
1543 EXPECT_CALL(*connection_, SendControlFrame(_))
1544 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07001545 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001546 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1547
1548 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1549 QUIC_STREAM_CANCELLED, kByteOffset);
1550 session_.OnRstStream(rst_frame);
fkastenholz305e1732019-06-18 05:01:22 -07001551 if (VersionHasIetfQuicFrames(transport_version())) {
1552 // The test is predicated on the stream being fully closed. For IETF QUIC,
1553 // the RST_STREAM only does one side (the read side from the perspective of
1554 // the node receiving the RST_STREAM). This is needed to fully close the
QUICHE teama6ef0a62019-03-07 20:34:33 -05001555 // stream and therefore fulfill all of the expects.
1556 QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
1557 QUIC_STREAM_CANCELLED);
1558 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
1559 }
1560 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
1561}
1562
1563TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
1564 // Test the situation where we receive a FIN on a stream, and before we fully
1565 // consume all the data from the sequencer buffer we locally RST the stream.
1566 // The bytes between highest consumed byte, and the final byte offset that we
1567 // determined when the FIN arrived, should be marked as consumed at the
1568 // connection level flow controller when the stream is reset.
1569 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1570
1571 const QuicStreamOffset kByteOffset =
1572 kInitialSessionFlowControlWindowForTest / 2 - 1;
1573 QuicStreamFrame frame(stream->id(), true, kByteOffset, ".");
1574 session_.OnStreamFrame(frame);
1575 EXPECT_TRUE(connection_->connected());
1576
1577 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
1578 EXPECT_EQ(kByteOffset + frame.data_length,
1579 stream->flow_controller()->highest_received_byte_offset());
1580
1581 // Reset stream locally.
1582 EXPECT_CALL(*connection_, SendControlFrame(_));
1583 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1584 stream->Reset(QUIC_STREAM_CANCELLED);
1585 EXPECT_EQ(kByteOffset + frame.data_length,
1586 session_.flow_controller()->bytes_consumed());
1587}
1588
1589TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
1590 // Test that when we RST the stream (and tear down stream state), and then
1591 // receive a FIN from the peer, we correctly adjust our connection level flow
1592 // control receive window.
1593
1594 // Connection starts with some non-zero highest received byte offset,
1595 // due to other active streams.
1596 const uint64_t kInitialConnectionBytesConsumed = 567;
1597 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1598 EXPECT_LT(kInitialConnectionBytesConsumed,
1599 kInitialConnectionHighestReceivedOffset);
1600 session_.flow_controller()->UpdateHighestReceivedOffset(
1601 kInitialConnectionHighestReceivedOffset);
1602 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1603
1604 // Reset our stream: this results in the stream being closed locally.
1605 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1606 EXPECT_CALL(*connection_, SendControlFrame(_));
1607 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1608 stream->Reset(QUIC_STREAM_CANCELLED);
1609
1610 // Now receive a response from the peer with a FIN. We should handle this by
1611 // adjusting the connection level flow control receive window to take into
1612 // account the total number of bytes sent by the peer.
1613 const QuicStreamOffset kByteOffset = 5678;
vasilvvc48c8712019-03-11 13:38:16 -07001614 std::string body = "hello";
QUICHE teama6ef0a62019-03-07 20:34:33 -05001615 QuicStreamFrame frame(stream->id(), true, kByteOffset, QuicStringPiece(body));
1616 session_.OnStreamFrame(frame);
1617
1618 QuicStreamOffset total_stream_bytes_sent_by_peer =
1619 kByteOffset + body.length();
1620 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer,
1621 session_.flow_controller()->bytes_consumed());
1622 EXPECT_EQ(
1623 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer,
1624 session_.flow_controller()->highest_received_byte_offset());
1625}
1626
1627TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
1628 // Test that when we RST the stream (and tear down stream state), and then
1629 // receive a RST from the peer, we correctly adjust our connection level flow
1630 // control receive window.
1631
1632 // Connection starts with some non-zero highest received byte offset,
1633 // due to other active streams.
1634 const uint64_t kInitialConnectionBytesConsumed = 567;
1635 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1636 EXPECT_LT(kInitialConnectionBytesConsumed,
1637 kInitialConnectionHighestReceivedOffset);
1638 session_.flow_controller()->UpdateHighestReceivedOffset(
1639 kInitialConnectionHighestReceivedOffset);
1640 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1641
1642 // Reset our stream: this results in the stream being closed locally.
1643 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1644 EXPECT_CALL(*connection_, SendControlFrame(_));
1645 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1646 stream->Reset(QUIC_STREAM_CANCELLED);
1647 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1648
1649 // Now receive a RST from the peer. We should handle this by adjusting the
1650 // connection level flow control receive window to take into account the total
1651 // number of bytes sent by the peer.
1652 const QuicStreamOffset kByteOffset = 5678;
1653 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1654 QUIC_STREAM_CANCELLED, kByteOffset);
1655 session_.OnRstStream(rst_frame);
1656
1657 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset,
1658 session_.flow_controller()->bytes_consumed());
1659 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset,
1660 session_.flow_controller()->highest_received_byte_offset());
1661}
1662
1663TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
1664 // Test that receipt of an invalid (< default) stream flow control window from
1665 // the peer results in the connection being torn down.
1666 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1667 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
1668 kInvalidWindow);
1669
dschinazic7036122019-04-30 12:46:34 -07001670 if (!connection_->version().AllowsLowFlowControlLimits()) {
1671 EXPECT_CALL(*connection_,
1672 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1673 } else {
1674 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1675 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001676 session_.OnConfigNegotiated();
1677}
1678
1679TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
1680 // Test that receipt of an invalid (< default) session flow control window
1681 // from the peer results in the connection being torn down.
1682 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1683 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
1684 kInvalidWindow);
dschinazic7036122019-04-30 12:46:34 -07001685 if (!connection_->version().AllowsLowFlowControlLimits()) {
1686 EXPECT_CALL(*connection_,
1687 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1688 } else {
1689 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1690 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001691 session_.OnConfigNegotiated();
1692}
1693
1694// Test negotiation of custom server initial flow control window.
1695TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
1696 QuicTagVector copt;
1697 copt.push_back(kIFW7);
1698 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
1699
1700 session_.OnConfigNegotiated();
1701 EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
1702 session_.flow_controller()));
1703}
1704
1705TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
1706 // Test that if we receive a stream RST with a highest byte offset that
1707 // violates flow control, that we close the connection.
1708 const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
1709 EXPECT_CALL(*connection_,
1710 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
1711 .Times(2);
1712
1713 // Check that stream frame + FIN results in connection close.
1714 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1715 EXPECT_CALL(*connection_, SendControlFrame(_));
1716 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1717 stream->Reset(QUIC_STREAM_CANCELLED);
1718 QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
1719 session_.OnStreamFrame(frame);
1720
1721 // Check that RST results in connection close.
1722 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1723 QUIC_STREAM_CANCELLED, kLargeOffset);
1724 session_.OnRstStream(rst_frame);
1725}
1726
1727TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
1728 // If a buggy/malicious peer creates too many streams that are not ended
fkastenholz305e1732019-06-18 05:01:22 -07001729 // with a FIN or RST then we send an RST to refuse streams. For IETF QUIC the
QUICHE teama6ef0a62019-03-07 20:34:33 -05001730 // connection is closed.
1731 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07001732 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001733 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1734 kMaxStreams);
1735 } else {
1736 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1737 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001738 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1739 const QuicStreamId kFinalStreamId =
1740 GetNthClientInitiatedBidirectionalId(kMaxStreams);
1741 // Create kMaxStreams data streams, and close them all without receiving a
1742 // FIN or a RST_STREAM from the client.
1743 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
1744 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
1745 QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
1746 session_.OnStreamFrame(data1);
1747 // EXPECT_EQ(1u, session_.GetNumOpenStreams());
fkastenholz305e1732019-06-18 05:01:22 -07001748 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001749 // Expect two control frames, RST STREAM and STOP SENDING
1750 EXPECT_CALL(*connection_, SendControlFrame(_))
1751 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07001752 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001753 } else {
1754 // Expect one control frame, just RST STREAM
1755 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001756 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001757 }
1758 // Close stream. Should not make new streams available since
1759 // the stream is not finished.
1760 EXPECT_CALL(*connection_, OnStreamReset(i, _));
1761 session_.CloseStream(i);
1762 }
1763
fkastenholz305e1732019-06-18 05:01:22 -07001764 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholz3c4eabf2019-04-22 07:49:59 -07001765 EXPECT_CALL(
1766 *connection_,
1767 CloseConnection(QUIC_INVALID_STREAM_ID,
nharpercd820e02019-05-16 15:12:07 -07001768 "Stream id 20 would exceed stream count limit 5", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001769 } else {
1770 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1771 EXPECT_CALL(*connection_,
1772 OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
1773 .Times(1);
1774 }
1775 // Create one more data streams to exceed limit of open stream.
1776 QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
1777 session_.OnStreamFrame(data1);
1778}
1779
1780TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpenedOutgoing) {
1781 // Verify that a draining stream (which has received a FIN but not consumed
1782 // it) does not count against the open quota (because it is closed from the
1783 // protocol point of view).
1784 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1785 QuicStreamId stream_id = stream->id();
1786 QuicStreamFrame data1(stream_id, true, 0, QuicStringPiece("HT"));
1787 session_.OnStreamFrame(data1);
fkastenholz8556dc22019-07-18 12:42:38 -07001788 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001789 session_.StreamDraining(stream_id);
1790}
1791
1792TEST_P(QuicSessionTestServer, NoPendingStreams) {
renjietange76b2da2019-05-13 14:50:23 -07001793 session_.set_uses_pending_streams(false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001794
1795 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1796 transport_version(), Perspective::IS_CLIENT);
1797 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1798 session_.OnStreamFrame(data1);
1799 EXPECT_EQ(1, session_.num_incoming_streams_created());
1800
1801 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1802 session_.OnStreamFrame(data2);
1803 EXPECT_EQ(1, session_.num_incoming_streams_created());
1804}
1805
1806TEST_P(QuicSessionTestServer, PendingStreams) {
bnccf6c3e62019-08-08 07:29:48 -07001807 if (!VersionHasStreamType(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001808 return;
1809 }
renjietange76b2da2019-05-13 14:50:23 -07001810 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001811
1812 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1813 transport_version(), Perspective::IS_CLIENT);
1814 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1815 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001816 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001817 EXPECT_EQ(0, session_.num_incoming_streams_created());
1818
1819 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1820 session_.OnStreamFrame(data2);
bnc092d8212019-08-07 11:53:20 -07001821 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001822 EXPECT_EQ(1, session_.num_incoming_streams_created());
1823}
1824
1825TEST_P(QuicSessionTestServer, RstPendingStreams) {
bnccf6c3e62019-08-08 07:29:48 -07001826 if (!VersionHasStreamType(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001827 return;
1828 }
renjietange76b2da2019-05-13 14:50:23 -07001829 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001830
1831 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1832 transport_version(), Perspective::IS_CLIENT);
1833 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1834 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001835 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001836 EXPECT_EQ(0, session_.num_incoming_streams_created());
renjietangec6b2c42019-07-16 20:31:51 -07001837 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001838
QUICHE teama6ef0a62019-03-07 20:34:33 -05001839 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1840 EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_RST_ACKNOWLEDGEMENT))
1841 .Times(1);
1842 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream_id,
1843 QUIC_ERROR_PROCESSING_STREAM, 12);
1844 session_.OnRstStream(rst1);
bnc092d8212019-08-07 11:53:20 -07001845 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001846 EXPECT_EQ(0, session_.num_incoming_streams_created());
renjietangec6b2c42019-07-16 20:31:51 -07001847 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001848
1849 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1850 session_.OnStreamFrame(data2);
bnc092d8212019-08-07 11:53:20 -07001851 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
1852 EXPECT_EQ(0, session_.num_incoming_streams_created());
1853 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1854}
1855
1856TEST_P(QuicSessionTestServer, OnFinPendingStreams) {
bnccf6c3e62019-08-08 07:29:48 -07001857 if (!VersionHasStreamType(transport_version())) {
bnc092d8212019-08-07 11:53:20 -07001858 return;
1859 }
1860 session_.set_uses_pending_streams(true);
1861
1862 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1863 transport_version(), Perspective::IS_CLIENT);
1864 QuicStreamFrame data(stream_id, true, 0, "");
1865 session_.OnStreamFrame(data);
1866
1867 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001868 EXPECT_EQ(0, session_.num_incoming_streams_created());
renjietangec6b2c42019-07-16 20:31:51 -07001869 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001870}
1871
renjietang28c04b72019-07-01 15:08:09 -07001872TEST_P(QuicSessionTestServer, PendingStreamOnWindowUpdate) {
bnccf6c3e62019-08-08 07:29:48 -07001873 if (!VersionHasStreamType(transport_version())) {
renjietang28c04b72019-07-01 15:08:09 -07001874 return;
1875 }
1876
1877 session_.set_uses_pending_streams(true);
1878 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1879 transport_version(), Perspective::IS_CLIENT);
1880 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1881 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001882 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
renjietang28c04b72019-07-01 15:08:09 -07001883 EXPECT_EQ(0, session_.num_incoming_streams_created());
1884 QuicWindowUpdateFrame window_update_frame(kInvalidControlFrameId, stream_id,
1885 0);
1886 EXPECT_CALL(
1887 *connection_,
1888 CloseConnection(
1889 QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
1890 "WindowUpdateFrame received on READ_UNIDIRECTIONAL stream.", _));
1891 session_.OnWindowUpdateFrame(window_update_frame);
1892}
1893
QUICHE teama6ef0a62019-03-07 20:34:33 -05001894TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
1895 // Verify that a draining stream (which has received a FIN but not consumed
1896 // it) does not count against the open quota (because it is closed from the
1897 // protocol point of view).
fkastenholz305e1732019-06-18 05:01:22 -07001898 if (VersionHasIetfQuicFrames(transport_version())) {
1899 // On IETF QUIC, we will expect to see a MAX_STREAMS go out when there are
1900 // not enough streams to create the next one.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001901 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1902 } else {
1903 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1904 }
1905 EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
1906 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07001907 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001908 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1909 kMaxStreams);
1910 } else {
1911 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1912 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001913
1914 // Create kMaxStreams + 1 data streams, and mark them draining.
1915 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1916 const QuicStreamId kFinalStreamId =
1917 GetNthClientInitiatedBidirectionalId(2 * kMaxStreams + 1);
1918 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
1919 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
1920 QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT"));
1921 session_.OnStreamFrame(data1);
1922 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
1923 session_.StreamDraining(i);
1924 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1925 }
1926}
1927
1928class QuicSessionTestClient : public QuicSessionTestBase {
1929 protected:
1930 QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {}
1931};
1932
1933INSTANTIATE_TEST_SUITE_P(Tests,
1934 QuicSessionTestClient,
1935 ::testing::ValuesIn(AllSupportedVersions()));
1936
1937TEST_P(QuicSessionTestClient, AvailableBidirectionalStreamsClient) {
renjietang880d2432019-07-16 13:14:37 -07001938 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001939 GetNthServerInitiatedBidirectionalId(2)) != nullptr);
1940 // Smaller bidirectional streams should be available.
1941 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1942 &session_, GetNthServerInitiatedBidirectionalId(0)));
1943 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1944 &session_, GetNthServerInitiatedBidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -07001945 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001946 GetNthServerInitiatedBidirectionalId(0)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -07001947 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001948 GetNthServerInitiatedBidirectionalId(1)) != nullptr);
1949 // And 5 should be not available.
1950 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
1951 &session_, GetNthClientInitiatedBidirectionalId(1)));
1952}
1953
1954TEST_P(QuicSessionTestClient, AvailableUnidirectionalStreamsClient) {
renjietang880d2432019-07-16 13:14:37 -07001955 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001956 GetNthServerInitiatedUnidirectionalId(2)) != nullptr);
1957 // Smaller unidirectional streams should be available.
1958 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1959 &session_, GetNthServerInitiatedUnidirectionalId(0)));
1960 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1961 &session_, GetNthServerInitiatedUnidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -07001962 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001963 GetNthServerInitiatedUnidirectionalId(0)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -07001964 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001965 GetNthServerInitiatedUnidirectionalId(1)) != nullptr);
1966 // And 5 should be not available.
1967 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
1968 &session_, GetNthClientInitiatedUnidirectionalId(1)));
1969}
1970
1971TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
1972 // Verify that an incoming FIN is recorded in a stream object even if the read
1973 // side has been closed. This prevents an entry from being made in
1974 // locally_closed_streams_highest_offset_ (which will never be deleted).
1975 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1976 QuicStreamId stream_id = stream->id();
1977
1978 // Close the read side manually.
1979 QuicStreamPeer::CloseReadSide(stream);
1980
1981 // Receive a stream data frame with FIN.
1982 QuicStreamFrame frame(stream_id, true, 0, QuicStringPiece());
1983 session_.OnStreamFrame(frame);
1984 EXPECT_TRUE(stream->fin_received());
1985
1986 // Reset stream locally.
1987 EXPECT_CALL(*connection_, SendControlFrame(_));
1988 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1989 stream->Reset(QUIC_STREAM_CANCELLED);
1990 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1991
1992 EXPECT_TRUE(connection_->connected());
1993 EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
1994 EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
1995
1996 // The stream is not waiting for the arrival of the peer's final offset as it
1997 // was received with the FIN earlier.
1998 EXPECT_EQ(
1999 0u,
2000 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
2001}
2002
2003TEST_P(QuicSessionTestServer, ZombieStreams) {
2004 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2005 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
2006 EXPECT_TRUE(stream2->IsWaitingForAcks());
2007
2008 EXPECT_CALL(*connection_, SendControlFrame(_));
2009 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2010 session_.CloseStream(stream2->id());
2011 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2012 ASSERT_EQ(1u, session_.closed_streams()->size());
2013 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2014 session_.OnStreamDoneWaitingForAcks(stream2->id());
2015 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2016 EXPECT_EQ(1u, session_.closed_streams()->size());
2017 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2018}
2019
2020TEST_P(QuicSessionTestServer, RstStreamReceivedAfterRstStreamSent) {
2021 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2022 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
2023 EXPECT_TRUE(stream2->IsWaitingForAcks());
2024
2025 EXPECT_CALL(*connection_, SendControlFrame(_));
2026 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
fkastenholz8556dc22019-07-18 12:42:38 -07002027 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002028 stream2->Reset(quic::QUIC_STREAM_CANCELLED);
2029
2030 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream2->id(),
2031 QUIC_ERROR_PROCESSING_STREAM, 0);
fkastenholz305e1732019-06-18 05:01:22 -07002032 if (!VersionHasIetfQuicFrames(transport_version())) {
fkastenholz8556dc22019-07-18 12:42:38 -07002033 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002034 }
2035 session_.OnRstStream(rst1);
2036}
2037
2038// Regression test of b/71548958.
2039TEST_P(QuicSessionTestServer, TestZombieStreams) {
nharperf5e68452019-05-29 17:24:18 -07002040 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
2041 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
2042 // enabled and fix it.
2043 return;
2044 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002045 session_.set_writev_consumes_all_data(true);
2046
2047 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07002048 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002049 stream2->WriteOrBufferData(body, false, nullptr);
2050 EXPECT_TRUE(stream2->IsWaitingForAcks());
2051 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream2).size());
2052
2053 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream2->id(),
2054 QUIC_STREAM_CANCELLED, 1234);
2055 // Just for the RST_STREAM
2056 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002057 .WillOnce(Invoke(&ClearControlFrame));
fkastenholz305e1732019-06-18 05:01:22 -07002058 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002059 EXPECT_CALL(*connection_,
2060 OnStreamReset(stream2->id(), QUIC_STREAM_CANCELLED));
2061 } else {
2062 EXPECT_CALL(*connection_,
2063 OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT));
2064 }
2065 stream2->OnStreamReset(rst_frame);
2066
fkastenholz305e1732019-06-18 05:01:22 -07002067 if (VersionHasIetfQuicFrames(transport_version())) {
2068 // The test is predicated on the stream being fully closed. For IETF QUIC,
2069 // the RST_STREAM only does one side (the read side from the perspective of
2070 // the node receiving the RST_STREAM). This is needed to fully close the
QUICHE teama6ef0a62019-03-07 20:34:33 -05002071 // stream and therefore fulfill all of the expects.
2072 QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
2073 QUIC_STREAM_CANCELLED);
2074 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
2075 }
2076 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2077 ASSERT_EQ(1u, session_.closed_streams()->size());
2078 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2079
2080 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
fkastenholz305e1732019-06-18 05:01:22 -07002081 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002082 // Once for the RST_STREAM, once for the STOP_SENDING
2083 EXPECT_CALL(*connection_, SendControlFrame(_))
2084 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07002085 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002086 } else {
2087 // Just for the RST_STREAM
2088 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
2089 }
2090 EXPECT_CALL(*connection_,
2091 OnStreamReset(stream4->id(), QUIC_STREAM_CANCELLED));
2092 stream4->WriteOrBufferData(body, false, nullptr);
2093 // Note well: Reset() actually closes the stream in both directions. For
2094 // GOOGLE QUIC it sends a RST_STREAM (which does a 2-way close), for IETF
fkastenholz305e1732019-06-18 05:01:22 -07002095 // QUIC it sends both a RST_STREAM and a STOP_SENDING (each of which
QUICHE teama6ef0a62019-03-07 20:34:33 -05002096 // closes in only one direction).
2097 stream4->Reset(QUIC_STREAM_CANCELLED);
2098 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2099 EXPECT_EQ(2u, session_.closed_streams()->size());
2100}
2101
2102TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
nharperf5e68452019-05-29 17:24:18 -07002103 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
2104 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
2105 // enabled and fix it.
2106 return;
2107 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002108 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2109 InSequence s;
2110
2111 // Drive congestion control manually.
2112 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2113 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2114
2115 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
2116 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2117 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2118
nharper46833c32019-05-15 21:33:05 -07002119 QuicStreamFrame frame1;
2120 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
2121 frame1 = QuicStreamFrame(
2122 QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
2123 0, 1300);
2124 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002125 QuicStreamFrame frame2(stream2->id(), false, 0, 9);
2126 QuicStreamFrame frame3(stream4->id(), false, 0, 9);
2127
2128 // Lost data on cryption stream, streams 2 and 4.
2129 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
QUICHE teamea740082019-03-11 17:58:43 -07002130 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002131 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2132 .WillOnce(Return(true));
2133 }
2134 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2135 session_.OnFrameLost(QuicFrame(frame3));
QUICHE teamea740082019-03-11 17:58:43 -07002136 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002137 session_.OnFrameLost(QuicFrame(frame1));
2138 } else {
QUICHE team6987b4a2019-03-15 16:23:04 -07002139 QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002140 session_.OnFrameLost(QuicFrame(&crypto_frame));
2141 }
2142 session_.OnFrameLost(QuicFrame(frame2));
2143 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2144
2145 // Mark streams 2 and 4 write blocked.
2146 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2147 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2148
2149 // Lost data is retransmitted before new data, and retransmissions for crypto
2150 // stream go first.
2151 // Do not check congestion window when crypto stream has lost data.
2152 EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
QUICHE teamea740082019-03-11 17:58:43 -07002153 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002154 EXPECT_CALL(*crypto_stream, OnCanWrite());
2155 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2156 .WillOnce(Return(false));
2157 }
2158 // Check congestion window for non crypto streams.
2159 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2160 EXPECT_CALL(*stream4, OnCanWrite());
2161 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(false));
2162 // Connection is blocked.
2163 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(false));
2164
2165 session_.OnCanWrite();
2166 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2167
2168 // Unblock connection.
2169 // Stream 2 retransmits lost data.
2170 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2171 EXPECT_CALL(*stream2, OnCanWrite());
2172 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2173 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2174 // Stream 2 sends new data.
2175 EXPECT_CALL(*stream2, OnCanWrite());
2176 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2177 EXPECT_CALL(*stream4, OnCanWrite());
2178 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2179
2180 session_.OnCanWrite();
2181 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2182}
2183
2184TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
nharperf5e68452019-05-29 17:24:18 -07002185 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
2186 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
2187 // enabled and fix it.
2188 return;
2189 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002190 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2191 InSequence s;
2192
2193 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2194 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2195 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2196
2197 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2198 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2199 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2200
2201 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(true));
2202 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
2203 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2204 session_.OnFrameLost(QuicFrame(frame3));
2205 session_.OnFrameLost(QuicFrame(frame2));
2206 session_.OnFrameLost(QuicFrame(frame1));
2207
2208 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2209 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2210 session_.MarkConnectionLevelWriteBlocked(stream6->id());
2211
2212 // Reset stream 4 locally.
2213 EXPECT_CALL(*connection_, SendControlFrame(_));
2214 EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
2215 stream4->Reset(QUIC_STREAM_CANCELLED);
2216
2217 // Verify stream 4 is removed from streams with lost data list.
2218 EXPECT_CALL(*stream6, OnCanWrite());
2219 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
2220 EXPECT_CALL(*stream2, OnCanWrite());
2221 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2222 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002223 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002224 EXPECT_CALL(*stream2, OnCanWrite());
2225 EXPECT_CALL(*stream6, OnCanWrite());
2226 session_.OnCanWrite();
2227}
2228
2229TEST_P(QuicSessionTestServer, RetransmitFrames) {
2230 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2231 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2232 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2233 InSequence s;
2234
2235 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2236 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2237 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2238 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002239 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002240 session_.SendWindowUpdate(stream2->id(), 9);
2241
2242 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2243 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2244 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2245 QuicWindowUpdateFrame window_update(1, stream2->id(), 9);
2246 QuicFrames frames;
2247 frames.push_back(QuicFrame(frame1));
2248 frames.push_back(QuicFrame(&window_update));
2249 frames.push_back(QuicFrame(frame2));
2250 frames.push_back(QuicFrame(frame3));
2251 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2252
2253 EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2254 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002255 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002256 EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2257 EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2258 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2259 session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
2260}
2261
2262// Regression test of b/110082001.
2263TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) {
2264 // This test mimics the scenario when a dynamic stream retransmits lost data
2265 // and causes connection close.
2266 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2267 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2268 QuicStreamFrame frame(stream->id(), false, 0, 9);
2269
2270 EXPECT_CALL(*stream, HasPendingRetransmission())
2271 .Times(2)
2272 .WillOnce(Return(true))
2273 .WillOnce(Return(false));
2274 session_.OnFrameLost(QuicFrame(frame));
2275 // Retransmit stream data causes connection close. Stream has not sent fin
2276 // yet, so an RST is sent.
2277 EXPECT_CALL(*stream, OnCanWrite())
2278 .WillOnce(Invoke(stream, &QuicStream::OnClose));
fkastenholz305e1732019-06-18 05:01:22 -07002279 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002280 // Once for the RST_STREAM, once for the STOP_SENDING
2281 EXPECT_CALL(*connection_, SendControlFrame(_))
2282 .Times(2)
2283 .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
2284 } else {
2285 // Just for the RST_STREAM
2286 EXPECT_CALL(*connection_, SendControlFrame(_))
2287 .WillOnce(Invoke(&session_, &TestSession::SaveFrame));
2288 }
2289 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
2290 session_.OnCanWrite();
2291}
2292
2293TEST_P(QuicSessionTestServer, SendMessage) {
2294 // Cannot send message when encryption is not established.
2295 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
2296 quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
2297 EXPECT_EQ(MessageResult(MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0),
2298 session_.SendMessage(
2299 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2300 "", &storage)));
2301
2302 // Finish handshake.
2303 CryptoHandshakeMessage handshake_message;
2304 session_.GetMutableCryptoStream()->OnHandshakeMessage(handshake_message);
2305 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
2306
2307 QuicStringPiece message;
2308 EXPECT_CALL(*connection_, SendMessage(1, _))
2309 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2310 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
2311 session_.SendMessage(
2312 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2313 message, &storage)));
2314 // Verify message_id increases.
2315 EXPECT_CALL(*connection_, SendMessage(2, _))
2316 .WillOnce(Return(MESSAGE_STATUS_TOO_LARGE));
2317 EXPECT_EQ(MessageResult(MESSAGE_STATUS_TOO_LARGE, 0),
2318 session_.SendMessage(
2319 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2320 message, &storage)));
2321 // Verify unsent message does not consume a message_id.
2322 EXPECT_CALL(*connection_, SendMessage(2, _))
2323 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2324 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 2),
2325 session_.SendMessage(
2326 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2327 message, &storage)));
2328
2329 QuicMessageFrame frame(1);
2330 QuicMessageFrame frame2(2);
2331 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2332 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2333
2334 // Lost message 2.
2335 session_.OnMessageLost(2);
2336 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2337
2338 // message 1 gets acked.
QUICHE team9467db02019-05-30 09:38:45 -07002339 session_.OnMessageAcked(1, QuicTime::Zero());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002340 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2341}
2342
2343// Regression test of b/115323618.
2344TEST_P(QuicSessionTestServer, LocallyResetZombieStreams) {
nharperf5e68452019-05-29 17:24:18 -07002345 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
2346 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
2347 // enabled and fix it.
2348 return;
2349 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002350 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
2351
2352 session_.set_writev_consumes_all_data(true);
2353 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07002354 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002355 stream2->CloseReadSide();
2356 stream2->WriteOrBufferData(body, true, nullptr);
2357 EXPECT_TRUE(stream2->IsWaitingForAcks());
2358 // Verify stream2 is a zombie streams.
2359 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2360
2361 QuicStreamFrame frame(stream2->id(), true, 0, 100);
2362 EXPECT_CALL(*stream2, HasPendingRetransmission())
2363 .WillRepeatedly(Return(true));
2364 session_.OnFrameLost(QuicFrame(frame));
2365
2366 // Reset stream2 locally.
2367 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002368 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002369 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2370 stream2->Reset(QUIC_STREAM_CANCELLED);
2371
2372 // Verify stream 2 gets closed.
2373 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2374 EXPECT_TRUE(session_.IsClosedStream(stream2->id()));
2375 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
2376 session_.OnCanWrite();
2377}
2378
2379TEST_P(QuicSessionTestServer, CleanUpClosedStreamsAlarm) {
2380 EXPECT_FALSE(
2381 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2382
2383 session_.set_writev_consumes_all_data(true);
2384 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2385 EXPECT_FALSE(stream2->IsWaitingForAcks());
2386
2387 EXPECT_CALL(*connection_, SendControlFrame(_));
2388 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2389 session_.CloseStream(stream2->id());
2390 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2391 EXPECT_EQ(1u, session_.closed_streams()->size());
2392 EXPECT_TRUE(
2393 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2394
2395 alarm_factory_.FireAlarm(
2396 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_));
2397 EXPECT_TRUE(session_.closed_streams()->empty());
2398}
2399
2400TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
nharperf5e68452019-05-29 17:24:18 -07002401 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
2402 // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
2403 // enabled and fix it.
2404 return;
2405 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002406 session_.set_writev_consumes_all_data(true);
2407 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2408 &session_, WRITE_UNIDIRECTIONAL);
2409 session_.ActivateStream(QuicWrapUnique(stream4));
vasilvvc48c8712019-03-11 13:38:16 -07002410 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002411 stream4->WriteOrBufferData(body, false, nullptr);
2412 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2413 stream4->WriteOrBufferData(body, true, nullptr);
2414 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2415}
2416
2417TEST_P(QuicSessionTestServer, ReceivedDataOnWriteUnidirectionalStream) {
2418 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2419 &session_, WRITE_UNIDIRECTIONAL);
2420 session_.ActivateStream(QuicWrapUnique(stream4));
2421
2422 EXPECT_CALL(
2423 *connection_,
2424 CloseConnection(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM, _, _))
2425 .Times(1);
2426 QuicStreamFrame stream_frame(GetNthServerInitiatedUnidirectionalId(1), false,
2427 0, 2);
2428 session_.OnStreamFrame(stream_frame);
2429}
2430
2431TEST_P(QuicSessionTestServer, ReadUnidirectionalStream) {
2432 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2433 &session_, READ_UNIDIRECTIONAL);
2434 session_.ActivateStream(QuicWrapUnique(stream4));
2435 EXPECT_FALSE(stream4->IsWaitingForAcks());
2436 // Discard all incoming data.
2437 stream4->StopReading();
2438
vasilvvc48c8712019-03-11 13:38:16 -07002439 std::string data(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002440 QuicStreamFrame stream_frame(GetNthClientInitiatedUnidirectionalId(1), false,
2441 0, data);
2442 stream4->OnStreamFrame(stream_frame);
2443 EXPECT_TRUE(session_.closed_streams()->empty());
2444
2445 QuicStreamFrame stream_frame2(GetNthClientInitiatedUnidirectionalId(1), true,
2446 100, data);
2447 stream4->OnStreamFrame(stream_frame2);
2448 EXPECT_EQ(1u, session_.closed_streams()->size());
2449}
2450
2451TEST_P(QuicSessionTestServer, WriteOrBufferDataOnReadUnidirectionalStream) {
2452 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2453 &session_, READ_UNIDIRECTIONAL);
2454 session_.ActivateStream(QuicWrapUnique(stream4));
2455
2456 EXPECT_CALL(*connection_,
2457 CloseConnection(
2458 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2459 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002460 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002461 stream4->WriteOrBufferData(body, false, nullptr);
2462}
2463
2464TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
2465 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2466 &session_, READ_UNIDIRECTIONAL);
2467 session_.ActivateStream(QuicWrapUnique(stream4));
2468
2469 EXPECT_CALL(*connection_,
2470 CloseConnection(
2471 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2472 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002473 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002474 struct iovec iov = {const_cast<char*>(body.data()), body.length()};
2475 QuicMemSliceStorage storage(
2476 &iov, 1, session_.connection()->helper()->GetStreamSendBufferAllocator(),
2477 1024);
2478 stream4->WriteMemSlices(storage.ToSpan(), false);
2479}
2480
2481TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
2482 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2483 &session_, READ_UNIDIRECTIONAL);
2484 session_.ActivateStream(QuicWrapUnique(stream4));
2485
2486 EXPECT_CALL(*connection_,
2487 CloseConnection(
2488 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2489 .Times(1);
2490 char data[1024];
2491 std::vector<std::pair<char*, size_t>> buffers;
2492 buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
2493 buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
2494 QuicTestMemSliceVector vector(buffers);
2495 stream4->WriteMemSlices(vector.span(), false);
2496}
2497
2498// Test code that tests that an incoming stream frame with a new (not previously
2499// seen) stream id is acceptable. The ID must not be larger than has been
2500// advertised. It may be equal to what has been advertised. These tests
2501// invoke QuicStreamIdManager::MaybeIncreaseLargestPeerStreamId by calling
2502// QuicSession::OnStreamFrame in order to check that all the steps are connected
2503// properly and that nothing in the call path interferes with the check.
2504// First test make sure that streams with ids below the limit are accepted.
2505TEST_P(QuicSessionTestServer, NewStreamIdBelowLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002506 if (!VersionHasIetfQuicFrames(transport_version())) {
2507 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002508 return;
2509 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002510 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002511 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002512 ->advertised_max_allowed_incoming_bidirectional_streams() -
2513 1,
2514 Perspective::IS_CLIENT,
2515 /*bidirectional=*/true);
2516
QUICHE teama6ef0a62019-03-07 20:34:33 -05002517 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2518 "Random String");
2519 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2520 session_.OnStreamFrame(bidirectional_stream_frame);
2521
fkastenholz3c4eabf2019-04-22 07:49:59 -07002522 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002523 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002524 ->advertised_max_allowed_incoming_unidirectional_streams() -
2525 1,
2526 Perspective::IS_CLIENT,
2527 /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002528 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2529 0, "Random String");
2530 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2531 session_.OnStreamFrame(unidirectional_stream_frame);
2532}
2533
2534// Accept a stream with an ID that equals the limit.
2535TEST_P(QuicSessionTestServer, NewStreamIdAtLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002536 if (!VersionHasIetfQuicFrames(transport_version())) {
2537 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002538 return;
2539 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002540 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002541 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002542 ->advertised_max_allowed_incoming_bidirectional_streams(),
2543 Perspective::IS_CLIENT, /*bidirectional=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002544 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2545 "Random String");
2546 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2547 session_.OnStreamFrame(bidirectional_stream_frame);
2548
fkastenholz3c4eabf2019-04-22 07:49:59 -07002549 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002550 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002551 ->advertised_max_allowed_incoming_unidirectional_streams(),
2552 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002553 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2554 0, "Random String");
2555 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2556 session_.OnStreamFrame(unidirectional_stream_frame);
2557}
2558
2559// Close the connection if the id exceeds the limit.
2560TEST_P(QuicSessionTestServer, NewStreamIdAboveLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002561 if (!VersionHasIetfQuicFrames(transport_version())) {
2562 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002563 return;
2564 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002565 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002566 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002567 ->advertised_max_allowed_incoming_bidirectional_streams() +
2568 1,
2569 Perspective::IS_CLIENT, /*bidirectional=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002570 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2571 "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002572 EXPECT_CALL(
2573 *connection_,
2574 CloseConnection(QUIC_INVALID_STREAM_ID,
nharpercd820e02019-05-16 15:12:07 -07002575 "Stream id 400 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002576 session_.OnStreamFrame(bidirectional_stream_frame);
2577
fkastenholz3c4eabf2019-04-22 07:49:59 -07002578 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002579 QuicSessionPeer::v99_streamid_manager(&session_)
fkastenholz3c4eabf2019-04-22 07:49:59 -07002580 ->advertised_max_allowed_incoming_unidirectional_streams() +
2581 1,
2582 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002583 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2584 0, "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002585 EXPECT_CALL(
2586 *connection_,
2587 CloseConnection(QUIC_INVALID_STREAM_ID,
2588 "Stream id 402 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002589 session_.OnStreamFrame(unidirectional_stream_frame);
2590}
2591
2592// Check that the OnStopSendingFrame upcall handles bad input properly
2593// First test checks that invalid stream ids are handled.
2594TEST_P(QuicSessionTestServer, OnStopSendingInputInvalidStreamId) {
fkastenholz305e1732019-06-18 05:01:22 -07002595 if (!VersionHasIetfQuicFrames(transport_version())) {
2596 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002597 return;
2598 }
2599 // Check that "invalid" stream ids are rejected.
2600 // Note that the notion of an invalid stream id is Google-specific.
2601 QuicStopSendingFrame frame(1, -1, 123);
2602 EXPECT_CALL(
2603 *connection_,
2604 CloseConnection(QUIC_INVALID_STREAM_ID,
2605 "Received STOP_SENDING for an invalid stream", _));
2606 EXPECT_FALSE(session_.OnStopSendingFrame(frame));
2607}
2608
2609// Second test, streams in the static stream map are not subject to
2610// STOP_SENDING; it's ignored.
2611TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
fkastenholz305e1732019-06-18 05:01:22 -07002612 if (!VersionHasIetfQuicFrames(transport_version())) {
2613 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002614 return;
2615 }
nharper46833c32019-05-15 21:33:05 -07002616 QuicStreamId stream_id = 0;
vasilvv0fc587f2019-09-06 13:33:08 -07002617 std::unique_ptr<TestStream> fake_static_stream = std::make_unique<TestStream>(
nharper46833c32019-05-15 21:33:05 -07002618 stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07002619 QuicSessionPeer::ActivateStream(&session_, std::move(fake_static_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002620 // Check that a stream id in the static stream map is ignored.
2621 // Note that the notion of a static stream is Google-specific.
nharper46833c32019-05-15 21:33:05 -07002622 QuicStopSendingFrame frame(1, stream_id, 123);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002623 EXPECT_CALL(*connection_,
2624 CloseConnection(QUIC_INVALID_STREAM_ID,
2625 "Received STOP_SENDING for a static stream", _));
2626 EXPECT_FALSE(session_.OnStopSendingFrame(frame));
2627}
2628
2629// Third test, if stream id specifies a closed stream:
2630// return true and do not close the connection.
2631TEST_P(QuicSessionTestServer, OnStopSendingInputClosedStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002632 if (!VersionHasIetfQuicFrames(transport_version())) {
2633 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002634 return;
2635 }
2636
2637 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2638 QuicStreamId stream_id = stream->id();
2639 // Expect these as side effect of the close operations.
2640 EXPECT_CALL(*connection_, SendControlFrame(_));
2641 EXPECT_CALL(*connection_, OnStreamReset(_, _));
2642 stream->CloseWriteSide();
2643 stream->CloseReadSide();
2644 QuicStopSendingFrame frame(1, stream_id, 123);
2645 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2646 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
2647}
2648
2649// Fourth test, if stream id specifies a nonexistent stream, return false and
2650// close the connection
2651TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002652 if (!VersionHasIetfQuicFrames(transport_version())) {
2653 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002654 return;
2655 }
2656
2657 QuicStopSendingFrame frame(1, GetNthServerInitiatedBidirectionalId(123456),
2658 123);
2659 EXPECT_CALL(
2660 *connection_,
2661 CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
2662 "Received STOP_SENDING for a non-existent stream", _))
2663 .Times(1);
2664 EXPECT_FALSE(session_.OnStopSendingFrame(frame));
2665}
2666
2667// For a valid stream, ensure that all works
2668TEST_P(QuicSessionTestServer, OnStopSendingInputValidStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002669 if (!VersionHasIetfQuicFrames(transport_version())) {
2670 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002671 return;
2672 }
2673
2674 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2675
2676 // Ensure that the stream starts out open in both directions.
bncc7d9e0c2019-04-16 10:22:15 -07002677 EXPECT_FALSE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002678 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
2679
2680 QuicStreamId stream_id = stream->id();
2681 QuicStopSendingFrame frame(1, stream_id, 123);
2682 EXPECT_CALL(*stream, OnStopSending(123));
2683 // Expect a reset to come back out.
2684 EXPECT_CALL(*connection_, SendControlFrame(_));
2685 EXPECT_CALL(
2686 *connection_,
2687 OnStreamReset(stream_id, static_cast<QuicRstStreamErrorCode>(123)));
2688 EXPECT_TRUE(session_.OnStopSendingFrame(frame));
2689 // When the STOP_SENDING is received, the node generates a RST_STREAM,
2690 // which closes the stream in the write direction. Ensure this.
2691 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
bncc7d9e0c2019-04-16 10:22:15 -07002692 EXPECT_TRUE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002693}
2694
fayangaee31ef2019-08-20 06:47:51 -07002695TEST_P(QuicSessionTestServer, WriteBufferedCryptoFrames) {
2696 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
2697 return;
2698 }
2699 std::string data(1350, 'a');
2700 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
2701 // Only consumed 1000 bytes.
2702 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 1350, 0))
2703 .WillOnce(Return(1000));
2704 crypto_stream->WriteCryptoData(ENCRYPTION_INITIAL, data);
2705 EXPECT_TRUE(session_.HasPendingHandshake());
2706 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2707
2708 EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
2709 crypto_stream->WriteCryptoData(ENCRYPTION_ZERO_RTT, data);
2710
2711 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 350, 1000))
2712 .WillOnce(Return(350));
2713 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1350, 0))
2714 .WillOnce(Return(1350));
2715 session_.OnCanWrite();
2716 EXPECT_FALSE(session_.HasPendingHandshake());
2717 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2718}
2719
QUICHE teama6ef0a62019-03-07 20:34:33 -05002720} // namespace
2721} // namespace test
2722} // namespace quic