[Android WebView] Fix webview perf bot switchover to use org.chromium.webview_shell...
[chromium-blink-merge.git] / net / tools / quic / quic_time_wait_list_manager_test.cc
blob423bd9530609bf43744c8b001d1f5bee8e1fe78f
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"
7 #include <errno.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;
32 using testing::Args;
33 using testing::Assign;
34 using testing::DoAll;
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;
42 using testing::Truly;
43 using testing::_;
45 namespace net {
46 namespace tools {
47 namespace test {
49 class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor {
50 public:
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_;
62 private:
63 QuicPublicResetPacket public_reset_packet_;
66 class QuicTimeWaitListManagerPeer {
67 public:
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);
84 namespace {
86 class MockFakeTimeEpollServer : public FakeTimeEpollServer {
87 public:
88 MOCK_METHOD2(RegisterAlarm, void(int64 timeout_in_us,
89 EpollAlarmCallbackInterface* alarm));
92 class QuicTimeWaitListManagerTest : public ::testing::Test {
93 protected:
94 QuicTimeWaitListManagerTest()
95 : helper_(&epoll_server_),
96 time_wait_list_manager_(&writer_,
97 &visitor_,
98 &helper_,
99 QuicSupportedVersions()),
100 framer_(QuicSupportedVersions(),
101 QuicTime::Zero(),
102 Perspective::IS_SERVER),
103 connection_id_(45),
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,
128 QuicVersion version,
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_,
143 client_address_,
144 connection_id,
145 sequence_number,
146 packet);
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);
167 QuicFrames frames;
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_;
184 QuicFramer framer_;
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> > {
193 public:
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 {}
221 private:
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,
231 sequence_number));
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(),
260 client_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(),
272 client_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));
294 } else {
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;
315 ++connection_id) {
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
337 // interval.
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;
343 ++connection_id) {
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;
350 ++connection_id) {
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(),
370 client_address_))
371 .With(Args<0, 1>(PublicResetPacketEq(connection_id,
372 sequence_number)))
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(),
379 client_address_))
380 .With(Args<0, 1>(PublicResetPacketEq(connection_id,
381 sequence_number)))
382 .WillOnce(DoAll(
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
391 // should be queued.
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(_, _, _, _))
400 .Times(0);
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(),
409 client_address_))
410 .With(Args<0, 1>(PublicResetPacketEq(connection_id,
411 sequence_number)))
412 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
413 EXPECT_CALL(writer_, WritePacket(_, _,
414 server_address_.address(),
415 client_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(),
466 client_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
492 // 50% flaky.
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));
557 } // namespace
558 } // namespace test
559 } // namespace tools
560 } // namespace net