blob: 4ee12302045d58066f71487343101e3ae3f6b1d3 [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"
dschinaziaab68182019-10-09 15:39:51 -070014#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050015#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
16#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
17#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
18#include "net/third_party/quiche/src/quic/core/quic_packets.h"
19#include "net/third_party/quiche/src/quic/core/quic_stream.h"
20#include "net/third_party/quiche/src/quic/core/quic_utils.h"
dschinaziaab68182019-10-09 15:39:51 -070021#include "net/third_party/quiche/src/quic/core/quic_versions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050022#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
24#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
26#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
27#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
28#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050029#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
30#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
31#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
32#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
35#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
36#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
fkastenholz56055be2019-09-17 11:17:37 -070037#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050038#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
39#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
40#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
41
42using spdy::kV3HighestPriority;
43using spdy::SpdyPriority;
44using testing::_;
45using testing::AtLeast;
46using testing::InSequence;
47using testing::Invoke;
48using testing::NiceMock;
49using testing::Return;
50using testing::StrictMock;
51using testing::WithArg;
52
53namespace quic {
54namespace test {
55namespace {
56
57class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
58 public:
59 explicit TestCryptoStream(QuicSession* session)
60 : QuicCryptoStream(session),
61 QuicCryptoHandshaker(this, session),
62 encryption_established_(false),
63 handshake_confirmed_(false),
64 params_(new QuicCryptoNegotiatedParameters) {}
65
66 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
67 encryption_established_ = true;
68 handshake_confirmed_ = true;
dschinaziaab68182019-10-09 15:39:51 -070069 QuicErrorCode error;
vasilvvc48c8712019-03-11 13:38:16 -070070 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -050071 session()->config()->SetInitialStreamFlowControlWindowToSend(
72 kInitialStreamFlowControlWindowForTest);
73 session()->config()->SetInitialSessionFlowControlWindowToSend(
74 kInitialSessionFlowControlWindowForTest);
dschinaziaab68182019-10-09 15:39:51 -070075 if (session()->connection()->version().handshake_protocol ==
76 PROTOCOL_TLS1_3) {
77 TransportParameters transport_parameters;
78 EXPECT_TRUE(
79 session()->config()->FillTransportParameters(&transport_parameters));
80 error = session()->config()->ProcessTransportParameters(
81 transport_parameters, CLIENT, &error_details);
82 } else {
83 CryptoHandshakeMessage msg;
84 session()->config()->ToHandshakeMessage(&msg, transport_version());
85 error =
86 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
87 }
bncf6f82b12019-10-30 07:01:01 -070088 EXPECT_THAT(error, IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -050089 session()->OnConfigNegotiated();
90 session()->connection()->SetDefaultEncryptionLevel(
91 ENCRYPTION_FORWARD_SECURE);
92 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
93 }
94
95 // QuicCryptoStream implementation
96 bool encryption_established() const override {
97 return encryption_established_;
98 }
99 bool handshake_confirmed() const override { return handshake_confirmed_; }
100 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
101 const override {
102 return *params_;
103 }
104 CryptoMessageParser* crypto_message_parser() override {
105 return QuicCryptoHandshaker::crypto_message_parser();
106 }
107
108 MOCK_METHOD0(OnCanWrite, void());
nharper46833c32019-05-15 21:33:05 -0700109 bool HasPendingCryptoRetransmission() const override { return false; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110
111 MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
112
113 private:
114 using QuicCryptoStream::session;
115
116 bool encryption_established_;
117 bool handshake_confirmed_;
118 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
119};
120
121class TestStream : public QuicStream {
122 public:
123 TestStream(QuicStreamId id, QuicSession* session, StreamType type)
nharper46833c32019-05-15 21:33:05 -0700124 : TestStream(id, session, /*is_static=*/false, type) {}
125
126 TestStream(QuicStreamId id,
127 QuicSession* session,
128 bool is_static,
129 StreamType type)
130 : QuicStream(id, session, is_static, type) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131
renjietangbaea59c2019-05-29 15:08:14 -0700132 TestStream(PendingStream* pending, StreamType type)
133 : QuicStream(pending, type, /*is_static=*/false) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134
135 using QuicStream::CloseReadSide;
136 using QuicStream::CloseWriteSide;
137 using QuicStream::WriteMemSlices;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138
139 void OnDataAvailable() override {}
140
141 MOCK_METHOD0(OnCanWrite, void());
142 MOCK_METHOD3(RetransmitStreamData,
143 bool(QuicStreamOffset, QuicByteCount, bool));
144
145 MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146};
147
148class TestSession : public QuicSession {
149 public:
150 explicit TestSession(QuicConnection* connection,
151 MockQuicSessionVisitor* session_visitor)
152 : QuicSession(connection,
153 session_visitor,
154 DefaultQuicConfig(),
renjietang216dc012019-08-27 11:28:27 -0700155 CurrentSupportedVersions(),
156 /*num_expected_unidirectional_static_streams = */ 0),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157 crypto_stream_(this),
158 writev_consumes_all_data_(false),
renjietange76b2da2019-05-13 14:50:23 -0700159 uses_pending_streams_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 num_incoming_streams_created_(0) {
161 Initialize();
162 this->connection()->SetEncrypter(
163 ENCRYPTION_FORWARD_SECURE,
vasilvv0fc587f2019-09-06 13:33:08 -0700164 std::make_unique<NullEncrypter>(connection->perspective()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500165 }
166
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700167 ~TestSession() override {
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700168 delete connection();
169 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170
171 TestCryptoStream* GetMutableCryptoStream() override {
172 return &crypto_stream_;
173 }
174
175 const TestCryptoStream* GetCryptoStream() const override {
176 return &crypto_stream_;
177 }
178
179 TestStream* CreateOutgoingBidirectionalStream() {
180 QuicStreamId id = GetNextOutgoingBidirectionalStreamId();
181 if (id ==
182 QuicUtils::GetInvalidStreamId(connection()->transport_version())) {
183 return nullptr;
184 }
185 TestStream* stream = new TestStream(id, this, BIDIRECTIONAL);
186 ActivateStream(QuicWrapUnique(stream));
187 return stream;
188 }
189
190 TestStream* CreateOutgoingUnidirectionalStream() {
191 TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
192 this, WRITE_UNIDIRECTIONAL);
193 ActivateStream(QuicWrapUnique(stream));
194 return stream;
195 }
196
197 TestStream* CreateIncomingStream(QuicStreamId id) override {
198 // Enforce the limit on the number of open streams.
199 if (GetNumOpenIncomingStreams() + 1 >
200 max_open_incoming_bidirectional_streams() &&
fkastenholz305e1732019-06-18 05:01:22 -0700201 !VersionHasIetfQuicFrames(connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500202 // No need to do this test for version 99; it's done by
renjietang880d2432019-07-16 13:14:37 -0700203 // QuicSession::GetOrCreateStream.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500204 connection()->CloseConnection(
205 QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
206 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
207 return nullptr;
208 }
209
210 TestStream* stream =
211 new TestStream(id, this,
212 DetermineStreamType(
213 id, connection()->transport_version(), perspective(),
214 /*is_incoming=*/true, BIDIRECTIONAL));
215 ActivateStream(QuicWrapUnique(stream));
216 ++num_incoming_streams_created_;
217 return stream;
218 }
219
renjietangbaea59c2019-05-29 15:08:14 -0700220 TestStream* CreateIncomingStream(PendingStream* pending) override {
221 QuicStreamId id = pending->id();
222 TestStream* stream = new TestStream(
223 pending, DetermineStreamType(id, connection()->transport_version(),
224 perspective(),
225 /*is_incoming=*/true, BIDIRECTIONAL));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226 ActivateStream(QuicWrapUnique(stream));
227 ++num_incoming_streams_created_;
228 return stream;
229 }
230
renjietange76b2da2019-05-13 14:50:23 -0700231 // QuicSession doesn't do anything in this method. So it's overridden here to
232 // test that the session handles pending streams correctly in terms of
233 // receiving stream frames.
renjietangbb1c4892019-05-24 15:58:44 -0700234 bool ProcessPendingStream(PendingStream* pending) override {
renjietange76b2da2019-05-13 14:50:23 -0700235 struct iovec iov;
236 if (pending->sequencer()->GetReadableRegion(&iov)) {
237 // Create TestStream once the first byte is received.
renjietangbaea59c2019-05-29 15:08:14 -0700238 CreateIncomingStream(pending);
renjietangbb1c4892019-05-24 15:58:44 -0700239 return true;
renjietange76b2da2019-05-13 14:50:23 -0700240 }
renjietangbb1c4892019-05-24 15:58:44 -0700241 return false;
renjietange76b2da2019-05-13 14:50:23 -0700242 }
243
QUICHE teama6ef0a62019-03-07 20:34:33 -0500244 bool IsClosedStream(QuicStreamId id) {
245 return QuicSession::IsClosedStream(id);
246 }
247
renjietang880d2432019-07-16 13:14:37 -0700248 QuicStream* GetOrCreateStream(QuicStreamId stream_id) {
249 return QuicSession::GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250 }
251
252 bool ShouldKeepConnectionAlive() const override {
renjietang17e29932019-08-08 10:04:31 -0700253 return GetNumActiveStreams() > 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500254 }
255
256 QuicConsumedData WritevData(QuicStream* stream,
257 QuicStreamId id,
258 size_t write_length,
259 QuicStreamOffset offset,
260 StreamSendingState state) override {
261 bool fin = state != NO_FIN;
262 QuicConsumedData consumed(write_length, fin);
263 if (!writev_consumes_all_data_) {
264 consumed =
265 QuicSession::WritevData(stream, id, write_length, offset, state);
266 }
267 if (fin && consumed.fin_consumed) {
268 stream->set_fin_sent(true);
269 }
270 QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
271 id, consumed.bytes_consumed);
272 return consumed;
273 }
274
fkastenholz8556dc22019-07-18 12:42:38 -0700275 MOCK_METHOD1(OnCanCreateNewOutgoingStream, void(bool unidirectional));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500276
277 void set_writev_consumes_all_data(bool val) {
278 writev_consumes_all_data_ = val;
279 }
280
281 QuicConsumedData SendStreamData(QuicStream* stream) {
282 struct iovec iov;
nharper46833c32019-05-15 21:33:05 -0700283 if (!QuicUtils::IsCryptoStreamId(connection()->transport_version(),
284 stream->id()) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285 this->connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
286 this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
287 }
288 MakeIOVector("not empty", &iov);
289 QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
290 QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
291 QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
292 consumed.bytes_consumed);
293 return consumed;
294 }
295
fkastenholz56055be2019-09-17 11:17:37 -0700296 const QuicFrame& save_frame() { return save_frame_; }
297
QUICHE teama6ef0a62019-03-07 20:34:33 -0500298 bool SaveFrame(const QuicFrame& frame) {
299 save_frame_ = frame;
300 DeleteFrame(&const_cast<QuicFrame&>(frame));
301 return true;
302 }
303
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
305 DCHECK(writev_consumes_all_data_);
306 return WritevData(stream, stream->id(), bytes, 0, FIN);
307 }
308
renjietange76b2da2019-05-13 14:50:23 -0700309 bool UsesPendingStreams() const override { return uses_pending_streams_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500310
renjietange76b2da2019-05-13 14:50:23 -0700311 void set_uses_pending_streams(bool uses_pending_streams) {
312 uses_pending_streams_ = uses_pending_streams;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 }
314
315 int num_incoming_streams_created() const {
316 return num_incoming_streams_created_;
317 }
318
319 using QuicSession::ActivateStream;
fkastenholz56055be2019-09-17 11:17:37 -0700320 using QuicSession::CanOpenNextOutgoingUnidirectionalStream;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500321 using QuicSession::closed_streams;
322 using QuicSession::zombie_streams;
323
324 private:
325 StrictMock<TestCryptoStream> crypto_stream_;
326
327 bool writev_consumes_all_data_;
renjietange76b2da2019-05-13 14:50:23 -0700328 bool uses_pending_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500329 QuicFrame save_frame_;
330 int num_incoming_streams_created_;
331};
332
333class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
334 protected:
fkastenholz56055be2019-09-17 11:17:37 -0700335 QuicSessionTestBase(Perspective perspective, bool configure_session)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500336 : connection_(
337 new StrictMock<MockQuicConnection>(&helper_,
338 &alarm_factory_,
339 perspective,
340 SupportedVersions(GetParam()))),
fkastenholz56055be2019-09-17 11:17:37 -0700341 session_(connection_, &session_visitor_),
342 configure_session_(configure_session) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343 session_.config()->SetInitialStreamFlowControlWindowToSend(
344 kInitialStreamFlowControlWindowForTest);
345 session_.config()->SetInitialSessionFlowControlWindowToSend(
346 kInitialSessionFlowControlWindowForTest);
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700347
fkastenholz56055be2019-09-17 11:17:37 -0700348 if (configure_session) {
dschinazi18cdf132019-10-09 16:08:18 -0700349 QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
350 session_.config(), kDefaultMaxStreamsPerConnection);
351 QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
352 session_.config(), kDefaultMaxStreamsPerConnection);
353 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
354 session_.config(), kMinimumFlowControlSendWindow);
355 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
356 session_.config(), kMinimumFlowControlSendWindow);
357 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
358 session_.config(), kMinimumFlowControlSendWindow);
359 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
360 session_.config(), kMinimumFlowControlSendWindow);
361 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
fkastenholz56055be2019-09-17 11:17:37 -0700362 session_.OnConfigNegotiated();
363 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500364 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
365 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
366 .Times(testing::AnyNumber());
367 }
368
fkastenholz56055be2019-09-17 11:17:37 -0700369 ~QuicSessionTestBase() {
370 if (configure_session_) {
371 EXPECT_TRUE(session_.is_configured());
372 }
373 }
374
QUICHE teama6ef0a62019-03-07 20:34:33 -0500375 void CheckClosedStreams() {
QUICHE teamdc41bf12019-03-20 12:58:42 -0700376 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
377 connection_->transport_version(), Perspective::IS_CLIENT);
378 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
379 first_stream_id =
380 QuicUtils::GetCryptoStreamId(connection_->transport_version());
381 }
382 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500383 if (!QuicContainsKey(closed_streams_, i)) {
384 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
385 } else {
386 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
387 }
388 }
389 }
390
391 void CloseStream(QuicStreamId id) {
renjietangd9762282019-11-11 17:11:18 -0800392 if (VersionHasIetfQuicFrames(transport_version())) {
393 if (QuicUtils::GetStreamType(id, session_.perspective(),
394 session_.IsIncomingStream(id)) ==
395 READ_UNIDIRECTIONAL) {
396 // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
397 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
398 EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
399 } else if (QuicUtils::GetStreamType(id, session_.perspective(),
400 session_.IsIncomingStream(id)) ==
401 WRITE_UNIDIRECTIONAL) {
402 // Verify RESET_STREAM but not STOP_SENDING is sent for write-only
403 // stream.
404 EXPECT_CALL(*connection_, SendControlFrame(_))
405 .Times(1)
406 .WillOnce(Invoke(&ClearControlFrame));
407 EXPECT_CALL(*connection_, OnStreamReset(id, _));
408 } else {
409 // Verify RESET_STREAM and STOP_SENDING are sent for BIDIRECTIONAL
410 // streams.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500411 EXPECT_CALL(*connection_, SendControlFrame(_))
412 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -0700413 .WillRepeatedly(Invoke(&ClearControlFrame));
renjietangd9762282019-11-11 17:11:18 -0800414 EXPECT_CALL(*connection_, OnStreamReset(id, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500415 }
renjietangd9762282019-11-11 17:11:18 -0800416 } else {
417 EXPECT_CALL(*connection_, SendControlFrame(_))
418 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500419 EXPECT_CALL(*connection_, OnStreamReset(id, _));
420 }
421 session_.CloseStream(id);
422 closed_streams_.insert(id);
423 }
424
425 QuicTransportVersion transport_version() const {
426 return connection_->transport_version();
427 }
428
429 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
430 return QuicUtils::GetFirstBidirectionalStreamId(
431 connection_->transport_version(), Perspective::IS_CLIENT) +
432 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
433 }
434
435 QuicStreamId GetNthClientInitiatedUnidirectionalId(int n) {
436 return QuicUtils::GetFirstUnidirectionalStreamId(
437 connection_->transport_version(), Perspective::IS_CLIENT) +
438 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
439 }
440
441 QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
442 return QuicUtils::GetFirstBidirectionalStreamId(
443 connection_->transport_version(), Perspective::IS_SERVER) +
444 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
445 }
446
447 QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
448 return QuicUtils::GetFirstUnidirectionalStreamId(
449 connection_->transport_version(), Perspective::IS_SERVER) +
450 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
451 }
452
fkastenholz3c4eabf2019-04-22 07:49:59 -0700453 QuicStreamId StreamCountToId(QuicStreamCount stream_count,
454 Perspective perspective,
455 bool bidirectional) {
456 // Calculate and build up stream ID rather than use
457 // GetFirst... because tests that rely on this method
458 // needs to do the stream count where #1 is 0/1/2/3, and not
459 // take into account that stream 0 is special.
460 QuicStreamId id =
fkastenholz305e1732019-06-18 05:01:22 -0700461 ((stream_count - 1) * QuicUtils::StreamIdDelta(transport_version()));
fkastenholz3c4eabf2019-04-22 07:49:59 -0700462 if (!bidirectional) {
463 id |= 0x2;
464 }
465 if (perspective == Perspective::IS_SERVER) {
466 id |= 0x1;
467 }
468 return id;
469 }
470
QUICHE teama6ef0a62019-03-07 20:34:33 -0500471 MockQuicConnectionHelper helper_;
472 MockAlarmFactory alarm_factory_;
473 NiceMock<MockQuicSessionVisitor> session_visitor_;
474 StrictMock<MockQuicConnection>* connection_;
475 TestSession session_;
476 std::set<QuicStreamId> closed_streams_;
fkastenholz56055be2019-09-17 11:17:37 -0700477 bool configure_session_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500478};
479
480class QuicSessionTestServer : public QuicSessionTestBase {
481 public:
482 // CheckMultiPathResponse validates that a written packet
483 // contains both expected path responses.
484 WriteResult CheckMultiPathResponse(const char* buffer,
485 size_t buf_len,
dschinazi17d42422019-06-18 16:35:07 -0700486 const QuicIpAddress& /*self_address*/,
487 const QuicSocketAddress& /*peer_address*/,
488 PerPacketOptions* /*options*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500489 QuicEncryptedPacket packet(buffer, buf_len);
490 {
491 InSequence s;
492 EXPECT_CALL(framer_visitor_, OnPacket());
493 EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
494 EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
495 EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
496 EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
497 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
498 .WillOnce(
499 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
500 EXPECT_EQ(path_frame_buffer1_, frame.data_buffer);
501 return true;
502 })));
503 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
504 .WillOnce(
505 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
506 EXPECT_EQ(path_frame_buffer2_, frame.data_buffer);
507 return true;
508 })));
509 EXPECT_CALL(framer_visitor_, OnPacketComplete());
510 }
511 client_framer_.ProcessPacket(packet);
512 return WriteResult(WRITE_STATUS_OK, 0);
513 }
514
515 protected:
516 QuicSessionTestServer()
fkastenholz56055be2019-09-17 11:17:37 -0700517 : QuicSessionTestBase(Perspective::IS_SERVER, /*configure_session=*/true),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518 path_frame_buffer1_({0, 1, 2, 3, 4, 5, 6, 7}),
519 path_frame_buffer2_({8, 9, 10, 11, 12, 13, 14, 15}),
520 client_framer_(SupportedVersions(GetParam()),
521 QuicTime::Zero(),
522 Perspective::IS_CLIENT,
523 kQuicDefaultConnectionIdLength) {
524 client_framer_.set_visitor(&framer_visitor_);
nharperc6b99512019-09-19 11:13:48 -0700525 client_framer_.SetInitialObfuscators(TestConnectionId());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500526 }
527
528 QuicPathFrameBuffer path_frame_buffer1_;
529 QuicPathFrameBuffer path_frame_buffer2_;
530 StrictMock<MockFramerVisitor> framer_visitor_;
531 // Framer used to process packets sent by server.
532 QuicFramer client_framer_;
533};
534
535INSTANTIATE_TEST_SUITE_P(Tests,
536 QuicSessionTestServer,
dschinazi142051a2019-09-18 18:17:29 -0700537 ::testing::ValuesIn(AllSupportedVersions()),
538 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500539
540TEST_P(QuicSessionTestServer, PeerAddress) {
541 EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
542 session_.peer_address());
543}
544
545TEST_P(QuicSessionTestServer, SelfAddress) {
546 EXPECT_TRUE(session_.self_address().IsInitialized());
547}
548
549TEST_P(QuicSessionTestServer, DontCallOnWriteBlockedForDisconnectedConnection) {
550 EXPECT_CALL(*connection_, CloseConnection(_, _, _))
551 .WillOnce(
552 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
553 connection_->CloseConnection(QUIC_NO_ERROR, "Everything is fine.",
554 ConnectionCloseBehavior::SILENT_CLOSE);
555 ASSERT_FALSE(connection_->connected());
556
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700557 EXPECT_CALL(session_visitor_, OnWriteBlocked(_)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500558 session_.OnWriteBlocked();
559}
560
561TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
562 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
563 CryptoHandshakeMessage message;
564 session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
565 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
566}
567
568TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
569 // Ensure that no streams are initially closed.
QUICHE teamdc41bf12019-03-20 12:58:42 -0700570 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
571 connection_->transport_version(), Perspective::IS_CLIENT);
572 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
573 first_stream_id =
574 QuicUtils::GetCryptoStreamId(connection_->transport_version());
575 }
576 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500577 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
578 }
579}
580
581TEST_P(QuicSessionTestServer, AvailableBidirectionalStreams) {
renjietang880d2432019-07-16 13:14:37 -0700582 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500583 GetNthClientInitiatedBidirectionalId(3)) != nullptr);
584 // Smaller bidirectional streams should be available.
585 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
586 &session_, GetNthClientInitiatedBidirectionalId(1)));
587 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
588 &session_, GetNthClientInitiatedBidirectionalId(2)));
renjietang880d2432019-07-16 13:14:37 -0700589 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500590 GetNthClientInitiatedBidirectionalId(2)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -0700591 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500592 GetNthClientInitiatedBidirectionalId(1)) != nullptr);
593}
594
595TEST_P(QuicSessionTestServer, AvailableUnidirectionalStreams) {
renjietang880d2432019-07-16 13:14:37 -0700596 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500597 GetNthClientInitiatedUnidirectionalId(3)) != nullptr);
598 // Smaller unidirectional streams should be available.
599 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
600 &session_, GetNthClientInitiatedUnidirectionalId(1)));
601 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
602 &session_, GetNthClientInitiatedUnidirectionalId(2)));
renjietang880d2432019-07-16 13:14:37 -0700603 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500604 GetNthClientInitiatedUnidirectionalId(2)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -0700605 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500606 GetNthClientInitiatedUnidirectionalId(1)) != nullptr);
607}
608
609TEST_P(QuicSessionTestServer, MaxAvailableBidirectionalStreams) {
fkastenholz305e1732019-06-18 05:01:22 -0700610 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500611 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams(),
612 session_.MaxAvailableBidirectionalStreams());
613 } else {
614 // The protocol specification requires that there can be at least 10 times
615 // as many available streams as the connection's maximum open streams.
616 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams() *
617 kMaxAvailableStreamsMultiplier,
618 session_.MaxAvailableBidirectionalStreams());
619 }
620}
621
622TEST_P(QuicSessionTestServer, MaxAvailableUnidirectionalStreams) {
fkastenholz305e1732019-06-18 05:01:22 -0700623 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500624 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams(),
625 session_.MaxAvailableUnidirectionalStreams());
626 } else {
627 // The protocol specification requires that there can be at least 10 times
628 // as many available streams as the connection's maximum open streams.
629 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams() *
630 kMaxAvailableStreamsMultiplier,
631 session_.MaxAvailableUnidirectionalStreams());
632 }
633}
634
635TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamLocallyCreated) {
636 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
637 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id());
638 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
639 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(1), stream4->id());
640
641 CheckClosedStreams();
642 CloseStream(GetNthServerInitiatedBidirectionalId(0));
643 CheckClosedStreams();
644 CloseStream(GetNthServerInitiatedBidirectionalId(1));
645 CheckClosedStreams();
646}
647
648TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamLocallyCreated) {
649 TestStream* stream2 = session_.CreateOutgoingUnidirectionalStream();
650 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(0), stream2->id());
651 TestStream* stream4 = session_.CreateOutgoingUnidirectionalStream();
652 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(1), stream4->id());
653
654 CheckClosedStreams();
655 CloseStream(GetNthServerInitiatedUnidirectionalId(0));
656 CheckClosedStreams();
657 CloseStream(GetNthServerInitiatedUnidirectionalId(1));
658 CheckClosedStreams();
659}
660
661TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamPeerCreated) {
662 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
663 QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
renjietang880d2432019-07-16 13:14:37 -0700664 session_.GetOrCreateStream(stream_id1);
665 session_.GetOrCreateStream(stream_id2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500666
667 CheckClosedStreams();
668 CloseStream(stream_id1);
669 CheckClosedStreams();
670 CloseStream(stream_id2);
671 // Create a stream, and make another available.
renjietang880d2432019-07-16 13:14:37 -0700672 QuicStream* stream3 = session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500673 stream_id2 +
674 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
675 CheckClosedStreams();
676 // Close one, but make sure the other is still not closed
677 CloseStream(stream3->id());
678 CheckClosedStreams();
679}
680
681TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamPeerCreated) {
682 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
683 QuicStreamId stream_id2 = GetNthClientInitiatedUnidirectionalId(1);
renjietang880d2432019-07-16 13:14:37 -0700684 session_.GetOrCreateStream(stream_id1);
685 session_.GetOrCreateStream(stream_id2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500686
687 CheckClosedStreams();
688 CloseStream(stream_id1);
689 CheckClosedStreams();
690 CloseStream(stream_id2);
691 // Create a stream, and make another available.
renjietang880d2432019-07-16 13:14:37 -0700692 QuicStream* stream3 = session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500693 stream_id2 +
694 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
695 CheckClosedStreams();
696 // Close one, but make sure the other is still not closed
697 CloseStream(stream3->id());
698 CheckClosedStreams();
699}
700
701TEST_P(QuicSessionTestServer, MaximumAvailableOpenedBidirectionalStreams) {
702 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700703 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500704 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700705 EXPECT_NE(nullptr,
706 session_.GetOrCreateStream(GetNthClientInitiatedBidirectionalId(
707 session_.max_open_incoming_bidirectional_streams() - 1)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500708}
709
710TEST_P(QuicSessionTestServer, MaximumAvailableOpenedUnidirectionalStreams) {
711 QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700712 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500713 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700714 EXPECT_NE(nullptr,
715 session_.GetOrCreateStream(GetNthClientInitiatedUnidirectionalId(
716 session_.max_open_incoming_unidirectional_streams() - 1)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500717}
718
719TEST_P(QuicSessionTestServer, TooManyAvailableBidirectionalStreams) {
720 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
721 QuicStreamId stream_id2;
renjietang880d2432019-07-16 13:14:37 -0700722 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500723 // A stream ID which is too large to create.
724 stream_id2 = GetNthClientInitiatedBidirectionalId(
725 session_.MaxAvailableBidirectionalStreams() + 2);
fkastenholz305e1732019-06-18 05:01:22 -0700726 if (VersionHasIetfQuicFrames(transport_version())) {
727 // IETF QUIC terminates the connection with invalid stream id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500728 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
729 } else {
730 // other versions terminate the connection with
731 // QUIC_TOO_MANY_AVAILABLE_STREAMS.
732 EXPECT_CALL(*connection_,
733 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
734 }
renjietang880d2432019-07-16 13:14:37 -0700735 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500736}
737
738TEST_P(QuicSessionTestServer, TooManyAvailableUnidirectionalStreams) {
739 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
740 QuicStreamId stream_id2;
renjietang880d2432019-07-16 13:14:37 -0700741 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500742 // A stream ID which is too large to create.
743 stream_id2 = GetNthClientInitiatedUnidirectionalId(
744 session_.MaxAvailableUnidirectionalStreams() + 2);
fkastenholz305e1732019-06-18 05:01:22 -0700745 if (VersionHasIetfQuicFrames(transport_version())) {
746 // IETF QUIC terminates the connection with invalid stream id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500747 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
748 } else {
749 // other versions terminate the connection with
750 // QUIC_TOO_MANY_AVAILABLE_STREAMS.
751 EXPECT_CALL(*connection_,
752 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
753 }
renjietang880d2432019-07-16 13:14:37 -0700754 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500755}
756
757TEST_P(QuicSessionTestServer, ManyAvailableBidirectionalStreams) {
758 // When max_open_streams_ is 200, should be able to create 200 streams
759 // out-of-order, that is, creating the one with the largest stream ID first.
fkastenholz305e1732019-06-18 05:01:22 -0700760 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700761 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
762 // Smaller limit on unidirectional streams to help detect crossed wires.
763 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 50);
764 } else {
765 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
766 }
767 // Create a stream at the start of the range.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500768 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700769 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500770
771 // Create the largest stream ID of a threatened total of 200 streams.
772 // GetNth... starts at 0, so for 200 streams, get the 199th.
fkastenholzd3a1de92019-05-15 07:00:07 -0700773 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700774 EXPECT_NE(nullptr, session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500775 GetNthClientInitiatedBidirectionalId(199)));
fkastenholzd3a1de92019-05-15 07:00:07 -0700776
fkastenholz305e1732019-06-18 05:01:22 -0700777 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700778 // If IETF QUIC, check to make sure that creating bidirectional
779 // streams does not mess up the unidirectional streams.
780 stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700781 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholzd3a1de92019-05-15 07:00:07 -0700782 // Now try to get the last possible unidirectional stream.
renjietang880d2432019-07-16 13:14:37 -0700783 EXPECT_NE(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700784 GetNthClientInitiatedUnidirectionalId(49)));
785 // and this should fail because it exceeds the unidirectional limit
786 // (but not the bi-)
787 EXPECT_CALL(
788 *connection_,
789 CloseConnection(QUIC_INVALID_STREAM_ID,
790 "Stream id 798 would exceed stream count limit 50",
791 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
792
793 ))
794 .Times(1);
renjietang880d2432019-07-16 13:14:37 -0700795 EXPECT_EQ(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700796 GetNthClientInitiatedUnidirectionalId(199)));
797 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500798}
799
800TEST_P(QuicSessionTestServer, ManyAvailableUnidirectionalStreams) {
801 // When max_open_streams_ is 200, should be able to create 200 streams
802 // out-of-order, that is, creating the one with the largest stream ID first.
fkastenholz305e1732019-06-18 05:01:22 -0700803 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700804 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 200);
805 // Smaller limit on unidirectional streams to help detect crossed wires.
806 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 50);
807 } else {
808 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
809 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500810 // Create one stream.
fkastenholzd3a1de92019-05-15 07:00:07 -0700811 QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700812 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500813
814 // Create the largest stream ID of a threatened total of 200 streams.
815 // GetNth... starts at 0, so for 200 streams, get the 199th.
fkastenholzd3a1de92019-05-15 07:00:07 -0700816 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700817 EXPECT_NE(nullptr, session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500818 GetNthClientInitiatedUnidirectionalId(199)));
fkastenholz305e1732019-06-18 05:01:22 -0700819 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700820 // If IETF QUIC, check to make sure that creating unidirectional
821 // streams does not mess up the bidirectional streams.
822 stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700823 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholzd3a1de92019-05-15 07:00:07 -0700824 // Now try to get the last possible bidirectional stream.
renjietang880d2432019-07-16 13:14:37 -0700825 EXPECT_NE(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700826 GetNthClientInitiatedBidirectionalId(49)));
827 // and this should fail because it exceeds the bnidirectional limit
828 // (but not the uni-)
nharpercd820e02019-05-16 15:12:07 -0700829 std::string error_detail;
830 if (QuicVersionUsesCryptoFrames(transport_version())) {
831 error_detail = "Stream id 796 would exceed stream count limit 50";
832 } else {
833 error_detail = "Stream id 800 would exceed stream count limit 50";
834 }
fkastenholzd3a1de92019-05-15 07:00:07 -0700835 EXPECT_CALL(
836 *connection_,
nharpercd820e02019-05-16 15:12:07 -0700837 CloseConnection(QUIC_INVALID_STREAM_ID, error_detail,
838 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
fkastenholzd3a1de92019-05-15 07:00:07 -0700839 .Times(1);
renjietang880d2432019-07-16 13:14:37 -0700840 EXPECT_EQ(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700841 GetNthClientInitiatedBidirectionalId(199)));
842 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500843}
844
845TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
846 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
847 if (GetParam() != AllSupportedVersions()[0]) {
848 return;
849 }
850
851 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
852 QuicStreamId closed_stream_id = stream2->id();
853 // Close the stream.
854 EXPECT_CALL(*connection_, SendControlFrame(_));
855 EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
856 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
vasilvvc48c8712019-03-11 13:38:16 -0700857 std::string msg =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500858 QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
859 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
860 msg);
861}
862
863TEST_P(QuicSessionTestServer, OnCanWrite) {
864 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_.MarkConnectionLevelWriteBlocked(stream2->id());
870 session_.MarkConnectionLevelWriteBlocked(stream6->id());
871 session_.MarkConnectionLevelWriteBlocked(stream4->id());
872
873 InSequence s;
874
875 // Reregister, to test the loop limit.
876 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
877 session_.SendStreamData(stream2);
878 session_.MarkConnectionLevelWriteBlocked(stream2->id());
879 }));
880 // 2 will get called a second time as it didn't finish its block
881 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
882 session_.SendStreamData(stream2);
883 }));
884 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
885 session_.SendStreamData(stream6);
886 }));
887 // 4 will not get called, as we exceeded the loop limit.
888 session_.OnCanWrite();
889 EXPECT_TRUE(session_.WillingAndAbleToWrite());
890}
891
892TEST_P(QuicSessionTestServer, TestBatchedWrites) {
893 session_.set_writev_consumes_all_data(true);
894 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
895 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
896 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
897
898 session_.set_writev_consumes_all_data(true);
899 session_.MarkConnectionLevelWriteBlocked(stream2->id());
900 session_.MarkConnectionLevelWriteBlocked(stream4->id());
901
902 // With two sessions blocked, we should get two write calls. They should both
903 // go to the first stream as it will only write 6k and mark itself blocked
904 // again.
905 InSequence s;
906 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
907 session_.SendLargeFakeData(stream2, 6000);
908 session_.MarkConnectionLevelWriteBlocked(stream2->id());
909 }));
910 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
911 session_.SendLargeFakeData(stream2, 6000);
912 session_.MarkConnectionLevelWriteBlocked(stream2->id());
913 }));
914 session_.OnCanWrite();
915
916 // We should get one more call for stream2, at which point it has used its
917 // write quota and we move over to stream 4.
918 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
919 session_.SendLargeFakeData(stream2, 6000);
920 session_.MarkConnectionLevelWriteBlocked(stream2->id());
921 }));
922 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
923 session_.SendLargeFakeData(stream4, 6000);
924 session_.MarkConnectionLevelWriteBlocked(stream4->id());
925 }));
926 session_.OnCanWrite();
927
928 // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
929 // priority stream 6. 4 should be preempted. 6 will write but *not* block so
930 // will cede back to 4.
fayang476683a2019-07-25 12:42:16 -0700931 stream6->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500932 EXPECT_CALL(*stream4, OnCanWrite())
933 .WillOnce(Invoke([this, stream4, stream6]() {
934 session_.SendLargeFakeData(stream4, 6000);
935 session_.MarkConnectionLevelWriteBlocked(stream4->id());
936 session_.MarkConnectionLevelWriteBlocked(stream6->id());
937 }));
938 EXPECT_CALL(*stream6, OnCanWrite())
939 .WillOnce(Invoke([this, stream4, stream6]() {
940 session_.SendStreamData(stream6);
941 session_.SendLargeFakeData(stream4, 6000);
942 }));
943 session_.OnCanWrite();
944
945 // Stream4 alread did 6k worth of writes, so after doing another 12k it should
946 // cede and 2 should resume.
947 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
948 session_.SendLargeFakeData(stream4, 12000);
949 session_.MarkConnectionLevelWriteBlocked(stream4->id());
950 }));
951 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
952 session_.SendLargeFakeData(stream2, 6000);
953 session_.MarkConnectionLevelWriteBlocked(stream2->id());
954 }));
955 session_.OnCanWrite();
956}
957
fayang944cfbc2019-07-31 09:15:00 -0700958TEST_P(QuicSessionTestServer, Http2Priority) {
959 if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
renjietang67e5bcb2019-09-26 16:19:55 -0700960 // The test is using HTTP/2 priority which is not supported in IETF QUIC.
fayang944cfbc2019-07-31 09:15:00 -0700961 return;
962 }
963 SetQuicReloadableFlag(quic_use_http2_priority_write_scheduler, true);
964 QuicTagVector copt;
965 copt.push_back(kH2PR);
966 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
967 session_.OnConfigNegotiated();
968 ASSERT_TRUE(session_.use_http2_priority_write_scheduler());
969
970 session_.set_writev_consumes_all_data(true);
971 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
972 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
973 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
974
975 session_.set_writev_consumes_all_data(true);
976 /*
977 0
978 /|\
979 2 4 6
980 */
981 session_.MarkConnectionLevelWriteBlocked(stream2->id());
982 session_.MarkConnectionLevelWriteBlocked(stream4->id());
983 session_.MarkConnectionLevelWriteBlocked(stream6->id());
984
985 // Verify streams are scheduled round robin.
986 InSequence s;
987 EXPECT_CALL(*stream2, OnCanWrite());
988 EXPECT_CALL(*stream4, OnCanWrite());
989 EXPECT_CALL(*stream6, OnCanWrite());
990 session_.OnCanWrite();
991
992 /*
993 0
994 |
995 4
996 / \
997 2 6
998 */
999 // Update stream 4's priority.
1000 stream4->SetPriority(
1001 spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, true));
1002 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1003 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1004 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1005
1006 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1007 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1008 }));
1009 EXPECT_CALL(*stream4, OnCanWrite());
1010 EXPECT_CALL(*stream2, OnCanWrite());
1011 session_.OnCanWrite();
1012 EXPECT_CALL(*stream6, OnCanWrite());
1013 session_.OnCanWrite();
1014
1015 /*
1016 0
1017 |
1018 6
1019 |
1020 4
1021 |
1022 2
1023 */
1024 // Update stream 6's priority.
1025 stream6->SetPriority(
1026 spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, true));
1027 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1028 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1029 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1030
1031 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1032 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1033 }));
1034 EXPECT_CALL(*stream6, OnCanWrite());
1035 EXPECT_CALL(*stream4, OnCanWrite());
1036 session_.OnCanWrite();
1037 EXPECT_CALL(*stream2, OnCanWrite());
1038 session_.OnCanWrite();
1039}
1040
fayang1b11b962019-09-16 14:01:48 -07001041TEST_P(QuicSessionTestServer, RoundRobinScheduling) {
1042 if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
renjietang67e5bcb2019-09-26 16:19:55 -07001043 // IETF QUIC currently doesn't support PRIORITY.
fayang1b11b962019-09-16 14:01:48 -07001044 return;
1045 }
1046 SetQuicReloadableFlag(quic_enable_rr_write_scheduler, true);
1047 QuicTagVector copt;
1048 copt.push_back(kRRWS);
1049 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
1050 session_.OnConfigNegotiated();
1051
1052 session_.set_writev_consumes_all_data(true);
1053 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1054 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1055 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1056
1057 session_.set_writev_consumes_all_data(true);
1058 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1059 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1060 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1061
1062 // Verify streams are scheduled round robin.
1063 InSequence s;
1064 EXPECT_CALL(*stream2, OnCanWrite());
1065 EXPECT_CALL(*stream4, OnCanWrite());
1066 EXPECT_CALL(*stream6, OnCanWrite());
1067 session_.OnCanWrite();
1068
1069 /* 2, 4, 6, 8 */
1070 TestStream* stream8 = session_.CreateOutgoingBidirectionalStream();
1071
1072 // Verify updated priority is ignored.
1073 stream4->SetPriority(spdy::SpdyStreamPrecedence(spdy::kV3HighestPriority));
1074 session_.MarkConnectionLevelWriteBlocked(stream8->id());
1075 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1076 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1077 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1078
1079 EXPECT_CALL(*stream8, OnCanWrite());
1080 EXPECT_CALL(*stream4, OnCanWrite());
1081 EXPECT_CALL(*stream2, OnCanWrite());
1082 EXPECT_CALL(*stream6, OnCanWrite());
1083 session_.OnCanWrite();
1084}
1085
QUICHE teama6ef0a62019-03-07 20:34:33 -05001086TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
1087 // Encryption needs to be established before data can be sent.
1088 CryptoHandshakeMessage msg;
1089 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1090 QuicConnectionPeer::GetWriter(session_.connection()));
1091 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1092
1093 // Drive congestion control manually.
1094 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1095 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1096
1097 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1098 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1099 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1100
1101 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1102 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1103 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1104
1105 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1106 EXPECT_CALL(*send_algorithm, GetCongestionWindow())
dschinazi66dea072019-04-09 11:41:06 -07001107 .WillRepeatedly(Return(kMaxOutgoingPacketSize * 10));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001108 EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
1109 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1110 session_.SendStreamData(stream2);
1111 }));
1112 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1113 session_.SendStreamData(stream4);
1114 }));
1115 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1116 session_.SendStreamData(stream6);
1117 }));
1118
1119 // Expect that we only send one packet, the writes from different streams
1120 // should be bundled together.
1121 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
1122 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1123 EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
1124 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1125 session_.OnCanWrite();
1126 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1127}
1128
1129TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
1130 session_.set_writev_consumes_all_data(true);
1131 InSequence s;
1132
1133 // Drive congestion control manually.
1134 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1135 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1136
1137 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1138 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1139 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1140
1141 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1142 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1143 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1144
1145 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1146 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1147 session_.SendStreamData(stream2);
1148 }));
1149 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1150 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1151 session_.SendStreamData(stream6);
1152 }));
1153 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
1154 // stream4->OnCanWrite is not called.
1155
1156 session_.OnCanWrite();
1157 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1158
1159 // Still congestion-control blocked.
1160 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
1161 session_.OnCanWrite();
1162 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1163
1164 // stream4->OnCanWrite is called once the connection stops being
1165 // congestion-control blocked.
1166 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1167 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1168 session_.SendStreamData(stream4);
1169 }));
1170 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1171 session_.OnCanWrite();
1172 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1173}
1174
1175TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
1176 // Drive congestion control manually in order to ensure that
1177 // application-limited signaling is handled correctly.
1178 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1179 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1180 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1181
1182 // Drive packet writer manually.
1183 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1184 QuicConnectionPeer::GetWriter(session_.connection()));
1185 EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
1186 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
1187
1188 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1189
1190 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1191
1192 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
1193 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)).Times(0);
1194
1195 session_.OnCanWrite();
1196 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1197}
1198
1199TEST_P(QuicSessionTestServer, BufferedHandshake) {
nharperd5c4a932019-05-13 13:58:49 -07001200 // This test is testing behavior of crypto stream flow control, but when
1201 // CRYPTO frames are used, there is no flow control for the crypto handshake.
1202 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1203 return;
1204 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001205 session_.set_writev_consumes_all_data(true);
1206 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
1207
1208 // Test that blocking other streams does not change our status.
1209 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1210 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1211 EXPECT_FALSE(session_.HasPendingHandshake());
1212
1213 TestStream* stream3 = session_.CreateOutgoingBidirectionalStream();
1214 session_.MarkConnectionLevelWriteBlocked(stream3->id());
1215 EXPECT_FALSE(session_.HasPendingHandshake());
1216
1217 // Blocking (due to buffering of) the Crypto stream is detected.
1218 session_.MarkConnectionLevelWriteBlocked(
1219 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1220 EXPECT_TRUE(session_.HasPendingHandshake());
1221
1222 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1223 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1224 EXPECT_TRUE(session_.HasPendingHandshake());
1225
1226 InSequence s;
1227 // Force most streams to re-register, which is common scenario when we block
1228 // the Crypto stream, and only the crypto stream can "really" write.
1229
1230 // Due to prioritization, we *should* be asked to write the crypto stream
1231 // first.
1232 // Don't re-register the crypto stream (which signals complete writing).
1233 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1234 EXPECT_CALL(*crypto_stream, OnCanWrite());
1235
1236 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1237 session_.SendStreamData(stream2);
1238 }));
1239 EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(Invoke([this, stream3]() {
1240 session_.SendStreamData(stream3);
1241 }));
1242 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1243 session_.SendStreamData(stream4);
1244 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1245 }));
1246
1247 session_.OnCanWrite();
1248 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1249 EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
1250}
1251
1252TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
1253 session_.set_writev_consumes_all_data(true);
1254 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1255 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1256 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1257
1258 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1259 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1260 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1261 CloseStream(stream6->id());
1262
1263 InSequence s;
1264 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001265 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001266 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1267 session_.SendStreamData(stream2);
1268 }));
1269 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1270 session_.SendStreamData(stream4);
1271 }));
1272 session_.OnCanWrite();
1273 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1274}
1275
1276TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
1277 // Drive congestion control manually in order to ensure that
1278 // application-limited signaling is handled correctly.
1279 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1280 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1281 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1282
1283 // Ensure connection level flow control blockage.
1284 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
1285 EXPECT_TRUE(session_.flow_controller()->IsBlocked());
1286 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1287 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1288
1289 // Mark the crypto and headers streams as write blocked, we expect them to be
1290 // allowed to write later.
nharperd5c4a932019-05-13 13:58:49 -07001291 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1292 session_.MarkConnectionLevelWriteBlocked(
1293 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1294 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001295
1296 // Create a data stream, and although it is write blocked we never expect it
1297 // to be allowed to write as we are connection level flow control blocked.
1298 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1299 session_.MarkConnectionLevelWriteBlocked(stream->id());
1300 EXPECT_CALL(*stream, OnCanWrite()).Times(0);
1301
1302 // The crypto and headers streams should be called even though we are
1303 // connection flow control blocked.
nharperd5c4a932019-05-13 13:58:49 -07001304 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1305 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1306 EXPECT_CALL(*crypto_stream, OnCanWrite());
1307 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001308
1309 // After the crypto and header streams perform a write, the connection will be
1310 // blocked by the flow control, hence it should become application-limited.
1311 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1312
1313 session_.OnCanWrite();
1314 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1315}
1316
1317TEST_P(QuicSessionTestServer, SendGoAway) {
fkastenholz305e1732019-06-18 05:01:22 -07001318 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001319 // In IETF QUIC, GOAWAY lives up in the HTTP layer.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001320 return;
1321 }
fayang93cc53a2019-08-22 12:47:30 -07001322 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001323 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1324 QuicConnectionPeer::GetWriter(session_.connection()));
1325 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
1326 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1327
1328 EXPECT_CALL(*connection_, SendControlFrame(_))
1329 .WillOnce(
1330 Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
1331 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1332 EXPECT_TRUE(session_.goaway_sent());
1333
1334 const QuicStreamId kTestStreamId = 5u;
1335 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1336 EXPECT_CALL(*connection_,
1337 OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
1338 .Times(0);
renjietang880d2432019-07-16 13:14:37 -07001339 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001340}
1341
1342TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
fkastenholz305e1732019-06-18 05:01:22 -07001343 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001344 // In IETF QUIC, GOAWAY lives up in the HTTP layer.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001345 return;
1346 }
1347 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001348 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001349 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1350 EXPECT_TRUE(session_.goaway_sent());
1351 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1352}
1353
1354TEST_P(QuicSessionTestServer, InvalidGoAway) {
fkastenholz305e1732019-06-18 05:01:22 -07001355 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001356 // In IETF QUIC, GOAWAY lives up in the HTTP layer.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001357 return;
1358 }
1359 QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
1360 session_.next_outgoing_bidirectional_stream_id(), "");
1361 session_.OnGoAway(go_away);
1362}
1363
1364// Test that server session will send a connectivity probe in response to a
1365// connectivity probe on the same path.
1366TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbe) {
1367 QuicSocketAddress old_peer_address =
1368 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1369 EXPECT_EQ(old_peer_address, session_.peer_address());
1370
1371 QuicSocketAddress new_peer_address =
1372 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort + 1);
1373
1374 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1375 QuicConnectionPeer::GetWriter(session_.connection()));
1376 EXPECT_CALL(*writer, WritePacket(_, _, _, new_peer_address, _))
1377 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1378 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1379 .WillOnce(Invoke(
1380 connection_,
1381 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
fkastenholz305e1732019-06-18 05:01:22 -07001382 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001383 // Need to explicitly do this to emulate the reception of a PathChallenge,
1384 // which stores its payload for use in generating the response.
1385 connection_->OnPathChallengeFrame(
1386 QuicPathChallengeFrame(0, path_frame_buffer1_));
1387 }
zhongyi83161e42019-08-19 09:06:25 -07001388 session_.OnPacketReceived(session_.self_address(), new_peer_address,
1389 /*is_connectivity_probe=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001390 EXPECT_EQ(old_peer_address, session_.peer_address());
1391}
1392
1393// Same as above, but check that if there are two PATH_CHALLENGE frames in the
1394// packet, the response has both of them AND we do not do migration. This for
fkastenholz305e1732019-06-18 05:01:22 -07001395// IETF QUIC only.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001396TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbes) {
fkastenholz305e1732019-06-18 05:01:22 -07001397 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001398 return;
1399 }
1400 QuicSocketAddress old_peer_address =
1401 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1402 EXPECT_EQ(old_peer_address, session_.peer_address());
1403
1404 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1405 QuicConnectionPeer::GetWriter(session_.connection()));
1406 // CheckMultiPathResponse validates that the written packet
1407 // contains both path responses.
1408 EXPECT_CALL(*writer, WritePacket(_, _, _, old_peer_address, _))
1409 .WillOnce(Invoke(this, &QuicSessionTestServer::CheckMultiPathResponse));
1410
1411 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1412 .WillOnce(Invoke(
1413 connection_,
1414 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
QUICHE team8c1daa22019-03-13 08:33:41 -07001415 QuicConnectionPeer::SetLastHeaderFormat(connection_,
1416 IETF_QUIC_SHORT_HEADER_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001417 // Need to explicitly do this to emulate the reception of a PathChallenge,
1418 // which stores its payload for use in generating the response.
1419 connection_->OnPathChallengeFrame(
1420 QuicPathChallengeFrame(0, path_frame_buffer1_));
1421 connection_->OnPathChallengeFrame(
1422 QuicPathChallengeFrame(0, path_frame_buffer2_));
zhongyi83161e42019-08-19 09:06:25 -07001423 session_.OnPacketReceived(session_.self_address(), old_peer_address,
1424 /*is_connectivity_probe=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001425}
1426
1427TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
1428 EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
1429 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1430 CryptoHandshakeMessage msg;
1431 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1432 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
1433 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1434}
1435
1436TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
renjietanga29a96a2019-10-10 12:47:50 -07001437 if (VersionUsesHttp3(connection_->transport_version())) {
renjietang67e5bcb2019-09-26 16:19:55 -07001438 // The test relies on headers stream, which no longer exists in IETF QUIC.
dschinazi552accc2019-06-17 17:07:34 -07001439 return;
1440 }
nharper46833c32019-05-15 21:33:05 -07001441 QuicStreamId headers_stream_id =
1442 QuicUtils::GetHeadersStreamId(connection_->transport_version());
vasilvv0fc587f2019-09-06 13:33:08 -07001443 std::unique_ptr<TestStream> fake_headers_stream =
1444 std::make_unique<TestStream>(headers_stream_id, &session_,
1445 /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07001446 QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001447 // Send two bytes of payload.
nharper46833c32019-05-15 21:33:05 -07001448 QuicStreamFrame data1(headers_stream_id, true, 0, QuicStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001449 EXPECT_CALL(*connection_,
1450 CloseConnection(
1451 QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
1452 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1453 session_.OnStreamFrame(data1);
1454}
1455
1456TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
renjietanga29a96a2019-10-10 12:47:50 -07001457 if (VersionUsesHttp3(connection_->transport_version())) {
renjietang67e5bcb2019-09-26 16:19:55 -07001458 // The test relies on headers stream, which no longer exists in IETF QUIC.
dschinazi552accc2019-06-17 17:07:34 -07001459 return;
1460 }
nharper46833c32019-05-15 21:33:05 -07001461 QuicStreamId headers_stream_id =
1462 QuicUtils::GetHeadersStreamId(connection_->transport_version());
vasilvv0fc587f2019-09-06 13:33:08 -07001463 std::unique_ptr<TestStream> fake_headers_stream =
1464 std::make_unique<TestStream>(headers_stream_id, &session_,
1465 /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07001466 QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001467 // Send two bytes of payload.
nharper46833c32019-05-15 21:33:05 -07001468 QuicRstStreamFrame rst1(kInvalidControlFrameId, headers_stream_id,
1469 QUIC_ERROR_PROCESSING_STREAM, 0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001470 EXPECT_CALL(*connection_,
1471 CloseConnection(
1472 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
1473 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1474 session_.OnRstStream(rst1);
1475}
1476
1477TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
1478 // Send two bytes of payload.
1479 QuicStreamFrame data1(
1480 QuicUtils::GetInvalidStreamId(connection_->transport_version()), true, 0,
1481 QuicStringPiece("HT"));
1482 EXPECT_CALL(*connection_,
1483 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001484 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001485 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1486 session_.OnStreamFrame(data1);
1487}
1488
1489TEST_P(QuicSessionTestServer, OnRstStreamInvalidStreamId) {
1490 // Send two bytes of payload.
1491 QuicRstStreamFrame rst1(
1492 kInvalidControlFrameId,
1493 QuicUtils::GetInvalidStreamId(connection_->transport_version()),
1494 QUIC_ERROR_PROCESSING_STREAM, 0);
1495 EXPECT_CALL(*connection_,
1496 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001497 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001498 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1499 session_.OnRstStream(rst1);
1500}
1501
1502TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
dschinaziaab68182019-10-09 15:39:51 -07001503 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
1504 // This test requires Google QUIC crypto because it assumes streams start
1505 // off unblocked.
1506 return;
1507 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001508 // Test that if a stream is flow control blocked, then on receipt of the SHLO
1509 // containing a suitable send window offset, the stream becomes unblocked.
1510
1511 // Ensure that Writev consumes all the data it is given (simulate no socket
1512 // blocking).
1513 session_.set_writev_consumes_all_data(true);
1514
1515 // Create a stream, and send enough data to make it flow control blocked.
1516 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07001517 std::string body(kMinimumFlowControlSendWindow, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001518 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1519 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1520 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1521 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
1522 stream2->WriteOrBufferData(body, false, nullptr);
1523 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
1524 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1525 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1526
1527 // Now complete the crypto handshake, resulting in an increased flow control
1528 // send window.
1529 CryptoHandshakeMessage msg;
1530 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1531 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
1532 // Stream is now unblocked.
1533 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1534 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1535 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1536}
1537
1538TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
QUICHE teamea740082019-03-11 17:58:43 -07001539 if (QuicVersionUsesCryptoFrames(GetParam().transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001540 // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
1541 // test doesn't make sense for those versions since CRYPTO frames aren't
1542 // flow controlled.
1543 return;
1544 }
1545 // Test that if the crypto stream is flow control blocked, then if the SHLO
1546 // contains a larger send window offset, the stream becomes unblocked.
1547 session_.set_writev_consumes_all_data(true);
1548 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1549 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1550 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1551 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1552 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1553 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1554 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001555 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001556 for (QuicStreamId i = 0;
1557 !crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
1558 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1559 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1560 QuicStreamOffset offset = crypto_stream->stream_bytes_written();
1561 QuicConfig config;
1562 CryptoHandshakeMessage crypto_message;
fkastenholzd3a1de92019-05-15 07:00:07 -07001563 config.ToHandshakeMessage(&crypto_message, transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001564 crypto_stream->SendHandshakeMessage(crypto_message);
1565 char buf[1000];
1566 QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
1567 crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
1568 }
1569 EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
1570 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1571 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1572 EXPECT_FALSE(session_.HasDataToWrite());
1573 EXPECT_TRUE(crypto_stream->HasBufferedData());
1574
1575 // Now complete the crypto handshake, resulting in an increased flow control
1576 // send window.
1577 CryptoHandshakeMessage msg;
1578 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1579 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
1580 &session_,
1581 QuicUtils::GetCryptoStreamId(connection_->transport_version())));
1582 // Stream is now unblocked and will no longer have buffered data.
1583 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1584 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1585 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1586}
1587
1588TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
1589 // Test that when we receive an out of order stream RST we correctly adjust
1590 // our connection level flow control receive window.
1591 // On close, the stream should mark as consumed all bytes between the highest
1592 // byte consumed so far and the final byte offset from the RST frame.
1593 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1594
1595 const QuicStreamOffset kByteOffset =
1596 1 + kInitialSessionFlowControlWindowForTest / 2;
1597
1598 EXPECT_CALL(*connection_, SendControlFrame(_))
1599 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07001600 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001601 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1602
1603 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1604 QUIC_STREAM_CANCELLED, kByteOffset);
1605 session_.OnRstStream(rst_frame);
fkastenholz305e1732019-06-18 05:01:22 -07001606 if (VersionHasIetfQuicFrames(transport_version())) {
1607 // The test is predicated on the stream being fully closed. For IETF QUIC,
1608 // the RST_STREAM only does one side (the read side from the perspective of
1609 // the node receiving the RST_STREAM). This is needed to fully close the
QUICHE teama6ef0a62019-03-07 20:34:33 -05001610 // stream and therefore fulfill all of the expects.
1611 QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
1612 QUIC_STREAM_CANCELLED);
renjietangeab918f2019-10-28 12:10:32 -07001613 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1614 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001615 }
1616 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
1617}
1618
1619TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
1620 // Test the situation where we receive a FIN on a stream, and before we fully
1621 // consume all the data from the sequencer buffer we locally RST the stream.
1622 // The bytes between highest consumed byte, and the final byte offset that we
1623 // determined when the FIN arrived, should be marked as consumed at the
1624 // connection level flow controller when the stream is reset.
1625 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1626
1627 const QuicStreamOffset kByteOffset =
1628 kInitialSessionFlowControlWindowForTest / 2 - 1;
1629 QuicStreamFrame frame(stream->id(), true, kByteOffset, ".");
1630 session_.OnStreamFrame(frame);
1631 EXPECT_TRUE(connection_->connected());
1632
1633 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
1634 EXPECT_EQ(kByteOffset + frame.data_length,
1635 stream->flow_controller()->highest_received_byte_offset());
1636
1637 // Reset stream locally.
1638 EXPECT_CALL(*connection_, SendControlFrame(_));
1639 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1640 stream->Reset(QUIC_STREAM_CANCELLED);
1641 EXPECT_EQ(kByteOffset + frame.data_length,
1642 session_.flow_controller()->bytes_consumed());
1643}
1644
1645TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
1646 // Test that when we RST the stream (and tear down stream state), and then
1647 // receive a FIN from the peer, we correctly adjust our connection level flow
1648 // control receive window.
1649
1650 // Connection starts with some non-zero highest received byte offset,
1651 // due to other active streams.
1652 const uint64_t kInitialConnectionBytesConsumed = 567;
1653 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1654 EXPECT_LT(kInitialConnectionBytesConsumed,
1655 kInitialConnectionHighestReceivedOffset);
1656 session_.flow_controller()->UpdateHighestReceivedOffset(
1657 kInitialConnectionHighestReceivedOffset);
1658 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1659
1660 // Reset our stream: this results in the stream being closed locally.
1661 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1662 EXPECT_CALL(*connection_, SendControlFrame(_));
1663 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1664 stream->Reset(QUIC_STREAM_CANCELLED);
1665
1666 // Now receive a response from the peer with a FIN. We should handle this by
1667 // adjusting the connection level flow control receive window to take into
1668 // account the total number of bytes sent by the peer.
1669 const QuicStreamOffset kByteOffset = 5678;
vasilvvc48c8712019-03-11 13:38:16 -07001670 std::string body = "hello";
QUICHE teama6ef0a62019-03-07 20:34:33 -05001671 QuicStreamFrame frame(stream->id(), true, kByteOffset, QuicStringPiece(body));
1672 session_.OnStreamFrame(frame);
1673
1674 QuicStreamOffset total_stream_bytes_sent_by_peer =
1675 kByteOffset + body.length();
1676 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer,
1677 session_.flow_controller()->bytes_consumed());
1678 EXPECT_EQ(
1679 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer,
1680 session_.flow_controller()->highest_received_byte_offset());
1681}
1682
1683TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
1684 // Test that when we RST the stream (and tear down stream state), and then
1685 // receive a RST from the peer, we correctly adjust our connection level flow
1686 // control receive window.
1687
1688 // Connection starts with some non-zero highest received byte offset,
1689 // due to other active streams.
1690 const uint64_t kInitialConnectionBytesConsumed = 567;
1691 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1692 EXPECT_LT(kInitialConnectionBytesConsumed,
1693 kInitialConnectionHighestReceivedOffset);
1694 session_.flow_controller()->UpdateHighestReceivedOffset(
1695 kInitialConnectionHighestReceivedOffset);
1696 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1697
1698 // Reset our stream: this results in the stream being closed locally.
1699 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1700 EXPECT_CALL(*connection_, SendControlFrame(_));
1701 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1702 stream->Reset(QUIC_STREAM_CANCELLED);
1703 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1704
1705 // Now receive a RST from the peer. We should handle this by adjusting the
1706 // connection level flow control receive window to take into account the total
1707 // number of bytes sent by the peer.
1708 const QuicStreamOffset kByteOffset = 5678;
1709 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1710 QUIC_STREAM_CANCELLED, kByteOffset);
1711 session_.OnRstStream(rst_frame);
1712
1713 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset,
1714 session_.flow_controller()->bytes_consumed());
1715 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset,
1716 session_.flow_controller()->highest_received_byte_offset());
1717}
1718
1719TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
1720 // Test that receipt of an invalid (< default) stream flow control window from
1721 // the peer results in the connection being torn down.
1722 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1723 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
1724 kInvalidWindow);
1725
dschinazi18cdf132019-10-09 16:08:18 -07001726 if (connection_->version().handshake_protocol != PROTOCOL_TLS1_3) {
dschinazic7036122019-04-30 12:46:34 -07001727 EXPECT_CALL(*connection_,
1728 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1729 } else {
1730 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1731 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001732 session_.OnConfigNegotiated();
1733}
1734
1735TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
1736 // Test that receipt of an invalid (< default) session flow control window
1737 // from the peer results in the connection being torn down.
1738 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1739 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
1740 kInvalidWindow);
dschinazic7036122019-04-30 12:46:34 -07001741 if (!connection_->version().AllowsLowFlowControlLimits()) {
1742 EXPECT_CALL(*connection_,
1743 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1744 } else {
1745 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1746 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001747 session_.OnConfigNegotiated();
1748}
1749
1750// Test negotiation of custom server initial flow control window.
1751TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
1752 QuicTagVector copt;
1753 copt.push_back(kIFW7);
1754 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
1755
1756 session_.OnConfigNegotiated();
1757 EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
1758 session_.flow_controller()));
1759}
1760
1761TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
1762 // Test that if we receive a stream RST with a highest byte offset that
1763 // violates flow control, that we close the connection.
1764 const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
1765 EXPECT_CALL(*connection_,
1766 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
1767 .Times(2);
1768
1769 // Check that stream frame + FIN results in connection close.
1770 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1771 EXPECT_CALL(*connection_, SendControlFrame(_));
1772 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1773 stream->Reset(QUIC_STREAM_CANCELLED);
1774 QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
1775 session_.OnStreamFrame(frame);
1776
1777 // Check that RST results in connection close.
1778 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1779 QUIC_STREAM_CANCELLED, kLargeOffset);
1780 session_.OnRstStream(rst_frame);
1781}
1782
1783TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
1784 // If a buggy/malicious peer creates too many streams that are not ended
fkastenholz305e1732019-06-18 05:01:22 -07001785 // with a FIN or RST then we send an RST to refuse streams. For IETF QUIC the
QUICHE teama6ef0a62019-03-07 20:34:33 -05001786 // connection is closed.
1787 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07001788 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001789 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1790 kMaxStreams);
1791 } else {
1792 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1793 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001794 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1795 const QuicStreamId kFinalStreamId =
1796 GetNthClientInitiatedBidirectionalId(kMaxStreams);
1797 // Create kMaxStreams data streams, and close them all without receiving a
1798 // FIN or a RST_STREAM from the client.
1799 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
1800 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
1801 QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
1802 session_.OnStreamFrame(data1);
1803 // EXPECT_EQ(1u, session_.GetNumOpenStreams());
fkastenholz305e1732019-06-18 05:01:22 -07001804 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001805 // Expect two control frames, RST STREAM and STOP SENDING
1806 EXPECT_CALL(*connection_, SendControlFrame(_))
1807 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07001808 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001809 } else {
1810 // Expect one control frame, just RST STREAM
1811 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001812 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001813 }
1814 // Close stream. Should not make new streams available since
1815 // the stream is not finished.
1816 EXPECT_CALL(*connection_, OnStreamReset(i, _));
1817 session_.CloseStream(i);
1818 }
1819
fkastenholz305e1732019-06-18 05:01:22 -07001820 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholz3c4eabf2019-04-22 07:49:59 -07001821 EXPECT_CALL(
1822 *connection_,
1823 CloseConnection(QUIC_INVALID_STREAM_ID,
nharpercd820e02019-05-16 15:12:07 -07001824 "Stream id 20 would exceed stream count limit 5", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001825 } else {
1826 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1827 EXPECT_CALL(*connection_,
1828 OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
1829 .Times(1);
1830 }
1831 // Create one more data streams to exceed limit of open stream.
1832 QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
1833 session_.OnStreamFrame(data1);
1834}
1835
1836TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpenedOutgoing) {
1837 // Verify that a draining stream (which has received a FIN but not consumed
1838 // it) does not count against the open quota (because it is closed from the
1839 // protocol point of view).
1840 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1841 QuicStreamId stream_id = stream->id();
1842 QuicStreamFrame data1(stream_id, true, 0, QuicStringPiece("HT"));
1843 session_.OnStreamFrame(data1);
fkastenholz8556dc22019-07-18 12:42:38 -07001844 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001845 session_.StreamDraining(stream_id);
1846}
1847
1848TEST_P(QuicSessionTestServer, NoPendingStreams) {
renjietange76b2da2019-05-13 14:50:23 -07001849 session_.set_uses_pending_streams(false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001850
1851 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1852 transport_version(), Perspective::IS_CLIENT);
1853 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1854 session_.OnStreamFrame(data1);
1855 EXPECT_EQ(1, session_.num_incoming_streams_created());
1856
1857 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1858 session_.OnStreamFrame(data2);
1859 EXPECT_EQ(1, session_.num_incoming_streams_created());
1860}
1861
1862TEST_P(QuicSessionTestServer, PendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07001863 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001864 return;
1865 }
renjietange76b2da2019-05-13 14:50:23 -07001866 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001867
1868 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1869 transport_version(), Perspective::IS_CLIENT);
1870 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1871 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001872 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001873 EXPECT_EQ(0, session_.num_incoming_streams_created());
1874
1875 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1876 session_.OnStreamFrame(data2);
bnc092d8212019-08-07 11:53:20 -07001877 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001878 EXPECT_EQ(1, session_.num_incoming_streams_created());
1879}
1880
1881TEST_P(QuicSessionTestServer, RstPendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07001882 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001883 return;
1884 }
renjietange76b2da2019-05-13 14:50:23 -07001885 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001886
1887 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1888 transport_version(), Perspective::IS_CLIENT);
1889 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1890 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001891 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001892 EXPECT_EQ(0, session_.num_incoming_streams_created());
renjietangec6b2c42019-07-16 20:31:51 -07001893 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001894
QUICHE teama6ef0a62019-03-07 20:34:33 -05001895 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream_id,
1896 QUIC_ERROR_PROCESSING_STREAM, 12);
1897 session_.OnRstStream(rst1);
bnc092d8212019-08-07 11:53:20 -07001898 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001899 EXPECT_EQ(0, session_.num_incoming_streams_created());
renjietangec6b2c42019-07-16 20:31:51 -07001900 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001901
1902 QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
1903 session_.OnStreamFrame(data2);
bnc092d8212019-08-07 11:53:20 -07001904 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
1905 EXPECT_EQ(0, session_.num_incoming_streams_created());
1906 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1907}
1908
1909TEST_P(QuicSessionTestServer, OnFinPendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07001910 if (!VersionUsesHttp3(transport_version())) {
bnc092d8212019-08-07 11:53:20 -07001911 return;
1912 }
1913 session_.set_uses_pending_streams(true);
1914
1915 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1916 transport_version(), Perspective::IS_CLIENT);
1917 QuicStreamFrame data(stream_id, true, 0, "");
1918 session_.OnStreamFrame(data);
1919
1920 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001921 EXPECT_EQ(0, session_.num_incoming_streams_created());
renjietangec6b2c42019-07-16 20:31:51 -07001922 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001923}
1924
renjietang28c04b72019-07-01 15:08:09 -07001925TEST_P(QuicSessionTestServer, PendingStreamOnWindowUpdate) {
renjietanga29a96a2019-10-10 12:47:50 -07001926 if (!VersionUsesHttp3(transport_version())) {
renjietang28c04b72019-07-01 15:08:09 -07001927 return;
1928 }
1929
1930 session_.set_uses_pending_streams(true);
1931 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1932 transport_version(), Perspective::IS_CLIENT);
1933 QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
1934 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001935 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
renjietang28c04b72019-07-01 15:08:09 -07001936 EXPECT_EQ(0, session_.num_incoming_streams_created());
1937 QuicWindowUpdateFrame window_update_frame(kInvalidControlFrameId, stream_id,
1938 0);
1939 EXPECT_CALL(
1940 *connection_,
1941 CloseConnection(
1942 QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
1943 "WindowUpdateFrame received on READ_UNIDIRECTIONAL stream.", _));
1944 session_.OnWindowUpdateFrame(window_update_frame);
1945}
1946
QUICHE teama6ef0a62019-03-07 20:34:33 -05001947TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
1948 // Verify that a draining stream (which has received a FIN but not consumed
1949 // it) does not count against the open quota (because it is closed from the
1950 // protocol point of view).
fkastenholz305e1732019-06-18 05:01:22 -07001951 if (VersionHasIetfQuicFrames(transport_version())) {
1952 // On IETF QUIC, we will expect to see a MAX_STREAMS go out when there are
1953 // not enough streams to create the next one.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001954 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1955 } else {
1956 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1957 }
1958 EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
1959 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07001960 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001961 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1962 kMaxStreams);
1963 } else {
1964 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1965 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001966
1967 // Create kMaxStreams + 1 data streams, and mark them draining.
1968 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1969 const QuicStreamId kFinalStreamId =
1970 GetNthClientInitiatedBidirectionalId(2 * kMaxStreams + 1);
1971 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
1972 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
1973 QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT"));
1974 session_.OnStreamFrame(data1);
1975 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
1976 session_.StreamDraining(i);
1977 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1978 }
1979}
1980
1981class QuicSessionTestClient : public QuicSessionTestBase {
1982 protected:
fkastenholz56055be2019-09-17 11:17:37 -07001983 QuicSessionTestClient()
1984 : QuicSessionTestBase(Perspective::IS_CLIENT,
1985 /*configure_session=*/true) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001986};
1987
1988INSTANTIATE_TEST_SUITE_P(Tests,
1989 QuicSessionTestClient,
dschinazi142051a2019-09-18 18:17:29 -07001990 ::testing::ValuesIn(AllSupportedVersions()),
1991 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001992
1993TEST_P(QuicSessionTestClient, AvailableBidirectionalStreamsClient) {
renjietang880d2432019-07-16 13:14:37 -07001994 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001995 GetNthServerInitiatedBidirectionalId(2)) != nullptr);
1996 // Smaller bidirectional streams should be available.
1997 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1998 &session_, GetNthServerInitiatedBidirectionalId(0)));
1999 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
2000 &session_, GetNthServerInitiatedBidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -07002001 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002002 GetNthServerInitiatedBidirectionalId(0)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -07002003 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002004 GetNthServerInitiatedBidirectionalId(1)) != nullptr);
2005 // And 5 should be not available.
2006 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
2007 &session_, GetNthClientInitiatedBidirectionalId(1)));
2008}
2009
2010TEST_P(QuicSessionTestClient, AvailableUnidirectionalStreamsClient) {
renjietang880d2432019-07-16 13:14:37 -07002011 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002012 GetNthServerInitiatedUnidirectionalId(2)) != nullptr);
2013 // Smaller unidirectional streams should be available.
2014 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
2015 &session_, GetNthServerInitiatedUnidirectionalId(0)));
2016 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
2017 &session_, GetNthServerInitiatedUnidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -07002018 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002019 GetNthServerInitiatedUnidirectionalId(0)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -07002020 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002021 GetNthServerInitiatedUnidirectionalId(1)) != nullptr);
2022 // And 5 should be not available.
2023 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
2024 &session_, GetNthClientInitiatedUnidirectionalId(1)));
2025}
2026
2027TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
2028 // Verify that an incoming FIN is recorded in a stream object even if the read
2029 // side has been closed. This prevents an entry from being made in
2030 // locally_closed_streams_highest_offset_ (which will never be deleted).
2031 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2032 QuicStreamId stream_id = stream->id();
2033
2034 // Close the read side manually.
2035 QuicStreamPeer::CloseReadSide(stream);
2036
2037 // Receive a stream data frame with FIN.
2038 QuicStreamFrame frame(stream_id, true, 0, QuicStringPiece());
2039 session_.OnStreamFrame(frame);
2040 EXPECT_TRUE(stream->fin_received());
2041
2042 // Reset stream locally.
2043 EXPECT_CALL(*connection_, SendControlFrame(_));
2044 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
2045 stream->Reset(QUIC_STREAM_CANCELLED);
2046 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
2047
2048 EXPECT_TRUE(connection_->connected());
2049 EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
2050 EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
2051
2052 // The stream is not waiting for the arrival of the peer's final offset as it
2053 // was received with the FIN earlier.
2054 EXPECT_EQ(
2055 0u,
2056 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
2057}
2058
2059TEST_P(QuicSessionTestServer, ZombieStreams) {
2060 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2061 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
2062 EXPECT_TRUE(stream2->IsWaitingForAcks());
2063
2064 EXPECT_CALL(*connection_, SendControlFrame(_));
2065 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2066 session_.CloseStream(stream2->id());
2067 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2068 ASSERT_EQ(1u, session_.closed_streams()->size());
2069 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2070 session_.OnStreamDoneWaitingForAcks(stream2->id());
2071 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2072 EXPECT_EQ(1u, session_.closed_streams()->size());
2073 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2074}
2075
2076TEST_P(QuicSessionTestServer, RstStreamReceivedAfterRstStreamSent) {
2077 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2078 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
2079 EXPECT_TRUE(stream2->IsWaitingForAcks());
2080
2081 EXPECT_CALL(*connection_, SendControlFrame(_));
2082 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
fkastenholz8556dc22019-07-18 12:42:38 -07002083 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002084 stream2->Reset(quic::QUIC_STREAM_CANCELLED);
2085
2086 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream2->id(),
2087 QUIC_ERROR_PROCESSING_STREAM, 0);
fkastenholz305e1732019-06-18 05:01:22 -07002088 if (!VersionHasIetfQuicFrames(transport_version())) {
fkastenholz8556dc22019-07-18 12:42:38 -07002089 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002090 }
2091 session_.OnRstStream(rst1);
2092}
2093
2094// Regression test of b/71548958.
2095TEST_P(QuicSessionTestServer, TestZombieStreams) {
2096 session_.set_writev_consumes_all_data(true);
2097
2098 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07002099 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002100 stream2->WriteOrBufferData(body, false, nullptr);
2101 EXPECT_TRUE(stream2->IsWaitingForAcks());
2102 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream2).size());
2103
2104 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream2->id(),
2105 QUIC_STREAM_CANCELLED, 1234);
2106 // Just for the RST_STREAM
2107 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002108 .WillOnce(Invoke(&ClearControlFrame));
fkastenholz305e1732019-06-18 05:01:22 -07002109 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002110 EXPECT_CALL(*connection_,
2111 OnStreamReset(stream2->id(), QUIC_STREAM_CANCELLED));
2112 } else {
2113 EXPECT_CALL(*connection_,
2114 OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT));
2115 }
2116 stream2->OnStreamReset(rst_frame);
2117
fkastenholz305e1732019-06-18 05:01:22 -07002118 if (VersionHasIetfQuicFrames(transport_version())) {
2119 // The test is predicated on the stream being fully closed. For IETF QUIC,
2120 // the RST_STREAM only does one side (the read side from the perspective of
2121 // the node receiving the RST_STREAM). This is needed to fully close the
QUICHE teama6ef0a62019-03-07 20:34:33 -05002122 // stream and therefore fulfill all of the expects.
2123 QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
2124 QUIC_STREAM_CANCELLED);
renjietangeab918f2019-10-28 12:10:32 -07002125 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2126 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002127 }
2128 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2129 ASSERT_EQ(1u, session_.closed_streams()->size());
2130 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2131
2132 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
fkastenholz305e1732019-06-18 05:01:22 -07002133 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002134 // Once for the RST_STREAM, once for the STOP_SENDING
2135 EXPECT_CALL(*connection_, SendControlFrame(_))
2136 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07002137 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002138 } else {
2139 // Just for the RST_STREAM
2140 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
2141 }
2142 EXPECT_CALL(*connection_,
2143 OnStreamReset(stream4->id(), QUIC_STREAM_CANCELLED));
2144 stream4->WriteOrBufferData(body, false, nullptr);
2145 // Note well: Reset() actually closes the stream in both directions. For
2146 // GOOGLE QUIC it sends a RST_STREAM (which does a 2-way close), for IETF
fkastenholz305e1732019-06-18 05:01:22 -07002147 // QUIC it sends both a RST_STREAM and a STOP_SENDING (each of which
QUICHE teama6ef0a62019-03-07 20:34:33 -05002148 // closes in only one direction).
2149 stream4->Reset(QUIC_STREAM_CANCELLED);
2150 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2151 EXPECT_EQ(2u, session_.closed_streams()->size());
2152}
2153
2154TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002155 InSequence s;
2156
2157 // Drive congestion control manually.
2158 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2159 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2160
2161 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
2162 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2163 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2164
nharper46833c32019-05-15 21:33:05 -07002165 QuicStreamFrame frame1;
2166 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
2167 frame1 = QuicStreamFrame(
2168 QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
2169 0, 1300);
2170 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002171 QuicStreamFrame frame2(stream2->id(), false, 0, 9);
2172 QuicStreamFrame frame3(stream4->id(), false, 0, 9);
2173
2174 // Lost data on cryption stream, streams 2 and 4.
2175 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
QUICHE teamea740082019-03-11 17:58:43 -07002176 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002177 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2178 .WillOnce(Return(true));
2179 }
2180 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2181 session_.OnFrameLost(QuicFrame(frame3));
QUICHE teamea740082019-03-11 17:58:43 -07002182 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002183 session_.OnFrameLost(QuicFrame(frame1));
2184 } else {
QUICHE team6987b4a2019-03-15 16:23:04 -07002185 QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002186 session_.OnFrameLost(QuicFrame(&crypto_frame));
2187 }
2188 session_.OnFrameLost(QuicFrame(frame2));
2189 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2190
2191 // Mark streams 2 and 4 write blocked.
2192 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2193 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2194
2195 // Lost data is retransmitted before new data, and retransmissions for crypto
2196 // stream go first.
2197 // Do not check congestion window when crypto stream has lost data.
2198 EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
QUICHE teamea740082019-03-11 17:58:43 -07002199 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002200 EXPECT_CALL(*crypto_stream, OnCanWrite());
2201 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2202 .WillOnce(Return(false));
2203 }
2204 // Check congestion window for non crypto streams.
2205 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2206 EXPECT_CALL(*stream4, OnCanWrite());
2207 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(false));
2208 // Connection is blocked.
2209 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(false));
2210
2211 session_.OnCanWrite();
2212 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2213
2214 // Unblock connection.
2215 // Stream 2 retransmits lost data.
2216 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2217 EXPECT_CALL(*stream2, OnCanWrite());
2218 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2219 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2220 // Stream 2 sends new data.
2221 EXPECT_CALL(*stream2, OnCanWrite());
2222 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2223 EXPECT_CALL(*stream4, OnCanWrite());
2224 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2225
2226 session_.OnCanWrite();
2227 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2228}
2229
2230TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002231 InSequence s;
2232
2233 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2234 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2235 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2236
2237 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2238 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2239 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2240
2241 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(true));
2242 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
2243 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2244 session_.OnFrameLost(QuicFrame(frame3));
2245 session_.OnFrameLost(QuicFrame(frame2));
2246 session_.OnFrameLost(QuicFrame(frame1));
2247
2248 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2249 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2250 session_.MarkConnectionLevelWriteBlocked(stream6->id());
2251
2252 // Reset stream 4 locally.
2253 EXPECT_CALL(*connection_, SendControlFrame(_));
2254 EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
2255 stream4->Reset(QUIC_STREAM_CANCELLED);
2256
2257 // Verify stream 4 is removed from streams with lost data list.
2258 EXPECT_CALL(*stream6, OnCanWrite());
2259 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
2260 EXPECT_CALL(*stream2, OnCanWrite());
2261 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2262 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002263 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002264 EXPECT_CALL(*stream2, OnCanWrite());
2265 EXPECT_CALL(*stream6, OnCanWrite());
2266 session_.OnCanWrite();
2267}
2268
2269TEST_P(QuicSessionTestServer, RetransmitFrames) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002270 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2271 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2272 InSequence s;
2273
2274 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2275 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2276 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2277 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002278 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002279 session_.SendWindowUpdate(stream2->id(), 9);
2280
2281 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2282 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2283 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2284 QuicWindowUpdateFrame window_update(1, stream2->id(), 9);
2285 QuicFrames frames;
2286 frames.push_back(QuicFrame(frame1));
2287 frames.push_back(QuicFrame(&window_update));
2288 frames.push_back(QuicFrame(frame2));
2289 frames.push_back(QuicFrame(frame3));
2290 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2291
2292 EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2293 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002294 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002295 EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2296 EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
2297 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2298 session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
2299}
2300
2301// Regression test of b/110082001.
2302TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) {
2303 // This test mimics the scenario when a dynamic stream retransmits lost data
2304 // and causes connection close.
QUICHE teama6ef0a62019-03-07 20:34:33 -05002305 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2306 QuicStreamFrame frame(stream->id(), false, 0, 9);
2307
2308 EXPECT_CALL(*stream, HasPendingRetransmission())
2309 .Times(2)
2310 .WillOnce(Return(true))
2311 .WillOnce(Return(false));
2312 session_.OnFrameLost(QuicFrame(frame));
2313 // Retransmit stream data causes connection close. Stream has not sent fin
2314 // yet, so an RST is sent.
2315 EXPECT_CALL(*stream, OnCanWrite())
2316 .WillOnce(Invoke(stream, &QuicStream::OnClose));
fkastenholz305e1732019-06-18 05:01:22 -07002317 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002318 // Once for the RST_STREAM, once for the STOP_SENDING
2319 EXPECT_CALL(*connection_, SendControlFrame(_))
2320 .Times(2)
2321 .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
2322 } else {
2323 // Just for the RST_STREAM
2324 EXPECT_CALL(*connection_, SendControlFrame(_))
2325 .WillOnce(Invoke(&session_, &TestSession::SaveFrame));
2326 }
2327 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
2328 session_.OnCanWrite();
2329}
2330
2331TEST_P(QuicSessionTestServer, SendMessage) {
2332 // Cannot send message when encryption is not established.
2333 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
2334 quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
2335 EXPECT_EQ(MessageResult(MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0),
2336 session_.SendMessage(
2337 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2338 "", &storage)));
2339
2340 // Finish handshake.
2341 CryptoHandshakeMessage handshake_message;
2342 session_.GetMutableCryptoStream()->OnHandshakeMessage(handshake_message);
2343 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
2344
2345 QuicStringPiece message;
2346 EXPECT_CALL(*connection_, SendMessage(1, _))
2347 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2348 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
2349 session_.SendMessage(
2350 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2351 message, &storage)));
2352 // Verify message_id increases.
2353 EXPECT_CALL(*connection_, SendMessage(2, _))
2354 .WillOnce(Return(MESSAGE_STATUS_TOO_LARGE));
2355 EXPECT_EQ(MessageResult(MESSAGE_STATUS_TOO_LARGE, 0),
2356 session_.SendMessage(
2357 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2358 message, &storage)));
2359 // Verify unsent message does not consume a message_id.
2360 EXPECT_CALL(*connection_, SendMessage(2, _))
2361 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2362 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 2),
2363 session_.SendMessage(
2364 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2365 message, &storage)));
2366
2367 QuicMessageFrame frame(1);
2368 QuicMessageFrame frame2(2);
2369 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2370 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2371
2372 // Lost message 2.
2373 session_.OnMessageLost(2);
2374 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2375
2376 // message 1 gets acked.
QUICHE team9467db02019-05-30 09:38:45 -07002377 session_.OnMessageAcked(1, QuicTime::Zero());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002378 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2379}
2380
2381// Regression test of b/115323618.
2382TEST_P(QuicSessionTestServer, LocallyResetZombieStreams) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002383 session_.set_writev_consumes_all_data(true);
2384 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07002385 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002386 stream2->CloseReadSide();
2387 stream2->WriteOrBufferData(body, true, nullptr);
2388 EXPECT_TRUE(stream2->IsWaitingForAcks());
2389 // Verify stream2 is a zombie streams.
2390 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2391
2392 QuicStreamFrame frame(stream2->id(), true, 0, 100);
2393 EXPECT_CALL(*stream2, HasPendingRetransmission())
2394 .WillRepeatedly(Return(true));
2395 session_.OnFrameLost(QuicFrame(frame));
2396
2397 // Reset stream2 locally.
2398 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002399 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002400 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2401 stream2->Reset(QUIC_STREAM_CANCELLED);
2402
2403 // Verify stream 2 gets closed.
2404 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2405 EXPECT_TRUE(session_.IsClosedStream(stream2->id()));
2406 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
2407 session_.OnCanWrite();
2408}
2409
2410TEST_P(QuicSessionTestServer, CleanUpClosedStreamsAlarm) {
2411 EXPECT_FALSE(
2412 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2413
2414 session_.set_writev_consumes_all_data(true);
2415 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2416 EXPECT_FALSE(stream2->IsWaitingForAcks());
2417
2418 EXPECT_CALL(*connection_, SendControlFrame(_));
2419 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2420 session_.CloseStream(stream2->id());
2421 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2422 EXPECT_EQ(1u, session_.closed_streams()->size());
2423 EXPECT_TRUE(
2424 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2425
2426 alarm_factory_.FireAlarm(
2427 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_));
2428 EXPECT_TRUE(session_.closed_streams()->empty());
2429}
2430
2431TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
2432 session_.set_writev_consumes_all_data(true);
2433 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2434 &session_, WRITE_UNIDIRECTIONAL);
2435 session_.ActivateStream(QuicWrapUnique(stream4));
vasilvvc48c8712019-03-11 13:38:16 -07002436 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002437 stream4->WriteOrBufferData(body, false, nullptr);
2438 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2439 stream4->WriteOrBufferData(body, true, nullptr);
2440 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2441}
2442
2443TEST_P(QuicSessionTestServer, ReceivedDataOnWriteUnidirectionalStream) {
2444 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2445 &session_, WRITE_UNIDIRECTIONAL);
2446 session_.ActivateStream(QuicWrapUnique(stream4));
2447
2448 EXPECT_CALL(
2449 *connection_,
2450 CloseConnection(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM, _, _))
2451 .Times(1);
2452 QuicStreamFrame stream_frame(GetNthServerInitiatedUnidirectionalId(1), false,
2453 0, 2);
2454 session_.OnStreamFrame(stream_frame);
2455}
2456
2457TEST_P(QuicSessionTestServer, ReadUnidirectionalStream) {
2458 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2459 &session_, READ_UNIDIRECTIONAL);
2460 session_.ActivateStream(QuicWrapUnique(stream4));
2461 EXPECT_FALSE(stream4->IsWaitingForAcks());
2462 // Discard all incoming data.
2463 stream4->StopReading();
2464
vasilvvc48c8712019-03-11 13:38:16 -07002465 std::string data(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002466 QuicStreamFrame stream_frame(GetNthClientInitiatedUnidirectionalId(1), false,
2467 0, data);
2468 stream4->OnStreamFrame(stream_frame);
2469 EXPECT_TRUE(session_.closed_streams()->empty());
2470
2471 QuicStreamFrame stream_frame2(GetNthClientInitiatedUnidirectionalId(1), true,
2472 100, data);
2473 stream4->OnStreamFrame(stream_frame2);
2474 EXPECT_EQ(1u, session_.closed_streams()->size());
2475}
2476
2477TEST_P(QuicSessionTestServer, WriteOrBufferDataOnReadUnidirectionalStream) {
2478 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2479 &session_, READ_UNIDIRECTIONAL);
2480 session_.ActivateStream(QuicWrapUnique(stream4));
2481
2482 EXPECT_CALL(*connection_,
2483 CloseConnection(
2484 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2485 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002486 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002487 stream4->WriteOrBufferData(body, false, nullptr);
2488}
2489
2490TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
2491 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2492 &session_, READ_UNIDIRECTIONAL);
2493 session_.ActivateStream(QuicWrapUnique(stream4));
2494
2495 EXPECT_CALL(*connection_,
2496 CloseConnection(
2497 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2498 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002499 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002500 struct iovec iov = {const_cast<char*>(body.data()), body.length()};
2501 QuicMemSliceStorage storage(
2502 &iov, 1, session_.connection()->helper()->GetStreamSendBufferAllocator(),
2503 1024);
2504 stream4->WriteMemSlices(storage.ToSpan(), false);
2505}
2506
2507TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
2508 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2509 &session_, READ_UNIDIRECTIONAL);
2510 session_.ActivateStream(QuicWrapUnique(stream4));
2511
2512 EXPECT_CALL(*connection_,
2513 CloseConnection(
2514 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2515 .Times(1);
2516 char data[1024];
2517 std::vector<std::pair<char*, size_t>> buffers;
2518 buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
2519 buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
2520 QuicTestMemSliceVector vector(buffers);
2521 stream4->WriteMemSlices(vector.span(), false);
2522}
2523
2524// Test code that tests that an incoming stream frame with a new (not previously
2525// seen) stream id is acceptable. The ID must not be larger than has been
2526// advertised. It may be equal to what has been advertised. These tests
2527// invoke QuicStreamIdManager::MaybeIncreaseLargestPeerStreamId by calling
2528// QuicSession::OnStreamFrame in order to check that all the steps are connected
2529// properly and that nothing in the call path interferes with the check.
2530// First test make sure that streams with ids below the limit are accepted.
2531TEST_P(QuicSessionTestServer, NewStreamIdBelowLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002532 if (!VersionHasIetfQuicFrames(transport_version())) {
2533 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002534 return;
2535 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002536 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002537 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002538 ->advertised_max_incoming_bidirectional_streams() -
fkastenholz3c4eabf2019-04-22 07:49:59 -07002539 1,
2540 Perspective::IS_CLIENT,
2541 /*bidirectional=*/true);
2542
QUICHE teama6ef0a62019-03-07 20:34:33 -05002543 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2544 "Random String");
2545 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2546 session_.OnStreamFrame(bidirectional_stream_frame);
2547
fkastenholz3c4eabf2019-04-22 07:49:59 -07002548 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002549 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002550 ->advertised_max_incoming_unidirectional_streams() -
fkastenholz3c4eabf2019-04-22 07:49:59 -07002551 1,
2552 Perspective::IS_CLIENT,
2553 /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002554 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2555 0, "Random String");
2556 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2557 session_.OnStreamFrame(unidirectional_stream_frame);
2558}
2559
2560// Accept a stream with an ID that equals the limit.
2561TEST_P(QuicSessionTestServer, NewStreamIdAtLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002562 if (!VersionHasIetfQuicFrames(transport_version())) {
2563 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002564 return;
2565 }
ianswettd1414532019-09-18 20:12:59 -07002566 QuicStreamId bidirectional_stream_id =
2567 StreamCountToId(QuicSessionPeer::v99_streamid_manager(&session_)
2568 ->advertised_max_incoming_bidirectional_streams(),
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");
2572 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2573 session_.OnStreamFrame(bidirectional_stream_frame);
2574
ianswettd1414532019-09-18 20:12:59 -07002575 QuicStreamId unidirectional_stream_id =
2576 StreamCountToId(QuicSessionPeer::v99_streamid_manager(&session_)
2577 ->advertised_max_incoming_unidirectional_streams(),
2578 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002579 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2580 0, "Random String");
2581 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2582 session_.OnStreamFrame(unidirectional_stream_frame);
2583}
2584
2585// Close the connection if the id exceeds the limit.
2586TEST_P(QuicSessionTestServer, NewStreamIdAboveLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002587 if (!VersionHasIetfQuicFrames(transport_version())) {
2588 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002589 return;
2590 }
fkastenholz56055be2019-09-17 11:17:37 -07002591
fkastenholz3c4eabf2019-04-22 07:49:59 -07002592 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002593 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002594 ->advertised_max_incoming_bidirectional_streams() +
fkastenholz3c4eabf2019-04-22 07:49:59 -07002595 1,
2596 Perspective::IS_CLIENT, /*bidirectional=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002597 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2598 "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002599 EXPECT_CALL(
2600 *connection_,
2601 CloseConnection(QUIC_INVALID_STREAM_ID,
nharpercd820e02019-05-16 15:12:07 -07002602 "Stream id 400 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002603 session_.OnStreamFrame(bidirectional_stream_frame);
2604
fkastenholz3c4eabf2019-04-22 07:49:59 -07002605 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002606 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002607 ->advertised_max_incoming_unidirectional_streams() +
fkastenholz3c4eabf2019-04-22 07:49:59 -07002608 1,
2609 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002610 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2611 0, "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002612 EXPECT_CALL(
2613 *connection_,
2614 CloseConnection(QUIC_INVALID_STREAM_ID,
2615 "Stream id 402 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002616 session_.OnStreamFrame(unidirectional_stream_frame);
2617}
2618
2619// Check that the OnStopSendingFrame upcall handles bad input properly
2620// First test checks that invalid stream ids are handled.
2621TEST_P(QuicSessionTestServer, OnStopSendingInputInvalidStreamId) {
fkastenholz305e1732019-06-18 05:01:22 -07002622 if (!VersionHasIetfQuicFrames(transport_version())) {
2623 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002624 return;
2625 }
2626 // Check that "invalid" stream ids are rejected.
2627 // Note that the notion of an invalid stream id is Google-specific.
2628 QuicStopSendingFrame frame(1, -1, 123);
2629 EXPECT_CALL(
2630 *connection_,
2631 CloseConnection(QUIC_INVALID_STREAM_ID,
2632 "Received STOP_SENDING for an invalid stream", _));
renjietangeab918f2019-10-28 12:10:32 -07002633 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002634}
2635
2636// Second test, streams in the static stream map are not subject to
2637// STOP_SENDING; it's ignored.
2638TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
fkastenholz305e1732019-06-18 05:01:22 -07002639 if (!VersionHasIetfQuicFrames(transport_version())) {
2640 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002641 return;
2642 }
nharper46833c32019-05-15 21:33:05 -07002643 QuicStreamId stream_id = 0;
vasilvv0fc587f2019-09-06 13:33:08 -07002644 std::unique_ptr<TestStream> fake_static_stream = std::make_unique<TestStream>(
nharper46833c32019-05-15 21:33:05 -07002645 stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07002646 QuicSessionPeer::ActivateStream(&session_, std::move(fake_static_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002647 // Check that a stream id in the static stream map is ignored.
2648 // Note that the notion of a static stream is Google-specific.
nharper46833c32019-05-15 21:33:05 -07002649 QuicStopSendingFrame frame(1, stream_id, 123);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002650 EXPECT_CALL(*connection_,
2651 CloseConnection(QUIC_INVALID_STREAM_ID,
2652 "Received STOP_SENDING for a static stream", _));
renjietangeab918f2019-10-28 12:10:32 -07002653 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002654}
2655
2656// Third test, if stream id specifies a closed stream:
2657// return true and do not close the connection.
2658TEST_P(QuicSessionTestServer, OnStopSendingInputClosedStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002659 if (!VersionHasIetfQuicFrames(transport_version())) {
2660 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002661 return;
2662 }
2663
2664 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2665 QuicStreamId stream_id = stream->id();
2666 // Expect these as side effect of the close operations.
2667 EXPECT_CALL(*connection_, SendControlFrame(_));
2668 EXPECT_CALL(*connection_, OnStreamReset(_, _));
2669 stream->CloseWriteSide();
2670 stream->CloseReadSide();
2671 QuicStopSendingFrame frame(1, stream_id, 123);
2672 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietangeab918f2019-10-28 12:10:32 -07002673 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002674}
2675
2676// Fourth test, if stream id specifies a nonexistent stream, return false and
2677// close the connection
2678TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002679 if (!VersionHasIetfQuicFrames(transport_version())) {
2680 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002681 return;
2682 }
2683
2684 QuicStopSendingFrame frame(1, GetNthServerInitiatedBidirectionalId(123456),
2685 123);
2686 EXPECT_CALL(
2687 *connection_,
2688 CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
2689 "Received STOP_SENDING for a non-existent stream", _))
2690 .Times(1);
renjietangeab918f2019-10-28 12:10:32 -07002691 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002692}
2693
2694// For a valid stream, ensure that all works
2695TEST_P(QuicSessionTestServer, OnStopSendingInputValidStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002696 if (!VersionHasIetfQuicFrames(transport_version())) {
2697 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002698 return;
2699 }
2700
2701 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2702
2703 // Ensure that the stream starts out open in both directions.
bncc7d9e0c2019-04-16 10:22:15 -07002704 EXPECT_FALSE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002705 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
2706
2707 QuicStreamId stream_id = stream->id();
2708 QuicStopSendingFrame frame(1, stream_id, 123);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002709 // Expect a reset to come back out.
2710 EXPECT_CALL(*connection_, SendControlFrame(_));
2711 EXPECT_CALL(
2712 *connection_,
2713 OnStreamReset(stream_id, static_cast<QuicRstStreamErrorCode>(123)));
renjietangeab918f2019-10-28 12:10:32 -07002714 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2715 session_.OnStopSendingFrame(frame);
renjietange5c12382019-11-07 10:13:14 -08002716
QUICHE teama6ef0a62019-03-07 20:34:33 -05002717 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
bncc7d9e0c2019-04-16 10:22:15 -07002718 EXPECT_TRUE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002719}
2720
fayangaee31ef2019-08-20 06:47:51 -07002721TEST_P(QuicSessionTestServer, WriteBufferedCryptoFrames) {
2722 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
2723 return;
2724 }
2725 std::string data(1350, 'a');
2726 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
2727 // Only consumed 1000 bytes.
2728 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 1350, 0))
2729 .WillOnce(Return(1000));
2730 crypto_stream->WriteCryptoData(ENCRYPTION_INITIAL, data);
2731 EXPECT_TRUE(session_.HasPendingHandshake());
2732 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2733
2734 EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
2735 crypto_stream->WriteCryptoData(ENCRYPTION_ZERO_RTT, data);
2736
2737 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 350, 1000))
2738 .WillOnce(Return(350));
2739 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1350, 0))
2740 .WillOnce(Return(1350));
2741 session_.OnCanWrite();
2742 EXPECT_FALSE(session_.HasPendingHandshake());
2743 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2744}
2745
renjietang963c2ec2019-09-12 11:46:50 -07002746// Regression test for
2747// https://bugs.chromium.org/p/chromium/issues/detail?id=1002119
2748TEST_P(QuicSessionTestServer, StreamFrameReceivedAfterFin) {
2749 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2750 QuicStreamFrame frame(stream->id(), true, 0, ",");
2751 session_.OnStreamFrame(frame);
2752
2753 QuicStreamFrame frame1(stream->id(), false, 1, ",");
renjietang15afba32019-10-23 14:32:35 -07002754 if (!GetQuicReloadableFlag(quic_close_connection_on_wrong_offset)) {
2755 EXPECT_CALL(*connection_, SendControlFrame(_));
2756 EXPECT_CALL(*connection_,
2757 OnStreamReset(stream->id(), QUIC_DATA_AFTER_CLOSE_OFFSET));
2758 } else {
2759 EXPECT_CALL(*connection_,
2760 CloseConnection(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET, _, _));
2761 }
renjietang89aa73e2019-10-21 15:03:51 -07002762 session_.OnStreamFrame(frame1);
renjietang963c2ec2019-09-12 11:46:50 -07002763}
2764
renjietangd9762282019-11-11 17:11:18 -08002765TEST_P(QuicSessionTestServer, ResetForIETFStreamTypes) {
2766 if (!VersionHasIetfQuicFrames(transport_version())) {
2767 return;
2768 }
2769
2770 QuicStreamId read_only = GetNthClientInitiatedUnidirectionalId(0);
2771 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
2772 EXPECT_CALL(*connection_, OnStreamReset(read_only, _));
2773 session_.SendRstStreamInner(read_only, QUIC_STREAM_CANCELLED, 0,
2774 /*close_write_side_only = */ true);
2775
2776 EXPECT_CALL(*connection_, SendControlFrame(_))
2777 .Times(1)
2778 .WillOnce(Invoke(&ClearControlFrame));
2779 EXPECT_CALL(*connection_, OnStreamReset(read_only, _));
2780 session_.SendRstStreamInner(read_only, QUIC_STREAM_CANCELLED, 0,
2781 /*close_write_side_only = */ false);
2782
2783 QuicStreamId write_only = GetNthServerInitiatedUnidirectionalId(0);
2784 EXPECT_CALL(*connection_, SendControlFrame(_))
2785 .Times(1)
2786 .WillOnce(Invoke(&ClearControlFrame));
2787 EXPECT_CALL(*connection_, OnStreamReset(write_only, _));
2788 session_.SendRstStreamInner(write_only, QUIC_STREAM_CANCELLED, 0,
2789 /*close_write_side_only = */ false);
2790
2791 QuicStreamId bidirectional = GetNthClientInitiatedBidirectionalId(0);
2792 EXPECT_CALL(*connection_, SendControlFrame(_))
2793 .Times(2)
2794 .WillRepeatedly(Invoke(&ClearControlFrame));
2795 EXPECT_CALL(*connection_, OnStreamReset(bidirectional, _));
2796 session_.SendRstStreamInner(bidirectional, QUIC_STREAM_CANCELLED, 0,
2797 /*close_write_side_only = */ false);
2798}
2799
fkastenholz56055be2019-09-17 11:17:37 -07002800// A client test class that can be used when the automatic configuration is not
2801// desired.
2802class QuicSessionTestClientUnconfigured : public QuicSessionTestBase {
2803 protected:
2804 QuicSessionTestClientUnconfigured()
2805 : QuicSessionTestBase(Perspective::IS_CLIENT,
2806 /*configure_session=*/false) {}
2807};
2808
2809INSTANTIATE_TEST_SUITE_P(Tests,
2810 QuicSessionTestClientUnconfigured,
dschinazi142051a2019-09-18 18:17:29 -07002811 ::testing::ValuesIn(AllSupportedVersions()),
2812 ::testing::PrintToStringParamName());
fkastenholz56055be2019-09-17 11:17:37 -07002813
2814TEST_P(QuicSessionTestClientUnconfigured, HoldMaxStreamsFrame) {
2815 if (!VersionHasIetfQuicFrames(transport_version())) {
2816 return;
2817 }
2818 QuicStreamIdManager* stream_id_manager =
2819 QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
2820
2821 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
2822 QuicStreamsBlockedFrame frame(1u, 0u, /*unidirectional=*/true);
2823 session_.OnStreamsBlockedFrame(frame);
2824 EXPECT_CALL(*connection_, SendControlFrame(_))
2825 .Times(1)
2826 .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
2827 session_.OnConfigNegotiated();
2828 EXPECT_EQ(MAX_STREAMS_FRAME, session_.save_frame().type);
2829 EXPECT_EQ(stream_id_manager->incoming_actual_max_streams(),
2830 session_.save_frame().max_streams_frame.stream_count);
2831 EXPECT_EQ(1u, session_.save_frame().max_streams_frame.control_frame_id);
2832}
2833
2834TEST_P(QuicSessionTestClientUnconfigured, HoldStreamsBlockedFrameXmit) {
2835 if (!VersionHasIetfQuicFrames(transport_version())) {
2836 // Applicable only to IETF QUIC
2837 return;
2838 }
2839 QuicStreamIdManager* stream_id_manager =
2840 QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
2841
2842 // Set the stream limit to 0 which will cause
2843 // CanOpenNextOutgoingUnidirectionalStream()
2844 // to generated a STREAMS_BLOCKED frame.
2845 QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager, 0);
2846
2847 // Since the stream limit is 0 and no sreams can be created this should return
2848 // false and have forced a streams-blocked to be queued up, with the
2849 // blocked stream id == 0.
2850 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
2851 EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
2852
2853 // We will expect two calls to SendControlFrame: The first is because
2854 // OnConfigNegotiated does not increase the limit, so the app still can not
2855 // create new streams (and therefore needs the STREAMS-BLOCKED to go out). The
2856 // second is because the ensuing CanOpenNext.. call will fail (this test not
2857 // actually increasing the limit) and that will send another STREAMS-BLOCKED.
2858 EXPECT_CALL(*connection_, SendControlFrame(_))
2859 .Times(2)
2860 .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
2861 // Set configuration data so that when the config happens, the stream limit is
2862 // not increased and another STREAMS-BLOCKED will be needed..
2863 QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(session_.config(),
2864 0);
2865
2866 session_.OnConfigNegotiated();
2867
2868 EXPECT_EQ(STREAMS_BLOCKED_FRAME, session_.save_frame().type);
2869 EXPECT_EQ(0u, session_.save_frame().streams_blocked_frame.stream_count);
2870 EXPECT_EQ(1u, session_.save_frame().streams_blocked_frame.control_frame_id);
2871
2872 EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
2873 EXPECT_EQ(STREAMS_BLOCKED_FRAME, session_.save_frame().type);
2874 EXPECT_EQ(0u, session_.save_frame().streams_blocked_frame.stream_count);
2875 EXPECT_EQ(2u, session_.save_frame().streams_blocked_frame.control_frame_id);
2876}
2877
2878TEST_P(QuicSessionTestClientUnconfigured, HoldStreamsBlockedFrameNoXmit) {
2879 if (!VersionHasIetfQuicFrames(transport_version())) {
2880 return;
2881 }
2882 QuicStreamIdManager* stream_id_manager =
2883 QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
2884
2885 // Set the stream limit to 0 which will cause
2886 // CanOpenNextOutgoingUnidirectionalStream()
2887 // to generated a STREAMS_BLOCKED frame.
2888 QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager, 0);
2889
2890 // Since the stream limit is 0 and no streams can be created this should
2891 // return false and have forced a streams-blocked to be queued up, with the
2892 // blocked stream id == 0.
2893 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
2894 EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
2895
2896 // Set configuration data so that when the config happens, the stream limit is
2897 // increased.
2898 QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(session_.config(),
2899 10);
2900
2901 // STREAMS_BLOCKED frame should not be sent because streams can now be
2902 // created.
2903 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
2904 session_.OnConfigNegotiated();
2905 EXPECT_TRUE(session_.CanOpenNextOutgoingUnidirectionalStream());
2906}
2907
dschinazi18cdf132019-10-09 16:08:18 -07002908TEST_P(QuicSessionTestClientUnconfigured, StreamInitiallyBlockedThenUnblocked) {
2909 if (!connection_->version().AllowsLowFlowControlLimits()) {
2910 return;
2911 }
2912 // Create a stream before negotiating the config and verify it starts off
2913 // blocked.
2914 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2915 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
2916 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
2917 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
2918
2919 // Negotiate the config with higher received limits.
2920 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
2921 session_.config(), kMinimumFlowControlSendWindow);
2922 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
2923 session_.config(), kMinimumFlowControlSendWindow);
2924 session_.OnConfigNegotiated();
2925
2926 // Stream is now unblocked.
2927 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
2928 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
2929 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
2930}
2931
QUICHE teama6ef0a62019-03-07 20:34:33 -05002932} // namespace
2933} // namespace test
2934} // namespace quic