blob: 36b55a1b0752ee9ed15b1b79d2b84f2b99c8c781 [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"
renjietangab9039a2020-03-30 14:53:19 -070015#include "net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050016#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
17#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
18#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
19#include "net/third_party/quiche/src/quic/core/quic_packets.h"
20#include "net/third_party/quiche/src/quic/core/quic_stream.h"
21#include "net/third_party/quiche/src/quic/core/quic_utils.h"
dschinaziaab68182019-10-09 15:39:51 -070022#include "net/third_party/quiche/src/quic/core/quic_versions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#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"
QUICHE teama6ef0a62019-03-07 20:34:33 -050028#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
29#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
30#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
31#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
fkastenholz56055be2019-09-17 11:17:37 -070035#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050036#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
37#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
38#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
bnc4e9283d2019-12-17 07:08:57 -080039#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
renjietang41a1b412020-02-27 15:05:14 -080040#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080041#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
42#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050043
44using spdy::kV3HighestPriority;
45using spdy::SpdyPriority;
46using testing::_;
47using testing::AtLeast;
48using testing::InSequence;
49using testing::Invoke;
50using testing::NiceMock;
51using testing::Return;
52using testing::StrictMock;
53using testing::WithArg;
54
55namespace quic {
56namespace test {
57namespace {
58
59class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
60 public:
61 explicit TestCryptoStream(QuicSession* session)
62 : QuicCryptoStream(session),
63 QuicCryptoHandshaker(this, session),
64 encryption_established_(false),
fayang685367a2020-01-14 10:40:15 -080065 one_rtt_keys_available_(false),
rch9001a962019-12-17 10:44:04 -080066 params_(new QuicCryptoNegotiatedParameters) {
67 // Simulate a negotiated cipher_suite with a fake value.
68 params_->cipher_suite = 1;
69 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050070
71 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
72 encryption_established_ = true;
fayang685367a2020-01-14 10:40:15 -080073 one_rtt_keys_available_ = true;
dschinaziaab68182019-10-09 15:39:51 -070074 QuicErrorCode error;
vasilvvc48c8712019-03-11 13:38:16 -070075 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 session()->config()->SetInitialStreamFlowControlWindowToSend(
77 kInitialStreamFlowControlWindowForTest);
78 session()->config()->SetInitialSessionFlowControlWindowToSend(
79 kInitialSessionFlowControlWindowForTest);
dschinaziaab68182019-10-09 15:39:51 -070080 if (session()->connection()->version().handshake_protocol ==
81 PROTOCOL_TLS1_3) {
82 TransportParameters transport_parameters;
83 EXPECT_TRUE(
84 session()->config()->FillTransportParameters(&transport_parameters));
85 error = session()->config()->ProcessTransportParameters(
86 transport_parameters, CLIENT, &error_details);
87 } else {
88 CryptoHandshakeMessage msg;
89 session()->config()->ToHandshakeMessage(&msg, transport_version());
90 error =
91 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
92 }
bncf6f82b12019-10-30 07:01:01 -070093 EXPECT_THAT(error, IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -050094 session()->OnConfigNegotiated();
fayangd18bfb92020-03-19 17:24:21 -070095 if (session()->connection()->version().handshake_protocol ==
96 PROTOCOL_TLS1_3) {
97 session()->OnOneRttKeysAvailable();
98 } else {
99 session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
100 }
fayangd96ecda2020-02-03 08:45:18 -0800101 session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500102 }
103
104 // QuicCryptoStream implementation
105 bool encryption_established() const override {
106 return encryption_established_;
107 }
fayang685367a2020-01-14 10:40:15 -0800108 bool one_rtt_keys_available() const override {
109 return one_rtt_keys_available_;
110 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500111 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
112 const override {
113 return *params_;
114 }
115 CryptoMessageParser* crypto_message_parser() override {
116 return QuicCryptoHandshaker::crypto_message_parser();
117 }
fayangd58736d2019-11-27 13:35:31 -0800118 void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
fayang2f2915d2020-01-24 06:47:15 -0800119 void OnOneRttPacketAcknowledged() override {}
fayang01062942020-01-22 07:23:23 -0800120 void OnHandshakeDoneReceived() override {}
fayang9a863cf2020-01-16 14:12:11 -0800121 HandshakeState GetHandshakeState() const override {
122 return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
123 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124
dschinazibb40f432020-04-16 13:15:21 -0700125 MOCK_METHOD(void, OnCanWrite, (), (override));
nharper46833c32019-05-15 21:33:05 -0700126 bool HasPendingCryptoRetransmission() const override { return false; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500127
dschinazibb40f432020-04-16 13:15:21 -0700128 MOCK_METHOD(bool, HasPendingRetransmission, (), (const, override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500129
130 private:
131 using QuicCryptoStream::session;
132
133 bool encryption_established_;
fayang685367a2020-01-14 10:40:15 -0800134 bool one_rtt_keys_available_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
136};
137
138class TestStream : public QuicStream {
139 public:
140 TestStream(QuicStreamId id, QuicSession* session, StreamType type)
nharper46833c32019-05-15 21:33:05 -0700141 : TestStream(id, session, /*is_static=*/false, type) {}
142
143 TestStream(QuicStreamId id,
144 QuicSession* session,
145 bool is_static,
146 StreamType type)
147 : QuicStream(id, session, is_static, type) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500148
renjietangbaea59c2019-05-29 15:08:14 -0700149 TestStream(PendingStream* pending, StreamType type)
150 : QuicStream(pending, type, /*is_static=*/false) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500151
152 using QuicStream::CloseReadSide;
153 using QuicStream::CloseWriteSide;
154 using QuicStream::WriteMemSlices;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155
156 void OnDataAvailable() override {}
157
dschinazibb40f432020-04-16 13:15:21 -0700158 MOCK_METHOD(void, OnCanWrite, (), (override));
159 MOCK_METHOD(bool,
160 RetransmitStreamData,
161 (QuicStreamOffset, QuicByteCount, bool, TransmissionType),
162 (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163
dschinazibb40f432020-04-16 13:15:21 -0700164 MOCK_METHOD(bool, HasPendingRetransmission, (), (override, const));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500165};
166
167class TestSession : public QuicSession {
168 public:
169 explicit TestSession(QuicConnection* connection,
170 MockQuicSessionVisitor* session_visitor)
171 : QuicSession(connection,
172 session_visitor,
173 DefaultQuicConfig(),
renjietang216dc012019-08-27 11:28:27 -0700174 CurrentSupportedVersions(),
175 /*num_expected_unidirectional_static_streams = */ 0),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500176 crypto_stream_(this),
177 writev_consumes_all_data_(false),
renjietange76b2da2019-05-13 14:50:23 -0700178 uses_pending_streams_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179 num_incoming_streams_created_(0) {
180 Initialize();
181 this->connection()->SetEncrypter(
182 ENCRYPTION_FORWARD_SECURE,
vasilvv0fc587f2019-09-06 13:33:08 -0700183 std::make_unique<NullEncrypter>(connection->perspective()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500184 }
185
ianswett6aefa0b2019-12-10 07:26:15 -0800186 ~TestSession() override { DeleteConnection(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500187
188 TestCryptoStream* GetMutableCryptoStream() override {
189 return &crypto_stream_;
190 }
191
192 const TestCryptoStream* GetCryptoStream() const override {
193 return &crypto_stream_;
194 }
195
196 TestStream* CreateOutgoingBidirectionalStream() {
197 QuicStreamId id = GetNextOutgoingBidirectionalStreamId();
198 if (id ==
199 QuicUtils::GetInvalidStreamId(connection()->transport_version())) {
200 return nullptr;
201 }
202 TestStream* stream = new TestStream(id, this, BIDIRECTIONAL);
203 ActivateStream(QuicWrapUnique(stream));
204 return stream;
205 }
206
207 TestStream* CreateOutgoingUnidirectionalStream() {
208 TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
209 this, WRITE_UNIDIRECTIONAL);
210 ActivateStream(QuicWrapUnique(stream));
211 return stream;
212 }
213
214 TestStream* CreateIncomingStream(QuicStreamId id) override {
215 // Enforce the limit on the number of open streams.
fayang01591ae2020-04-23 14:14:56 -0700216 if (!VersionHasIetfQuicFrames(connection()->transport_version()) &&
217 GetNumOpenIncomingStreams() + 1 >
218 max_open_incoming_bidirectional_streams()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500219 // No need to do this test for version 99; it's done by
renjietang880d2432019-07-16 13:14:37 -0700220 // QuicSession::GetOrCreateStream.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500221 connection()->CloseConnection(
222 QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
223 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
224 return nullptr;
225 }
226
227 TestStream* stream =
228 new TestStream(id, this,
229 DetermineStreamType(
230 id, connection()->transport_version(), perspective(),
231 /*is_incoming=*/true, BIDIRECTIONAL));
232 ActivateStream(QuicWrapUnique(stream));
233 ++num_incoming_streams_created_;
234 return stream;
235 }
236
renjietangbaea59c2019-05-29 15:08:14 -0700237 TestStream* CreateIncomingStream(PendingStream* pending) override {
238 QuicStreamId id = pending->id();
239 TestStream* stream = new TestStream(
240 pending, DetermineStreamType(id, connection()->transport_version(),
241 perspective(),
242 /*is_incoming=*/true, BIDIRECTIONAL));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500243 ActivateStream(QuicWrapUnique(stream));
244 ++num_incoming_streams_created_;
245 return stream;
246 }
247
renjietange76b2da2019-05-13 14:50:23 -0700248 // QuicSession doesn't do anything in this method. So it's overridden here to
249 // test that the session handles pending streams correctly in terms of
250 // receiving stream frames.
renjietangbb1c4892019-05-24 15:58:44 -0700251 bool ProcessPendingStream(PendingStream* pending) override {
renjietange76b2da2019-05-13 14:50:23 -0700252 struct iovec iov;
253 if (pending->sequencer()->GetReadableRegion(&iov)) {
254 // Create TestStream once the first byte is received.
renjietangbaea59c2019-05-29 15:08:14 -0700255 CreateIncomingStream(pending);
renjietangbb1c4892019-05-24 15:58:44 -0700256 return true;
renjietange76b2da2019-05-13 14:50:23 -0700257 }
renjietangbb1c4892019-05-24 15:58:44 -0700258 return false;
renjietange76b2da2019-05-13 14:50:23 -0700259 }
260
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261 bool IsClosedStream(QuicStreamId id) {
262 return QuicSession::IsClosedStream(id);
263 }
264
renjietang880d2432019-07-16 13:14:37 -0700265 QuicStream* GetOrCreateStream(QuicStreamId stream_id) {
266 return QuicSession::GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267 }
268
269 bool ShouldKeepConnectionAlive() const override {
renjietang17e29932019-08-08 10:04:31 -0700270 return GetNumActiveStreams() > 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500271 }
272
renjietang41a1b412020-02-27 15:05:14 -0800273 QuicConsumedData WritevData(
274 QuicStreamId id,
275 size_t write_length,
276 QuicStreamOffset offset,
277 StreamSendingState state,
renjietang4d992bf2020-03-03 13:01:55 -0800278 TransmissionType type,
renjietang41a1b412020-02-27 15:05:14 -0800279 quiche::QuicheOptional<EncryptionLevel> level) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500280 bool fin = state != NO_FIN;
281 QuicConsumedData consumed(write_length, fin);
282 if (!writev_consumes_all_data_) {
renjietang4d992bf2020-03-03 13:01:55 -0800283 consumed =
284 QuicSession::WritevData(id, write_length, offset, state, type, level);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285 }
286 QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
287 id, consumed.bytes_consumed);
288 return consumed;
289 }
290
dschinazibb40f432020-04-16 13:15:21 -0700291 MOCK_METHOD(void,
292 OnCanCreateNewOutgoingStream,
293 (bool unidirectional),
294 (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500295
296 void set_writev_consumes_all_data(bool val) {
297 writev_consumes_all_data_ = val;
298 }
299
300 QuicConsumedData SendStreamData(QuicStream* stream) {
301 struct iovec iov;
nharper46833c32019-05-15 21:33:05 -0700302 if (!QuicUtils::IsCryptoStreamId(connection()->transport_version(),
303 stream->id()) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 this->connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
305 this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
306 }
307 MakeIOVector("not empty", &iov);
308 QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
renjietang4d992bf2020-03-03 13:01:55 -0800309 QuicConsumedData consumed =
310 WritevData(stream->id(), 9, 0, FIN, NOT_RETRANSMISSION, QuicheNullOpt);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500311 QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
312 consumed.bytes_consumed);
313 return consumed;
314 }
315
fkastenholz56055be2019-09-17 11:17:37 -0700316 const QuicFrame& save_frame() { return save_frame_; }
317
QUICHE teama6ef0a62019-03-07 20:34:33 -0500318 bool SaveFrame(const QuicFrame& frame) {
319 save_frame_ = frame;
320 DeleteFrame(&const_cast<QuicFrame&>(frame));
321 return true;
322 }
323
QUICHE teama6ef0a62019-03-07 20:34:33 -0500324 QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
325 DCHECK(writev_consumes_all_data_);
renjietang4d992bf2020-03-03 13:01:55 -0800326 return WritevData(stream->id(), bytes, 0, FIN, NOT_RETRANSMISSION,
327 QuicheNullOpt);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500328 }
329
renjietange76b2da2019-05-13 14:50:23 -0700330 bool UsesPendingStreams() const override { return uses_pending_streams_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500331
renjietange76b2da2019-05-13 14:50:23 -0700332 void set_uses_pending_streams(bool uses_pending_streams) {
333 uses_pending_streams_ = uses_pending_streams;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500334 }
335
336 int num_incoming_streams_created() const {
337 return num_incoming_streams_created_;
338 }
339
340 using QuicSession::ActivateStream;
fayang769172b2020-03-19 14:27:39 -0700341 using QuicSession::CanOpenNextOutgoingBidirectionalStream;
fkastenholz56055be2019-09-17 11:17:37 -0700342 using QuicSession::CanOpenNextOutgoingUnidirectionalStream;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343 using QuicSession::closed_streams;
fayang769172b2020-03-19 14:27:39 -0700344 using QuicSession::GetNextOutgoingBidirectionalStreamId;
345 using QuicSession::GetNextOutgoingUnidirectionalStreamId;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500346 using QuicSession::zombie_streams;
347
348 private:
349 StrictMock<TestCryptoStream> crypto_stream_;
350
351 bool writev_consumes_all_data_;
renjietange76b2da2019-05-13 14:50:23 -0700352 bool uses_pending_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500353 QuicFrame save_frame_;
354 int num_incoming_streams_created_;
355};
356
357class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
358 protected:
fkastenholz56055be2019-09-17 11:17:37 -0700359 QuicSessionTestBase(Perspective perspective, bool configure_session)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500360 : connection_(
361 new StrictMock<MockQuicConnection>(&helper_,
362 &alarm_factory_,
363 perspective,
364 SupportedVersions(GetParam()))),
fkastenholz56055be2019-09-17 11:17:37 -0700365 session_(connection_, &session_visitor_),
366 configure_session_(configure_session) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500367 session_.config()->SetInitialStreamFlowControlWindowToSend(
368 kInitialStreamFlowControlWindowForTest);
369 session_.config()->SetInitialSessionFlowControlWindowToSend(
370 kInitialSessionFlowControlWindowForTest);
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700371
fkastenholz56055be2019-09-17 11:17:37 -0700372 if (configure_session) {
renjietangab9039a2020-03-30 14:53:19 -0700373 if (VersionHasIetfQuicFrames(transport_version())) {
374 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
375 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(true)).Times(1);
376 }
renjietange6d94672020-01-07 10:30:10 -0800377 QuicConfigPeer::SetReceivedMaxBidirectionalStreams(
dschinazi18cdf132019-10-09 16:08:18 -0700378 session_.config(), kDefaultMaxStreamsPerConnection);
renjietange6d94672020-01-07 10:30:10 -0800379 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
dschinazi18cdf132019-10-09 16:08:18 -0700380 session_.config(), kDefaultMaxStreamsPerConnection);
381 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
382 session_.config(), kMinimumFlowControlSendWindow);
383 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
384 session_.config(), kMinimumFlowControlSendWindow);
385 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
386 session_.config(), kMinimumFlowControlSendWindow);
387 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
388 session_.config(), kMinimumFlowControlSendWindow);
389 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
fkastenholz56055be2019-09-17 11:17:37 -0700390 session_.OnConfigNegotiated();
391 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500392 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
393 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
394 .Times(testing::AnyNumber());
renjietangab9039a2020-03-30 14:53:19 -0700395 testing::Mock::VerifyAndClearExpectations(&session_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500396 }
397
fkastenholz56055be2019-09-17 11:17:37 -0700398 ~QuicSessionTestBase() {
399 if (configure_session_) {
400 EXPECT_TRUE(session_.is_configured());
401 }
402 }
403
QUICHE teama6ef0a62019-03-07 20:34:33 -0500404 void CheckClosedStreams() {
QUICHE teamdc41bf12019-03-20 12:58:42 -0700405 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
406 connection_->transport_version(), Perspective::IS_CLIENT);
407 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
408 first_stream_id =
409 QuicUtils::GetCryptoStreamId(connection_->transport_version());
410 }
411 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500412 if (!QuicContainsKey(closed_streams_, i)) {
413 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
414 } else {
415 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
416 }
417 }
418 }
419
420 void CloseStream(QuicStreamId id) {
renjietangd9762282019-11-11 17:11:18 -0800421 if (VersionHasIetfQuicFrames(transport_version())) {
422 if (QuicUtils::GetStreamType(id, session_.perspective(),
423 session_.IsIncomingStream(id)) ==
424 READ_UNIDIRECTIONAL) {
425 // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
426 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
427 EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
428 } else if (QuicUtils::GetStreamType(id, session_.perspective(),
429 session_.IsIncomingStream(id)) ==
430 WRITE_UNIDIRECTIONAL) {
431 // Verify RESET_STREAM but not STOP_SENDING is sent for write-only
432 // stream.
433 EXPECT_CALL(*connection_, SendControlFrame(_))
434 .Times(1)
435 .WillOnce(Invoke(&ClearControlFrame));
436 EXPECT_CALL(*connection_, OnStreamReset(id, _));
437 } else {
438 // Verify RESET_STREAM and STOP_SENDING are sent for BIDIRECTIONAL
439 // streams.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500440 EXPECT_CALL(*connection_, SendControlFrame(_))
441 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -0700442 .WillRepeatedly(Invoke(&ClearControlFrame));
renjietangd9762282019-11-11 17:11:18 -0800443 EXPECT_CALL(*connection_, OnStreamReset(id, _));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500444 }
renjietangd9762282019-11-11 17:11:18 -0800445 } else {
446 EXPECT_CALL(*connection_, SendControlFrame(_))
447 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500448 EXPECT_CALL(*connection_, OnStreamReset(id, _));
449 }
450 session_.CloseStream(id);
451 closed_streams_.insert(id);
452 }
453
454 QuicTransportVersion transport_version() const {
455 return connection_->transport_version();
456 }
457
458 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
459 return QuicUtils::GetFirstBidirectionalStreamId(
460 connection_->transport_version(), Perspective::IS_CLIENT) +
461 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
462 }
463
464 QuicStreamId GetNthClientInitiatedUnidirectionalId(int n) {
465 return QuicUtils::GetFirstUnidirectionalStreamId(
466 connection_->transport_version(), Perspective::IS_CLIENT) +
467 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
468 }
469
470 QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
471 return QuicUtils::GetFirstBidirectionalStreamId(
472 connection_->transport_version(), Perspective::IS_SERVER) +
473 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
474 }
475
476 QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
477 return QuicUtils::GetFirstUnidirectionalStreamId(
478 connection_->transport_version(), Perspective::IS_SERVER) +
479 QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
480 }
481
fkastenholz3c4eabf2019-04-22 07:49:59 -0700482 QuicStreamId StreamCountToId(QuicStreamCount stream_count,
483 Perspective perspective,
484 bool bidirectional) {
485 // Calculate and build up stream ID rather than use
486 // GetFirst... because tests that rely on this method
487 // needs to do the stream count where #1 is 0/1/2/3, and not
488 // take into account that stream 0 is special.
489 QuicStreamId id =
fkastenholz305e1732019-06-18 05:01:22 -0700490 ((stream_count - 1) * QuicUtils::StreamIdDelta(transport_version()));
fkastenholz3c4eabf2019-04-22 07:49:59 -0700491 if (!bidirectional) {
492 id |= 0x2;
493 }
494 if (perspective == Perspective::IS_SERVER) {
495 id |= 0x1;
496 }
497 return id;
498 }
499
QUICHE teama6ef0a62019-03-07 20:34:33 -0500500 MockQuicConnectionHelper helper_;
501 MockAlarmFactory alarm_factory_;
502 NiceMock<MockQuicSessionVisitor> session_visitor_;
503 StrictMock<MockQuicConnection>* connection_;
504 TestSession session_;
505 std::set<QuicStreamId> closed_streams_;
fkastenholz56055be2019-09-17 11:17:37 -0700506 bool configure_session_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500507};
508
509class QuicSessionTestServer : public QuicSessionTestBase {
510 public:
511 // CheckMultiPathResponse validates that a written packet
512 // contains both expected path responses.
513 WriteResult CheckMultiPathResponse(const char* buffer,
514 size_t buf_len,
dschinazi17d42422019-06-18 16:35:07 -0700515 const QuicIpAddress& /*self_address*/,
516 const QuicSocketAddress& /*peer_address*/,
517 PerPacketOptions* /*options*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518 QuicEncryptedPacket packet(buffer, buf_len);
519 {
520 InSequence s;
521 EXPECT_CALL(framer_visitor_, OnPacket());
522 EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
523 EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
524 EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
525 EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
526 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
527 .WillOnce(
528 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
529 EXPECT_EQ(path_frame_buffer1_, frame.data_buffer);
530 return true;
531 })));
532 EXPECT_CALL(framer_visitor_, OnPathResponseFrame(_))
533 .WillOnce(
534 WithArg<0>(Invoke([this](const QuicPathResponseFrame& frame) {
535 EXPECT_EQ(path_frame_buffer2_, frame.data_buffer);
536 return true;
537 })));
538 EXPECT_CALL(framer_visitor_, OnPacketComplete());
539 }
540 client_framer_.ProcessPacket(packet);
541 return WriteResult(WRITE_STATUS_OK, 0);
542 }
543
544 protected:
545 QuicSessionTestServer()
fkastenholz56055be2019-09-17 11:17:37 -0700546 : QuicSessionTestBase(Perspective::IS_SERVER, /*configure_session=*/true),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500547 path_frame_buffer1_({0, 1, 2, 3, 4, 5, 6, 7}),
548 path_frame_buffer2_({8, 9, 10, 11, 12, 13, 14, 15}),
549 client_framer_(SupportedVersions(GetParam()),
550 QuicTime::Zero(),
551 Perspective::IS_CLIENT,
552 kQuicDefaultConnectionIdLength) {
553 client_framer_.set_visitor(&framer_visitor_);
nharperc6b99512019-09-19 11:13:48 -0700554 client_framer_.SetInitialObfuscators(TestConnectionId());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500555 }
556
557 QuicPathFrameBuffer path_frame_buffer1_;
558 QuicPathFrameBuffer path_frame_buffer2_;
559 StrictMock<MockFramerVisitor> framer_visitor_;
560 // Framer used to process packets sent by server.
561 QuicFramer client_framer_;
562};
563
564INSTANTIATE_TEST_SUITE_P(Tests,
565 QuicSessionTestServer,
dschinazi142051a2019-09-18 18:17:29 -0700566 ::testing::ValuesIn(AllSupportedVersions()),
567 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500568
569TEST_P(QuicSessionTestServer, PeerAddress) {
570 EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
571 session_.peer_address());
572}
573
574TEST_P(QuicSessionTestServer, SelfAddress) {
575 EXPECT_TRUE(session_.self_address().IsInitialized());
576}
577
578TEST_P(QuicSessionTestServer, DontCallOnWriteBlockedForDisconnectedConnection) {
579 EXPECT_CALL(*connection_, CloseConnection(_, _, _))
580 .WillOnce(
581 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
582 connection_->CloseConnection(QUIC_NO_ERROR, "Everything is fine.",
583 ConnectionCloseBehavior::SILENT_CLOSE);
584 ASSERT_FALSE(connection_->connected());
585
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700586 EXPECT_CALL(session_visitor_, OnWriteBlocked(_)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500587 session_.OnWriteBlocked();
588}
589
fayanga3d8df72020-01-14 11:54:39 -0800590TEST_P(QuicSessionTestServer, OneRttKeysAvailable) {
591 EXPECT_FALSE(session_.OneRttKeysAvailable());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500592 CryptoHandshakeMessage message;
fayang01062942020-01-22 07:23:23 -0800593 if (connection_->version().HasHandshakeDone()) {
594 EXPECT_CALL(*connection_, SendControlFrame(_));
595 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500596 session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
fayanga3d8df72020-01-14 11:54:39 -0800597 EXPECT_TRUE(session_.OneRttKeysAvailable());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500598}
599
600TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
601 // Ensure that no streams are initially closed.
QUICHE teamdc41bf12019-03-20 12:58:42 -0700602 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
603 connection_->transport_version(), Perspective::IS_CLIENT);
604 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
605 first_stream_id =
606 QuicUtils::GetCryptoStreamId(connection_->transport_version());
607 }
608 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500609 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
610 }
611}
612
613TEST_P(QuicSessionTestServer, AvailableBidirectionalStreams) {
renjietang880d2432019-07-16 13:14:37 -0700614 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500615 GetNthClientInitiatedBidirectionalId(3)) != nullptr);
616 // Smaller bidirectional streams should be available.
617 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
618 &session_, GetNthClientInitiatedBidirectionalId(1)));
619 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
620 &session_, GetNthClientInitiatedBidirectionalId(2)));
renjietang880d2432019-07-16 13:14:37 -0700621 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500622 GetNthClientInitiatedBidirectionalId(2)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -0700623 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500624 GetNthClientInitiatedBidirectionalId(1)) != nullptr);
625}
626
627TEST_P(QuicSessionTestServer, AvailableUnidirectionalStreams) {
renjietang880d2432019-07-16 13:14:37 -0700628 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500629 GetNthClientInitiatedUnidirectionalId(3)) != nullptr);
630 // Smaller unidirectional streams should be available.
631 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
632 &session_, GetNthClientInitiatedUnidirectionalId(1)));
633 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
634 &session_, GetNthClientInitiatedUnidirectionalId(2)));
renjietang880d2432019-07-16 13:14:37 -0700635 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500636 GetNthClientInitiatedUnidirectionalId(2)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -0700637 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500638 GetNthClientInitiatedUnidirectionalId(1)) != nullptr);
639}
640
641TEST_P(QuicSessionTestServer, MaxAvailableBidirectionalStreams) {
fkastenholz305e1732019-06-18 05:01:22 -0700642 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500643 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams(),
644 session_.MaxAvailableBidirectionalStreams());
645 } else {
646 // The protocol specification requires that there can be at least 10 times
647 // as many available streams as the connection's maximum open streams.
648 EXPECT_EQ(session_.max_open_incoming_bidirectional_streams() *
649 kMaxAvailableStreamsMultiplier,
650 session_.MaxAvailableBidirectionalStreams());
651 }
652}
653
654TEST_P(QuicSessionTestServer, MaxAvailableUnidirectionalStreams) {
fkastenholz305e1732019-06-18 05:01:22 -0700655 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500656 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams(),
657 session_.MaxAvailableUnidirectionalStreams());
658 } else {
659 // The protocol specification requires that there can be at least 10 times
660 // as many available streams as the connection's maximum open streams.
661 EXPECT_EQ(session_.max_open_incoming_unidirectional_streams() *
662 kMaxAvailableStreamsMultiplier,
663 session_.MaxAvailableUnidirectionalStreams());
664 }
665}
666
667TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamLocallyCreated) {
668 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
669 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id());
670 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
671 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(1), stream4->id());
672
673 CheckClosedStreams();
674 CloseStream(GetNthServerInitiatedBidirectionalId(0));
675 CheckClosedStreams();
676 CloseStream(GetNthServerInitiatedBidirectionalId(1));
677 CheckClosedStreams();
678}
679
680TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamLocallyCreated) {
681 TestStream* stream2 = session_.CreateOutgoingUnidirectionalStream();
682 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(0), stream2->id());
683 TestStream* stream4 = session_.CreateOutgoingUnidirectionalStream();
684 EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(1), stream4->id());
685
686 CheckClosedStreams();
687 CloseStream(GetNthServerInitiatedUnidirectionalId(0));
688 CheckClosedStreams();
689 CloseStream(GetNthServerInitiatedUnidirectionalId(1));
690 CheckClosedStreams();
691}
692
693TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamPeerCreated) {
694 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
695 QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
renjietang880d2432019-07-16 13:14:37 -0700696 session_.GetOrCreateStream(stream_id1);
697 session_.GetOrCreateStream(stream_id2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500698
699 CheckClosedStreams();
700 CloseStream(stream_id1);
701 CheckClosedStreams();
702 CloseStream(stream_id2);
703 // Create a stream, and make another available.
renjietang880d2432019-07-16 13:14:37 -0700704 QuicStream* stream3 = session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500705 stream_id2 +
706 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
707 CheckClosedStreams();
708 // Close one, but make sure the other is still not closed
709 CloseStream(stream3->id());
710 CheckClosedStreams();
711}
712
713TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamPeerCreated) {
714 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
715 QuicStreamId stream_id2 = GetNthClientInitiatedUnidirectionalId(1);
renjietang880d2432019-07-16 13:14:37 -0700716 session_.GetOrCreateStream(stream_id1);
717 session_.GetOrCreateStream(stream_id2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500718
719 CheckClosedStreams();
720 CloseStream(stream_id1);
721 CheckClosedStreams();
722 CloseStream(stream_id2);
723 // Create a stream, and make another available.
renjietang880d2432019-07-16 13:14:37 -0700724 QuicStream* stream3 = session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500725 stream_id2 +
726 2 * QuicUtils::StreamIdDelta(connection_->transport_version()));
727 CheckClosedStreams();
728 // Close one, but make sure the other is still not closed
729 CloseStream(stream3->id());
730 CheckClosedStreams();
731}
732
733TEST_P(QuicSessionTestServer, MaximumAvailableOpenedBidirectionalStreams) {
734 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700735 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500736 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700737 EXPECT_NE(nullptr,
738 session_.GetOrCreateStream(GetNthClientInitiatedBidirectionalId(
739 session_.max_open_incoming_bidirectional_streams() - 1)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500740}
741
742TEST_P(QuicSessionTestServer, MaximumAvailableOpenedUnidirectionalStreams) {
743 QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700744 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500745 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700746 EXPECT_NE(nullptr,
747 session_.GetOrCreateStream(GetNthClientInitiatedUnidirectionalId(
748 session_.max_open_incoming_unidirectional_streams() - 1)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500749}
750
751TEST_P(QuicSessionTestServer, TooManyAvailableBidirectionalStreams) {
752 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
753 QuicStreamId stream_id2;
renjietang880d2432019-07-16 13:14:37 -0700754 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500755 // A stream ID which is too large to create.
756 stream_id2 = GetNthClientInitiatedBidirectionalId(
757 session_.MaxAvailableBidirectionalStreams() + 2);
fkastenholz305e1732019-06-18 05:01:22 -0700758 if (VersionHasIetfQuicFrames(transport_version())) {
759 // IETF QUIC terminates the connection with invalid stream id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500760 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
761 } else {
762 // other versions terminate the connection with
763 // QUIC_TOO_MANY_AVAILABLE_STREAMS.
764 EXPECT_CALL(*connection_,
765 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
766 }
renjietang880d2432019-07-16 13:14:37 -0700767 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500768}
769
770TEST_P(QuicSessionTestServer, TooManyAvailableUnidirectionalStreams) {
771 QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0);
772 QuicStreamId stream_id2;
renjietang880d2432019-07-16 13:14:37 -0700773 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500774 // A stream ID which is too large to create.
775 stream_id2 = GetNthClientInitiatedUnidirectionalId(
776 session_.MaxAvailableUnidirectionalStreams() + 2);
fkastenholz305e1732019-06-18 05:01:22 -0700777 if (VersionHasIetfQuicFrames(transport_version())) {
778 // IETF QUIC terminates the connection with invalid stream id
QUICHE teama6ef0a62019-03-07 20:34:33 -0500779 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
780 } else {
781 // other versions terminate the connection with
782 // QUIC_TOO_MANY_AVAILABLE_STREAMS.
783 EXPECT_CALL(*connection_,
784 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
785 }
renjietang880d2432019-07-16 13:14:37 -0700786 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500787}
788
789TEST_P(QuicSessionTestServer, ManyAvailableBidirectionalStreams) {
790 // When max_open_streams_ is 200, should be able to create 200 streams
791 // out-of-order, that is, creating the one with the largest stream ID first.
fkastenholz305e1732019-06-18 05:01:22 -0700792 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700793 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
794 // Smaller limit on unidirectional streams to help detect crossed wires.
795 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 50);
796 } else {
797 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
798 }
799 // Create a stream at the start of the range.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500800 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700801 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500802
803 // Create the largest stream ID of a threatened total of 200 streams.
804 // GetNth... starts at 0, so for 200 streams, get the 199th.
fkastenholzd3a1de92019-05-15 07:00:07 -0700805 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700806 EXPECT_NE(nullptr, session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500807 GetNthClientInitiatedBidirectionalId(199)));
fkastenholzd3a1de92019-05-15 07:00:07 -0700808
fkastenholz305e1732019-06-18 05:01:22 -0700809 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700810 // If IETF QUIC, check to make sure that creating bidirectional
811 // streams does not mess up the unidirectional streams.
812 stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700813 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholzd3a1de92019-05-15 07:00:07 -0700814 // Now try to get the last possible unidirectional stream.
renjietang880d2432019-07-16 13:14:37 -0700815 EXPECT_NE(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700816 GetNthClientInitiatedUnidirectionalId(49)));
817 // and this should fail because it exceeds the unidirectional limit
818 // (but not the bi-)
819 EXPECT_CALL(
820 *connection_,
821 CloseConnection(QUIC_INVALID_STREAM_ID,
822 "Stream id 798 would exceed stream count limit 50",
renjietang7133ea92020-04-01 12:49:36 -0700823 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
fkastenholzd3a1de92019-05-15 07:00:07 -0700824 .Times(1);
renjietang880d2432019-07-16 13:14:37 -0700825 EXPECT_EQ(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700826 GetNthClientInitiatedUnidirectionalId(199)));
827 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500828}
829
830TEST_P(QuicSessionTestServer, ManyAvailableUnidirectionalStreams) {
831 // When max_open_streams_ is 200, should be able to create 200 streams
832 // out-of-order, that is, creating the one with the largest stream ID first.
fkastenholz305e1732019-06-18 05:01:22 -0700833 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700834 QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 200);
835 // Smaller limit on unidirectional streams to help detect crossed wires.
836 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 50);
837 } else {
838 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
839 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500840 // Create one stream.
fkastenholzd3a1de92019-05-15 07:00:07 -0700841 QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700842 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500843
844 // Create the largest stream ID of a threatened total of 200 streams.
845 // GetNth... starts at 0, so for 200 streams, get the 199th.
fkastenholzd3a1de92019-05-15 07:00:07 -0700846 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietang880d2432019-07-16 13:14:37 -0700847 EXPECT_NE(nullptr, session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500848 GetNthClientInitiatedUnidirectionalId(199)));
fkastenholz305e1732019-06-18 05:01:22 -0700849 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700850 // If IETF QUIC, check to make sure that creating unidirectional
851 // streams does not mess up the bidirectional streams.
852 stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700853 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholzd3a1de92019-05-15 07:00:07 -0700854 // Now try to get the last possible bidirectional stream.
renjietang880d2432019-07-16 13:14:37 -0700855 EXPECT_NE(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700856 GetNthClientInitiatedBidirectionalId(49)));
857 // and this should fail because it exceeds the bnidirectional limit
858 // (but not the uni-)
nharpercd820e02019-05-16 15:12:07 -0700859 std::string error_detail;
860 if (QuicVersionUsesCryptoFrames(transport_version())) {
861 error_detail = "Stream id 796 would exceed stream count limit 50";
862 } else {
863 error_detail = "Stream id 800 would exceed stream count limit 50";
864 }
fkastenholzd3a1de92019-05-15 07:00:07 -0700865 EXPECT_CALL(
866 *connection_,
nharpercd820e02019-05-16 15:12:07 -0700867 CloseConnection(QUIC_INVALID_STREAM_ID, error_detail,
868 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
fkastenholzd3a1de92019-05-15 07:00:07 -0700869 .Times(1);
renjietang880d2432019-07-16 13:14:37 -0700870 EXPECT_EQ(nullptr, session_.GetOrCreateStream(
fkastenholzd3a1de92019-05-15 07:00:07 -0700871 GetNthClientInitiatedBidirectionalId(199)));
872 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500873}
874
875TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500876 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
877 QuicStreamId closed_stream_id = stream2->id();
878 // Close the stream.
879 EXPECT_CALL(*connection_, SendControlFrame(_));
880 EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
881 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800882 std::string msg = quiche::QuicheStrCat("Marking unknown stream ",
883 closed_stream_id, " blocked.");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500884 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
885 msg);
886}
887
888TEST_P(QuicSessionTestServer, OnCanWrite) {
889 session_.set_writev_consumes_all_data(true);
890 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
891 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
892 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
893
894 session_.MarkConnectionLevelWriteBlocked(stream2->id());
895 session_.MarkConnectionLevelWriteBlocked(stream6->id());
896 session_.MarkConnectionLevelWriteBlocked(stream4->id());
897
898 InSequence s;
899
900 // Reregister, to test the loop limit.
901 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
902 session_.SendStreamData(stream2);
903 session_.MarkConnectionLevelWriteBlocked(stream2->id());
904 }));
905 // 2 will get called a second time as it didn't finish its block
906 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
907 session_.SendStreamData(stream2);
908 }));
909 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
910 session_.SendStreamData(stream6);
911 }));
912 // 4 will not get called, as we exceeded the loop limit.
913 session_.OnCanWrite();
914 EXPECT_TRUE(session_.WillingAndAbleToWrite());
915}
916
917TEST_P(QuicSessionTestServer, TestBatchedWrites) {
918 session_.set_writev_consumes_all_data(true);
919 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
920 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
921 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
922
923 session_.set_writev_consumes_all_data(true);
924 session_.MarkConnectionLevelWriteBlocked(stream2->id());
925 session_.MarkConnectionLevelWriteBlocked(stream4->id());
926
927 // With two sessions blocked, we should get two write calls. They should both
928 // go to the first stream as it will only write 6k and mark itself blocked
929 // again.
930 InSequence s;
931 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
932 session_.SendLargeFakeData(stream2, 6000);
933 session_.MarkConnectionLevelWriteBlocked(stream2->id());
934 }));
935 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
936 session_.SendLargeFakeData(stream2, 6000);
937 session_.MarkConnectionLevelWriteBlocked(stream2->id());
938 }));
939 session_.OnCanWrite();
940
941 // We should get one more call for stream2, at which point it has used its
942 // write quota and we move over to stream 4.
943 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
944 session_.SendLargeFakeData(stream2, 6000);
945 session_.MarkConnectionLevelWriteBlocked(stream2->id());
946 }));
947 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
948 session_.SendLargeFakeData(stream4, 6000);
949 session_.MarkConnectionLevelWriteBlocked(stream4->id());
950 }));
951 session_.OnCanWrite();
952
953 // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
954 // priority stream 6. 4 should be preempted. 6 will write but *not* block so
955 // will cede back to 4.
fayang476683a2019-07-25 12:42:16 -0700956 stream6->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500957 EXPECT_CALL(*stream4, OnCanWrite())
958 .WillOnce(Invoke([this, stream4, stream6]() {
959 session_.SendLargeFakeData(stream4, 6000);
960 session_.MarkConnectionLevelWriteBlocked(stream4->id());
961 session_.MarkConnectionLevelWriteBlocked(stream6->id());
962 }));
963 EXPECT_CALL(*stream6, OnCanWrite())
964 .WillOnce(Invoke([this, stream4, stream6]() {
965 session_.SendStreamData(stream6);
966 session_.SendLargeFakeData(stream4, 6000);
967 }));
968 session_.OnCanWrite();
969
970 // Stream4 alread did 6k worth of writes, so after doing another 12k it should
971 // cede and 2 should resume.
972 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
973 session_.SendLargeFakeData(stream4, 12000);
974 session_.MarkConnectionLevelWriteBlocked(stream4->id());
975 }));
976 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
977 session_.SendLargeFakeData(stream2, 6000);
978 session_.MarkConnectionLevelWriteBlocked(stream2->id());
979 }));
980 session_.OnCanWrite();
981}
982
fayang944cfbc2019-07-31 09:15:00 -0700983TEST_P(QuicSessionTestServer, Http2Priority) {
984 if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
renjietang67e5bcb2019-09-26 16:19:55 -0700985 // The test is using HTTP/2 priority which is not supported in IETF QUIC.
fayang944cfbc2019-07-31 09:15:00 -0700986 return;
987 }
fayang944cfbc2019-07-31 09:15:00 -0700988 QuicTagVector copt;
989 copt.push_back(kH2PR);
990 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
991 session_.OnConfigNegotiated();
992 ASSERT_TRUE(session_.use_http2_priority_write_scheduler());
993
994 session_.set_writev_consumes_all_data(true);
995 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
996 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
997 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
998
999 session_.set_writev_consumes_all_data(true);
1000 /*
1001 0
1002 /|\
1003 2 4 6
1004 */
1005 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1006 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1007 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1008
1009 // Verify streams are scheduled round robin.
1010 InSequence s;
1011 EXPECT_CALL(*stream2, OnCanWrite());
1012 EXPECT_CALL(*stream4, OnCanWrite());
1013 EXPECT_CALL(*stream6, OnCanWrite());
1014 session_.OnCanWrite();
1015
1016 /*
1017 0
1018 |
1019 4
1020 / \
1021 2 6
1022 */
1023 // Update stream 4's priority.
1024 stream4->SetPriority(
1025 spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, true));
1026 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1027 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1028 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1029
1030 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1031 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1032 }));
1033 EXPECT_CALL(*stream4, OnCanWrite());
1034 EXPECT_CALL(*stream2, OnCanWrite());
1035 session_.OnCanWrite();
1036 EXPECT_CALL(*stream6, OnCanWrite());
1037 session_.OnCanWrite();
1038
1039 /*
1040 0
1041 |
1042 6
1043 |
1044 4
1045 |
1046 2
1047 */
1048 // Update stream 6's priority.
1049 stream6->SetPriority(
1050 spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, true));
1051 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1052 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1053 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1054
1055 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1056 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1057 }));
1058 EXPECT_CALL(*stream6, OnCanWrite());
1059 EXPECT_CALL(*stream4, OnCanWrite());
1060 session_.OnCanWrite();
1061 EXPECT_CALL(*stream2, OnCanWrite());
1062 session_.OnCanWrite();
1063}
1064
fayang1b11b962019-09-16 14:01:48 -07001065TEST_P(QuicSessionTestServer, RoundRobinScheduling) {
1066 if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
renjietang67e5bcb2019-09-26 16:19:55 -07001067 // IETF QUIC currently doesn't support PRIORITY.
fayang1b11b962019-09-16 14:01:48 -07001068 return;
1069 }
fayang1b11b962019-09-16 14:01:48 -07001070 QuicTagVector copt;
1071 copt.push_back(kRRWS);
1072 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
1073 session_.OnConfigNegotiated();
1074
1075 session_.set_writev_consumes_all_data(true);
1076 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1077 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1078 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1079
1080 session_.set_writev_consumes_all_data(true);
1081 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1082 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1083 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1084
1085 // Verify streams are scheduled round robin.
1086 InSequence s;
1087 EXPECT_CALL(*stream2, OnCanWrite());
1088 EXPECT_CALL(*stream4, OnCanWrite());
1089 EXPECT_CALL(*stream6, OnCanWrite());
1090 session_.OnCanWrite();
1091
1092 /* 2, 4, 6, 8 */
1093 TestStream* stream8 = session_.CreateOutgoingBidirectionalStream();
1094
1095 // Verify updated priority is ignored.
1096 stream4->SetPriority(spdy::SpdyStreamPrecedence(spdy::kV3HighestPriority));
1097 session_.MarkConnectionLevelWriteBlocked(stream8->id());
1098 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1099 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1100 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1101
1102 EXPECT_CALL(*stream8, OnCanWrite());
1103 EXPECT_CALL(*stream4, OnCanWrite());
1104 EXPECT_CALL(*stream2, OnCanWrite());
1105 EXPECT_CALL(*stream6, OnCanWrite());
1106 session_.OnCanWrite();
1107}
1108
QUICHE teama6ef0a62019-03-07 20:34:33 -05001109TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
1110 // Encryption needs to be established before data can be sent.
fayang01062942020-01-22 07:23:23 -08001111 if (connection_->version().HasHandshakeDone()) {
1112 EXPECT_CALL(*connection_, SendControlFrame(_))
1113 .WillRepeatedly(Invoke(&ClearControlFrame));
1114 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001115 CryptoHandshakeMessage msg;
1116 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1117 QuicConnectionPeer::GetWriter(session_.connection()));
1118 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1119
1120 // Drive congestion control manually.
1121 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1122 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1123
1124 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1125 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1126 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1127
1128 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1129 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1130 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1131
1132 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1133 EXPECT_CALL(*send_algorithm, GetCongestionWindow())
dschinazi66dea072019-04-09 11:41:06 -07001134 .WillRepeatedly(Return(kMaxOutgoingPacketSize * 10));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001135 EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
1136 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1137 session_.SendStreamData(stream2);
1138 }));
1139 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1140 session_.SendStreamData(stream4);
1141 }));
1142 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1143 session_.SendStreamData(stream6);
1144 }));
1145
1146 // Expect that we only send one packet, the writes from different streams
1147 // should be bundled together.
1148 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
1149 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1150 EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
1151 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1152 session_.OnCanWrite();
1153 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1154}
1155
1156TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
1157 session_.set_writev_consumes_all_data(true);
1158 InSequence s;
1159
1160 // Drive congestion control manually.
1161 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1162 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1163
1164 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1165 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1166 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1167
1168 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1169 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1170 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1171
1172 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1173 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1174 session_.SendStreamData(stream2);
1175 }));
1176 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1177 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
1178 session_.SendStreamData(stream6);
1179 }));
1180 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
1181 // stream4->OnCanWrite is not called.
1182
1183 session_.OnCanWrite();
1184 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1185
1186 // Still congestion-control blocked.
1187 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
1188 session_.OnCanWrite();
1189 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1190
1191 // stream4->OnCanWrite is called once the connection stops being
1192 // congestion-control blocked.
1193 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1194 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1195 session_.SendStreamData(stream4);
1196 }));
1197 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1198 session_.OnCanWrite();
1199 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1200}
1201
1202TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
1203 // Drive congestion control manually in order to ensure that
1204 // application-limited signaling is handled correctly.
1205 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1206 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1207 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1208
1209 // Drive packet writer manually.
1210 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1211 QuicConnectionPeer::GetWriter(session_.connection()));
1212 EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
1213 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
1214
1215 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1216
1217 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1218
1219 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
1220 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)).Times(0);
1221
1222 session_.OnCanWrite();
1223 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1224}
1225
fayang769172b2020-03-19 14:27:39 -07001226TEST_P(QuicSessionTestServer, SendStreamsBlocked) {
1227 if (!VersionHasIetfQuicFrames(transport_version())) {
1228 return;
1229 }
1230 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; ++i) {
1231 ASSERT_TRUE(session_.CanOpenNextOutgoingBidirectionalStream());
1232 session_.GetNextOutgoingBidirectionalStreamId();
1233 }
1234 // Next checking causes STREAMS_BLOCKED to be sent.
1235 EXPECT_CALL(*connection_, SendControlFrame(_))
1236 .WillOnce(Invoke([](const QuicFrame& frame) {
1237 EXPECT_FALSE(frame.streams_blocked_frame.unidirectional);
1238 EXPECT_EQ(kDefaultMaxStreamsPerConnection,
1239 frame.streams_blocked_frame.stream_count);
1240 ClearControlFrame(frame);
1241 return true;
1242 }));
1243 EXPECT_FALSE(session_.CanOpenNextOutgoingBidirectionalStream());
1244
1245 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; ++i) {
1246 ASSERT_TRUE(session_.CanOpenNextOutgoingUnidirectionalStream());
1247 session_.GetNextOutgoingUnidirectionalStreamId();
1248 }
1249 // Next checking causes STREAM_BLOCKED to be sent.
1250 EXPECT_CALL(*connection_, SendControlFrame(_))
1251 .WillOnce(Invoke([](const QuicFrame& frame) {
1252 EXPECT_TRUE(frame.streams_blocked_frame.unidirectional);
1253 EXPECT_EQ(kDefaultMaxStreamsPerConnection,
1254 frame.streams_blocked_frame.stream_count);
1255 ClearControlFrame(frame);
1256 return true;
1257 }));
1258 EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
1259}
1260
QUICHE teama6ef0a62019-03-07 20:34:33 -05001261TEST_P(QuicSessionTestServer, BufferedHandshake) {
nharperd5c4a932019-05-13 13:58:49 -07001262 // This test is testing behavior of crypto stream flow control, but when
1263 // CRYPTO frames are used, there is no flow control for the crypto handshake.
1264 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1265 return;
1266 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001267 session_.set_writev_consumes_all_data(true);
1268 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
1269
1270 // Test that blocking other streams does not change our status.
1271 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1272 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1273 EXPECT_FALSE(session_.HasPendingHandshake());
1274
1275 TestStream* stream3 = session_.CreateOutgoingBidirectionalStream();
1276 session_.MarkConnectionLevelWriteBlocked(stream3->id());
1277 EXPECT_FALSE(session_.HasPendingHandshake());
1278
1279 // Blocking (due to buffering of) the Crypto stream is detected.
1280 session_.MarkConnectionLevelWriteBlocked(
1281 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1282 EXPECT_TRUE(session_.HasPendingHandshake());
1283
1284 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1285 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1286 EXPECT_TRUE(session_.HasPendingHandshake());
1287
1288 InSequence s;
1289 // Force most streams to re-register, which is common scenario when we block
1290 // the Crypto stream, and only the crypto stream can "really" write.
1291
1292 // Due to prioritization, we *should* be asked to write the crypto stream
1293 // first.
1294 // Don't re-register the crypto stream (which signals complete writing).
1295 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1296 EXPECT_CALL(*crypto_stream, OnCanWrite());
1297
1298 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1299 session_.SendStreamData(stream2);
1300 }));
1301 EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(Invoke([this, stream3]() {
1302 session_.SendStreamData(stream3);
1303 }));
1304 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1305 session_.SendStreamData(stream4);
1306 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1307 }));
1308
1309 session_.OnCanWrite();
1310 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1311 EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
1312}
1313
1314TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
1315 session_.set_writev_consumes_all_data(true);
1316 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1317 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1318 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1319
1320 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1321 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1322 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1323 CloseStream(stream6->id());
1324
1325 InSequence s;
1326 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001327 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001328 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1329 session_.SendStreamData(stream2);
1330 }));
1331 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1332 session_.SendStreamData(stream4);
1333 }));
1334 session_.OnCanWrite();
1335 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1336}
1337
1338TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
1339 // Drive congestion control manually in order to ensure that
1340 // application-limited signaling is handled correctly.
1341 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1342 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1343 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1344
1345 // Ensure connection level flow control blockage.
1346 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
1347 EXPECT_TRUE(session_.flow_controller()->IsBlocked());
1348 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1349 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1350
1351 // Mark the crypto and headers streams as write blocked, we expect them to be
1352 // allowed to write later.
nharperd5c4a932019-05-13 13:58:49 -07001353 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1354 session_.MarkConnectionLevelWriteBlocked(
1355 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
1356 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001357
1358 // Create a data stream, and although it is write blocked we never expect it
1359 // to be allowed to write as we are connection level flow control blocked.
1360 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1361 session_.MarkConnectionLevelWriteBlocked(stream->id());
1362 EXPECT_CALL(*stream, OnCanWrite()).Times(0);
1363
1364 // The crypto and headers streams should be called even though we are
1365 // connection flow control blocked.
nharperd5c4a932019-05-13 13:58:49 -07001366 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
1367 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1368 EXPECT_CALL(*crypto_stream, OnCanWrite());
1369 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001370
1371 // After the crypto and header streams perform a write, the connection will be
1372 // blocked by the flow control, hence it should become application-limited.
1373 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1374
1375 session_.OnCanWrite();
1376 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1377}
1378
1379TEST_P(QuicSessionTestServer, SendGoAway) {
fkastenholz305e1732019-06-18 05:01:22 -07001380 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001381 // In IETF QUIC, GOAWAY lives up in the HTTP layer.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001382 return;
1383 }
fayang93cc53a2019-08-22 12:47:30 -07001384 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001385 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1386 QuicConnectionPeer::GetWriter(session_.connection()));
1387 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
1388 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1389
1390 EXPECT_CALL(*connection_, SendControlFrame(_))
1391 .WillOnce(
1392 Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
1393 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1394 EXPECT_TRUE(session_.goaway_sent());
1395
1396 const QuicStreamId kTestStreamId = 5u;
1397 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1398 EXPECT_CALL(*connection_,
1399 OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
1400 .Times(0);
renjietang880d2432019-07-16 13:14:37 -07001401 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001402}
1403
1404TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
fkastenholz305e1732019-06-18 05:01:22 -07001405 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001406 // In IETF QUIC, GOAWAY lives up in the HTTP layer.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001407 return;
1408 }
1409 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001410 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001411 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1412 EXPECT_TRUE(session_.goaway_sent());
1413 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1414}
1415
1416TEST_P(QuicSessionTestServer, InvalidGoAway) {
fkastenholz305e1732019-06-18 05:01:22 -07001417 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001418 // In IETF QUIC, GOAWAY lives up in the HTTP layer.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001419 return;
1420 }
1421 QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
1422 session_.next_outgoing_bidirectional_stream_id(), "");
1423 session_.OnGoAway(go_away);
1424}
1425
1426// Test that server session will send a connectivity probe in response to a
1427// connectivity probe on the same path.
1428TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbe) {
1429 QuicSocketAddress old_peer_address =
1430 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1431 EXPECT_EQ(old_peer_address, session_.peer_address());
1432
1433 QuicSocketAddress new_peer_address =
1434 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort + 1);
1435
1436 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1437 QuicConnectionPeer::GetWriter(session_.connection()));
1438 EXPECT_CALL(*writer, WritePacket(_, _, _, new_peer_address, _))
1439 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1440 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1441 .WillOnce(Invoke(
1442 connection_,
1443 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
fkastenholz305e1732019-06-18 05:01:22 -07001444 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001445 // Need to explicitly do this to emulate the reception of a PathChallenge,
1446 // which stores its payload for use in generating the response.
1447 connection_->OnPathChallengeFrame(
1448 QuicPathChallengeFrame(0, path_frame_buffer1_));
1449 }
zhongyi83161e42019-08-19 09:06:25 -07001450 session_.OnPacketReceived(session_.self_address(), new_peer_address,
1451 /*is_connectivity_probe=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001452 EXPECT_EQ(old_peer_address, session_.peer_address());
1453}
1454
1455// Same as above, but check that if there are two PATH_CHALLENGE frames in the
1456// packet, the response has both of them AND we do not do migration. This for
fkastenholz305e1732019-06-18 05:01:22 -07001457// IETF QUIC only.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001458TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbes) {
fkastenholz305e1732019-06-18 05:01:22 -07001459 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001460 return;
1461 }
1462 QuicSocketAddress old_peer_address =
1463 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1464 EXPECT_EQ(old_peer_address, session_.peer_address());
1465
1466 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1467 QuicConnectionPeer::GetWriter(session_.connection()));
1468 // CheckMultiPathResponse validates that the written packet
1469 // contains both path responses.
1470 EXPECT_CALL(*writer, WritePacket(_, _, _, old_peer_address, _))
1471 .WillOnce(Invoke(this, &QuicSessionTestServer::CheckMultiPathResponse));
1472
1473 EXPECT_CALL(*connection_, SendConnectivityProbingResponsePacket(_))
1474 .WillOnce(Invoke(
1475 connection_,
1476 &MockQuicConnection::ReallySendConnectivityProbingResponsePacket));
QUICHE team8c1daa22019-03-13 08:33:41 -07001477 QuicConnectionPeer::SetLastHeaderFormat(connection_,
1478 IETF_QUIC_SHORT_HEADER_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001479 // Need to explicitly do this to emulate the reception of a PathChallenge,
1480 // which stores its payload for use in generating the response.
1481 connection_->OnPathChallengeFrame(
1482 QuicPathChallengeFrame(0, path_frame_buffer1_));
1483 connection_->OnPathChallengeFrame(
1484 QuicPathChallengeFrame(0, path_frame_buffer2_));
zhongyi83161e42019-08-19 09:06:25 -07001485 session_.OnPacketReceived(session_.self_address(), old_peer_address,
1486 /*is_connectivity_probe=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001487}
1488
1489TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
1490 EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
1491 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
fayang01062942020-01-22 07:23:23 -08001492 if (connection_->version().HasHandshakeDone()) {
1493 EXPECT_CALL(*connection_, SendControlFrame(_));
1494 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001495 CryptoHandshakeMessage msg;
1496 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1497 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
1498 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1499}
1500
1501TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
renjietanga29a96a2019-10-10 12:47:50 -07001502 if (VersionUsesHttp3(connection_->transport_version())) {
renjietang67e5bcb2019-09-26 16:19:55 -07001503 // The test relies on headers stream, which no longer exists in IETF QUIC.
dschinazi552accc2019-06-17 17:07:34 -07001504 return;
1505 }
nharper46833c32019-05-15 21:33:05 -07001506 QuicStreamId headers_stream_id =
1507 QuicUtils::GetHeadersStreamId(connection_->transport_version());
vasilvv0fc587f2019-09-06 13:33:08 -07001508 std::unique_ptr<TestStream> fake_headers_stream =
1509 std::make_unique<TestStream>(headers_stream_id, &session_,
1510 /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07001511 QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001512 // Send two bytes of payload.
dmcardlecf0bfcf2019-12-13 08:08:21 -08001513 QuicStreamFrame data1(headers_stream_id, true, 0,
1514 quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001515 EXPECT_CALL(*connection_,
1516 CloseConnection(
1517 QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
1518 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1519 session_.OnStreamFrame(data1);
1520}
1521
QUICHE teama6ef0a62019-03-07 20:34:33 -05001522TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
1523 // Send two bytes of payload.
1524 QuicStreamFrame data1(
1525 QuicUtils::GetInvalidStreamId(connection_->transport_version()), true, 0,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001526 quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001527 EXPECT_CALL(*connection_,
1528 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001529 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001530 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1531 session_.OnStreamFrame(data1);
1532}
1533
1534TEST_P(QuicSessionTestServer, OnRstStreamInvalidStreamId) {
1535 // Send two bytes of payload.
1536 QuicRstStreamFrame rst1(
1537 kInvalidControlFrameId,
1538 QuicUtils::GetInvalidStreamId(connection_->transport_version()),
1539 QUIC_ERROR_PROCESSING_STREAM, 0);
1540 EXPECT_CALL(*connection_,
1541 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001542 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001543 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1544 session_.OnRstStream(rst1);
1545}
1546
1547TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
dschinaziaab68182019-10-09 15:39:51 -07001548 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
1549 // This test requires Google QUIC crypto because it assumes streams start
1550 // off unblocked.
1551 return;
1552 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001553 // Test that if a stream is flow control blocked, then on receipt of the SHLO
1554 // containing a suitable send window offset, the stream becomes unblocked.
1555
1556 // Ensure that Writev consumes all the data it is given (simulate no socket
1557 // blocking).
1558 session_.set_writev_consumes_all_data(true);
1559
1560 // Create a stream, and send enough data to make it flow control blocked.
1561 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07001562 std::string body(kMinimumFlowControlSendWindow, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001563 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1564 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1565 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1566 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
1567 stream2->WriteOrBufferData(body, false, nullptr);
1568 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
1569 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1570 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1571
1572 // Now complete the crypto handshake, resulting in an increased flow control
1573 // send window.
1574 CryptoHandshakeMessage msg;
1575 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1576 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
1577 // Stream is now unblocked.
1578 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1579 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1580 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1581}
1582
1583TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
QUICHE teamea740082019-03-11 17:58:43 -07001584 if (QuicVersionUsesCryptoFrames(GetParam().transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001585 // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
1586 // test doesn't make sense for those versions since CRYPTO frames aren't
1587 // flow controlled.
1588 return;
1589 }
1590 // Test that if the crypto stream is flow control blocked, then if the SHLO
1591 // contains a larger send window offset, the stream becomes unblocked.
1592 session_.set_writev_consumes_all_data(true);
1593 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1594 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1595 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1596 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1597 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1598 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1599 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001600 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001601 for (QuicStreamId i = 0;
1602 !crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
1603 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1604 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1605 QuicStreamOffset offset = crypto_stream->stream_bytes_written();
1606 QuicConfig config;
1607 CryptoHandshakeMessage crypto_message;
fkastenholzd3a1de92019-05-15 07:00:07 -07001608 config.ToHandshakeMessage(&crypto_message, transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001609 crypto_stream->SendHandshakeMessage(crypto_message);
1610 char buf[1000];
QUICHE team173c48f2019-11-19 16:34:44 -08001611 QuicDataWriter writer(1000, buf, quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001612 crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
1613 }
1614 EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
1615 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1616 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1617 EXPECT_FALSE(session_.HasDataToWrite());
1618 EXPECT_TRUE(crypto_stream->HasBufferedData());
1619
1620 // Now complete the crypto handshake, resulting in an increased flow control
1621 // send window.
1622 CryptoHandshakeMessage msg;
1623 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1624 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
1625 &session_,
1626 QuicUtils::GetCryptoStreamId(connection_->transport_version())));
1627 // Stream is now unblocked and will no longer have buffered data.
1628 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1629 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1630 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1631}
1632
1633TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
1634 // Test that when we receive an out of order stream RST we correctly adjust
1635 // our connection level flow control receive window.
1636 // On close, the stream should mark as consumed all bytes between the highest
1637 // byte consumed so far and the final byte offset from the RST frame.
1638 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1639
1640 const QuicStreamOffset kByteOffset =
1641 1 + kInitialSessionFlowControlWindowForTest / 2;
1642
1643 EXPECT_CALL(*connection_, SendControlFrame(_))
1644 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07001645 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001646 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1647
1648 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1649 QUIC_STREAM_CANCELLED, kByteOffset);
1650 session_.OnRstStream(rst_frame);
fkastenholz305e1732019-06-18 05:01:22 -07001651 if (VersionHasIetfQuicFrames(transport_version())) {
ianswett0a8ff622020-02-05 23:28:58 -08001652 // The test requires the stream to be fully closed in both directions. For
1653 // IETF QUIC, the RST_STREAM only closes one side.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001654 QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
1655 QUIC_STREAM_CANCELLED);
renjietangeab918f2019-10-28 12:10:32 -07001656 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1657 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001658 }
1659 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
1660}
1661
1662TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
1663 // Test the situation where we receive a FIN on a stream, and before we fully
1664 // consume all the data from the sequencer buffer we locally RST the stream.
1665 // The bytes between highest consumed byte, and the final byte offset that we
1666 // determined when the FIN arrived, should be marked as consumed at the
1667 // connection level flow controller when the stream is reset.
1668 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1669
1670 const QuicStreamOffset kByteOffset =
1671 kInitialSessionFlowControlWindowForTest / 2 - 1;
1672 QuicStreamFrame frame(stream->id(), true, kByteOffset, ".");
1673 session_.OnStreamFrame(frame);
1674 EXPECT_TRUE(connection_->connected());
1675
1676 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
1677 EXPECT_EQ(kByteOffset + frame.data_length,
1678 stream->flow_controller()->highest_received_byte_offset());
1679
1680 // Reset stream locally.
1681 EXPECT_CALL(*connection_, SendControlFrame(_));
1682 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1683 stream->Reset(QUIC_STREAM_CANCELLED);
1684 EXPECT_EQ(kByteOffset + frame.data_length,
1685 session_.flow_controller()->bytes_consumed());
1686}
1687
1688TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
1689 // Test that when we RST the stream (and tear down stream state), and then
1690 // receive a FIN from the peer, we correctly adjust our connection level flow
1691 // control receive window.
1692
1693 // Connection starts with some non-zero highest received byte offset,
1694 // due to other active streams.
1695 const uint64_t kInitialConnectionBytesConsumed = 567;
1696 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1697 EXPECT_LT(kInitialConnectionBytesConsumed,
1698 kInitialConnectionHighestReceivedOffset);
1699 session_.flow_controller()->UpdateHighestReceivedOffset(
1700 kInitialConnectionHighestReceivedOffset);
1701 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1702
1703 // Reset our stream: this results in the stream being closed locally.
1704 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1705 EXPECT_CALL(*connection_, SendControlFrame(_));
1706 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1707 stream->Reset(QUIC_STREAM_CANCELLED);
1708
1709 // Now receive a response from the peer with a FIN. We should handle this by
1710 // adjusting the connection level flow control receive window to take into
1711 // account the total number of bytes sent by the peer.
1712 const QuicStreamOffset kByteOffset = 5678;
vasilvvc48c8712019-03-11 13:38:16 -07001713 std::string body = "hello";
dmcardlecf0bfcf2019-12-13 08:08:21 -08001714 QuicStreamFrame frame(stream->id(), true, kByteOffset,
1715 quiche::QuicheStringPiece(body));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001716 session_.OnStreamFrame(frame);
1717
1718 QuicStreamOffset total_stream_bytes_sent_by_peer =
1719 kByteOffset + body.length();
1720 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer,
1721 session_.flow_controller()->bytes_consumed());
1722 EXPECT_EQ(
1723 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer,
1724 session_.flow_controller()->highest_received_byte_offset());
1725}
1726
1727TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
1728 // Test that when we RST the stream (and tear down stream state), and then
1729 // receive a RST from the peer, we correctly adjust our connection level flow
1730 // control receive window.
1731
1732 // Connection starts with some non-zero highest received byte offset,
1733 // due to other active streams.
1734 const uint64_t kInitialConnectionBytesConsumed = 567;
1735 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1736 EXPECT_LT(kInitialConnectionBytesConsumed,
1737 kInitialConnectionHighestReceivedOffset);
1738 session_.flow_controller()->UpdateHighestReceivedOffset(
1739 kInitialConnectionHighestReceivedOffset);
1740 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1741
1742 // Reset our stream: this results in the stream being closed locally.
1743 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1744 EXPECT_CALL(*connection_, SendControlFrame(_));
1745 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1746 stream->Reset(QUIC_STREAM_CANCELLED);
1747 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1748
1749 // Now receive a RST from the peer. We should handle this by adjusting the
1750 // connection level flow control receive window to take into account the total
1751 // number of bytes sent by the peer.
1752 const QuicStreamOffset kByteOffset = 5678;
1753 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1754 QUIC_STREAM_CANCELLED, kByteOffset);
1755 session_.OnRstStream(rst_frame);
1756
1757 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset,
1758 session_.flow_controller()->bytes_consumed());
1759 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset,
1760 session_.flow_controller()->highest_received_byte_offset());
1761}
1762
1763TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
1764 // Test that receipt of an invalid (< default) stream flow control window from
1765 // the peer results in the connection being torn down.
1766 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1767 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
1768 kInvalidWindow);
1769
dschinazi18cdf132019-10-09 16:08:18 -07001770 if (connection_->version().handshake_protocol != PROTOCOL_TLS1_3) {
dschinazic7036122019-04-30 12:46:34 -07001771 EXPECT_CALL(*connection_,
1772 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1773 } else {
1774 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1775 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001776 session_.OnConfigNegotiated();
1777}
1778
1779TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
1780 // Test that receipt of an invalid (< default) session flow control window
1781 // from the peer results in the connection being torn down.
1782 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1783 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
1784 kInvalidWindow);
dschinazic7036122019-04-30 12:46:34 -07001785 if (!connection_->version().AllowsLowFlowControlLimits()) {
1786 EXPECT_CALL(*connection_,
1787 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1788 } else {
1789 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
1790 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001791 session_.OnConfigNegotiated();
1792}
1793
1794// Test negotiation of custom server initial flow control window.
1795TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
1796 QuicTagVector copt;
1797 copt.push_back(kIFW7);
1798 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
1799
1800 session_.OnConfigNegotiated();
1801 EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
1802 session_.flow_controller()));
1803}
1804
1805TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
1806 // Test that if we receive a stream RST with a highest byte offset that
1807 // violates flow control, that we close the connection.
1808 const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
1809 EXPECT_CALL(*connection_,
1810 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
1811 .Times(2);
1812
1813 // Check that stream frame + FIN results in connection close.
1814 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1815 EXPECT_CALL(*connection_, SendControlFrame(_));
1816 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1817 stream->Reset(QUIC_STREAM_CANCELLED);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001818 QuicStreamFrame frame(stream->id(), true, kLargeOffset,
1819 quiche::QuicheStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001820 session_.OnStreamFrame(frame);
1821
1822 // Check that RST results in connection close.
1823 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1824 QUIC_STREAM_CANCELLED, kLargeOffset);
1825 session_.OnRstStream(rst_frame);
1826}
1827
1828TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
1829 // If a buggy/malicious peer creates too many streams that are not ended
fkastenholz305e1732019-06-18 05:01:22 -07001830 // with a FIN or RST then we send an RST to refuse streams. For IETF QUIC the
QUICHE teama6ef0a62019-03-07 20:34:33 -05001831 // connection is closed.
1832 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07001833 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001834 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1835 kMaxStreams);
1836 } else {
1837 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1838 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001839 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1840 const QuicStreamId kFinalStreamId =
1841 GetNthClientInitiatedBidirectionalId(kMaxStreams);
1842 // Create kMaxStreams data streams, and close them all without receiving a
1843 // FIN or a RST_STREAM from the client.
1844 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
1845 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
dmcardlecf0bfcf2019-12-13 08:08:21 -08001846 QuicStreamFrame data1(i, false, 0, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001847 session_.OnStreamFrame(data1);
1848 // EXPECT_EQ(1u, session_.GetNumOpenStreams());
fkastenholz305e1732019-06-18 05:01:22 -07001849 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001850 // Expect two control frames, RST STREAM and STOP SENDING
1851 EXPECT_CALL(*connection_, SendControlFrame(_))
1852 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07001853 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001854 } else {
1855 // Expect one control frame, just RST STREAM
1856 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001857 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001858 }
1859 // Close stream. Should not make new streams available since
1860 // the stream is not finished.
1861 EXPECT_CALL(*connection_, OnStreamReset(i, _));
1862 session_.CloseStream(i);
1863 }
1864
fkastenholz305e1732019-06-18 05:01:22 -07001865 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholz3c4eabf2019-04-22 07:49:59 -07001866 EXPECT_CALL(
1867 *connection_,
1868 CloseConnection(QUIC_INVALID_STREAM_ID,
nharpercd820e02019-05-16 15:12:07 -07001869 "Stream id 20 would exceed stream count limit 5", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001870 } else {
1871 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1872 EXPECT_CALL(*connection_,
1873 OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
1874 .Times(1);
1875 }
1876 // Create one more data streams to exceed limit of open stream.
dmcardlecf0bfcf2019-12-13 08:08:21 -08001877 QuicStreamFrame data1(kFinalStreamId, false, 0,
1878 quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001879 session_.OnStreamFrame(data1);
1880}
1881
1882TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpenedOutgoing) {
1883 // Verify that a draining stream (which has received a FIN but not consumed
1884 // it) does not count against the open quota (because it is closed from the
1885 // protocol point of view).
1886 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1887 QuicStreamId stream_id = stream->id();
dmcardlecf0bfcf2019-12-13 08:08:21 -08001888 QuicStreamFrame data1(stream_id, true, 0, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001889 session_.OnStreamFrame(data1);
fkastenholz8556dc22019-07-18 12:42:38 -07001890 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
fayangbe6d6642020-04-16 14:15:34 -07001891 session_.StreamDraining(stream_id, /*unidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001892}
1893
1894TEST_P(QuicSessionTestServer, NoPendingStreams) {
renjietange76b2da2019-05-13 14:50:23 -07001895 session_.set_uses_pending_streams(false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001896
1897 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1898 transport_version(), Perspective::IS_CLIENT);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001899 QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001900 session_.OnStreamFrame(data1);
1901 EXPECT_EQ(1, session_.num_incoming_streams_created());
1902
dmcardlecf0bfcf2019-12-13 08:08:21 -08001903 QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001904 session_.OnStreamFrame(data2);
1905 EXPECT_EQ(1, session_.num_incoming_streams_created());
1906}
1907
1908TEST_P(QuicSessionTestServer, PendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07001909 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001910 return;
1911 }
renjietange76b2da2019-05-13 14:50:23 -07001912 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001913
1914 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1915 transport_version(), Perspective::IS_CLIENT);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001916 QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001917 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001918 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001919 EXPECT_EQ(0, session_.num_incoming_streams_created());
1920
dmcardlecf0bfcf2019-12-13 08:08:21 -08001921 QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001922 session_.OnStreamFrame(data2);
bnc092d8212019-08-07 11:53:20 -07001923 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001924 EXPECT_EQ(1, session_.num_incoming_streams_created());
1925}
1926
1927TEST_P(QuicSessionTestServer, RstPendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07001928 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001929 return;
1930 }
renjietange76b2da2019-05-13 14:50:23 -07001931 session_.set_uses_pending_streams(true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001932
1933 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1934 transport_version(), Perspective::IS_CLIENT);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001935 QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001936 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001937 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001938 EXPECT_EQ(0, session_.num_incoming_streams_created());
fayang01591ae2020-04-23 14:14:56 -07001939 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001940
QUICHE teama6ef0a62019-03-07 20:34:33 -05001941 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream_id,
1942 QUIC_ERROR_PROCESSING_STREAM, 12);
1943 session_.OnRstStream(rst1);
bnc092d8212019-08-07 11:53:20 -07001944 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001945 EXPECT_EQ(0, session_.num_incoming_streams_created());
fayang01591ae2020-04-23 14:14:56 -07001946 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001947
dmcardlecf0bfcf2019-12-13 08:08:21 -08001948 QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001949 session_.OnStreamFrame(data2);
bnc092d8212019-08-07 11:53:20 -07001950 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
1951 EXPECT_EQ(0, session_.num_incoming_streams_created());
fayang01591ae2020-04-23 14:14:56 -07001952 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
bnc092d8212019-08-07 11:53:20 -07001953}
1954
1955TEST_P(QuicSessionTestServer, OnFinPendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07001956 if (!VersionUsesHttp3(transport_version())) {
bnc092d8212019-08-07 11:53:20 -07001957 return;
1958 }
1959 session_.set_uses_pending_streams(true);
1960
1961 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1962 transport_version(), Perspective::IS_CLIENT);
1963 QuicStreamFrame data(stream_id, true, 0, "");
1964 session_.OnStreamFrame(data);
1965
1966 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001967 EXPECT_EQ(0, session_.num_incoming_streams_created());
fayang01591ae2020-04-23 14:14:56 -07001968 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001969}
1970
renjietang28c04b72019-07-01 15:08:09 -07001971TEST_P(QuicSessionTestServer, PendingStreamOnWindowUpdate) {
renjietanga29a96a2019-10-10 12:47:50 -07001972 if (!VersionUsesHttp3(transport_version())) {
renjietang28c04b72019-07-01 15:08:09 -07001973 return;
1974 }
1975
1976 session_.set_uses_pending_streams(true);
1977 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1978 transport_version(), Perspective::IS_CLIENT);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001979 QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
renjietang28c04b72019-07-01 15:08:09 -07001980 session_.OnStreamFrame(data1);
bnc092d8212019-08-07 11:53:20 -07001981 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
renjietang28c04b72019-07-01 15:08:09 -07001982 EXPECT_EQ(0, session_.num_incoming_streams_created());
1983 QuicWindowUpdateFrame window_update_frame(kInvalidControlFrameId, stream_id,
1984 0);
1985 EXPECT_CALL(
1986 *connection_,
1987 CloseConnection(
1988 QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
1989 "WindowUpdateFrame received on READ_UNIDIRECTIONAL stream.", _));
1990 session_.OnWindowUpdateFrame(window_update_frame);
1991}
1992
QUICHE teama6ef0a62019-03-07 20:34:33 -05001993TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
1994 // Verify that a draining stream (which has received a FIN but not consumed
1995 // it) does not count against the open quota (because it is closed from the
1996 // protocol point of view).
fkastenholz305e1732019-06-18 05:01:22 -07001997 if (VersionHasIetfQuicFrames(transport_version())) {
1998 // On IETF QUIC, we will expect to see a MAX_STREAMS go out when there are
1999 // not enough streams to create the next one.
QUICHE teama6ef0a62019-03-07 20:34:33 -05002000 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
2001 } else {
2002 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
2003 }
2004 EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
2005 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07002006 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07002007 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
2008 kMaxStreams);
2009 } else {
2010 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
2011 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002012
2013 // Create kMaxStreams + 1 data streams, and mark them draining.
2014 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
2015 const QuicStreamId kFinalStreamId =
2016 GetNthClientInitiatedBidirectionalId(2 * kMaxStreams + 1);
2017 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
2018 i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
dmcardlecf0bfcf2019-12-13 08:08:21 -08002019 QuicStreamFrame data1(i, true, 0, quiche::QuicheStringPiece("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002020 session_.OnStreamFrame(data1);
fayang01591ae2020-04-23 14:14:56 -07002021 EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
fayangbe6d6642020-04-16 14:15:34 -07002022 session_.StreamDraining(i, /*unidirectional=*/false);
fayang01591ae2020-04-23 14:14:56 -07002023 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002024 }
2025}
2026
2027class QuicSessionTestClient : public QuicSessionTestBase {
2028 protected:
fkastenholz56055be2019-09-17 11:17:37 -07002029 QuicSessionTestClient()
2030 : QuicSessionTestBase(Perspective::IS_CLIENT,
2031 /*configure_session=*/true) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05002032};
2033
2034INSTANTIATE_TEST_SUITE_P(Tests,
2035 QuicSessionTestClient,
dschinazi142051a2019-09-18 18:17:29 -07002036 ::testing::ValuesIn(AllSupportedVersions()),
2037 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002038
2039TEST_P(QuicSessionTestClient, AvailableBidirectionalStreamsClient) {
renjietang880d2432019-07-16 13:14:37 -07002040 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002041 GetNthServerInitiatedBidirectionalId(2)) != nullptr);
2042 // Smaller bidirectional streams should be available.
2043 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
2044 &session_, GetNthServerInitiatedBidirectionalId(0)));
2045 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
2046 &session_, GetNthServerInitiatedBidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -07002047 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002048 GetNthServerInitiatedBidirectionalId(0)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -07002049 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002050 GetNthServerInitiatedBidirectionalId(1)) != nullptr);
2051 // And 5 should be not available.
2052 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
2053 &session_, GetNthClientInitiatedBidirectionalId(1)));
2054}
2055
renjietangab9039a2020-03-30 14:53:19 -07002056TEST_P(QuicSessionTestClient, OnMaxStreamFrame) {
2057 if (!VersionUsesHttp3(transport_version())) {
2058 return;
2059 }
2060 QuicMaxStreamsFrame frame;
2061 frame.unidirectional = false;
2062 frame.stream_count = 120;
2063 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
2064 session_.OnMaxStreamsFrame(frame);
2065
2066 QuicMaxStreamsFrame frame2;
2067 frame2.unidirectional = false;
2068 frame2.stream_count = 110;
2069 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(0);
2070 session_.OnMaxStreamsFrame(frame2);
2071}
2072
QUICHE teama6ef0a62019-03-07 20:34:33 -05002073TEST_P(QuicSessionTestClient, AvailableUnidirectionalStreamsClient) {
renjietang880d2432019-07-16 13:14:37 -07002074 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002075 GetNthServerInitiatedUnidirectionalId(2)) != nullptr);
2076 // Smaller unidirectional streams should be available.
2077 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
2078 &session_, GetNthServerInitiatedUnidirectionalId(0)));
2079 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
2080 &session_, GetNthServerInitiatedUnidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -07002081 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002082 GetNthServerInitiatedUnidirectionalId(0)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -07002083 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002084 GetNthServerInitiatedUnidirectionalId(1)) != nullptr);
2085 // And 5 should be not available.
2086 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
2087 &session_, GetNthClientInitiatedUnidirectionalId(1)));
2088}
2089
2090TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
2091 // Verify that an incoming FIN is recorded in a stream object even if the read
2092 // side has been closed. This prevents an entry from being made in
2093 // locally_closed_streams_highest_offset_ (which will never be deleted).
2094 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2095 QuicStreamId stream_id = stream->id();
2096
2097 // Close the read side manually.
2098 QuicStreamPeer::CloseReadSide(stream);
2099
2100 // Receive a stream data frame with FIN.
dmcardlecf0bfcf2019-12-13 08:08:21 -08002101 QuicStreamFrame frame(stream_id, true, 0, quiche::QuicheStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002102 session_.OnStreamFrame(frame);
2103 EXPECT_TRUE(stream->fin_received());
2104
2105 // Reset stream locally.
2106 EXPECT_CALL(*connection_, SendControlFrame(_));
2107 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
2108 stream->Reset(QUIC_STREAM_CANCELLED);
2109 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
2110
2111 EXPECT_TRUE(connection_->connected());
2112 EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
2113 EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
2114
2115 // The stream is not waiting for the arrival of the peer's final offset as it
2116 // was received with the FIN earlier.
2117 EXPECT_EQ(
2118 0u,
2119 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
2120}
2121
bncec3602c2020-03-12 17:57:59 -07002122TEST_P(QuicSessionTestClient, IncomingStreamWithClientInitiatedStreamId) {
2123 const QuicErrorCode expected_error =
2124 VersionHasIetfQuicFrames(transport_version())
2125 ? QUIC_HTTP_STREAM_WRONG_DIRECTION
2126 : QUIC_INVALID_STREAM_ID;
2127 EXPECT_CALL(
2128 *connection_,
2129 CloseConnection(expected_error, "Data for nonexistent stream",
2130 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
2131
2132 QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(1),
2133 /* fin = */ false, /* offset = */ 0,
2134 quiche::QuicheStringPiece("foo"));
2135 session_.OnStreamFrame(frame);
2136}
2137
QUICHE teama6ef0a62019-03-07 20:34:33 -05002138TEST_P(QuicSessionTestServer, ZombieStreams) {
2139 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2140 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
2141 EXPECT_TRUE(stream2->IsWaitingForAcks());
2142
2143 EXPECT_CALL(*connection_, SendControlFrame(_));
2144 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2145 session_.CloseStream(stream2->id());
2146 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2147 ASSERT_EQ(1u, session_.closed_streams()->size());
2148 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2149 session_.OnStreamDoneWaitingForAcks(stream2->id());
2150 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2151 EXPECT_EQ(1u, session_.closed_streams()->size());
2152 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2153}
2154
2155TEST_P(QuicSessionTestServer, RstStreamReceivedAfterRstStreamSent) {
2156 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2157 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
2158 EXPECT_TRUE(stream2->IsWaitingForAcks());
2159
2160 EXPECT_CALL(*connection_, SendControlFrame(_));
2161 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
fkastenholz8556dc22019-07-18 12:42:38 -07002162 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002163 stream2->Reset(quic::QUIC_STREAM_CANCELLED);
2164
2165 QuicRstStreamFrame rst1(kInvalidControlFrameId, stream2->id(),
2166 QUIC_ERROR_PROCESSING_STREAM, 0);
fkastenholz305e1732019-06-18 05:01:22 -07002167 if (!VersionHasIetfQuicFrames(transport_version())) {
fkastenholz8556dc22019-07-18 12:42:38 -07002168 EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002169 }
2170 session_.OnRstStream(rst1);
2171}
2172
2173// Regression test of b/71548958.
2174TEST_P(QuicSessionTestServer, TestZombieStreams) {
2175 session_.set_writev_consumes_all_data(true);
2176
2177 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07002178 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002179 stream2->WriteOrBufferData(body, false, nullptr);
2180 EXPECT_TRUE(stream2->IsWaitingForAcks());
2181 EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream2).size());
2182
2183 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream2->id(),
2184 QUIC_STREAM_CANCELLED, 1234);
2185 // Just for the RST_STREAM
2186 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002187 .WillOnce(Invoke(&ClearControlFrame));
fkastenholz305e1732019-06-18 05:01:22 -07002188 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002189 EXPECT_CALL(*connection_,
2190 OnStreamReset(stream2->id(), QUIC_STREAM_CANCELLED));
2191 } else {
2192 EXPECT_CALL(*connection_,
2193 OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT));
2194 }
2195 stream2->OnStreamReset(rst_frame);
2196
fkastenholz305e1732019-06-18 05:01:22 -07002197 if (VersionHasIetfQuicFrames(transport_version())) {
ianswett0a8ff622020-02-05 23:28:58 -08002198 // The test requires the stream to be fully closed in both directions. For
2199 // IETF QUIC, the RST_STREAM only closes one side.
QUICHE teama6ef0a62019-03-07 20:34:33 -05002200 QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
2201 QUIC_STREAM_CANCELLED);
renjietangeab918f2019-10-28 12:10:32 -07002202 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2203 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002204 }
2205 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2206 ASSERT_EQ(1u, session_.closed_streams()->size());
2207 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
2208
2209 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
fkastenholz305e1732019-06-18 05:01:22 -07002210 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002211 // Once for the RST_STREAM, once for the STOP_SENDING
2212 EXPECT_CALL(*connection_, SendControlFrame(_))
2213 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -07002214 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002215 } else {
2216 // Just for the RST_STREAM
2217 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
2218 }
2219 EXPECT_CALL(*connection_,
2220 OnStreamReset(stream4->id(), QUIC_STREAM_CANCELLED));
2221 stream4->WriteOrBufferData(body, false, nullptr);
2222 // Note well: Reset() actually closes the stream in both directions. For
2223 // GOOGLE QUIC it sends a RST_STREAM (which does a 2-way close), for IETF
fkastenholz305e1732019-06-18 05:01:22 -07002224 // QUIC it sends both a RST_STREAM and a STOP_SENDING (each of which
QUICHE teama6ef0a62019-03-07 20:34:33 -05002225 // closes in only one direction).
2226 stream4->Reset(QUIC_STREAM_CANCELLED);
2227 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2228 EXPECT_EQ(2u, session_.closed_streams()->size());
2229}
2230
2231TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002232 InSequence s;
2233
2234 // Drive congestion control manually.
2235 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2236 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2237
2238 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
2239 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2240 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2241
nharper46833c32019-05-15 21:33:05 -07002242 QuicStreamFrame frame1;
2243 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
2244 frame1 = QuicStreamFrame(
2245 QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
2246 0, 1300);
2247 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002248 QuicStreamFrame frame2(stream2->id(), false, 0, 9);
2249 QuicStreamFrame frame3(stream4->id(), false, 0, 9);
2250
2251 // Lost data on cryption stream, streams 2 and 4.
2252 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
QUICHE teamea740082019-03-11 17:58:43 -07002253 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002254 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2255 .WillOnce(Return(true));
2256 }
2257 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2258 session_.OnFrameLost(QuicFrame(frame3));
QUICHE teamea740082019-03-11 17:58:43 -07002259 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002260 session_.OnFrameLost(QuicFrame(frame1));
2261 } else {
QUICHE team6987b4a2019-03-15 16:23:04 -07002262 QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002263 session_.OnFrameLost(QuicFrame(&crypto_frame));
2264 }
2265 session_.OnFrameLost(QuicFrame(frame2));
2266 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2267
2268 // Mark streams 2 and 4 write blocked.
2269 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2270 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2271
2272 // Lost data is retransmitted before new data, and retransmissions for crypto
2273 // stream go first.
2274 // Do not check congestion window when crypto stream has lost data.
2275 EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
QUICHE teamea740082019-03-11 17:58:43 -07002276 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002277 EXPECT_CALL(*crypto_stream, OnCanWrite());
2278 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2279 .WillOnce(Return(false));
2280 }
2281 // Check congestion window for non crypto streams.
2282 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2283 EXPECT_CALL(*stream4, OnCanWrite());
2284 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(false));
2285 // Connection is blocked.
2286 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(false));
2287
2288 session_.OnCanWrite();
2289 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2290
2291 // Unblock connection.
2292 // Stream 2 retransmits lost data.
2293 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2294 EXPECT_CALL(*stream2, OnCanWrite());
2295 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2296 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2297 // Stream 2 sends new data.
2298 EXPECT_CALL(*stream2, OnCanWrite());
2299 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2300 EXPECT_CALL(*stream4, OnCanWrite());
2301 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2302
2303 session_.OnCanWrite();
2304 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2305}
2306
2307TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002308 InSequence s;
2309
2310 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2311 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2312 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2313
2314 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2315 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2316 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2317
2318 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(true));
2319 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
2320 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2321 session_.OnFrameLost(QuicFrame(frame3));
2322 session_.OnFrameLost(QuicFrame(frame2));
2323 session_.OnFrameLost(QuicFrame(frame1));
2324
2325 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2326 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2327 session_.MarkConnectionLevelWriteBlocked(stream6->id());
2328
2329 // Reset stream 4 locally.
2330 EXPECT_CALL(*connection_, SendControlFrame(_));
2331 EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
2332 stream4->Reset(QUIC_STREAM_CANCELLED);
2333
2334 // Verify stream 4 is removed from streams with lost data list.
2335 EXPECT_CALL(*stream6, OnCanWrite());
2336 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
2337 EXPECT_CALL(*stream2, OnCanWrite());
2338 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2339 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002340 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002341 EXPECT_CALL(*stream2, OnCanWrite());
2342 EXPECT_CALL(*stream6, OnCanWrite());
2343 session_.OnCanWrite();
2344}
2345
2346TEST_P(QuicSessionTestServer, RetransmitFrames) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002347 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2348 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2349 InSequence s;
2350
2351 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2352 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2353 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2354 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002355 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002356 session_.SendWindowUpdate(stream2->id(), 9);
2357
2358 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2359 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2360 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2361 QuicWindowUpdateFrame window_update(1, stream2->id(), 9);
2362 QuicFrames frames;
2363 frames.push_back(QuicFrame(frame1));
2364 frames.push_back(QuicFrame(&window_update));
2365 frames.push_back(QuicFrame(frame2));
2366 frames.push_back(QuicFrame(frame3));
2367 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2368
renjietang4d992bf2020-03-03 13:01:55 -08002369 EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _, _))
2370 .WillOnce(Return(true));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002371 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002372 .WillOnce(Invoke(&ClearControlFrame));
renjietang4d992bf2020-03-03 13:01:55 -08002373 EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _, _))
2374 .WillOnce(Return(true));
2375 EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _))
2376 .WillOnce(Return(true));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002377 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2378 session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
2379}
2380
2381// Regression test of b/110082001.
2382TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) {
2383 // This test mimics the scenario when a dynamic stream retransmits lost data
2384 // and causes connection close.
QUICHE teama6ef0a62019-03-07 20:34:33 -05002385 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2386 QuicStreamFrame frame(stream->id(), false, 0, 9);
2387
2388 EXPECT_CALL(*stream, HasPendingRetransmission())
2389 .Times(2)
2390 .WillOnce(Return(true))
2391 .WillOnce(Return(false));
2392 session_.OnFrameLost(QuicFrame(frame));
2393 // Retransmit stream data causes connection close. Stream has not sent fin
2394 // yet, so an RST is sent.
fayangd62ea772020-04-17 06:32:16 -07002395 if (session_.break_close_loop()) {
2396 EXPECT_CALL(*stream, OnCanWrite()).WillOnce(Invoke([this, stream]() {
2397 session_.CloseStream(stream->id());
2398 }));
2399 } else {
2400 EXPECT_CALL(*stream, OnCanWrite())
2401 .WillOnce(Invoke(stream, &QuicStream::OnClose));
2402 }
fkastenholz305e1732019-06-18 05:01:22 -07002403 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002404 // Once for the RST_STREAM, once for the STOP_SENDING
2405 EXPECT_CALL(*connection_, SendControlFrame(_))
2406 .Times(2)
2407 .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
2408 } else {
2409 // Just for the RST_STREAM
2410 EXPECT_CALL(*connection_, SendControlFrame(_))
2411 .WillOnce(Invoke(&session_, &TestSession::SaveFrame));
2412 }
2413 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
2414 session_.OnCanWrite();
2415}
2416
2417TEST_P(QuicSessionTestServer, SendMessage) {
2418 // Cannot send message when encryption is not established.
fayanga3d8df72020-01-14 11:54:39 -08002419 EXPECT_FALSE(session_.OneRttKeysAvailable());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002420 quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
2421 EXPECT_EQ(MessageResult(MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0),
2422 session_.SendMessage(
2423 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2424 "", &storage)));
2425
2426 // Finish handshake.
fayang01062942020-01-22 07:23:23 -08002427 if (connection_->version().HasHandshakeDone()) {
2428 EXPECT_CALL(*connection_, SendControlFrame(_));
2429 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002430 CryptoHandshakeMessage handshake_message;
2431 session_.GetMutableCryptoStream()->OnHandshakeMessage(handshake_message);
fayanga3d8df72020-01-14 11:54:39 -08002432 EXPECT_TRUE(session_.OneRttKeysAvailable());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002433
dmcardlecf0bfcf2019-12-13 08:08:21 -08002434 quiche::QuicheStringPiece message;
QUICHE team350e9e62019-11-19 13:16:24 -08002435 EXPECT_CALL(*connection_, SendMessage(1, _, false))
QUICHE teama6ef0a62019-03-07 20:34:33 -05002436 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2437 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
2438 session_.SendMessage(
2439 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2440 message, &storage)));
2441 // Verify message_id increases.
QUICHE team350e9e62019-11-19 13:16:24 -08002442 EXPECT_CALL(*connection_, SendMessage(2, _, false))
QUICHE teama6ef0a62019-03-07 20:34:33 -05002443 .WillOnce(Return(MESSAGE_STATUS_TOO_LARGE));
2444 EXPECT_EQ(MessageResult(MESSAGE_STATUS_TOO_LARGE, 0),
2445 session_.SendMessage(
2446 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2447 message, &storage)));
2448 // Verify unsent message does not consume a message_id.
QUICHE team350e9e62019-11-19 13:16:24 -08002449 EXPECT_CALL(*connection_, SendMessage(2, _, false))
QUICHE teama6ef0a62019-03-07 20:34:33 -05002450 .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
2451 EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 2),
2452 session_.SendMessage(
2453 MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
2454 message, &storage)));
2455
2456 QuicMessageFrame frame(1);
2457 QuicMessageFrame frame2(2);
2458 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2459 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2460
2461 // Lost message 2.
2462 session_.OnMessageLost(2);
2463 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame2)));
2464
2465 // message 1 gets acked.
QUICHE team9467db02019-05-30 09:38:45 -07002466 session_.OnMessageAcked(1, QuicTime::Zero());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002467 EXPECT_FALSE(session_.IsFrameOutstanding(QuicFrame(&frame)));
2468}
2469
2470// Regression test of b/115323618.
2471TEST_P(QuicSessionTestServer, LocallyResetZombieStreams) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002472 session_.set_writev_consumes_all_data(true);
2473 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07002474 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002475 stream2->CloseReadSide();
2476 stream2->WriteOrBufferData(body, true, nullptr);
2477 EXPECT_TRUE(stream2->IsWaitingForAcks());
2478 // Verify stream2 is a zombie streams.
2479 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2480
2481 QuicStreamFrame frame(stream2->id(), true, 0, 100);
2482 EXPECT_CALL(*stream2, HasPendingRetransmission())
2483 .WillRepeatedly(Return(true));
2484 session_.OnFrameLost(QuicFrame(frame));
2485
2486 // Reset stream2 locally.
2487 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002488 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002489 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2490 stream2->Reset(QUIC_STREAM_CANCELLED);
2491
2492 // Verify stream 2 gets closed.
2493 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2494 EXPECT_TRUE(session_.IsClosedStream(stream2->id()));
2495 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
2496 session_.OnCanWrite();
2497}
2498
2499TEST_P(QuicSessionTestServer, CleanUpClosedStreamsAlarm) {
2500 EXPECT_FALSE(
2501 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2502
2503 session_.set_writev_consumes_all_data(true);
2504 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2505 EXPECT_FALSE(stream2->IsWaitingForAcks());
2506
2507 EXPECT_CALL(*connection_, SendControlFrame(_));
2508 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
2509 session_.CloseStream(stream2->id());
2510 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
2511 EXPECT_EQ(1u, session_.closed_streams()->size());
2512 EXPECT_TRUE(
2513 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet());
2514
2515 alarm_factory_.FireAlarm(
2516 QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_));
2517 EXPECT_TRUE(session_.closed_streams()->empty());
2518}
2519
2520TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
2521 session_.set_writev_consumes_all_data(true);
2522 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2523 &session_, WRITE_UNIDIRECTIONAL);
2524 session_.ActivateStream(QuicWrapUnique(stream4));
vasilvvc48c8712019-03-11 13:38:16 -07002525 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002526 stream4->WriteOrBufferData(body, false, nullptr);
2527 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2528 stream4->WriteOrBufferData(body, true, nullptr);
2529 EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
2530}
2531
2532TEST_P(QuicSessionTestServer, ReceivedDataOnWriteUnidirectionalStream) {
2533 TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
2534 &session_, WRITE_UNIDIRECTIONAL);
2535 session_.ActivateStream(QuicWrapUnique(stream4));
2536
2537 EXPECT_CALL(
2538 *connection_,
2539 CloseConnection(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM, _, _))
2540 .Times(1);
2541 QuicStreamFrame stream_frame(GetNthServerInitiatedUnidirectionalId(1), false,
2542 0, 2);
2543 session_.OnStreamFrame(stream_frame);
2544}
2545
2546TEST_P(QuicSessionTestServer, ReadUnidirectionalStream) {
2547 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2548 &session_, READ_UNIDIRECTIONAL);
2549 session_.ActivateStream(QuicWrapUnique(stream4));
2550 EXPECT_FALSE(stream4->IsWaitingForAcks());
2551 // Discard all incoming data.
2552 stream4->StopReading();
2553
vasilvvc48c8712019-03-11 13:38:16 -07002554 std::string data(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002555 QuicStreamFrame stream_frame(GetNthClientInitiatedUnidirectionalId(1), false,
2556 0, data);
2557 stream4->OnStreamFrame(stream_frame);
2558 EXPECT_TRUE(session_.closed_streams()->empty());
2559
2560 QuicStreamFrame stream_frame2(GetNthClientInitiatedUnidirectionalId(1), true,
2561 100, data);
2562 stream4->OnStreamFrame(stream_frame2);
2563 EXPECT_EQ(1u, session_.closed_streams()->size());
2564}
2565
2566TEST_P(QuicSessionTestServer, WriteOrBufferDataOnReadUnidirectionalStream) {
2567 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2568 &session_, READ_UNIDIRECTIONAL);
2569 session_.ActivateStream(QuicWrapUnique(stream4));
2570
2571 EXPECT_CALL(*connection_,
2572 CloseConnection(
2573 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2574 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002575 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002576 stream4->WriteOrBufferData(body, false, nullptr);
2577}
2578
2579TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
2580 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2581 &session_, READ_UNIDIRECTIONAL);
2582 session_.ActivateStream(QuicWrapUnique(stream4));
2583
2584 EXPECT_CALL(*connection_,
2585 CloseConnection(
2586 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2587 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -07002588 std::string body(100, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05002589 struct iovec iov = {const_cast<char*>(body.data()), body.length()};
2590 QuicMemSliceStorage storage(
2591 &iov, 1, session_.connection()->helper()->GetStreamSendBufferAllocator(),
2592 1024);
2593 stream4->WriteMemSlices(storage.ToSpan(), false);
2594}
2595
2596TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
2597 TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
2598 &session_, READ_UNIDIRECTIONAL);
2599 session_.ActivateStream(QuicWrapUnique(stream4));
2600
2601 EXPECT_CALL(*connection_,
2602 CloseConnection(
2603 QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
2604 .Times(1);
2605 char data[1024];
2606 std::vector<std::pair<char*, size_t>> buffers;
bnc4e9283d2019-12-17 07:08:57 -08002607 buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data)));
2608 buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002609 QuicTestMemSliceVector vector(buffers);
2610 stream4->WriteMemSlices(vector.span(), false);
2611}
2612
2613// Test code that tests that an incoming stream frame with a new (not previously
2614// seen) stream id is acceptable. The ID must not be larger than has been
2615// advertised. It may be equal to what has been advertised. These tests
2616// invoke QuicStreamIdManager::MaybeIncreaseLargestPeerStreamId by calling
2617// QuicSession::OnStreamFrame in order to check that all the steps are connected
2618// properly and that nothing in the call path interferes with the check.
2619// First test make sure that streams with ids below the limit are accepted.
2620TEST_P(QuicSessionTestServer, NewStreamIdBelowLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002621 if (!VersionHasIetfQuicFrames(transport_version())) {
2622 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002623 return;
2624 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07002625 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002626 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002627 ->advertised_max_incoming_bidirectional_streams() -
fkastenholz3c4eabf2019-04-22 07:49:59 -07002628 1,
2629 Perspective::IS_CLIENT,
2630 /*bidirectional=*/true);
2631
QUICHE teama6ef0a62019-03-07 20:34:33 -05002632 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2633 "Random String");
2634 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2635 session_.OnStreamFrame(bidirectional_stream_frame);
2636
fkastenholz3c4eabf2019-04-22 07:49:59 -07002637 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002638 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002639 ->advertised_max_incoming_unidirectional_streams() -
fkastenholz3c4eabf2019-04-22 07:49:59 -07002640 1,
2641 Perspective::IS_CLIENT,
2642 /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002643 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2644 0, "Random String");
2645 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2646 session_.OnStreamFrame(unidirectional_stream_frame);
2647}
2648
2649// Accept a stream with an ID that equals the limit.
2650TEST_P(QuicSessionTestServer, NewStreamIdAtLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002651 if (!VersionHasIetfQuicFrames(transport_version())) {
2652 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002653 return;
2654 }
ianswettd1414532019-09-18 20:12:59 -07002655 QuicStreamId bidirectional_stream_id =
2656 StreamCountToId(QuicSessionPeer::v99_streamid_manager(&session_)
2657 ->advertised_max_incoming_bidirectional_streams(),
2658 Perspective::IS_CLIENT, /*bidirectional=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002659 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2660 "Random String");
2661 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2662 session_.OnStreamFrame(bidirectional_stream_frame);
2663
ianswettd1414532019-09-18 20:12:59 -07002664 QuicStreamId unidirectional_stream_id =
2665 StreamCountToId(QuicSessionPeer::v99_streamid_manager(&session_)
2666 ->advertised_max_incoming_unidirectional_streams(),
2667 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002668 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2669 0, "Random String");
2670 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2671 session_.OnStreamFrame(unidirectional_stream_frame);
2672}
2673
2674// Close the connection if the id exceeds the limit.
2675TEST_P(QuicSessionTestServer, NewStreamIdAboveLimit) {
fkastenholz305e1732019-06-18 05:01:22 -07002676 if (!VersionHasIetfQuicFrames(transport_version())) {
2677 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002678 return;
2679 }
fkastenholz56055be2019-09-17 11:17:37 -07002680
fkastenholz3c4eabf2019-04-22 07:49:59 -07002681 QuicStreamId bidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002682 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002683 ->advertised_max_incoming_bidirectional_streams() +
fkastenholz3c4eabf2019-04-22 07:49:59 -07002684 1,
2685 Perspective::IS_CLIENT, /*bidirectional=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002686 QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
2687 "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002688 EXPECT_CALL(
2689 *connection_,
2690 CloseConnection(QUIC_INVALID_STREAM_ID,
nharpercd820e02019-05-16 15:12:07 -07002691 "Stream id 400 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002692 session_.OnStreamFrame(bidirectional_stream_frame);
2693
fkastenholz3c4eabf2019-04-22 07:49:59 -07002694 QuicStreamId unidirectional_stream_id = StreamCountToId(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002695 QuicSessionPeer::v99_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -07002696 ->advertised_max_incoming_unidirectional_streams() +
fkastenholz3c4eabf2019-04-22 07:49:59 -07002697 1,
2698 Perspective::IS_CLIENT, /*bidirectional=*/false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002699 QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
2700 0, "Random String");
fkastenholz3c4eabf2019-04-22 07:49:59 -07002701 EXPECT_CALL(
2702 *connection_,
2703 CloseConnection(QUIC_INVALID_STREAM_ID,
2704 "Stream id 402 would exceed stream count limit 100", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002705 session_.OnStreamFrame(unidirectional_stream_frame);
2706}
2707
ianswett0a8ff622020-02-05 23:28:58 -08002708// Checks that invalid stream ids are handled.
2709TEST_P(QuicSessionTestServer, OnStopSendingInvalidStreamId) {
fkastenholz305e1732019-06-18 05:01:22 -07002710 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002711 return;
2712 }
2713 // Check that "invalid" stream ids are rejected.
QUICHE teama6ef0a62019-03-07 20:34:33 -05002714 QuicStopSendingFrame frame(1, -1, 123);
2715 EXPECT_CALL(
2716 *connection_,
2717 CloseConnection(QUIC_INVALID_STREAM_ID,
2718 "Received STOP_SENDING for an invalid stream", _));
renjietangeab918f2019-10-28 12:10:32 -07002719 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002720}
2721
ianswett0a8ff622020-02-05 23:28:58 -08002722TEST_P(QuicSessionTestServer, OnStopSendingReadUnidirectional) {
fkastenholz305e1732019-06-18 05:01:22 -07002723 if (!VersionHasIetfQuicFrames(transport_version())) {
ianswett0a8ff622020-02-05 23:28:58 -08002724 return;
2725 }
2726 // It's illegal to send STOP_SENDING with a stream ID that is read-only.
2727 QuicStopSendingFrame frame(1, GetNthClientInitiatedUnidirectionalId(1), 123);
2728 EXPECT_CALL(
2729 *connection_,
2730 CloseConnection(QUIC_INVALID_STREAM_ID,
2731 "Received STOP_SENDING for a read-only stream", _));
2732 session_.OnStopSendingFrame(frame);
2733}
2734
2735// Static streams ignore STOP_SENDING.
2736TEST_P(QuicSessionTestServer, OnStopSendingStaticStreams) {
2737 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002738 return;
2739 }
nharper46833c32019-05-15 21:33:05 -07002740 QuicStreamId stream_id = 0;
vasilvv0fc587f2019-09-06 13:33:08 -07002741 std::unique_ptr<TestStream> fake_static_stream = std::make_unique<TestStream>(
nharper46833c32019-05-15 21:33:05 -07002742 stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
renjietang5c729f02019-09-06 12:43:48 -07002743 QuicSessionPeer::ActivateStream(&session_, std::move(fake_static_stream));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002744 // Check that a stream id in the static stream map is ignored.
nharper46833c32019-05-15 21:33:05 -07002745 QuicStopSendingFrame frame(1, stream_id, 123);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002746 EXPECT_CALL(*connection_,
2747 CloseConnection(QUIC_INVALID_STREAM_ID,
2748 "Received STOP_SENDING for a static stream", _));
renjietangeab918f2019-10-28 12:10:32 -07002749 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002750}
2751
ianswett0a8ff622020-02-05 23:28:58 -08002752// If stream is write closed, do not send a RESET_STREAM frame.
2753TEST_P(QuicSessionTestServer, OnStopSendingForWriteClosedStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002754 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002755 return;
2756 }
2757
2758 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2759 QuicStreamId stream_id = stream->id();
fayangd62ea772020-04-17 06:32:16 -07002760 QuicStreamPeer::SetFinSent(stream);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002761 stream->CloseWriteSide();
ianswett0a8ff622020-02-05 23:28:58 -08002762 EXPECT_TRUE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002763 QuicStopSendingFrame frame(1, stream_id, 123);
2764 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
renjietangeab918f2019-10-28 12:10:32 -07002765 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002766}
2767
ianswett0a8ff622020-02-05 23:28:58 -08002768// If stream is closed, return true and do not close the connection.
2769TEST_P(QuicSessionTestServer, OnStopSendingClosedStream) {
2770 if (!VersionHasIetfQuicFrames(transport_version())) {
2771 return;
2772 }
2773
2774 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2775 QuicStreamId stream_id = stream->id();
2776 // Expect these as side effect of closing the stream.
2777 EXPECT_CALL(*connection_, SendControlFrame(_));
2778 EXPECT_CALL(*connection_, OnStreamReset(_, _));
2779 session_.CloseStream(stream_id);
2780 QuicStopSendingFrame frame(1, stream_id, 123);
2781 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2782 session_.OnStopSendingFrame(frame);
2783}
2784
renjietangf0d56112020-03-09 14:05:19 -07002785// If stream id is a nonexistent local stream, return false and close the
2786// connection.
2787TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentLocalStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002788 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002789 return;
2790 }
2791
2792 QuicStopSendingFrame frame(1, GetNthServerInitiatedBidirectionalId(123456),
2793 123);
bncec3602c2020-03-12 17:57:59 -07002794 EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_STREAM_WRONG_DIRECTION,
renjietangf0d56112020-03-09 14:05:19 -07002795 "Data for nonexistent stream", _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05002796 .Times(1);
renjietangeab918f2019-10-28 12:10:32 -07002797 session_.OnStopSendingFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002798}
2799
renjietangf0d56112020-03-09 14:05:19 -07002800// If a STOP_SENDING is received for a peer initiated stream, the new stream
2801// will be created.
2802TEST_P(QuicSessionTestServer, OnStopSendingNewStream) {
2803 if (!VersionHasIetfQuicFrames(transport_version())) {
2804 return;
2805 }
2806 QuicStopSendingFrame frame(1, GetNthClientInitiatedBidirectionalId(1), 123);
2807
2808 // A Rst will be sent as a response for STOP_SENDING.
2809 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
2810 EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1);
2811 session_.OnStopSendingFrame(frame);
2812
2813 QuicStream* stream =
2814 session_.GetOrCreateStream(GetNthClientInitiatedBidirectionalId(1));
2815 EXPECT_TRUE(stream);
2816 EXPECT_TRUE(stream->write_side_closed());
2817}
2818
QUICHE teama6ef0a62019-03-07 20:34:33 -05002819// For a valid stream, ensure that all works
2820TEST_P(QuicSessionTestServer, OnStopSendingInputValidStream) {
fkastenholz305e1732019-06-18 05:01:22 -07002821 if (!VersionHasIetfQuicFrames(transport_version())) {
2822 // Applicable only to IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05002823 return;
2824 }
2825
2826 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2827
2828 // Ensure that the stream starts out open in both directions.
bncc7d9e0c2019-04-16 10:22:15 -07002829 EXPECT_FALSE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002830 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
2831
2832 QuicStreamId stream_id = stream->id();
2833 QuicStopSendingFrame frame(1, stream_id, 123);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002834 // Expect a reset to come back out.
2835 EXPECT_CALL(*connection_, SendControlFrame(_));
2836 EXPECT_CALL(
2837 *connection_,
2838 OnStreamReset(stream_id, static_cast<QuicRstStreamErrorCode>(123)));
renjietangeab918f2019-10-28 12:10:32 -07002839 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
2840 session_.OnStopSendingFrame(frame);
renjietange5c12382019-11-07 10:13:14 -08002841
QUICHE teama6ef0a62019-03-07 20:34:33 -05002842 EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
bncc7d9e0c2019-04-16 10:22:15 -07002843 EXPECT_TRUE(stream->write_side_closed());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002844}
2845
fayangaee31ef2019-08-20 06:47:51 -07002846TEST_P(QuicSessionTestServer, WriteBufferedCryptoFrames) {
2847 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
2848 return;
2849 }
2850 std::string data(1350, 'a');
2851 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
2852 // Only consumed 1000 bytes.
2853 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 1350, 0))
2854 .WillOnce(Return(1000));
2855 crypto_stream->WriteCryptoData(ENCRYPTION_INITIAL, data);
2856 EXPECT_TRUE(session_.HasPendingHandshake());
2857 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2858
2859 EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
2860 crypto_stream->WriteCryptoData(ENCRYPTION_ZERO_RTT, data);
2861
2862 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 350, 1000))
2863 .WillOnce(Return(350));
2864 EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1350, 0))
2865 .WillOnce(Return(1350));
2866 session_.OnCanWrite();
2867 EXPECT_FALSE(session_.HasPendingHandshake());
2868 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2869}
2870
renjietang963c2ec2019-09-12 11:46:50 -07002871// Regression test for
2872// https://bugs.chromium.org/p/chromium/issues/detail?id=1002119
2873TEST_P(QuicSessionTestServer, StreamFrameReceivedAfterFin) {
2874 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
2875 QuicStreamFrame frame(stream->id(), true, 0, ",");
2876 session_.OnStreamFrame(frame);
2877
2878 QuicStreamFrame frame1(stream->id(), false, 1, ",");
renjietang7ab48c32019-12-09 15:40:31 -08002879 EXPECT_CALL(*connection_,
2880 CloseConnection(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET, _, _));
renjietang89aa73e2019-10-21 15:03:51 -07002881 session_.OnStreamFrame(frame1);
renjietang963c2ec2019-09-12 11:46:50 -07002882}
2883
renjietangd9762282019-11-11 17:11:18 -08002884TEST_P(QuicSessionTestServer, ResetForIETFStreamTypes) {
2885 if (!VersionHasIetfQuicFrames(transport_version())) {
2886 return;
2887 }
2888
2889 QuicStreamId read_only = GetNthClientInitiatedUnidirectionalId(0);
renjietangd9762282019-11-11 17:11:18 -08002890
2891 EXPECT_CALL(*connection_, SendControlFrame(_))
2892 .Times(1)
2893 .WillOnce(Invoke(&ClearControlFrame));
2894 EXPECT_CALL(*connection_, OnStreamReset(read_only, _));
renjietang61cc2452019-11-26 10:57:10 -08002895 session_.SendRstStream(read_only, QUIC_STREAM_CANCELLED, 0);
renjietangd9762282019-11-11 17:11:18 -08002896
2897 QuicStreamId write_only = GetNthServerInitiatedUnidirectionalId(0);
2898 EXPECT_CALL(*connection_, SendControlFrame(_))
2899 .Times(1)
2900 .WillOnce(Invoke(&ClearControlFrame));
2901 EXPECT_CALL(*connection_, OnStreamReset(write_only, _));
renjietang61cc2452019-11-26 10:57:10 -08002902 session_.SendRstStream(write_only, QUIC_STREAM_CANCELLED, 0);
renjietangd9762282019-11-11 17:11:18 -08002903
2904 QuicStreamId bidirectional = GetNthClientInitiatedBidirectionalId(0);
2905 EXPECT_CALL(*connection_, SendControlFrame(_))
2906 .Times(2)
2907 .WillRepeatedly(Invoke(&ClearControlFrame));
2908 EXPECT_CALL(*connection_, OnStreamReset(bidirectional, _));
renjietang61cc2452019-11-26 10:57:10 -08002909 session_.SendRstStream(bidirectional, QUIC_STREAM_CANCELLED, 0);
renjietangd9762282019-11-11 17:11:18 -08002910}
2911
fayangd2866522020-02-12 11:15:27 -08002912TEST_P(QuicSessionTestServer, DecryptionKeyAvailableBeforeEncryptionKey) {
2913 if (connection_->version().handshake_protocol != PROTOCOL_TLS1_3) {
2914 return;
2915 }
2916 ASSERT_FALSE(connection_->framer().HasEncrypterOfEncryptionLevel(
2917 ENCRYPTION_HANDSHAKE));
2918 EXPECT_FALSE(session_.OnNewDecryptionKeyAvailable(
2919 ENCRYPTION_HANDSHAKE, /*decrypter=*/nullptr,
2920 /*set_alternative_decrypter=*/false, /*latch_once_used=*/false));
2921}
2922
bncec3602c2020-03-12 17:57:59 -07002923TEST_P(QuicSessionTestServer, IncomingStreamWithServerInitiatedStreamId) {
2924 const QuicErrorCode expected_error =
2925 VersionHasIetfQuicFrames(transport_version())
2926 ? QUIC_HTTP_STREAM_WRONG_DIRECTION
2927 : QUIC_INVALID_STREAM_ID;
2928 EXPECT_CALL(
2929 *connection_,
2930 CloseConnection(expected_error, "Data for nonexistent stream",
2931 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
2932
2933 QuicStreamFrame frame(GetNthServerInitiatedBidirectionalId(1),
2934 /* fin = */ false, /* offset = */ 0,
2935 quiche::QuicheStringPiece("foo"));
2936 session_.OnStreamFrame(frame);
2937}
2938
fkastenholz56055be2019-09-17 11:17:37 -07002939// A client test class that can be used when the automatic configuration is not
2940// desired.
2941class QuicSessionTestClientUnconfigured : public QuicSessionTestBase {
2942 protected:
2943 QuicSessionTestClientUnconfigured()
2944 : QuicSessionTestBase(Perspective::IS_CLIENT,
2945 /*configure_session=*/false) {}
2946};
2947
2948INSTANTIATE_TEST_SUITE_P(Tests,
2949 QuicSessionTestClientUnconfigured,
dschinazi142051a2019-09-18 18:17:29 -07002950 ::testing::ValuesIn(AllSupportedVersions()),
2951 ::testing::PrintToStringParamName());
fkastenholz56055be2019-09-17 11:17:37 -07002952
dschinazi18cdf132019-10-09 16:08:18 -07002953TEST_P(QuicSessionTestClientUnconfigured, StreamInitiallyBlockedThenUnblocked) {
2954 if (!connection_->version().AllowsLowFlowControlLimits()) {
2955 return;
2956 }
2957 // Create a stream before negotiating the config and verify it starts off
2958 // blocked.
renjietangcbfb93e2020-01-23 17:03:30 -08002959 QuicSessionPeer::SetMaxOpenOutgoingBidirectionalStreams(&session_, 10);
dschinazi18cdf132019-10-09 16:08:18 -07002960 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2961 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
2962 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
2963 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
2964
2965 // Negotiate the config with higher received limits.
2966 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
2967 session_.config(), kMinimumFlowControlSendWindow);
2968 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
2969 session_.config(), kMinimumFlowControlSendWindow);
2970 session_.OnConfigNegotiated();
2971
2972 // Stream is now unblocked.
2973 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
2974 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
2975 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
2976}
2977
QUICHE teama6ef0a62019-03-07 20:34:33 -05002978} // namespace
2979} // namespace test
2980} // namespace quic