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 "quiche/quic/tools/quic_simple_server_session.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <utility>
10 
11 #include "absl/strings/str_cat.h"
12 #include "quiche/quic/core/crypto/null_encrypter.h"
13 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
14 #include "quiche/quic/core/crypto/quic_random.h"
15 #include "quiche/quic/core/http/http_encoder.h"
16 #include "quiche/quic/core/proto/cached_network_parameters_proto.h"
17 #include "quiche/quic/core/quic_connection.h"
18 #include "quiche/quic/core/quic_crypto_server_stream.h"
19 #include "quiche/quic/core/quic_utils.h"
20 #include "quiche/quic/core/quic_versions.h"
21 #include "quiche/quic/core/tls_server_handshaker.h"
22 #include "quiche/quic/platform/api/quic_expect_bug.h"
23 #include "quiche/quic/platform/api/quic_flags.h"
24 #include "quiche/quic/platform/api/quic_socket_address.h"
25 #include "quiche/quic/platform/api/quic_test.h"
26 #include "quiche/quic/test_tools/crypto_test_utils.h"
27 #include "quiche/quic/test_tools/mock_quic_session_visitor.h"
28 #include "quiche/quic/test_tools/quic_config_peer.h"
29 #include "quiche/quic/test_tools/quic_connection_peer.h"
30 #include "quiche/quic/test_tools/quic_sent_packet_manager_peer.h"
31 #include "quiche/quic/test_tools/quic_session_peer.h"
32 #include "quiche/quic/test_tools/quic_spdy_session_peer.h"
33 #include "quiche/quic/test_tools/quic_stream_peer.h"
34 #include "quiche/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
35 #include "quiche/quic/test_tools/quic_test_utils.h"
36 #include "quiche/quic/tools/quic_backend_response.h"
37 #include "quiche/quic/tools/quic_memory_cache_backend.h"
38 #include "quiche/quic/tools/quic_simple_server_stream.h"
39 
40 using testing::_;
41 using testing::AtLeast;
42 using testing::InSequence;
43 using testing::Invoke;
44 using testing::Return;
45 using testing::StrictMock;
46 
47 namespace quic {
48 namespace test {
49 namespace {
50 
51 // Data to be sent on a request stream.  In Google QUIC, this is interpreted as
52 // DATA payload (there is no framing on request streams).  In IETF QUIC, this is
53 // interpreted as HEADERS frame (type 0x1) with payload length 122 ('z').  Since
54 // no payload is included, QPACK decoder will not be invoked.
55 const char* const kStreamData = "\1z";
56 
57 }  // namespace
58 
59 class QuicSimpleServerSessionPeer {
60  public:
SetCryptoStream(QuicSimpleServerSession * s,QuicCryptoServerStreamBase * crypto_stream)61   static void SetCryptoStream(QuicSimpleServerSession* s,
62                               QuicCryptoServerStreamBase* crypto_stream) {
63     s->crypto_stream_.reset(crypto_stream);
64   }
65 
CreateIncomingStream(QuicSimpleServerSession * s,QuicStreamId id)66   static QuicSpdyStream* CreateIncomingStream(QuicSimpleServerSession* s,
67                                               QuicStreamId id) {
68     return s->CreateIncomingStream(id);
69   }
70 
CreateOutgoingUnidirectionalStream(QuicSimpleServerSession * s)71   static QuicSimpleServerStream* CreateOutgoingUnidirectionalStream(
72       QuicSimpleServerSession* s) {
73     return s->CreateOutgoingUnidirectionalStream();
74   }
75 };
76 
77 namespace {
78 
79 const size_t kMaxStreamsForTest = 10;
80 
81 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
82  public:
MockQuicCryptoServerStream(const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,QuicSession * session,QuicCryptoServerStreamBase::Helper * helper)83   explicit MockQuicCryptoServerStream(
84       const QuicCryptoServerConfig* crypto_config,
85       QuicCompressedCertsCache* compressed_certs_cache, QuicSession* session,
86       QuicCryptoServerStreamBase::Helper* helper)
87       : QuicCryptoServerStream(crypto_config, compressed_certs_cache, session,
88                                helper) {}
89   MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
90   MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
91       delete;
~MockQuicCryptoServerStream()92   ~MockQuicCryptoServerStream() override {}
93 
94   MOCK_METHOD(void, SendServerConfigUpdate, (const CachedNetworkParameters*),
95               (override));
96 
encryption_established() const97   bool encryption_established() const override { return true; }
98 };
99 
100 class MockTlsServerHandshaker : public TlsServerHandshaker {
101  public:
MockTlsServerHandshaker(QuicSession * session,const QuicCryptoServerConfig * crypto_config)102   explicit MockTlsServerHandshaker(QuicSession* session,
103                                    const QuicCryptoServerConfig* crypto_config)
104       : TlsServerHandshaker(session, crypto_config) {}
105   MockTlsServerHandshaker(const MockTlsServerHandshaker&) = delete;
106   MockTlsServerHandshaker& operator=(const MockTlsServerHandshaker&) = delete;
~MockTlsServerHandshaker()107   ~MockTlsServerHandshaker() override {}
108 
109   MOCK_METHOD(void, SendServerConfigUpdate, (const CachedNetworkParameters*),
110               (override));
111 
encryption_established() const112   bool encryption_established() const override { return true; }
113 };
114 
115 class MockQuicConnectionWithSendStreamData : public MockQuicConnection {
116  public:
MockQuicConnectionWithSendStreamData(MockQuicConnectionHelper * helper,MockAlarmFactory * alarm_factory,Perspective perspective,const ParsedQuicVersionVector & supported_versions)117   MockQuicConnectionWithSendStreamData(
118       MockQuicConnectionHelper* helper, MockAlarmFactory* alarm_factory,
119       Perspective perspective,
120       const ParsedQuicVersionVector& supported_versions)
121       : MockQuicConnection(helper, alarm_factory, perspective,
122                            supported_versions) {
123     auto consume_all_data = [](QuicStreamId /*id*/, size_t write_length,
124                                QuicStreamOffset /*offset*/,
125                                StreamSendingState state) {
126       return QuicConsumedData(write_length, state != NO_FIN);
127     };
128     ON_CALL(*this, SendStreamData(_, _, _, _))
129         .WillByDefault(Invoke(consume_all_data));
130   }
131 
132   MOCK_METHOD(QuicConsumedData, SendStreamData,
133               (QuicStreamId id, size_t write_length, QuicStreamOffset offset,
134                StreamSendingState state),
135               (override));
136 };
137 
138 class MockQuicSimpleServerSession : public QuicSimpleServerSession {
139  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)140   MockQuicSimpleServerSession(
141       const QuicConfig& config, QuicConnection* connection,
142       QuicSession::Visitor* visitor, QuicCryptoServerStreamBase::Helper* helper,
143       const QuicCryptoServerConfig* crypto_config,
144       QuicCompressedCertsCache* compressed_certs_cache,
145       QuicSimpleServerBackend* quic_simple_server_backend)
146       : QuicSimpleServerSession(
147             config, CurrentSupportedVersions(), connection, visitor, helper,
148             crypto_config, compressed_certs_cache, quic_simple_server_backend) {
149   }
150   MOCK_METHOD(void, SendBlocked, (QuicStreamId, QuicStreamOffset), (override));
151   MOCK_METHOD(bool, WriteControlFrame,
152               (const QuicFrame& frame, TransmissionType type), (override));
153 };
154 
155 class QuicSimpleServerSessionTest
156     : public QuicTestWithParam<ParsedQuicVersion> {
157  public:
158   // The function ensures that A) the MAX_STREAMS frames get properly deleted
159   // (since the test uses a 'did we leak memory' check ... if we just lose the
160   // frame, the test fails) and B) returns true (instead of the default, false)
161   // which ensures that the rest of the system thinks that the frame actually
162   // was transmitted.
ClearMaxStreamsControlFrame(const QuicFrame & frame)163   bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
164     if (frame.type == MAX_STREAMS_FRAME) {
165       DeleteFrame(&const_cast<QuicFrame&>(frame));
166       return true;
167     }
168     return false;
169   }
170 
171  protected:
QuicSimpleServerSessionTest()172   QuicSimpleServerSessionTest()
173       : crypto_config_(QuicCryptoServerConfig::TESTING,
174                        QuicRandom::GetInstance(),
175                        crypto_test_utils::ProofSourceForTesting(),
176                        KeyExchangeSource::Default()),
177         compressed_certs_cache_(
178             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
179     config_.SetMaxBidirectionalStreamsToSend(kMaxStreamsForTest);
180     QuicConfigPeer::SetReceivedMaxBidirectionalStreams(&config_,
181                                                        kMaxStreamsForTest);
182     config_.SetMaxUnidirectionalStreamsToSend(kMaxStreamsForTest);
183 
184     config_.SetInitialStreamFlowControlWindowToSend(
185         kInitialStreamFlowControlWindowForTest);
186     config_.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
187         kInitialStreamFlowControlWindowForTest);
188     config_.SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
189         kInitialStreamFlowControlWindowForTest);
190     config_.SetInitialMaxStreamDataBytesUnidirectionalToSend(
191         kInitialStreamFlowControlWindowForTest);
192     config_.SetInitialSessionFlowControlWindowToSend(
193         kInitialSessionFlowControlWindowForTest);
194     if (VersionUsesHttp3(transport_version())) {
195       QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
196           &config_, kMaxStreamsForTest + 3);
197     } else {
198       QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(&config_,
199                                                           kMaxStreamsForTest);
200     }
201 
202     ParsedQuicVersionVector supported_versions = SupportedVersions(version());
203     connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
204         &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
205     connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
206     connection_->SetEncrypter(
207         ENCRYPTION_FORWARD_SECURE,
208         std::make_unique<NullEncrypter>(connection_->perspective()));
209     session_ = std::make_unique<MockQuicSimpleServerSession>(
210         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
211         &compressed_certs_cache_, &memory_cache_backend_);
212     MockClock clock;
213     handshake_message_ = crypto_config_.AddDefaultConfig(
214         QuicRandom::GetInstance(), &clock,
215         QuicCryptoServerConfig::ConfigOptions());
216     session_->Initialize();
217 
218     if (VersionHasIetfQuicFrames(transport_version())) {
219       EXPECT_CALL(*session_, WriteControlFrame(_, _))
220           .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType));
221     }
222     session_->OnConfigNegotiated();
223   }
224 
GetNthClientInitiatedBidirectionalId(int n)225   QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
226     return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
227   }
228 
GetNthServerInitiatedUnidirectionalId(int n)229   QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
230     return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
231         transport_version(), n);
232   }
233 
version() const234   ParsedQuicVersion version() const { return GetParam(); }
235 
transport_version() const236   QuicTransportVersion transport_version() const {
237     return version().transport_version;
238   }
239 
InjectStopSending(QuicStreamId stream_id,QuicRstStreamErrorCode rst_stream_code)240   void InjectStopSending(QuicStreamId stream_id,
241                          QuicRstStreamErrorCode rst_stream_code) {
242     // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
243     // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
244     // a one-way close.
245     if (!VersionHasIetfQuicFrames(transport_version())) {
246       // Only needed for version 99/IETF QUIC.
247       return;
248     }
249     EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1);
250     QuicStopSendingFrame stop_sending(kInvalidControlFrameId, stream_id,
251                                       rst_stream_code);
252     // Expect the RESET_STREAM that is generated in response to receiving a
253     // STOP_SENDING.
254     EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code));
255     session_->OnStopSendingFrame(stop_sending);
256   }
257 
258   StrictMock<MockQuicSessionVisitor> owner_;
259   StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_;
260   MockQuicConnectionHelper helper_;
261   MockAlarmFactory alarm_factory_;
262   StrictMock<MockQuicConnectionWithSendStreamData>* connection_;
263   QuicConfig config_;
264   QuicCryptoServerConfig crypto_config_;
265   QuicCompressedCertsCache compressed_certs_cache_;
266   QuicMemoryCacheBackend memory_cache_backend_;
267   std::unique_ptr<MockQuicSimpleServerSession> session_;
268   std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
269 };
270 
271 INSTANTIATE_TEST_SUITE_P(Tests, QuicSimpleServerSessionTest,
272                          ::testing::ValuesIn(AllSupportedVersions()),
273                          ::testing::PrintToStringParamName());
274 
TEST_P(QuicSimpleServerSessionTest,CloseStreamDueToReset)275 TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
276   // Send some data open a stream, then reset it.
277   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
278                         kStreamData);
279   session_->OnStreamFrame(data1);
280   EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
281 
282   // Receive a reset (and send a RST in response).
283   QuicRstStreamFrame rst1(kInvalidControlFrameId,
284                           GetNthClientInitiatedBidirectionalId(0),
285                           QUIC_ERROR_PROCESSING_STREAM, 0);
286   EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
287   EXPECT_CALL(*session_, WriteControlFrame(_, _));
288 
289   if (!VersionHasIetfQuicFrames(transport_version())) {
290     // For version 99, this is covered in InjectStopSending()
291     EXPECT_CALL(*connection_,
292                 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
293                               QUIC_RST_ACKNOWLEDGEMENT));
294   }
295   session_->OnRstStream(rst1);
296   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
297   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
298   // a one-way close.
299   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
300                     QUIC_ERROR_PROCESSING_STREAM);
301   EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
302 
303   // Send the same two bytes of payload in a new packet.
304   session_->OnStreamFrame(data1);
305 
306   // The stream should not be re-opened.
307   EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
308   EXPECT_TRUE(connection_->connected());
309 }
310 
TEST_P(QuicSimpleServerSessionTest,NeverOpenStreamDueToReset)311 TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
312   // Send a reset (and expect the peer to send a RST in response).
313   QuicRstStreamFrame rst1(kInvalidControlFrameId,
314                           GetNthClientInitiatedBidirectionalId(0),
315                           QUIC_ERROR_PROCESSING_STREAM, 0);
316   EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
317   if (!VersionHasIetfQuicFrames(transport_version())) {
318     EXPECT_CALL(*session_, WriteControlFrame(_, _));
319     // For version 99, this is covered in InjectStopSending()
320     EXPECT_CALL(*connection_,
321                 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
322                               QUIC_RST_ACKNOWLEDGEMENT));
323   }
324   session_->OnRstStream(rst1);
325   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
326   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
327   // a one-way close.
328   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
329                     QUIC_ERROR_PROCESSING_STREAM);
330 
331   EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
332 
333   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
334                         kStreamData);
335   session_->OnStreamFrame(data1);
336 
337   // The stream should never be opened, now that the reset is received.
338   EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
339   EXPECT_TRUE(connection_->connected());
340 }
341 
TEST_P(QuicSimpleServerSessionTest,AcceptClosedStream)342 TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
343   // Send some data to open two streams.
344   QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
345                          kStreamData);
346   QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
347                          kStreamData);
348   session_->OnStreamFrame(frame1);
349   session_->OnStreamFrame(frame2);
350   EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
351 
352   // Send a reset (and expect the peer to send a RST in response).
353   QuicRstStreamFrame rst(kInvalidControlFrameId,
354                          GetNthClientInitiatedBidirectionalId(0),
355                          QUIC_ERROR_PROCESSING_STREAM, 0);
356   EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
357   if (!VersionHasIetfQuicFrames(transport_version())) {
358     EXPECT_CALL(*session_, WriteControlFrame(_, _));
359     // For version 99, this is covered in InjectStopSending()
360     EXPECT_CALL(*connection_,
361                 OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
362                               QUIC_RST_ACKNOWLEDGEMENT));
363   }
364   session_->OnRstStream(rst);
365   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
366   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
367   // a one-way close.
368   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
369                     QUIC_ERROR_PROCESSING_STREAM);
370 
371   // If we were tracking, we'd probably want to reject this because it's data
372   // past the reset point of stream 3.  As it's a closed stream we just drop the
373   // data on the floor, but accept the packet because it has data for stream 5.
374   QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false, 2,
375                          kStreamData);
376   QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
377                          kStreamData);
378   session_->OnStreamFrame(frame3);
379   session_->OnStreamFrame(frame4);
380   // The stream should never be opened, now that the reset is received.
381   EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
382   EXPECT_TRUE(connection_->connected());
383 }
384 
TEST_P(QuicSimpleServerSessionTest,CreateIncomingStreamDisconnected)385 TEST_P(QuicSimpleServerSessionTest, CreateIncomingStreamDisconnected) {
386   // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
387   if (version() != AllSupportedVersions()[0]) {
388     return;
389   }
390 
391   // Tests that incoming stream creation fails when connection is not connected.
392   size_t initial_num_open_stream =
393       QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
394   QuicConnectionPeer::TearDownLocalConnectionState(connection_);
395   EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingStream(
396                       session_.get(), GetNthClientInitiatedBidirectionalId(0)),
397                   "ShouldCreateIncomingStream called when disconnected");
398   EXPECT_EQ(initial_num_open_stream,
399             QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
400 }
401 
TEST_P(QuicSimpleServerSessionTest,CreateIncomingStream)402 TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) {
403   QuicSpdyStream* stream = QuicSimpleServerSessionPeer::CreateIncomingStream(
404       session_.get(), GetNthClientInitiatedBidirectionalId(0));
405   EXPECT_NE(nullptr, stream);
406   EXPECT_EQ(GetNthClientInitiatedBidirectionalId(0), stream->id());
407 }
408 
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamDisconnected)409 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) {
410   // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
411   if (version() != AllSupportedVersions()[0]) {
412     return;
413   }
414 
415   // Tests that outgoing stream creation fails when connection is not connected.
416   size_t initial_num_open_stream =
417       QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
418   QuicConnectionPeer::TearDownLocalConnectionState(connection_);
419   EXPECT_QUIC_BUG(
420       QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
421           session_.get()),
422       "ShouldCreateOutgoingUnidirectionalStream called when disconnected");
423 
424   EXPECT_EQ(initial_num_open_stream,
425             QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
426 }
427 
TEST_P(QuicSimpleServerSessionTest,CreateOutgoingDynamicStreamUnencrypted)428 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUnencrypted) {
429   // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
430   if (version() != AllSupportedVersions()[0]) {
431     return;
432   }
433 
434   // Tests that outgoing stream creation fails when encryption has not yet been
435   // established.
436   size_t initial_num_open_stream =
437       QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
438   EXPECT_QUIC_BUG(
439       QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
440           session_.get()),
441       "Encryption not established so no outgoing stream created.");
442   EXPECT_EQ(initial_num_open_stream,
443             QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
444 }
445 
446 // Tests that calling GetOrCreateStream() on an outgoing stream should result in
447 // the connection being closed.
TEST_P(QuicSimpleServerSessionTest,GetEvenIncomingError)448 TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
449   const size_t initial_num_open_stream =
450       QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
451   const QuicErrorCode expected_error = VersionUsesHttp3(transport_version())
452                                            ? QUIC_HTTP_STREAM_WRONG_DIRECTION
453                                            : QUIC_INVALID_STREAM_ID;
454   EXPECT_CALL(*connection_, CloseConnection(expected_error,
455                                             "Data for nonexistent stream", _));
456   EXPECT_EQ(nullptr,
457             QuicSessionPeer::GetOrCreateStream(
458                 session_.get(), GetNthServerInitiatedUnidirectionalId(3)));
459   EXPECT_EQ(initial_num_open_stream,
460             QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
461 }
462 
463 }  // namespace
464 }  // namespace test
465 }  // namespace quic
466