xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_stream_id_manager_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2018 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 #include "quiche/quic/core/quic_stream_id_manager.h"
5 
6 #include <cstdint>
7 #include <string>
8 #include <utility>
9 
10 #include "absl/strings/str_cat.h"
11 #include "quiche/quic/core/quic_constants.h"
12 #include "quiche/quic/core/quic_utils.h"
13 #include "quiche/quic/core/quic_versions.h"
14 #include "quiche/quic/platform/api/quic_expect_bug.h"
15 #include "quiche/quic/platform/api/quic_test.h"
16 #include "quiche/quic/test_tools/quic_stream_id_manager_peer.h"
17 
18 using testing::_;
19 using testing::StrictMock;
20 
21 namespace quic {
22 namespace test {
23 namespace {
24 
25 class MockDelegate : public QuicStreamIdManager::DelegateInterface {
26  public:
27   MOCK_METHOD(void, SendMaxStreams,
28               (QuicStreamCount stream_count, bool unidirectional), (override));
29   MOCK_METHOD(bool, CanSendMaxStreams, (), (override));
30 };
31 
32 struct TestParams {
TestParamsquic::test::__anon6bb801720111::TestParams33   TestParams(ParsedQuicVersion version, Perspective perspective,
34              bool is_unidirectional)
35       : version(version),
36         perspective(perspective),
37         is_unidirectional(is_unidirectional) {}
38 
39   ParsedQuicVersion version;
40   Perspective perspective;
41   bool is_unidirectional;
42 };
43 
44 // Used by ::testing::PrintToStringParamName().
PrintToString(const TestParams & p)45 std::string PrintToString(const TestParams& p) {
46   return absl::StrCat(
47       ParsedQuicVersionToString(p.version), "_",
48       (p.perspective == Perspective::IS_CLIENT ? "Client" : "Server"),
49       (p.is_unidirectional ? "Unidirectional" : "Bidirectional"));
50 }
51 
GetTestParams()52 std::vector<TestParams> GetTestParams() {
53   std::vector<TestParams> params;
54   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
55     if (!version.HasIetfQuicFrames()) {
56       continue;
57     }
58     for (Perspective perspective :
59          {Perspective::IS_CLIENT, Perspective::IS_SERVER}) {
60       for (bool is_unidirectional : {true, false}) {
61         params.push_back(TestParams(version, perspective, is_unidirectional));
62       }
63     }
64   }
65   return params;
66 }
67 
68 class QuicStreamIdManagerTest : public QuicTestWithParam<TestParams> {
69  protected:
QuicStreamIdManagerTest()70   QuicStreamIdManagerTest()
71       : stream_id_manager_(&delegate_, IsUnidirectional(), perspective(),
72                            GetParam().version, 0,
73                            kDefaultMaxStreamsPerConnection) {
74     QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version()));
75   }
76 
transport_version() const77   QuicTransportVersion transport_version() const {
78     return GetParam().version.transport_version;
79   }
80 
81   // Returns the stream ID for the Nth incoming stream (created by the peer)
82   // of the corresponding directionality of this manager.
GetNthIncomingStreamId(int n)83   QuicStreamId GetNthIncomingStreamId(int n) {
84     return QuicUtils::StreamIdDelta(transport_version()) * n +
85            (IsUnidirectional()
86                 ? QuicUtils::GetFirstUnidirectionalStreamId(
87                       transport_version(),
88                       QuicUtils::InvertPerspective(perspective()))
89                 : QuicUtils::GetFirstBidirectionalStreamId(
90                       transport_version(),
91                       QuicUtils::InvertPerspective(perspective())));
92   }
93 
IsUnidirectional()94   bool IsUnidirectional() { return GetParam().is_unidirectional; }
perspective()95   Perspective perspective() { return GetParam().perspective; }
96 
97   StrictMock<MockDelegate> delegate_;
98   QuicStreamIdManager stream_id_manager_;
99 };
100 
101 INSTANTIATE_TEST_SUITE_P(Tests, QuicStreamIdManagerTest,
102                          ::testing::ValuesIn(GetTestParams()),
103                          ::testing::PrintToStringParamName());
104 
TEST_P(QuicStreamIdManagerTest,Initialization)105 TEST_P(QuicStreamIdManagerTest, Initialization) {
106   EXPECT_EQ(0u, stream_id_manager_.outgoing_max_streams());
107 
108   EXPECT_EQ(kDefaultMaxStreamsPerConnection,
109             stream_id_manager_.incoming_actual_max_streams());
110   EXPECT_EQ(kDefaultMaxStreamsPerConnection,
111             stream_id_manager_.incoming_advertised_max_streams());
112   EXPECT_EQ(kDefaultMaxStreamsPerConnection,
113             stream_id_manager_.incoming_initial_max_open_streams());
114 }
115 
116 // This test checks that the stream advertisement window is set to 1
117 // if the number of stream ids is 1. This is a special case in the code.
TEST_P(QuicStreamIdManagerTest,CheckMaxStreamsWindowForSingleStream)118 TEST_P(QuicStreamIdManagerTest, CheckMaxStreamsWindowForSingleStream) {
119   stream_id_manager_.SetMaxOpenIncomingStreams(1);
120   EXPECT_EQ(1u, stream_id_manager_.incoming_initial_max_open_streams());
121   EXPECT_EQ(1u, stream_id_manager_.incoming_actual_max_streams());
122 }
123 
TEST_P(QuicStreamIdManagerTest,CheckMaxStreamsBadValuesOverMaxFailsOutgoing)124 TEST_P(QuicStreamIdManagerTest, CheckMaxStreamsBadValuesOverMaxFailsOutgoing) {
125   QuicStreamCount implementation_max = QuicUtils::GetMaxStreamCount();
126   // Ensure that the limit is less than the implementation maximum.
127   EXPECT_LT(stream_id_manager_.outgoing_max_streams(), implementation_max);
128 
129   EXPECT_TRUE(
130       stream_id_manager_.MaybeAllowNewOutgoingStreams(implementation_max + 1));
131   // Should be pegged at the max.
132   EXPECT_EQ(implementation_max, stream_id_manager_.outgoing_max_streams());
133 }
134 
135 // Check the case of the stream count in a STREAMS_BLOCKED frame is less than
136 // the count most recently advertised in a MAX_STREAMS frame.
TEST_P(QuicStreamIdManagerTest,ProcessStreamsBlockedOk)137 TEST_P(QuicStreamIdManagerTest, ProcessStreamsBlockedOk) {
138   QuicStreamCount stream_count =
139       stream_id_manager_.incoming_initial_max_open_streams();
140   QuicStreamsBlockedFrame frame(0, stream_count - 1, IsUnidirectional());
141   // We have notified peer about current max.
142   EXPECT_CALL(delegate_, SendMaxStreams(stream_count, IsUnidirectional()))
143       .Times(0);
144   std::string error_details;
145   EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
146 }
147 
148 // Check the case of the stream count in a STREAMS_BLOCKED frame is equal to the
149 // count most recently advertised in a MAX_STREAMS frame. No MAX_STREAMS
150 // should be generated.
TEST_P(QuicStreamIdManagerTest,ProcessStreamsBlockedNoOp)151 TEST_P(QuicStreamIdManagerTest, ProcessStreamsBlockedNoOp) {
152   QuicStreamCount stream_count =
153       stream_id_manager_.incoming_initial_max_open_streams();
154   QuicStreamsBlockedFrame frame(0, stream_count, IsUnidirectional());
155   EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
156 }
157 
158 // Check the case of the stream count in a STREAMS_BLOCKED frame is greater than
159 // the count most recently advertised in a MAX_STREAMS frame. Expect a
160 // connection close with an error.
TEST_P(QuicStreamIdManagerTest,ProcessStreamsBlockedTooBig)161 TEST_P(QuicStreamIdManagerTest, ProcessStreamsBlockedTooBig) {
162   EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
163   QuicStreamCount stream_count =
164       stream_id_manager_.incoming_initial_max_open_streams() + 1;
165   QuicStreamsBlockedFrame frame(0, stream_count, IsUnidirectional());
166   std::string error_details;
167   EXPECT_FALSE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
168   EXPECT_EQ(
169       error_details,
170       "StreamsBlockedFrame's stream count 101 exceeds incoming max stream 100");
171 }
172 
173 // Same basic tests as above, but calls
174 // QuicStreamIdManager::MaybeIncreaseLargestPeerStreamId directly, avoiding the
175 // call chain. The intent is that if there is a problem, the following tests
176 // will point to either the stream ID manager or the call chain. They also
177 // provide specific, small scale, tests of a public QuicStreamIdManager method.
178 // First test make sure that streams with ids below the limit are accepted.
TEST_P(QuicStreamIdManagerTest,IsIncomingStreamIdValidBelowLimit)179 TEST_P(QuicStreamIdManagerTest, IsIncomingStreamIdValidBelowLimit) {
180   QuicStreamId stream_id = GetNthIncomingStreamId(
181       stream_id_manager_.incoming_actual_max_streams() - 2);
182   EXPECT_TRUE(
183       stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, nullptr));
184 }
185 
186 // Accept a stream with an ID that equals the limit.
TEST_P(QuicStreamIdManagerTest,IsIncomingStreamIdValidAtLimit)187 TEST_P(QuicStreamIdManagerTest, IsIncomingStreamIdValidAtLimit) {
188   QuicStreamId stream_id = GetNthIncomingStreamId(
189       stream_id_manager_.incoming_actual_max_streams() - 1);
190   EXPECT_TRUE(
191       stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, nullptr));
192 }
193 
194 // Close the connection if the id exceeds the limit.
TEST_P(QuicStreamIdManagerTest,IsIncomingStreamIdInValidAboveLimit)195 TEST_P(QuicStreamIdManagerTest, IsIncomingStreamIdInValidAboveLimit) {
196   QuicStreamId stream_id =
197       GetNthIncomingStreamId(stream_id_manager_.incoming_actual_max_streams());
198   std::string error_details;
199   EXPECT_FALSE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
200       stream_id, &error_details));
201   EXPECT_EQ(error_details,
202             absl::StrCat("Stream id ", stream_id,
203                          " would exceed stream count limit 100"));
204 }
205 
TEST_P(QuicStreamIdManagerTest,OnStreamsBlockedFrame)206 TEST_P(QuicStreamIdManagerTest, OnStreamsBlockedFrame) {
207   // Get the current maximum allowed incoming stream count.
208   QuicStreamCount advertised_stream_count =
209       stream_id_manager_.incoming_advertised_max_streams();
210 
211   QuicStreamsBlockedFrame frame;
212 
213   frame.unidirectional = IsUnidirectional();
214 
215   // If the peer is saying it's blocked on the stream count that
216   // we've advertised, it's a noop since the peer has the correct information.
217   frame.stream_count = advertised_stream_count;
218   std::string error_details;
219   EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
220 
221   // If the peer is saying it's blocked on a stream count that is larger
222   // than what we've advertised, the connection should get closed.
223   frame.stream_count = advertised_stream_count + 1;
224   EXPECT_FALSE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
225   EXPECT_EQ(
226       error_details,
227       "StreamsBlockedFrame's stream count 101 exceeds incoming max stream 100");
228 
229   // If the peer is saying it's blocked on a count that is less than
230   // our actual count, we send a MAX_STREAMS frame and update
231   // the advertised value.
232   // First, need to bump up the actual max so there is room for the MAX
233   // STREAMS frame to send a larger ID.
234   QuicStreamCount actual_stream_count =
235       stream_id_manager_.incoming_actual_max_streams();
236 
237   // Closing a stream will result in the ability to initiate one more
238   // stream
239   stream_id_manager_.OnStreamClosed(
240       QuicStreamIdManagerPeer::GetFirstIncomingStreamId(&stream_id_manager_));
241   EXPECT_EQ(actual_stream_count + 1u,
242             stream_id_manager_.incoming_actual_max_streams());
243   EXPECT_EQ(stream_id_manager_.incoming_actual_max_streams(),
244             stream_id_manager_.incoming_advertised_max_streams() + 1u);
245 
246   // Now simulate receiving a STREAMS_BLOCKED frame...
247   // Changing the actual maximum, above, forces a MAX_STREAMS frame to be
248   // sent, so the logic for that (SendMaxStreamsFrame(), etc) is tested.
249 
250   // The STREAMS_BLOCKED frame contains the previous advertised count,
251   // not the one that the peer would have received as a result of the
252   // MAX_STREAMS sent earler.
253   frame.stream_count = advertised_stream_count;
254 
255   EXPECT_CALL(delegate_, CanSendMaxStreams()).WillOnce(testing::Return(true));
256   EXPECT_CALL(delegate_,
257               SendMaxStreams(stream_id_manager_.incoming_actual_max_streams(),
258                              IsUnidirectional()));
259 
260   EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
261   // Check that the saved frame is correct.
262   EXPECT_EQ(stream_id_manager_.incoming_actual_max_streams(),
263             stream_id_manager_.incoming_advertised_max_streams());
264 }
265 
TEST_P(QuicStreamIdManagerTest,OnStreamsBlockedFrameCantSend)266 TEST_P(QuicStreamIdManagerTest, OnStreamsBlockedFrameCantSend) {
267   // Get the current maximum allowed incoming stream count.
268   QuicStreamCount advertised_stream_count =
269       stream_id_manager_.incoming_advertised_max_streams();
270 
271   QuicStreamsBlockedFrame frame;
272 
273   frame.unidirectional = IsUnidirectional();
274 
275   // First, need to bump up the actual max so there is room for the MAX
276   // STREAMS frame to send a larger ID.
277   QuicStreamCount actual_stream_count =
278       stream_id_manager_.incoming_actual_max_streams();
279 
280   // Closing a stream will result in the ability to initiate one more
281   // stream
282   stream_id_manager_.OnStreamClosed(
283       QuicStreamIdManagerPeer::GetFirstIncomingStreamId(&stream_id_manager_));
284   EXPECT_EQ(actual_stream_count + 1u,
285             stream_id_manager_.incoming_actual_max_streams());
286   EXPECT_EQ(stream_id_manager_.incoming_actual_max_streams(),
287             stream_id_manager_.incoming_advertised_max_streams() + 1u);
288 
289   // Now simulate receiving a STREAMS_BLOCKED frame...
290   // Changing the actual maximum, above, forces a MAX_STREAMS frame to be
291   // sent, so the logic for that (SendMaxStreamsFrame(), etc) is tested.
292 
293   // The STREAMS_BLOCKED frame contains the previous advertised count,
294   // not the one that the peer would have received as a result of the
295   // MAX_STREAMS sent earler.
296   frame.stream_count = advertised_stream_count;
297 
298   // Since the delegate returns false, no MAX_STREAMS frame should be sent,
299   // and the advertised limit should not increse.
300   EXPECT_CALL(delegate_, CanSendMaxStreams()).WillOnce(testing::Return(false));
301   EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
302 
303   const QuicStreamCount advertised_max_streams =
304       stream_id_manager_.incoming_advertised_max_streams();
305   std::string error_details;
306   EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
307   EXPECT_EQ(advertised_max_streams,
308             stream_id_manager_.incoming_advertised_max_streams());
309 }
310 
TEST_P(QuicStreamIdManagerTest,GetNextOutgoingStream)311 TEST_P(QuicStreamIdManagerTest, GetNextOutgoingStream) {
312   // Number of streams we can open and the first one we should get when
313   // opening...
314   size_t number_of_streams = kDefaultMaxStreamsPerConnection;
315 
316   EXPECT_TRUE(
317       stream_id_manager_.MaybeAllowNewOutgoingStreams(number_of_streams));
318 
319   QuicStreamId stream_id = IsUnidirectional()
320                                ? QuicUtils::GetFirstUnidirectionalStreamId(
321                                      transport_version(), perspective())
322                                : QuicUtils::GetFirstBidirectionalStreamId(
323                                      transport_version(), perspective());
324 
325   EXPECT_EQ(number_of_streams, stream_id_manager_.outgoing_max_streams());
326   while (number_of_streams) {
327     EXPECT_TRUE(stream_id_manager_.CanOpenNextOutgoingStream());
328     EXPECT_EQ(stream_id, stream_id_manager_.GetNextOutgoingStreamId());
329     stream_id += QuicUtils::StreamIdDelta(transport_version());
330     number_of_streams--;
331   }
332 
333   // If we try to check that the next outgoing stream id is available it should
334   // fail.
335   EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
336 
337   // If we try to get the next id (above the limit), it should cause a quic-bug.
338   EXPECT_QUIC_BUG(
339       stream_id_manager_.GetNextOutgoingStreamId(),
340       "Attempt to allocate a new outgoing stream that would exceed the limit");
341 }
342 
TEST_P(QuicStreamIdManagerTest,MaybeIncreaseLargestPeerStreamId)343 TEST_P(QuicStreamIdManagerTest, MaybeIncreaseLargestPeerStreamId) {
344   QuicStreamId max_stream_id = GetNthIncomingStreamId(
345       stream_id_manager_.incoming_actual_max_streams() - 1);
346   EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(max_stream_id,
347                                                                   nullptr));
348 
349   QuicStreamId first_stream_id = GetNthIncomingStreamId(0);
350   EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
351       first_stream_id, nullptr));
352   // A bad stream ID results in a closed connection.
353   std::string error_details;
354   EXPECT_FALSE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
355       max_stream_id + QuicUtils::StreamIdDelta(transport_version()),
356       &error_details));
357   EXPECT_EQ(error_details,
358             absl::StrCat(
359                 "Stream id ",
360                 max_stream_id + QuicUtils::StreamIdDelta(transport_version()),
361                 " would exceed stream count limit 100"));
362 }
363 
TEST_P(QuicStreamIdManagerTest,MaxStreamsWindow)364 TEST_P(QuicStreamIdManagerTest, MaxStreamsWindow) {
365   // Open and then close a number of streams to get close to the threshold of
366   // sending a MAX_STREAM_FRAME.
367   int stream_count = stream_id_manager_.incoming_initial_max_open_streams() /
368                          GetQuicFlag(quic_max_streams_window_divisor) -
369                      1;
370 
371   // Should not get a control-frame transmission since the peer should have
372   // "plenty" of stream IDs to use.
373   EXPECT_CALL(delegate_, CanSendMaxStreams()).Times(0);
374   EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
375 
376   // Get the first incoming stream ID to try and allocate.
377   QuicStreamId stream_id = GetNthIncomingStreamId(0);
378   size_t old_available_incoming_streams =
379       stream_id_manager_.available_incoming_streams();
380   auto i = stream_count;
381   while (i) {
382     EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id,
383                                                                     nullptr));
384 
385     // This node should think that the peer believes it has one fewer
386     // stream it can create.
387     old_available_incoming_streams--;
388     EXPECT_EQ(old_available_incoming_streams,
389               stream_id_manager_.available_incoming_streams());
390 
391     i--;
392     stream_id += QuicUtils::StreamIdDelta(transport_version());
393   }
394 
395   // Now close them, still should get no MAX_STREAMS
396   stream_id = GetNthIncomingStreamId(0);
397   QuicStreamCount expected_actual_max =
398       stream_id_manager_.incoming_actual_max_streams();
399   QuicStreamCount expected_advertised_max_streams =
400       stream_id_manager_.incoming_advertised_max_streams();
401   while (stream_count) {
402     stream_id_manager_.OnStreamClosed(stream_id);
403     stream_count--;
404     stream_id += QuicUtils::StreamIdDelta(transport_version());
405     expected_actual_max++;
406     EXPECT_EQ(expected_actual_max,
407               stream_id_manager_.incoming_actual_max_streams());
408     // Advertised maximum should remain the same.
409     EXPECT_EQ(expected_advertised_max_streams,
410               stream_id_manager_.incoming_advertised_max_streams());
411   }
412 
413   // This should not change.
414   EXPECT_EQ(old_available_incoming_streams,
415             stream_id_manager_.available_incoming_streams());
416 
417   // Now whenever we close a stream we should get a MAX_STREAMS frame.
418   // Above code closed all the open streams, so we have to open/close
419   //  EXPECT_CALL(delegate_,
420   //  SendMaxStreams(stream_id_manager_.incoming_actual_max_streams(),
421   //  IsUnidirectional()));
422   EXPECT_CALL(delegate_, CanSendMaxStreams()).WillOnce(testing::Return(true));
423   EXPECT_CALL(delegate_, SendMaxStreams(_, IsUnidirectional()));
424   EXPECT_TRUE(
425       stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, nullptr));
426   stream_id_manager_.OnStreamClosed(stream_id);
427 }
428 
TEST_P(QuicStreamIdManagerTest,MaxStreamsWindowCantSend)429 TEST_P(QuicStreamIdManagerTest, MaxStreamsWindowCantSend) {
430   // Open and then close a number of streams to get close to the threshold of
431   // sending a MAX_STREAM_FRAME.
432   int stream_count = stream_id_manager_.incoming_initial_max_open_streams() /
433                          GetQuicFlag(quic_max_streams_window_divisor) -
434                      1;
435 
436   // Should not get a control-frame transmission since the peer should have
437   // "plenty" of stream IDs to use.
438   EXPECT_CALL(delegate_, CanSendMaxStreams()).Times(0);
439   EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
440 
441   // Get the first incoming stream ID to try and allocate.
442   QuicStreamId stream_id = GetNthIncomingStreamId(0);
443   size_t old_available_incoming_streams =
444       stream_id_manager_.available_incoming_streams();
445   auto i = stream_count;
446   while (i) {
447     EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id,
448                                                                     nullptr));
449 
450     // This node should think that the peer believes it has one fewer
451     // stream it can create.
452     old_available_incoming_streams--;
453     EXPECT_EQ(old_available_incoming_streams,
454               stream_id_manager_.available_incoming_streams());
455 
456     i--;
457     stream_id += QuicUtils::StreamIdDelta(transport_version());
458   }
459 
460   // Now close them, still should get no MAX_STREAMS
461   stream_id = GetNthIncomingStreamId(0);
462   QuicStreamCount expected_actual_max =
463       stream_id_manager_.incoming_actual_max_streams();
464   QuicStreamCount expected_advertised_max_streams =
465       stream_id_manager_.incoming_advertised_max_streams();
466   while (stream_count) {
467     stream_id_manager_.OnStreamClosed(stream_id);
468     stream_count--;
469     stream_id += QuicUtils::StreamIdDelta(transport_version());
470     expected_actual_max++;
471     EXPECT_EQ(expected_actual_max,
472               stream_id_manager_.incoming_actual_max_streams());
473     // Advertised maximum should remain the same.
474     EXPECT_EQ(expected_advertised_max_streams,
475               stream_id_manager_.incoming_advertised_max_streams());
476   }
477 
478   // This should not change.
479   EXPECT_EQ(old_available_incoming_streams,
480             stream_id_manager_.available_incoming_streams());
481 
482   // Now whenever we close a stream we should get a MAX_STREAMS frame,
483   // but since the delegate returns false, no MAX_STREAMS frame should
484   // be send and the advertised limit will not change.
485   // Above code closed all the open streams, so we have to open/close
486   EXPECT_CALL(delegate_, CanSendMaxStreams()).WillOnce(testing::Return(false));
487   EXPECT_CALL(delegate_, SendMaxStreams(_, IsUnidirectional())).Times(0);
488   EXPECT_TRUE(
489       stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, nullptr));
490   stream_id_manager_.OnStreamClosed(stream_id);
491   // Advertised maximum should remain the same.
492   EXPECT_EQ(expected_advertised_max_streams,
493             stream_id_manager_.incoming_advertised_max_streams());
494 }
495 
TEST_P(QuicStreamIdManagerTest,MaxStreamsWindowStopsIncreasing)496 TEST_P(QuicStreamIdManagerTest, MaxStreamsWindowStopsIncreasing) {
497   // Verify that the incoming stream limit does not increase after
498   // StopIncreasingIncomingMaxStreams() is called, even when streams are closed.
499 
500   QuicStreamId stream_count =
501       stream_id_manager_.incoming_initial_max_open_streams();
502   // Open up to the stream limit.
503   QuicStreamId stream_id = GetNthIncomingStreamId(0);
504   for (QuicStreamCount i = 0; i < stream_count; ++i) {
505     EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id,
506                                                                     nullptr));
507 
508     stream_id += QuicUtils::StreamIdDelta(transport_version());
509   }
510 
511   // Prevent max streams from increasing.
512   stream_id_manager_.StopIncreasingIncomingMaxStreams();
513 
514   // Since the limit does not increase, a MAX_STREAMS frame will not be sent.
515   EXPECT_CALL(delegate_, CanSendMaxStreams()).Times(0);
516   EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
517 
518   // Now close them.
519   stream_id = GetNthIncomingStreamId(0);
520   QuicStreamCount expected_actual_max =
521       stream_id_manager_.incoming_actual_max_streams();
522   QuicStreamCount expected_advertised_max_streams =
523       stream_id_manager_.incoming_advertised_max_streams();
524   for (QuicStreamCount i = 0; i < stream_count; ++i) {
525     stream_id_manager_.OnStreamClosed(stream_id);
526     stream_id += QuicUtils::StreamIdDelta(transport_version());
527     // Limits should not change.
528     EXPECT_EQ(expected_actual_max,
529               stream_id_manager_.incoming_actual_max_streams());
530     EXPECT_EQ(expected_advertised_max_streams,
531               stream_id_manager_.incoming_advertised_max_streams());
532   }
533 }
534 
TEST_P(QuicStreamIdManagerTest,StreamsBlockedEdgeConditions)535 TEST_P(QuicStreamIdManagerTest, StreamsBlockedEdgeConditions) {
536   QuicStreamsBlockedFrame frame;
537   frame.unidirectional = IsUnidirectional();
538 
539   // Check that receipt of a STREAMS BLOCKED with stream-count = 0 does nothing
540   // when max_allowed_incoming_streams is 0.
541   EXPECT_CALL(delegate_, CanSendMaxStreams()).Times(0);
542   EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
543   stream_id_manager_.SetMaxOpenIncomingStreams(0);
544   frame.stream_count = 0;
545   std::string error_details;
546   EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
547 
548   // Check that receipt of a STREAMS BLOCKED with stream-count = 0 invokes a
549   // MAX STREAMS, count = 123, when the MaxOpen... is set to 123.
550   EXPECT_CALL(delegate_, CanSendMaxStreams()).WillOnce(testing::Return(true));
551   EXPECT_CALL(delegate_, SendMaxStreams(123u, IsUnidirectional()));
552   QuicStreamIdManagerPeer::set_incoming_actual_max_streams(&stream_id_manager_,
553                                                            123);
554   frame.stream_count = 0;
555   EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
556 }
557 
558 // Test that a MAX_STREAMS frame is generated when half the stream ids become
559 // available. This has a useful side effect of testing that when streams are
560 // closed, the number of available stream ids increases.
TEST_P(QuicStreamIdManagerTest,MaxStreamsSlidingWindow)561 TEST_P(QuicStreamIdManagerTest, MaxStreamsSlidingWindow) {
562   QuicStreamCount first_advert =
563       stream_id_manager_.incoming_advertised_max_streams();
564 
565   // Open/close enough streams to shrink the window without causing a MAX
566   // STREAMS to be generated. The loop
567   // will make that many stream IDs available, so the last CloseStream should
568   // cause a MAX STREAMS frame to be generated.
569   int i =
570       static_cast<int>(stream_id_manager_.incoming_initial_max_open_streams() /
571                        GetQuicFlag(quic_max_streams_window_divisor));
572   QuicStreamId id =
573       QuicStreamIdManagerPeer::GetFirstIncomingStreamId(&stream_id_manager_);
574   EXPECT_CALL(delegate_, CanSendMaxStreams()).WillOnce(testing::Return(true));
575   EXPECT_CALL(delegate_, SendMaxStreams(first_advert + i, IsUnidirectional()));
576   while (i) {
577     EXPECT_TRUE(
578         stream_id_manager_.MaybeIncreaseLargestPeerStreamId(id, nullptr));
579     stream_id_manager_.OnStreamClosed(id);
580     i--;
581     id += QuicUtils::StreamIdDelta(transport_version());
582   }
583 }
584 
TEST_P(QuicStreamIdManagerTest,NewStreamDoesNotExceedLimit)585 TEST_P(QuicStreamIdManagerTest, NewStreamDoesNotExceedLimit) {
586   EXPECT_TRUE(stream_id_manager_.MaybeAllowNewOutgoingStreams(100));
587 
588   size_t stream_count = stream_id_manager_.outgoing_max_streams();
589   EXPECT_NE(0u, stream_count);
590 
591   while (stream_count) {
592     EXPECT_TRUE(stream_id_manager_.CanOpenNextOutgoingStream());
593     stream_id_manager_.GetNextOutgoingStreamId();
594     stream_count--;
595   }
596 
597   EXPECT_EQ(stream_id_manager_.outgoing_stream_count(),
598             stream_id_manager_.outgoing_max_streams());
599   // Create another, it should fail.
600   EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
601 }
602 
TEST_P(QuicStreamIdManagerTest,AvailableStreams)603 TEST_P(QuicStreamIdManagerTest, AvailableStreams) {
604   stream_id_manager_.MaybeIncreaseLargestPeerStreamId(GetNthIncomingStreamId(3),
605                                                       nullptr);
606 
607   EXPECT_TRUE(stream_id_manager_.IsAvailableStream(GetNthIncomingStreamId(1)));
608   EXPECT_TRUE(stream_id_manager_.IsAvailableStream(GetNthIncomingStreamId(2)));
609   EXPECT_FALSE(stream_id_manager_.IsAvailableStream(GetNthIncomingStreamId(3)));
610   EXPECT_TRUE(stream_id_manager_.IsAvailableStream(GetNthIncomingStreamId(4)));
611 }
612 
613 // Tests that if MaybeIncreaseLargestPeerStreamId is given an extremely
614 // large stream ID (larger than the limit) it is rejected.
615 // This is a regression for Chromium bugs 909987 and 910040
TEST_P(QuicStreamIdManagerTest,ExtremeMaybeIncreaseLargestPeerStreamId)616 TEST_P(QuicStreamIdManagerTest, ExtremeMaybeIncreaseLargestPeerStreamId) {
617   QuicStreamId too_big_stream_id = GetNthIncomingStreamId(
618       stream_id_manager_.incoming_actual_max_streams() + 20);
619 
620   std::string error_details;
621   EXPECT_FALSE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
622       too_big_stream_id, &error_details));
623   EXPECT_EQ(error_details,
624             absl::StrCat("Stream id ", too_big_stream_id,
625                          " would exceed stream count limit 100"));
626 }
627 
628 }  // namespace
629 }  // namespace test
630 }  // namespace quic
631