blob: 83ea72fdb96159a4bf511d50bc648644a1ec8fdb [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
6
7#include <cstdint>
8#include <set>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include <utility>
11
12#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
13#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
14#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
15#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
16#include "net/third_party/quiche/src/quic/core/quic_packets.h"
17#include "net/third_party/quiche/src/quic/core/quic_stream.h"
18#include "net/third_party/quiche/src/quic/core/quic_utils.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050024#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
26#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
27#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
28#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
29#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
30#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
31#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
34#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
35
36using spdy::kV3HighestPriority;
37using spdy::Spdy3PriorityToHttp2Weight;
38using spdy::SpdyFramer;
39using spdy::SpdyHeaderBlock;
40using spdy::SpdyPriority;
41using spdy::SpdyPriorityIR;
42using spdy::SpdySerializedFrame;
43using testing::_;
44using testing::AtLeast;
45using testing::InSequence;
46using testing::Invoke;
47using testing::Return;
48using testing::StrictMock;
49
50namespace quic {
51namespace test {
52namespace {
53
54class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
55 public:
56 explicit TestCryptoStream(QuicSession* session)
57 : QuicCryptoStream(session),
58 QuicCryptoHandshaker(this, session),
59 encryption_established_(false),
60 handshake_confirmed_(false),
61 params_(new QuicCryptoNegotiatedParameters) {}
62
63 void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
64 encryption_established_ = true;
65 handshake_confirmed_ = true;
66 CryptoHandshakeMessage msg;
vasilvvc48c8712019-03-11 13:38:16 -070067 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 session()->config()->SetInitialStreamFlowControlWindowToSend(
69 kInitialStreamFlowControlWindowForTest);
70 session()->config()->SetInitialSessionFlowControlWindowToSend(
71 kInitialSessionFlowControlWindowForTest);
72 session()->config()->ToHandshakeMessage(&msg);
73 const QuicErrorCode error =
74 session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
75 EXPECT_EQ(QUIC_NO_ERROR, error);
76 session()->OnConfigNegotiated();
77 session()->connection()->SetDefaultEncryptionLevel(
78 ENCRYPTION_FORWARD_SECURE);
79 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
80 }
81
82 // QuicCryptoStream implementation
83 bool encryption_established() const override {
84 return encryption_established_;
85 }
86 bool handshake_confirmed() const override { return handshake_confirmed_; }
87 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
88 const override {
89 return *params_;
90 }
91 CryptoMessageParser* crypto_message_parser() override {
92 return QuicCryptoHandshaker::crypto_message_parser();
93 }
94
95 MOCK_METHOD0(OnCanWrite, void());
96
97 bool HasPendingCryptoRetransmission() override { return false; }
98
99 MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
100
101 private:
102 using QuicCryptoStream::session;
103
104 bool encryption_established_;
105 bool handshake_confirmed_;
106 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
107};
108
109class TestHeadersStream : public QuicHeadersStream {
110 public:
111 explicit TestHeadersStream(QuicSpdySession* session)
112 : QuicHeadersStream(session) {}
113
114 MOCK_METHOD0(OnCanWrite, void());
115};
116
117class TestStream : public QuicSpdyStream {
118 public:
119 TestStream(QuicStreamId id, QuicSpdySession* session, StreamType type)
120 : QuicSpdyStream(id, session, type) {}
121
122 TestStream(PendingStream pending, QuicSpdySession* session, StreamType type)
123 : QuicSpdyStream(std::move(pending), session, type) {}
124
125 using QuicStream::CloseWriteSide;
126
127 void OnBodyAvailable() override {}
128
129 MOCK_METHOD0(OnCanWrite, void());
130 MOCK_METHOD3(RetransmitStreamData,
131 bool(QuicStreamOffset, QuicByteCount, bool));
132
133 MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
134};
135
136class TestSession : public QuicSpdySession {
137 public:
138 explicit TestSession(QuicConnection* connection)
139 : QuicSpdySession(connection,
140 nullptr,
141 DefaultQuicConfig(),
142 CurrentSupportedVersions()),
143 crypto_stream_(this),
144 writev_consumes_all_data_(false) {
145 Initialize();
146 this->connection()->SetEncrypter(
147 ENCRYPTION_FORWARD_SECURE,
148 QuicMakeUnique<NullEncrypter>(connection->perspective()));
149 }
150
151 ~TestSession() override { delete connection(); }
152
153 TestCryptoStream* GetMutableCryptoStream() override {
154 return &crypto_stream_;
155 }
156
157 const TestCryptoStream* GetCryptoStream() const override {
158 return &crypto_stream_;
159 }
160
161 TestStream* CreateOutgoingBidirectionalStream() override {
162 TestStream* stream = new TestStream(GetNextOutgoingBidirectionalStreamId(),
163 this, BIDIRECTIONAL);
164 ActivateStream(QuicWrapUnique(stream));
165 return stream;
166 }
167
168 TestStream* CreateOutgoingUnidirectionalStream() override {
169 TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
170 this, WRITE_UNIDIRECTIONAL);
171 ActivateStream(QuicWrapUnique(stream));
172 return stream;
173 }
174
175 TestStream* CreateIncomingStream(QuicStreamId id) override {
176 // Enforce the limit on the number of open streams.
177 if (GetNumOpenIncomingStreams() + 1 >
178 max_open_incoming_bidirectional_streams() &&
179 connection()->transport_version() != QUIC_VERSION_99) {
180 connection()->CloseConnection(
181 QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
182 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
183 return nullptr;
184 } else {
185 TestStream* stream = new TestStream(
186 id, this,
187 DetermineStreamType(id, connection()->transport_version(),
188 perspective(), /*is_incoming=*/true,
189 BIDIRECTIONAL));
190 ActivateStream(QuicWrapUnique(stream));
191 return stream;
192 }
193 }
194
195 TestStream* CreateIncomingStream(PendingStream pending) override {
196 QuicStreamId id = pending.id();
197 TestStream* stream =
198 new TestStream(std::move(pending), this,
199 DetermineStreamType(
200 id, connection()->transport_version(), perspective(),
201 /*is_incoming=*/true, BIDIRECTIONAL));
202 ActivateStream(QuicWrapUnique(stream));
203 return stream;
204 }
205
206 bool ShouldCreateIncomingStream(QuicStreamId /*id*/) override { return true; }
207
208 bool ShouldCreateOutgoingBidirectionalStream() override { return true; }
209 bool ShouldCreateOutgoingUnidirectionalStream() override { return true; }
210
211 bool IsClosedStream(QuicStreamId id) {
212 return QuicSession::IsClosedStream(id);
213 }
214
215 QuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id) {
216 return QuicSpdySession::GetOrCreateDynamicStream(stream_id);
217 }
218
219 QuicConsumedData WritevData(QuicStream* stream,
220 QuicStreamId id,
221 size_t write_length,
222 QuicStreamOffset offset,
223 StreamSendingState state) override {
224 bool fin = state != NO_FIN;
225 QuicConsumedData consumed(write_length, fin);
226 if (!writev_consumes_all_data_) {
227 consumed =
228 QuicSession::WritevData(stream, id, write_length, offset, state);
229 }
230 if (fin && consumed.fin_consumed) {
231 stream->set_fin_sent(true);
232 }
233 QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
234 id, consumed.bytes_consumed);
235 return consumed;
236 }
237
238 void set_writev_consumes_all_data(bool val) {
239 writev_consumes_all_data_ = val;
240 }
241
242 QuicConsumedData SendStreamData(QuicStream* stream) {
243 struct iovec iov;
QUICHE teamdc41bf12019-03-20 12:58:42 -0700244 if ((QuicVersionUsesCryptoFrames(connection()->transport_version()) ||
245 stream->id() !=
246 QuicUtils::GetCryptoStreamId(connection()->transport_version())) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247 connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
248 this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
249 }
250 MakeIOVector("not empty", &iov);
251 QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
252 QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
253 QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
254 consumed.bytes_consumed);
255 return consumed;
256 }
257
258 bool ClearControlFrame(const QuicFrame& frame) {
259 DeleteFrame(&const_cast<QuicFrame&>(frame));
260 return true;
261 }
262
263 QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
264 DCHECK(writev_consumes_all_data_);
265 return WritevData(stream, stream->id(), bytes, 0, FIN);
266 }
267
268 using QuicSession::closed_streams;
269 using QuicSession::zombie_streams;
270 using QuicSpdySession::ShouldBufferIncomingStream;
271
272 private:
273 StrictMock<TestCryptoStream> crypto_stream_;
274
275 bool writev_consumes_all_data_;
276};
277
278class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
279 public:
fkastenholz3c4eabf2019-04-22 07:49:59 -0700280 bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
281 if (frame.type == MAX_STREAMS_FRAME) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500282 DeleteFrame(&const_cast<QuicFrame&>(frame));
283 return true;
284 }
285 return false;
286 }
287
288 protected:
289 explicit QuicSpdySessionTestBase(Perspective perspective)
290 : connection_(
291 new StrictMock<MockQuicConnection>(&helper_,
292 &alarm_factory_,
293 perspective,
294 SupportedVersions(GetParam()))),
295 session_(connection_) {
296 session_.config()->SetInitialStreamFlowControlWindowToSend(
297 kInitialStreamFlowControlWindowForTest);
298 session_.config()->SetInitialSessionFlowControlWindowToSend(
299 kInitialSessionFlowControlWindowForTest);
300 headers_[":host"] = "www.google.com";
301 headers_[":path"] = "/index.hml";
302 headers_[":scheme"] = "http";
303 headers_["cookie"] =
304 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
305 "__utmc=160408618; "
306 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
307 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
308 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
309 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
310 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
311 "1zFMi5vzcns38-8_Sns; "
312 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
313 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
314 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
315 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
316 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
317 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
318 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
319 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
320 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
321 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
322 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
323 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
324 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
325 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
326 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
327 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
328 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
329 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
330 .Times(testing::AnyNumber());
331 }
332
333 void CheckClosedStreams() {
QUICHE teamdc41bf12019-03-20 12:58:42 -0700334 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
335 connection_->transport_version(), Perspective::IS_CLIENT);
336 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
337 first_stream_id =
338 QuicUtils::GetCryptoStreamId(connection_->transport_version());
339 }
340 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500341 if (!QuicContainsKey(closed_streams_, i)) {
342 EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
343 } else {
344 EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
345 }
346 }
347 }
348
349 void CloseStream(QuicStreamId id) {
350 if (!IsVersion99()) {
351 EXPECT_CALL(*connection_, SendControlFrame(_))
352 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
353 } else {
354 // V99 has two frames, RST_STREAM and STOP_SENDING
355 EXPECT_CALL(*connection_, SendControlFrame(_))
356 .Times(2)
357 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
358 }
359 EXPECT_CALL(*connection_, OnStreamReset(id, _));
360 session_.CloseStream(id);
361 closed_streams_.insert(id);
362 }
363
364 QuicTransportVersion transport_version() const {
365 return connection_->transport_version();
366 }
367
368 bool IsVersion99() const { return transport_version() == QUIC_VERSION_99; }
369
370 QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
371 return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
372 }
373
374 QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
375 return GetNthServerInitiatedBidirectionalStreamId(
376 connection_->transport_version(), n);
377 }
378
379 QuicStreamId IdDelta() {
380 return QuicUtils::StreamIdDelta(connection_->transport_version());
381 }
382
fkastenholz3c4eabf2019-04-22 07:49:59 -0700383 QuicStreamId StreamCountToId(QuicStreamCount stream_count,
384 Perspective perspective,
385 bool bidirectional) {
386 // Calculate and build up stream ID rather than use
387 // GetFirst... because the test that relies on this method
388 // needs to do the stream count where #1 is 0/1/2/3, and not
389 // take into account that stream 0 is special.
390 QuicStreamId id =
391 ((stream_count - 1) * QuicUtils::StreamIdDelta(QUIC_VERSION_99));
392 if (!bidirectional) {
393 id |= 0x2;
394 }
395 if (perspective == Perspective::IS_SERVER) {
396 id |= 0x1;
397 }
398 return id;
399 }
400
QUICHE teama6ef0a62019-03-07 20:34:33 -0500401 MockQuicConnectionHelper helper_;
402 MockAlarmFactory alarm_factory_;
403 StrictMock<MockQuicConnection>* connection_;
404 TestSession session_;
405 std::set<QuicStreamId> closed_streams_;
406 SpdyHeaderBlock headers_;
407};
408
409class QuicSpdySessionTestServer : public QuicSpdySessionTestBase {
410 protected:
411 QuicSpdySessionTestServer()
412 : QuicSpdySessionTestBase(Perspective::IS_SERVER) {}
413};
414
415INSTANTIATE_TEST_SUITE_P(Tests,
416 QuicSpdySessionTestServer,
417 ::testing::ValuesIn(AllSupportedVersions()));
418
419TEST_P(QuicSpdySessionTestServer, ShouldBufferIncomingStreamUnidirectional) {
420 if (!IsVersion99()) {
421 return;
422 }
423 EXPECT_TRUE(session_.ShouldBufferIncomingStream(
424 QuicUtils::GetFirstUnidirectionalStreamId(
425 connection_->transport_version(), Perspective::IS_CLIENT)));
426}
427
428TEST_P(QuicSpdySessionTestServer, ShouldBufferIncomingStreamBidirectional) {
429 if (!IsVersion99()) {
430 return;
431 }
432 EXPECT_FALSE(session_.ShouldBufferIncomingStream(
433 QuicUtils::GetFirstBidirectionalStreamId(connection_->transport_version(),
434 Perspective::IS_CLIENT)));
435}
436
437TEST_P(QuicSpdySessionTestServer, PeerAddress) {
438 EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
439 session_.peer_address());
440}
441
442TEST_P(QuicSpdySessionTestServer, SelfAddress) {
443 EXPECT_TRUE(session_.self_address().IsInitialized());
444}
445
446TEST_P(QuicSpdySessionTestServer, IsCryptoHandshakeConfirmed) {
447 EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
448 CryptoHandshakeMessage message;
449 session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
450 EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
451}
452
453TEST_P(QuicSpdySessionTestServer, IsClosedStreamDefault) {
454 // Ensure that no streams are initially closed.
QUICHE teamdc41bf12019-03-20 12:58:42 -0700455 QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
456 connection_->transport_version(), Perspective::IS_CLIENT);
457 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
458 first_stream_id =
459 QuicUtils::GetCryptoStreamId(connection_->transport_version());
460 }
461 for (QuicStreamId i = first_stream_id; i < 100; i++) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462 EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
463 }
464}
465
466TEST_P(QuicSpdySessionTestServer, AvailableStreams) {
467 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
468 GetNthClientInitiatedBidirectionalId(2)) != nullptr);
469 // Both client initiated streams with smaller stream IDs are available.
470 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
471 &session_, GetNthClientInitiatedBidirectionalId(0)));
472 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
473 &session_, GetNthClientInitiatedBidirectionalId(1)));
474 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
475 GetNthClientInitiatedBidirectionalId(1)) != nullptr);
476 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
477 GetNthClientInitiatedBidirectionalId(0)) != nullptr);
478}
479
480TEST_P(QuicSpdySessionTestServer, IsClosedStreamLocallyCreated) {
481 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
482 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id());
483 QuicSpdyStream* stream4 = session_.CreateOutgoingBidirectionalStream();
484 EXPECT_EQ(GetNthServerInitiatedBidirectionalId(1), stream4->id());
485
486 CheckClosedStreams();
487 CloseStream(GetNthServerInitiatedBidirectionalId(0));
488 CheckClosedStreams();
489 CloseStream(GetNthServerInitiatedBidirectionalId(1));
490 CheckClosedStreams();
491}
492
493TEST_P(QuicSpdySessionTestServer, IsClosedStreamPeerCreated) {
494 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
495 QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
496 session_.GetOrCreateDynamicStream(stream_id1);
497 session_.GetOrCreateDynamicStream(stream_id2);
498
499 CheckClosedStreams();
500 CloseStream(stream_id1);
501 CheckClosedStreams();
502 CloseStream(stream_id2);
503 // Create a stream, and make another available.
504 QuicStream* stream3 = session_.GetOrCreateDynamicStream(stream_id2 + 4);
505 CheckClosedStreams();
506 // Close one, but make sure the other is still not closed
507 CloseStream(stream3->id());
508 CheckClosedStreams();
509}
510
511TEST_P(QuicSpdySessionTestServer, MaximumAvailableOpenedStreams) {
512 if (IsVersion99()) {
513 // For IETF QUIC, we should be able to obtain the max allowed
514 // stream ID, the next ID should fail. Since the actual limit
515 // is not the number of open streams, we allocate the max and the max+2.
516 // Get the max allowed stream ID, this should succeed.
fkastenholz3c4eabf2019-04-22 07:49:59 -0700517 QuicStreamId stream_id = StreamCountToId(
518 QuicSessionPeer::v99_streamid_manager(&session_)
519 ->actual_max_allowed_incoming_bidirectional_streams(),
520 Perspective::IS_CLIENT, // Client initates stream, allocs stream id.
521 /*bidirectional=*/true);
522 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
523 stream_id = StreamCountToId(
524 QuicSessionPeer::v99_streamid_manager(&session_)
525 ->actual_max_allowed_incoming_unidirectional_streams(),
526 Perspective::IS_CLIENT,
527 /*bidirectional=*/false);
528 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
529 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(2);
530 // Get the (max allowed stream ID)++. These should all fail.
531 stream_id = StreamCountToId(
532 QuicSessionPeer::v99_streamid_manager(&session_)
533 ->actual_max_allowed_incoming_bidirectional_streams() +
534 1,
535 Perspective::IS_CLIENT,
536 /*bidirectional=*/true);
537 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id));
538
539 stream_id = StreamCountToId(
540 QuicSessionPeer::v99_streamid_manager(&session_)
541 ->actual_max_allowed_incoming_unidirectional_streams() +
542 1,
543 Perspective::IS_CLIENT,
544 /*bidirectional=*/false);
545 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500546 } else {
547 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
548 session_.GetOrCreateDynamicStream(stream_id);
549 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
550 EXPECT_NE(
551 nullptr,
552 session_.GetOrCreateDynamicStream(
553 stream_id +
554 IdDelta() *
555 (session_.max_open_incoming_bidirectional_streams() - 1)));
556 }
557}
558
559TEST_P(QuicSpdySessionTestServer, TooManyAvailableStreams) {
560 QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
561 QuicStreamId stream_id2;
562 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1));
563 // A stream ID which is too large to create.
564 stream_id2 = GetNthClientInitiatedBidirectionalId(
565 2 * session_.MaxAvailableBidirectionalStreams() + 4);
566 if (IsVersion99()) {
567 EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
568 } else {
569 EXPECT_CALL(*connection_,
570 CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
571 }
572 EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2));
573}
574
575TEST_P(QuicSpdySessionTestServer, ManyAvailableStreams) {
576 // When max_open_streams_ is 200, should be able to create 200 streams
577 // out-of-order, that is, creating the one with the largest stream ID first.
578 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
579 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
580 // Create one stream.
581 session_.GetOrCreateDynamicStream(stream_id);
582 EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
583 // Stream count is 200, GetNth... starts counting at 0, so the 200'th stream
fkastenholz3c4eabf2019-04-22 07:49:59 -0700584 // is 199. BUT actually we need to do 198 because the crypto stream (Stream
585 // ID 0) has not been registered, but GetNth... assumes that it has.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500586 EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
fkastenholz3c4eabf2019-04-22 07:49:59 -0700587 GetNthClientInitiatedBidirectionalId(198)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500588}
589
590TEST_P(QuicSpdySessionTestServer,
591 DebugDFatalIfMarkingClosedStreamWriteBlocked) {
592 // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
593 if (GetParam() != AllSupportedVersions()[0]) {
594 return;
595 }
596
597 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
598 QuicStreamId closed_stream_id = stream2->id();
599 // Close the stream.
600 EXPECT_CALL(*connection_, SendControlFrame(_));
601 EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
602 stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
vasilvvc48c8712019-03-11 13:38:16 -0700603 std::string msg =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500604 QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
605 EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
606 msg);
607}
608
609TEST_P(QuicSpdySessionTestServer, OnCanWrite) {
610 session_.set_writev_consumes_all_data(true);
611 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
612 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
613 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
614
615 session_.MarkConnectionLevelWriteBlocked(stream2->id());
616 session_.MarkConnectionLevelWriteBlocked(stream6->id());
617 session_.MarkConnectionLevelWriteBlocked(stream4->id());
618
619 InSequence s;
620
621 // Reregister, to test the loop limit.
622 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
623 session_.SendStreamData(stream2);
624 session_.MarkConnectionLevelWriteBlocked(stream2->id());
625 }));
626 // 2 will get called a second time as it didn't finish its block
627 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
628 session_.SendStreamData(stream2);
629 }));
630 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
631 session_.SendStreamData(stream6);
632 }));
633 // 4 will not get called, as we exceeded the loop limit.
634 session_.OnCanWrite();
635 EXPECT_TRUE(session_.WillingAndAbleToWrite());
636}
637
638TEST_P(QuicSpdySessionTestServer, TestBatchedWrites) {
639 session_.set_writev_consumes_all_data(true);
640 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
641 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
642 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
643
644 session_.set_writev_consumes_all_data(true);
645 session_.MarkConnectionLevelWriteBlocked(stream2->id());
646 session_.MarkConnectionLevelWriteBlocked(stream4->id());
647
648 // With two sessions blocked, we should get two write calls. They should both
649 // go to the first stream as it will only write 6k and mark itself blocked
650 // again.
651 InSequence s;
652 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
653 session_.SendLargeFakeData(stream2, 6000);
654 session_.MarkConnectionLevelWriteBlocked(stream2->id());
655 }));
656 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
657 session_.SendLargeFakeData(stream2, 6000);
658 session_.MarkConnectionLevelWriteBlocked(stream2->id());
659 }));
660 session_.OnCanWrite();
661
662 // We should get one more call for stream2, at which point it has used its
663 // write quota and we move over to stream 4.
664 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
665 session_.SendLargeFakeData(stream2, 6000);
666 session_.MarkConnectionLevelWriteBlocked(stream2->id());
667 }));
668 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
669 session_.SendLargeFakeData(stream4, 6000);
670 session_.MarkConnectionLevelWriteBlocked(stream4->id());
671 }));
672 session_.OnCanWrite();
673
674 // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
675 // priority stream 6. 4 should be preempted. 6 will write but *not* block so
676 // will cede back to 4.
677 stream6->SetPriority(kV3HighestPriority);
678 EXPECT_CALL(*stream4, OnCanWrite())
679 .WillOnce(Invoke([this, stream4, stream6]() {
680 session_.SendLargeFakeData(stream4, 6000);
681 session_.MarkConnectionLevelWriteBlocked(stream4->id());
682 session_.MarkConnectionLevelWriteBlocked(stream6->id());
683 }));
684 EXPECT_CALL(*stream6, OnCanWrite())
685 .WillOnce(Invoke([this, stream4, stream6]() {
686 session_.SendStreamData(stream6);
687 session_.SendLargeFakeData(stream4, 6000);
688 }));
689 session_.OnCanWrite();
690
691 // Stream4 alread did 6k worth of writes, so after doing another 12k it should
692 // cede and 2 should resume.
693 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
694 session_.SendLargeFakeData(stream4, 12000);
695 session_.MarkConnectionLevelWriteBlocked(stream4->id());
696 }));
697 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
698 session_.SendLargeFakeData(stream2, 6000);
699 session_.MarkConnectionLevelWriteBlocked(stream2->id());
700 }));
701 session_.OnCanWrite();
702}
703
704TEST_P(QuicSpdySessionTestServer, OnCanWriteBundlesStreams) {
705 if (IsVersion99()) {
706 EXPECT_CALL(*connection_, SendControlFrame(_))
707 .WillRepeatedly(Invoke(
fkastenholz3c4eabf2019-04-22 07:49:59 -0700708 this, &QuicSpdySessionTestServer::ClearMaxStreamsControlFrame));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500709 }
710 // Encryption needs to be established before data can be sent.
711 CryptoHandshakeMessage msg;
712 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
713 QuicConnectionPeer::GetWriter(session_.connection()));
714 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
715 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
716 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
717
718 // Drive congestion control manually.
719 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
720 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
721
722 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
723 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
724 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
725
726 session_.MarkConnectionLevelWriteBlocked(stream2->id());
727 session_.MarkConnectionLevelWriteBlocked(stream6->id());
728 session_.MarkConnectionLevelWriteBlocked(stream4->id());
729
730 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
731 EXPECT_CALL(*send_algorithm, GetCongestionWindow())
dschinazi66dea072019-04-09 11:41:06 -0700732 .WillRepeatedly(Return(kMaxOutgoingPacketSize * 10));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500733 EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
734 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
735 session_.SendStreamData(stream2);
736 }));
737 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
738 session_.SendStreamData(stream4);
739 }));
740 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
741 session_.SendStreamData(stream6);
742 }));
743
744 // Expect that we only send one packet, the writes from different streams
745 // should be bundled together.
746 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
747 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
748 EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
749 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
750 session_.OnCanWrite();
751 EXPECT_FALSE(session_.WillingAndAbleToWrite());
752}
753
754TEST_P(QuicSpdySessionTestServer, OnCanWriteCongestionControlBlocks) {
755 session_.set_writev_consumes_all_data(true);
756 InSequence s;
757
758 // Drive congestion control manually.
759 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
760 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
761
762 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
763 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
764 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
765
766 session_.MarkConnectionLevelWriteBlocked(stream2->id());
767 session_.MarkConnectionLevelWriteBlocked(stream6->id());
768 session_.MarkConnectionLevelWriteBlocked(stream4->id());
769
770 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
771 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
772 session_.SendStreamData(stream2);
773 }));
774 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
775 EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
776 session_.SendStreamData(stream6);
777 }));
778 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
779 // stream4->OnCanWrite is not called.
780
781 session_.OnCanWrite();
782 EXPECT_TRUE(session_.WillingAndAbleToWrite());
783
784 // Still congestion-control blocked.
785 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
786 session_.OnCanWrite();
787 EXPECT_TRUE(session_.WillingAndAbleToWrite());
788
789 // stream4->OnCanWrite is called once the connection stops being
790 // congestion-control blocked.
791 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
792 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
793 session_.SendStreamData(stream4);
794 }));
795 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
796 session_.OnCanWrite();
797 EXPECT_FALSE(session_.WillingAndAbleToWrite());
798}
799
800TEST_P(QuicSpdySessionTestServer, OnCanWriteWriterBlocks) {
801 // Drive congestion control manually in order to ensure that
802 // application-limited signaling is handled correctly.
803 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
804 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
805 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
806
807 // Drive packet writer manually.
808 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
809 QuicConnectionPeer::GetWriter(session_.connection()));
810 EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
811 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
812
813 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
814
815 session_.MarkConnectionLevelWriteBlocked(stream2->id());
816
817 EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
818 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)).Times(0);
819
820 session_.OnCanWrite();
821 EXPECT_TRUE(session_.WillingAndAbleToWrite());
822}
823
824TEST_P(QuicSpdySessionTestServer, BufferedHandshake) {
825 session_.set_writev_consumes_all_data(true);
826 EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
827
828 // Test that blocking other streams does not change our status.
829 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
830 session_.MarkConnectionLevelWriteBlocked(stream2->id());
831 EXPECT_FALSE(session_.HasPendingHandshake());
832
833 TestStream* stream3 = session_.CreateOutgoingBidirectionalStream();
834 session_.MarkConnectionLevelWriteBlocked(stream3->id());
835 EXPECT_FALSE(session_.HasPendingHandshake());
836
837 // Blocking (due to buffering of) the Crypto stream is detected.
838 session_.MarkConnectionLevelWriteBlocked(
839 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
840 EXPECT_TRUE(session_.HasPendingHandshake());
841
842 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
843 session_.MarkConnectionLevelWriteBlocked(stream4->id());
844 EXPECT_TRUE(session_.HasPendingHandshake());
845
846 InSequence s;
847 // Force most streams to re-register, which is common scenario when we block
848 // the Crypto stream, and only the crypto stream can "really" write.
849
850 // Due to prioritization, we *should* be asked to write the crypto stream
851 // first.
852 // Don't re-register the crypto stream (which signals complete writing).
853 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
854 EXPECT_CALL(*crypto_stream, OnCanWrite());
855
856 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
857 session_.SendStreamData(stream2);
858 }));
859 EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(Invoke([this, stream3]() {
860 session_.SendStreamData(stream3);
861 }));
862 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
863 session_.SendStreamData(stream4);
864 session_.MarkConnectionLevelWriteBlocked(stream4->id());
865 }));
866
867 session_.OnCanWrite();
868 EXPECT_TRUE(session_.WillingAndAbleToWrite());
869 EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
870}
871
872TEST_P(QuicSpdySessionTestServer, OnCanWriteWithClosedStream) {
873 session_.set_writev_consumes_all_data(true);
874 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
875 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
876 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
877
878 session_.MarkConnectionLevelWriteBlocked(stream2->id());
879 session_.MarkConnectionLevelWriteBlocked(stream6->id());
880 session_.MarkConnectionLevelWriteBlocked(stream4->id());
881 CloseStream(stream6->id());
882
883 InSequence s;
884 EXPECT_CALL(*connection_, SendControlFrame(_))
885 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
886 EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
887 session_.SendStreamData(stream2);
888 }));
889 EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
890 session_.SendStreamData(stream4);
891 }));
892 session_.OnCanWrite();
893 EXPECT_FALSE(session_.WillingAndAbleToWrite());
894}
895
896TEST_P(QuicSpdySessionTestServer,
897 OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
898 // Drive congestion control manually in order to ensure that
899 // application-limited signaling is handled correctly.
900 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
901 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
902 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
903
904 // Ensure connection level flow control blockage.
905 QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
906 EXPECT_TRUE(session_.flow_controller()->IsBlocked());
907 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
908 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
909
910 // Mark the crypto and headers streams as write blocked, we expect them to be
911 // allowed to write later.
912 session_.MarkConnectionLevelWriteBlocked(
913 QuicUtils::GetCryptoStreamId(connection_->transport_version()));
914
915 // Create a data stream, and although it is write blocked we never expect it
916 // to be allowed to write as we are connection level flow control blocked.
917 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
918 session_.MarkConnectionLevelWriteBlocked(stream->id());
919 EXPECT_CALL(*stream, OnCanWrite()).Times(0);
920
921 // The crypto and headers streams should be called even though we are
922 // connection flow control blocked.
923 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
924 EXPECT_CALL(*crypto_stream, OnCanWrite());
renjietangfbeb5bf2019-04-19 15:06:20 -0700925 TestHeadersStream* headers_stream;
926 if (!GetQuicReloadableFlag(quic_eliminate_static_stream_map)) {
927 QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
928 headers_stream = new TestHeadersStream(&session_);
929 QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
930 } else {
931 QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, nullptr);
932 headers_stream = new TestHeadersStream(&session_);
933 QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, headers_stream);
934 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500935 session_.MarkConnectionLevelWriteBlocked(
936 QuicUtils::GetHeadersStreamId(connection_->transport_version()));
937 EXPECT_CALL(*headers_stream, OnCanWrite());
938
939 // After the crypto and header streams perform a write, the connection will be
940 // blocked by the flow control, hence it should become application-limited.
941 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
942
943 session_.OnCanWrite();
944 EXPECT_FALSE(session_.WillingAndAbleToWrite());
945}
946
947TEST_P(QuicSpdySessionTestServer, SendGoAway) {
948 if (IsVersion99()) {
949 // GoAway frames are not in version 99
950 return;
951 }
952 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
953 QuicConnectionPeer::GetWriter(session_.connection()));
954 EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
955 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
956
957 EXPECT_CALL(*connection_, SendControlFrame(_))
958 .WillOnce(
959 Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
960 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
961 EXPECT_TRUE(session_.goaway_sent());
962
963 const QuicStreamId kTestStreamId = 5u;
964 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
965 EXPECT_CALL(*connection_,
966 OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
967 .Times(0);
968 EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId));
969}
970
971TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
972 if (IsVersion99()) {
973 // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
974 // supported.
975 return;
976 }
977 EXPECT_CALL(*connection_, SendControlFrame(_))
978 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
979 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
980 EXPECT_TRUE(session_.goaway_sent());
981 session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
982}
983
984TEST_P(QuicSpdySessionTestServer, InvalidGoAway) {
985 if (IsVersion99()) {
986 // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
987 // supported.
988 return;
989 }
990 QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
991 session_.next_outgoing_bidirectional_stream_id(), "");
992 session_.OnGoAway(go_away);
993}
994
995// Test that server session will send a connectivity probe in response to a
996// connectivity probe on the same path.
997TEST_P(QuicSpdySessionTestServer, ServerReplyToConnecitivityProbe) {
998 QuicSocketAddress old_peer_address =
999 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
1000 EXPECT_EQ(old_peer_address, session_.peer_address());
1001
1002 QuicSocketAddress new_peer_address =
1003 QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort + 1);
1004
1005 EXPECT_CALL(*connection_,
1006 SendConnectivityProbingResponsePacket(new_peer_address));
1007 if (IsVersion99()) {
1008 // Need to explicitly do this to emulate the reception of a PathChallenge,
1009 // which stores its payload for use in generating the response.
1010 connection_->OnPathChallengeFrame(
1011 QuicPathChallengeFrame(0, {{0, 1, 2, 3, 4, 5, 6, 7}}));
1012 }
1013 session_.OnConnectivityProbeReceived(session_.self_address(),
1014 new_peer_address);
1015 EXPECT_EQ(old_peer_address, session_.peer_address());
1016}
1017
1018TEST_P(QuicSpdySessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
1019 EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
1020 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1021 CryptoHandshakeMessage msg;
1022 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1023 EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
1024 QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
1025}
1026
1027TEST_P(QuicSpdySessionTestServer, RstStreamBeforeHeadersDecompressed) {
1028 // Send two bytes of payload.
1029 QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
1030 QuicStringPiece("HT"));
1031 session_.OnStreamFrame(data1);
1032 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
1033
1034 EXPECT_CALL(*connection_, SendControlFrame(_));
1035 if (!IsVersion99()) {
1036 // For version99, OnStreamReset gets called because of the STOP_SENDING,
1037 // below. EXPECT the call there.
1038 EXPECT_CALL(*connection_,
1039 OnStreamReset(GetNthClientInitiatedBidirectionalId(0), _));
1040 }
1041 QuicRstStreamFrame rst1(kInvalidControlFrameId,
1042 GetNthClientInitiatedBidirectionalId(0),
1043 QUIC_ERROR_PROCESSING_STREAM, 0);
1044 session_.OnRstStream(rst1);
1045
1046 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
1047 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
1048 // one-way close.
1049 if (IsVersion99()) {
1050 // Only needed for version 99/IETF QUIC.
1051 QuicStopSendingFrame stop_sending(
1052 kInvalidControlFrameId, GetNthClientInitiatedBidirectionalId(0),
1053 static_cast<QuicApplicationErrorCode>(QUIC_ERROR_PROCESSING_STREAM));
1054 // Expect the RESET_STREAM that is generated in response to receiving a
1055 // STOP_SENDING.
1056 EXPECT_CALL(*connection_,
1057 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
1058 QUIC_ERROR_PROCESSING_STREAM));
1059 session_.OnStopSendingFrame(stop_sending);
1060 }
1061
1062 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1063 // Connection should remain alive.
1064 EXPECT_TRUE(connection_->connected());
1065}
1066
1067TEST_P(QuicSpdySessionTestServer, OnStreamFrameFinStaticStreamId) {
1068 // Send two bytes of payload.
1069 QuicStreamFrame data1(
1070 QuicUtils::GetCryptoStreamId(connection_->transport_version()), true, 0,
1071 QuicStringPiece("HT"));
1072 EXPECT_CALL(*connection_,
1073 CloseConnection(
1074 QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
1075 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1076 session_.OnStreamFrame(data1);
1077}
1078
1079TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
1080 // Send two bytes of payload.
1081 QuicRstStreamFrame rst1(
1082 kInvalidControlFrameId,
1083 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
1084 QUIC_ERROR_PROCESSING_STREAM, 0);
1085 EXPECT_CALL(*connection_,
1086 CloseConnection(
1087 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
1088 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1089 session_.OnRstStream(rst1);
1090}
1091
1092TEST_P(QuicSpdySessionTestServer, OnStreamFrameInvalidStreamId) {
1093 // Send two bytes of payload.
1094 QuicStreamFrame data1(
1095 QuicUtils::GetInvalidStreamId(connection_->transport_version()), true, 0,
1096 QuicStringPiece("HT"));
1097 EXPECT_CALL(*connection_,
1098 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001099 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001100 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1101 session_.OnStreamFrame(data1);
1102}
1103
1104TEST_P(QuicSpdySessionTestServer, OnRstStreamInvalidStreamId) {
1105 // Send two bytes of payload.
1106 QuicRstStreamFrame rst1(
1107 kInvalidControlFrameId,
1108 QuicUtils::GetInvalidStreamId(connection_->transport_version()),
1109 QUIC_ERROR_PROCESSING_STREAM, 0);
1110 EXPECT_CALL(*connection_,
1111 CloseConnection(
bnce433f532019-04-16 13:05:27 -07001112 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -05001113 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
1114 session_.OnRstStream(rst1);
1115}
1116
1117TEST_P(QuicSpdySessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
1118 // Test that if a stream is flow control blocked, then on receipt of the SHLO
1119 // containing a suitable send window offset, the stream becomes unblocked.
1120
1121 // Ensure that Writev consumes all the data it is given (simulate no socket
1122 // blocking).
1123 session_.set_writev_consumes_all_data(true);
1124
1125 // Create a stream, and send enough data to make it flow control blocked.
1126 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
vasilvvc48c8712019-03-11 13:38:16 -07001127 std::string body(kMinimumFlowControlSendWindow, '.');
QUICHE teama6ef0a62019-03-07 20:34:33 -05001128 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1129 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1130 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1131 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
1132 stream2->WriteOrBufferBody(body, false);
1133 EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
1134 EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
1135 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1136
1137 // Now complete the crypto handshake, resulting in an increased flow control
1138 // send window.
1139 CryptoHandshakeMessage msg;
1140 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1141 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
1142 // Stream is now unblocked.
1143 EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
1144 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1145 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1146}
1147
1148TEST_P(QuicSpdySessionTestServer,
1149 HandshakeUnblocksFlowControlBlockedCryptoStream) {
QUICHE teamea740082019-03-11 17:58:43 -07001150 if (QuicVersionUsesCryptoFrames(GetParam().transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001151 // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
1152 // test doesn't make sense for those versions.
1153 return;
1154 }
1155 // Test that if the crypto stream is flow control blocked, then if the SHLO
1156 // contains a larger send window offset, the stream becomes unblocked.
1157 session_.set_writev_consumes_all_data(true);
1158 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1159 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1160 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1161 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1162 QuicHeadersStream* headers_stream =
1163 QuicSpdySessionPeer::GetHeadersStream(&session_);
1164 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
1165 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1166 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1167 if (IsVersion99()) {
1168 EXPECT_CALL(*connection_, SendControlFrame(_))
1169 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1170 } else {
1171 EXPECT_CALL(*connection_, SendControlFrame(_))
1172 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1173 }
1174 for (QuicStreamId i = 0;
1175 !crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
1176 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1177 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1178 QuicStreamOffset offset = crypto_stream->stream_bytes_written();
1179 QuicConfig config;
1180 CryptoHandshakeMessage crypto_message;
1181 config.ToHandshakeMessage(&crypto_message);
1182 crypto_stream->SendHandshakeMessage(crypto_message);
1183 char buf[1000];
1184 QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
1185 crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
1186 }
1187 EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
1188 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
1189 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1190 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1191 EXPECT_FALSE(session_.HasDataToWrite());
1192 EXPECT_TRUE(crypto_stream->HasBufferedData());
1193
1194 // Now complete the crypto handshake, resulting in an increased flow control
1195 // send window.
1196 CryptoHandshakeMessage msg;
1197 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1198 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
1199 &session_,
1200 QuicUtils::GetCryptoStreamId(connection_->transport_version())));
1201 // Stream is now unblocked and will no longer have buffered data.
1202 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1203 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1204 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1205}
1206
1207#if !defined(OS_IOS)
1208// This test is failing flakily for iOS bots.
1209// http://crbug.com/425050
1210// NOTE: It's not possible to use the standard MAYBE_ convention to disable
1211// this test on iOS because when this test gets instantiated it ends up with
1212// various names that are dependent on the parameters passed.
1213TEST_P(QuicSpdySessionTestServer,
1214 HandshakeUnblocksFlowControlBlockedHeadersStream) {
1215 // Test that if the header stream is flow control blocked, then if the SHLO
1216 // contains a larger send window offset, the stream becomes unblocked.
1217 session_.set_writev_consumes_all_data(true);
1218 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1219 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1220 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1221 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1222 QuicHeadersStream* headers_stream =
1223 QuicSpdySessionPeer::GetHeadersStream(&session_);
1224 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
1225 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1226 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1227 QuicStreamId stream_id = 5;
1228 // Write until the header stream is flow control blocked.
1229 EXPECT_CALL(*connection_, SendControlFrame(_))
1230 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1231 SpdyHeaderBlock headers;
1232 SimpleRandom random;
1233 while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2000) {
1234 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1235 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1236 headers["header"] = QuicStrCat(random.RandUint64(), random.RandUint64(),
1237 random.RandUint64());
1238 session_.WriteHeadersOnHeadersStream(stream_id, headers.Clone(), true, 0,
1239 nullptr);
1240 stream_id += IdDelta();
1241 }
1242 // Write once more to ensure that the headers stream has buffered data. The
1243 // random headers may have exactly filled the flow control window.
1244 session_.WriteHeadersOnHeadersStream(stream_id, std::move(headers), true, 0,
1245 nullptr);
1246 EXPECT_TRUE(headers_stream->HasBufferedData());
1247
1248 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked());
1249 EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
1250 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1251 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1252 EXPECT_FALSE(session_.HasDataToWrite());
1253
1254 // Now complete the crypto handshake, resulting in an increased flow control
1255 // send window.
1256 CryptoHandshakeMessage msg;
1257 session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
1258
1259 // Stream is now unblocked and will no longer have buffered data.
1260 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
1261 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1262 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1263 EXPECT_TRUE(headers_stream->HasBufferedData());
1264 EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
1265 &session_,
1266 QuicUtils::GetHeadersStreamId(connection_->transport_version())));
1267}
1268#endif // !defined(OS_IOS)
1269
1270TEST_P(QuicSpdySessionTestServer,
1271 ConnectionFlowControlAccountingRstOutOfOrder) {
1272 // Test that when we receive an out of order stream RST we correctly adjust
1273 // our connection level flow control receive window.
1274 // On close, the stream should mark as consumed all bytes between the highest
1275 // byte consumed so far and the final byte offset from the RST frame.
1276 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1277
1278 const QuicStreamOffset kByteOffset =
1279 1 + kInitialSessionFlowControlWindowForTest / 2;
1280
1281 EXPECT_CALL(*connection_, SendControlFrame(_))
1282 .Times(2)
1283 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
1284 if (!IsVersion99()) {
1285 // For version99 the call to OnStreamReset happens as a result of receiving
1286 // the STOP_SENDING, so set up the EXPECT there.
1287 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1288 }
1289 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1290 QUIC_STREAM_CANCELLED, kByteOffset);
1291 session_.OnRstStream(rst_frame);
1292 // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
1293 // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
1294 // one-way close.
1295 if (IsVersion99()) {
1296 // Only needed for version 99/IETF QUIC.
1297 QuicStopSendingFrame stop_sending(
1298 kInvalidControlFrameId, stream->id(),
1299 static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED));
1300 // Expect the RESET_STREAM that is generated in response to receiving a
1301 // STOP_SENDING.
1302 EXPECT_CALL(*connection_,
1303 OnStreamReset(stream->id(), QUIC_STREAM_CANCELLED));
1304 session_.OnStopSendingFrame(stop_sending);
1305 }
1306
1307 EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
1308}
1309
1310TEST_P(QuicSpdySessionTestServer,
1311 ConnectionFlowControlAccountingFinAndLocalReset) {
1312 // Test the situation where we receive a FIN on a stream, and before we fully
1313 // consume all the data from the sequencer buffer we locally RST the stream.
1314 // The bytes between highest consumed byte, and the final byte offset that we
1315 // determined when the FIN arrived, should be marked as consumed at the
1316 // connection level flow controller when the stream is reset.
1317 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1318
1319 const QuicStreamOffset kByteOffset =
1320 kInitialSessionFlowControlWindowForTest / 2 - 1;
1321 QuicStreamFrame frame(stream->id(), true, kByteOffset, ".");
1322 session_.OnStreamFrame(frame);
1323 EXPECT_TRUE(connection_->connected());
1324
1325 EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
1326 EXPECT_EQ(kByteOffset + frame.data_length,
1327 stream->flow_controller()->highest_received_byte_offset());
1328
1329 // Reset stream locally.
1330 EXPECT_CALL(*connection_, SendControlFrame(_));
1331 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1332 stream->Reset(QUIC_STREAM_CANCELLED);
1333 EXPECT_EQ(kByteOffset + frame.data_length,
1334 session_.flow_controller()->bytes_consumed());
1335}
1336
1337TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
1338 // Test that when we RST the stream (and tear down stream state), and then
1339 // receive a FIN from the peer, we correctly adjust our connection level flow
1340 // control receive window.
1341
1342 // Connection starts with some non-zero highest received byte offset,
1343 // due to other active streams.
1344 const uint64_t kInitialConnectionBytesConsumed = 567;
1345 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1346 EXPECT_LT(kInitialConnectionBytesConsumed,
1347 kInitialConnectionHighestReceivedOffset);
1348 session_.flow_controller()->UpdateHighestReceivedOffset(
1349 kInitialConnectionHighestReceivedOffset);
1350 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1351
1352 // Reset our stream: this results in the stream being closed locally.
1353 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1354 EXPECT_CALL(*connection_, SendControlFrame(_));
1355 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1356 stream->Reset(QUIC_STREAM_CANCELLED);
1357
1358 // Now receive a response from the peer with a FIN. We should handle this by
1359 // adjusting the connection level flow control receive window to take into
1360 // account the total number of bytes sent by the peer.
1361 const QuicStreamOffset kByteOffset = 5678;
vasilvvc48c8712019-03-11 13:38:16 -07001362 std::string body = "hello";
QUICHE teama6ef0a62019-03-07 20:34:33 -05001363 QuicStreamFrame frame(stream->id(), true, kByteOffset, QuicStringPiece(body));
1364 session_.OnStreamFrame(frame);
1365
1366 QuicStreamOffset total_stream_bytes_sent_by_peer =
1367 kByteOffset + body.length();
1368 EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer,
1369 session_.flow_controller()->bytes_consumed());
1370 EXPECT_EQ(
1371 kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer,
1372 session_.flow_controller()->highest_received_byte_offset());
1373}
1374
1375TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
1376 // Test that when we RST the stream (and tear down stream state), and then
1377 // receive a RST from the peer, we correctly adjust our connection level flow
1378 // control receive window.
1379
1380 // Connection starts with some non-zero highest received byte offset,
1381 // due to other active streams.
1382 const uint64_t kInitialConnectionBytesConsumed = 567;
1383 const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
1384 EXPECT_LT(kInitialConnectionBytesConsumed,
1385 kInitialConnectionHighestReceivedOffset);
1386 session_.flow_controller()->UpdateHighestReceivedOffset(
1387 kInitialConnectionHighestReceivedOffset);
1388 session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
1389
1390 // Reset our stream: this results in the stream being closed locally.
1391 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1392 EXPECT_CALL(*connection_, SendControlFrame(_));
1393 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1394 stream->Reset(QUIC_STREAM_CANCELLED);
1395 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1396
1397 // Now receive a RST from the peer. We should handle this by adjusting the
1398 // connection level flow control receive window to take into account the total
1399 // number of bytes sent by the peer.
1400 const QuicStreamOffset kByteOffset = 5678;
1401 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1402 QUIC_STREAM_CANCELLED, kByteOffset);
1403 session_.OnRstStream(rst_frame);
1404
1405 EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset,
1406 session_.flow_controller()->bytes_consumed());
1407 EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset,
1408 session_.flow_controller()->highest_received_byte_offset());
1409}
1410
1411TEST_P(QuicSpdySessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
1412 // Test that receipt of an invalid (< default) stream flow control window from
1413 // the peer results in the connection being torn down.
1414 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1415 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
1416 kInvalidWindow);
1417
1418 EXPECT_CALL(*connection_,
1419 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1420 session_.OnConfigNegotiated();
1421}
1422
1423TEST_P(QuicSpdySessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
1424 // Test that receipt of an invalid (< default) session flow control window
1425 // from the peer results in the connection being torn down.
1426 const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
1427 QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
1428 kInvalidWindow);
1429
1430 EXPECT_CALL(*connection_,
1431 CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
1432 session_.OnConfigNegotiated();
1433}
1434
1435// Test negotiation of custom server initial flow control window.
1436TEST_P(QuicSpdySessionTestServer, CustomFlowControlWindow) {
1437 QuicTagVector copt;
1438 copt.push_back(kIFW7);
1439 QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
1440
1441 session_.OnConfigNegotiated();
1442 EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
1443 session_.flow_controller()));
1444}
1445
1446TEST_P(QuicSpdySessionTestServer, FlowControlWithInvalidFinalOffset) {
1447 // Test that if we receive a stream RST with a highest byte offset that
1448 // violates flow control, that we close the connection.
1449 const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
1450 EXPECT_CALL(*connection_,
1451 CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
1452 .Times(2);
1453
1454 // Check that stream frame + FIN results in connection close.
1455 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1456 EXPECT_CALL(*connection_, SendControlFrame(_));
1457 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1458 stream->Reset(QUIC_STREAM_CANCELLED);
1459 QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
1460 session_.OnStreamFrame(frame);
1461
1462 // Check that RST results in connection close.
1463 QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
1464 QUIC_STREAM_CANCELLED, kLargeOffset);
1465 session_.OnRstStream(rst_frame);
1466}
1467
1468TEST_P(QuicSpdySessionTestServer, WindowUpdateUnblocksHeadersStream) {
1469 // Test that a flow control blocked headers stream gets unblocked on recipt of
1470 // a WINDOW_UPDATE frame.
1471
1472 // Set the headers stream to be flow control blocked.
1473 QuicHeadersStream* headers_stream =
1474 QuicSpdySessionPeer::GetHeadersStream(&session_);
1475 QuicFlowControllerPeer::SetSendWindowOffset(headers_stream->flow_controller(),
1476 0);
1477 EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked());
1478 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1479 EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
1480
1481 // Unblock the headers stream by supplying a WINDOW_UPDATE.
1482 QuicWindowUpdateFrame window_update_frame(kInvalidControlFrameId,
1483 headers_stream->id(),
1484 2 * kMinimumFlowControlSendWindow);
1485 session_.OnWindowUpdateFrame(window_update_frame);
1486 EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
1487 EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
1488 EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
1489}
1490
1491TEST_P(QuicSpdySessionTestServer,
1492 TooManyUnfinishedStreamsCauseServerRejectStream) {
1493 // If a buggy/malicious peer creates too many streams that are not ended
1494 // with a FIN or RST then we send an RST to refuse streams for versions other
1495 // than version 99. In version 99 the connection gets closed.
1496 const QuicStreamId kMaxStreams = 5;
1497 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
fkastenholz3c4eabf2019-04-22 07:49:59 -07001498 // GetNth assumes that both the crypto and header streams have been
1499 // open, but the stream id manager, using GetFirstBidirectional... only
1500 // assumes that the crypto stream is open. This means that GetNth...(0)
1501 // Will return stream ID == 8 (with id ==0 for crypto and id==4 for headers).
1502 // It also means that GetNth(kMax..=5) returns 28 (streams 0/1/2/3/4 are ids
1503 // 8, 12, 16, 20, 24, respectively, so stream#5 is stream id 28).
1504 // However, the stream ID manager does not assume stream 4 is for headers.
1505 // The ID manager would assume that stream#5 is streamid 24.
1506 // In order to make this all work out properly, kFinalStreamId will
1507 // be set to GetNth...(kMaxStreams-1)... but only for V99
QUICHE teama6ef0a62019-03-07 20:34:33 -05001508 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1509 const QuicStreamId kFinalStreamId =
1510 GetNthClientInitiatedBidirectionalId(kMaxStreams);
1511 // Create kMaxStreams data streams, and close them all without receiving a
1512 // FIN or a RST_STREAM from the client.
1513 const QuicStreamId kNextId =
1514 QuicUtils::StreamIdDelta(connection_->transport_version());
1515 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += kNextId) {
1516 QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
1517 session_.OnStreamFrame(data1);
1518 // EXPECT_EQ(1u, session_.GetNumOpenStreams());
1519 if (!IsVersion99()) {
1520 EXPECT_CALL(*connection_, SendControlFrame(_))
1521 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1522 } else {
1523 // V99 has two frames, RST_STREAM and STOP_SENDING
1524 EXPECT_CALL(*connection_, SendControlFrame(_))
1525 .Times(2)
1526 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
1527 }
1528 // Close the stream only if not version 99. If we are version 99
1529 // then closing the stream opens up the available stream id space,
1530 // so we never bump into the limit.
1531 EXPECT_CALL(*connection_, OnStreamReset(i, _));
1532 session_.CloseStream(i);
1533 }
1534 // Try and open a stream that exceeds the limit.
1535 if (!IsVersion99()) {
1536 // On versions other than 99, opening such a stream results in a
1537 // RST_STREAM.
1538 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1539 EXPECT_CALL(*connection_,
1540 OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
1541 .Times(1);
1542 } else {
1543 // On version 99 opening such a stream results in a connection close.
fkastenholz3c4eabf2019-04-22 07:49:59 -07001544 EXPECT_CALL(
1545 *connection_,
1546 CloseConnection(QUIC_INVALID_STREAM_ID,
1547 "Stream id 28 would exceed stream count limit 7", _));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001548 }
1549 // Create one more data streams to exceed limit of open stream.
1550 QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
1551 session_.OnStreamFrame(data1);
1552}
1553
1554TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) {
1555 // Verify that a draining stream (which has received a FIN but not consumed
1556 // it) does not count against the open quota (because it is closed from the
1557 // protocol point of view).
1558 if (IsVersion99()) {
fkastenholz3c4eabf2019-04-22 07:49:59 -07001559 // Version 99 will result in a MAX_STREAMS frame as streams are consumed
QUICHE teama6ef0a62019-03-07 20:34:33 -05001560 // (via the OnStreamFrame call) and then released (via
1561 // StreamDraining). Eventually this node will believe that the peer is
fkastenholz3c4eabf2019-04-22 07:49:59 -07001562 // running low on available stream ids and then send a MAX_STREAMS frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001563 // caught by this EXPECT_CALL.
1564 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
1565 } else {
1566 EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
1567 }
1568 EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
1569 const QuicStreamId kMaxStreams = 5;
1570 QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
1571
1572 // Create kMaxStreams + 1 data streams, and mark them draining.
1573 const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
1574 const QuicStreamId kFinalStreamId =
1575 GetNthClientInitiatedBidirectionalId(kMaxStreams + 1);
1576 for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += IdDelta()) {
1577 QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT"));
1578 session_.OnStreamFrame(data1);
1579 EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
1580 session_.StreamDraining(i);
1581 EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
1582 }
1583}
1584
1585class QuicSpdySessionTestClient : public QuicSpdySessionTestBase {
1586 protected:
1587 QuicSpdySessionTestClient()
1588 : QuicSpdySessionTestBase(Perspective::IS_CLIENT) {}
1589};
1590
1591INSTANTIATE_TEST_SUITE_P(Tests,
1592 QuicSpdySessionTestClient,
1593 ::testing::ValuesIn(AllSupportedVersions()));
1594
1595TEST_P(QuicSpdySessionTestClient, AvailableStreamsClient) {
1596 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1597 GetNthServerInitiatedBidirectionalId(2)) != nullptr);
1598 // Both server initiated streams with smaller stream IDs should be available.
1599 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1600 &session_, GetNthServerInitiatedBidirectionalId(0)));
1601 EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(
1602 &session_, GetNthServerInitiatedBidirectionalId(1)));
1603 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1604 GetNthServerInitiatedBidirectionalId(0)) != nullptr);
1605 ASSERT_TRUE(session_.GetOrCreateDynamicStream(
1606 GetNthServerInitiatedBidirectionalId(1)) != nullptr);
1607 // And client initiated stream ID should be not available.
1608 EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(
1609 &session_, GetNthClientInitiatedBidirectionalId(0)));
1610}
1611
1612TEST_P(QuicSpdySessionTestClient, RecordFinAfterReadSideClosed) {
1613 // Verify that an incoming FIN is recorded in a stream object even if the read
1614 // side has been closed. This prevents an entry from being made in
1615 // locally_closed_streams_highest_offset_ (which will never be deleted).
1616 TestStream* stream = session_.CreateOutgoingBidirectionalStream();
1617 QuicStreamId stream_id = stream->id();
1618
1619 // Close the read side manually.
1620 QuicStreamPeer::CloseReadSide(stream);
1621
1622 // Receive a stream data frame with FIN.
1623 QuicStreamFrame frame(stream_id, true, 0, QuicStringPiece());
1624 session_.OnStreamFrame(frame);
1625 EXPECT_TRUE(stream->fin_received());
1626
1627 // Reset stream locally.
1628 EXPECT_CALL(*connection_, SendControlFrame(_));
1629 EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
1630 stream->Reset(QUIC_STREAM_CANCELLED);
1631 EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
1632
1633 EXPECT_TRUE(connection_->connected());
1634 EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
1635 EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
1636
1637 // The stream is not waiting for the arrival of the peer's final offset as it
1638 // was received with the FIN earlier.
1639 EXPECT_EQ(
1640 0u,
1641 QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
1642}
1643
1644TEST_P(QuicSpdySessionTestClient, WritePriority) {
renjietangfbeb5bf2019-04-19 15:06:20 -07001645 TestHeadersStream* headers_stream;
1646 if (!GetQuicReloadableFlag(quic_eliminate_static_stream_map)) {
1647 QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
1648 headers_stream = new TestHeadersStream(&session_);
1649 QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
1650 } else {
1651 QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, nullptr);
1652 headers_stream = new TestHeadersStream(&session_);
1653 QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, headers_stream);
1654 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001655
1656 // Make packet writer blocked so |headers_stream| will buffer its write data.
1657 MockPacketWriter* writer = static_cast<MockPacketWriter*>(
1658 QuicConnectionPeer::GetWriter(session_.connection()));
1659 EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
1660
1661 const QuicStreamId id = 4;
1662 const QuicStreamId parent_stream_id = 9;
1663 const SpdyPriority priority = kV3HighestPriority;
1664 const bool exclusive = true;
1665 session_.WritePriority(id, parent_stream_id,
1666 Spdy3PriorityToHttp2Weight(priority), exclusive);
1667
1668 QuicStreamSendBuffer& send_buffer =
1669 QuicStreamPeer::SendBuffer(headers_stream);
1670 if (transport_version() > QUIC_VERSION_39) {
1671 ASSERT_EQ(1u, send_buffer.size());
1672
1673 SpdyPriorityIR priority_frame(
1674 id, parent_stream_id, Spdy3PriorityToHttp2Weight(priority), exclusive);
1675 SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
1676 SpdySerializedFrame frame = spdy_framer.SerializeFrame(priority_frame);
1677
1678 const QuicMemSlice& slice =
1679 QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer)->slice;
1680 EXPECT_EQ(QuicStringPiece(frame.data(), frame.size()),
1681 QuicStringPiece(slice.data(), slice.length()));
1682 } else {
1683 EXPECT_EQ(0u, send_buffer.size());
1684 }
1685}
1686
1687TEST_P(QuicSpdySessionTestServer, ZombieStreams) {
1688 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1689 QuicStreamPeer::SetStreamBytesWritten(3, stream2);
1690 EXPECT_TRUE(stream2->IsWaitingForAcks());
1691
1692 EXPECT_CALL(*connection_, SendControlFrame(_));
1693 EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
1694 session_.CloseStream(stream2->id());
1695 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
1696 ASSERT_EQ(1u, session_.closed_streams()->size());
1697 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
1698 session_.OnStreamDoneWaitingForAcks(2);
1699 EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
1700 EXPECT_EQ(1u, session_.closed_streams()->size());
1701 EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
1702}
1703
1704TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
1705 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
1706 InSequence s;
1707
1708 // Drive congestion control manually.
1709 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1710 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1711
1712 TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
1713 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1714 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1715
QUICHE teama6ef0a62019-03-07 20:34:33 -05001716 QuicStreamFrame frame2(stream2->id(), false, 0, 9);
1717 QuicStreamFrame frame3(stream4->id(), false, 0, 9);
1718
1719 // Lost data on cryption stream, streams 2 and 4.
1720 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
QUICHE teamea740082019-03-11 17:58:43 -07001721 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001722 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
1723 .WillOnce(Return(true));
1724 }
1725 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
1726 session_.OnFrameLost(QuicFrame(frame3));
QUICHE teamea740082019-03-11 17:58:43 -07001727 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teamdc41bf12019-03-20 12:58:42 -07001728 QuicStreamFrame frame1(
1729 QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
1730 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001731 session_.OnFrameLost(QuicFrame(frame1));
1732 } else {
QUICHE team6987b4a2019-03-15 16:23:04 -07001733 QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, 0, 1300);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001734 session_.OnFrameLost(QuicFrame(&crypto_frame));
1735 }
1736 session_.OnFrameLost(QuicFrame(frame2));
1737 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1738
1739 // Mark streams 2 and 4 write blocked.
1740 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1741 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1742
1743 // Lost data is retransmitted before new data, and retransmissions for crypto
1744 // stream go first.
1745 // Do not check congestion window when crypto stream has lost data.
1746 EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
QUICHE teamea740082019-03-11 17:58:43 -07001747 if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001748 EXPECT_CALL(*crypto_stream, OnCanWrite());
1749 EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
1750 .WillOnce(Return(false));
1751 }
1752 // Check congestion window for non crypto streams.
1753 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1754 EXPECT_CALL(*stream4, OnCanWrite());
1755 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(false));
1756 // Connection is blocked.
1757 EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(false));
1758
1759 session_.OnCanWrite();
1760 EXPECT_TRUE(session_.WillingAndAbleToWrite());
1761
1762 // Unblock connection.
1763 // Stream 2 retransmits lost data.
1764 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1765 EXPECT_CALL(*stream2, OnCanWrite());
1766 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
1767 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1768 // Stream 2 sends new data.
1769 EXPECT_CALL(*stream2, OnCanWrite());
1770 EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
1771 EXPECT_CALL(*stream4, OnCanWrite());
1772 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1773
1774 session_.OnCanWrite();
1775 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1776}
1777
1778TEST_P(QuicSpdySessionTestServer, DonotRetransmitDataOfClosedStreams) {
1779 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
1780 InSequence s;
1781
1782 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1783 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1784 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1785
1786 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
1787 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
1788 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
1789
1790 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(true));
1791 EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
1792 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
1793 session_.OnFrameLost(QuicFrame(frame3));
1794 session_.OnFrameLost(QuicFrame(frame2));
1795 session_.OnFrameLost(QuicFrame(frame1));
1796
1797 session_.MarkConnectionLevelWriteBlocked(stream2->id());
1798 session_.MarkConnectionLevelWriteBlocked(stream4->id());
1799 session_.MarkConnectionLevelWriteBlocked(stream6->id());
1800
1801 // Reset stream 4 locally.
1802 EXPECT_CALL(*connection_, SendControlFrame(_));
1803 EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
1804 stream4->Reset(QUIC_STREAM_CANCELLED);
1805
1806 // Verify stream 4 is removed from streams with lost data list.
1807 EXPECT_CALL(*stream6, OnCanWrite());
1808 EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
1809 EXPECT_CALL(*stream2, OnCanWrite());
1810 EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
1811 EXPECT_CALL(*connection_, SendControlFrame(_))
1812 .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
1813 EXPECT_CALL(*stream2, OnCanWrite());
1814 EXPECT_CALL(*stream6, OnCanWrite());
1815 session_.OnCanWrite();
1816}
1817
1818TEST_P(QuicSpdySessionTestServer, RetransmitFrames) {
1819 QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
1820 MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
1821 QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
1822 InSequence s;
1823
1824 TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
1825 TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
1826 TestStream* stream6 = session_.CreateOutgoingBidirectionalStream();
1827 EXPECT_CALL(*connection_, SendControlFrame(_))
1828 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1829 session_.SendWindowUpdate(stream2->id(), 9);
1830
1831 QuicStreamFrame frame1(stream2->id(), false, 0, 9);
1832 QuicStreamFrame frame2(stream4->id(), false, 0, 9);
1833 QuicStreamFrame frame3(stream6->id(), false, 0, 9);
1834 QuicWindowUpdateFrame window_update(1, stream2->id(), 9);
1835 QuicFrames frames;
1836 frames.push_back(QuicFrame(frame1));
1837 frames.push_back(QuicFrame(&window_update));
1838 frames.push_back(QuicFrame(frame2));
1839 frames.push_back(QuicFrame(frame3));
1840 EXPECT_FALSE(session_.WillingAndAbleToWrite());
1841
1842 EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
1843 EXPECT_CALL(*connection_, SendControlFrame(_))
1844 .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
1845 EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
1846 EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
1847 EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
1848 session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
1849}
1850
1851TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) {
1852 QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
1853 TestStream* stream = session_.CreateIncomingStream(stream_id);
1854 session_.OnPriorityFrame(stream_id, kV3HighestPriority);
1855 EXPECT_EQ(kV3HighestPriority, stream->priority());
1856}
1857
1858} // namespace
1859} // namespace test
1860} // namespace quic