xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/core/quic_connection_id_manager.h"
6 
7 #include <cstddef>
8 
9 #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h"
10 #include "quiche/quic/core/quic_connection_id.h"
11 #include "quiche/quic/core/quic_error_codes.h"
12 #include "quiche/quic/platform/api/quic_flags.h"
13 #include "quiche/quic/platform/api/quic_test.h"
14 #include "quiche/quic/test_tools/mock_clock.h"
15 #include "quiche/quic/test_tools/mock_connection_id_generator.h"
16 #include "quiche/quic/test_tools/quic_connection_id_manager_peer.h"
17 #include "quiche/quic/test_tools/quic_test_utils.h"
18 
19 namespace quic::test {
20 namespace {
21 
22 using ::quic::test::IsError;
23 using ::quic::test::IsQuicNoError;
24 using ::quic::test::QuicConnectionIdManagerPeer;
25 using ::quic::test::TestConnectionId;
26 using ::testing::_;
27 using ::testing::ElementsAre;
28 using ::testing::IsNull;
29 using ::testing::Return;
30 using ::testing::StrictMock;
31 
32 class TestPeerIssuedConnectionIdManagerVisitor
33     : public QuicConnectionIdManagerVisitorInterface {
34  public:
SetPeerIssuedConnectionIdManager(QuicPeerIssuedConnectionIdManager * peer_issued_connection_id_manager)35   void SetPeerIssuedConnectionIdManager(
36       QuicPeerIssuedConnectionIdManager* peer_issued_connection_id_manager) {
37     peer_issued_connection_id_manager_ = peer_issued_connection_id_manager;
38   }
39 
OnPeerIssuedConnectionIdRetired()40   void OnPeerIssuedConnectionIdRetired() override {
41     // Replace current connection Id if it has been retired.
42     if (!peer_issued_connection_id_manager_->IsConnectionIdActive(
43             current_peer_issued_connection_id_)) {
44       current_peer_issued_connection_id_ =
45           peer_issued_connection_id_manager_->ConsumeOneUnusedConnectionId()
46               ->connection_id;
47     }
48     // Retire all the to-be-retired connection Ids.
49     most_recent_retired_connection_id_sequence_numbers_ =
50         peer_issued_connection_id_manager_
51             ->ConsumeToBeRetiredConnectionIdSequenceNumbers();
52   }
53 
54   const std::vector<uint64_t>&
most_recent_retired_connection_id_sequence_numbers()55   most_recent_retired_connection_id_sequence_numbers() {
56     return most_recent_retired_connection_id_sequence_numbers_;
57   }
58 
SetCurrentPeerConnectionId(QuicConnectionId cid)59   void SetCurrentPeerConnectionId(QuicConnectionId cid) {
60     current_peer_issued_connection_id_ = cid;
61   }
62 
GetCurrentPeerConnectionId()63   const QuicConnectionId& GetCurrentPeerConnectionId() {
64     return current_peer_issued_connection_id_;
65   }
66 
SendNewConnectionId(const QuicNewConnectionIdFrame &)67   bool SendNewConnectionId(const QuicNewConnectionIdFrame& /*frame*/) override {
68     return false;
69   }
MaybeReserveConnectionId(const QuicConnectionId &)70   bool MaybeReserveConnectionId(const QuicConnectionId&) override {
71     return false;
72   }
73 
OnSelfIssuedConnectionIdRetired(const QuicConnectionId &)74   void OnSelfIssuedConnectionIdRetired(
75       const QuicConnectionId& /*connection_id*/) override {}
76 
77  private:
78   QuicPeerIssuedConnectionIdManager* peer_issued_connection_id_manager_ =
79       nullptr;
80   QuicConnectionId current_peer_issued_connection_id_;
81   std::vector<uint64_t> most_recent_retired_connection_id_sequence_numbers_;
82 };
83 
84 class QuicPeerIssuedConnectionIdManagerTest : public QuicTest {
85  public:
QuicPeerIssuedConnectionIdManagerTest()86   QuicPeerIssuedConnectionIdManagerTest()
87       : peer_issued_cid_manager_(
88             /*active_connection_id_limit=*/2, initial_connection_id_, &clock_,
89             &alarm_factory_, &cid_manager_visitor_, /*context=*/nullptr) {
90     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
91     cid_manager_visitor_.SetPeerIssuedConnectionIdManager(
92         &peer_issued_cid_manager_);
93     cid_manager_visitor_.SetCurrentPeerConnectionId(initial_connection_id_);
94     retire_peer_issued_cid_alarm_ =
95         QuicConnectionIdManagerPeer::GetRetirePeerIssuedConnectionIdAlarm(
96             &peer_issued_cid_manager_);
97   }
98 
99  protected:
100   MockClock clock_;
101   test::MockAlarmFactory alarm_factory_;
102   TestPeerIssuedConnectionIdManagerVisitor cid_manager_visitor_;
103   QuicConnectionId initial_connection_id_ = TestConnectionId(0);
104   QuicPeerIssuedConnectionIdManager peer_issued_cid_manager_;
105   QuicAlarm* retire_peer_issued_cid_alarm_ = nullptr;
106   std::string error_details_;
107   bool duplicate_frame_ = false;
108 };
109 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ConnectionIdSequenceWhenMigrationSucceed)110 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
111        ConnectionIdSequenceWhenMigrationSucceed) {
112   {
113     // Receives CID #1 from peer.
114     QuicNewConnectionIdFrame frame;
115     frame.connection_id = TestConnectionId(1);
116     frame.sequence_number = 1u;
117     frame.retire_prior_to = 0u;
118     frame.stateless_reset_token =
119         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
120     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
121                     frame, &error_details_, &duplicate_frame_),
122                 IsQuicNoError());
123 
124     // Start to use CID #1 for alternative path.
125     const QuicConnectionIdData* aternative_connection_id_data =
126         peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
127     ASSERT_THAT(aternative_connection_id_data, testing::NotNull());
128     EXPECT_EQ(aternative_connection_id_data->connection_id,
129               TestConnectionId(1));
130     EXPECT_EQ(aternative_connection_id_data->stateless_reset_token,
131               frame.stateless_reset_token);
132 
133     // Connection migration succeed. Prepares to retire CID #0.
134     peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
135         {TestConnectionId(1)});
136     cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(1));
137     ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
138     alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
139     EXPECT_THAT(cid_manager_visitor_
140                     .most_recent_retired_connection_id_sequence_numbers(),
141                 ElementsAre(0u));
142   }
143 
144   {
145     // Receives CID #2 from peer since CID #0 is retired.
146     QuicNewConnectionIdFrame frame;
147     frame.connection_id = TestConnectionId(2);
148     frame.sequence_number = 2u;
149     frame.retire_prior_to = 1u;
150     frame.stateless_reset_token =
151         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
152     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
153                     frame, &error_details_, &duplicate_frame_),
154                 IsQuicNoError());
155     // Start to use CID #2 for alternative path.
156     peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
157     // Connection migration succeed. Prepares to retire CID #1.
158     peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
159         {TestConnectionId(2)});
160     cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(2));
161     ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
162     alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
163     EXPECT_THAT(cid_manager_visitor_
164                     .most_recent_retired_connection_id_sequence_numbers(),
165                 ElementsAre(1u));
166   }
167 
168   {
169     // Receives CID #3 from peer since CID #1 is retired.
170     QuicNewConnectionIdFrame frame;
171     frame.connection_id = TestConnectionId(3);
172     frame.sequence_number = 3u;
173     frame.retire_prior_to = 2u;
174     frame.stateless_reset_token =
175         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
176     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
177                     frame, &error_details_, &duplicate_frame_),
178                 IsQuicNoError());
179     // Start to use CID #3 for alternative path.
180     peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
181     // Connection migration succeed. Prepares to retire CID #2.
182     peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
183         {TestConnectionId(3)});
184     cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(3));
185     ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
186     alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
187     EXPECT_THAT(cid_manager_visitor_
188                     .most_recent_retired_connection_id_sequence_numbers(),
189                 ElementsAre(2u));
190   }
191 
192   {
193     // Receives CID #4 from peer since CID #2 is retired.
194     QuicNewConnectionIdFrame frame;
195     frame.connection_id = TestConnectionId(4);
196     frame.sequence_number = 4u;
197     frame.retire_prior_to = 3u;
198     frame.stateless_reset_token =
199         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
200     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
201                     frame, &error_details_, &duplicate_frame_),
202                 IsQuicNoError());
203   }
204 }
205 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ConnectionIdSequenceWhenMigrationFail)206 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
207        ConnectionIdSequenceWhenMigrationFail) {
208   {
209     // Receives CID #1 from peer.
210     QuicNewConnectionIdFrame frame;
211     frame.connection_id = TestConnectionId(1);
212     frame.sequence_number = 1u;
213     frame.retire_prior_to = 0u;
214     frame.stateless_reset_token =
215         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
216     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
217                     frame, &error_details_, &duplicate_frame_),
218                 IsQuicNoError());
219     // Start to use CID #1 for alternative path.
220     peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
221     // Connection migration fails. Prepares to retire CID #1.
222     peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
223         {initial_connection_id_});
224     // Actually retires CID #1.
225     ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
226     alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
227     EXPECT_THAT(cid_manager_visitor_
228                     .most_recent_retired_connection_id_sequence_numbers(),
229                 ElementsAre(1u));
230   }
231 
232   {
233     // Receives CID #2 from peer since CID #1 is retired.
234     QuicNewConnectionIdFrame frame;
235     frame.connection_id = TestConnectionId(2);
236     frame.sequence_number = 2u;
237     frame.retire_prior_to = 0u;
238     frame.stateless_reset_token =
239         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
240     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
241                     frame, &error_details_, &duplicate_frame_),
242                 IsQuicNoError());
243     // Start to use CID #2 for alternative path.
244     peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
245     // Connection migration fails again. Prepares to retire CID #2.
246     peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
247         {initial_connection_id_});
248     // Actually retires CID #2.
249     ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
250     alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
251     EXPECT_THAT(cid_manager_visitor_
252                     .most_recent_retired_connection_id_sequence_numbers(),
253                 ElementsAre(2u));
254   }
255 
256   {
257     // Receives CID #3 from peer since CID #2 is retired.
258     QuicNewConnectionIdFrame frame;
259     frame.connection_id = TestConnectionId(3);
260     frame.sequence_number = 3u;
261     frame.retire_prior_to = 0u;
262     frame.stateless_reset_token =
263         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
264     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
265                     frame, &error_details_, &duplicate_frame_),
266                 IsQuicNoError());
267     // Start to use CID #3 for alternative path.
268     peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
269     // Connection migration succeed. Prepares to retire CID #0.
270     peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
271         {TestConnectionId(3)});
272     // After CID #3 is default (i.e., when there is no pending frame to write
273     // associated with CID #0), #0 can actually be retired.
274     cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(3));
275     ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
276     alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
277     EXPECT_THAT(cid_manager_visitor_
278                     .most_recent_retired_connection_id_sequence_numbers(),
279                 ElementsAre(0u));
280   }
281 
282   {
283     // Receives CID #4 from peer since CID #0 is retired.
284     QuicNewConnectionIdFrame frame;
285     frame.connection_id = TestConnectionId(4);
286     frame.sequence_number = 4u;
287     frame.retire_prior_to = 3u;
288     frame.stateless_reset_token =
289         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
290     EXPECT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
291                     frame, &error_details_, &duplicate_frame_),
292                 IsQuicNoError());
293     EXPECT_FALSE(retire_peer_issued_cid_alarm_->IsSet());
294   }
295 }
296 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ReceivesNewConnectionIdOutOfOrder)297 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
298        ReceivesNewConnectionIdOutOfOrder) {
299   {
300     // Receives new CID #1 that retires prior to #0.
301     // Outcome: (active: #0 unused: #1)
302     QuicNewConnectionIdFrame frame;
303     frame.connection_id = TestConnectionId(1);
304     frame.sequence_number = 1u;
305     frame.retire_prior_to = 0u;
306     frame.stateless_reset_token =
307         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
308     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
309                     frame, &error_details_, &duplicate_frame_),
310                 IsQuicNoError());
311     // Start to use CID #1 for alternative path.
312     // Outcome: (active: #0 #1 unused: None)
313     peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
314   }
315 
316   {
317     // Receives new CID #3 that retires prior to #2.
318     // Outcome: (active: None unused: #3)
319     QuicNewConnectionIdFrame frame;
320     frame.connection_id = TestConnectionId(3);
321     frame.sequence_number = 3u;
322     frame.retire_prior_to = 2u;
323     frame.stateless_reset_token =
324         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
325     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
326                     frame, &error_details_, &duplicate_frame_),
327                 IsQuicNoError());
328   }
329 
330   {
331     // Receives new CID #2 that retires prior to #1.
332     // Outcome: (active: None unused: #3, #2)
333     QuicNewConnectionIdFrame frame;
334     frame.connection_id = TestConnectionId(2);
335     frame.sequence_number = 2u;
336     frame.retire_prior_to = 1u;
337     frame.stateless_reset_token =
338         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
339     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
340                     frame, &error_details_, &duplicate_frame_),
341                 IsQuicNoError());
342   }
343 
344   {
345     EXPECT_FALSE(
346         peer_issued_cid_manager_.IsConnectionIdActive(TestConnectionId(0)));
347     EXPECT_FALSE(
348         peer_issued_cid_manager_.IsConnectionIdActive(TestConnectionId(1)));
349     // When there is no frame associated with #0 and #1 to write, replace the
350     // in-use CID with an unused CID (#2) and retires #0 & #1.
351     ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
352     alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
353     EXPECT_THAT(cid_manager_visitor_
354                     .most_recent_retired_connection_id_sequence_numbers(),
355                 ElementsAre(0u, 1u));
356     EXPECT_EQ(cid_manager_visitor_.GetCurrentPeerConnectionId(),
357               TestConnectionId(2));
358     // Get another unused CID for path validation.
359     EXPECT_EQ(
360         peer_issued_cid_manager_.ConsumeOneUnusedConnectionId()->connection_id,
361         TestConnectionId(3));
362   }
363 }
364 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,VisitedNewConnectionIdFrameIsIgnored)365 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
366        VisitedNewConnectionIdFrameIsIgnored) {
367   // Receives new CID #1 that retires prior to #0.
368   // Outcome: (active: #0 unused: #1)
369   QuicNewConnectionIdFrame frame;
370   frame.connection_id = TestConnectionId(1);
371   frame.sequence_number = 1u;
372   frame.retire_prior_to = 0u;
373   frame.stateless_reset_token =
374       QuicUtils::GenerateStatelessResetToken(frame.connection_id);
375   ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
376                   frame, &error_details_, &duplicate_frame_),
377               IsQuicNoError());
378   // Start to use CID #1 for alternative path.
379   // Outcome: (active: #0 #1 unused: None)
380   peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
381   // Prepare to retire CID #1 as path validation fails.
382   peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
383       {initial_connection_id_});
384   // Actually retires CID #1.
385   ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
386   alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
387   EXPECT_THAT(
388       cid_manager_visitor_.most_recent_retired_connection_id_sequence_numbers(),
389       ElementsAre(1u));
390   // Receives the same frame again. Should be a no-op.
391   ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
392                   frame, &error_details_, &duplicate_frame_),
393               IsQuicNoError());
394   EXPECT_EQ(true, duplicate_frame_);
395   EXPECT_THAT(peer_issued_cid_manager_.ConsumeOneUnusedConnectionId(),
396               testing::IsNull());
397 }
398 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ErrorWhenActiveConnectionIdLimitExceeded)399 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
400        ErrorWhenActiveConnectionIdLimitExceeded) {
401   {
402     // Receives new CID #1 that retires prior to #0.
403     // Outcome: (active: #0 unused: #1)
404     QuicNewConnectionIdFrame frame;
405     frame.connection_id = TestConnectionId(1);
406     frame.sequence_number = 1u;
407     frame.retire_prior_to = 0u;
408     frame.stateless_reset_token =
409         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
410     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
411                     frame, &error_details_, &duplicate_frame_),
412                 IsQuicNoError());
413   }
414 
415   {
416     QuicNewConnectionIdFrame frame;
417     frame.connection_id = TestConnectionId(2);
418     frame.sequence_number = 2u;
419     frame.retire_prior_to = 0u;
420     frame.stateless_reset_token =
421         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
422     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
423                     frame, &error_details_, &duplicate_frame_),
424                 IsError(QUIC_CONNECTION_ID_LIMIT_ERROR));
425   }
426 }
427 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ErrorWhenTheSameConnectionIdIsSeenWithDifferentSequenceNumbers)428 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
429        ErrorWhenTheSameConnectionIdIsSeenWithDifferentSequenceNumbers) {
430   {
431     QuicNewConnectionIdFrame frame;
432     frame.connection_id = TestConnectionId(1);
433     frame.sequence_number = 1u;
434     frame.retire_prior_to = 0u;
435     frame.stateless_reset_token =
436         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
437     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
438                     frame, &error_details_, &duplicate_frame_),
439                 IsQuicNoError());
440   }
441 
442   {
443     QuicNewConnectionIdFrame frame;
444     frame.connection_id = TestConnectionId(1);
445     frame.sequence_number = 2u;
446     frame.retire_prior_to = 1u;
447     frame.stateless_reset_token =
448         QuicUtils::GenerateStatelessResetToken(TestConnectionId(2));
449     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
450                     frame, &error_details_, &duplicate_frame_),
451                 IsError(IETF_QUIC_PROTOCOL_VIOLATION));
452   }
453 }
454 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,NewConnectionIdFrameWithTheSameSequenceNumberIsIgnored)455 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
456        NewConnectionIdFrameWithTheSameSequenceNumberIsIgnored) {
457   {
458     QuicNewConnectionIdFrame frame;
459     frame.connection_id = TestConnectionId(1);
460     frame.sequence_number = 1u;
461     frame.retire_prior_to = 0u;
462     frame.stateless_reset_token =
463         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
464     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
465                     frame, &error_details_, &duplicate_frame_),
466                 IsQuicNoError());
467   }
468 
469   {
470     QuicNewConnectionIdFrame frame;
471     frame.connection_id = TestConnectionId(2);
472     frame.sequence_number = 1u;
473     frame.retire_prior_to = 0u;
474     frame.stateless_reset_token =
475         QuicUtils::GenerateStatelessResetToken(TestConnectionId(2));
476     EXPECT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
477                     frame, &error_details_, &duplicate_frame_),
478                 IsQuicNoError());
479     EXPECT_EQ(true, duplicate_frame_);
480     EXPECT_EQ(
481         peer_issued_cid_manager_.ConsumeOneUnusedConnectionId()->connection_id,
482         TestConnectionId(1));
483     EXPECT_THAT(peer_issued_cid_manager_.ConsumeOneUnusedConnectionId(),
484                 IsNull());
485   }
486 }
487 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ErrorWhenThereAreTooManyGapsInIssuedConnectionIdSequenceNumbers)488 TEST_F(QuicPeerIssuedConnectionIdManagerTest,
489        ErrorWhenThereAreTooManyGapsInIssuedConnectionIdSequenceNumbers) {
490   // Add 20 intervals: [0, 1), [2, 3), ..., [38,39)
491   for (int i = 2; i <= 38; i += 2) {
492     QuicNewConnectionIdFrame frame;
493     frame.connection_id = TestConnectionId(i);
494     frame.sequence_number = i;
495     frame.retire_prior_to = i;
496     frame.stateless_reset_token =
497         QuicUtils::GenerateStatelessResetToken(frame.connection_id);
498     ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
499                     frame, &error_details_, &duplicate_frame_),
500                 IsQuicNoError());
501   }
502 
503   // Interval [40, 41) goes over the limit.
504   QuicNewConnectionIdFrame frame;
505   frame.connection_id = TestConnectionId(40);
506   frame.sequence_number = 40u;
507   frame.retire_prior_to = 40u;
508   frame.stateless_reset_token =
509       QuicUtils::GenerateStatelessResetToken(frame.connection_id);
510   ASSERT_THAT(peer_issued_cid_manager_.OnNewConnectionIdFrame(
511                   frame, &error_details_, &duplicate_frame_),
512               IsError(IETF_QUIC_PROTOCOL_VIOLATION));
513 }
514 
TEST_F(QuicPeerIssuedConnectionIdManagerTest,ReplaceConnectionId)515 TEST_F(QuicPeerIssuedConnectionIdManagerTest, ReplaceConnectionId) {
516   ASSERT_TRUE(
517       peer_issued_cid_manager_.IsConnectionIdActive(initial_connection_id_));
518   peer_issued_cid_manager_.ReplaceConnectionId(initial_connection_id_,
519                                                TestConnectionId(1));
520   EXPECT_FALSE(
521       peer_issued_cid_manager_.IsConnectionIdActive(initial_connection_id_));
522   EXPECT_TRUE(
523       peer_issued_cid_manager_.IsConnectionIdActive(TestConnectionId(1)));
524 }
525 
526 class TestSelfIssuedConnectionIdManagerVisitor
527     : public QuicConnectionIdManagerVisitorInterface {
528  public:
OnPeerIssuedConnectionIdRetired()529   void OnPeerIssuedConnectionIdRetired() override {}
530 
531   MOCK_METHOD(bool, SendNewConnectionId,
532               (const QuicNewConnectionIdFrame& frame), (override));
533   MOCK_METHOD(bool, MaybeReserveConnectionId,
534               (const QuicConnectionId& connection_id), (override));
535   MOCK_METHOD(void, OnSelfIssuedConnectionIdRetired,
536               (const QuicConnectionId& connection_id), (override));
537 };
538 
539 class QuicSelfIssuedConnectionIdManagerTest : public QuicTest {
540  public:
QuicSelfIssuedConnectionIdManagerTest()541   QuicSelfIssuedConnectionIdManagerTest()
542       : cid_manager_(/*active_connection_id_limit*/ 2, initial_connection_id_,
543                      &clock_, &alarm_factory_, &cid_manager_visitor_,
544                      /*context=*/nullptr, connection_id_generator_) {
545     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
546     retire_self_issued_cid_alarm_ =
547         QuicConnectionIdManagerPeer::GetRetireSelfIssuedConnectionIdAlarm(
548             &cid_manager_);
549   }
550 
551  protected:
552   // Verify that a call to GenerateNewConnectionId() does the right thing.
CheckGenerate(QuicConnectionId old_cid)553   QuicConnectionId CheckGenerate(QuicConnectionId old_cid) {
554     QuicConnectionId new_cid = old_cid;
555     (*new_cid.mutable_data())++;
556     // Ready for the actual call.
557     EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(old_cid))
558         .WillOnce(Return(new_cid));
559     return new_cid;
560   }
561 
562   MockClock clock_;
563   test::MockAlarmFactory alarm_factory_;
564   TestSelfIssuedConnectionIdManagerVisitor cid_manager_visitor_;
565   QuicConnectionId initial_connection_id_ = TestConnectionId(0);
566   StrictMock<QuicSelfIssuedConnectionIdManager> cid_manager_;
567   QuicAlarm* retire_self_issued_cid_alarm_ = nullptr;
568   std::string error_details_;
569   QuicTime::Delta pto_delay_ = QuicTime::Delta::FromMilliseconds(10);
570   MockConnectionIdGenerator connection_id_generator_;
571 };
572 
573 MATCHER_P3(ExpectedNewConnectionIdFrame, connection_id, sequence_number,
574            retire_prior_to, "") {
575   return (arg.connection_id == connection_id) &&
576          (arg.sequence_number == sequence_number) &&
577          (arg.retire_prior_to == retire_prior_to);
578 }
579 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,RetireSelfIssuedConnectionIdInOrder)580 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
581        RetireSelfIssuedConnectionIdInOrder) {
582   QuicConnectionId cid0 = initial_connection_id_;
583   QuicConnectionId cid1 = CheckGenerate(cid0);
584   QuicConnectionId cid2 = CheckGenerate(cid1);
585   QuicConnectionId cid3 = CheckGenerate(cid2);
586   QuicConnectionId cid4 = CheckGenerate(cid3);
587   QuicConnectionId cid5 = CheckGenerate(cid4);
588 
589   // Sends CID #1 to peer.
590   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
591       .WillOnce(Return(true));
592   EXPECT_CALL(cid_manager_visitor_,
593               SendNewConnectionId(ExpectedNewConnectionIdFrame(cid1, 1u, 0u)))
594       .WillOnce(Return(true));
595   cid_manager_.MaybeSendNewConnectionIds();
596 
597   {
598     // Peer retires CID #0;
599     // Sends CID #2 and asks peer to retire CIDs prior to #1.
600     // Outcome: (#1, #2) are active.
601     EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
602         .WillOnce(Return(true));
603     EXPECT_CALL(cid_manager_visitor_,
604                 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid2, 2u, 1u)))
605         .WillOnce(Return(true));
606     QuicRetireConnectionIdFrame retire_cid_frame;
607     retire_cid_frame.sequence_number = 0u;
608     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
609                     retire_cid_frame, pto_delay_, &error_details_),
610                 IsQuicNoError());
611   }
612 
613   {
614     // Peer retires CID #1;
615     // Sends CID #3 and asks peer to retire CIDs prior to #2.
616     // Outcome: (#2, #3) are active.
617     EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid3))
618         .WillOnce(Return(true));
619     EXPECT_CALL(cid_manager_visitor_,
620                 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid3, 3u, 2u)))
621         .WillOnce(Return(true));
622     QuicRetireConnectionIdFrame retire_cid_frame;
623     retire_cid_frame.sequence_number = 1u;
624     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
625                     retire_cid_frame, pto_delay_, &error_details_),
626                 IsQuicNoError());
627   }
628 
629   {
630     // Peer retires CID #2;
631     // Sends CID #4 and asks peer to retire CIDs prior to #3.
632     // Outcome: (#3, #4) are active.
633     EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid4))
634         .WillOnce(Return(true));
635     EXPECT_CALL(cid_manager_visitor_,
636                 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid4, 4u, 3u)))
637         .WillOnce(Return(true));
638     QuicRetireConnectionIdFrame retire_cid_frame;
639     retire_cid_frame.sequence_number = 2u;
640     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
641                     retire_cid_frame, pto_delay_, &error_details_),
642                 IsQuicNoError());
643   }
644 
645   {
646     // Peer retires CID #3;
647     // Sends CID #5 and asks peer to retire CIDs prior to #4.
648     // Outcome: (#4, #5) are active.
649     EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid5))
650         .WillOnce(Return(true));
651     EXPECT_CALL(cid_manager_visitor_,
652                 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid5, 5u, 4u)))
653         .WillOnce(Return(true));
654     QuicRetireConnectionIdFrame retire_cid_frame;
655     retire_cid_frame.sequence_number = 3u;
656     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
657                     retire_cid_frame, pto_delay_, &error_details_),
658                 IsQuicNoError());
659   }
660 }
661 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,RetireSelfIssuedConnectionIdOutOfOrder)662 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
663        RetireSelfIssuedConnectionIdOutOfOrder) {
664   QuicConnectionId cid0 = initial_connection_id_;
665   QuicConnectionId cid1 = CheckGenerate(cid0);
666   QuicConnectionId cid2 = CheckGenerate(cid1);
667   QuicConnectionId cid3 = CheckGenerate(cid2);
668   QuicConnectionId cid4 = CheckGenerate(cid3);
669 
670   // Sends CID #1 to peer.
671   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
672       .WillOnce(Return(true));
673   EXPECT_CALL(cid_manager_visitor_,
674               SendNewConnectionId(ExpectedNewConnectionIdFrame(cid1, 1u, 0u)))
675       .WillOnce(Return(true));
676   cid_manager_.MaybeSendNewConnectionIds();
677 
678   {
679     // Peer retires CID #1;
680     // Sends CID #2 and asks peer to retire CIDs prior to #0.
681     // Outcome: (#0, #2) are active.
682     EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
683         .WillOnce(Return(true));
684     EXPECT_CALL(cid_manager_visitor_,
685                 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid2, 2u, 0u)))
686         .WillOnce(Return(true));
687     QuicRetireConnectionIdFrame retire_cid_frame;
688     retire_cid_frame.sequence_number = 1u;
689     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
690                     retire_cid_frame, pto_delay_, &error_details_),
691                 IsQuicNoError());
692   }
693 
694   {
695     // Peer retires CID #1 again. This is a no-op.
696     QuicRetireConnectionIdFrame retire_cid_frame;
697     retire_cid_frame.sequence_number = 1u;
698     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
699                     retire_cid_frame, pto_delay_, &error_details_),
700                 IsQuicNoError());
701   }
702 
703   {
704     // Peer retires CID #0;
705     // Sends CID #3 and asks peer to retire CIDs prior to #2.
706     // Outcome: (#2, #3) are active.
707     EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid3))
708         .WillOnce(Return(true));
709     EXPECT_CALL(cid_manager_visitor_,
710                 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid3, 3u, 2u)))
711         .WillOnce(Return(true));
712     QuicRetireConnectionIdFrame retire_cid_frame;
713     retire_cid_frame.sequence_number = 0u;
714     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
715                     retire_cid_frame, pto_delay_, &error_details_),
716                 IsQuicNoError());
717   }
718 
719   {
720     // Peer retires CID #3;
721     // Sends CID #4 and asks peer to retire CIDs prior to #2.
722     // Outcome: (#2, #4) are active.
723     EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid4))
724         .WillOnce(Return(true));
725     EXPECT_CALL(cid_manager_visitor_,
726                 SendNewConnectionId(ExpectedNewConnectionIdFrame(cid4, 4u, 2u)))
727         .WillOnce(Return(true));
728     QuicRetireConnectionIdFrame retire_cid_frame;
729     retire_cid_frame.sequence_number = 3u;
730     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
731                     retire_cid_frame, pto_delay_, &error_details_),
732                 IsQuicNoError());
733   }
734 
735   {
736     // Peer retires CID #0 again. This is a no-op.
737     QuicRetireConnectionIdFrame retire_cid_frame;
738     retire_cid_frame.sequence_number = 0u;
739     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
740                     retire_cid_frame, pto_delay_, &error_details_),
741                 IsQuicNoError());
742   }
743 }
744 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ScheduleConnectionIdRetirementOneAtATime)745 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
746        ScheduleConnectionIdRetirementOneAtATime) {
747   QuicConnectionId cid0 = initial_connection_id_;
748   QuicConnectionId cid1 = CheckGenerate(cid0);
749   QuicConnectionId cid2 = CheckGenerate(cid1);
750   QuicConnectionId cid3 = CheckGenerate(cid2);
751   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
752       .Times(3)
753       .WillRepeatedly(Return(true));
754   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
755       .Times(3)
756       .WillRepeatedly(Return(true));
757   QuicTime::Delta connection_id_expire_timeout = 3 * pto_delay_;
758   QuicRetireConnectionIdFrame retire_cid_frame;
759 
760   // CID #1 is sent to peer.
761   cid_manager_.MaybeSendNewConnectionIds();
762 
763   // CID #0's retirement is scheduled and CID #2 is sent to peer.
764   retire_cid_frame.sequence_number = 0u;
765   ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
766                   retire_cid_frame, pto_delay_, &error_details_),
767               IsQuicNoError());
768   // While CID #0's retirement is scheduled, it is not retired yet.
769   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
770               ElementsAre(cid0, cid1, cid2));
771   EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
772   EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
773             clock_.ApproximateNow() + connection_id_expire_timeout);
774 
775   // CID #0 is actually retired.
776   EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid0));
777   clock_.AdvanceTime(connection_id_expire_timeout);
778   alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
779   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
780               ElementsAre(cid1, cid2));
781   EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
782 
783   // CID #1's retirement is scheduled and CID #3 is sent to peer.
784   retire_cid_frame.sequence_number = 1u;
785   ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
786                   retire_cid_frame, pto_delay_, &error_details_),
787               IsQuicNoError());
788   // While CID #1's retirement is scheduled, it is not retired yet.
789   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
790               ElementsAre(cid1, cid2, cid3));
791   EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
792   EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
793             clock_.ApproximateNow() + connection_id_expire_timeout);
794 
795   // CID #1 is actually retired.
796   EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid1));
797   clock_.AdvanceTime(connection_id_expire_timeout);
798   alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
799   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
800               ElementsAre(cid2, cid3));
801   EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
802 }
803 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ScheduleMultipleConnectionIdRetirement)804 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
805        ScheduleMultipleConnectionIdRetirement) {
806   QuicConnectionId cid0 = initial_connection_id_;
807   QuicConnectionId cid1 = CheckGenerate(cid0);
808   QuicConnectionId cid2 = CheckGenerate(cid1);
809   QuicConnectionId cid3 = CheckGenerate(cid2);
810   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
811       .Times(3)
812       .WillRepeatedly(Return(true));
813   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
814       .Times(3)
815       .WillRepeatedly(Return(true));
816   QuicTime::Delta connection_id_expire_timeout = 3 * pto_delay_;
817   QuicRetireConnectionIdFrame retire_cid_frame;
818 
819   // CID #1 is sent to peer.
820   cid_manager_.MaybeSendNewConnectionIds();
821 
822   // CID #0's retirement is scheduled and CID #2 is sent to peer.
823   retire_cid_frame.sequence_number = 0u;
824   ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
825                   retire_cid_frame, pto_delay_, &error_details_),
826               IsQuicNoError());
827 
828   clock_.AdvanceTime(connection_id_expire_timeout * 0.25);
829 
830   // CID #1's retirement is scheduled and CID #3 is sent to peer.
831   retire_cid_frame.sequence_number = 1u;
832   ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
833                   retire_cid_frame, pto_delay_, &error_details_),
834               IsQuicNoError());
835 
836   // While CID #0, #1s retirement is scheduled, they are not retired yet.
837   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
838               ElementsAre(cid0, cid1, cid2, cid3));
839   EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
840   EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
841             clock_.ApproximateNow() + connection_id_expire_timeout * 0.75);
842 
843   // CID #0 is actually retired.
844   EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid0));
845   clock_.AdvanceTime(connection_id_expire_timeout * 0.75);
846   alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
847   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
848               ElementsAre(cid1, cid2, cid3));
849   EXPECT_TRUE(retire_self_issued_cid_alarm_->IsSet());
850   EXPECT_EQ(retire_self_issued_cid_alarm_->deadline(),
851             clock_.ApproximateNow() + connection_id_expire_timeout * 0.25);
852 
853   // CID #1 is actually retired.
854   EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid1));
855   clock_.AdvanceTime(connection_id_expire_timeout * 0.25);
856   alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
857   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
858               ElementsAre(cid2, cid3));
859   EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
860 }
861 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,AllExpiredConnectionIdsAreRetiredInOneBatch)862 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
863        AllExpiredConnectionIdsAreRetiredInOneBatch) {
864   QuicConnectionId cid0 = initial_connection_id_;
865   QuicConnectionId cid1 = CheckGenerate(cid0);
866   QuicConnectionId cid2 = CheckGenerate(cid1);
867   QuicConnectionId cid3 = CheckGenerate(cid2);
868   QuicConnectionId cid;
869   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
870       .Times(3)
871       .WillRepeatedly(Return(true));
872   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
873       .Times(3)
874       .WillRepeatedly(Return(true));
875   QuicTime::Delta connection_id_expire_timeout = 3 * pto_delay_;
876   QuicRetireConnectionIdFrame retire_cid_frame;
877   EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid0));
878   EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
879   EXPECT_FALSE(cid_manager_.ConsumeOneConnectionId().has_value());
880 
881   // CID #1 is sent to peer.
882   cid_manager_.MaybeSendNewConnectionIds();
883   EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid1));
884   EXPECT_TRUE(cid_manager_.HasConnectionIdToConsume());
885   cid = *cid_manager_.ConsumeOneConnectionId();
886   EXPECT_EQ(cid1, cid);
887   EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
888 
889   // CID #0's retirement is scheduled and CID #2 is sent to peer.
890   retire_cid_frame.sequence_number = 0u;
891   cid_manager_.OnRetireConnectionIdFrame(retire_cid_frame, pto_delay_,
892                                          &error_details_);
893   EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid0));
894   EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid1));
895   EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid2));
896   EXPECT_TRUE(cid_manager_.HasConnectionIdToConsume());
897   cid = *cid_manager_.ConsumeOneConnectionId();
898   EXPECT_EQ(cid2, cid);
899   EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
900 
901   clock_.AdvanceTime(connection_id_expire_timeout * 0.1);
902 
903   // CID #1's retirement is scheduled and CID #3 is sent to peer.
904   retire_cid_frame.sequence_number = 1u;
905   cid_manager_.OnRetireConnectionIdFrame(retire_cid_frame, pto_delay_,
906                                          &error_details_);
907 
908   {
909     // CID #0 & #1 are retired in a single alarm fire.
910     clock_.AdvanceTime(connection_id_expire_timeout);
911     testing::InSequence s;
912     EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid0));
913     EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid1));
914     alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
915     EXPECT_FALSE(cid_manager_.IsConnectionIdInUse(cid0));
916     EXPECT_FALSE(cid_manager_.IsConnectionIdInUse(cid1));
917     EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid2));
918     EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
919                 ElementsAre(cid2, cid3));
920     EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
921   }
922 }
923 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ErrorWhenRetireConnectionIdNeverIssued)924 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
925        ErrorWhenRetireConnectionIdNeverIssued) {
926   QuicConnectionId cid0 = initial_connection_id_;
927   QuicConnectionId cid1 = CheckGenerate(cid0);
928 
929   // CID #1 is sent to peer.
930   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
931       .WillOnce(Return(true));
932   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
933       .WillOnce(Return(true));
934   cid_manager_.MaybeSendNewConnectionIds();
935 
936   // CID #2 is never issued.
937   QuicRetireConnectionIdFrame retire_cid_frame;
938   retire_cid_frame.sequence_number = 2u;
939   ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
940                   retire_cid_frame, pto_delay_, &error_details_),
941               IsError(IETF_QUIC_PROTOCOL_VIOLATION));
942 }
943 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,ErrorWhenTooManyConnectionIdWaitingToBeRetired)944 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
945        ErrorWhenTooManyConnectionIdWaitingToBeRetired) {
946   // CID #0 & #1 are issued.
947   QuicConnectionId last_connection_id = CheckGenerate(initial_connection_id_);
948   EXPECT_CALL(cid_manager_visitor_,
949               MaybeReserveConnectionId(last_connection_id))
950       .WillOnce(Return(true));
951   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
952       .WillOnce(Return(true));
953   cid_manager_.MaybeSendNewConnectionIds();
954 
955   // Add 8 connection IDs to the to-be-retired list.
956 
957   for (int i = 0; i < 8; ++i) {
958     last_connection_id = CheckGenerate(last_connection_id);
959     EXPECT_CALL(cid_manager_visitor_,
960                 MaybeReserveConnectionId(last_connection_id))
961         .WillOnce(Return(true));
962     EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_));
963     QuicRetireConnectionIdFrame retire_cid_frame;
964     retire_cid_frame.sequence_number = i;
965     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
966                     retire_cid_frame, pto_delay_, &error_details_),
967                 IsQuicNoError());
968   }
969   QuicRetireConnectionIdFrame retire_cid_frame;
970   retire_cid_frame.sequence_number = 8u;
971   // This would have push the number of to-be-retired connection IDs over its
972   // limit.
973   ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
974                   retire_cid_frame, pto_delay_, &error_details_),
975               IsError(QUIC_TOO_MANY_CONNECTION_ID_WAITING_TO_RETIRE));
976 }
977 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,CannotIssueNewCidDueToVisitor)978 TEST_F(QuicSelfIssuedConnectionIdManagerTest, CannotIssueNewCidDueToVisitor) {
979   QuicConnectionId cid0 = initial_connection_id_;
980   QuicConnectionId cid1 = CheckGenerate(cid0);
981   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
982       .WillOnce(Return(false));
983   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_)).Times(0);
984   cid_manager_.MaybeSendNewConnectionIds();
985 }
986 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,CannotIssueNewCidUponRetireConnectionIdDueToVisitor)987 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
988        CannotIssueNewCidUponRetireConnectionIdDueToVisitor) {
989   QuicConnectionId cid0 = initial_connection_id_;
990   QuicConnectionId cid1 = CheckGenerate(cid0);
991   QuicConnectionId cid2 = CheckGenerate(cid1);
992   // CID #0 & #1 are issued.
993   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
994       .WillOnce(Return(true));
995   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
996       .WillOnce(Return(true));
997   cid_manager_.MaybeSendNewConnectionIds();
998 
999   // CID #2 is not issued.
1000   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
1001       .WillOnce(Return(false));
1002   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_)).Times(0);
1003   QuicRetireConnectionIdFrame retire_cid_frame;
1004   retire_cid_frame.sequence_number = 1;
1005   ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
1006                   retire_cid_frame, pto_delay_, &error_details_),
1007               IsQuicNoError());
1008 }
1009 
TEST_F(QuicSelfIssuedConnectionIdManagerTest,DoNotIssueConnectionIdVoluntarilyIfOneHasIssuedForPerferredAddress)1010 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
1011        DoNotIssueConnectionIdVoluntarilyIfOneHasIssuedForPerferredAddress) {
1012   QuicConnectionId cid0 = initial_connection_id_;
1013   QuicConnectionId cid1 = CheckGenerate(cid0);
1014   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
1015       .WillOnce(Return(true));
1016   std::optional<QuicNewConnectionIdFrame> new_cid_frame =
1017       cid_manager_.MaybeIssueNewConnectionIdForPreferredAddress();
1018   ASSERT_TRUE(new_cid_frame.has_value());
1019   ASSERT_THAT(*new_cid_frame, ExpectedNewConnectionIdFrame(cid1, 1u, 0u));
1020   EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
1021               ElementsAre(cid0, cid1));
1022 
1023   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_)).Times(0);
1024   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_)).Times(0);
1025   cid_manager_.MaybeSendNewConnectionIds();
1026 }
1027 
1028 // Regression test for b/258450534
TEST_F(QuicSelfIssuedConnectionIdManagerTest,RetireConnectionIdAfterConnectionIdCollisionIsFine)1029 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
1030        RetireConnectionIdAfterConnectionIdCollisionIsFine) {
1031   QuicConnectionId cid0 = initial_connection_id_;
1032   QuicConnectionId cid1 = CheckGenerate(cid0);
1033   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
1034       .WillOnce(Return(true));
1035   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
1036       .WillOnce(Return(true));
1037   cid_manager_.MaybeSendNewConnectionIds();
1038 
1039   QuicRetireConnectionIdFrame retire_cid_frame(/*control_frame_id=*/0,
1040                                                /*sequence_number=*/1);
1041   QuicConnectionId cid2 = CheckGenerate(cid1);
1042   // This happens when cid2 is aleady present in the dispatcher map.
1043   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid2))
1044       .WillOnce(Return(false));
1045   std::string error_details;
1046   EXPECT_EQ(
1047       cid_manager_.OnRetireConnectionIdFrame(
1048           retire_cid_frame, QuicTime::Delta::FromSeconds(1), &error_details),
1049       QUIC_NO_ERROR)
1050       << error_details;
1051 
1052   EXPECT_EQ(
1053       cid_manager_.OnRetireConnectionIdFrame(
1054           retire_cid_frame, QuicTime::Delta::FromSeconds(1), &error_details),
1055       QUIC_NO_ERROR)
1056       << error_details;
1057 }
1058 
1059 }  // namespace
1060 }  // namespace quic::test
1061