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