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.
5 #include "net/tools/quic/quic_time_wait_list_manager.h"
9 #include "net/quic/crypto/crypto_protocol.h"
10 #include "net/quic/crypto/null_encrypter.h"
11 #include "net/quic/crypto/quic_decrypter.h"
12 #include "net/quic/crypto/quic_encrypter.h"
13 #include "net/quic/quic_connection_helper.h"
14 #include "net/quic/quic_data_reader.h"
15 #include "net/quic/quic_flags.h"
16 #include "net/quic/quic_framer.h"
17 #include "net/quic/quic_packet_writer.h"
18 #include "net/quic/quic_protocol.h"
19 #include "net/quic/quic_utils.h"
20 #include "net/quic/test_tools/quic_test_utils.h"
21 #include "net/tools/quic/quic_epoll_connection_helper.h"
22 #include "net/tools/quic/test_tools/mock_epoll_server.h"
23 #include "net/tools/quic/test_tools/quic_test_utils.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using net::test::BuildUnsizedDataPacket
;
28 using net::test::NoOpFramerVisitor
;
29 using net::test::QuicVersionMax
;
30 using net::test::QuicVersionMin
;
31 using net::test::ValueRestore
;
33 using testing::Assign
;
35 using testing::Matcher
;
36 using testing::MatcherInterface
;
37 using testing::NiceMock
;
38 using testing::Return
;
39 using testing::ReturnPointee
;
40 using testing::SetArgPointee
;
41 using testing::StrictMock
;
49 class FramerVisitorCapturingPublicReset
: public NoOpFramerVisitor
{
51 FramerVisitorCapturingPublicReset() {}
52 ~FramerVisitorCapturingPublicReset() override
{}
54 void OnPublicResetPacket(const QuicPublicResetPacket
& public_reset
) override
{
55 public_reset_packet_
= public_reset
;
58 const QuicPublicResetPacket
public_reset_packet() {
59 return public_reset_packet_
;
63 QuicPublicResetPacket public_reset_packet_
;
66 class QuicTimeWaitListManagerPeer
{
68 static bool ShouldSendResponse(QuicTimeWaitListManager
* manager
,
69 int received_packet_count
) {
70 return manager
->ShouldSendResponse(received_packet_count
);
73 static QuicTime::Delta
time_wait_period(QuicTimeWaitListManager
* manager
) {
74 return manager
->time_wait_period_
;
77 static QuicVersion
GetQuicVersionFromConnectionId(
78 QuicTimeWaitListManager
* manager
,
79 QuicConnectionId connection_id
) {
80 return manager
->GetQuicVersionFromConnectionId(connection_id
);
86 class MockFakeTimeEpollServer
: public FakeTimeEpollServer
{
88 MOCK_METHOD2(RegisterAlarm
, void(int64 timeout_in_us
,
89 EpollAlarmCallbackInterface
* alarm
));
92 class QuicTimeWaitListManagerTest
: public ::testing::Test
{
94 QuicTimeWaitListManagerTest()
95 : helper_(&epoll_server_
),
96 time_wait_list_manager_(&writer_
,
99 QuicSupportedVersions()),
100 framer_(QuicSupportedVersions(),
102 Perspective::IS_SERVER
),
104 client_address_(net::test::TestPeerIPAddress(), kTestPort
),
105 writer_is_blocked_(false) {}
107 ~QuicTimeWaitListManagerTest() override
{}
109 void SetUp() override
{
110 EXPECT_CALL(writer_
, IsWriteBlocked())
111 .WillRepeatedly(ReturnPointee(&writer_is_blocked_
));
112 EXPECT_CALL(writer_
, IsWriteBlockedDataBuffered())
113 .WillRepeatedly(Return(false));
116 void AddConnectionId(QuicConnectionId connection_id
) {
117 AddConnectionId(connection_id
, QuicVersionMax(),
118 /*connection_rejected_statelessly=*/false, nullptr);
121 void AddStatelessConnectionId(QuicConnectionId connection_id
) {
122 time_wait_list_manager_
.AddConnectionIdToTimeWait(
123 connection_id
, QuicVersionMax(),
124 /*connection_rejected_statelessly=*/true, nullptr);
127 void AddConnectionId(QuicConnectionId connection_id
,
129 bool connection_rejected_statelessly
,
130 QuicEncryptedPacket
* packet
) {
131 time_wait_list_manager_
.AddConnectionIdToTimeWait(
132 connection_id
, version
, connection_rejected_statelessly
, packet
);
135 bool IsConnectionIdInTimeWait(QuicConnectionId connection_id
) {
136 return time_wait_list_manager_
.IsConnectionIdInTimeWait(connection_id
);
139 void ProcessPacket(QuicConnectionId connection_id
,
140 QuicPacketSequenceNumber sequence_number
) {
141 QuicEncryptedPacket
packet(nullptr, 0);
142 time_wait_list_manager_
.ProcessPacket(server_address_
,
149 QuicEncryptedPacket
* ConstructEncryptedPacket(
150 EncryptionLevel level
,
151 QuicConnectionId connection_id
,
152 QuicPacketSequenceNumber sequence_number
) {
153 QuicPacketHeader header
;
154 header
.public_header
.connection_id
= connection_id
;
155 header
.public_header
.connection_id_length
= PACKET_8BYTE_CONNECTION_ID
;
156 header
.public_header
.version_flag
= false;
157 header
.public_header
.reset_flag
= false;
158 header
.public_header
.sequence_number_length
= PACKET_6BYTE_SEQUENCE_NUMBER
;
159 header
.packet_sequence_number
= sequence_number
;
160 header
.entropy_flag
= false;
161 header
.entropy_hash
= 0;
162 header
.fec_flag
= false;
163 header
.is_in_fec_group
= NOT_IN_FEC_GROUP
;
164 header
.fec_group
= 0;
165 QuicStreamFrame
stream_frame(1, false, 0, StringPiece("data"));
166 QuicFrame
frame(&stream_frame
);
168 frames
.push_back(frame
);
169 scoped_ptr
<QuicPacket
> packet(
170 BuildUnsizedDataPacket(&framer_
, header
, frames
));
171 EXPECT_TRUE(packet
!= nullptr);
172 char buffer
[kMaxPacketSize
];
173 scoped_ptr
<QuicEncryptedPacket
> encrypted(framer_
.EncryptPacket(
174 ENCRYPTION_NONE
, sequence_number
, *packet
, buffer
, kMaxPacketSize
));
175 EXPECT_TRUE(encrypted
!= nullptr);
176 return encrypted
->Clone();
179 NiceMock
<MockFakeTimeEpollServer
> epoll_server_
;
180 QuicEpollConnectionHelper helper_
;
181 StrictMock
<MockPacketWriter
> writer_
;
182 StrictMock
<MockQuicServerSessionVisitor
> visitor_
;
183 QuicTimeWaitListManager time_wait_list_manager_
;
185 QuicConnectionId connection_id_
;
186 IPEndPoint server_address_
;
187 IPEndPoint client_address_
;
188 bool writer_is_blocked_
;
191 class ValidatePublicResetPacketPredicate
192 : public MatcherInterface
<const std::tr1::tuple
<const char*, int> > {
194 explicit ValidatePublicResetPacketPredicate(QuicConnectionId connection_id
,
195 QuicPacketSequenceNumber number
)
196 : connection_id_(connection_id
), sequence_number_(number
) {
199 bool MatchAndExplain(
200 const std::tr1::tuple
<const char*, int> packet_buffer
,
201 testing::MatchResultListener
* /* listener */) const override
{
202 FramerVisitorCapturingPublicReset visitor
;
203 QuicFramer
framer(QuicSupportedVersions(), QuicTime::Zero(),
204 Perspective::IS_CLIENT
);
205 framer
.set_visitor(&visitor
);
206 QuicEncryptedPacket
encrypted(std::tr1::get
<0>(packet_buffer
),
207 std::tr1::get
<1>(packet_buffer
));
208 framer
.ProcessPacket(encrypted
);
209 QuicPublicResetPacket packet
= visitor
.public_reset_packet();
210 return connection_id_
== packet
.public_header
.connection_id
&&
211 packet
.public_header
.reset_flag
&& !packet
.public_header
.version_flag
&&
212 sequence_number_
== packet
.rejected_sequence_number
&&
213 net::test::TestPeerIPAddress() == packet
.client_address
.address() &&
214 kTestPort
== packet
.client_address
.port();
217 void DescribeTo(::std::ostream
* os
) const override
{}
219 void DescribeNegationTo(::std::ostream
* os
) const override
{}
222 QuicConnectionId connection_id_
;
223 QuicPacketSequenceNumber sequence_number_
;
227 Matcher
<const std::tr1::tuple
<const char*, int> > PublicResetPacketEq(
228 QuicConnectionId connection_id
,
229 QuicPacketSequenceNumber sequence_number
) {
230 return MakeMatcher(new ValidatePublicResetPacketPredicate(connection_id
,
234 TEST_F(QuicTimeWaitListManagerTest
, CheckConnectionIdInTimeWait
) {
235 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_
));
236 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id_
));
237 AddConnectionId(connection_id_
);
238 EXPECT_EQ(1u, time_wait_list_manager_
.num_connections());
239 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_
));
242 TEST_F(QuicTimeWaitListManagerTest
, CheckStatelessConnectionIdInTimeWait
) {
243 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_
));
244 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id_
));
245 AddStatelessConnectionId(connection_id_
);
246 EXPECT_EQ(1u, time_wait_list_manager_
.num_connections());
247 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_
));
250 TEST_F(QuicTimeWaitListManagerTest
, SendConnectionClose
) {
251 const size_t kConnectionCloseLength
= 100;
252 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id_
));
253 AddConnectionId(connection_id_
, QuicVersionMax(),
254 /*connection_rejected_statelessly=*/false,
255 new QuicEncryptedPacket(new char[kConnectionCloseLength
],
256 kConnectionCloseLength
, true));
257 const int kRandomSequenceNumber
= 1;
258 EXPECT_CALL(writer_
, WritePacket(_
, kConnectionCloseLength
,
259 server_address_
.address(),
261 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 1)));
263 ProcessPacket(connection_id_
, kRandomSequenceNumber
);
266 TEST_F(QuicTimeWaitListManagerTest
, SendPublicReset
) {
267 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id_
));
268 AddConnectionId(connection_id_
);
269 const int kRandomSequenceNumber
= 1;
270 EXPECT_CALL(writer_
, WritePacket(_
, _
,
271 server_address_
.address(),
273 .With(Args
<0, 1>(PublicResetPacketEq(connection_id_
,
274 kRandomSequenceNumber
)))
275 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 0)));
277 ProcessPacket(connection_id_
, kRandomSequenceNumber
);
280 TEST_F(QuicTimeWaitListManagerTest
, SendPublicResetWithExponentialBackOff
) {
281 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id_
));
282 AddConnectionId(connection_id_
);
283 EXPECT_EQ(1u, time_wait_list_manager_
.num_connections());
284 for (int sequence_number
= 1; sequence_number
< 101; ++sequence_number
) {
285 if ((sequence_number
& (sequence_number
- 1)) == 0) {
286 EXPECT_CALL(writer_
, WritePacket(_
, _
, _
, _
))
287 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 1)));
289 ProcessPacket(connection_id_
, sequence_number
);
290 // Send public reset with exponential back off.
291 if ((sequence_number
& (sequence_number
- 1)) == 0) {
292 EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
293 &time_wait_list_manager_
, sequence_number
));
295 EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
296 &time_wait_list_manager_
, sequence_number
));
301 TEST_F(QuicTimeWaitListManagerTest
, NoPublicResetForStatelessConnections
) {
302 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id_
));
303 AddStatelessConnectionId(connection_id_
);
304 const int kRandomSequenceNumber
= 1;
305 ProcessPacket(connection_id_
, kRandomSequenceNumber
);
308 TEST_F(QuicTimeWaitListManagerTest
, CleanUpOldConnectionIds
) {
309 const size_t kConnectionIdCount
= 100;
310 const size_t kOldConnectionIdCount
= 31;
312 // Add connection_ids such that their expiry time is time_wait_period_.
313 epoll_server_
.set_now_in_usec(0);
314 for (size_t connection_id
= 1; connection_id
<= kOldConnectionIdCount
;
316 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id
));
317 AddConnectionId(connection_id
);
319 EXPECT_EQ(kOldConnectionIdCount
, time_wait_list_manager_
.num_connections());
321 // Add remaining connection_ids such that their add time is
322 // 2 * time_wait_period_.
323 const QuicTime::Delta time_wait_period
=
324 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_
);
325 epoll_server_
.set_now_in_usec(time_wait_period
.ToMicroseconds());
326 for (size_t connection_id
= kOldConnectionIdCount
+ 1;
327 connection_id
<= kConnectionIdCount
; ++connection_id
) {
328 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id
));
329 AddConnectionId(connection_id
);
331 EXPECT_EQ(kConnectionIdCount
, time_wait_list_manager_
.num_connections());
333 QuicTime::Delta offset
= QuicTime::Delta::FromMicroseconds(39);
334 // Now set the current time as time_wait_period + offset usecs.
335 epoll_server_
.set_now_in_usec(time_wait_period
.Add(offset
).ToMicroseconds());
336 // After all the old connection_ids are cleaned up, check the next alarm
338 int64 next_alarm_time
= epoll_server_
.ApproximateNowInUsec() +
339 time_wait_period
.Subtract(offset
).ToMicroseconds();
340 EXPECT_CALL(epoll_server_
, RegisterAlarm(next_alarm_time
, _
));
342 for (size_t connection_id
= 1; connection_id
<= kConnectionIdCount
;
344 if (connection_id
<= kOldConnectionIdCount
) {
345 EXPECT_CALL(visitor_
, OnConnectionRemovedFromTimeWaitList(connection_id
));
348 time_wait_list_manager_
.CleanUpOldConnectionIds();
349 for (size_t connection_id
= 1; connection_id
<= kConnectionIdCount
;
351 EXPECT_EQ(connection_id
> kOldConnectionIdCount
,
352 IsConnectionIdInTimeWait(connection_id
))
353 << "kOldConnectionIdCount: " << kOldConnectionIdCount
354 << " connection_id: " << connection_id
;
356 EXPECT_EQ(kConnectionIdCount
- kOldConnectionIdCount
,
357 time_wait_list_manager_
.num_connections());
360 TEST_F(QuicTimeWaitListManagerTest
, SendQueuedPackets
) {
361 QuicConnectionId connection_id
= 1;
362 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id
));
363 AddConnectionId(connection_id
);
364 QuicPacketSequenceNumber sequence_number
= 234;
365 scoped_ptr
<QuicEncryptedPacket
> packet(ConstructEncryptedPacket(
366 ENCRYPTION_NONE
, connection_id
, sequence_number
));
367 // Let first write through.
368 EXPECT_CALL(writer_
, WritePacket(_
, _
,
369 server_address_
.address(),
371 .With(Args
<0, 1>(PublicResetPacketEq(connection_id
,
373 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, packet
->length())));
374 ProcessPacket(connection_id
, sequence_number
);
376 // write block for the next packet.
377 EXPECT_CALL(writer_
, WritePacket(_
, _
,
378 server_address_
.address(),
380 .With(Args
<0, 1>(PublicResetPacketEq(connection_id
,
383 Assign(&writer_is_blocked_
, true),
384 Return(WriteResult(WRITE_STATUS_BLOCKED
, EAGAIN
))));
385 EXPECT_CALL(visitor_
, OnWriteBlocked(&time_wait_list_manager_
));
386 ProcessPacket(connection_id
, sequence_number
);
387 // 3rd packet. No public reset should be sent;
388 ProcessPacket(connection_id
, sequence_number
);
390 // write packet should not be called since we are write blocked but the
392 QuicConnectionId other_connection_id
= 2;
393 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(other_connection_id
));
394 AddConnectionId(other_connection_id
);
395 QuicPacketSequenceNumber other_sequence_number
= 23423;
396 scoped_ptr
<QuicEncryptedPacket
> other_packet(
397 ConstructEncryptedPacket(
398 ENCRYPTION_NONE
, other_connection_id
, other_sequence_number
));
399 EXPECT_CALL(writer_
, WritePacket(_
, _
, _
, _
))
401 EXPECT_CALL(visitor_
, OnWriteBlocked(&time_wait_list_manager_
));
402 ProcessPacket(other_connection_id
, other_sequence_number
);
403 EXPECT_EQ(2u, time_wait_list_manager_
.num_connections());
405 // Now expect all the write blocked public reset packets to be sent again.
406 writer_is_blocked_
= false;
407 EXPECT_CALL(writer_
, WritePacket(_
, _
,
408 server_address_
.address(),
410 .With(Args
<0, 1>(PublicResetPacketEq(connection_id
,
412 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, packet
->length())));
413 EXPECT_CALL(writer_
, WritePacket(_
, _
,
414 server_address_
.address(),
416 .With(Args
<0, 1>(PublicResetPacketEq(other_connection_id
,
417 other_sequence_number
)))
418 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
,
419 other_packet
->length())));
420 time_wait_list_manager_
.OnCanWrite();
423 TEST_F(QuicTimeWaitListManagerTest
, GetQuicVersionFromMap
) {
424 const int kConnectionId1
= 123;
425 const int kConnectionId2
= 456;
426 const int kConnectionId3
= 789;
428 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(kConnectionId1
));
429 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(kConnectionId2
));
430 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(kConnectionId3
));
431 AddConnectionId(kConnectionId1
, QuicVersionMin(),
432 /*connection_rejected_statelessly=*/false, nullptr);
433 AddConnectionId(kConnectionId2
, QuicVersionMax(),
434 /*connection_rejected_statelessly=*/false, nullptr);
435 AddConnectionId(kConnectionId3
, QuicVersionMax(),
436 /*connection_rejected_statelessly=*/false, nullptr);
438 EXPECT_EQ(QuicVersionMin(),
439 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
440 &time_wait_list_manager_
, kConnectionId1
));
441 EXPECT_EQ(QuicVersionMax(),
442 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
443 &time_wait_list_manager_
, kConnectionId2
));
444 EXPECT_EQ(QuicVersionMax(),
445 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
446 &time_wait_list_manager_
, kConnectionId3
));
449 TEST_F(QuicTimeWaitListManagerTest
, AddConnectionIdTwice
) {
450 // Add connection_ids such that their expiry time is time_wait_period_.
451 epoll_server_
.set_now_in_usec(0);
452 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id_
));
453 AddConnectionId(connection_id_
);
454 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_
));
455 const size_t kConnectionCloseLength
= 100;
456 AddConnectionId(connection_id_
, QuicVersionMax(),
457 /*connection_rejected_statelessly=*/false,
458 new QuicEncryptedPacket(new char[kConnectionCloseLength
],
459 kConnectionCloseLength
, true));
460 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_
));
461 EXPECT_EQ(1u, time_wait_list_manager_
.num_connections());
463 EXPECT_CALL(writer_
, WritePacket(_
,
464 kConnectionCloseLength
,
465 server_address_
.address(),
467 .WillOnce(Return(WriteResult(WRITE_STATUS_OK
, 1)));
469 const int kRandomSequenceNumber
= 1;
470 ProcessPacket(connection_id_
, kRandomSequenceNumber
);
472 const QuicTime::Delta time_wait_period
=
473 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_
);
475 QuicTime::Delta offset
= QuicTime::Delta::FromMicroseconds(39);
476 // Now set the current time as time_wait_period + offset usecs.
477 epoll_server_
.set_now_in_usec(time_wait_period
.Add(offset
).ToMicroseconds());
478 // After the connection_ids are cleaned up, check the next alarm interval.
479 int64 next_alarm_time
= epoll_server_
.ApproximateNowInUsec() +
480 time_wait_period
.ToMicroseconds();
482 EXPECT_CALL(epoll_server_
, RegisterAlarm(next_alarm_time
, _
));
483 EXPECT_CALL(visitor_
, OnConnectionRemovedFromTimeWaitList(connection_id_
));
484 time_wait_list_manager_
.CleanUpOldConnectionIds();
485 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_
));
486 EXPECT_EQ(0u, time_wait_list_manager_
.num_connections());
489 TEST_F(QuicTimeWaitListManagerTest
, ConnectionIdsOrderedByTime
) {
490 // Simple randomization: the values of connection_ids are swapped based on the
491 // current seconds on the clock. If the container is broken, the test will be
493 int odd_second
= static_cast<int>(epoll_server_
.ApproximateNowInUsec()) % 2;
494 EXPECT_TRUE(odd_second
== 0 || odd_second
== 1);
495 const QuicConnectionId connection_id1
= odd_second
;
496 const QuicConnectionId connection_id2
= 1 - odd_second
;
498 // 1 will hash lower than 2, but we add it later. They should come out in the
499 // add order, not hash order.
500 epoll_server_
.set_now_in_usec(0);
501 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id1
));
502 AddConnectionId(connection_id1
);
503 epoll_server_
.set_now_in_usec(10);
504 EXPECT_CALL(visitor_
, OnConnectionAddedToTimeWaitList(connection_id2
));
505 AddConnectionId(connection_id2
);
506 EXPECT_EQ(2u, time_wait_list_manager_
.num_connections());
508 const QuicTime::Delta time_wait_period
=
509 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_
);
510 epoll_server_
.set_now_in_usec(time_wait_period
.ToMicroseconds() + 1);
512 EXPECT_CALL(epoll_server_
, RegisterAlarm(_
, _
));
514 EXPECT_CALL(visitor_
, OnConnectionRemovedFromTimeWaitList(connection_id1
));
515 time_wait_list_manager_
.CleanUpOldConnectionIds();
516 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id1
));
517 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id2
));
518 EXPECT_EQ(1u, time_wait_list_manager_
.num_connections());
521 TEST_F(QuicTimeWaitListManagerTest
, MaxConnectionsTest
) {
522 // Basically, shut off time-based eviction.
523 FLAGS_quic_time_wait_list_seconds
= 10000000000;
524 FLAGS_quic_time_wait_list_max_connections
= 5;
526 QuicConnectionId current_connection_id
= 0;
527 // Add exactly the maximum number of connections
528 for (int64 i
= 0; i
< FLAGS_quic_time_wait_list_max_connections
; ++i
) {
529 ++current_connection_id
;
530 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id
));
531 EXPECT_CALL(visitor_
,
532 OnConnectionAddedToTimeWaitList(current_connection_id
));
533 AddConnectionId(current_connection_id
);
534 EXPECT_EQ(current_connection_id
, time_wait_list_manager_
.num_connections());
535 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id
));
538 // Now keep adding. Since we're already at the max, every new connection-id
539 // will evict the oldest one.
540 for (int64 i
= 0; i
< FLAGS_quic_time_wait_list_max_connections
; ++i
) {
541 ++current_connection_id
;
542 const QuicConnectionId id_to_evict
=
543 current_connection_id
- FLAGS_quic_time_wait_list_max_connections
;
544 EXPECT_TRUE(IsConnectionIdInTimeWait(id_to_evict
));
545 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id
));
546 EXPECT_CALL(visitor_
, OnConnectionRemovedFromTimeWaitList(id_to_evict
));
547 EXPECT_CALL(visitor_
,
548 OnConnectionAddedToTimeWaitList(current_connection_id
));
549 AddConnectionId(current_connection_id
);
550 EXPECT_EQ(static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections
),
551 time_wait_list_manager_
.num_connections());
552 EXPECT_FALSE(IsConnectionIdInTimeWait(id_to_evict
));
553 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id
));