blob: 2e8b80f4527da665defb3c44c7ee8c0b916208fd [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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/core/http/quic_spdy_session.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
7#include <cstdint>
bnc92fa63a2020-02-04 05:13:43 -08008#include <limits>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include <set>
vasilvv872e7a32019-03-12 16:42:44 -070010#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011#include <utility>
12
vasilvvfe1c8f32020-10-19 14:10:59 -070013#include "absl/base/macros.h"
vasilvv72b789c2020-10-27 17:39:17 -070014#include "absl/strings/escaping.h"
vasilvva163b382020-12-04 11:47:46 -080015#include "absl/strings/str_cat.h"
vasilvve2707e32020-10-08 12:27:46 -070016#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050017#include "quic/core/crypto/crypto_protocol.h"
18#include "quic/core/crypto/null_encrypter.h"
19#include "quic/core/frames/quic_stream_frame.h"
20#include "quic/core/frames/quic_streams_blocked_frame.h"
21#include "quic/core/http/http_constants.h"
22#include "quic/core/http/http_encoder.h"
23#include "quic/core/qpack/qpack_header_table.h"
24#include "quic/core/quic_config.h"
25#include "quic/core/quic_crypto_stream.h"
26#include "quic/core/quic_data_writer.h"
27#include "quic/core/quic_error_codes.h"
28#include "quic/core/quic_packets.h"
29#include "quic/core/quic_stream.h"
30#include "quic/core/quic_types.h"
31#include "quic/core/quic_utils.h"
32#include "quic/core/quic_versions.h"
33#include "quic/platform/api/quic_expect_bug.h"
34#include "quic/platform/api/quic_flags.h"
35#include "quic/platform/api/quic_map_util.h"
36#include "quic/platform/api/quic_ptr_util.h"
37#include "quic/platform/api/quic_test.h"
38#include "quic/test_tools/qpack/qpack_encoder_peer.h"
39#include "quic/test_tools/qpack/qpack_header_table_peer.h"
40#include "quic/test_tools/qpack/qpack_test_utils.h"
41#include "quic/test_tools/quic_config_peer.h"
42#include "quic/test_tools/quic_connection_peer.h"
43#include "quic/test_tools/quic_flow_controller_peer.h"
44#include "quic/test_tools/quic_session_peer.h"
45#include "quic/test_tools/quic_spdy_session_peer.h"
46#include "quic/test_tools/quic_stream_peer.h"
47#include "quic/test_tools/quic_stream_send_buffer_peer.h"
48#include "quic/test_tools/quic_test_utils.h"
49#include "common/platform/api/quiche_text_utils.h"
50#include "common/quiche_endian.h"
51#include "spdy/core/spdy_framer.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050052
53using spdy::kV3HighestPriority;
54using spdy::Spdy3PriorityToHttp2Weight;
55using spdy::SpdyFramer;
56using spdy::SpdyHeaderBlock;
57using spdy::SpdyPriority;
58using spdy::SpdyPriorityIR;
59using spdy::SpdySerializedFrame;
dschinazi101d2eb2020-07-06 19:42:34 -070060using ::testing::_;
61using ::testing::AnyNumber;
62using ::testing::AtLeast;
63using ::testing::InSequence;
64using ::testing::Invoke;
65using ::testing::Return;
66using ::testing::StrictMock;
QUICHE teama6ef0a62019-03-07 20:34:33 -050067
68namespace quic {
69namespace test {
70namespace {
71
bnc4ff60622019-08-09 18:55:45 -070072bool VerifyAndClearStopSendingFrame(const QuicFrame& frame) {
73 EXPECT_EQ(STOP_SENDING_FRAME, frame.type);
74 return ClearControlFrame(frame);
75}
76
QUICHE teama6ef0a62019-03-07 20:34:33 -050077class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
78 public:
79 explicit TestCryptoStream(QuicSession* session)
80 : QuicCryptoStream(session),
81 QuicCryptoHandshaker(this, session),
82 encryption_established_(false),
fayang685367a2020-01-14 10:40:15 -080083 one_rtt_keys_available_(false),
rch9001a962019-12-17 10:44:04 -080084 params_(new QuicCryptoNegotiatedParameters) {
85 // Simulate a negotiated cipher_suite with a fake value.
86 params_->cipher_suite = 1;
87 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050088
fayang29ce0bd2020-10-29 08:28:44 -070089 void EstablishZeroRttEncryption() {
90 encryption_established_ = true;
91 session()->connection()->SetEncrypter(
92 ENCRYPTION_ZERO_RTT,
93 std::make_unique<NullEncrypter>(session()->perspective()));
94 }
95
QUICHE teama6ef0a62019-03-07 20:34:33 -050096 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
97 encryption_established_ = true;
fayang685367a2020-01-14 10:40:15 -080098 one_rtt_keys_available_ = true;
dschinaziaab68182019-10-09 15:39:51 -070099 QuicErrorCode error;
vasilvvc48c8712019-03-11 13:38:16 -0700100 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101 session()->config()->SetInitialStreamFlowControlWindowToSend(
102 kInitialStreamFlowControlWindowForTest);
103 session()->config()->SetInitialSessionFlowControlWindowToSend(
104 kInitialSessionFlowControlWindowForTest);
dschinazi1f6aca82020-12-04 13:20:08 -0800105 if (session()->version().UsesTls()) {
dschinazie7c38a52020-05-29 15:25:45 -0700106 if (session()->perspective() == Perspective::IS_CLIENT) {
107 session()->config()->SetOriginalConnectionIdToSend(
108 session()->connection()->connection_id());
109 session()->config()->SetInitialSourceConnectionIdToSend(
110 session()->connection()->connection_id());
111 } else {
112 session()->config()->SetInitialSourceConnectionIdToSend(
113 session()->connection()->client_connection_id());
114 }
dschinaziaab68182019-10-09 15:39:51 -0700115 TransportParameters transport_parameters;
116 EXPECT_TRUE(
117 session()->config()->FillTransportParameters(&transport_parameters));
118 error = session()->config()->ProcessTransportParameters(
dschinazi52c8f332020-08-17 13:30:01 -0700119 transport_parameters, /* is_resumption = */ false, &error_details);
dschinaziaab68182019-10-09 15:39:51 -0700120 } else {
121 CryptoHandshakeMessage msg;
122 session()->config()->ToHandshakeMessage(&msg, transport_version());
123 error =
124 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
125 }
bncc5769502019-11-27 10:01:44 -0800126 EXPECT_THAT(error, IsQuicNoError());
fayanga45ee8a2020-03-20 08:56:11 -0700127 session()->OnNewEncryptionKeyAvailable(
128 ENCRYPTION_FORWARD_SECURE,
129 std::make_unique<NullEncrypter>(session()->perspective()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500130 session()->OnConfigNegotiated();
fayangd18bfb92020-03-19 17:24:21 -0700131 if (session()->connection()->version().handshake_protocol ==
132 PROTOCOL_TLS1_3) {
renjietangc50cc4a2020-08-17 18:33:30 -0700133 session()->OnTlsHandshakeComplete();
fayangd18bfb92020-03-19 17:24:21 -0700134 } else {
135 session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
136 }
fayangd96ecda2020-02-03 08:45:18 -0800137 session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138 }
139
140 // QuicCryptoStream implementation
nharper6a6bd312020-09-17 13:20:53 -0700141 ssl_early_data_reason_t EarlyDataReason() const override {
142 return ssl_early_data_unknown;
143 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144 bool encryption_established() const override {
145 return encryption_established_;
146 }
fayang685367a2020-01-14 10:40:15 -0800147 bool one_rtt_keys_available() const override {
148 return one_rtt_keys_available_;
149 }
fayang9a863cf2020-01-16 14:12:11 -0800150 HandshakeState GetHandshakeState() const override {
151 return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
152 }
nharperac52a862020-06-08 12:41:06 -0700153 void SetServerApplicationStateForResumption(
154 std::unique_ptr<ApplicationState> /*application_state*/) override {}
mattm072a7e32020-10-09 16:16:56 -0700155 bool KeyUpdateSupportedLocally() const override { return false; }
156 std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
157 override {
158 return nullptr;
159 }
160 std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override {
161 return nullptr;
162 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
164 const override {
165 return *params_;
166 }
167 CryptoMessageParser* crypto_message_parser() override {
168 return QuicCryptoHandshaker::crypto_message_parser();
169 }
fayangd58736d2019-11-27 13:35:31 -0800170 void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
fayang2f2915d2020-01-24 06:47:15 -0800171 void OnOneRttPacketAcknowledged() override {}
fayang44ae4e92020-04-28 13:09:42 -0700172 void OnHandshakePacketSent() override {}
fayang01062942020-01-22 07:23:23 -0800173 void OnHandshakeDoneReceived() override {}
fayang133b8682020-12-08 05:50:33 -0800174 void OnNewTokenReceived(absl::string_view /*token*/) override {}
175 std::string GetAddressToken() const override { return ""; }
176 bool ValidateAddressToken(absl::string_view /*token*/) const override {
177 return true;
178 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179
wub713afae2020-04-27 07:48:31 -0700180 MOCK_METHOD(void, OnCanWrite, (), (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181
nharper46833c32019-05-15 21:33:05 -0700182 bool HasPendingCryptoRetransmission() const override { return false; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183
wub713afae2020-04-27 07:48:31 -0700184 MOCK_METHOD(bool, HasPendingRetransmission, (), (const, override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185
renjietang70738bb2020-07-08 15:07:12 -0700186 void OnConnectionClosed(QuicErrorCode /*error*/,
187 ConnectionCloseSource /*source*/) override {}
188
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189 private:
190 using QuicCryptoStream::session;
191
192 bool encryption_established_;
fayang685367a2020-01-14 10:40:15 -0800193 bool one_rtt_keys_available_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
195};
196
197class TestHeadersStream : public QuicHeadersStream {
198 public:
199 explicit TestHeadersStream(QuicSpdySession* session)
200 : QuicHeadersStream(session) {}
201
wub713afae2020-04-27 07:48:31 -0700202 MOCK_METHOD(void, OnCanWrite, (), (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500203};
204
205class TestStream : public QuicSpdyStream {
206 public:
207 TestStream(QuicStreamId id, QuicSpdySession* session, StreamType type)
208 : QuicSpdyStream(id, session, type) {}
209
renjietangbaea59c2019-05-29 15:08:14 -0700210 TestStream(PendingStream* pending, QuicSpdySession* session, StreamType type)
211 : QuicSpdyStream(pending, session, type) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500212
213 using QuicStream::CloseWriteSide;
214
215 void OnBodyAvailable() override {}
216
wub713afae2020-04-27 07:48:31 -0700217 MOCK_METHOD(void, OnCanWrite, (), (override));
218 MOCK_METHOD(bool,
219 RetransmitStreamData,
220 (QuicStreamOffset, QuicByteCount, bool, TransmissionType),
221 (override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500222
wub713afae2020-04-27 07:48:31 -0700223 MOCK_METHOD(bool, HasPendingRetransmission, (), (const, override));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224};
225
226class TestSession : public QuicSpdySession {
227 public:
228 explicit TestSession(QuicConnection* connection)
229 : QuicSpdySession(connection,
230 nullptr,
231 DefaultQuicConfig(),
232 CurrentSupportedVersions()),
233 crypto_stream_(this),
234 writev_consumes_all_data_(false) {
235 Initialize();
236 this->connection()->SetEncrypter(
237 ENCRYPTION_FORWARD_SECURE,
vasilvv0fc587f2019-09-06 13:33:08 -0700238 std::make_unique<NullEncrypter>(connection->perspective()));
fayang6a258412020-05-28 08:57:12 -0700239 if (this->connection()->version().SupportsAntiAmplificationLimit()) {
240 QuicConnectionPeer::SetAddressValidated(this->connection());
241 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500242 }
243
ianswett6aefa0b2019-12-10 07:26:15 -0800244 ~TestSession() override { DeleteConnection(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500245
246 TestCryptoStream* GetMutableCryptoStream() override {
247 return &crypto_stream_;
248 }
249
250 const TestCryptoStream* GetCryptoStream() const override {
251 return &crypto_stream_;
252 }
253
254 TestStream* CreateOutgoingBidirectionalStream() override {
255 TestStream* stream = new TestStream(GetNextOutgoingBidirectionalStreamId(),
256 this, BIDIRECTIONAL);
257 ActivateStream(QuicWrapUnique(stream));
258 return stream;
259 }
260
261 TestStream* CreateOutgoingUnidirectionalStream() override {
262 TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
263 this, WRITE_UNIDIRECTIONAL);
264 ActivateStream(QuicWrapUnique(stream));
265 return stream;
266 }
267
268 TestStream* CreateIncomingStream(QuicStreamId id) override {
269 // Enforce the limit on the number of open streams.
fayang01591ae2020-04-23 14:14:56 -0700270 if (!VersionHasIetfQuicFrames(connection()->transport_version()) &&
fayangbd94f4c2020-06-01 14:36:37 -0700271 stream_id_manager().num_open_incoming_streams() + 1 >
fayang01591ae2020-04-23 14:14:56 -0700272 max_open_incoming_bidirectional_streams()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500273 connection()->CloseConnection(
274 QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
275 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
276 return nullptr;
277 } else {
278 TestStream* stream = new TestStream(
279 id, this,
renjietangd262e252020-06-19 15:11:24 -0700280 DetermineStreamType(id, connection()->version(), perspective(),
281 /*is_incoming=*/true, BIDIRECTIONAL));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500282 ActivateStream(QuicWrapUnique(stream));
283 return stream;
284 }
285 }
286
renjietangbaea59c2019-05-29 15:08:14 -0700287 TestStream* CreateIncomingStream(PendingStream* pending) override {
288 QuicStreamId id = pending->id();
renjietangd262e252020-06-19 15:11:24 -0700289 TestStream* stream = new TestStream(
290 pending, this,
291 DetermineStreamType(id, connection()->version(), perspective(),
292 /*is_incoming=*/true, BIDIRECTIONAL));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500293 ActivateStream(QuicWrapUnique(stream));
294 return stream;
295 }
296
297 bool ShouldCreateIncomingStream(QuicStreamId /*id*/) override { return true; }
298
299 bool ShouldCreateOutgoingBidirectionalStream() override { return true; }
300 bool ShouldCreateOutgoingUnidirectionalStream() override { return true; }
301
302 bool IsClosedStream(QuicStreamId id) {
303 return QuicSession::IsClosedStream(id);
304 }
305
renjietang880d2432019-07-16 13:14:37 -0700306 QuicStream* GetOrCreateStream(QuicStreamId stream_id) {
307 return QuicSpdySession::GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500308 }
309
vasilvv7df418b2020-10-13 13:47:09 -0700310 QuicConsumedData WritevData(QuicStreamId id,
311 size_t write_length,
312 QuicStreamOffset offset,
313 StreamSendingState state,
314 TransmissionType type,
315 absl::optional<EncryptionLevel> level) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316 bool fin = state != NO_FIN;
317 QuicConsumedData consumed(write_length, fin);
318 if (!writev_consumes_all_data_) {
renjietang4d992bf2020-03-03 13:01:55 -0800319 consumed =
320 QuicSession::WritevData(id, write_length, offset, state, type, level);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500321 }
322 QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
323 id, consumed.bytes_consumed);
324 return consumed;
325 }
326
327 void set_writev_consumes_all_data(bool val) {
328 writev_consumes_all_data_ = val;
329 }
330
331 QuicConsumedData SendStreamData(QuicStream* stream) {
332 struct iovec iov;
nharper46833c32019-05-15 21:33:05 -0700333 if (!QuicUtils::IsCryptoStreamId(connection()->transport_version(),
334 stream->id()) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500335 connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
336 this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
337 }
338 MakeIOVector("not empty", &iov);
339 QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
renjietang41a1b412020-02-27 15:05:14 -0800340 QuicConsumedData consumed =
fayang9c41f8b2020-10-30 13:13:06 -0700341 WritevData(stream->id(), 9, 0, FIN, NOT_RETRANSMISSION,
342 GetEncryptionLevelToSendApplicationData());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343 QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
344 consumed.bytes_consumed);
345 return consumed;
346 }
347
QUICHE teama6ef0a62019-03-07 20:34:33 -0500348 QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
349 DCHECK(writev_consumes_all_data_);
renjietang4d992bf2020-03-03 13:01:55 -0800350 return WritevData(stream->id(), bytes, 0, FIN, NOT_RETRANSMISSION,
fayang9c41f8b2020-10-30 13:13:06 -0700351 GetEncryptionLevelToSendApplicationData());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500352 }
353
bnc9be5c212020-12-11 12:38:20 -0800354 MOCK_METHOD(void, OnAcceptChFrame, (const AcceptChFrame&), (override));
355
QUICHE teama6ef0a62019-03-07 20:34:33 -0500356 using QuicSession::closed_streams;
renjietang56d2ed22019-10-22 14:11:55 -0700357 using QuicSession::ShouldKeepConnectionAlive;
renjietange76b2da2019-05-13 14:50:23 -0700358 using QuicSpdySession::ProcessPendingStream;
359 using QuicSpdySession::UsesPendingStreams;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500360
361 private:
362 StrictMock<TestCryptoStream> crypto_stream_;
363
364 bool writev_consumes_all_data_;
365};
366
367class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
368 public:
fkastenholz3c4eabf2019-04-22 07:49:59 -0700369 bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
370 if (frame.type == MAX_STREAMS_FRAME) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500371 DeleteFrame(&const_cast<QuicFrame&>(frame));
372 return true;
373 }
374 return false;
375 }
376
377 protected:
378 explicit QuicSpdySessionTestBase(Perspective perspective)
379 : connection_(
380 new StrictMock<MockQuicConnection>(&helper_,
381 &alarm_factory_,
382 perspective,
383 SupportedVersions(GetParam()))),
384 session_(connection_) {
385 session_.config()->SetInitialStreamFlowControlWindowToSend(
386 kInitialStreamFlowControlWindowForTest);
387 session_.config()->SetInitialSessionFlowControlWindowToSend(
388 kInitialSessionFlowControlWindowForTest);
renjietanga29a96a2019-10-10 12:47:50 -0700389 if (VersionUsesHttp3(transport_version())) {
renjietange6d94672020-01-07 10:30:10 -0800390 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
renjietang241ba602020-04-29 13:29:46 -0700391 session_.config(), kHttp3StaticUnidirectionalStreamCount);
renjietang216dc012019-08-27 11:28:27 -0700392 }
renjietangbb2e22a2019-09-12 15:46:39 -0700393 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
394 session_.config(), kMinimumFlowControlSendWindow);
dschinazi18cdf132019-10-09 16:08:18 -0700395 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
396 session_.config(), kMinimumFlowControlSendWindow);
397 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesIncomingBidirectional(
398 session_.config(), kMinimumFlowControlSendWindow);
399 QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
400 session_.config(), kMinimumFlowControlSendWindow);
renjietangbb2e22a2019-09-12 15:46:39 -0700401 session_.OnConfigNegotiated();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500402 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
403 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
404 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
405 .Times(testing::AnyNumber());
renjietang7712ed72020-03-25 14:07:30 -0700406 writer_ = static_cast<MockPacketWriter*>(
407 QuicConnectionPeer::GetWriter(session_.connection()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500408 }
409
410 void CheckClosedStreams() {
QUICHE teamdc41bf12019-03-20 12:58:42 -0700411 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
renjietange47e15f2019-10-29 14:19:30 -0700412 transport_version(), Perspective::IS_CLIENT);
413 if (!QuicVersionUsesCryptoFrames(transport_version())) {
414 first_stream_id = QuicUtils::GetCryptoStreamId(transport_version());
QUICHE teamdc41bf12019-03-20 12:58:42 -0700415 }
416 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500417 if (!QuicContainsKey(closed_streams_, i)) {
418 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
419 } else {
420 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
421 }
422 }
423 }
424
425 void CloseStream(QuicStreamId id) {
fkastenholz305e1732019-06-18 05:01:22 -0700426 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500427 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -0700428 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500429 } else {
renjietangf8bde4b2020-10-02 13:25:08 -0700430 // IETF QUIC has two frames, RST_STREAM and STOP_SENDING
QUICHE teama6ef0a62019-03-07 20:34:33 -0500431 EXPECT_CALL(*connection_, SendControlFrame(_))
432 .Times(2)
bnc5b3c3be2019-06-25 10:37:09 -0700433 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500434 }
435 EXPECT_CALL(*connection_, OnStreamReset(id, _));
renjietangfcf3f182020-06-30 15:06:56 -0700436
437 // QPACK streams might write data upon stream reset. Let the test session
438 // handle the data.
439 session_.set_writev_consumes_all_data(true);
440
renjietangff4240d2020-07-01 06:19:55 -0700441 session_.ResetStream(id, QUIC_STREAM_CANCELLED);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500442 closed_streams_.insert(id);
443 }
444
445 QuicTransportVersion transport_version() const {
446 return connection_->transport_version();
447 }
448
QUICHE teama6ef0a62019-03-07 20:34:33 -0500449 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
450 return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
451 }
452
453 QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
renjietange47e15f2019-10-29 14:19:30 -0700454 return GetNthServerInitiatedBidirectionalStreamId(transport_version(), n);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500455 }
456
457 QuicStreamId IdDelta() {
renjietange47e15f2019-10-29 14:19:30 -0700458 return QuicUtils::StreamIdDelta(transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500459 }
460
renjietang3a1bb802019-06-11 10:42:41 -0700461 std::string EncodeSettings(const SettingsFrame& settings) {
renjietang3a1bb802019-06-11 10:42:41 -0700462 std::unique_ptr<char[]> buffer;
bnc46942722019-10-29 11:56:21 -0700463 auto header_length = HttpEncoder::SerializeSettingsFrame(settings, &buffer);
renjietang3a1bb802019-06-11 10:42:41 -0700464 return std::string(buffer.get(), header_length);
465 }
466
bncf6b86b22020-01-26 11:08:46 -0800467 std::string SerializePriorityUpdateFrame(
468 const PriorityUpdateFrame& priority_update) {
469 std::unique_ptr<char[]> priority_buffer;
470 QuicByteCount priority_frame_length =
471 HttpEncoder::SerializePriorityUpdateFrame(priority_update,
472 &priority_buffer);
473 return std::string(priority_buffer.get(), priority_frame_length);
474 }
475
bnc9a7a6732020-04-14 06:08:02 -0700476 std::string SerializeMaxPushIdFrame(PushId push_id) {
477 MaxPushIdFrame max_push_id_frame;
478 max_push_id_frame.push_id = push_id;
479 std::unique_ptr<char[]> buffer;
480 QuicByteCount frame_length =
481 HttpEncoder::SerializeMaxPushIdFrame(max_push_id_frame, &buffer);
482 return std::string(buffer.get(), frame_length);
483 }
484
fkastenholz3c4eabf2019-04-22 07:49:59 -0700485 QuicStreamId StreamCountToId(QuicStreamCount stream_count,
486 Perspective perspective,
487 bool bidirectional) {
488 // Calculate and build up stream ID rather than use
489 // GetFirst... because the test that relies on this method
490 // needs to do the stream count where #1 is 0/1/2/3, and not
491 // take into account that stream 0 is special.
492 QuicStreamId id =
fkastenholz305e1732019-06-18 05:01:22 -0700493 ((stream_count - 1) * QuicUtils::StreamIdDelta(transport_version()));
fkastenholz3c4eabf2019-04-22 07:49:59 -0700494 if (!bidirectional) {
495 id |= 0x2;
496 }
497 if (perspective == Perspective::IS_SERVER) {
498 id |= 0x1;
499 }
500 return id;
501 }
502
renjietang7712ed72020-03-25 14:07:30 -0700503 void CompleteHandshake() {
504 if (VersionHasIetfQuicFrames(transport_version())) {
505 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
506 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
507 }
dschinazi1f6aca82020-12-04 13:20:08 -0800508 if (connection_->version().UsesTls() &&
bnce4031262020-03-30 10:52:57 -0700509 connection_->perspective() == Perspective::IS_SERVER) {
dschinazi1f6aca82020-12-04 13:20:08 -0800510 // HANDSHAKE_DONE frame.
renjietang7712ed72020-03-25 14:07:30 -0700511 EXPECT_CALL(*connection_, SendControlFrame(_))
512 .WillOnce(Invoke(&ClearControlFrame));
513 }
514
515 CryptoHandshakeMessage message;
516 session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
517 testing::Mock::VerifyAndClearExpectations(writer_);
518 testing::Mock::VerifyAndClearExpectations(connection_);
519 }
520
QUICHE teama6ef0a62019-03-07 20:34:33 -0500521 MockQuicConnectionHelper helper_;
522 MockAlarmFactory alarm_factory_;
523 StrictMock<MockQuicConnection>* connection_;
524 TestSession session_;
525 std::set<QuicStreamId> closed_streams_;
renjietang7712ed72020-03-25 14:07:30 -0700526 MockPacketWriter* writer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500527};
528
529class QuicSpdySessionTestServer : public QuicSpdySessionTestBase {
530 protected:
531 QuicSpdySessionTestServer()
532 : QuicSpdySessionTestBase(Perspective::IS_SERVER) {}
533};
534
535INSTANTIATE_TEST_SUITE_P(Tests,
536 QuicSpdySessionTestServer,
dschinazi142051a2019-09-18 18:17:29 -0700537 ::testing::ValuesIn(AllSupportedVersions()),
538 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500539
renjietange76b2da2019-05-13 14:50:23 -0700540TEST_P(QuicSpdySessionTestServer, UsesPendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -0700541 if (!VersionUsesHttp3(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500542 return;
543 }
renjietangbb1c4892019-05-24 15:58:44 -0700544 EXPECT_TRUE(session_.UsesPendingStreams());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500545}
546
547TEST_P(QuicSpdySessionTestServer, PeerAddress) {
548 EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
549 session_.peer_address());
550}
551
552TEST_P(QuicSpdySessionTestServer, SelfAddress) {
553 EXPECT_TRUE(session_.self_address().IsInitialized());
554}
555
fayanga3d8df72020-01-14 11:54:39 -0800556TEST_P(QuicSpdySessionTestServer, OneRttKeysAvailable) {
fayanga3d8df72020-01-14 11:54:39 -0800557 EXPECT_FALSE(session_.OneRttKeysAvailable());
renjietang7712ed72020-03-25 14:07:30 -0700558 CompleteHandshake();
fayanga3d8df72020-01-14 11:54:39 -0800559 EXPECT_TRUE(session_.OneRttKeysAvailable());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500560}
561
562TEST_P(QuicSpdySessionTestServer, IsClosedStreamDefault) {
563 // Ensure that no streams are initially closed.
QUICHE teamdc41bf12019-03-20 12:58:42 -0700564 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
renjietange47e15f2019-10-29 14:19:30 -0700565 transport_version(), Perspective::IS_CLIENT);
566 if (!QuicVersionUsesCryptoFrames(transport_version())) {
567 first_stream_id = QuicUtils::GetCryptoStreamId(transport_version());
QUICHE teamdc41bf12019-03-20 12:58:42 -0700568 }
569 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500570 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
571 }
572}
573
574TEST_P(QuicSpdySessionTestServer, AvailableStreams) {
renjietang880d2432019-07-16 13:14:37 -0700575 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500576 GetNthClientInitiatedBidirectionalId(2)) != nullptr);
577 // Both client initiated streams with smaller stream IDs are available.
578 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
579 &session_, GetNthClientInitiatedBidirectionalId(0)));
580 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
581 &session_, GetNthClientInitiatedBidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -0700582 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500583 GetNthClientInitiatedBidirectionalId(1)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -0700584 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500585 GetNthClientInitiatedBidirectionalId(0)) != nullptr);
586}
587
588TEST_P(QuicSpdySessionTestServer, IsClosedStreamLocallyCreated) {
fayang29ce0bd2020-10-29 08:28:44 -0700589 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500590 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
591 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id());
592 QuicSpdyStream* stream4 = session_.CreateOutgoingBidirectionalStream();
593 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(1), stream4->id());
594
595 CheckClosedStreams();
596 CloseStream(GetNthServerInitiatedBidirectionalId(0));
597 CheckClosedStreams();
598 CloseStream(GetNthServerInitiatedBidirectionalId(1));
599 CheckClosedStreams();
600}
601
602TEST_P(QuicSpdySessionTestServer, IsClosedStreamPeerCreated) {
fayang29ce0bd2020-10-29 08:28:44 -0700603 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500604 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
605 QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
renjietang880d2432019-07-16 13:14:37 -0700606 session_.GetOrCreateStream(stream_id1);
607 session_.GetOrCreateStream(stream_id2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500608
609 CheckClosedStreams();
610 CloseStream(stream_id1);
611 CheckClosedStreams();
612 CloseStream(stream_id2);
613 // Create a stream, and make another available.
renjietang880d2432019-07-16 13:14:37 -0700614 QuicStream* stream3 = session_.GetOrCreateStream(stream_id2 + 4);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500615 CheckClosedStreams();
616 // Close one, but make sure the other is still not closed
617 CloseStream(stream3->id());
618 CheckClosedStreams();
619}
620
621TEST_P(QuicSpdySessionTestServer, MaximumAvailableOpenedStreams) {
fkastenholz305e1732019-06-18 05:01:22 -0700622 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500623 // For IETF QUIC, we should be able to obtain the max allowed
624 // stream ID, the next ID should fail. Since the actual limit
625 // is not the number of open streams, we allocate the max and the max+2.
626 // Get the max allowed stream ID, this should succeed.
fkastenholz3c4eabf2019-04-22 07:49:59 -0700627 QuicStreamId stream_id = StreamCountToId(
renjietangf8bde4b2020-10-02 13:25:08 -0700628 QuicSessionPeer::ietf_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -0700629 ->max_incoming_bidirectional_streams(),
fkastenholz3c4eabf2019-04-22 07:49:59 -0700630 Perspective::IS_CLIENT, // Client initates stream, allocs stream id.
631 /*bidirectional=*/true);
renjietang880d2432019-07-16 13:14:37 -0700632 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
renjietangf8bde4b2020-10-02 13:25:08 -0700633 stream_id =
634 StreamCountToId(QuicSessionPeer::ietf_streamid_manager(&session_)
635 ->max_incoming_unidirectional_streams(),
636 Perspective::IS_CLIENT,
637 /*bidirectional=*/false);
renjietang880d2432019-07-16 13:14:37 -0700638 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholz3c4eabf2019-04-22 07:49:59 -0700639 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(2);
640 // Get the (max allowed stream ID)++. These should all fail.
renjietangf8bde4b2020-10-02 13:25:08 -0700641 stream_id =
642 StreamCountToId(QuicSessionPeer::ietf_streamid_manager(&session_)
643 ->max_incoming_bidirectional_streams() +
644 1,
645 Perspective::IS_CLIENT,
646 /*bidirectional=*/true);
renjietang880d2432019-07-16 13:14:37 -0700647 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id));
fkastenholz3c4eabf2019-04-22 07:49:59 -0700648
ianswettd1414532019-09-18 20:12:59 -0700649 stream_id =
renjietangf8bde4b2020-10-02 13:25:08 -0700650 StreamCountToId(QuicSessionPeer::ietf_streamid_manager(&session_)
ianswettd1414532019-09-18 20:12:59 -0700651 ->max_incoming_unidirectional_streams() +
652 1,
653 Perspective::IS_CLIENT,
654 /*bidirectional=*/false);
renjietang880d2432019-07-16 13:14:37 -0700655 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500656 } else {
657 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
renjietang880d2432019-07-16 13:14:37 -0700658 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500659 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
660 EXPECT_NE(
661 nullptr,
renjietang880d2432019-07-16 13:14:37 -0700662 session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500663 stream_id +
664 IdDelta() *
665 (session_.max_open_incoming_bidirectional_streams() - 1)));
666 }
667}
668
669TEST_P(QuicSpdySessionTestServer, TooManyAvailableStreams) {
670 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
671 QuicStreamId stream_id2;
renjietang880d2432019-07-16 13:14:37 -0700672 EXPECT_NE(nullptr, session_.GetOrCreateStream(stream_id1));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500673 // A stream ID which is too large to create.
674 stream_id2 = GetNthClientInitiatedBidirectionalId(
675 2 * session_.MaxAvailableBidirectionalStreams() + 4);
fkastenholz305e1732019-06-18 05:01:22 -0700676 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500677 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
678 } else {
679 EXPECT_CALL(*connection_,
680 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
681 }
renjietang880d2432019-07-16 13:14:37 -0700682 EXPECT_EQ(nullptr, session_.GetOrCreateStream(stream_id2));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500683}
684
685TEST_P(QuicSpdySessionTestServer, ManyAvailableStreams) {
686 // When max_open_streams_ is 200, should be able to create 200 streams
687 // out-of-order, that is, creating the one with the largest stream ID first.
fkastenholz305e1732019-06-18 05:01:22 -0700688 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700689 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
690 } else {
691 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
692 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500693 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
694 // Create one stream.
renjietang880d2432019-07-16 13:14:37 -0700695 session_.GetOrCreateStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500696 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
697 // Stream count is 200, GetNth... starts counting at 0, so the 200'th stream
fkastenholz3c4eabf2019-04-22 07:49:59 -0700698 // is 199. BUT actually we need to do 198 because the crypto stream (Stream
699 // ID 0) has not been registered, but GetNth... assumes that it has.
renjietang880d2432019-07-16 13:14:37 -0700700 EXPECT_NE(nullptr, session_.GetOrCreateStream(
fkastenholz3c4eabf2019-04-22 07:49:59 -0700701 GetNthClientInitiatedBidirectionalId(198)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500702}
703
704TEST_P(QuicSpdySessionTestServer,
705 DebugDFatalIfMarkingClosedStreamWriteBlocked) {
dschinazi1e41d212020-03-31 15:55:25 -0700706 CompleteHandshake();
707 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
708 .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500709
710 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
711 QuicStreamId closed_stream_id = stream2->id();
712 // Close the stream.
713 EXPECT_CALL(*connection_, SendControlFrame(_));
714 EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
715 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
vasilvva163b382020-12-04 11:47:46 -0800716 std::string msg =
717 absl::StrCat("Marking unknown stream ", closed_stream_id, " blocked.");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500718 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
719 msg);
720}
721
722TEST_P(QuicSpdySessionTestServer, OnCanWrite) {
fayanga61d1ce2020-10-27 11:05:44 -0700723 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500724 session_.set_writev_consumes_all_data(true);
725 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
726 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
727 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
728
729 session_.MarkConnectionLevelWriteBlocked(stream2->id());
730 session_.MarkConnectionLevelWriteBlocked(stream6->id());
731 session_.MarkConnectionLevelWriteBlocked(stream4->id());
732
733 InSequence s;
734
735 // Reregister, to test the loop limit.
736 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
737 session_.SendStreamData(stream2);
738 session_.MarkConnectionLevelWriteBlocked(stream2->id());
739 }));
740 // 2 will get called a second time as it didn't finish its block
741 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
742 session_.SendStreamData(stream2);
743 }));
744 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
745 session_.SendStreamData(stream6);
746 }));
747 // 4 will not get called, as we exceeded the loop limit.
748 session_.OnCanWrite();
749 EXPECT_TRUE(session_.WillingAndAbleToWrite());
750}
751
renjietange358ac42020-03-23 17:26:54 -0700752TEST_P(QuicSpdySessionTestServer, TooLargeStreamBlocked) {
753 // STREAMS_BLOCKED frame is IETF QUIC only.
754 if (!VersionUsesHttp3(transport_version())) {
755 return;
756 }
757
renjietang7712ed72020-03-25 14:07:30 -0700758 CompleteHandshake();
renjietange358ac42020-03-23 17:26:54 -0700759 StrictMock<MockHttp3DebugVisitor> debug_visitor;
760 session_.set_debug_visitor(&debug_visitor);
renjietange358ac42020-03-23 17:26:54 -0700761
762 // Simualte the situation where the incoming stream count is at its limit and
763 // the peer is blocked.
764 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
765 static_cast<QuicSession*>(&session_), QuicUtils::GetMaxStreamCount());
766 QuicStreamsBlockedFrame frame;
767 frame.stream_count = QuicUtils::GetMaxStreamCount();
renjietang7712ed72020-03-25 14:07:30 -0700768 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
769 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
renjietange358ac42020-03-23 17:26:54 -0700770 EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(_));
771 session_.OnStreamsBlockedFrame(frame);
772}
773
QUICHE teama6ef0a62019-03-07 20:34:33 -0500774TEST_P(QuicSpdySessionTestServer, TestBatchedWrites) {
775 session_.set_writev_consumes_all_data(true);
776 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
777 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
778 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
779
780 session_.set_writev_consumes_all_data(true);
781 session_.MarkConnectionLevelWriteBlocked(stream2->id());
782 session_.MarkConnectionLevelWriteBlocked(stream4->id());
783
784 // With two sessions blocked, we should get two write calls. They should both
785 // go to the first stream as it will only write 6k and mark itself blocked
786 // again.
787 InSequence s;
788 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
789 session_.SendLargeFakeData(stream2, 6000);
790 session_.MarkConnectionLevelWriteBlocked(stream2->id());
791 }));
792 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
793 session_.SendLargeFakeData(stream2, 6000);
794 session_.MarkConnectionLevelWriteBlocked(stream2->id());
795 }));
796 session_.OnCanWrite();
797
798 // We should get one more call for stream2, at which point it has used its
799 // write quota and we move over to stream 4.
800 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
801 session_.SendLargeFakeData(stream2, 6000);
802 session_.MarkConnectionLevelWriteBlocked(stream2->id());
803 }));
804 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
805 session_.SendLargeFakeData(stream4, 6000);
806 session_.MarkConnectionLevelWriteBlocked(stream4->id());
807 }));
808 session_.OnCanWrite();
809
810 // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
811 // priority stream 6. 4 should be preempted. 6 will write but *not* block so
812 // will cede back to 4.
fayang476683a2019-07-25 12:42:16 -0700813 stream6->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500814 EXPECT_CALL(*stream4, OnCanWrite())
815 .WillOnce(Invoke([this, stream4, stream6]() {
816 session_.SendLargeFakeData(stream4, 6000);
817 session_.MarkConnectionLevelWriteBlocked(stream4->id());
818 session_.MarkConnectionLevelWriteBlocked(stream6->id());
819 }));
820 EXPECT_CALL(*stream6, OnCanWrite())
821 .WillOnce(Invoke([this, stream4, stream6]() {
822 session_.SendStreamData(stream6);
823 session_.SendLargeFakeData(stream4, 6000);
824 }));
825 session_.OnCanWrite();
826
827 // Stream4 alread did 6k worth of writes, so after doing another 12k it should
828 // cede and 2 should resume.
829 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
830 session_.SendLargeFakeData(stream4, 12000);
831 session_.MarkConnectionLevelWriteBlocked(stream4->id());
832 }));
833 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
834 session_.SendLargeFakeData(stream2, 6000);
835 session_.MarkConnectionLevelWriteBlocked(stream2->id());
836 }));
837 session_.OnCanWrite();
838}
839
840TEST_P(QuicSpdySessionTestServer, OnCanWriteBundlesStreams) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500841 // Encryption needs to be established before data can be sent.
renjietang7712ed72020-03-25 14:07:30 -0700842 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500843
844 // Drive congestion control manually.
845 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
846 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
847
848 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
849 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
850 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
851
852 session_.MarkConnectionLevelWriteBlocked(stream2->id());
853 session_.MarkConnectionLevelWriteBlocked(stream6->id());
854 session_.MarkConnectionLevelWriteBlocked(stream4->id());
855
856 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
857 EXPECT_CALL(*send_algorithm, GetCongestionWindow())
dschinazi66dea072019-04-09 11:41:06 -0700858 .WillRepeatedly(Return(kMaxOutgoingPacketSize * 10));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500859 EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
860 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
861 session_.SendStreamData(stream2);
862 }));
863 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
864 session_.SendStreamData(stream4);
865 }));
866 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
867 session_.SendStreamData(stream6);
868 }));
869
870 // Expect that we only send one packet, the writes from different streams
871 // should be bundled together.
renjietang7712ed72020-03-25 14:07:30 -0700872 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500873 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
874 EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
875 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
876 session_.OnCanWrite();
877 EXPECT_FALSE(session_.WillingAndAbleToWrite());
878}
879
880TEST_P(QuicSpdySessionTestServer, OnCanWriteCongestionControlBlocks) {
fayanga61d1ce2020-10-27 11:05:44 -0700881 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500882 session_.set_writev_consumes_all_data(true);
883 InSequence s;
884
885 // Drive congestion control manually.
886 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
887 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
888
889 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
890 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
891 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
892
893 session_.MarkConnectionLevelWriteBlocked(stream2->id());
894 session_.MarkConnectionLevelWriteBlocked(stream6->id());
895 session_.MarkConnectionLevelWriteBlocked(stream4->id());
896
897 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
898 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
899 session_.SendStreamData(stream2);
900 }));
dschinazi101d2eb2020-07-06 19:42:34 -0700901 EXPECT_CALL(*send_algorithm, GetCongestionWindow()).Times(AnyNumber());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500902 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
903 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
904 session_.SendStreamData(stream6);
905 }));
906 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
907 // stream4->OnCanWrite is not called.
908
909 session_.OnCanWrite();
910 EXPECT_TRUE(session_.WillingAndAbleToWrite());
911
912 // Still congestion-control blocked.
913 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
914 session_.OnCanWrite();
915 EXPECT_TRUE(session_.WillingAndAbleToWrite());
916
917 // stream4->OnCanWrite is called once the connection stops being
918 // congestion-control blocked.
919 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
920 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
921 session_.SendStreamData(stream4);
922 }));
923 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
924 session_.OnCanWrite();
925 EXPECT_FALSE(session_.WillingAndAbleToWrite());
926}
927
928TEST_P(QuicSpdySessionTestServer, OnCanWriteWriterBlocks) {
fayanga61d1ce2020-10-27 11:05:44 -0700929 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500930 // Drive congestion control manually in order to ensure that
931 // application-limited signaling is handled correctly.
932 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
933 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
934 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
935
936 // Drive packet writer manually.
renjietang7712ed72020-03-25 14:07:30 -0700937 EXPECT_CALL(*writer_, IsWriteBlocked()).WillRepeatedly(Return(true));
938 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _)).Times(0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500939
940 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
941
942 session_.MarkConnectionLevelWriteBlocked(stream2->id());
943
944 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
945 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)).Times(0);
946
947 session_.OnCanWrite();
948 EXPECT_TRUE(session_.WillingAndAbleToWrite());
949}
950
951TEST_P(QuicSpdySessionTestServer, BufferedHandshake) {
nharperd5c4a932019-05-13 13:58:49 -0700952 // This tests prioritization of the crypto stream when flow control limits are
953 // reached. When CRYPTO frames are in use, there is no flow control for the
954 // crypto handshake, so this test is irrelevant.
renjietange47e15f2019-10-29 14:19:30 -0700955 if (QuicVersionUsesCryptoFrames(transport_version())) {
nharperd5c4a932019-05-13 13:58:49 -0700956 return;
957 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500958 session_.set_writev_consumes_all_data(true);
959 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
960
961 // Test that blocking other streams does not change our status.
962 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
963 session_.MarkConnectionLevelWriteBlocked(stream2->id());
964 EXPECT_FALSE(session_.HasPendingHandshake());
965
966 TestStream* stream3 = session_.CreateOutgoingBidirectionalStream();
967 session_.MarkConnectionLevelWriteBlocked(stream3->id());
968 EXPECT_FALSE(session_.HasPendingHandshake());
969
970 // Blocking (due to buffering of) the Crypto stream is detected.
971 session_.MarkConnectionLevelWriteBlocked(
renjietange47e15f2019-10-29 14:19:30 -0700972 QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500973 EXPECT_TRUE(session_.HasPendingHandshake());
974
975 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
976 session_.MarkConnectionLevelWriteBlocked(stream4->id());
977 EXPECT_TRUE(session_.HasPendingHandshake());
978
979 InSequence s;
980 // Force most streams to re-register, which is common scenario when we block
981 // the Crypto stream, and only the crypto stream can "really" write.
982
983 // Due to prioritization, we *should* be asked to write the crypto stream
984 // first.
985 // Don't re-register the crypto stream (which signals complete writing).
986 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
987 EXPECT_CALL(*crypto_stream, OnCanWrite());
988
989 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
990 session_.SendStreamData(stream2);
991 }));
992 EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(Invoke([this, stream3]() {
993 session_.SendStreamData(stream3);
994 }));
995 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
996 session_.SendStreamData(stream4);
997 session_.MarkConnectionLevelWriteBlocked(stream4->id());
998 }));
999
1000 session_.OnCanWrite();
1001 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1002 EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
1003}
1004
1005TEST_P(QuicSpdySessionTestServer, OnCanWriteWithClosedStream) {
fayang29ce0bd2020-10-29 08:28:44 -07001006 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001007 session_.set_writev_consumes_all_data(true);
1008 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1009 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1010 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1011
1012 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1013 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1014 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1015 CloseStream(stream6->id());
1016
1017 InSequence s;
1018 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001019 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001020 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
1021 session_.SendStreamData(stream2);
1022 }));
1023 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
1024 session_.SendStreamData(stream4);
1025 }));
1026 session_.OnCanWrite();
1027 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1028}
1029
1030TEST_P(QuicSpdySessionTestServer,
1031 OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
fayanga61d1ce2020-10-27 11:05:44 -07001032 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001033 // Drive congestion control manually in order to ensure that
1034 // application-limited signaling is handled correctly.
1035 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1036 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1037 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
1038
1039 // Ensure connection level flow control blockage.
1040 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
1041 EXPECT_TRUE(session_.flow_controller()->IsBlocked());
1042 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1043 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1044
1045 // Mark the crypto and headers streams as write blocked, we expect them to be
1046 // allowed to write later.
renjietange47e15f2019-10-29 14:19:30 -07001047 if (!QuicVersionUsesCryptoFrames(transport_version())) {
nharperd5c4a932019-05-13 13:58:49 -07001048 session_.MarkConnectionLevelWriteBlocked(
renjietange47e15f2019-10-29 14:19:30 -07001049 QuicUtils::GetCryptoStreamId(transport_version()));
nharperd5c4a932019-05-13 13:58:49 -07001050 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001051
1052 // Create a data stream, and although it is write blocked we never expect it
1053 // to be allowed to write as we are connection level flow control blocked.
1054 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1055 session_.MarkConnectionLevelWriteBlocked(stream->id());
1056 EXPECT_CALL(*stream, OnCanWrite()).Times(0);
1057
1058 // The crypto and headers streams should be called even though we are
1059 // connection flow control blocked.
renjietange47e15f2019-10-29 14:19:30 -07001060 if (!QuicVersionUsesCryptoFrames(transport_version())) {
nharperd5c4a932019-05-13 13:58:49 -07001061 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1062 EXPECT_CALL(*crypto_stream, OnCanWrite());
1063 }
renjietangb663b862019-07-08 16:02:39 -07001064
renjietange47e15f2019-10-29 14:19:30 -07001065 if (!VersionUsesHttp3(transport_version())) {
renjietang118c8ac2019-07-30 11:43:59 -07001066 TestHeadersStream* headers_stream;
1067 QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
1068 headers_stream = new TestHeadersStream(&session_);
1069 QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
1070 session_.MarkConnectionLevelWriteBlocked(
renjietange47e15f2019-10-29 14:19:30 -07001071 QuicUtils::GetHeadersStreamId(transport_version()));
renjietang118c8ac2019-07-30 11:43:59 -07001072 EXPECT_CALL(*headers_stream, OnCanWrite());
1073 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001074
1075 // After the crypto and header streams perform a write, the connection will be
1076 // blocked by the flow control, hence it should become application-limited.
1077 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1078
1079 session_.OnCanWrite();
1080 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1081}
1082
1083TEST_P(QuicSpdySessionTestServer, SendGoAway) {
fayang29ce0bd2020-10-29 08:28:44 -07001084 CompleteHandshake();
fkastenholz305e1732019-06-18 05:01:22 -07001085 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001086 // HTTP/3 GOAWAY has different semantic and thus has its own test.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001087 return;
1088 }
fayang93cc53a2019-08-22 12:47:30 -07001089 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
renjietang7712ed72020-03-25 14:07:30 -07001090 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001091 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1092
1093 EXPECT_CALL(*connection_, SendControlFrame(_))
1094 .WillOnce(
1095 Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
1096 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1097 EXPECT_TRUE(session_.goaway_sent());
1098
1099 const QuicStreamId kTestStreamId = 5u;
1100 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1101 EXPECT_CALL(*connection_,
1102 OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
1103 .Times(0);
renjietang880d2432019-07-16 13:14:37 -07001104 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001105}
1106
fayangb6daf212020-12-08 12:00:40 -08001107TEST_P(QuicSpdySessionTestServer, SendGoAwayWithoutEncryption) {
1108 SetQuicReloadableFlag(quic_encrypted_goaway, true);
1109 if (VersionHasIetfQuicFrames(transport_version())) {
1110 // HTTP/3 GOAWAY has different semantic and thus has its own test.
1111 return;
1112 }
1113 EXPECT_CALL(
1114 *connection_,
1115 CloseConnection(QUIC_PEER_GOING_AWAY, "Going Away.",
1116 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1117 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1118 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1119 EXPECT_FALSE(session_.goaway_sent());
1120}
1121
renjietang686ce582019-10-17 14:28:16 -07001122TEST_P(QuicSpdySessionTestServer, SendHttp3GoAway) {
1123 if (!VersionUsesHttp3(transport_version())) {
1124 return;
1125 }
bncb9d5e792020-03-20 17:43:41 -07001126
renjietang7712ed72020-03-25 14:07:30 -07001127 CompleteHandshake();
bncb9d5e792020-03-20 17:43:41 -07001128 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1129 session_.set_debug_visitor(&debug_visitor);
1130
renjietang7712ed72020-03-25 14:07:30 -07001131 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
1132 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
bnc01aa36e2020-11-11 08:26:27 -08001133 if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
1134 // Send max stream id (currently 32 bits).
1135 EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0xfffffffc));
1136 } else {
1137 // No client-initiated stream has been received, therefore a GOAWAY frame
1138 // with stream ID = 0 is sent to notify the client that all requests can be
1139 // retried on a different connection.
1140 EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0));
1141 }
fayangb6daf212020-12-08 12:00:40 -08001142 session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
bnc3988f572020-08-27 05:27:04 -07001143 EXPECT_TRUE(session_.goaway_sent());
renjietang686ce582019-10-17 14:28:16 -07001144
bnc01aa36e2020-11-11 08:26:27 -08001145 // New incoming stream is not reset.
renjietang686ce582019-10-17 14:28:16 -07001146 const QuicStreamId kTestStreamId =
1147 GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
1148 EXPECT_CALL(*connection_, OnStreamReset(kTestStreamId, _)).Times(0);
1149 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
bnc01aa36e2020-11-11 08:26:27 -08001150
1151 // No more GOAWAY frames are sent because they could not convey new
1152 // information to the client.
fayangb6daf212020-12-08 12:00:40 -08001153 session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
1154}
1155
1156TEST_P(QuicSpdySessionTestServer, SendHttp3GoAwayWithoutEncryption) {
1157 SetQuicReloadableFlag(quic_encrypted_goaway, true);
1158 if (!VersionUsesHttp3(transport_version())) {
1159 return;
1160 }
1161 EXPECT_CALL(
1162 *connection_,
1163 CloseConnection(QUIC_PEER_GOING_AWAY, "Goaway",
1164 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1165 session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
1166 EXPECT_FALSE(session_.goaway_sent());
renjietang686ce582019-10-17 14:28:16 -07001167}
1168
bncf3d32412020-09-09 18:21:03 -07001169TEST_P(QuicSpdySessionTestServer, SendHttp3GoAwayAfterStreamIsCreated) {
1170 if (!VersionUsesHttp3(transport_version())) {
1171 return;
1172 }
1173
bncf3d32412020-09-09 18:21:03 -07001174 CompleteHandshake();
1175 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1176 session_.set_debug_visitor(&debug_visitor);
1177
1178 const QuicStreamId kTestStreamId =
1179 GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
1180 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
1181
1182 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
1183 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
bnc01aa36e2020-11-11 08:26:27 -08001184 if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
1185 // Send max stream id (currently 32 bits).
1186 EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0xfffffffc));
1187 } else {
1188 // The first stream, of kTestStreamId = 0, could already have been
1189 // processed. A GOAWAY frame is sent to notify the client that requests
1190 // starting with stream ID = 4 can be retried on a different connection.
1191 EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 4));
1192 }
fayangb6daf212020-12-08 12:00:40 -08001193 session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
bncf3d32412020-09-09 18:21:03 -07001194 EXPECT_TRUE(session_.goaway_sent());
1195
1196 // No more GOAWAY frames are sent because they could not convey new
1197 // information to the client.
fayangb6daf212020-12-08 12:00:40 -08001198 session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
bncf3d32412020-09-09 18:21:03 -07001199}
1200
QUICHE team63eb43a2020-09-02 15:12:29 -07001201TEST_P(QuicSpdySessionTestServer, SendHttp3Shutdown) {
bnc01aa36e2020-11-11 08:26:27 -08001202 if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
1203 return;
1204 }
1205
QUICHE team63eb43a2020-09-02 15:12:29 -07001206 if (!VersionUsesHttp3(transport_version())) {
1207 return;
1208 }
1209
1210 CompleteHandshake();
1211 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1212 session_.set_debug_visitor(&debug_visitor);
1213
1214 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
1215 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1216 EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(_));
1217 session_.SendHttp3Shutdown();
1218 EXPECT_TRUE(session_.goaway_sent());
1219
1220 const QuicStreamId kTestStreamId =
1221 GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
1222 EXPECT_CALL(*connection_, OnStreamReset(kTestStreamId, _)).Times(0);
1223 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
1224}
1225
1226TEST_P(QuicSpdySessionTestServer, SendHttp3GoAwayAfterShutdownNotice) {
bnc01aa36e2020-11-11 08:26:27 -08001227 if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
1228 return;
1229 }
1230
QUICHE team63eb43a2020-09-02 15:12:29 -07001231 if (!VersionUsesHttp3(transport_version())) {
1232 return;
1233 }
1234
1235 CompleteHandshake();
1236 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1237 session_.set_debug_visitor(&debug_visitor);
1238
1239 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
1240 .Times(2)
1241 .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
1242 EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(_)).Times(2);
1243
1244 session_.SendHttp3Shutdown();
1245 EXPECT_TRUE(session_.goaway_sent());
fayangb6daf212020-12-08 12:00:40 -08001246 session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
QUICHE team63eb43a2020-09-02 15:12:29 -07001247
1248 const QuicStreamId kTestStreamId =
1249 GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
1250 EXPECT_CALL(*connection_, OnStreamReset(kTestStreamId, _)).Times(0);
1251 EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
1252}
1253
QUICHE teama6ef0a62019-03-07 20:34:33 -05001254TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
fayang29ce0bd2020-10-29 08:28:44 -07001255 CompleteHandshake();
fkastenholz305e1732019-06-18 05:01:22 -07001256 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001257 // HTTP/3 GOAWAY doesn't have such restriction.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001258 return;
1259 }
1260 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001261 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001262 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1263 EXPECT_TRUE(session_.goaway_sent());
1264 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
1265}
1266
1267TEST_P(QuicSpdySessionTestServer, InvalidGoAway) {
fkastenholz305e1732019-06-18 05:01:22 -07001268 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang686ce582019-10-17 14:28:16 -07001269 // HTTP/3 GOAWAY has different semantics and thus has its own test.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001270 return;
1271 }
1272 QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
1273 session_.next_outgoing_bidirectional_stream_id(), "");
1274 session_.OnGoAway(go_away);
1275}
1276
bncaf8e3302020-07-27 07:42:59 -07001277TEST_P(QuicSpdySessionTestServer, Http3GoAwayLargerIdThanBefore) {
1278 if (!VersionUsesHttp3(transport_version())) {
1279 return;
1280 }
bncaf8e3302020-07-27 07:42:59 -07001281
bnc3988f572020-08-27 05:27:04 -07001282 EXPECT_FALSE(session_.goaway_received());
bncaf8e3302020-07-27 07:42:59 -07001283 PushId push_id1 = 0;
1284 session_.OnHttp3GoAway(push_id1);
bnc3988f572020-08-27 05:27:04 -07001285 EXPECT_TRUE(session_.goaway_received());
bncaf8e3302020-07-27 07:42:59 -07001286
1287 EXPECT_CALL(
1288 *connection_,
1289 CloseConnection(
1290 QUIC_HTTP_GOAWAY_ID_LARGER_THAN_PREVIOUS,
1291 "GOAWAY received with ID 1 greater than previously received ID 0",
1292 _));
1293 PushId push_id2 = 1;
1294 session_.OnHttp3GoAway(push_id2);
1295}
1296
QUICHE teama6ef0a62019-03-07 20:34:33 -05001297// Test that server session will send a connectivity probe in response to a
1298// connectivity probe on the same path.
1299TEST_P(QuicSpdySessionTestServer, ServerReplyToConnecitivityProbe) {
danzh353c9f02021-01-13 09:36:04 -08001300 if (VersionHasIetfQuicFrames(transport_version()) &&
1301 connection_->send_path_response()) {
1302 return;
1303 }
danzh8a27a1a2020-09-02 10:26:28 -07001304 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001305 QuicSocketAddress old_peer_address =
1306 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1307 EXPECT_EQ(old_peer_address, session_.peer_address());
1308
1309 QuicSocketAddress new_peer_address =
1310 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort + 1);
1311
danzh8a27a1a2020-09-02 10:26:28 -07001312 if (connection_->send_path_response()) {
1313 EXPECT_CALL(*connection_,
1314 SendConnectivityProbingPacket(nullptr, new_peer_address));
1315 } else {
1316 EXPECT_CALL(*connection_,
1317 SendConnectivityProbingResponsePacket(new_peer_address));
1318 }
1319
fkastenholz305e1732019-06-18 05:01:22 -07001320 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001321 // Need to explicitly do this to emulate the reception of a PathChallenge,
1322 // which stores its payload for use in generating the response.
1323 connection_->OnPathChallengeFrame(
1324 QuicPathChallengeFrame(0, {{0, 1, 2, 3, 4, 5, 6, 7}}));
1325 }
zhongyi83161e42019-08-19 09:06:25 -07001326 session_.OnPacketReceived(session_.self_address(), new_peer_address,
1327 /*is_connectivity_probe=*/true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001328 EXPECT_EQ(old_peer_address, session_.peer_address());
1329}
1330
1331TEST_P(QuicSpdySessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
1332 EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
1333 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
renjietang7712ed72020-03-25 14:07:30 -07001334 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001335 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
1336 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1337}
1338
1339TEST_P(QuicSpdySessionTestServer, RstStreamBeforeHeadersDecompressed) {
renjietang7712ed72020-03-25 14:07:30 -07001340 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001341 // Send two bytes of payload.
1342 QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
vasilvve2707e32020-10-08 12:27:46 -07001343 absl::string_view("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001344 session_.OnStreamFrame(data1);
fayang01591ae2020-04-23 14:14:56 -07001345 EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001346
fkastenholz305e1732019-06-18 05:01:22 -07001347 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001348 // For version99, OnStreamReset gets called because of the STOP_SENDING,
1349 // below. EXPECT the call there.
1350 EXPECT_CALL(*connection_,
1351 OnStreamReset(GetNthClientInitiatedBidirectionalId(0), _));
1352 }
renjietang7712ed72020-03-25 14:07:30 -07001353
1354 // In HTTP/3, Qpack stream will send data on stream reset and cause packet to
1355 // be flushed.
1356 if (VersionUsesHttp3(transport_version())) {
1357 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
1358 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
1359 }
1360 EXPECT_CALL(*connection_, SendControlFrame(_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001361 QuicRstStreamFrame rst1(kInvalidControlFrameId,
1362 GetNthClientInitiatedBidirectionalId(0),
1363 QUIC_ERROR_PROCESSING_STREAM, 0);
1364 session_.OnRstStream(rst1);
1365
1366 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
1367 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
1368 // one-way close.
fkastenholz305e1732019-06-18 05:01:22 -07001369 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001370 // Only needed for version 99/IETF QUIC.
bnc187eea32020-09-02 12:16:15 -07001371 QuicStopSendingFrame stop_sending(kInvalidControlFrameId,
1372 GetNthClientInitiatedBidirectionalId(0),
1373 QUIC_ERROR_PROCESSING_STREAM);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001374 // Expect the RESET_STREAM that is generated in response to receiving a
1375 // STOP_SENDING.
1376 EXPECT_CALL(*connection_,
1377 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
1378 QUIC_ERROR_PROCESSING_STREAM));
1379 session_.OnStopSendingFrame(stop_sending);
1380 }
1381
fayang01591ae2020-04-23 14:14:56 -07001382 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001383 // Connection should remain alive.
1384 EXPECT_TRUE(connection_->connected());
1385}
1386
1387TEST_P(QuicSpdySessionTestServer, OnStreamFrameFinStaticStreamId) {
renjietang118c8ac2019-07-30 11:43:59 -07001388 QuicStreamId id;
1389 // Initialize HTTP/3 control stream.
renjietanga29a96a2019-10-10 12:47:50 -07001390 if (VersionUsesHttp3(transport_version())) {
renjietang118c8ac2019-07-30 11:43:59 -07001391 id = GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
1392 char type[] = {kControlStream};
1393
vasilvve2707e32020-10-08 12:27:46 -07001394 QuicStreamFrame data1(id, false, 0, absl::string_view(type, 1));
renjietang118c8ac2019-07-30 11:43:59 -07001395 session_.OnStreamFrame(data1);
1396 } else {
renjietange47e15f2019-10-29 14:19:30 -07001397 id = QuicUtils::GetHeadersStreamId(transport_version());
renjietang118c8ac2019-07-30 11:43:59 -07001398 }
1399
QUICHE teama6ef0a62019-03-07 20:34:33 -05001400 // Send two bytes of payload.
vasilvve2707e32020-10-08 12:27:46 -07001401 QuicStreamFrame data1(id, true, 0, absl::string_view("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001402 EXPECT_CALL(*connection_,
1403 CloseConnection(
1404 QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
1405 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1406 session_.OnStreamFrame(data1);
1407}
1408
1409TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
renjietang118c8ac2019-07-30 11:43:59 -07001410 QuicStreamId id;
bnc09c1eda2020-03-13 04:52:38 -07001411 QuicErrorCode expected_error;
renjietang546c7142020-03-05 14:12:10 -08001412 std::string error_message;
renjietang118c8ac2019-07-30 11:43:59 -07001413 // Initialize HTTP/3 control stream.
renjietanga29a96a2019-10-10 12:47:50 -07001414 if (VersionUsesHttp3(transport_version())) {
renjietang118c8ac2019-07-30 11:43:59 -07001415 id = GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
1416 char type[] = {kControlStream};
1417
vasilvve2707e32020-10-08 12:27:46 -07001418 QuicStreamFrame data1(id, false, 0, absl::string_view(type, 1));
renjietang118c8ac2019-07-30 11:43:59 -07001419 session_.OnStreamFrame(data1);
bnc09c1eda2020-03-13 04:52:38 -07001420 expected_error = QUIC_HTTP_CLOSED_CRITICAL_STREAM;
1421 error_message = "RESET_STREAM received for receive control stream";
renjietang118c8ac2019-07-30 11:43:59 -07001422 } else {
renjietange47e15f2019-10-29 14:19:30 -07001423 id = QuicUtils::GetHeadersStreamId(transport_version());
bnc09c1eda2020-03-13 04:52:38 -07001424 expected_error = QUIC_INVALID_STREAM_ID;
renjietang546c7142020-03-05 14:12:10 -08001425 error_message = "Attempt to reset headers stream";
renjietang118c8ac2019-07-30 11:43:59 -07001426 }
1427
QUICHE teama6ef0a62019-03-07 20:34:33 -05001428 // Send two bytes of payload.
renjietang118c8ac2019-07-30 11:43:59 -07001429 QuicRstStreamFrame rst1(kInvalidControlFrameId, id,
1430 QUIC_ERROR_PROCESSING_STREAM, 0);
renjietang546c7142020-03-05 14:12:10 -08001431 EXPECT_CALL(
1432 *connection_,
bnc09c1eda2020-03-13 04:52:38 -07001433 CloseConnection(expected_error, error_message,
renjietang546c7142020-03-05 14:12:10 -08001434 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001435 session_.OnRstStream(rst1);
1436}
1437
1438TEST_P(QuicSpdySessionTestServer, OnStreamFrameInvalidStreamId) {
1439 // Send two bytes of payload.
renjietange47e15f2019-10-29 14:19:30 -07001440 QuicStreamFrame data1(QuicUtils::GetInvalidStreamId(transport_version()),
vasilvve2707e32020-10-08 12:27:46 -07001441 true, 0, absl::string_view("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001442 EXPECT_CALL(*connection_,
1443 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001444 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001445 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1446 session_.OnStreamFrame(data1);
1447}
1448
1449TEST_P(QuicSpdySessionTestServer, OnRstStreamInvalidStreamId) {
1450 // Send two bytes of payload.
renjietange47e15f2019-10-29 14:19:30 -07001451 QuicRstStreamFrame rst1(kInvalidControlFrameId,
1452 QuicUtils::GetInvalidStreamId(transport_version()),
1453 QUIC_ERROR_PROCESSING_STREAM, 0);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001454 EXPECT_CALL(*connection_,
1455 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001456 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001457 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1458 session_.OnRstStream(rst1);
1459}
1460
1461TEST_P(QuicSpdySessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
dschinaziaab68182019-10-09 15:39:51 -07001462 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
1463 // This test requires Google QUIC crypto because it assumes streams start
1464 // off unblocked.
1465 return;
1466 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001467 // Test that if a stream is flow control blocked, then on receipt of the SHLO
1468 // containing a suitable send window offset, the stream becomes unblocked.
1469
1470 // Ensure that Writev consumes all the data it is given (simulate no socket
1471 // blocking).
fayang29ce0bd2020-10-29 08:28:44 -07001472 session_.GetMutableCryptoStream()->EstablishZeroRttEncryption();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001473 session_.set_writev_consumes_all_data(true);
1474
1475 // Create a stream, and send enough data to make it flow control blocked.
1476 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07001477 std::string body(kMinimumFlowControlSendWindow, '.');
renjietang07b2e8d2020-08-10 15:18:24 -07001478 EXPECT_FALSE(stream2->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001479 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1480 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1481 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
1482 stream2->WriteOrBufferBody(body, false);
renjietang07b2e8d2020-08-10 15:18:24 -07001483 EXPECT_TRUE(stream2->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001484 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1485 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1486
1487 // Now complete the crypto handshake, resulting in an increased flow control
1488 // send window.
renjietang7712ed72020-03-25 14:07:30 -07001489 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001490 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
1491 // Stream is now unblocked.
renjietang07b2e8d2020-08-10 15:18:24 -07001492 EXPECT_FALSE(stream2->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001493 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1494 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1495}
1496
1497TEST_P(QuicSpdySessionTestServer,
1498 HandshakeUnblocksFlowControlBlockedCryptoStream) {
fayang29ce0bd2020-10-29 08:28:44 -07001499 if (QuicVersionUsesCryptoFrames(transport_version()) ||
1500 connection_->encrypted_control_frames()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001501 // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
fayang29ce0bd2020-10-29 08:28:44 -07001502 // test doesn't make sense for those versions. With
1503 // use_encryption_level_context, control frames can only be sent when
1504 // encryption gets established, do not send BLOCKED for crypto streams.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001505 return;
1506 }
1507 // Test that if the crypto stream is flow control blocked, then if the SHLO
1508 // contains a larger send window offset, the stream becomes unblocked.
1509 session_.set_writev_consumes_all_data(true);
1510 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
renjietang07b2e8d2020-08-10 15:18:24 -07001511 EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001512 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1513 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1514 QuicHeadersStream* headers_stream =
1515 QuicSpdySessionPeer::GetHeadersStream(&session_);
renjietang07b2e8d2020-08-10 15:18:24 -07001516 EXPECT_FALSE(headers_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001517 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1518 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
renjietangeab92852019-10-25 12:16:14 -07001519 EXPECT_CALL(*connection_, SendControlFrame(_))
1520 .WillOnce(Invoke(&ClearControlFrame));
renjietang07b2e8d2020-08-10 15:18:24 -07001521 for (QuicStreamId i = 0; !crypto_stream->IsFlowControlBlocked() && i < 1000u;
1522 i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001523 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1524 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1525 QuicStreamOffset offset = crypto_stream->stream_bytes_written();
1526 QuicConfig config;
1527 CryptoHandshakeMessage crypto_message;
fkastenholzd3a1de92019-05-15 07:00:07 -07001528 config.ToHandshakeMessage(&crypto_message, transport_version());
fayang9c41f8b2020-10-30 13:13:06 -07001529 crypto_stream->SendHandshakeMessage(crypto_message, ENCRYPTION_INITIAL);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001530 char buf[1000];
QUICHE team173c48f2019-11-19 16:34:44 -08001531 QuicDataWriter writer(1000, buf, quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001532 crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
1533 }
renjietang07b2e8d2020-08-10 15:18:24 -07001534 EXPECT_TRUE(crypto_stream->IsFlowControlBlocked());
1535 EXPECT_FALSE(headers_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001536 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1537 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1538 EXPECT_FALSE(session_.HasDataToWrite());
1539 EXPECT_TRUE(crypto_stream->HasBufferedData());
1540
1541 // Now complete the crypto handshake, resulting in an increased flow control
1542 // send window.
renjietang7712ed72020-03-25 14:07:30 -07001543 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001544 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
renjietange47e15f2019-10-29 14:19:30 -07001545 &session_, QuicUtils::GetCryptoStreamId(transport_version())));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001546 // Stream is now unblocked and will no longer have buffered data.
renjietang07b2e8d2020-08-10 15:18:24 -07001547 EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001548 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1549 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1550}
1551
1552#if !defined(OS_IOS)
1553// This test is failing flakily for iOS bots.
1554// http://crbug.com/425050
1555// NOTE: It's not possible to use the standard MAYBE_ convention to disable
1556// this test on iOS because when this test gets instantiated it ends up with
1557// various names that are dependent on the parameters passed.
1558TEST_P(QuicSpdySessionTestServer,
1559 HandshakeUnblocksFlowControlBlockedHeadersStream) {
nharperd5c4a932019-05-13 13:58:49 -07001560 // This test depends on stream-level flow control for the crypto stream, which
1561 // doesn't exist when CRYPTO frames are used.
renjietange47e15f2019-10-29 14:19:30 -07001562 if (QuicVersionUsesCryptoFrames(transport_version())) {
nharperd5c4a932019-05-13 13:58:49 -07001563 return;
1564 }
renjietang2abedac2019-05-20 14:04:50 -07001565
1566 // This test depends on the headers stream, which does not exist when QPACK is
1567 // used.
renjietanga29a96a2019-10-10 12:47:50 -07001568 if (VersionUsesHttp3(transport_version())) {
renjietang2abedac2019-05-20 14:04:50 -07001569 return;
1570 }
1571
QUICHE teama6ef0a62019-03-07 20:34:33 -05001572 // Test that if the header stream is flow control blocked, then if the SHLO
1573 // contains a larger send window offset, the stream becomes unblocked.
fayang29ce0bd2020-10-29 08:28:44 -07001574 session_.GetMutableCryptoStream()->EstablishZeroRttEncryption();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001575 session_.set_writev_consumes_all_data(true);
1576 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
renjietang07b2e8d2020-08-10 15:18:24 -07001577 EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001578 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1579 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1580 QuicHeadersStream* headers_stream =
1581 QuicSpdySessionPeer::GetHeadersStream(&session_);
renjietang07b2e8d2020-08-10 15:18:24 -07001582 EXPECT_FALSE(headers_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001583 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1584 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1585 QuicStreamId stream_id = 5;
1586 // Write until the header stream is flow control blocked.
1587 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07001588 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001589 SpdyHeaderBlock headers;
1590 SimpleRandom random;
renjietang07b2e8d2020-08-10 15:18:24 -07001591 while (!headers_stream->IsFlowControlBlocked() && stream_id < 2000) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001592 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1593 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
vasilvva163b382020-12-04 11:47:46 -08001594 headers["header"] = absl::StrCat(random.RandUint64(), random.RandUint64(),
1595 random.RandUint64());
fayang476683a2019-07-25 12:42:16 -07001596 session_.WriteHeadersOnHeadersStream(stream_id, headers.Clone(), true,
1597 spdy::SpdyStreamPrecedence(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001598 nullptr);
1599 stream_id += IdDelta();
1600 }
1601 // Write once more to ensure that the headers stream has buffered data. The
1602 // random headers may have exactly filled the flow control window.
fayang476683a2019-07-25 12:42:16 -07001603 session_.WriteHeadersOnHeadersStream(stream_id, std::move(headers), true,
1604 spdy::SpdyStreamPrecedence(0), nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001605 EXPECT_TRUE(headers_stream->HasBufferedData());
1606
renjietang07b2e8d2020-08-10 15:18:24 -07001607 EXPECT_TRUE(headers_stream->IsFlowControlBlocked());
1608 EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001609 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1610 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1611 EXPECT_FALSE(session_.HasDataToWrite());
1612
1613 // Now complete the crypto handshake, resulting in an increased flow control
1614 // send window.
renjietang7712ed72020-03-25 14:07:30 -07001615 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001616
1617 // Stream is now unblocked and will no longer have buffered data.
renjietang07b2e8d2020-08-10 15:18:24 -07001618 EXPECT_FALSE(headers_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001619 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1620 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1621 EXPECT_TRUE(headers_stream->HasBufferedData());
1622 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
renjietange47e15f2019-10-29 14:19:30 -07001623 &session_, QuicUtils::GetHeadersStreamId(transport_version())));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001624}
1625#endif // !defined(OS_IOS)
1626
1627TEST_P(QuicSpdySessionTestServer,
1628 ConnectionFlowControlAccountingRstOutOfOrder) {
renjietang2be2a7e2020-03-12 15:47:29 -07001629 EXPECT_CALL(*connection_, SendControlFrame(_))
1630 .WillRepeatedly(Invoke(&ClearControlFrame));
renjietang7712ed72020-03-25 14:07:30 -07001631 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001632 // Test that when we receive an out of order stream RST we correctly adjust
1633 // our connection level flow control receive window.
1634 // On close, the stream should mark as consumed all bytes between the highest
1635 // byte consumed so far and the final byte offset from the RST frame.
1636 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1637
1638 const QuicStreamOffset kByteOffset =
1639 1 + kInitialSessionFlowControlWindowForTest / 2;
1640
fkastenholz305e1732019-06-18 05:01:22 -07001641 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001642 // For version99 the call to OnStreamReset happens as a result of receiving
1643 // the STOP_SENDING, so set up the EXPECT there.
1644 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
renjietang7712ed72020-03-25 14:07:30 -07001645 EXPECT_CALL(*connection_, SendControlFrame(_));
1646 } else {
1647 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
1648 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001649 }
1650 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1651 QUIC_STREAM_CANCELLED, kByteOffset);
1652 session_.OnRstStream(rst_frame);
1653 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
1654 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
1655 // one-way close.
fkastenholz305e1732019-06-18 05:01:22 -07001656 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001657 // Only needed for version 99/IETF QUIC.
bnc187eea32020-09-02 12:16:15 -07001658 QuicStopSendingFrame stop_sending(kInvalidControlFrameId, stream->id(),
1659 QUIC_STREAM_CANCELLED);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001660 // Expect the RESET_STREAM that is generated in response to receiving a
1661 // STOP_SENDING.
1662 EXPECT_CALL(*connection_,
1663 OnStreamReset(stream->id(), QUIC_STREAM_CANCELLED));
renjietang7712ed72020-03-25 14:07:30 -07001664 EXPECT_CALL(*connection_, SendControlFrame(_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001665 session_.OnStopSendingFrame(stop_sending);
1666 }
1667
1668 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
1669}
1670
QUICHE teama6ef0a62019-03-07 20:34:33 -05001671TEST_P(QuicSpdySessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
nharperf5e68452019-05-29 17:24:18 -07001672 if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
renjietangbb2e22a2019-09-12 15:46:39 -07001673 // IETF Quic doesn't require a minimum flow control window.
nharperf5e68452019-05-29 17:24:18 -07001674 return;
1675 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001676 // Test that receipt of an invalid (< default) stream flow control window from
1677 // the peer results in the connection being torn down.
1678 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1679 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
1680 kInvalidWindow);
1681
1682 EXPECT_CALL(*connection_,
1683 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1684 session_.OnConfigNegotiated();
1685}
1686
renjietang203926d2019-09-04 15:09:03 -07001687TEST_P(QuicSpdySessionTestServer, TooLowUnidirectionalStreamLimitHttp3) {
renjietanga29a96a2019-10-10 12:47:50 -07001688 if (!VersionUsesHttp3(transport_version())) {
renjietang203926d2019-09-04 15:09:03 -07001689 return;
1690 }
fayang29ce0bd2020-10-29 08:28:44 -07001691 session_.GetMutableCryptoStream()->EstablishZeroRttEncryption();
renjietange6d94672020-01-07 10:30:10 -08001692 QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 2u);
renjietangc02d4462020-06-08 14:25:16 -07001693 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
renjietang203926d2019-09-04 15:09:03 -07001694
1695 EXPECT_CALL(
1696 *connection_,
renjietang241ba602020-04-29 13:29:46 -07001697 CloseConnection(
1698 _, "new unidirectional limit 2 decreases the current limit: 3", _));
renjietang203926d2019-09-04 15:09:03 -07001699 session_.OnConfigNegotiated();
1700}
1701
QUICHE teama6ef0a62019-03-07 20:34:33 -05001702// Test negotiation of custom server initial flow control window.
1703TEST_P(QuicSpdySessionTestServer, CustomFlowControlWindow) {
1704 QuicTagVector copt;
1705 copt.push_back(kIFW7);
1706 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
renjietangc02d4462020-06-08 14:25:16 -07001707 connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001708 session_.OnConfigNegotiated();
1709 EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
1710 session_.flow_controller()));
1711}
1712
QUICHE teama6ef0a62019-03-07 20:34:33 -05001713TEST_P(QuicSpdySessionTestServer, WindowUpdateUnblocksHeadersStream) {
renjietange47e15f2019-10-29 14:19:30 -07001714 if (VersionUsesHttp3(transport_version())) {
renjietang67e5bcb2019-09-26 16:19:55 -07001715 // The test relies on headers stream, which no longer exists in IETF QUIC.
nharperf5e68452019-05-29 17:24:18 -07001716 return;
1717 }
renjietang118c8ac2019-07-30 11:43:59 -07001718
QUICHE teama6ef0a62019-03-07 20:34:33 -05001719 // Test that a flow control blocked headers stream gets unblocked on recipt of
1720 // a WINDOW_UPDATE frame.
1721
1722 // Set the headers stream to be flow control blocked.
1723 QuicHeadersStream* headers_stream =
1724 QuicSpdySessionPeer::GetHeadersStream(&session_);
renjietang07b2e8d2020-08-10 15:18:24 -07001725 QuicStreamPeer::SetSendWindowOffset(headers_stream, 0);
1726 EXPECT_TRUE(headers_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001727 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1728 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1729
1730 // Unblock the headers stream by supplying a WINDOW_UPDATE.
1731 QuicWindowUpdateFrame window_update_frame(kInvalidControlFrameId,
1732 headers_stream->id(),
1733 2 * kMinimumFlowControlSendWindow);
1734 session_.OnWindowUpdateFrame(window_update_frame);
renjietang07b2e8d2020-08-10 15:18:24 -07001735 EXPECT_FALSE(headers_stream->IsFlowControlBlocked());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001736 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1737 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1738}
1739
1740TEST_P(QuicSpdySessionTestServer,
1741 TooManyUnfinishedStreamsCauseServerRejectStream) {
1742 // If a buggy/malicious peer creates too many streams that are not ended
1743 // with a FIN or RST then we send an RST to refuse streams for versions other
1744 // than version 99. In version 99 the connection gets closed.
fayang29ce0bd2020-10-29 08:28:44 -07001745 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001746 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07001747 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001748 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1749 kMaxStreams);
1750 } else {
1751 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1752 }
fkastenholz3c4eabf2019-04-22 07:49:59 -07001753 // GetNth assumes that both the crypto and header streams have been
1754 // open, but the stream id manager, using GetFirstBidirectional... only
1755 // assumes that the crypto stream is open. This means that GetNth...(0)
1756 // Will return stream ID == 8 (with id ==0 for crypto and id==4 for headers).
1757 // It also means that GetNth(kMax..=5) returns 28 (streams 0/1/2/3/4 are ids
1758 // 8, 12, 16, 20, 24, respectively, so stream#5 is stream id 28).
1759 // However, the stream ID manager does not assume stream 4 is for headers.
1760 // The ID manager would assume that stream#5 is streamid 24.
1761 // In order to make this all work out properly, kFinalStreamId will
renjietangf8bde4b2020-10-02 13:25:08 -07001762 // be set to GetNth...(kMaxStreams-1)... but only for IETF QUIC
QUICHE teama6ef0a62019-03-07 20:34:33 -05001763 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1764 const QuicStreamId kFinalStreamId =
1765 GetNthClientInitiatedBidirectionalId(kMaxStreams);
1766 // Create kMaxStreams data streams, and close them all without receiving a
1767 // FIN or a RST_STREAM from the client.
renjietange47e15f2019-10-29 14:19:30 -07001768 const QuicStreamId kNextId = QuicUtils::StreamIdDelta(transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001769 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += kNextId) {
vasilvve2707e32020-10-08 12:27:46 -07001770 QuicStreamFrame data1(i, false, 0, absl::string_view("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001771 session_.OnStreamFrame(data1);
renjietangfcf3f182020-06-30 15:06:56 -07001772 CloseStream(i);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001773 }
1774 // Try and open a stream that exceeds the limit.
fkastenholz305e1732019-06-18 05:01:22 -07001775 if (!VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001776 // On versions other than 99, opening such a stream results in a
1777 // RST_STREAM.
1778 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1779 EXPECT_CALL(*connection_,
1780 OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
1781 .Times(1);
1782 } else {
1783 // On version 99 opening such a stream results in a connection close.
dschinazi7ae3d602019-06-19 11:04:29 -07001784 EXPECT_CALL(
1785 *connection_,
1786 CloseConnection(QUIC_INVALID_STREAM_ID,
1787 testing::MatchesRegex(
renjietang118c8ac2019-07-30 11:43:59 -07001788 "Stream id \\d+ would exceed stream count limit 5"),
dschinazi7ae3d602019-06-19 11:04:29 -07001789 _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001790 }
1791 // Create one more data streams to exceed limit of open stream.
vasilvve2707e32020-10-08 12:27:46 -07001792 QuicStreamFrame data1(kFinalStreamId, false, 0, absl::string_view("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001793 session_.OnStreamFrame(data1);
1794}
1795
1796TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) {
1797 // Verify that a draining stream (which has received a FIN but not consumed
1798 // it) does not count against the open quota (because it is closed from the
1799 // protocol point of view).
fayang29ce0bd2020-10-29 08:28:44 -07001800 CompleteHandshake();
fkastenholz305e1732019-06-18 05:01:22 -07001801 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholz56055be2019-09-17 11:17:37 -07001802 // Simulate receiving a config. so that MAX_STREAMS/etc frames may
1803 // be transmitted
1804 QuicSessionPeer::set_is_configured(&session_, true);
fkastenholz3c4eabf2019-04-22 07:49:59 -07001805 // Version 99 will result in a MAX_STREAMS frame as streams are consumed
QUICHE teama6ef0a62019-03-07 20:34:33 -05001806 // (via the OnStreamFrame call) and then released (via
1807 // StreamDraining). Eventually this node will believe that the peer is
fkastenholz3c4eabf2019-04-22 07:49:59 -07001808 // running low on available stream ids and then send a MAX_STREAMS frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001809 // caught by this EXPECT_CALL.
1810 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1811 } else {
1812 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1813 }
1814 EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
1815 const QuicStreamId kMaxStreams = 5;
fkastenholz305e1732019-06-18 05:01:22 -07001816 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001817 QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
1818 kMaxStreams);
1819 } else {
1820 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1821 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001822
1823 // Create kMaxStreams + 1 data streams, and mark them draining.
1824 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1825 const QuicStreamId kFinalStreamId =
1826 GetNthClientInitiatedBidirectionalId(kMaxStreams + 1);
1827 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += IdDelta()) {
vasilvve2707e32020-10-08 12:27:46 -07001828 QuicStreamFrame data1(i, true, 0, absl::string_view("HT"));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001829 session_.OnStreamFrame(data1);
fayang01591ae2020-04-23 14:14:56 -07001830 EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
fayangbe6d6642020-04-16 14:15:34 -07001831 session_.StreamDraining(i, /*unidirectional=*/false);
fayang01591ae2020-04-23 14:14:56 -07001832 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001833 }
1834}
1835
bnc9a7a6732020-04-14 06:08:02 -07001836TEST_P(QuicSpdySessionTestServer, ReduceMaxPushId) {
1837 if (!VersionUsesHttp3(transport_version())) {
1838 return;
1839 }
1840
1841 StrictMock<MockHttp3DebugVisitor> debug_visitor;
1842 session_.set_debug_visitor(&debug_visitor);
1843
1844 // Use an arbitrary stream id for incoming control stream.
1845 QuicStreamId stream_id =
1846 GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
1847 char type[] = {kControlStream};
vasilvve2707e32020-10-08 12:27:46 -07001848 absl::string_view stream_type(type, 1);
bnc9a7a6732020-04-14 06:08:02 -07001849
1850 QuicStreamOffset offset = 0;
1851 QuicStreamFrame data1(stream_id, false, offset, stream_type);
1852 offset += stream_type.length();
1853 EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id));
1854 session_.OnStreamFrame(data1);
1855 EXPECT_EQ(stream_id,
1856 QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
1857
1858 SettingsFrame settings;
1859 std::string settings_frame = EncodeSettings(settings);
1860 QuicStreamFrame data2(stream_id, false, offset, settings_frame);
1861 offset += settings_frame.length();
1862
1863 EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
1864 session_.OnStreamFrame(data2);
1865
1866 std::string max_push_id_frame1 = SerializeMaxPushIdFrame(/* push_id = */ 3);
1867 QuicStreamFrame data3(stream_id, false, offset, max_push_id_frame1);
1868 offset += max_push_id_frame1.length();
1869
1870 EXPECT_CALL(debug_visitor, OnMaxPushIdFrameReceived(_));
1871 session_.OnStreamFrame(data3);
1872
1873 std::string max_push_id_frame2 = SerializeMaxPushIdFrame(/* push_id = */ 1);
1874 QuicStreamFrame data4(stream_id, false, offset, max_push_id_frame2);
1875
1876 EXPECT_CALL(debug_visitor, OnMaxPushIdFrameReceived(_));
1877 EXPECT_CALL(*connection_,
1878 CloseConnection(QUIC_HTTP_INVALID_MAX_PUSH_ID,
1879 "MAX_PUSH_ID received with value 1 which is "
1880 "smaller that previously received value 3",
1881 _));
1882 session_.OnStreamFrame(data4);
1883}
1884
QUICHE teama6ef0a62019-03-07 20:34:33 -05001885class QuicSpdySessionTestClient : public QuicSpdySessionTestBase {
1886 protected:
1887 QuicSpdySessionTestClient()
1888 : QuicSpdySessionTestBase(Perspective::IS_CLIENT) {}
1889};
1890
1891INSTANTIATE_TEST_SUITE_P(Tests,
1892 QuicSpdySessionTestClient,
dschinazi142051a2019-09-18 18:17:29 -07001893 ::testing::ValuesIn(AllSupportedVersions()),
1894 ::testing::PrintToStringParamName());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001895
renjietange76b2da2019-05-13 14:50:23 -07001896TEST_P(QuicSpdySessionTestClient, UsesPendingStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07001897 if (!VersionUsesHttp3(transport_version())) {
renjietange76b2da2019-05-13 14:50:23 -07001898 return;
1899 }
renjietangbb1c4892019-05-24 15:58:44 -07001900 EXPECT_TRUE(session_.UsesPendingStreams());
renjietange76b2da2019-05-13 14:50:23 -07001901}
1902
renjietanga553da02019-06-24 11:57:04 -07001903// Regression test for crbug.com/977581.
1904TEST_P(QuicSpdySessionTestClient, BadStreamFramePendingStream) {
renjietanga29a96a2019-10-10 12:47:50 -07001905 if (!VersionUsesHttp3(transport_version())) {
renjietanga553da02019-06-24 11:57:04 -07001906 return;
1907 }
1908
fayang01591ae2020-04-23 14:14:56 -07001909 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
renjietanga553da02019-06-24 11:57:04 -07001910 QuicStreamId stream_id1 =
1911 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
1912 // A bad stream frame with no data and no fin.
1913 QuicStreamFrame data1(stream_id1, false, 0, 0);
fayang528c36b2020-12-23 07:02:09 -08001914 if (!GetQuicReloadableFlag(quic_accept_empty_stream_frame_with_no_fin)) {
1915 EXPECT_CALL(*connection_, CloseConnection(_, _, _))
1916 .WillOnce(
1917 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
mattm55006b02021-01-14 15:09:54 -08001918 EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
fayang528c36b2020-12-23 07:02:09 -08001919 }
renjietanga553da02019-06-24 11:57:04 -07001920 session_.OnStreamFrame(data1);
1921}
1922
renjietang56d2ed22019-10-22 14:11:55 -07001923TEST_P(QuicSpdySessionTestClient, PendingStreamKeepsConnectionAlive) {
1924 if (!VersionUsesHttp3(transport_version())) {
1925 return;
1926 }
1927
1928 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
1929 transport_version(), Perspective::IS_SERVER);
1930
1931 QuicStreamFrame frame(stream_id, false, 1, "test");
1932 EXPECT_FALSE(session_.ShouldKeepConnectionAlive());
1933 session_.OnStreamFrame(frame);
1934 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
1935 EXPECT_TRUE(session_.ShouldKeepConnectionAlive());
1936}
1937
QUICHE teama6ef0a62019-03-07 20:34:33 -05001938TEST_P(QuicSpdySessionTestClient, AvailableStreamsClient) {
renjietang880d2432019-07-16 13:14:37 -07001939 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001940 GetNthServerInitiatedBidirectionalId(2)) != nullptr);
1941 // Both server initiated streams with smaller stream IDs should be available.
1942 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1943 &session_, GetNthServerInitiatedBidirectionalId(0)));
1944 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1945 &session_, GetNthServerInitiatedBidirectionalId(1)));
renjietang880d2432019-07-16 13:14:37 -07001946 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001947 GetNthServerInitiatedBidirectionalId(0)) != nullptr);
renjietang880d2432019-07-16 13:14:37 -07001948 ASSERT_TRUE(session_.GetOrCreateStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001949 GetNthServerInitiatedBidirectionalId(1)) != nullptr);
1950 // And client initiated stream ID should be not available.
1951 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
1952 &session_, GetNthClientInitiatedBidirectionalId(0)));
1953}
1954
bnca980ce52019-06-14 10:49:15 -07001955// Regression test for b/130740258 and https://crbug.com/971779.
1956// If headers that are too large or empty are received (these cases are handled
1957// the same way, as QuicHeaderList clears itself when headers exceed the limit),
1958// then the stream is reset. No more frames must be sent in this case.
1959TEST_P(QuicSpdySessionTestClient, TooLargeHeadersMustNotCauseWriteAfterReset) {
1960 // In IETF QUIC, HEADERS do not carry FIN flag, and OnStreamHeaderList() is
1961 // never called after an error, including too large headers.
renjietanga29a96a2019-10-10 12:47:50 -07001962 if (VersionUsesHttp3(transport_version())) {
bnca980ce52019-06-14 10:49:15 -07001963 return;
1964 }
renjietang7712ed72020-03-25 14:07:30 -07001965 CompleteHandshake();
bnca980ce52019-06-14 10:49:15 -07001966 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1967
renjietang7712ed72020-03-25 14:07:30 -07001968 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
1969 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
bnca980ce52019-06-14 10:49:15 -07001970 // Write headers with FIN set to close write side of stream.
1971 // Header block does not matter.
1972 stream->WriteHeaders(SpdyHeaderBlock(), /* fin = */ true, nullptr);
1973
1974 // Receive headers that are too large or empty, with FIN set.
1975 // This causes the stream to be reset. No frames must be written after this.
1976 QuicHeaderList headers;
1977 EXPECT_CALL(*connection_, SendControlFrame(_));
1978 EXPECT_CALL(*connection_,
1979 OnStreamReset(stream->id(), QUIC_HEADERS_TOO_LARGE));
1980 stream->OnStreamHeaderList(/* fin = */ true,
1981 headers.uncompressed_header_bytes(), headers);
1982}
1983
QUICHE teama6ef0a62019-03-07 20:34:33 -05001984TEST_P(QuicSpdySessionTestClient, RecordFinAfterReadSideClosed) {
1985 // Verify that an incoming FIN is recorded in a stream object even if the read
1986 // side has been closed. This prevents an entry from being made in
1987 // locally_closed_streams_highest_offset_ (which will never be deleted).
fayang29ce0bd2020-10-29 08:28:44 -07001988 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001989 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1990 QuicStreamId stream_id = stream->id();
1991
1992 // Close the read side manually.
1993 QuicStreamPeer::CloseReadSide(stream);
1994
1995 // Receive a stream data frame with FIN.
vasilvve2707e32020-10-08 12:27:46 -07001996 QuicStreamFrame frame(stream_id, true, 0, absl::string_view());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001997 session_.OnStreamFrame(frame);
1998 EXPECT_TRUE(stream->fin_received());
1999
2000 // Reset stream locally.
2001 EXPECT_CALL(*connection_, SendControlFrame(_));
2002 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
2003 stream->Reset(QUIC_STREAM_CANCELLED);
2004 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
2005
2006 EXPECT_TRUE(connection_->connected());
2007 EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
2008 EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
2009
2010 // The stream is not waiting for the arrival of the peer's final offset as it
2011 // was received with the FIN earlier.
2012 EXPECT_EQ(
2013 0u,
2014 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
2015}
2016
2017TEST_P(QuicSpdySessionTestClient, WritePriority) {
renjietanga29a96a2019-10-10 12:47:50 -07002018 if (VersionUsesHttp3(transport_version())) {
renjietang67e5bcb2019-09-26 16:19:55 -07002019 // IETF QUIC currently doesn't support PRIORITY.
renjietang7cedcbf2019-07-19 12:06:36 -07002020 return;
2021 }
renjietang7712ed72020-03-25 14:07:30 -07002022 CompleteHandshake();
renjietang2be2a7e2020-03-12 15:47:29 -07002023
renjietangfbeb5bf2019-04-19 15:06:20 -07002024 TestHeadersStream* headers_stream;
renjietang9818f8c2019-07-16 11:12:27 -07002025 QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
renjietangb663b862019-07-08 16:02:39 -07002026 headers_stream = new TestHeadersStream(&session_);
renjietang9818f8c2019-07-16 11:12:27 -07002027 QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002028
2029 // Make packet writer blocked so |headers_stream| will buffer its write data.
renjietang7712ed72020-03-25 14:07:30 -07002030 EXPECT_CALL(*writer_, IsWriteBlocked()).WillRepeatedly(Return(true));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002031
2032 const QuicStreamId id = 4;
2033 const QuicStreamId parent_stream_id = 9;
2034 const SpdyPriority priority = kV3HighestPriority;
2035 const bool exclusive = true;
2036 session_.WritePriority(id, parent_stream_id,
2037 Spdy3PriorityToHttp2Weight(priority), exclusive);
2038
2039 QuicStreamSendBuffer& send_buffer =
2040 QuicStreamPeer::SendBuffer(headers_stream);
fayang8265a2a2019-10-16 11:23:51 -07002041 ASSERT_EQ(1u, send_buffer.size());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002042
fayang8265a2a2019-10-16 11:23:51 -07002043 SpdyPriorityIR priority_frame(
2044 id, parent_stream_id, Spdy3PriorityToHttp2Weight(priority), exclusive);
2045 SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
2046 SpdySerializedFrame frame = spdy_framer.SerializeFrame(priority_frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002047
fayang8265a2a2019-10-16 11:23:51 -07002048 const QuicMemSlice& slice =
2049 QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer)->slice;
vasilvve2707e32020-10-08 12:27:46 -07002050 EXPECT_EQ(absl::string_view(frame.data(), frame.size()),
2051 absl::string_view(slice.data(), slice.length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002052}
2053
renjietangbb1c4892019-05-24 15:58:44 -07002054TEST_P(QuicSpdySessionTestClient, Http3ServerPush) {
renjietanga29a96a2019-10-10 12:47:50 -07002055 if (!VersionUsesHttp3(transport_version())) {
renjietangbb1c4892019-05-24 15:58:44 -07002056 return;
2057 }
2058
fayang01591ae2020-04-23 14:14:56 -07002059 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
bnca7ac8472019-07-27 11:48:50 -07002060
2061 // Push unidirectional stream is type 0x01.
vasilvv72b789c2020-10-27 17:39:17 -07002062 std::string frame_type1 = absl::HexStringToBytes("01");
renjietangbb1c4892019-05-24 15:58:44 -07002063 QuicStreamId stream_id1 =
2064 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
bnca7ac8472019-07-27 11:48:50 -07002065 session_.OnStreamFrame(QuicStreamFrame(stream_id1, /* fin = */ false,
2066 /* offset = */ 0, frame_type1));
2067
fayang01591ae2020-04-23 14:14:56 -07002068 EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
renjietang880d2432019-07-16 13:14:37 -07002069 QuicStream* stream = session_.GetOrCreateStream(stream_id1);
renjietang07b2e8d2020-08-10 15:18:24 -07002070 EXPECT_EQ(1u, QuicStreamPeer::bytes_consumed(stream));
renjietangbb1c4892019-05-24 15:58:44 -07002071 EXPECT_EQ(1u, session_.flow_controller()->bytes_consumed());
2072
bnca7ac8472019-07-27 11:48:50 -07002073 // The same stream type can be encoded differently.
vasilvv72b789c2020-10-27 17:39:17 -07002074 std::string frame_type2 = absl::HexStringToBytes("80000001");
renjietangbb1c4892019-05-24 15:58:44 -07002075 QuicStreamId stream_id2 =
2076 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
bnca7ac8472019-07-27 11:48:50 -07002077 session_.OnStreamFrame(QuicStreamFrame(stream_id2, /* fin = */ false,
2078 /* offset = */ 0, frame_type2));
2079
fayang01591ae2020-04-23 14:14:56 -07002080 EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
renjietang880d2432019-07-16 13:14:37 -07002081 stream = session_.GetOrCreateStream(stream_id2);
renjietang07b2e8d2020-08-10 15:18:24 -07002082 EXPECT_EQ(4u, QuicStreamPeer::bytes_consumed(stream));
renjietangbb1c4892019-05-24 15:58:44 -07002083 EXPECT_EQ(5u, session_.flow_controller()->bytes_consumed());
2084}
2085
2086TEST_P(QuicSpdySessionTestClient, Http3ServerPushOutofOrderFrame) {
renjietanga29a96a2019-10-10 12:47:50 -07002087 if (!VersionUsesHttp3(transport_version())) {
renjietangbb1c4892019-05-24 15:58:44 -07002088 return;
2089 }
2090
fayang01591ae2020-04-23 14:14:56 -07002091 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
renjietangbb1c4892019-05-24 15:58:44 -07002092
bnca7ac8472019-07-27 11:48:50 -07002093 // Push unidirectional stream is type 0x01.
vasilvv72b789c2020-10-27 17:39:17 -07002094 std::string frame_type = absl::HexStringToBytes("01");
bnca7ac8472019-07-27 11:48:50 -07002095 // The first field of a push stream is the Push ID.
vasilvv72b789c2020-10-27 17:39:17 -07002096 std::string push_id = absl::HexStringToBytes("4000");
bnca7ac8472019-07-27 11:48:50 -07002097
2098 QuicStreamId stream_id =
2099 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2100
2101 QuicStreamFrame data1(stream_id,
2102 /* fin = */ false, /* offset = */ 0, frame_type);
2103 QuicStreamFrame data2(stream_id,
2104 /* fin = */ false, /* offset = */ frame_type.size(),
2105 push_id);
2106
2107 // Receiving some stream data without stream type does not open the stream.
renjietangbb1c4892019-05-24 15:58:44 -07002108 session_.OnStreamFrame(data2);
fayang01591ae2020-04-23 14:14:56 -07002109 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
bnca7ac8472019-07-27 11:48:50 -07002110
2111 session_.OnStreamFrame(data1);
fayang01591ae2020-04-23 14:14:56 -07002112 EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
bnca7ac8472019-07-27 11:48:50 -07002113 QuicStream* stream = session_.GetOrCreateStream(stream_id);
renjietang07b2e8d2020-08-10 15:18:24 -07002114 EXPECT_EQ(3u, stream->highest_received_byte_offset());
renjietangbb1c4892019-05-24 15:58:44 -07002115}
2116
QUICHE teama6ef0a62019-03-07 20:34:33 -05002117TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
fayanga61d1ce2020-10-27 11:05:44 -07002118 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05002119 InSequence s;
2120
2121 // Drive congestion control manually.
2122 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2123 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2124
2125 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
2126 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2127 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2128
QUICHE teama6ef0a62019-03-07 20:34:33 -05002129 QuicStreamFrame frame2(stream2->id(), false, 0, 9);
2130 QuicStreamFrame frame3(stream4->id(), false, 0, 9);
2131
2132 // Lost data on cryption stream, streams 2 and 4.
2133 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
renjietange47e15f2019-10-29 14:19:30 -07002134 if (!QuicVersionUsesCryptoFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002135 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2136 .WillOnce(Return(true));
2137 }
2138 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2139 session_.OnFrameLost(QuicFrame(frame3));
renjietange47e15f2019-10-29 14:19:30 -07002140 if (!QuicVersionUsesCryptoFrames(transport_version())) {
2141 QuicStreamFrame frame1(QuicUtils::GetCryptoStreamId(transport_version()),
2142 false, 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002143 session_.OnFrameLost(QuicFrame(frame1));
2144 } else {
QUICHE team6987b4a2019-03-15 16:23:04 -07002145 QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002146 session_.OnFrameLost(QuicFrame(&crypto_frame));
2147 }
2148 session_.OnFrameLost(QuicFrame(frame2));
2149 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2150
2151 // Mark streams 2 and 4 write blocked.
2152 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2153 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2154
2155 // Lost data is retransmitted before new data, and retransmissions for crypto
2156 // stream go first.
2157 // Do not check congestion window when crypto stream has lost data.
2158 EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
renjietange47e15f2019-10-29 14:19:30 -07002159 if (!QuicVersionUsesCryptoFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002160 EXPECT_CALL(*crypto_stream, OnCanWrite());
2161 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
2162 .WillOnce(Return(false));
2163 }
2164 // Check congestion window for non crypto streams.
2165 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2166 EXPECT_CALL(*stream4, OnCanWrite());
2167 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(false));
2168 // Connection is blocked.
2169 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(false));
2170
2171 session_.OnCanWrite();
2172 EXPECT_TRUE(session_.WillingAndAbleToWrite());
2173
2174 // Unblock connection.
2175 // Stream 2 retransmits lost data.
2176 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2177 EXPECT_CALL(*stream2, OnCanWrite());
2178 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2179 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2180 // Stream 2 sends new data.
2181 EXPECT_CALL(*stream2, OnCanWrite());
2182 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
2183 EXPECT_CALL(*stream4, OnCanWrite());
2184 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2185
2186 session_.OnCanWrite();
2187 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2188}
2189
2190TEST_P(QuicSpdySessionTestServer, DonotRetransmitDataOfClosedStreams) {
bnc6f18a822019-11-27 17:50:38 -08002191 // Resetting a stream will send a QPACK Stream Cancellation instruction on the
2192 // decoder stream. For simplicity, ignore writes on this stream.
fayang29ce0bd2020-10-29 08:28:44 -07002193 CompleteHandshake();
bnc6f18a822019-11-27 17:50:38 -08002194 NoopQpackStreamSenderDelegate qpack_stream_sender_delegate;
2195 if (VersionUsesHttp3(transport_version())) {
2196 session_.qpack_decoder()->set_qpack_stream_sender_delegate(
2197 &qpack_stream_sender_delegate);
2198 }
2199
QUICHE teama6ef0a62019-03-07 20:34:33 -05002200 InSequence s;
2201
2202 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2203 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2204 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2205
2206 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2207 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2208 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2209
2210 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(true));
2211 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
2212 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
2213 session_.OnFrameLost(QuicFrame(frame3));
2214 session_.OnFrameLost(QuicFrame(frame2));
2215 session_.OnFrameLost(QuicFrame(frame1));
2216
2217 session_.MarkConnectionLevelWriteBlocked(stream2->id());
2218 session_.MarkConnectionLevelWriteBlocked(stream4->id());
2219 session_.MarkConnectionLevelWriteBlocked(stream6->id());
2220
2221 // Reset stream 4 locally.
2222 EXPECT_CALL(*connection_, SendControlFrame(_));
2223 EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
2224 stream4->Reset(QUIC_STREAM_CANCELLED);
2225
2226 // Verify stream 4 is removed from streams with lost data list.
2227 EXPECT_CALL(*stream6, OnCanWrite());
2228 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
2229 EXPECT_CALL(*stream2, OnCanWrite());
2230 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
2231 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002232 .WillRepeatedly(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002233 EXPECT_CALL(*stream2, OnCanWrite());
2234 EXPECT_CALL(*stream6, OnCanWrite());
2235 session_.OnCanWrite();
2236}
2237
2238TEST_P(QuicSpdySessionTestServer, RetransmitFrames) {
fayang29ce0bd2020-10-29 08:28:44 -07002239 CompleteHandshake();
QUICHE teama6ef0a62019-03-07 20:34:33 -05002240 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
2241 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
2242 InSequence s;
2243
2244 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
2245 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
2246 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
2247 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002248 .WillOnce(Invoke(&ClearControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002249 session_.SendWindowUpdate(stream2->id(), 9);
2250
2251 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
2252 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
2253 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
2254 QuicWindowUpdateFrame window_update(1, stream2->id(), 9);
2255 QuicFrames frames;
2256 frames.push_back(QuicFrame(frame1));
2257 frames.push_back(QuicFrame(&window_update));
2258 frames.push_back(QuicFrame(frame2));
2259 frames.push_back(QuicFrame(frame3));
2260 EXPECT_FALSE(session_.WillingAndAbleToWrite());
2261
renjietang4d992bf2020-03-03 13:01:55 -08002262 EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _, _))
2263 .WillOnce(Return(true));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002264 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc5b3c3be2019-06-25 10:37:09 -07002265 .WillOnce(Invoke(&ClearControlFrame));
renjietang4d992bf2020-03-03 13:01:55 -08002266 EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _, _))
2267 .WillOnce(Return(true));
2268 EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _))
2269 .WillOnce(Return(true));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002270 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
2271 session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
2272}
2273
2274TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) {
2275 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
2276 TestStream* stream = session_.CreateIncomingStream(stream_id);
fayang476683a2019-07-25 12:42:16 -07002277 session_.OnPriorityFrame(stream_id,
2278 spdy::SpdyStreamPrecedence(kV3HighestPriority));
2279 EXPECT_EQ(spdy::SpdyStreamPrecedence(kV3HighestPriority),
2280 stream->precedence());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002281}
2282
bncf6b86b22020-01-26 11:08:46 -08002283TEST_P(QuicSpdySessionTestServer, OnPriorityUpdateFrame) {
2284 if (!VersionUsesHttp3(transport_version())) {
2285 return;
2286 }
2287
bncb9d5e792020-03-20 17:43:41 -07002288 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2289 session_.set_debug_visitor(&debug_visitor);
2290
bncf6b86b22020-01-26 11:08:46 -08002291 // Create control stream.
2292 QuicStreamId receive_control_stream_id =
2293 GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
2294 char type[] = {kControlStream};
vasilvve2707e32020-10-08 12:27:46 -07002295 absl::string_view stream_type(type, 1);
bncf6b86b22020-01-26 11:08:46 -08002296 QuicStreamOffset offset = 0;
2297 QuicStreamFrame data1(receive_control_stream_id, false, offset, stream_type);
2298 offset += stream_type.length();
bncb9d5e792020-03-20 17:43:41 -07002299 EXPECT_CALL(debug_visitor,
2300 OnPeerControlStreamCreated(receive_control_stream_id));
bncf6b86b22020-01-26 11:08:46 -08002301 session_.OnStreamFrame(data1);
2302 EXPECT_EQ(receive_control_stream_id,
2303 QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
2304
2305 // Send SETTINGS frame.
2306 std::string serialized_settings = EncodeSettings({});
2307 QuicStreamFrame data2(receive_control_stream_id, false, offset,
2308 serialized_settings);
2309 offset += serialized_settings.length();
bncb9d5e792020-03-20 17:43:41 -07002310 EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
bncf6b86b22020-01-26 11:08:46 -08002311 session_.OnStreamFrame(data2);
2312
2313 // PRIORITY_UPDATE frame for first request stream.
2314 const QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
2315 struct PriorityUpdateFrame priority_update1;
2316 priority_update1.prioritized_element_type = REQUEST_STREAM;
2317 priority_update1.prioritized_element_id = stream_id1;
bnc5f202512020-02-01 18:43:02 -08002318 priority_update1.priority_field_value = "u=2";
bncf6b86b22020-01-26 11:08:46 -08002319 std::string serialized_priority_update1 =
2320 SerializePriorityUpdateFrame(priority_update1);
2321 QuicStreamFrame data3(receive_control_stream_id,
2322 /* fin = */ false, offset, serialized_priority_update1);
2323 offset += serialized_priority_update1.size();
2324
2325 // PRIORITY_UPDATE frame arrives after stream creation.
2326 TestStream* stream1 = session_.CreateIncomingStream(stream_id1);
bnc9e7c08c2020-11-09 11:24:49 -08002327 EXPECT_EQ(QuicStream::kDefaultUrgency,
bnc5f202512020-02-01 18:43:02 -08002328 stream1->precedence().spdy3_priority());
bncb9d5e792020-03-20 17:43:41 -07002329 EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameReceived(priority_update1));
bncf6b86b22020-01-26 11:08:46 -08002330 session_.OnStreamFrame(data3);
bnc5f202512020-02-01 18:43:02 -08002331 EXPECT_EQ(2u, stream1->precedence().spdy3_priority());
bncf6b86b22020-01-26 11:08:46 -08002332
2333 // PRIORITY_UPDATE frame for second request stream.
2334 const QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
2335 struct PriorityUpdateFrame priority_update2;
2336 priority_update2.prioritized_element_type = REQUEST_STREAM;
2337 priority_update2.prioritized_element_id = stream_id2;
2338 priority_update2.priority_field_value = "u=2";
2339 std::string serialized_priority_update2 =
2340 SerializePriorityUpdateFrame(priority_update2);
2341 QuicStreamFrame stream_frame3(receive_control_stream_id,
2342 /* fin = */ false, offset,
2343 serialized_priority_update2);
2344
2345 // PRIORITY_UPDATE frame arrives before stream creation,
2346 // priority value is buffered.
bncb9d5e792020-03-20 17:43:41 -07002347 EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameReceived(priority_update2));
bncf6b86b22020-01-26 11:08:46 -08002348 session_.OnStreamFrame(stream_frame3);
2349 // Priority is applied upon stream construction.
2350 TestStream* stream2 = session_.CreateIncomingStream(stream_id2);
2351 EXPECT_EQ(2u, stream2->precedence().spdy3_priority());
2352}
2353
renjietang0c558862019-05-08 13:26:23 -07002354TEST_P(QuicSpdySessionTestServer, SimplePendingStreamType) {
renjietanga29a96a2019-10-10 12:47:50 -07002355 if (!VersionUsesHttp3(transport_version())) {
renjietang0c558862019-05-08 13:26:23 -07002356 return;
2357 }
fayang29ce0bd2020-10-29 08:28:44 -07002358 CompleteHandshake();
bnc4ff60622019-08-09 18:55:45 -07002359 char input[] = {0x04, // type
2360 'a', 'b', 'c'}; // data
vasilvvfe1c8f32020-10-19 14:10:59 -07002361 absl::string_view payload(input, ABSL_ARRAYSIZE(input));
bnc4ff60622019-08-09 18:55:45 -07002362
2363 // This is a server test with a client-initiated unidirectional stream.
2364 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
2365 transport_version(), Perspective::IS_CLIENT);
2366
2367 for (bool fin : {true, false}) {
2368 QuicStreamFrame frame(stream_id, fin, /* offset = */ 0, payload);
2369
2370 // A STOP_SENDING frame is sent in response to the unknown stream type.
2371 EXPECT_CALL(*connection_, SendControlFrame(_))
bnc731f4472020-03-12 04:25:18 -07002372 .WillOnce(Invoke([stream_id](const QuicFrame& frame) {
2373 EXPECT_EQ(STOP_SENDING_FRAME, frame.type);
2374
2375 QuicStopSendingFrame* stop_sending = frame.stop_sending_frame;
2376 EXPECT_EQ(stream_id, stop_sending->stream_id);
bncba7be052020-11-24 06:58:02 -08002377 EXPECT_EQ(QUIC_STREAM_STREAM_CREATION_ERROR,
2378 stop_sending->error_code);
bnc4fd6e9b2020-09-10 13:06:54 -07002379 EXPECT_EQ(
2380 static_cast<uint64_t>(QuicHttp3ErrorCode::STREAM_CREATION_ERROR),
2381 stop_sending->ietf_error_code);
bnc731f4472020-03-12 04:25:18 -07002382
2383 return ClearControlFrame(frame);
2384 }));
bnc4ff60622019-08-09 18:55:45 -07002385 session_.OnStreamFrame(frame);
2386
2387 PendingStream* pending =
2388 QuicSessionPeer::GetPendingStream(&session_, stream_id);
2389 if (fin) {
2390 // Stream is closed if FIN is received.
2391 EXPECT_FALSE(pending);
2392 } else {
2393 ASSERT_TRUE(pending);
2394 // The pending stream must ignore read data.
2395 EXPECT_TRUE(pending->sequencer()->ignore_read_data());
2396 }
2397
2398 stream_id += QuicUtils::StreamIdDelta(transport_version());
2399 }
renjietang0c558862019-05-08 13:26:23 -07002400}
2401
2402TEST_P(QuicSpdySessionTestServer, SimplePendingStreamTypeOutOfOrderDelivery) {
renjietanga29a96a2019-10-10 12:47:50 -07002403 if (!VersionUsesHttp3(transport_version())) {
renjietang0c558862019-05-08 13:26:23 -07002404 return;
2405 }
fayang29ce0bd2020-10-29 08:28:44 -07002406 CompleteHandshake();
bnc4ff60622019-08-09 18:55:45 -07002407 char input[] = {0x04, // type
2408 'a', 'b', 'c'}; // data
vasilvvfe1c8f32020-10-19 14:10:59 -07002409 absl::string_view payload(input, ABSL_ARRAYSIZE(input));
renjietang0c558862019-05-08 13:26:23 -07002410
bnc4ff60622019-08-09 18:55:45 -07002411 // This is a server test with a client-initiated unidirectional stream.
2412 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
2413 transport_version(), Perspective::IS_CLIENT);
2414
2415 for (bool fin : {true, false}) {
2416 QuicStreamFrame frame1(stream_id, /* fin = */ false, /* offset = */ 0,
2417 payload.substr(0, 1));
2418 QuicStreamFrame frame2(stream_id, fin, /* offset = */ 1, payload.substr(1));
2419
2420 // Deliver frames out of order.
2421 session_.OnStreamFrame(frame2);
2422 // A STOP_SENDING frame is sent in response to the unknown stream type.
2423 EXPECT_CALL(*connection_, SendControlFrame(_))
2424 .WillOnce(Invoke(&VerifyAndClearStopSendingFrame));
2425 session_.OnStreamFrame(frame1);
2426
2427 PendingStream* pending =
2428 QuicSessionPeer::GetPendingStream(&session_, stream_id);
2429 if (fin) {
2430 // Stream is closed if FIN is received.
2431 EXPECT_FALSE(pending);
2432 } else {
2433 ASSERT_TRUE(pending);
2434 // The pending stream must ignore read data.
2435 EXPECT_TRUE(pending->sequencer()->ignore_read_data());
2436 }
2437
2438 stream_id += QuicUtils::StreamIdDelta(transport_version());
2439 }
renjietang0c558862019-05-08 13:26:23 -07002440}
2441
2442TEST_P(QuicSpdySessionTestServer,
2443 MultipleBytesPendingStreamTypeOutOfOrderDelivery) {
renjietanga29a96a2019-10-10 12:47:50 -07002444 if (!VersionUsesHttp3(transport_version())) {
renjietang0c558862019-05-08 13:26:23 -07002445 return;
2446 }
fayang29ce0bd2020-10-29 08:28:44 -07002447 CompleteHandshake();
bnc4ff60622019-08-09 18:55:45 -07002448 char input[] = {0x41, 0x00, // type (256)
2449 'a', 'b', 'c'}; // data
vasilvvfe1c8f32020-10-19 14:10:59 -07002450 absl::string_view payload(input, ABSL_ARRAYSIZE(input));
renjietang0c558862019-05-08 13:26:23 -07002451
bnc4ff60622019-08-09 18:55:45 -07002452 // This is a server test with a client-initiated unidirectional stream.
2453 QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
2454 transport_version(), Perspective::IS_CLIENT);
renjietang0c558862019-05-08 13:26:23 -07002455
bnc4ff60622019-08-09 18:55:45 -07002456 for (bool fin : {true, false}) {
2457 QuicStreamFrame frame1(stream_id, /* fin = */ false, /* offset = */ 0,
2458 payload.substr(0, 1));
2459 QuicStreamFrame frame2(stream_id, /* fin = */ false, /* offset = */ 1,
2460 payload.substr(1, 1));
2461 QuicStreamFrame frame3(stream_id, fin, /* offset = */ 2, payload.substr(2));
renjietang0c558862019-05-08 13:26:23 -07002462
bnc4ff60622019-08-09 18:55:45 -07002463 // Deliver frames out of order.
2464 session_.OnStreamFrame(frame3);
2465 // The first byte does not contain the entire type varint.
2466 session_.OnStreamFrame(frame1);
2467 // A STOP_SENDING frame is sent in response to the unknown stream type.
2468 EXPECT_CALL(*connection_, SendControlFrame(_))
2469 .WillOnce(Invoke(&VerifyAndClearStopSendingFrame));
2470 session_.OnStreamFrame(frame2);
2471
2472 PendingStream* pending =
2473 QuicSessionPeer::GetPendingStream(&session_, stream_id);
2474 if (fin) {
2475 // Stream is closed if FIN is received.
2476 EXPECT_FALSE(pending);
2477 } else {
2478 ASSERT_TRUE(pending);
2479 // The pending stream must ignore read data.
2480 EXPECT_TRUE(pending->sequencer()->ignore_read_data());
2481 }
2482
2483 stream_id += QuicUtils::StreamIdDelta(transport_version());
2484 }
renjietang0c558862019-05-08 13:26:23 -07002485}
2486
renjietang3a1bb802019-06-11 10:42:41 -07002487TEST_P(QuicSpdySessionTestServer, ReceiveControlStream) {
renjietanga29a96a2019-10-10 12:47:50 -07002488 if (!VersionUsesHttp3(transport_version())) {
renjietang3a1bb802019-06-11 10:42:41 -07002489 return;
2490 }
bncb9d5e792020-03-20 17:43:41 -07002491
renjietang7712ed72020-03-25 14:07:30 -07002492 CompleteHandshake();
bncb9d5e792020-03-20 17:43:41 -07002493 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2494 session_.set_debug_visitor(&debug_visitor);
2495
bnca0c8f5a2019-08-04 11:49:03 -07002496 // Use an arbitrary stream id.
renjietang3a1bb802019-06-11 10:42:41 -07002497 QuicStreamId stream_id =
2498 GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
2499 char type[] = {kControlStream};
2500
vasilvve2707e32020-10-08 12:27:46 -07002501 QuicStreamFrame data1(stream_id, false, 0, absl::string_view(type, 1));
bncb9d5e792020-03-20 17:43:41 -07002502 EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id));
renjietang3a1bb802019-06-11 10:42:41 -07002503 session_.OnStreamFrame(data1);
2504 EXPECT_EQ(stream_id,
2505 QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
2506
2507 SettingsFrame settings;
bnca0c8f5a2019-08-04 11:49:03 -07002508 settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 512;
renjietang4e9714d2020-09-21 15:25:23 -07002509 settings.values[SETTINGS_MAX_FIELD_SECTION_SIZE] = 5;
bnca0c8f5a2019-08-04 11:49:03 -07002510 settings.values[SETTINGS_QPACK_BLOCKED_STREAMS] = 42;
renjietang3a1bb802019-06-11 10:42:41 -07002511 std::string data = EncodeSettings(settings);
vasilvve2707e32020-10-08 12:27:46 -07002512 QuicStreamFrame frame(stream_id, false, 1, absl::string_view(data));
renjietang3a1bb802019-06-11 10:42:41 -07002513
bnca0c8f5a2019-08-04 11:49:03 -07002514 QpackEncoder* qpack_encoder = session_.qpack_encoder();
2515 QpackHeaderTable* header_table =
2516 QpackEncoderPeer::header_table(qpack_encoder);
2517
2518 EXPECT_NE(512u,
2519 QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table));
renjietang3a1bb802019-06-11 10:42:41 -07002520 EXPECT_NE(5u, session_.max_outbound_header_list_size());
bnca0c8f5a2019-08-04 11:49:03 -07002521 EXPECT_NE(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
2522
renjietanga6d47372019-09-27 14:17:56 -07002523 EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
renjietang3a1bb802019-06-11 10:42:41 -07002524 session_.OnStreamFrame(frame);
bnca0c8f5a2019-08-04 11:49:03 -07002525
2526 EXPECT_EQ(512u,
2527 QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table));
renjietang3a1bb802019-06-11 10:42:41 -07002528 EXPECT_EQ(5u, session_.max_outbound_header_list_size());
bnca0c8f5a2019-08-04 11:49:03 -07002529 EXPECT_EQ(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
renjietang3a1bb802019-06-11 10:42:41 -07002530}
2531
2532TEST_P(QuicSpdySessionTestServer, ReceiveControlStreamOutOfOrderDelivery) {
renjietanga29a96a2019-10-10 12:47:50 -07002533 if (!VersionUsesHttp3(transport_version())) {
renjietang3a1bb802019-06-11 10:42:41 -07002534 return;
2535 }
2536 // Use an arbitrary stream id.
2537 QuicStreamId stream_id =
2538 GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
2539 char type[] = {kControlStream};
2540 SettingsFrame settings;
renjietang21fc64c2020-09-22 10:59:50 -07002541 settings.values[10] = 2;
renjietang4e9714d2020-09-21 15:25:23 -07002542 settings.values[SETTINGS_MAX_FIELD_SECTION_SIZE] = 5;
renjietang3a1bb802019-06-11 10:42:41 -07002543 std::string data = EncodeSettings(settings);
2544
vasilvve2707e32020-10-08 12:27:46 -07002545 QuicStreamFrame data1(stream_id, false, 1, absl::string_view(data));
2546 QuicStreamFrame data2(stream_id, false, 0, absl::string_view(type, 1));
renjietang3a1bb802019-06-11 10:42:41 -07002547
2548 session_.OnStreamFrame(data1);
2549 EXPECT_NE(5u, session_.max_outbound_header_list_size());
2550 session_.OnStreamFrame(data2);
2551 EXPECT_EQ(5u, session_.max_outbound_header_list_size());
2552}
2553
bnc2f2b7422019-10-02 18:10:43 -07002554// Regression test for https://crbug.com/1009551.
2555TEST_P(QuicSpdySessionTestServer, StreamClosedWhileHeaderDecodingBlocked) {
renjietanga29a96a2019-10-10 12:47:50 -07002556 if (!VersionUsesHttp3(transport_version())) {
bnc2f2b7422019-10-02 18:10:43 -07002557 return;
2558 }
fayang29ce0bd2020-10-29 08:28:44 -07002559 CompleteHandshake();
bnc2f2b7422019-10-02 18:10:43 -07002560 session_.qpack_decoder()->OnSetDynamicTableCapacity(1024);
2561
2562 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
2563 TestStream* stream = session_.CreateIncomingStream(stream_id);
2564
2565 // HEADERS frame referencing first dynamic table entry.
vasilvv72b789c2020-10-27 17:39:17 -07002566 std::string headers_payload = absl::HexStringToBytes("020080");
bnc2f2b7422019-10-02 18:10:43 -07002567 std::unique_ptr<char[]> headers_buffer;
bnc2f2b7422019-10-02 18:10:43 -07002568 QuicByteCount headers_frame_header_length =
bnc46942722019-10-29 11:56:21 -07002569 HttpEncoder::SerializeHeadersFrameHeader(headers_payload.length(),
2570 &headers_buffer);
vasilvve2707e32020-10-08 12:27:46 -07002571 absl::string_view headers_frame_header(headers_buffer.get(),
2572 headers_frame_header_length);
vasilvva163b382020-12-04 11:47:46 -08002573 std::string headers = absl::StrCat(headers_frame_header, headers_payload);
bnc2f2b7422019-10-02 18:10:43 -07002574 stream->OnStreamFrame(QuicStreamFrame(stream_id, false, 0, headers));
2575
2576 // Decoding is blocked because dynamic table entry has not been received yet.
2577 EXPECT_FALSE(stream->headers_decompressed());
2578
2579 // Stream is closed and destroyed.
2580 CloseStream(stream_id);
2581 session_.CleanUpClosedStreams();
2582
2583 // Dynamic table entry arrived on the decoder stream.
2584 // The destroyed stream object must not be referenced.
2585 session_.qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
2586}
2587
bnc45a573a2019-10-04 09:30:02 -07002588// Regression test for https://crbug.com/1011294.
2589TEST_P(QuicSpdySessionTestServer, SessionDestroyedWhileHeaderDecodingBlocked) {
renjietanga29a96a2019-10-10 12:47:50 -07002590 if (!VersionUsesHttp3(transport_version())) {
bnc45a573a2019-10-04 09:30:02 -07002591 return;
2592 }
2593
2594 session_.qpack_decoder()->OnSetDynamicTableCapacity(1024);
2595
2596 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
2597 TestStream* stream = session_.CreateIncomingStream(stream_id);
2598
2599 // HEADERS frame referencing first dynamic table entry.
vasilvv72b789c2020-10-27 17:39:17 -07002600 std::string headers_payload = absl::HexStringToBytes("020080");
bnc45a573a2019-10-04 09:30:02 -07002601 std::unique_ptr<char[]> headers_buffer;
bnc45a573a2019-10-04 09:30:02 -07002602 QuicByteCount headers_frame_header_length =
bnc46942722019-10-29 11:56:21 -07002603 HttpEncoder::SerializeHeadersFrameHeader(headers_payload.length(),
2604 &headers_buffer);
vasilvve2707e32020-10-08 12:27:46 -07002605 absl::string_view headers_frame_header(headers_buffer.get(),
2606 headers_frame_header_length);
vasilvva163b382020-12-04 11:47:46 -08002607 std::string headers = absl::StrCat(headers_frame_header, headers_payload);
bnc45a573a2019-10-04 09:30:02 -07002608 stream->OnStreamFrame(QuicStreamFrame(stream_id, false, 0, headers));
2609
2610 // Decoding is blocked because dynamic table entry has not been received yet.
2611 EXPECT_FALSE(stream->headers_decompressed());
2612
2613 // |session_| gets destoyed. That destroys QpackDecoder, a member of
2614 // QuicSpdySession (derived class), which destroys QpackHeaderTable.
2615 // Then |*stream|, owned by QuicSession (base class) get destroyed, which
2616 // destroys QpackProgessiveDecoder, a registered Observer of QpackHeaderTable.
2617 // This must not cause a crash.
2618}
2619
bnc4ff60622019-08-09 18:55:45 -07002620TEST_P(QuicSpdySessionTestClient, ResetAfterInvalidIncomingStreamType) {
renjietanga29a96a2019-10-10 12:47:50 -07002621 if (!VersionUsesHttp3(transport_version())) {
bnc4ff60622019-08-09 18:55:45 -07002622 return;
2623 }
fayang29ce0bd2020-10-29 08:28:44 -07002624 CompleteHandshake();
bnc4ff60622019-08-09 18:55:45 -07002625 ASSERT_TRUE(session_.UsesPendingStreams());
2626
2627 const QuicStreamId stream_id =
2628 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2629
2630 // Payload consists of two bytes. The first byte is an unknown unidirectional
2631 // stream type. The second one would be the type of a push stream, but it
2632 // must not be interpreted as stream type.
vasilvv72b789c2020-10-27 17:39:17 -07002633 std::string payload = absl::HexStringToBytes("3f01");
bnc4ff60622019-08-09 18:55:45 -07002634 QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0,
2635 payload);
2636
2637 // A STOP_SENDING frame is sent in response to the unknown stream type.
2638 EXPECT_CALL(*connection_, SendControlFrame(_))
2639 .WillOnce(Invoke(&VerifyAndClearStopSendingFrame));
2640 session_.OnStreamFrame(frame);
2641
2642 // There are no active streams.
fayang01591ae2020-04-23 14:14:56 -07002643 EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
bnc4ff60622019-08-09 18:55:45 -07002644
2645 // The pending stream is still around, because it did not receive a FIN.
2646 PendingStream* pending =
2647 QuicSessionPeer::GetPendingStream(&session_, stream_id);
2648 ASSERT_TRUE(pending);
2649
2650 // The pending stream must ignore read data.
2651 EXPECT_TRUE(pending->sequencer()->ignore_read_data());
2652
2653 // If the stream frame is received again, it should be ignored.
2654 session_.OnStreamFrame(frame);
2655
2656 // Receive RESET_STREAM.
2657 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_id,
2658 QUIC_STREAM_CANCELLED,
2659 /* bytes_written = */ payload.size());
2660
bnc4ff60622019-08-09 18:55:45 -07002661 session_.OnRstStream(rst_frame);
2662
2663 // The stream is closed.
2664 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
2665}
2666
2667TEST_P(QuicSpdySessionTestClient, FinAfterInvalidIncomingStreamType) {
renjietanga29a96a2019-10-10 12:47:50 -07002668 if (!VersionUsesHttp3(transport_version())) {
bnc4ff60622019-08-09 18:55:45 -07002669 return;
2670 }
fayang29ce0bd2020-10-29 08:28:44 -07002671 CompleteHandshake();
bnc4ff60622019-08-09 18:55:45 -07002672 ASSERT_TRUE(session_.UsesPendingStreams());
2673
2674 const QuicStreamId stream_id =
2675 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2676
2677 // Payload consists of two bytes. The first byte is an unknown unidirectional
2678 // stream type. The second one would be the type of a push stream, but it
2679 // must not be interpreted as stream type.
vasilvv72b789c2020-10-27 17:39:17 -07002680 std::string payload = absl::HexStringToBytes("3f01");
bnc4ff60622019-08-09 18:55:45 -07002681 QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0,
2682 payload);
2683
2684 // A STOP_SENDING frame is sent in response to the unknown stream type.
2685 EXPECT_CALL(*connection_, SendControlFrame(_))
2686 .WillOnce(Invoke(&VerifyAndClearStopSendingFrame));
2687 session_.OnStreamFrame(frame);
2688
2689 // The pending stream is still around, because it did not receive a FIN.
2690 PendingStream* pending =
2691 QuicSessionPeer::GetPendingStream(&session_, stream_id);
2692 EXPECT_TRUE(pending);
2693
2694 // The pending stream must ignore read data.
2695 EXPECT_TRUE(pending->sequencer()->ignore_read_data());
2696
2697 // If the stream frame is received again, it should be ignored.
2698 session_.OnStreamFrame(frame);
2699
2700 // Receive FIN.
2701 session_.OnStreamFrame(QuicStreamFrame(stream_id, /* fin = */ true,
2702 /* offset = */ payload.size(), ""));
2703
2704 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
2705}
2706
2707TEST_P(QuicSpdySessionTestClient, ResetInMiddleOfStreamType) {
renjietanga29a96a2019-10-10 12:47:50 -07002708 if (!VersionUsesHttp3(transport_version())) {
bnc4ff60622019-08-09 18:55:45 -07002709 return;
2710 }
2711 ASSERT_TRUE(session_.UsesPendingStreams());
2712
2713 const QuicStreamId stream_id =
2714 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2715
2716 // Payload is the first byte of a two byte varint encoding.
vasilvv72b789c2020-10-27 17:39:17 -07002717 std::string payload = absl::HexStringToBytes("40");
bnc4ff60622019-08-09 18:55:45 -07002718 QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0,
2719 payload);
2720
2721 session_.OnStreamFrame(frame);
2722 EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
2723
2724 // Receive RESET_STREAM.
2725 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_id,
2726 QUIC_STREAM_CANCELLED,
2727 /* bytes_written = */ payload.size());
2728
bnc4ff60622019-08-09 18:55:45 -07002729 session_.OnRstStream(rst_frame);
2730
2731 // The stream is closed.
2732 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
2733}
2734
2735TEST_P(QuicSpdySessionTestClient, FinInMiddleOfStreamType) {
renjietanga29a96a2019-10-10 12:47:50 -07002736 if (!VersionUsesHttp3(transport_version())) {
bnc4ff60622019-08-09 18:55:45 -07002737 return;
2738 }
2739 ASSERT_TRUE(session_.UsesPendingStreams());
2740
2741 const QuicStreamId stream_id =
2742 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2743
2744 // Payload is the first byte of a two byte varint encoding with a FIN.
vasilvv72b789c2020-10-27 17:39:17 -07002745 std::string payload = absl::HexStringToBytes("40");
bnc4ff60622019-08-09 18:55:45 -07002746 QuicStreamFrame frame(stream_id, /* fin = */ true, /* offset = */ 0, payload);
2747
2748 session_.OnStreamFrame(frame);
2749 EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
2750}
2751
renjietangd6a35672019-08-15 12:30:08 -07002752TEST_P(QuicSpdySessionTestClient, DuplicateHttp3UnidirectionalStreams) {
renjietanga29a96a2019-10-10 12:47:50 -07002753 if (!VersionUsesHttp3(transport_version())) {
renjietangd6a35672019-08-15 12:30:08 -07002754 return;
2755 }
renjietangaaf85e42019-09-17 10:29:50 -07002756
bncb9d5e792020-03-20 17:43:41 -07002757 StrictMock<MockHttp3DebugVisitor> debug_visitor;
renjietangaaf85e42019-09-17 10:29:50 -07002758 session_.set_debug_visitor(&debug_visitor);
2759
renjietangd6a35672019-08-15 12:30:08 -07002760 QuicStreamId id1 =
2761 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
renjietang309b7fb2019-08-21 12:26:26 -07002762 char type1[] = {kControlStream};
renjietangd6a35672019-08-15 12:30:08 -07002763
vasilvve2707e32020-10-08 12:27:46 -07002764 QuicStreamFrame data1(id1, false, 0, absl::string_view(type1, 1));
renjietangaaf85e42019-09-17 10:29:50 -07002765 EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(id1));
renjietangd6a35672019-08-15 12:30:08 -07002766 session_.OnStreamFrame(data1);
2767 QuicStreamId id2 =
2768 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
vasilvve2707e32020-10-08 12:27:46 -07002769 QuicStreamFrame data2(id2, false, 0, absl::string_view(type1, 1));
renjietangaaf85e42019-09-17 10:29:50 -07002770 EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(id2)).Times(0);
renjietangd6a35672019-08-15 12:30:08 -07002771 EXPECT_CALL(*connection_,
bncec3602c2020-03-12 17:57:59 -07002772 CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
renjietangd6a35672019-08-15 12:30:08 -07002773 "Control stream is received twice.", _));
2774 EXPECT_QUIC_PEER_BUG(
2775 session_.OnStreamFrame(data2),
renjietang309b7fb2019-08-21 12:26:26 -07002776 "Received a duplicate Control stream: Closing connection.");
2777
2778 QuicStreamId id3 =
2779 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 2);
2780 char type2[]{kQpackEncoderStream};
2781
vasilvve2707e32020-10-08 12:27:46 -07002782 QuicStreamFrame data3(id3, false, 0, absl::string_view(type2, 1));
renjietangaaf85e42019-09-17 10:29:50 -07002783 EXPECT_CALL(debug_visitor, OnPeerQpackEncoderStreamCreated(id3));
renjietang309b7fb2019-08-21 12:26:26 -07002784 session_.OnStreamFrame(data3);
2785
2786 QuicStreamId id4 =
2787 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
vasilvve2707e32020-10-08 12:27:46 -07002788 QuicStreamFrame data4(id4, false, 0, absl::string_view(type2, 1));
renjietangaaf85e42019-09-17 10:29:50 -07002789 EXPECT_CALL(debug_visitor, OnPeerQpackEncoderStreamCreated(id4)).Times(0);
renjietang309b7fb2019-08-21 12:26:26 -07002790 EXPECT_CALL(*connection_,
bncec3602c2020-03-12 17:57:59 -07002791 CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
renjietang309b7fb2019-08-21 12:26:26 -07002792 "QPACK encoder stream is received twice.", _));
2793 EXPECT_QUIC_PEER_BUG(
2794 session_.OnStreamFrame(data4),
2795 "Received a duplicate QPACK encoder stream: Closing connection.");
2796
2797 QuicStreamId id5 =
2798 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 4);
2799 char type3[]{kQpackDecoderStream};
2800
vasilvve2707e32020-10-08 12:27:46 -07002801 QuicStreamFrame data5(id5, false, 0, absl::string_view(type3, 1));
renjietangaaf85e42019-09-17 10:29:50 -07002802 EXPECT_CALL(debug_visitor, OnPeerQpackDecoderStreamCreated(id5));
renjietang309b7fb2019-08-21 12:26:26 -07002803 session_.OnStreamFrame(data5);
2804
2805 QuicStreamId id6 =
2806 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 5);
vasilvve2707e32020-10-08 12:27:46 -07002807 QuicStreamFrame data6(id6, false, 0, absl::string_view(type3, 1));
renjietangaaf85e42019-09-17 10:29:50 -07002808 EXPECT_CALL(debug_visitor, OnPeerQpackDecoderStreamCreated(id6)).Times(0);
renjietang309b7fb2019-08-21 12:26:26 -07002809 EXPECT_CALL(*connection_,
bncec3602c2020-03-12 17:57:59 -07002810 CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
renjietang309b7fb2019-08-21 12:26:26 -07002811 "QPACK decoder stream is received twice.", _));
2812 EXPECT_QUIC_PEER_BUG(
2813 session_.OnStreamFrame(data6),
2814 "Received a duplicate QPACK decoder stream: Closing connection.");
renjietangd6a35672019-08-15 12:30:08 -07002815}
2816
bnc331385e2019-09-11 05:02:16 -07002817TEST_P(QuicSpdySessionTestClient, EncoderStreamError) {
renjietanga29a96a2019-10-10 12:47:50 -07002818 if (!VersionUsesHttp3(transport_version())) {
bnc331385e2019-09-11 05:02:16 -07002819 return;
2820 }
2821
vasilvv72b789c2020-10-27 17:39:17 -07002822 std::string data = absl::HexStringToBytes(
bnc331385e2019-09-11 05:02:16 -07002823 "02" // Encoder stream.
2824 "00"); // Duplicate entry 0, but no entries exist.
2825
2826 QuicStreamId stream_id =
2827 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2828
2829 QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0, data);
2830
2831 EXPECT_CALL(
2832 *connection_,
bnc4e440102020-10-20 17:32:29 -07002833 CloseConnection(
2834 GetQuicReloadableFlag(quic_granular_qpack_error_codes)
2835 ? QUIC_QPACK_ENCODER_STREAM_DUPLICATE_INVALID_RELATIVE_INDEX
2836 : QUIC_QPACK_ENCODER_STREAM_ERROR,
2837 "Encoder stream error: Invalid relative index.", _));
bnc331385e2019-09-11 05:02:16 -07002838 session_.OnStreamFrame(frame);
2839}
2840
2841TEST_P(QuicSpdySessionTestClient, DecoderStreamError) {
renjietanga29a96a2019-10-10 12:47:50 -07002842 if (!VersionUsesHttp3(transport_version())) {
bnc331385e2019-09-11 05:02:16 -07002843 return;
2844 }
2845
vasilvv72b789c2020-10-27 17:39:17 -07002846 std::string data = absl::HexStringToBytes(
bnc331385e2019-09-11 05:02:16 -07002847 "03" // Decoder stream.
2848 "00"); // Insert Count Increment with forbidden increment value of zero.
2849
2850 QuicStreamId stream_id =
2851 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2852
2853 QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0, data);
2854
2855 EXPECT_CALL(
2856 *connection_,
bnc4e440102020-10-20 17:32:29 -07002857 CloseConnection(GetQuicReloadableFlag(quic_granular_qpack_error_codes)
2858 ? QUIC_QPACK_DECODER_STREAM_INVALID_ZERO_INCREMENT
2859 : QUIC_QPACK_DECODER_STREAM_ERROR,
bnc331385e2019-09-11 05:02:16 -07002860 "Decoder stream error: Invalid increment value 0.", _));
2861 session_.OnStreamFrame(frame);
2862}
2863
renjietang686ce582019-10-17 14:28:16 -07002864TEST_P(QuicSpdySessionTestClient, InvalidHttp3GoAway) {
2865 if (!VersionUsesHttp3(transport_version())) {
2866 return;
2867 }
bnc5f7d0e82020-09-14 10:31:58 -07002868 EXPECT_CALL(*connection_,
2869 CloseConnection(QUIC_HTTP_GOAWAY_INVALID_STREAM_ID,
2870 "GOAWAY with invalid stream ID", _));
renjietang686ce582019-10-17 14:28:16 -07002871 QuicStreamId stream_id =
2872 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
2873 session_.OnHttp3GoAway(stream_id);
2874}
2875
bncaf8e3302020-07-27 07:42:59 -07002876TEST_P(QuicSpdySessionTestClient, Http3GoAwayLargerIdThanBefore) {
2877 if (!VersionUsesHttp3(transport_version())) {
2878 return;
2879 }
bncaf8e3302020-07-27 07:42:59 -07002880
bnc3988f572020-08-27 05:27:04 -07002881 EXPECT_FALSE(session_.goaway_received());
bncaf8e3302020-07-27 07:42:59 -07002882 QuicStreamId stream_id1 =
2883 GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
2884 session_.OnHttp3GoAway(stream_id1);
bnc3988f572020-08-27 05:27:04 -07002885 EXPECT_TRUE(session_.goaway_received());
bncaf8e3302020-07-27 07:42:59 -07002886
2887 EXPECT_CALL(
2888 *connection_,
2889 CloseConnection(
2890 QUIC_HTTP_GOAWAY_ID_LARGER_THAN_PREVIOUS,
2891 "GOAWAY received with ID 4 greater than previously received ID 0",
2892 _));
2893 QuicStreamId stream_id2 =
2894 GetNthClientInitiatedBidirectionalStreamId(transport_version(), 1);
2895 session_.OnHttp3GoAway(stream_id2);
2896}
2897
bnc1618f0d2020-03-19 07:18:44 -07002898// Test that receipt of CANCEL_PUSH frame does not result in closing the
2899// connection.
2900// TODO(b/151841240): Handle CANCEL_PUSH frames instead of ignoring them.
2901TEST_P(QuicSpdySessionTestClient, IgnoreCancelPush) {
2902 if (!VersionUsesHttp3(transport_version())) {
2903 return;
2904 }
2905
bncb9d5e792020-03-20 17:43:41 -07002906 StrictMock<MockHttp3DebugVisitor> debug_visitor;
2907 session_.set_debug_visitor(&debug_visitor);
2908
bnc1618f0d2020-03-19 07:18:44 -07002909 // Create control stream.
2910 QuicStreamId receive_control_stream_id =
2911 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
2912 char type[] = {kControlStream};
vasilvve2707e32020-10-08 12:27:46 -07002913 absl::string_view stream_type(type, 1);
bnc1618f0d2020-03-19 07:18:44 -07002914 QuicStreamOffset offset = 0;
2915 QuicStreamFrame data1(receive_control_stream_id, /* fin = */ false, offset,
2916 stream_type);
2917 offset += stream_type.length();
bncb9d5e792020-03-20 17:43:41 -07002918 EXPECT_CALL(debug_visitor,
2919 OnPeerControlStreamCreated(receive_control_stream_id));
bnc1618f0d2020-03-19 07:18:44 -07002920 session_.OnStreamFrame(data1);
2921 EXPECT_EQ(receive_control_stream_id,
2922 QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
2923
bncf72ef0b2020-04-02 06:59:32 -07002924 // First frame has to be SETTINGS.
2925 std::string serialized_settings = EncodeSettings({});
2926 QuicStreamFrame data2(receive_control_stream_id, /* fin = */ false, offset,
2927 serialized_settings);
2928 offset += serialized_settings.length();
2929 EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
2930 session_.OnStreamFrame(data2);
2931
bnc1618f0d2020-03-19 07:18:44 -07002932 CancelPushFrame cancel_push{/* push_id = */ 0};
2933 std::unique_ptr<char[]> buffer;
2934 auto frame_length =
2935 HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
bncf72ef0b2020-04-02 06:59:32 -07002936 QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
vasilvve2707e32020-10-08 12:27:46 -07002937 absl::string_view(buffer.get(), frame_length));
bncb9d5e792020-03-20 17:43:41 -07002938 EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
bncf72ef0b2020-04-02 06:59:32 -07002939 session_.OnStreamFrame(data3);
bnc1618f0d2020-03-19 07:18:44 -07002940}
2941
bnc7a69d552020-03-17 07:05:16 -07002942TEST_P(QuicSpdySessionTestServer, ServerPushEnabledDefaultValue) {
2943 if (VersionUsesHttp3(transport_version())) {
2944 EXPECT_FALSE(session_.server_push_enabled());
2945 } else {
2946 EXPECT_TRUE(session_.server_push_enabled());
2947 }
2948}
2949
bnc92fa63a2020-02-04 05:13:43 -08002950TEST_P(QuicSpdySessionTestServer, OnSetting) {
renjietang7712ed72020-03-25 14:07:30 -07002951 CompleteHandshake();
bnc92fa63a2020-02-04 05:13:43 -08002952 if (VersionUsesHttp3(transport_version())) {
2953 EXPECT_EQ(std::numeric_limits<size_t>::max(),
2954 session_.max_outbound_header_list_size());
renjietang4e9714d2020-09-21 15:25:23 -07002955 session_.OnSetting(SETTINGS_MAX_FIELD_SECTION_SIZE, 5);
bnc92fa63a2020-02-04 05:13:43 -08002956 EXPECT_EQ(5u, session_.max_outbound_header_list_size());
2957
renjietang7712ed72020-03-25 14:07:30 -07002958 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
2959 .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
bnc92fa63a2020-02-04 05:13:43 -08002960 QpackEncoder* qpack_encoder = session_.qpack_encoder();
2961 EXPECT_EQ(0u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
2962 session_.OnSetting(SETTINGS_QPACK_BLOCKED_STREAMS, 12);
2963 EXPECT_EQ(12u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
2964
2965 QpackHeaderTable* header_table =
2966 QpackEncoderPeer::header_table(qpack_encoder);
2967 EXPECT_EQ(0u, header_table->maximum_dynamic_table_capacity());
2968 session_.OnSetting(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 37);
2969 EXPECT_EQ(37u, header_table->maximum_dynamic_table_capacity());
2970
2971 return;
2972 }
2973
2974 EXPECT_EQ(std::numeric_limits<size_t>::max(),
2975 session_.max_outbound_header_list_size());
renjietang4e9714d2020-09-21 15:25:23 -07002976 session_.OnSetting(SETTINGS_MAX_FIELD_SECTION_SIZE, 5);
bnc92fa63a2020-02-04 05:13:43 -08002977 EXPECT_EQ(5u, session_.max_outbound_header_list_size());
2978
2979 EXPECT_TRUE(session_.server_push_enabled());
2980 session_.OnSetting(spdy::SETTINGS_ENABLE_PUSH, 0);
2981 EXPECT_FALSE(session_.server_push_enabled());
2982
2983 spdy::HpackEncoder* hpack_encoder =
2984 QuicSpdySessionPeer::GetSpdyFramer(&session_)->GetHpackEncoder();
2985 EXPECT_EQ(4096u, hpack_encoder->CurrentHeaderTableSizeSetting());
2986 session_.OnSetting(spdy::SETTINGS_HEADER_TABLE_SIZE, 59);
2987 EXPECT_EQ(59u, hpack_encoder->CurrentHeaderTableSizeSetting());
2988}
2989
bnc77b46412020-02-21 08:09:09 -08002990TEST_P(QuicSpdySessionTestServer, FineGrainedHpackErrorCodes) {
2991 if (VersionUsesHttp3(transport_version())) {
2992 // HPACK is not used in HTTP/3.
2993 return;
2994 }
2995
bnc77b46412020-02-21 08:09:09 -08002996 QuicStreamId request_stream_id = 5;
2997 session_.CreateIncomingStream(request_stream_id);
2998
2999 // Index 126 does not exist (static table has 61 entries and dynamic table is
3000 // empty).
vasilvv72b789c2020-10-27 17:39:17 -07003001 std::string headers_frame = absl::HexStringToBytes(
bnc77b46412020-02-21 08:09:09 -08003002 "000006" // length
3003 "01" // type
3004 "24" // flags: PRIORITY | END_HEADERS
3005 "00000005" // stream_id
3006 "00000000" // stream dependency
3007 "10" // weight
3008 "fe"); // payload: reference to index 126.
3009 QuicStreamId headers_stream_id =
3010 QuicUtils::GetHeadersStreamId(transport_version());
3011 QuicStreamFrame data(headers_stream_id, false, 0, headers_frame);
3012
3013 EXPECT_CALL(
3014 *connection_,
3015 CloseConnection(QUIC_HPACK_INVALID_INDEX,
3016 "SPDY framing error: HPACK_INVALID_INDEX",
3017 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
3018 session_.OnStreamFrame(data);
3019}
3020
bnc09c1eda2020-03-13 04:52:38 -07003021TEST_P(QuicSpdySessionTestServer, PeerClosesCriticalReceiveStream) {
3022 if (!VersionUsesHttp3(transport_version())) {
3023 return;
3024 }
3025
3026 struct {
3027 char type;
3028 const char* error_details;
3029 } kTestData[] = {
3030 {kControlStream, "RESET_STREAM received for receive control stream"},
3031 {kQpackEncoderStream, "RESET_STREAM received for QPACK receive stream"},
3032 {kQpackDecoderStream, "RESET_STREAM received for QPACK receive stream"},
3033 };
vasilvvfe1c8f32020-10-19 14:10:59 -07003034 for (size_t i = 0; i < ABSL_ARRAYSIZE(kTestData); ++i) {
bnc09c1eda2020-03-13 04:52:38 -07003035 QuicStreamId stream_id =
3036 GetNthClientInitiatedUnidirectionalStreamId(transport_version(), i + 1);
3037 const QuicByteCount data_length = 1;
vasilvve2707e32020-10-08 12:27:46 -07003038 QuicStreamFrame data(stream_id, false, 0,
3039 absl::string_view(&kTestData[i].type, data_length));
bnc09c1eda2020-03-13 04:52:38 -07003040 session_.OnStreamFrame(data);
3041
3042 EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
3043 kTestData[i].error_details, _));
3044
3045 QuicRstStreamFrame rst(kInvalidControlFrameId, stream_id,
3046 QUIC_STREAM_CANCELLED, data_length);
3047 session_.OnRstStream(rst);
3048 }
3049}
3050
fayangb4c1dac2020-05-29 14:46:25 -07003051TEST_P(QuicSpdySessionTestServer,
3052 H3ControlStreamsLimitedByConnectionFlowControl) {
3053 if (!VersionUsesHttp3(transport_version())) {
3054 return;
3055 }
3056 // Ensure connection level flow control blockage.
3057 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
3058 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
3059
3060 QuicSendControlStream* send_control_stream =
3061 QuicSpdySessionPeer::GetSendControlStream(&session_);
3062 // Mark send_control stream write blocked.
3063 session_.MarkConnectionLevelWriteBlocked(send_control_stream->id());
fayangfaad93f2020-07-06 08:44:49 -07003064 EXPECT_FALSE(session_.WillingAndAbleToWrite());
fayangb4c1dac2020-05-29 14:46:25 -07003065}
3066
bnc09c1eda2020-03-13 04:52:38 -07003067TEST_P(QuicSpdySessionTestServer, PeerClosesCriticalSendStream) {
3068 if (!VersionUsesHttp3(transport_version())) {
3069 return;
3070 }
3071
3072 QuicSendControlStream* control_stream =
3073 QuicSpdySessionPeer::GetSendControlStream(&session_);
3074 ASSERT_TRUE(control_stream);
3075
3076 QuicStopSendingFrame stop_sending_control_stream(
bnc187eea32020-09-02 12:16:15 -07003077 kInvalidControlFrameId, control_stream->id(), QUIC_STREAM_CANCELLED);
bnc09c1eda2020-03-13 04:52:38 -07003078 EXPECT_CALL(
3079 *connection_,
3080 CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
3081 "STOP_SENDING received for send control stream", _));
3082 session_.OnStopSendingFrame(stop_sending_control_stream);
3083
3084 QpackSendStream* decoder_stream =
3085 QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
3086 ASSERT_TRUE(decoder_stream);
3087
3088 QuicStopSendingFrame stop_sending_decoder_stream(
bnc187eea32020-09-02 12:16:15 -07003089 kInvalidControlFrameId, decoder_stream->id(), QUIC_STREAM_CANCELLED);
bnc09c1eda2020-03-13 04:52:38 -07003090 EXPECT_CALL(
3091 *connection_,
3092 CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
3093 "STOP_SENDING received for QPACK send stream", _));
3094 session_.OnStopSendingFrame(stop_sending_decoder_stream);
3095
3096 QpackSendStream* encoder_stream =
3097 QuicSpdySessionPeer::GetQpackEncoderSendStream(&session_);
3098 ASSERT_TRUE(encoder_stream);
3099
3100 QuicStopSendingFrame stop_sending_encoder_stream(
bnc187eea32020-09-02 12:16:15 -07003101 kInvalidControlFrameId, encoder_stream->id(), QUIC_STREAM_CANCELLED);
bnc09c1eda2020-03-13 04:52:38 -07003102 EXPECT_CALL(
3103 *connection_,
3104 CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
3105 "STOP_SENDING received for QPACK send stream", _));
3106 session_.OnStopSendingFrame(stop_sending_encoder_stream);
3107}
3108
bnc1618f0d2020-03-19 07:18:44 -07003109// Test that receipt of CANCEL_PUSH frame does not result in closing the
3110// connection.
3111// TODO(b/151841240): Handle CANCEL_PUSH frames instead of ignoring them.
3112TEST_P(QuicSpdySessionTestServer, IgnoreCancelPush) {
3113 if (!VersionUsesHttp3(transport_version())) {
3114 return;
3115 }
3116
bncf72ef0b2020-04-02 06:59:32 -07003117 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3118 session_.set_debug_visitor(&debug_visitor);
3119
bnc1618f0d2020-03-19 07:18:44 -07003120 // Create control stream.
3121 QuicStreamId receive_control_stream_id =
3122 GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
3123 char type[] = {kControlStream};
vasilvve2707e32020-10-08 12:27:46 -07003124 absl::string_view stream_type(type, 1);
bnc1618f0d2020-03-19 07:18:44 -07003125 QuicStreamOffset offset = 0;
3126 QuicStreamFrame data1(receive_control_stream_id, /* fin = */ false, offset,
3127 stream_type);
3128 offset += stream_type.length();
bncf72ef0b2020-04-02 06:59:32 -07003129 EXPECT_CALL(debug_visitor,
3130 OnPeerControlStreamCreated(receive_control_stream_id));
bnc1618f0d2020-03-19 07:18:44 -07003131 session_.OnStreamFrame(data1);
3132 EXPECT_EQ(receive_control_stream_id,
3133 QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
3134
bncf72ef0b2020-04-02 06:59:32 -07003135 // First frame has to be SETTINGS.
3136 std::string serialized_settings = EncodeSettings({});
3137 QuicStreamFrame data2(receive_control_stream_id, /* fin = */ false, offset,
3138 serialized_settings);
3139 offset += serialized_settings.length();
3140 EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
3141 session_.OnStreamFrame(data2);
3142
bnc1618f0d2020-03-19 07:18:44 -07003143 CancelPushFrame cancel_push{/* push_id = */ 0};
3144 std::unique_ptr<char[]> buffer;
3145 auto frame_length =
3146 HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
bncf72ef0b2020-04-02 06:59:32 -07003147 QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
vasilvve2707e32020-10-08 12:27:46 -07003148 absl::string_view(buffer.get(), frame_length));
bncf72ef0b2020-04-02 06:59:32 -07003149 EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
3150 session_.OnStreamFrame(data3);
bnc1618f0d2020-03-19 07:18:44 -07003151}
3152
bncc03d2c22020-10-15 13:30:09 -07003153TEST_P(QuicSpdySessionTestServer, Http3GoAwayWhenClosingConnection) {
3154 if (!VersionUsesHttp3(transport_version())) {
3155 return;
3156 }
3157
3158 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3159 session_.set_debug_visitor(&debug_visitor);
3160
3161 EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
3162 CompleteHandshake();
3163
3164 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
3165
3166 // Create stream by receiving some data (CreateIncomingStream() would not
3167 // update the session's largest peer created stream ID).
3168 const size_t headers_payload_length = 10;
3169 std::unique_ptr<char[]> headers_buffer;
3170 QuicByteCount headers_frame_header_length =
3171 HttpEncoder::SerializeHeadersFrameHeader(headers_payload_length,
3172 &headers_buffer);
3173 absl::string_view headers_frame_header(headers_buffer.get(),
3174 headers_frame_header_length);
3175 EXPECT_CALL(debug_visitor,
3176 OnHeadersFrameReceived(stream_id, headers_payload_length));
3177 session_.OnStreamFrame(
3178 QuicStreamFrame(stream_id, false, 0, headers_frame_header));
3179
3180 EXPECT_EQ(stream_id, QuicSessionPeer::GetLargestPeerCreatedStreamId(
3181 &session_, /*unidirectional = */ false));
3182
3183 if (GetQuicReloadableFlag(quic_send_goaway_with_connection_close)) {
bnc12786302020-11-23 10:50:15 -08003184 // Stream with stream_id is already received and potentially processed,
3185 // therefore a GOAWAY frame is sent with the next stream ID.
3186 EXPECT_CALL(debug_visitor,
3187 OnGoAwayFrameSent(
3188 stream_id + QuicUtils::StreamIdDelta(transport_version())));
bncc03d2c22020-10-15 13:30:09 -07003189 }
3190
3191 // Close connection.
3192 EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
3193 .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
3194 EXPECT_CALL(*connection_, CloseConnection(QUIC_NO_ERROR, _, _))
3195 .WillOnce(
3196 Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
mattm55006b02021-01-14 15:09:54 -08003197 EXPECT_CALL(*connection_, SendConnectionClosePacket(QUIC_NO_ERROR, _, _))
bncc03d2c22020-10-15 13:30:09 -07003198 .WillOnce(Invoke(connection_,
3199 &MockQuicConnection::ReallySendConnectionClosePacket));
3200 connection_->CloseConnection(
3201 QUIC_NO_ERROR, "closing connection",
3202 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
3203}
3204
bnce4031262020-03-30 10:52:57 -07003205TEST_P(QuicSpdySessionTestClient, SendInitialMaxPushIdIfSet) {
3206 if (!VersionUsesHttp3(transport_version())) {
3207 return;
3208 }
3209
3210 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3211 session_.set_debug_visitor(&debug_visitor);
3212
bnc25173022020-04-10 07:05:15 -07003213 const PushId max_push_id = 5;
bnce4031262020-03-30 10:52:57 -07003214 session_.SetMaxPushId(max_push_id);
3215
3216 InSequence s;
3217 EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
3218 const MaxPushIdFrame max_push_id_frame{max_push_id};
3219 EXPECT_CALL(debug_visitor, OnMaxPushIdFrameSent(max_push_id_frame));
3220
3221 CompleteHandshake();
3222}
3223
3224TEST_P(QuicSpdySessionTestClient, DoNotSendInitialMaxPushIdIfNotSet) {
3225 if (!VersionUsesHttp3(transport_version())) {
3226 return;
3227 }
3228
3229 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3230 session_.set_debug_visitor(&debug_visitor);
3231
3232 InSequence s;
3233 EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
3234
3235 CompleteHandshake();
3236}
3237
renjietang6e173ef2020-08-13 18:34:09 -07003238TEST_P(QuicSpdySessionTestClient, DoNotSendInitialMaxPushIdIfSetToDefaut) {
3239 if (!VersionUsesHttp3(transport_version())) {
3240 return;
3241 }
3242
3243 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3244 session_.set_debug_visitor(&debug_visitor);
3245
3246 session_.SetMaxPushId(0);
3247
3248 InSequence s;
3249 EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
3250 CompleteHandshake();
3251}
3252
renjietang21fc64c2020-09-22 10:59:50 -07003253TEST_P(QuicSpdySessionTestClient, ReceiveSpdySettingInHttp3) {
renjietangd2b7cef2020-11-30 13:51:24 -08003254 if (!VersionUsesHttp3(transport_version())) {
renjietang21fc64c2020-09-22 10:59:50 -07003255 return;
3256 }
3257
3258 SettingsFrame frame;
3259 frame.values[SETTINGS_MAX_FIELD_SECTION_SIZE] = 5;
renjietang15be59c2020-09-22 11:19:55 -07003260 // https://datatracker.ietf.org/doc/html/draft-ietf-quic-http-30#section-7.2.4.1
renjietang21fc64c2020-09-22 10:59:50 -07003261 // specifies the presence of HTTP/2 setting as error.
3262 frame.values[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = 100;
3263
3264 CompleteHandshake();
3265
3266 EXPECT_CALL(*connection_,
3267 CloseConnection(QUIC_HTTP_RECEIVE_SPDY_SETTING, _, _));
3268 session_.OnSettingsFrame(frame);
3269}
3270
bnc9be5c212020-12-11 12:38:20 -08003271TEST_P(QuicSpdySessionTestClient, ReceiveAcceptChFrame) {
3272 if (!VersionUsesHttp3(transport_version())) {
3273 return;
3274 }
3275
3276 if (!GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
3277 return;
3278 }
3279
3280 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3281 session_.set_debug_visitor(&debug_visitor);
3282
3283 // Create control stream.
3284 QuicStreamId receive_control_stream_id =
3285 GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
3286 char type[] = {kControlStream};
3287 absl::string_view stream_type(type, 1);
3288 QuicStreamOffset offset = 0;
3289 QuicStreamFrame data1(receive_control_stream_id, /* fin = */ false, offset,
3290 stream_type);
3291 offset += stream_type.length();
3292 EXPECT_CALL(debug_visitor,
3293 OnPeerControlStreamCreated(receive_control_stream_id));
3294
3295 session_.OnStreamFrame(data1);
3296 EXPECT_EQ(receive_control_stream_id,
3297 QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
3298
3299 // First frame has to be SETTINGS.
3300 std::string serialized_settings = EncodeSettings({});
3301 QuicStreamFrame data2(receive_control_stream_id, /* fin = */ false, offset,
3302 serialized_settings);
3303 offset += serialized_settings.length();
3304 EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
3305
3306 session_.OnStreamFrame(data2);
3307
3308 // Receive ACCEPT_CH frame.
3309 AcceptChFrame accept_ch;
3310 accept_ch.entries.push_back({"foo", "bar"});
3311 std::unique_ptr<char[]> buffer;
3312 auto frame_length = HttpEncoder::SerializeAcceptChFrame(accept_ch, &buffer);
3313 QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
3314 absl::string_view(buffer.get(), frame_length));
3315
3316 EXPECT_CALL(debug_visitor, OnAcceptChFrameReceived(accept_ch));
3317 EXPECT_CALL(session_, OnAcceptChFrame(accept_ch));
3318
3319 session_.OnStreamFrame(data3);
3320}
3321
bnc40494612021-01-21 04:50:33 -08003322TEST_P(QuicSpdySessionTestClient, OnAlpsData) {
3323 StrictMock<MockHttp3DebugVisitor> debug_visitor;
3324 session_.set_debug_visitor(&debug_visitor);
3325
3326 AcceptChFrame accept_ch_frame{{{"foo", "bar"}}};
3327 std::string serialized_accept_ch_frame = absl::HexStringToBytes(
3328 "4089" // type (ACCEPT_CH)
3329 "08" // length
3330 "03" // length of origin
3331 "666f6f" // origin "foo"
3332 "03" // length of value
3333 "626172"); // value "bar"
3334
3335 if (GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
3336 EXPECT_CALL(debug_visitor, OnAcceptChFrameReceivedViaAlps(accept_ch_frame));
3337 }
3338
3339 session_.OnAlpsData(
3340 reinterpret_cast<const uint8_t*>(serialized_accept_ch_frame.data()),
3341 serialized_accept_ch_frame.size());
3342}
3343
QUICHE teama6ef0a62019-03-07 20:34:33 -05003344} // namespace
3345} // namespace test
3346} // namespace quic