1 // Copyright 2013 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/tools/quic_simple_server_session.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <utility>
10 
11 #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
12 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
13 #include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
14 #include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
15 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
16 #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
17 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
18 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
19 #include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
20 #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
21 #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
22 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
23 #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
24 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
25 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
26 #include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
27 #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
28 #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
29 #include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
30 #include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
31 #include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
32 #include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
33 #include "net/third_party/quiche/src/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
34 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
35 #include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
36 #include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
37 #include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
38 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
39 #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
40 
41 using testing::_;
42 using testing::AnyNumber;
43 using testing::AtLeast;
44 using testing::InSequence;
45 using testing::Invoke;
46 using testing::Return;
47 using testing::StrictMock;
48 
49 namespace quic {
50 namespace test {
51 namespace {
52 
53 typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo;
54 
55 const QuicByteCount kHeadersFrameHeaderLength = 2;
56 const QuicByteCount kHeadersFramePayloadLength = 9;
57 
58 }  // namespace
59 
60 class QuicSimpleServerSessionPeer {
61  public:
SetCryptoStream(QuicSimpleServerSession * s,QuicCryptoServerStreamBase * crypto_stream)62   static void SetCryptoStream(QuicSimpleServerSession* s,
63                               QuicCryptoServerStreamBase* crypto_stream) {
64     s->crypto_stream_.reset(crypto_stream);
65   }
66 
CreateIncomingStream(QuicSimpleServerSession * s,QuicStreamId id)67   static QuicSpdyStream* CreateIncomingStream(QuicSimpleServerSession* s,
68                                               QuicStreamId id) {
69     return s->CreateIncomingStream(id);
70   }
71 
CreateOutgoingUnidirectionalStream(QuicSimpleServerSession * s)72   static QuicSimpleServerStream* CreateOutgoingUnidirectionalStream(
73       QuicSimpleServerSession* s) {
74     return s->CreateOutgoingUnidirectionalStream();
75   }
76 };
77 
78 namespace {
79 
80 const size_t kMaxStreamsForTest = 10;
81 
82 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
83  public:
MockQuicCryptoServerStream(const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSession * session,QuicCryptoServerStreamBase::Helper * helper)84   explicit MockQuicCryptoServerStream(
85       const QuicCryptoServerConfig* crypto_config,
86       QuicCompressedCertsCache* compressed_certs_cache,
87       QuicSession* session,
88       QuicCryptoServerStreamBase::Helper* helper)
89       : QuicCryptoServerStream(crypto_config,
90                                compressed_certs_cache,
91                                session,
92                                helper) {}
93   MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
94   MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
95       delete;
~MockQuicCryptoServerStream()96   ~MockQuicCryptoServerStream() override {}
97 
98   MOCK_METHOD1(SendServerConfigUpdate,
99                void(const CachedNetworkParameters* cached_network_parameters));
100 
encryption_established() const101   bool encryption_established() const override { return true; }
102 };
103 
104 class MockTlsServerHandshaker : public TlsServerHandshaker {
105  public:
MockTlsServerHandshaker(QuicSession * session,SSL_CTX * ssl_ctx,ProofSource * proof_source)106   explicit MockTlsServerHandshaker(QuicSession* session,
107                                    SSL_CTX* ssl_ctx,
108                                    ProofSource* proof_source)
109       : TlsServerHandshaker(session, ssl_ctx, proof_source) {}
110   MockTlsServerHandshaker(const MockTlsServerHandshaker&) = delete;
111   MockTlsServerHandshaker& operator=(const MockTlsServerHandshaker&) = delete;
~MockTlsServerHandshaker()112   ~MockTlsServerHandshaker() override {}
113 
114   MOCK_METHOD1(SendServerConfigUpdate,
115                void(const CachedNetworkParameters* cached_network_parameters));
116 
encryption_established() const117   bool encryption_established() const override { return true; }
118 };
119 
CreateMockCryptoServerStream(const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSession * session,QuicCryptoServerStreamBase::Helper * helper)120 QuicCryptoServerStreamBase* CreateMockCryptoServerStream(
121     const QuicCryptoServerConfig* crypto_config,
122     QuicCompressedCertsCache* compressed_certs_cache,
123     QuicSession* session,
124     QuicCryptoServerStreamBase::Helper* helper) {
125   switch (session->connection()->version().handshake_protocol) {
126     case PROTOCOL_QUIC_CRYPTO:
127       return new MockQuicCryptoServerStream(
128           crypto_config, compressed_certs_cache, session, helper);
129     case PROTOCOL_TLS1_3:
130       return new MockTlsServerHandshaker(session, crypto_config->ssl_ctx(),
131                                          crypto_config->proof_source());
132     case PROTOCOL_UNSUPPORTED:
133       break;
134   }
135   QUIC_BUG << "Unknown handshake protocol: "
136            << static_cast<int>(
137                   session->connection()->version().handshake_protocol);
138   return nullptr;
139 }
140 
141 class MockQuicConnectionWithSendStreamData : public MockQuicConnection {
142  public:
MockQuicConnectionWithSendStreamData(MockQuicConnectionHelper * helper,MockAlarmFactory * alarm_factory,Perspective perspective,const ParsedQuicVersionVector & supported_versions)143   MockQuicConnectionWithSendStreamData(
144       MockQuicConnectionHelper* helper,
145       MockAlarmFactory* alarm_factory,
146       Perspective perspective,
147       const ParsedQuicVersionVector& supported_versions)
148       : MockQuicConnection(helper,
149                            alarm_factory,
150                            perspective,
151                            supported_versions) {
152     auto consume_all_data = [](QuicStreamId /*id*/, size_t write_length,
153                                QuicStreamOffset /*offset*/,
154                                StreamSendingState state) {
155       return QuicConsumedData(write_length, state != NO_FIN);
156     };
157     ON_CALL(*this, SendStreamData(_, _, _, _))
158         .WillByDefault(Invoke(consume_all_data));
159   }
160 
161   MOCK_METHOD4(SendStreamData,
162                QuicConsumedData(QuicStreamId id,
163                                 size_t write_length,
164                                 QuicStreamOffset offset,
165                                 StreamSendingState state));
166 };
167 
168 class MockQuicSimpleServerSession : public QuicSimpleServerSession {
169  public:
MockQuicSimpleServerSession(const QuicConfig & config,QuicConnection * connection,QuicSession::Visitor * visitor,QuicCryptoServerStreamBase::Helper * helper,const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSimpleServerBackend * quic_simple_server_backend)170   MockQuicSimpleServerSession(
171       const QuicConfig& config,
172       QuicConnection* connection,
173       QuicSession::Visitor* visitor,
174       QuicCryptoServerStreamBase::Helper* helper,
175       const QuicCryptoServerConfig* crypto_config,
176       QuicCompressedCertsCache* compressed_certs_cache,
177       QuicSimpleServerBackend* quic_simple_server_backend)
178       : QuicSimpleServerSession(config,
179                                 CurrentSupportedVersions(),
180                                 connection,
181                                 visitor,
182                                 helper,
183                                 crypto_config,
184                                 compressed_certs_cache,
185                                 quic_simple_server_backend) {}
186   // Methods taking non-copyable types like SpdyHeaderBlock by value cannot be
187   // mocked directly.
WritePushPromise(QuicStreamId original_stream_id,QuicStreamId promised_stream_id,spdy::SpdyHeaderBlock headers)188   void WritePushPromise(QuicStreamId original_stream_id,
189                         QuicStreamId promised_stream_id,
190                         spdy::SpdyHeaderBlock headers) override {
191     return WritePushPromiseMock(original_stream_id, promised_stream_id,
192                                 headers);
193   }
194   MOCK_METHOD3(WritePushPromiseMock,
195                void(QuicStreamId original_stream_id,
196                     QuicStreamId promised_stream_id,
197                     const spdy::SpdyHeaderBlock& headers));
198 
199   MOCK_METHOD1(SendBlocked, void(QuicStreamId));
200 };
201 
202 class QuicSimpleServerSessionTest
203     : public QuicTestWithParam<ParsedQuicVersion> {
204  public:
205   // The function ensures that A) the MAX_STREAMS frames get properly deleted
206   // (since the test uses a 'did we leak memory' check ... if we just lose the
207   // frame, the test fails) and B) returns true (instead of the default, false)
208   // which ensures that the rest of the system thinks that the frame actually
209   // was transmitted.
ClearMaxStreamsControlFrame(const QuicFrame & frame)210   bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
211     if (frame.type == MAX_STREAMS_FRAME) {
212       DeleteFrame(&const_cast<QuicFrame&>(frame));
213       return true;
214     }
215     return false;
216   }
217 
218  protected:
QuicSimpleServerSessionTest()219   QuicSimpleServerSessionTest()
220       : crypto_config_(QuicCryptoServerConfig::TESTING,
221                        QuicRandom::GetInstance(),
222                        crypto_test_utils::ProofSourceForTesting(),
223                        KeyExchangeSource::Default()),
224         compressed_certs_cache_(
225             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
226     config_.SetMaxBidirectionalStreamsToSend(kMaxStreamsForTest);
227     QuicConfigPeer::SetReceivedMaxBidirectionalStreams(&config_,
228                                                        kMaxStreamsForTest);
229     config_.SetMaxUnidirectionalStreamsToSend(kMaxStreamsForTest);
230 
231     config_.SetInitialStreamFlowControlWindowToSend(
232         kInitialStreamFlowControlWindowForTest);
233     config_.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
234         kInitialStreamFlowControlWindowForTest);
235     config_.SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
236         kInitialStreamFlowControlWindowForTest);
237     config_.SetInitialMaxStreamDataBytesUnidirectionalToSend(
238         kInitialStreamFlowControlWindowForTest);
239     config_.SetInitialSessionFlowControlWindowToSend(
240         kInitialSessionFlowControlWindowForTest);
241     if (VersionUsesHttp3(transport_version())) {
242       QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
243           &config_, kMaxStreamsForTest + 3);
244     } else {
245       QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(&config_,
246                                                           kMaxStreamsForTest);
247     }
248 
249     ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
250     connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
251         &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
252     connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
253     session_ = std::make_unique<MockQuicSimpleServerSession>(
254         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
255         &compressed_certs_cache_, &memory_cache_backend_);
256     MockClock clock;
257     handshake_message_ = crypto_config_.AddDefaultConfig(
258         QuicRandom::GetInstance(), &clock,
259         QuicCryptoServerConfig::ConfigOptions());
260     session_->Initialize();
261 
262     if (VersionHasIetfQuicFrames(transport_version())) {
263       EXPECT_CALL(*connection_, SendControlFrame(_))
264           .WillRepeatedly(Invoke(
265               this, &QuicSimpleServerSessionTest::ClearMaxStreamsControlFrame));
266     }
267     session_->OnConfigNegotiated();
268   }
269 
GetNthClientInitiatedBidirectionalId(int n)270   QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
271     return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
272   }
273 
GetNthServerInitiatedUnidirectionalId(int n)274   QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
275     return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
276         transport_version(), n);
277   }
278 
transport_version() const279   QuicTransportVersion transport_version() const {
280     return GetParam().transport_version;
281   }
282 
InjectStopSending(QuicStreamId stream_id,QuicRstStreamErrorCode rst_stream_code)283   void InjectStopSending(QuicStreamId stream_id,
284                          QuicRstStreamErrorCode rst_stream_code) {
285     // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
286     // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
287     // a one-way close.
288     if (!VersionHasIetfQuicFrames(transport_version())) {
289       // Only needed for version 99/IETF QUIC.
290       return;
291     }
292     EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1);
293     QuicStopSendingFrame stop_sending(
294         kInvalidControlFrameId, stream_id,
295         static_cast<QuicApplicationErrorCode>(rst_stream_code));
296     // Expect the RESET_STREAM that is generated in response to receiving a
297     // STOP_SENDING.
298     EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code));
299     session_->OnStopSendingFrame(stop_sending);
300   }
301 
302   StrictMock<MockQuicSessionVisitor> owner_;
303   StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_;
304   MockQuicConnectionHelper helper_;
305   MockAlarmFactory alarm_factory_;
306   StrictMock<MockQuicConnectionWithSendStreamData>* connection_;
307   QuicConfig config_;
308   QuicCryptoServerConfig crypto_config_;
309   QuicCompressedCertsCache compressed_certs_cache_;
310   QuicMemoryCacheBackend memory_cache_backend_;
311   std::unique_ptr<MockQuicSimpleServerSession> session_;
312   std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
313 };
314 
315 INSTANTIATE_TEST_SUITE_P(Tests,
316                          QuicSimpleServerSessionTest,
317                          ::testing::ValuesIn(AllSupportedVersions()),
318                          ::testing::PrintToStringParamName());
319 
TEST_P(QuicSimpleServerSessionTest,CloseStreamDueToReset)320 TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
321   // Open a stream, then reset it.
322   // Send two bytes of payload to open it.
323   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
324                         quiche::QuicheStringPiece("HT"));
325   session_->OnStreamFrame(data1);
326   EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
327 
328   // Receive a reset (and send a RST in response).
329   QuicRstStreamFrame rst1(kInvalidControlFrameId,
330                           GetNthClientInitiatedBidirectionalId(0),
331                           QUIC_ERROR_PROCESSING_STREAM, 0);
332   EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
333   EXPECT_CALL(*connection_, SendControlFrame(_));
334   if (!VersionHasIetfQuicFrames(transport_version())) {
335     // For version 99, this is covered in InjectStopSending()
336     EXPECT_CALL(*connection_,
337                 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
338                               QUIC_RST_ACKNOWLEDGEMENT));
339   }
340   session_->OnRstStream(rst1);
341   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
342   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
343   // a one-way close.
344   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
345                     QUIC_ERROR_PROCESSING_STREAM);
346   EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
347 
348   // Send the same two bytes of payload in a new packet.
349   session_->OnStreamFrame(data1);
350 
351   // The stream should not be re-opened.
352   EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
353   EXPECT_TRUE(connection_->connected());
354 }
355 
TEST_P(QuicSimpleServerSessionTest,NeverOpenStreamDueToReset)356 TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
357   // Send a reset (and expect the peer to send a RST in response).
358   QuicRstStreamFrame rst1(kInvalidControlFrameId,
359                           GetNthClientInitiatedBidirectionalId(0),
360                           QUIC_ERROR_PROCESSING_STREAM, 0);
361   EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
362   if (!VersionHasIetfQuicFrames(transport_version())) {
363     EXPECT_CALL(*connection_, SendControlFrame(_));
364     // For version 99, this is covered in InjectStopSending()
365     EXPECT_CALL(*connection_,
366                 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
367                               QUIC_RST_ACKNOWLEDGEMENT));
368   }
369   session_->OnRstStream(rst1);
370   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
371   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
372   // a one-way close.
373   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
374                     QUIC_ERROR_PROCESSING_STREAM);
375 
376   EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
377 
378   // Send two bytes of payload.
379   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
380                         quiche::QuicheStringPiece("HT"));
381   session_->OnStreamFrame(data1);
382 
383   // The stream should never be opened, now that the reset is received.
384   EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
385   EXPECT_TRUE(connection_->connected());
386 }
387 
TEST_P(QuicSimpleServerSessionTest,AcceptClosedStream)388 TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
389   // Send (empty) compressed headers followed by two bytes of data.
390   QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
391                          quiche::QuicheStringPiece("\1\0\0\0\0\0\0\0HT"));
392   QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
393                          quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT"));
394   session_->OnStreamFrame(frame1);
395   session_->OnStreamFrame(frame2);
396   EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
397 
398   // Send a reset (and expect the peer to send a RST in response).
399   QuicRstStreamFrame rst(kInvalidControlFrameId,
400                          GetNthClientInitiatedBidirectionalId(0),
401                          QUIC_ERROR_PROCESSING_STREAM, 0);
402   EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
403   if (!VersionHasIetfQuicFrames(transport_version())) {
404     EXPECT_CALL(*connection_, SendControlFrame(_));
405     // For version 99, this is covered in InjectStopSending()
406     EXPECT_CALL(*connection_,
407                 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
408                               QUIC_RST_ACKNOWLEDGEMENT));
409   }
410   session_->OnRstStream(rst);
411   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
412   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
413   // a one-way close.
414   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
415                     QUIC_ERROR_PROCESSING_STREAM);
416 
417   // If we were tracking, we'd probably want to reject this because it's data
418   // past the reset point of stream 3.  As it's a closed stream we just drop the
419   // data on the floor, but accept the packet because it has data for stream 5.
420   QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false, 2,
421                          quiche::QuicheStringPiece("TP"));
422   QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
423                          quiche::QuicheStringPiece("TP"));
424   session_->OnStreamFrame(frame3);
425   session_->OnStreamFrame(frame4);
426   // The stream should never be opened, now that the reset is received.
427   EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
428   EXPECT_TRUE(connection_->connected());
429 }
430 
TEST_P(QuicSimpleServerSessionTest,CreateIncomingStreamDisconnected)431 TEST_P(QuicSimpleServerSessionTest, CreateIncomingStreamDisconnected) {
432   // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
433   if (GetParam() != AllSupportedVersions()[0]) {
434     return;
435   }
436 
437   // Tests that incoming stream creation fails when connection is not connected.
438   size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
439   QuicConnectionPeer::TearDownLocalConnectionState(connection_);
440   EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingStream(
441                       session_.get(), GetNthClientInitiatedBidirectionalId(0)),
442                   "ShouldCreateIncomingStream called when disconnected");
443   EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
444 }
445 
TEST_P(QuicSimpleServerSessionTest,CreateIncomingStream)446 TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) {
447   QuicSpdyStream* stream = QuicSimpleServerSessionPeer::CreateIncomingStream(
448       session_.get(), GetNthClientInitiatedBidirectionalId(0));
449   EXPECT_NE(nullptr, stream);
450   EXPECT_EQ(GetNthClientInitiatedBidirectionalId(0), stream->id());
451 }
452 
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamDisconnected)453 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) {
454   // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
455   if (GetParam() != AllSupportedVersions()[0]) {
456     return;
457   }
458 
459   // Tests that outgoing stream creation fails when connection is not connected.
460   size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
461   QuicConnectionPeer::TearDownLocalConnectionState(connection_);
462   EXPECT_QUIC_BUG(
463       QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
464           session_.get()),
465       "ShouldCreateOutgoingUnidirectionalStream called when disconnected");
466 
467   EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams());
468 }
469 
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamUnencrypted)470 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUnencrypted) {
471   // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
472   if (GetParam() != AllSupportedVersions()[0]) {
473     return;
474   }
475 
476   // Tests that outgoing stream creation fails when encryption has not yet been
477   // established.
478   size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
479   EXPECT_QUIC_BUG(
480       QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
481           session_.get()),
482       "Encryption not established so no outgoing stream created.");
483   EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams());
484 }
485 
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamUptoLimit)486 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
487   // Tests that outgoing stream creation should not be affected by existing
488   // incoming stream and vice-versa. But when reaching the limit of max outgoing
489   // stream allowed, creation should fail.
490 
491   // Receive some data to initiate a incoming stream which should not effect
492   // creating outgoing streams.
493   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
494                         quiche::QuicheStringPiece("HT"));
495   session_->OnStreamFrame(data1);
496   EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
497   EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
498 
499   if (!VersionUsesHttp3(transport_version())) {
500     session_->UnregisterStreamPriority(
501         QuicUtils::GetHeadersStreamId(transport_version()),
502         /*is_static=*/true);
503   }
504   // Assume encryption already established.
505   QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr);
506   QuicCryptoServerStreamBase* crypto_stream =
507       CreateMockCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
508                                    session_.get(), &stream_helper_);
509   QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
510   if (!VersionUsesHttp3(transport_version())) {
511     session_->RegisterStreamPriority(
512         QuicUtils::GetHeadersStreamId(transport_version()),
513         /*is_static=*/true,
514         spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority));
515   }
516 
517   // Create push streams till reaching the upper limit of allowed open streams.
518   for (size_t i = 0; i < kMaxStreamsForTest; ++i) {
519     QuicSpdyStream* created_stream =
520         QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
521             session_.get());
522     if (VersionUsesHttp3(transport_version())) {
523       EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(i + 3),
524                 created_stream->id());
525     } else {
526       EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(i), created_stream->id());
527     }
528     EXPECT_EQ(i + 1, session_->GetNumOpenOutgoingStreams());
529   }
530 
531   // Continuing creating push stream would fail.
532   EXPECT_EQ(nullptr,
533             QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
534                 session_.get()));
535   EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
536 
537   // Create peer initiated stream should have no problem.
538   QuicStreamFrame data2(GetNthClientInitiatedBidirectionalId(1), false, 0,
539                         quiche::QuicheStringPiece("HT"));
540   session_->OnStreamFrame(data2);
541   EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
542 }
543 
TEST_P(QuicSimpleServerSessionTest,OnStreamFrameWithEvenStreamId)544 TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) {
545   QuicStreamFrame frame(GetNthServerInitiatedUnidirectionalId(0), false, 0,
546                         quiche::QuicheStringPiece());
547   EXPECT_CALL(*connection_,
548               CloseConnection(QUIC_INVALID_STREAM_ID,
549                               "Client sent data on server push stream", _));
550   session_->OnStreamFrame(frame);
551 }
552 
553 // Tests that calling GetOrCreateStream() on an outgoing stream not promised yet
554 // should result close connection.
TEST_P(QuicSimpleServerSessionTest,GetEvenIncomingError)555 TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
556   const size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
557   const QuicErrorCode expected_error = VersionUsesHttp3(transport_version())
558                                            ? QUIC_HTTP_STREAM_WRONG_DIRECTION
559                                            : QUIC_INVALID_STREAM_ID;
560   EXPECT_CALL(*connection_, CloseConnection(expected_error,
561                                             "Data for nonexistent stream", _));
562   EXPECT_EQ(nullptr,
563             QuicSessionPeer::GetOrCreateStream(
564                 session_.get(), GetNthServerInitiatedUnidirectionalId(3)));
565   EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
566 }
567 
568 // In order to test the case where server push stream creation goes beyond
569 // limit, server push streams need to be hanging there instead of
570 // immediately closing after sending back response.
571 // To achieve this goal, this class resets flow control windows so that large
572 // responses will not be sent fully in order to prevent push streams from being
573 // closed immediately.
574 // Also adjust connection-level flow control window to ensure a large response
575 // can cause stream-level flow control blocked but not connection-level.
576 class QuicSimpleServerSessionServerPushTest
577     : public QuicSimpleServerSessionTest {
578  protected:
579   const size_t kStreamFlowControlWindowSize = 32 * 1024;  // 32KB.
580 
QuicSimpleServerSessionServerPushTest()581   QuicSimpleServerSessionServerPushTest() {
582     // Reset stream level flow control window to be 32KB.
583     if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
584       if (VersionHasIetfQuicFrames(transport_version())) {
585         QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
586             &config_, kStreamFlowControlWindowSize);
587       } else {
588         // In this version, push streams are server-initiated bidirectional
589         // streams, which are outgoing since we are the server here.
590         QuicConfigPeer::
591             SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
592                 &config_, kStreamFlowControlWindowSize);
593       }
594     } else {
595       QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(
596           &config_, kStreamFlowControlWindowSize);
597     }
598     // Reset connection level flow control window to be 1.5 MB which is large
599     // enough that it won't block any stream to write before stream level flow
600     // control blocks it.
601     QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
602         &config_, kInitialSessionFlowControlWindowForTest);
603 
604     ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
605     connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
606         &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
607     session_ = std::make_unique<MockQuicSimpleServerSession>(
608         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
609         &compressed_certs_cache_, &memory_cache_backend_);
610     session_->Initialize();
611     // Needed to make new session flow control window and server push work.
612 
613     if (VersionHasIetfQuicFrames(transport_version())) {
614       EXPECT_CALL(*connection_, SendControlFrame(_))
615           .WillRepeatedly(Invoke(this, &QuicSimpleServerSessionServerPushTest::
616                                            ClearMaxStreamsControlFrame));
617     }
618     session_->OnConfigNegotiated();
619 
620     if (!VersionUsesHttp3(transport_version())) {
621       session_->UnregisterStreamPriority(
622           QuicUtils::GetHeadersStreamId(transport_version()),
623           /*is_static=*/true);
624     }
625     QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr);
626     // Assume encryption already established.
627     QuicCryptoServerStreamBase* crypto_stream =
628         CreateMockCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
629                                      session_.get(), &stream_helper_);
630 
631     QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
632     if (!VersionUsesHttp3(transport_version())) {
633       session_->RegisterStreamPriority(
634           QuicUtils::GetHeadersStreamId(transport_version()),
635           /*is_static=*/true,
636           spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority));
637     }
638     if (VersionUsesHttp3(transport_version())) {
639       // Ignore writes on the control stream.
640       auto send_control_stream =
641           QuicSpdySessionPeer::GetSendControlStream(session_.get());
642       EXPECT_CALL(*connection_,
643                   SendStreamData(send_control_stream->id(), _, _, NO_FIN))
644           .Times(AnyNumber());
645     }
646   }
647 
648   // Given |num_resources|, create this number of fake push resources and push
649   // them by sending PUSH_PROMISE for all and sending push responses for as much
650   // as possible(limited by kMaxStreamsForTest).
651   // If |num_resources| > kMaxStreamsForTest, the left over will be queued.
652   // Returns the length of the DATA frame header, or 0 if the version does not
653   // use DATA frames.
PromisePushResources(size_t num_resources)654   QuicByteCount PromisePushResources(size_t num_resources) {
655     // testing::InSequence seq;
656     // To prevent push streams from being closed the response need to be larger
657     // than stream flow control window so stream won't send the full body.
658     size_t body_size = 2 * kStreamFlowControlWindowSize;  // 64KB.
659 
660     std::string request_url = "mail.google.com/";
661     spdy::SpdyHeaderBlock request_headers;
662     std::string resource_host = "www.google.com";
663     std::string partial_push_resource_path = "/server_push_src";
664     std::list<QuicBackendResponse::ServerPushInfo> push_resources;
665     std::string scheme = "http";
666     QuicByteCount data_frame_header_length = 0;
667     for (unsigned int i = 1; i <= num_resources; ++i) {
668       QuicStreamId stream_id;
669       if (VersionUsesHttp3(transport_version())) {
670         stream_id = GetNthServerInitiatedUnidirectionalId(i + 2);
671       } else {
672         stream_id = GetNthServerInitiatedUnidirectionalId(i - 1);
673       }
674       std::string path = partial_push_resource_path +
675                          quiche::QuicheTextUtils::Uint64ToString(i);
676       std::string url = scheme + "://" + resource_host + path;
677       QuicUrl resource_url = QuicUrl(url);
678       std::string body(body_size, 'a');
679       std::string data;
680       data_frame_header_length = 0;
681       if (VersionUsesHttp3(transport_version())) {
682         std::unique_ptr<char[]> buffer;
683         data_frame_header_length =
684             HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
685         std::string header(buffer.get(), data_frame_header_length);
686         data = header + body;
687       } else {
688         data = body;
689       }
690 
691       memory_cache_backend_.AddSimpleResponse(resource_host, path, 200, data);
692       push_resources.push_back(QuicBackendResponse::ServerPushInfo(
693           resource_url, spdy::SpdyHeaderBlock(), QuicStream::kDefaultPriority,
694           body));
695       // PUSH_PROMISED are sent for all the resources.
696       EXPECT_CALL(*session_,
697                   WritePushPromiseMock(GetNthClientInitiatedBidirectionalId(0),
698                                        stream_id, _));
699       if (i <= kMaxStreamsForTest) {
700         // |kMaxStreamsForTest| promised responses should be sent.
701         // Since flow control window is smaller than response body, not the
702         // whole body will be sent.
703         QuicStreamOffset offset = 0;
704         if (VersionUsesHttp3(transport_version())) {
705           EXPECT_CALL(*connection_,
706                       SendStreamData(stream_id, 1, offset, NO_FIN));
707           offset++;
708         }
709 
710         if (VersionUsesHttp3(transport_version())) {
711           EXPECT_CALL(*connection_,
712                       SendStreamData(stream_id, kHeadersFrameHeaderLength,
713                                      offset, NO_FIN));
714           offset += kHeadersFrameHeaderLength;
715           EXPECT_CALL(*connection_,
716                       SendStreamData(stream_id, kHeadersFramePayloadLength,
717                                      offset, NO_FIN));
718           offset += kHeadersFramePayloadLength;
719         }
720         if (VersionUsesHttp3(transport_version())) {
721           EXPECT_CALL(*connection_,
722                       SendStreamData(stream_id, data_frame_header_length,
723                                      offset, NO_FIN));
724           offset += data_frame_header_length;
725         }
726         EXPECT_CALL(*connection_, SendStreamData(stream_id, _, offset, NO_FIN))
727             .WillOnce(Return(QuicConsumedData(
728                 kStreamFlowControlWindowSize - offset, false)));
729         EXPECT_CALL(*session_, SendBlocked(stream_id));
730       }
731     }
732     session_->PromisePushResources(
733         request_url, push_resources, GetNthClientInitiatedBidirectionalId(0),
734         spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, false),
735         request_headers);
736     return data_frame_header_length;
737   }
738 
MaybeConsumeHeadersStreamData()739   void MaybeConsumeHeadersStreamData() {
740     if (!VersionUsesHttp3(transport_version())) {
741       QuicStreamId headers_stream_id =
742           QuicUtils::GetHeadersStreamId(transport_version());
743       EXPECT_CALL(*connection_, SendStreamData(headers_stream_id, _, _, _))
744           .Times(AtLeast(1));
745     }
746   }
747 };
748 
749 INSTANTIATE_TEST_SUITE_P(Tests,
750                          QuicSimpleServerSessionServerPushTest,
751                          ::testing::ValuesIn(AllSupportedVersions()));
752 
753 // Tests that given more than kMaxStreamsForTest resources, all their
754 // PUSH_PROMISE's will be sent out and only kMaxStreamsForTest streams will be
755 // opened and send push response.
TEST_P(QuicSimpleServerSessionServerPushTest,TestPromisePushResources)756 TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
757   MaybeConsumeHeadersStreamData();
758   if (VersionUsesHttp3(transport_version())) {
759     session_->EnableServerPush();
760     session_->OnMaxPushIdFrame(kMaxQuicStreamId);
761   }
762   size_t num_resources = kMaxStreamsForTest + 5;
763   PromisePushResources(num_resources);
764   EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
765 }
766 
767 // Tests that after promised stream queued up, when an opened stream is marked
768 // draining, a queued promised stream will become open and send push response.
TEST_P(QuicSimpleServerSessionServerPushTest,HandlePromisedPushRequestsAfterStreamDraining)769 TEST_P(QuicSimpleServerSessionServerPushTest,
770        HandlePromisedPushRequestsAfterStreamDraining) {
771   MaybeConsumeHeadersStreamData();
772   if (VersionUsesHttp3(transport_version())) {
773     session_->EnableServerPush();
774     session_->OnMaxPushIdFrame(kMaxQuicStreamId);
775   }
776   size_t num_resources = kMaxStreamsForTest + 1;
777   QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
778   QuicStreamId next_out_going_stream_id;
779   if (VersionUsesHttp3(transport_version())) {
780     next_out_going_stream_id =
781         GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
782   } else {
783     next_out_going_stream_id =
784         GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
785   }
786 
787   // After an open stream is marked draining, a new stream is expected to be
788   // created and a response sent on the stream.
789   QuicStreamOffset offset = 0;
790   if (VersionUsesHttp3(transport_version())) {
791     EXPECT_CALL(*connection_,
792                 SendStreamData(next_out_going_stream_id, 1, offset, NO_FIN));
793     offset++;
794   }
795   if (VersionUsesHttp3(transport_version())) {
796     EXPECT_CALL(*connection_,
797                 SendStreamData(next_out_going_stream_id,
798                                kHeadersFrameHeaderLength, offset, NO_FIN));
799     offset += kHeadersFrameHeaderLength;
800     EXPECT_CALL(*connection_,
801                 SendStreamData(next_out_going_stream_id,
802                                kHeadersFramePayloadLength, offset, NO_FIN));
803     offset += kHeadersFramePayloadLength;
804   }
805   if (VersionUsesHttp3(transport_version())) {
806     EXPECT_CALL(*connection_,
807                 SendStreamData(next_out_going_stream_id,
808                                data_frame_header_length, offset, NO_FIN));
809     offset += data_frame_header_length;
810   }
811   EXPECT_CALL(*connection_,
812               SendStreamData(next_out_going_stream_id, _, offset, NO_FIN))
813       .WillOnce(Return(
814           QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
815   EXPECT_CALL(*session_, SendBlocked(next_out_going_stream_id));
816 
817   if (VersionHasIetfQuicFrames(transport_version())) {
818     // The PromisePushedResources call, above, will have used all available
819     // stream ids.  For version 99, stream ids are not made available until
820     // a MAX_STREAMS frame is received. This emulates the reception of one.
821     // For pre-v-99, the node monitors its own stream usage and makes streams
822     // available as it closes/etc them.
823     // Version 99 also has unidirectional static streams, so we need to send
824     // MaxStreamFrame of the number of resources + number of static streams.
825     session_->OnMaxStreamsFrame(
826         QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
827   }
828 
829   if (VersionUsesHttp3(transport_version())) {
830     session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(3));
831   } else {
832     session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(0));
833   }
834   // Number of open outgoing streams should still be the same, because a new
835   // stream is opened. And the queue should be empty.
836   EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
837 }
838 
839 // Tests that after all resources are promised, a RST frame from client can
840 // prevent a promised resource to be send out.
TEST_P(QuicSimpleServerSessionServerPushTest,ResetPromisedStreamToCancelServerPush)841 TEST_P(QuicSimpleServerSessionServerPushTest,
842        ResetPromisedStreamToCancelServerPush) {
843   if (VersionHasIetfQuicFrames(transport_version())) {
844     // This test is resetting a stream that is not opened yet. IETF QUIC has no
845     // way to handle this. Some similar tests can be added once CANCEL_PUSH is
846     // supported.
847     return;
848   }
849   MaybeConsumeHeadersStreamData();
850   if (VersionUsesHttp3(transport_version())) {
851     session_->EnableServerPush();
852     session_->OnMaxPushIdFrame(kMaxQuicStreamId);
853   }
854 
855   // Having two extra resources to be send later. One of them will be reset, so
856   // when opened stream become close, only one will become open.
857   size_t num_resources = kMaxStreamsForTest + 2;
858   if (VersionHasIetfQuicFrames(transport_version())) {
859     // V99 will send out a STREAMS_BLOCKED frame when it tries to exceed the
860     // limit. This will clear the frames so that they do not block the later
861     // rst-stream frame.
862     EXPECT_CALL(*connection_, SendControlFrame(_))
863         .WillOnce(Invoke(&ClearControlFrame));
864   }
865   QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
866 
867   // Reset the last stream in the queue. It should be marked cancelled.
868   QuicStreamId stream_got_reset;
869   if (VersionUsesHttp3(transport_version())) {
870     stream_got_reset =
871         GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 4);
872   } else {
873     stream_got_reset =
874         GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 1);
875   }
876   QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset,
877                          QUIC_STREAM_CANCELLED, 0);
878   EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
879   EXPECT_CALL(*connection_, SendControlFrame(_))
880       .WillOnce(Invoke(&ClearControlFrame));
881   EXPECT_CALL(*connection_,
882               OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
883   session_->OnRstStream(rst);
884 
885   // When the first 2 streams becomes draining, the two queued up stream could
886   // be created. But since one of them was marked cancelled due to RST frame,
887   // only one queued resource will be sent out.
888   QuicStreamId stream_not_reset;
889   if (VersionUsesHttp3(transport_version())) {
890     stream_not_reset =
891         GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
892   } else {
893     stream_not_reset =
894         GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
895   }
896   InSequence s;
897   QuicStreamOffset offset = 0;
898   if (VersionUsesHttp3(transport_version())) {
899     EXPECT_CALL(*connection_,
900                 SendStreamData(stream_not_reset, 1, offset, NO_FIN));
901     offset++;
902     EXPECT_CALL(*connection_,
903                 SendStreamData(stream_not_reset, kHeadersFrameHeaderLength,
904                                offset, NO_FIN));
905     offset += kHeadersFrameHeaderLength;
906     EXPECT_CALL(*connection_,
907                 SendStreamData(stream_not_reset, kHeadersFramePayloadLength,
908                                offset, NO_FIN));
909     offset += kHeadersFramePayloadLength;
910     EXPECT_CALL(*connection_,
911                 SendStreamData(stream_not_reset, data_frame_header_length,
912                                offset, NO_FIN));
913     offset += data_frame_header_length;
914   }
915   EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, offset, NO_FIN))
916       .WillOnce(Return(
917           QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
918   EXPECT_CALL(*session_, SendBlocked(stream_not_reset));
919 
920   if (VersionHasIetfQuicFrames(transport_version())) {
921     // The PromisePushedResources call, above, will have used all available
922     // stream ids.  For version 99, stream ids are not made available until
923     // a MAX_STREAMS frame is received. This emulates the reception of one.
924     // For pre-v-99, the node monitors its own stream usage and makes streams
925     // available as it closes/etc them.
926     session_->OnMaxStreamsFrame(
927         QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
928   }
929   session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(3));
930   session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(4));
931 }
932 
933 // Tests that closing a open outgoing stream can trigger a promised resource in
934 // the queue to be send out.
TEST_P(QuicSimpleServerSessionServerPushTest,CloseStreamToHandleMorePromisedStream)935 TEST_P(QuicSimpleServerSessionServerPushTest,
936        CloseStreamToHandleMorePromisedStream) {
937   MaybeConsumeHeadersStreamData();
938   if (VersionUsesHttp3(transport_version())) {
939     session_->EnableServerPush();
940     session_->OnMaxPushIdFrame(kMaxQuicStreamId);
941   }
942   size_t num_resources = kMaxStreamsForTest + 1;
943   if (VersionHasIetfQuicFrames(transport_version())) {
944     // V99 will send out a stream-id-blocked frame when the we desired to exceed
945     // the limit. This will clear the frames so that they do not block the later
946     // rst-stream frame.
947     EXPECT_CALL(*connection_, SendControlFrame(_))
948         .WillOnce(Invoke(&ClearControlFrame));
949   }
950   QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
951   QuicStreamId stream_to_open;
952   if (VersionUsesHttp3(transport_version())) {
953     stream_to_open =
954         GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
955   } else {
956     stream_to_open = GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
957   }
958 
959   // Resetting an open stream will close the stream and give space for extra
960   // stream to be opened.
961   QuicStreamId stream_got_reset = GetNthServerInitiatedUnidirectionalId(3);
962   EXPECT_CALL(*connection_, SendControlFrame(_));
963   if (!VersionHasIetfQuicFrames(transport_version())) {
964     EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
965     // For version 99, this is covered in InjectStopSending()
966     EXPECT_CALL(*connection_,
967                 OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
968   }
969   QuicStreamOffset offset = 0;
970   if (VersionUsesHttp3(transport_version())) {
971     EXPECT_CALL(*connection_,
972                 SendStreamData(stream_to_open, 1, offset, NO_FIN));
973     offset++;
974     EXPECT_CALL(*connection_,
975                 SendStreamData(stream_to_open, kHeadersFrameHeaderLength,
976                                offset, NO_FIN));
977     offset += kHeadersFrameHeaderLength;
978     EXPECT_CALL(*connection_,
979                 SendStreamData(stream_to_open, kHeadersFramePayloadLength,
980                                offset, NO_FIN));
981     offset += kHeadersFramePayloadLength;
982     EXPECT_CALL(*connection_,
983                 SendStreamData(stream_to_open, data_frame_header_length, offset,
984                                NO_FIN));
985     offset += data_frame_header_length;
986   }
987   EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, offset, NO_FIN))
988       .WillOnce(Return(
989           QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
990 
991   EXPECT_CALL(*session_, SendBlocked(stream_to_open));
992   QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset,
993                          QUIC_STREAM_CANCELLED, 0);
994   if (VersionHasIetfQuicFrames(transport_version())) {
995     // The PromisePushedResources call, above, will have used all available
996     // stream ids.  For version 99, stream ids are not made available until
997     // a MAX_STREAMS frame is received. This emulates the reception of one.
998     // For pre-v-99, the node monitors its own stream usage and makes streams
999     // available as it closes/etc them.
1000     session_->OnMaxStreamsFrame(
1001         QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
1002   } else {
1003     session_->OnRstStream(rst);
1004   }
1005   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
1006   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
1007   // a one-way close.
1008   InjectStopSending(stream_got_reset, QUIC_STREAM_CANCELLED);
1009 }
1010 
1011 }  // namespace
1012 }  // namespace test
1013 }  // namespace quic
1014