1 // 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_client_session.h"
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
13 #include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
14 #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
15 #include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
16 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
17 #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
18 #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
19 #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
20 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
21 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
22 #include "net/third_party/quiche/src/quic/test_tools/mock_quic_spdy_client_stream.h"
23 #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
24 #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
25 #include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
26 #include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
27 #include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
28 #include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
29 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
30 #include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
31 #include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
32 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
33 
34 using spdy::SpdyHeaderBlock;
35 using testing::_;
36 using testing::AnyNumber;
37 using testing::AtLeast;
38 using testing::AtMost;
39 using testing::Invoke;
40 using testing::Truly;
41 
42 namespace quic {
43 namespace test {
44 namespace {
45 
46 const char kServerHostname[] = "test.example.com";
47 const uint16_t kPort = 443;
48 
49 class TestQuicSpdyClientSession : public QuicSpdyClientSession {
50  public:
TestQuicSpdyClientSession(const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicConnection * connection,const QuicServerId & server_id,QuicCryptoClientConfig * crypto_config,QuicClientPushPromiseIndex * push_promise_index)51   explicit TestQuicSpdyClientSession(
52       const QuicConfig& config,
53       const ParsedQuicVersionVector& supported_versions,
54       QuicConnection* connection,
55       const QuicServerId& server_id,
56       QuicCryptoClientConfig* crypto_config,
57       QuicClientPushPromiseIndex* push_promise_index)
58       : QuicSpdyClientSession(config,
59                               supported_versions,
60                               connection,
61                               server_id,
62                               crypto_config,
63                               push_promise_index) {}
64 
CreateClientStream()65   std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override {
66     return std::make_unique<MockQuicSpdyClientStream>(
67         GetNextOutgoingBidirectionalStreamId(), this, BIDIRECTIONAL);
68   }
69 
CreateIncomingStream(QuicStreamId id)70   MockQuicSpdyClientStream* CreateIncomingStream(QuicStreamId id) override {
71     if (!ShouldCreateIncomingStream(id)) {
72       return nullptr;
73     }
74     MockQuicSpdyClientStream* stream =
75         new MockQuicSpdyClientStream(id, this, READ_UNIDIRECTIONAL);
76     ActivateStream(QuicWrapUnique(stream));
77     return stream;
78   }
79 };
80 
81 class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
82  protected:
QuicSpdyClientSessionTest()83   QuicSpdyClientSessionTest()
84       : crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
85         promised_stream_id_(
86             QuicUtils::GetInvalidStreamId(GetParam().transport_version)),
87         associated_stream_id_(
88             QuicUtils::GetInvalidStreamId(GetParam().transport_version)) {
89     Initialize();
90     // Advance the time, because timers do not like uninitialized times.
91     connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
92   }
93 
~QuicSpdyClientSessionTest()94   ~QuicSpdyClientSessionTest() override {
95     // Session must be destroyed before promised_by_url_
96     session_.reset(nullptr);
97   }
98 
Initialize()99   void Initialize() {
100     session_.reset();
101     connection_ = new PacketSavingConnection(&helper_, &alarm_factory_,
102                                              Perspective::IS_CLIENT,
103                                              SupportedVersions(GetParam()));
104     session_ = std::make_unique<TestQuicSpdyClientSession>(
105         DefaultQuicConfig(), SupportedVersions(GetParam()), connection_,
106         QuicServerId(kServerHostname, kPort, false), &crypto_config_,
107         &push_promise_index_);
108     session_->Initialize();
109     push_promise_[":path"] = "/bar";
110     push_promise_[":authority"] = "www.google.com";
111     push_promise_[":method"] = "GET";
112     push_promise_[":scheme"] = "https";
113     promise_url_ =
114         SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_);
115     promised_stream_id_ = GetNthServerInitiatedUnidirectionalStreamId(
116         connection_->transport_version(), 0);
117     associated_stream_id_ = GetNthClientInitiatedBidirectionalStreamId(
118         connection_->transport_version(), 0);
119   }
120 
121   // The function ensures that A) the MAX_STREAMS frames get properly deleted
122   // (since the test uses a 'did we leak memory' check ... if we just lose the
123   // frame, the test fails) and B) returns true (instead of the default, false)
124   // which ensures that the rest of the system thinks that the frame actually
125   // was transmitted.
ClearMaxStreamsControlFrame(const QuicFrame & frame)126   bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
127     if (frame.type == MAX_STREAMS_FRAME) {
128       DeleteFrame(&const_cast<QuicFrame&>(frame));
129       return true;
130     }
131     return false;
132   }
133 
134  public:
ClearStreamsBlockedControlFrame(const QuicFrame & frame)135   bool ClearStreamsBlockedControlFrame(const QuicFrame& frame) {
136     if (frame.type == STREAMS_BLOCKED_FRAME) {
137       DeleteFrame(&const_cast<QuicFrame&>(frame));
138       return true;
139     }
140     return false;
141   }
142 
143  protected:
CompleteCryptoHandshake()144   void CompleteCryptoHandshake() {
145     CompleteCryptoHandshake(kDefaultMaxStreamsPerConnection);
146   }
147 
CompleteCryptoHandshake(uint32_t server_max_incoming_streams)148   void CompleteCryptoHandshake(uint32_t server_max_incoming_streams) {
149     if (VersionHasIetfQuicFrames(connection_->transport_version())) {
150       EXPECT_CALL(*connection_, SendControlFrame(_))
151           .Times(testing::AnyNumber())
152           .WillRepeatedly(Invoke(
153               this, &QuicSpdyClientSessionTest::ClearMaxStreamsControlFrame));
154     }
155     session_->CryptoConnect();
156     QuicCryptoClientStream* stream = static_cast<QuicCryptoClientStream*>(
157         session_->GetMutableCryptoStream());
158     QuicConfig config = DefaultQuicConfig();
159     if (VersionHasIetfQuicFrames(connection_->transport_version())) {
160       config.SetMaxUnidirectionalStreamsToSend(
161           server_max_incoming_streams +
162           session_->num_expected_unidirectional_static_streams());
163       config.SetMaxBidirectionalStreamsToSend(server_max_incoming_streams);
164     } else {
165       config.SetMaxBidirectionalStreamsToSend(server_max_incoming_streams);
166     }
167     std::unique_ptr<QuicCryptoServerConfig> crypto_config =
168         crypto_test_utils::CryptoServerConfigForTesting();
169     crypto_test_utils::HandshakeWithFakeServer(
170         &config, crypto_config.get(), &helper_, &alarm_factory_, connection_,
171         stream, AlpnForVersion(connection_->version()));
172   }
173 
174   QuicCryptoClientConfig crypto_config_;
175   MockQuicConnectionHelper helper_;
176   MockAlarmFactory alarm_factory_;
177   PacketSavingConnection* connection_;
178   std::unique_ptr<TestQuicSpdyClientSession> session_;
179   QuicClientPushPromiseIndex push_promise_index_;
180   SpdyHeaderBlock push_promise_;
181   std::string promise_url_;
182   QuicStreamId promised_stream_id_;
183   QuicStreamId associated_stream_id_;
184 };
185 
186 INSTANTIATE_TEST_SUITE_P(Tests,
187                          QuicSpdyClientSessionTest,
188                          ::testing::ValuesIn(AllSupportedVersions()),
189                          ::testing::PrintToStringParamName());
190 
TEST_P(QuicSpdyClientSessionTest,CryptoConnect)191 TEST_P(QuicSpdyClientSessionTest, CryptoConnect) {
192   CompleteCryptoHandshake();
193 }
194 
TEST_P(QuicSpdyClientSessionTest,NoEncryptionAfterInitialEncryption)195 TEST_P(QuicSpdyClientSessionTest, NoEncryptionAfterInitialEncryption) {
196   if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
197     // This test relies on resumption and is QUIC crypto specific, so it is
198     // disabled for TLS.
199     // TODO(nharper): Add support for resumption to the TLS handshake, and fix
200     // this test to not rely on QUIC crypto.
201     return;
202   }
203   // Complete a handshake in order to prime the crypto config for 0-RTT.
204   CompleteCryptoHandshake();
205 
206   // Now create a second session using the same crypto config.
207   Initialize();
208 
209   EXPECT_CALL(*connection_, OnCanWrite());
210   // Starting the handshake should move immediately to encryption
211   // established and will allow streams to be created.
212   session_->CryptoConnect();
213   EXPECT_TRUE(session_->IsEncryptionEstablished());
214   QuicSpdyClientStream* stream = session_->CreateOutgoingBidirectionalStream();
215   ASSERT_TRUE(stream != nullptr);
216   EXPECT_FALSE(QuicUtils::IsCryptoStreamId(connection_->transport_version(),
217                                            stream->id()));
218 
219   // Process an "inchoate" REJ from the server which will cause
220   // an inchoate CHLO to be sent and will leave the encryption level
221   // at NONE.
222   CryptoHandshakeMessage rej;
223   crypto_test_utils::FillInDummyReject(&rej);
224   EXPECT_TRUE(session_->IsEncryptionEstablished());
225   crypto_test_utils::SendHandshakeMessageToStream(
226       session_->GetMutableCryptoStream(), rej, Perspective::IS_CLIENT);
227   EXPECT_FALSE(session_->IsEncryptionEstablished());
228   EXPECT_EQ(ENCRYPTION_INITIAL,
229             QuicPacketCreatorPeer::GetEncryptionLevel(
230                 QuicConnectionPeer::GetPacketCreator(connection_)));
231   // Verify that no new streams may be created.
232   EXPECT_TRUE(session_->CreateOutgoingBidirectionalStream() == nullptr);
233   // Verify that no data may be send on existing streams.
234   char data[] = "hello world";
235   EXPECT_QUIC_BUG(
236       session_->WritevData(stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN,
237                            NOT_RETRANSMISSION, QuicheNullOpt),
238       "Client: Try to send data of stream");
239 }
240 
TEST_P(QuicSpdyClientSessionTest,MaxNumStreamsWithNoFinOrRst)241 TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
242   if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
243     // This test relies on the MIDS transport parameter, which is not yet
244     // supported in TLS 1.3.
245     // TODO(nharper): Add support for Transport Parameters in the TLS handshake.
246     return;
247   }
248 
249   uint32_t kServerMaxIncomingStreams = 1;
250   CompleteCryptoHandshake(kServerMaxIncomingStreams);
251 
252   QuicSpdyClientStream* stream = session_->CreateOutgoingBidirectionalStream();
253   ASSERT_TRUE(stream);
254   EXPECT_FALSE(session_->CreateOutgoingBidirectionalStream());
255 
256   // Close the stream, but without having received a FIN or a RST_STREAM
257   // or MAX_STREAMS (V99) and check that a new one can not be created.
258   session_->CloseStream(stream->id());
259   EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams());
260 
261   stream = session_->CreateOutgoingBidirectionalStream();
262   EXPECT_FALSE(stream);
263 
264   if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
265     EXPECT_EQ(1u,
266               QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
267                   ->outgoing_stream_count());
268   }
269 }
270 
TEST_P(QuicSpdyClientSessionTest,MaxNumStreamsWithRst)271 TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithRst) {
272   if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
273     // This test relies on the MIDS transport parameter, which is not yet
274     // supported in TLS 1.3.
275     // TODO(nharper): Add support for Transport Parameters in the TLS handshake.
276     return;
277   }
278 
279   uint32_t kServerMaxIncomingStreams = 1;
280   CompleteCryptoHandshake(kServerMaxIncomingStreams);
281 
282   QuicSpdyClientStream* stream = session_->CreateOutgoingBidirectionalStream();
283   ASSERT_NE(nullptr, stream);
284   EXPECT_EQ(nullptr, session_->CreateOutgoingBidirectionalStream());
285 
286   // Close the stream and receive an RST frame to remove the unfinished stream
287   session_->CloseStream(stream->id());
288   session_->OnRstStream(QuicRstStreamFrame(kInvalidControlFrameId, stream->id(),
289                                            QUIC_RST_ACKNOWLEDGEMENT, 0));
290   // Check that a new one can be created.
291   EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
292   if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
293     // In V99 the stream limit increases only if we get a MAX_STREAMS
294     // frame; pretend we got one.
295 
296     QuicMaxStreamsFrame frame(0, 2,
297                               /*unidirectional=*/false);
298     session_->OnMaxStreamsFrame(frame);
299   }
300   stream = session_->CreateOutgoingBidirectionalStream();
301   EXPECT_NE(nullptr, stream);
302   if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
303     // Ensure that we have 2 total streams, 1 open and 1 closed.
304     QuicStreamCount expected_stream_count = 2;
305     EXPECT_EQ(expected_stream_count,
306               QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
307                   ->outgoing_stream_count());
308   }
309 }
310 
TEST_P(QuicSpdyClientSessionTest,ResetAndTrailers)311 TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) {
312   if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
313     // This test relies on the MIDS transport parameter, which is not yet
314     // supported in TLS 1.3.
315     // TODO(nharper): Add support for Transport Parameters in the TLS handshake.
316     return;
317   }
318   // Tests the situation in which the client sends a RST at the same time that
319   // the server sends trailing headers (trailers). Receipt of the trailers by
320   // the client should result in all outstanding stream state being tidied up
321   // (including flow control, and number of available outgoing streams).
322   uint32_t kServerMaxIncomingStreams = 1;
323   CompleteCryptoHandshake(kServerMaxIncomingStreams);
324 
325   QuicSpdyClientStream* stream = session_->CreateOutgoingBidirectionalStream();
326   ASSERT_NE(nullptr, stream);
327 
328   if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
329     // For v99, trying to open a stream and failing due to lack
330     // of stream ids will result in a STREAMS_BLOCKED. Make
331     // sure we get one. Also clear out the frame because if it's
332     // left sitting, the later SendRstStream will not actually
333     // transmit the RST_STREAM because the connection will be in write-blocked
334     // state. This means that the SendControlFrame that is expected w.r.t. the
335     // RST_STREAM, below, will not be satisfied.
336     EXPECT_CALL(*connection_, SendControlFrame(_))
337         .WillOnce(Invoke(
338             this, &QuicSpdyClientSessionTest::ClearStreamsBlockedControlFrame));
339   }
340 
341   EXPECT_EQ(nullptr, session_->CreateOutgoingBidirectionalStream());
342 
343   QuicStreamId stream_id = stream->id();
344 
345   EXPECT_CALL(*connection_, SendControlFrame(_))
346       .Times(AtLeast(1))
347       .WillRepeatedly(Invoke(&ClearControlFrame));
348   EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1);
349   session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0);
350 
351   // A new stream cannot be created as the reset stream still counts as an open
352   // outgoing stream until closed by the server.
353   EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams());
354   stream = session_->CreateOutgoingBidirectionalStream();
355   EXPECT_EQ(nullptr, stream);
356 
357   // The stream receives trailers with final byte offset: this is one of three
358   // ways that a peer can signal the end of a stream (the others being RST,
359   // stream data + FIN).
360   QuicHeaderList trailers;
361   trailers.OnHeaderBlockStart();
362   trailers.OnHeader(kFinalOffsetHeaderKey, "0");
363   trailers.OnHeaderBlockEnd(0, 0);
364   session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers);
365 
366   // The stream is now complete from the client's perspective, and it should
367   // be able to create a new outgoing stream.
368   EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
369   if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
370     QuicMaxStreamsFrame frame(0, 2,
371                               /*unidirectional=*/false);
372 
373     session_->OnMaxStreamsFrame(frame);
374   }
375   stream = session_->CreateOutgoingBidirectionalStream();
376   EXPECT_NE(nullptr, stream);
377   if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
378     // Ensure that we have 2 open streams.
379     QuicStreamCount expected_stream_count = 2;
380     EXPECT_EQ(expected_stream_count,
381               QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
382                   ->outgoing_stream_count());
383   }
384 }
385 
TEST_P(QuicSpdyClientSessionTest,ReceivedMalformedTrailersAfterSendingRst)386 TEST_P(QuicSpdyClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) {
387   // Tests the situation where the client has sent a RST to the server, and has
388   // received trailing headers with a malformed final byte offset value.
389   CompleteCryptoHandshake();
390 
391   QuicSpdyClientStream* stream = session_->CreateOutgoingBidirectionalStream();
392   ASSERT_NE(nullptr, stream);
393 
394   // Send the RST, which results in the stream being closed locally (but some
395   // state remains while the client waits for a response from the server).
396   QuicStreamId stream_id = stream->id();
397   EXPECT_CALL(*connection_, SendControlFrame(_))
398       .Times(AtLeast(1))
399       .WillRepeatedly(Invoke(&ClearControlFrame));
400   EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1);
401   session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0);
402 
403   // The stream receives trailers with final byte offset, but the header value
404   // is non-numeric and should be treated as malformed.
405   QuicHeaderList trailers;
406   trailers.OnHeaderBlockStart();
407   trailers.OnHeader(kFinalOffsetHeaderKey, "invalid non-numeric value");
408   trailers.OnHeaderBlockEnd(0, 0);
409 
410   EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
411   session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers);
412 }
413 
TEST_P(QuicSpdyClientSessionTest,OnStreamHeaderListWithStaticStream)414 TEST_P(QuicSpdyClientSessionTest, OnStreamHeaderListWithStaticStream) {
415   // Test situation where OnStreamHeaderList is called by stream with static id.
416   CompleteCryptoHandshake();
417 
418   QuicHeaderList trailers;
419   trailers.OnHeaderBlockStart();
420   trailers.OnHeader(kFinalOffsetHeaderKey, "0");
421   trailers.OnHeaderBlockEnd(0, 0);
422 
423   // Initialize H/3 control stream.
424   QuicStreamId id;
425   if (VersionUsesHttp3(connection_->transport_version())) {
426     id = GetNthServerInitiatedUnidirectionalStreamId(
427         connection_->transport_version(), 3);
428     char type[] = {0x00};
429 
430     QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
431     session_->OnStreamFrame(data1);
432   } else {
433     id = QuicUtils::GetHeadersStreamId(connection_->transport_version());
434   }
435 
436   EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
437                                             "stream is static", _))
438       .Times(1);
439   session_->OnStreamHeaderList(id,
440                                /*fin=*/false, 0, trailers);
441 }
442 
TEST_P(QuicSpdyClientSessionTest,OnPromiseHeaderListWithStaticStream)443 TEST_P(QuicSpdyClientSessionTest, OnPromiseHeaderListWithStaticStream) {
444   // Test situation where OnPromiseHeaderList is called by stream with static
445   // id.
446   CompleteCryptoHandshake();
447 
448   QuicHeaderList trailers;
449   trailers.OnHeaderBlockStart();
450   trailers.OnHeader(kFinalOffsetHeaderKey, "0");
451   trailers.OnHeaderBlockEnd(0, 0);
452 
453   // Initialize H/3 control stream.
454   QuicStreamId id;
455   if (VersionUsesHttp3(connection_->transport_version())) {
456     id = GetNthServerInitiatedUnidirectionalStreamId(
457         connection_->transport_version(), 3);
458     char type[] = {0x00};
459 
460     QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
461     session_->OnStreamFrame(data1);
462   } else {
463     id = QuicUtils::GetHeadersStreamId(connection_->transport_version());
464   }
465   EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
466                                             "stream is static", _))
467       .Times(1);
468   session_->OnPromiseHeaderList(id, promised_stream_id_, 0, trailers);
469 }
470 
TEST_P(QuicSpdyClientSessionTest,GoAwayReceived)471 TEST_P(QuicSpdyClientSessionTest, GoAwayReceived) {
472   if (VersionHasIetfQuicFrames(connection_->transport_version())) {
473     return;
474   }
475   CompleteCryptoHandshake();
476 
477   // After receiving a GoAway, I should no longer be able to create outgoing
478   // streams.
479   session_->connection()->OnGoAwayFrame(QuicGoAwayFrame(
480       kInvalidControlFrameId, QUIC_PEER_GOING_AWAY, 1u, "Going away."));
481   EXPECT_EQ(nullptr, session_->CreateOutgoingBidirectionalStream());
482 }
483 
CheckForDecryptionError(QuicFramer * framer)484 static bool CheckForDecryptionError(QuicFramer* framer) {
485   return framer->error() == QUIC_DECRYPTION_FAILURE;
486 }
487 
488 // Various sorts of invalid packets that should not cause a connection
489 // to be closed.
TEST_P(QuicSpdyClientSessionTest,InvalidPacketReceived)490 TEST_P(QuicSpdyClientSessionTest, InvalidPacketReceived) {
491   QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort);
492   QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort);
493 
494   EXPECT_CALL(*connection_, ProcessUdpPacket(server_address, client_address, _))
495       .WillRepeatedly(Invoke(static_cast<MockQuicConnection*>(connection_),
496                              &MockQuicConnection::ReallyProcessUdpPacket));
497   EXPECT_CALL(*connection_, OnCanWrite()).Times(AnyNumber());
498   EXPECT_CALL(*connection_, OnError(_)).Times(1);
499 
500   // Verify that empty packets don't close the connection.
501   QuicReceivedPacket zero_length_packet(nullptr, 0, QuicTime::Zero(), false);
502   EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
503   session_->ProcessUdpPacket(client_address, server_address,
504                              zero_length_packet);
505 
506   // Verifiy that small, invalid packets don't close the connection.
507   char buf[2] = {0x00, 0x01};
508   QuicConnectionId connection_id = session_->connection()->connection_id();
509   QuicReceivedPacket valid_packet(buf, 2, QuicTime::Zero(), false);
510   // Close connection shouldn't be called.
511   EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
512   EXPECT_CALL(*connection_, OnError(_)).Times(AtMost(1));
513   session_->ProcessUdpPacket(client_address, server_address, valid_packet);
514 
515   // Verify that a non-decryptable packet doesn't close the connection.
516   QuicFramerPeer::SetLastSerializedServerConnectionId(
517       QuicConnectionPeer::GetFramer(connection_), connection_id);
518   ParsedQuicVersionVector versions = SupportedVersions(GetParam());
519   QuicConnectionId destination_connection_id = EmptyQuicConnectionId();
520   QuicConnectionId source_connection_id = connection_id;
521   std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
522       destination_connection_id, source_connection_id, false, false, 100,
523       "data", true, CONNECTION_ID_ABSENT, CONNECTION_ID_ABSENT,
524       PACKET_4BYTE_PACKET_NUMBER, &versions, Perspective::IS_SERVER));
525   std::unique_ptr<QuicReceivedPacket> received(
526       ConstructReceivedPacket(*packet, QuicTime::Zero()));
527   // Change the last byte of the encrypted data.
528   *(const_cast<char*>(received->data() + received->length() - 1)) += 1;
529   EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
530   EXPECT_CALL(*connection_, OnError(Truly(CheckForDecryptionError))).Times(1);
531   session_->ProcessUdpPacket(client_address, server_address, *received);
532 }
533 
534 // A packet with invalid framing should cause a connection to be closed.
TEST_P(QuicSpdyClientSessionTest,InvalidFramedPacketReceived)535 TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) {
536   const ParsedQuicVersion version = GetParam();
537   if (version.handshake_protocol == PROTOCOL_TLS1_3) {
538     // TODO(nharper, b/112643533): Figure out why this test fails when TLS is
539     // enabled and fix it.
540     return;
541   }
542   QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort);
543   QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort);
544   if (version.KnowsWhichDecrypterToUse()) {
545     connection_->InstallDecrypter(
546         ENCRYPTION_FORWARD_SECURE,
547         std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
548   } else {
549     connection_->SetDecrypter(
550         ENCRYPTION_FORWARD_SECURE,
551         std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
552   }
553 
554   EXPECT_CALL(*connection_, ProcessUdpPacket(server_address, client_address, _))
555       .WillRepeatedly(Invoke(static_cast<MockQuicConnection*>(connection_),
556                              &MockQuicConnection::ReallyProcessUdpPacket));
557   EXPECT_CALL(*connection_, OnError(_)).Times(1);
558 
559   // Verify that a decryptable packet with bad frames does close the connection.
560   QuicConnectionId destination_connection_id =
561       session_->connection()->connection_id();
562   QuicConnectionId source_connection_id = EmptyQuicConnectionId();
563   QuicFramerPeer::SetLastSerializedServerConnectionId(
564       QuicConnectionPeer::GetFramer(connection_), destination_connection_id);
565   bool version_flag = false;
566   QuicConnectionIdIncluded scid_included = CONNECTION_ID_ABSENT;
567   if (VersionHasIetfInvariantHeader(version.transport_version)) {
568     version_flag = true;
569     source_connection_id = destination_connection_id;
570     scid_included = CONNECTION_ID_PRESENT;
571   }
572   std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
573       destination_connection_id, source_connection_id, version_flag, false, 100,
574       "data", CONNECTION_ID_ABSENT, scid_included, PACKET_4BYTE_PACKET_NUMBER,
575       version, Perspective::IS_SERVER));
576   std::unique_ptr<QuicReceivedPacket> received(
577       ConstructReceivedPacket(*packet, QuicTime::Zero()));
578   EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
579   session_->ProcessUdpPacket(client_address, server_address, *received);
580 }
581 
TEST_P(QuicSpdyClientSessionTest,PushPromiseOnPromiseHeaders)582 TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeaders) {
583   // Initialize crypto before the client session will create a stream.
584   CompleteCryptoHandshake();
585 
586   if (VersionHasIetfQuicFrames(connection_->transport_version())) {
587     session_->SetMaxPushId(GetNthServerInitiatedUnidirectionalStreamId(
588         connection_->transport_version(), 10));
589   }
590 
591   MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
592       session_->CreateOutgoingBidirectionalStream());
593 
594   EXPECT_CALL(*stream, OnPromiseHeaderList(_, _, _));
595   session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0,
596                                 QuicHeaderList());
597 }
598 
TEST_P(QuicSpdyClientSessionTest,PushPromiseStreamIdTooHigh)599 TEST_P(QuicSpdyClientSessionTest, PushPromiseStreamIdTooHigh) {
600   // Initialize crypto before the client session will create a stream.
601   CompleteCryptoHandshake();
602   QuicStreamId stream_id =
603       QuicSessionPeer::GetNextOutgoingBidirectionalStreamId(session_.get());
604   QuicSessionPeer::ActivateStream(
605       session_.get(), std::make_unique<QuicSpdyClientStream>(
606                           stream_id, session_.get(), BIDIRECTIONAL));
607 
608   if (VersionHasIetfQuicFrames(connection_->transport_version())) {
609     session_->SetMaxPushId(GetNthServerInitiatedUnidirectionalStreamId(
610         connection_->transport_version(), 10));
611     // TODO(b/136295430) Use PushId to represent Push IDs instead of
612     // QuicStreamId.
613     EXPECT_CALL(
614         *connection_,
615         CloseConnection(QUIC_INVALID_STREAM_ID,
616                         "Received push stream id higher than MAX_PUSH_ID.", _));
617   }
618   auto promise_id = GetNthServerInitiatedUnidirectionalStreamId(
619       connection_->transport_version(), 11);
620   auto headers = QuicHeaderList();
621   headers.OnHeaderBlockStart();
622   headers.OnHeader(":path", "/bar");
623   headers.OnHeader(":authority", "www.google.com");
624   headers.OnHeader(":method", "GET");
625   headers.OnHeader(":scheme", "https");
626   headers.OnHeaderBlockEnd(0, 0);
627   session_->OnPromiseHeaderList(stream_id, promise_id, 0, headers);
628 }
629 
TEST_P(QuicSpdyClientSessionTest,PushPromiseOnPromiseHeadersAlreadyClosed)630 TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeadersAlreadyClosed) {
631   // Initialize crypto before the client session will create a stream.
632   CompleteCryptoHandshake();
633 
634   session_->CreateOutgoingBidirectionalStream();
635 
636   EXPECT_CALL(*connection_, SendControlFrame(_));
637   EXPECT_CALL(*connection_,
638               OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM));
639   session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
640 
641   session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0,
642                                 QuicHeaderList());
643 }
644 
TEST_P(QuicSpdyClientSessionTest,PushPromiseOutOfOrder)645 TEST_P(QuicSpdyClientSessionTest, PushPromiseOutOfOrder) {
646   // Initialize crypto before the client session will create a stream.
647   CompleteCryptoHandshake();
648 
649   if (VersionHasIetfQuicFrames(connection_->transport_version())) {
650     session_->SetMaxPushId(GetNthServerInitiatedUnidirectionalStreamId(
651         connection_->transport_version(), 10));
652   }
653 
654   MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
655       session_->CreateOutgoingBidirectionalStream());
656 
657   EXPECT_CALL(*stream, OnPromiseHeaderList(promised_stream_id_, _, _));
658   session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0,
659                                 QuicHeaderList());
660   associated_stream_id_ +=
661       QuicUtils::StreamIdDelta(connection_->transport_version());
662   EXPECT_CALL(*connection_,
663               CloseConnection(QUIC_INVALID_STREAM_ID,
664                               "Received push stream id lesser or equal to the"
665                               " last accepted before",
666                               _));
667   session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0,
668                                 QuicHeaderList());
669 }
670 
TEST_P(QuicSpdyClientSessionTest,PushPromiseOutgoingStreamId)671 TEST_P(QuicSpdyClientSessionTest, PushPromiseOutgoingStreamId) {
672   // Initialize crypto before the client session will create a stream.
673   CompleteCryptoHandshake();
674 
675   MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
676       session_->CreateOutgoingBidirectionalStream());
677 
678   // Promise an illegal (outgoing) stream id.
679   promised_stream_id_ = GetNthClientInitiatedBidirectionalStreamId(
680       connection_->transport_version(), 0);
681   EXPECT_CALL(
682       *connection_,
683       CloseConnection(QUIC_INVALID_STREAM_ID,
684                       "Received push stream id for outgoing stream.", _));
685 
686   session_->OnPromiseHeaderList(stream->id(), promised_stream_id_, 0,
687                                 QuicHeaderList());
688 }
689 
TEST_P(QuicSpdyClientSessionTest,PushPromiseHandlePromise)690 TEST_P(QuicSpdyClientSessionTest, PushPromiseHandlePromise) {
691   // Initialize crypto before the client session will create a stream.
692   CompleteCryptoHandshake();
693 
694   session_->CreateOutgoingBidirectionalStream();
695 
696   EXPECT_TRUE(session_->HandlePromised(associated_stream_id_,
697                                        promised_stream_id_, push_promise_));
698 
699   EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr);
700   EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
701 }
702 
TEST_P(QuicSpdyClientSessionTest,PushPromiseAlreadyClosed)703 TEST_P(QuicSpdyClientSessionTest, PushPromiseAlreadyClosed) {
704   // Initialize crypto before the client session will create a stream.
705   CompleteCryptoHandshake();
706 
707   session_->CreateOutgoingBidirectionalStream();
708   session_->GetOrCreateStream(promised_stream_id_);
709 
710   EXPECT_CALL(*connection_, SendControlFrame(_));
711   EXPECT_CALL(*connection_,
712               OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM));
713 
714   session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
715   SpdyHeaderBlock promise_headers;
716   EXPECT_FALSE(session_->HandlePromised(associated_stream_id_,
717                                         promised_stream_id_, promise_headers));
718 
719   // Verify that the promise was not created.
720   EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
721   EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
722 }
723 
TEST_P(QuicSpdyClientSessionTest,PushPromiseDuplicateUrl)724 TEST_P(QuicSpdyClientSessionTest, PushPromiseDuplicateUrl) {
725   // Initialize crypto before the client session will create a stream.
726   CompleteCryptoHandshake();
727 
728   session_->CreateOutgoingBidirectionalStream();
729 
730   EXPECT_TRUE(session_->HandlePromised(associated_stream_id_,
731                                        promised_stream_id_, push_promise_));
732 
733   EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr);
734   EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
735 
736   promised_stream_id_ +=
737       QuicUtils::StreamIdDelta(connection_->transport_version());
738   EXPECT_CALL(*connection_, SendControlFrame(_));
739   EXPECT_CALL(*connection_,
740               OnStreamReset(promised_stream_id_, QUIC_DUPLICATE_PROMISE_URL));
741 
742   EXPECT_FALSE(session_->HandlePromised(associated_stream_id_,
743                                         promised_stream_id_, push_promise_));
744 
745   // Verify that the promise was not created.
746   EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
747 }
748 
TEST_P(QuicSpdyClientSessionTest,ReceivingPromiseEnhanceYourCalm)749 TEST_P(QuicSpdyClientSessionTest, ReceivingPromiseEnhanceYourCalm) {
750   for (size_t i = 0u; i < session_->get_max_promises(); i++) {
751     push_promise_[":path"] = quiche::QuicheStringPrintf("/bar%zu", i);
752 
753     QuicStreamId id =
754         promised_stream_id_ +
755         i * QuicUtils::StreamIdDelta(connection_->transport_version());
756 
757     EXPECT_TRUE(
758         session_->HandlePromised(associated_stream_id_, id, push_promise_));
759 
760     // Verify that the promise is in the unclaimed streams map.
761     std::string promise_url(
762         SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_));
763     EXPECT_NE(session_->GetPromisedByUrl(promise_url), nullptr);
764     EXPECT_NE(session_->GetPromisedById(id), nullptr);
765   }
766 
767   // One more promise, this should be refused.
768   int i = session_->get_max_promises();
769   push_promise_[":path"] = quiche::QuicheStringPrintf("/bar%d", i);
770 
771   QuicStreamId id =
772       promised_stream_id_ +
773       i * QuicUtils::StreamIdDelta(connection_->transport_version());
774   EXPECT_CALL(*connection_, SendControlFrame(_));
775   EXPECT_CALL(*connection_, OnStreamReset(id, QUIC_REFUSED_STREAM));
776   EXPECT_FALSE(
777       session_->HandlePromised(associated_stream_id_, id, push_promise_));
778 
779   // Verify that the promise was not created.
780   std::string promise_url(
781       SpdyServerPushUtils::GetPromisedUrlFromHeaders(push_promise_));
782   EXPECT_EQ(session_->GetPromisedById(id), nullptr);
783   EXPECT_EQ(session_->GetPromisedByUrl(promise_url), nullptr);
784 }
785 
TEST_P(QuicSpdyClientSessionTest,IsClosedTrueAfterResetPromisedAlreadyOpen)786 TEST_P(QuicSpdyClientSessionTest, IsClosedTrueAfterResetPromisedAlreadyOpen) {
787   // Initialize crypto before the client session will create a stream.
788   CompleteCryptoHandshake();
789 
790   session_->GetOrCreateStream(promised_stream_id_);
791   EXPECT_CALL(*connection_, SendControlFrame(_));
792   EXPECT_CALL(*connection_,
793               OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM));
794   session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
795   EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_));
796 }
797 
TEST_P(QuicSpdyClientSessionTest,IsClosedTrueAfterResetPromisedNonexistant)798 TEST_P(QuicSpdyClientSessionTest, IsClosedTrueAfterResetPromisedNonexistant) {
799   // Initialize crypto before the client session will create a stream.
800   CompleteCryptoHandshake();
801 
802   EXPECT_CALL(*connection_, SendControlFrame(_));
803   EXPECT_CALL(*connection_,
804               OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM));
805   session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
806   EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_));
807 }
808 
TEST_P(QuicSpdyClientSessionTest,OnInitialHeadersCompleteIsPush)809 TEST_P(QuicSpdyClientSessionTest, OnInitialHeadersCompleteIsPush) {
810   // Initialize crypto before the client session will create a stream.
811   CompleteCryptoHandshake();
812   session_->GetOrCreateStream(promised_stream_id_);
813   EXPECT_TRUE(session_->HandlePromised(associated_stream_id_,
814                                        promised_stream_id_, push_promise_));
815   EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr);
816   EXPECT_NE(session_->GetPromisedStream(promised_stream_id_), nullptr);
817   EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
818 
819   session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock());
820 }
821 
TEST_P(QuicSpdyClientSessionTest,OnInitialHeadersCompleteIsNotPush)822 TEST_P(QuicSpdyClientSessionTest, OnInitialHeadersCompleteIsNotPush) {
823   // Initialize crypto before the client session will create a stream.
824   CompleteCryptoHandshake();
825   session_->CreateOutgoingBidirectionalStream();
826   session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock());
827 }
828 
TEST_P(QuicSpdyClientSessionTest,DeletePromised)829 TEST_P(QuicSpdyClientSessionTest, DeletePromised) {
830   // Initialize crypto before the client session will create a stream.
831   CompleteCryptoHandshake();
832   session_->GetOrCreateStream(promised_stream_id_);
833   EXPECT_TRUE(session_->HandlePromised(associated_stream_id_,
834                                        promised_stream_id_, push_promise_));
835   QuicClientPromisedInfo* promised =
836       session_->GetPromisedById(promised_stream_id_);
837   EXPECT_NE(promised, nullptr);
838   EXPECT_NE(session_->GetPromisedStream(promised_stream_id_), nullptr);
839   EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
840 
841   session_->DeletePromised(promised);
842   EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
843   EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
844 }
845 
TEST_P(QuicSpdyClientSessionTest,ResetPromised)846 TEST_P(QuicSpdyClientSessionTest, ResetPromised) {
847   // Initialize crypto before the client session will create a stream.
848   CompleteCryptoHandshake();
849   session_->GetOrCreateStream(promised_stream_id_);
850   EXPECT_TRUE(session_->HandlePromised(associated_stream_id_,
851                                        promised_stream_id_, push_promise_));
852   EXPECT_CALL(*connection_, SendControlFrame(_));
853   EXPECT_CALL(*connection_,
854               OnStreamReset(promised_stream_id_, QUIC_STREAM_PEER_GOING_AWAY));
855   session_->SendRstStream(promised_stream_id_, QUIC_STREAM_PEER_GOING_AWAY, 0);
856   QuicClientPromisedInfo* promised =
857       session_->GetPromisedById(promised_stream_id_);
858   EXPECT_NE(promised, nullptr);
859   EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
860   EXPECT_EQ(session_->GetPromisedStream(promised_stream_id_), nullptr);
861 }
862 
TEST_P(QuicSpdyClientSessionTest,PushPromiseInvalidMethod)863 TEST_P(QuicSpdyClientSessionTest, PushPromiseInvalidMethod) {
864   // Initialize crypto before the client session will create a stream.
865   CompleteCryptoHandshake();
866 
867   session_->CreateOutgoingBidirectionalStream();
868 
869   EXPECT_CALL(*connection_, SendControlFrame(_));
870   EXPECT_CALL(*connection_,
871               OnStreamReset(promised_stream_id_, QUIC_INVALID_PROMISE_METHOD));
872 
873   push_promise_[":method"] = "POST";
874   EXPECT_FALSE(session_->HandlePromised(associated_stream_id_,
875                                         promised_stream_id_, push_promise_));
876 
877   EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
878   EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
879 }
880 
TEST_P(QuicSpdyClientSessionTest,PushPromiseInvalidHost)881 TEST_P(QuicSpdyClientSessionTest, PushPromiseInvalidHost) {
882   // Initialize crypto before the client session will create a stream.
883   CompleteCryptoHandshake();
884 
885   session_->CreateOutgoingBidirectionalStream();
886 
887   EXPECT_CALL(*connection_, SendControlFrame(_));
888   EXPECT_CALL(*connection_,
889               OnStreamReset(promised_stream_id_, QUIC_INVALID_PROMISE_URL));
890 
891   push_promise_[":authority"] = "";
892   EXPECT_FALSE(session_->HandlePromised(associated_stream_id_,
893                                         promised_stream_id_, push_promise_));
894 
895   EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr);
896   EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
897 }
898 
TEST_P(QuicSpdyClientSessionTest,TryToCreateServerInitiatedBidirectionalStream)899 TEST_P(QuicSpdyClientSessionTest,
900        TryToCreateServerInitiatedBidirectionalStream) {
901   if (VersionHasIetfQuicFrames(connection_->transport_version())) {
902     EXPECT_CALL(
903         *connection_,
904         CloseConnection(QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM, _, _));
905   } else {
906     EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
907   }
908   session_->GetOrCreateStream(GetNthServerInitiatedBidirectionalStreamId(
909       connection_->transport_version(), 0));
910 }
911 
TEST_P(QuicSpdyClientSessionTest,TooManyPushPromises)912 TEST_P(QuicSpdyClientSessionTest, TooManyPushPromises) {
913   // Initialize crypto before the client session will create a stream.
914   CompleteCryptoHandshake();
915   QuicStreamId stream_id =
916       QuicSessionPeer::GetNextOutgoingBidirectionalStreamId(session_.get());
917   QuicSessionPeer::ActivateStream(
918       session_.get(), std::make_unique<QuicSpdyClientStream>(
919                           stream_id, session_.get(), BIDIRECTIONAL));
920 
921   if (VersionHasIetfQuicFrames(connection_->transport_version())) {
922     session_->SetMaxPushId(kMaxQuicStreamId);
923   }
924 
925   EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM));
926 
927   for (size_t promise_count = 0; promise_count <= session_->get_max_promises();
928        promise_count++) {
929     auto promise_id = GetNthServerInitiatedUnidirectionalStreamId(
930         connection_->transport_version(), promise_count);
931     auto headers = QuicHeaderList();
932     headers.OnHeaderBlockStart();
933     headers.OnHeader(":path", quiche::QuicheStrCat("/", promise_count));
934     headers.OnHeader(":authority", "www.google.com");
935     headers.OnHeader(":method", "GET");
936     headers.OnHeader(":scheme", "https");
937     headers.OnHeaderBlockEnd(0, 0);
938     session_->OnPromiseHeaderList(stream_id, promise_id, 0, headers);
939   }
940 }
941 
942 }  // namespace
943 }  // namespace test
944 }  // namespace quic
945