OLD | NEW |
| (Empty) |
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 "net/tools/quic/quic_time_wait_list_manager.h" | |
6 | |
7 #include <errno.h> | |
8 | |
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_data_reader.h" | |
14 #include "net/quic/quic_flags.h" | |
15 #include "net/quic/quic_framer.h" | |
16 #include "net/quic/quic_packet_writer.h" | |
17 #include "net/quic/quic_protocol.h" | |
18 #include "net/quic/quic_utils.h" | |
19 #include "net/quic/test_tools/quic_test_utils.h" | |
20 #include "net/tools/quic/test_tools/mock_epoll_server.h" | |
21 #include "net/tools/quic/test_tools/quic_test_utils.h" | |
22 #include "testing/gmock/include/gmock/gmock.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 | |
25 using net::test::BuildUnsizedDataPacket; | |
26 using net::test::NoOpFramerVisitor; | |
27 using net::test::QuicVersionMax; | |
28 using net::test::QuicVersionMin; | |
29 using net::test::ValueRestore; | |
30 using testing::Args; | |
31 using testing::Assign; | |
32 using testing::DoAll; | |
33 using testing::Matcher; | |
34 using testing::MatcherInterface; | |
35 using testing::NiceMock; | |
36 using testing::Return; | |
37 using testing::ReturnPointee; | |
38 using testing::SetArgPointee; | |
39 using testing::StrictMock; | |
40 using testing::Truly; | |
41 using testing::_; | |
42 | |
43 namespace net { | |
44 namespace tools { | |
45 namespace test { | |
46 | |
47 class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor { | |
48 public: | |
49 FramerVisitorCapturingPublicReset() {} | |
50 ~FramerVisitorCapturingPublicReset() override {} | |
51 | |
52 void OnPublicResetPacket(const QuicPublicResetPacket& public_reset) override { | |
53 public_reset_packet_ = public_reset; | |
54 } | |
55 | |
56 const QuicPublicResetPacket public_reset_packet() { | |
57 return public_reset_packet_; | |
58 } | |
59 | |
60 private: | |
61 QuicPublicResetPacket public_reset_packet_; | |
62 }; | |
63 | |
64 class QuicTimeWaitListManagerPeer { | |
65 public: | |
66 static bool ShouldSendResponse(QuicTimeWaitListManager* manager, | |
67 int received_packet_count) { | |
68 return manager->ShouldSendResponse(received_packet_count); | |
69 } | |
70 | |
71 static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager) { | |
72 return manager->kTimeWaitPeriod_; | |
73 } | |
74 | |
75 static QuicVersion GetQuicVersionFromConnectionId( | |
76 QuicTimeWaitListManager* manager, | |
77 QuicConnectionId connection_id) { | |
78 return manager->GetQuicVersionFromConnectionId(connection_id); | |
79 } | |
80 }; | |
81 | |
82 namespace { | |
83 | |
84 class MockFakeTimeEpollServer : public FakeTimeEpollServer { | |
85 public: | |
86 MOCK_METHOD2(RegisterAlarm, void(int64 timeout_in_us, | |
87 EpollAlarmCallbackInterface* alarm)); | |
88 }; | |
89 | |
90 class QuicTimeWaitListManagerTest : public ::testing::Test { | |
91 protected: | |
92 QuicTimeWaitListManagerTest() | |
93 : time_wait_list_manager_(&writer_, &visitor_, | |
94 &epoll_server_, QuicSupportedVersions()), | |
95 framer_(QuicSupportedVersions(), QuicTime::Zero(), true), | |
96 connection_id_(45), | |
97 client_address_(net::test::TestPeerIPAddress(), kTestPort), | |
98 writer_is_blocked_(false) {} | |
99 | |
100 ~QuicTimeWaitListManagerTest() override {} | |
101 | |
102 void SetUp() override { | |
103 EXPECT_CALL(writer_, IsWriteBlocked()) | |
104 .WillRepeatedly(ReturnPointee(&writer_is_blocked_)); | |
105 EXPECT_CALL(writer_, IsWriteBlockedDataBuffered()) | |
106 .WillRepeatedly(Return(false)); | |
107 } | |
108 | |
109 void AddConnectionId(QuicConnectionId connection_id) { | |
110 AddConnectionId(connection_id, QuicVersionMax(), nullptr); | |
111 } | |
112 | |
113 void AddConnectionId(QuicConnectionId connection_id, | |
114 QuicVersion version, | |
115 QuicEncryptedPacket* packet) { | |
116 time_wait_list_manager_.AddConnectionIdToTimeWait( | |
117 connection_id, version, packet); | |
118 } | |
119 | |
120 bool IsConnectionIdInTimeWait(QuicConnectionId connection_id) { | |
121 return time_wait_list_manager_.IsConnectionIdInTimeWait(connection_id); | |
122 } | |
123 | |
124 void ProcessPacket(QuicConnectionId connection_id, | |
125 QuicPacketSequenceNumber sequence_number) { | |
126 QuicEncryptedPacket packet(nullptr, 0); | |
127 time_wait_list_manager_.ProcessPacket(server_address_, | |
128 client_address_, | |
129 connection_id, | |
130 sequence_number, | |
131 packet); | |
132 } | |
133 | |
134 QuicEncryptedPacket* ConstructEncryptedPacket( | |
135 EncryptionLevel level, | |
136 QuicConnectionId connection_id, | |
137 QuicPacketSequenceNumber sequence_number) { | |
138 QuicPacketHeader header; | |
139 header.public_header.connection_id = connection_id; | |
140 header.public_header.connection_id_length = PACKET_8BYTE_CONNECTION_ID; | |
141 header.public_header.version_flag = false; | |
142 header.public_header.reset_flag = false; | |
143 header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER; | |
144 header.packet_sequence_number = sequence_number; | |
145 header.entropy_flag = false; | |
146 header.entropy_hash = 0; | |
147 header.fec_flag = false; | |
148 header.is_in_fec_group = NOT_IN_FEC_GROUP; | |
149 header.fec_group = 0; | |
150 QuicStreamFrame stream_frame(1, false, 0, MakeIOVector("data")); | |
151 QuicFrame frame(&stream_frame); | |
152 QuicFrames frames; | |
153 frames.push_back(frame); | |
154 scoped_ptr<QuicPacket> packet( | |
155 BuildUnsizedDataPacket(&framer_, header, frames)); | |
156 EXPECT_TRUE(packet != nullptr); | |
157 QuicEncryptedPacket* encrypted = framer_.EncryptPacket(ENCRYPTION_NONE, | |
158 sequence_number, | |
159 *packet); | |
160 EXPECT_TRUE(encrypted != nullptr); | |
161 return encrypted; | |
162 } | |
163 | |
164 NiceMock<MockFakeTimeEpollServer> epoll_server_; | |
165 StrictMock<MockPacketWriter> writer_; | |
166 StrictMock<MockQuicServerSessionVisitor> visitor_; | |
167 QuicTimeWaitListManager time_wait_list_manager_; | |
168 QuicFramer framer_; | |
169 QuicConnectionId connection_id_; | |
170 IPEndPoint server_address_; | |
171 IPEndPoint client_address_; | |
172 bool writer_is_blocked_; | |
173 }; | |
174 | |
175 class ValidatePublicResetPacketPredicate | |
176 : public MatcherInterface<const std::tr1::tuple<const char*, int> > { | |
177 public: | |
178 explicit ValidatePublicResetPacketPredicate(QuicConnectionId connection_id, | |
179 QuicPacketSequenceNumber number) | |
180 : connection_id_(connection_id), sequence_number_(number) { | |
181 } | |
182 | |
183 virtual bool MatchAndExplain( | |
184 const std::tr1::tuple<const char*, int> packet_buffer, | |
185 testing::MatchResultListener* /* listener */) const override { | |
186 FramerVisitorCapturingPublicReset visitor; | |
187 QuicFramer framer(QuicSupportedVersions(), | |
188 QuicTime::Zero(), | |
189 false); | |
190 framer.set_visitor(&visitor); | |
191 QuicEncryptedPacket encrypted(std::tr1::get<0>(packet_buffer), | |
192 std::tr1::get<1>(packet_buffer)); | |
193 framer.ProcessPacket(encrypted); | |
194 QuicPublicResetPacket packet = visitor.public_reset_packet(); | |
195 return connection_id_ == packet.public_header.connection_id && | |
196 packet.public_header.reset_flag && !packet.public_header.version_flag && | |
197 sequence_number_ == packet.rejected_sequence_number && | |
198 net::test::TestPeerIPAddress() == packet.client_address.address() && | |
199 kTestPort == packet.client_address.port(); | |
200 } | |
201 | |
202 virtual void DescribeTo(::std::ostream* os) const override {} | |
203 | |
204 virtual void DescribeNegationTo(::std::ostream* os) const override {} | |
205 | |
206 private: | |
207 QuicConnectionId connection_id_; | |
208 QuicPacketSequenceNumber sequence_number_; | |
209 }; | |
210 | |
211 | |
212 Matcher<const std::tr1::tuple<const char*, int> > PublicResetPacketEq( | |
213 QuicConnectionId connection_id, | |
214 QuicPacketSequenceNumber sequence_number) { | |
215 return MakeMatcher(new ValidatePublicResetPacketPredicate(connection_id, | |
216 sequence_number)); | |
217 } | |
218 | |
219 TEST_F(QuicTimeWaitListManagerTest, CheckConnectionIdInTimeWait) { | |
220 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_)); | |
221 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
222 AddConnectionId(connection_id_); | |
223 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
224 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); | |
225 } | |
226 | |
227 TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) { | |
228 size_t kConnectionCloseLength = 100; | |
229 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
230 AddConnectionId( | |
231 connection_id_, | |
232 QuicVersionMax(), | |
233 new QuicEncryptedPacket( | |
234 new char[kConnectionCloseLength], kConnectionCloseLength, true)); | |
235 const int kRandomSequenceNumber = 1; | |
236 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, | |
237 server_address_.address(), | |
238 client_address_)) | |
239 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); | |
240 | |
241 ProcessPacket(connection_id_, kRandomSequenceNumber); | |
242 } | |
243 | |
244 TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) { | |
245 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
246 AddConnectionId(connection_id_); | |
247 const int kRandomSequenceNumber = 1; | |
248 EXPECT_CALL(writer_, WritePacket(_, _, | |
249 server_address_.address(), | |
250 client_address_)) | |
251 .With(Args<0, 1>(PublicResetPacketEq(connection_id_, | |
252 kRandomSequenceNumber))) | |
253 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); | |
254 | |
255 ProcessPacket(connection_id_, kRandomSequenceNumber); | |
256 } | |
257 | |
258 TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) { | |
259 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
260 AddConnectionId(connection_id_); | |
261 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
262 for (int sequence_number = 1; sequence_number < 101; ++sequence_number) { | |
263 if ((sequence_number & (sequence_number - 1)) == 0) { | |
264 EXPECT_CALL(writer_, WritePacket(_, _, _, _)) | |
265 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); | |
266 } | |
267 ProcessPacket(connection_id_, sequence_number); | |
268 // Send public reset with exponential back off. | |
269 if ((sequence_number & (sequence_number - 1)) == 0) { | |
270 EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse( | |
271 &time_wait_list_manager_, sequence_number)); | |
272 } else { | |
273 EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse( | |
274 &time_wait_list_manager_, sequence_number)); | |
275 } | |
276 } | |
277 } | |
278 | |
279 TEST_F(QuicTimeWaitListManagerTest, CleanUpOldConnectionIds) { | |
280 const size_t kConnectionIdCount = 100; | |
281 const size_t kOldConnectionIdCount = 31; | |
282 | |
283 // Add connection_ids such that their expiry time is kTimeWaitPeriod_. | |
284 epoll_server_.set_now_in_usec(0); | |
285 for (size_t connection_id = 1; connection_id <= kOldConnectionIdCount; | |
286 ++connection_id) { | |
287 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); | |
288 AddConnectionId(connection_id); | |
289 } | |
290 EXPECT_EQ(kOldConnectionIdCount, time_wait_list_manager_.num_connections()); | |
291 | |
292 // Add remaining connection_ids such that their add time is | |
293 // 2 * kTimeWaitPeriod. | |
294 const QuicTime::Delta time_wait_period = | |
295 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); | |
296 epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds()); | |
297 for (size_t connection_id = kOldConnectionIdCount + 1; | |
298 connection_id <= kConnectionIdCount; ++connection_id) { | |
299 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); | |
300 AddConnectionId(connection_id); | |
301 } | |
302 EXPECT_EQ(kConnectionIdCount, time_wait_list_manager_.num_connections()); | |
303 | |
304 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); | |
305 // Now set the current time as time_wait_period + offset usecs. | |
306 epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds()); | |
307 // After all the old connection_ids are cleaned up, check the next alarm | |
308 // interval. | |
309 int64 next_alarm_time = epoll_server_.ApproximateNowInUsec() + | |
310 time_wait_period.Subtract(offset).ToMicroseconds(); | |
311 EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); | |
312 | |
313 for (size_t connection_id = 1; connection_id <= kConnectionIdCount; | |
314 ++connection_id) { | |
315 if (connection_id <= kOldConnectionIdCount) { | |
316 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(connection_id)); | |
317 } | |
318 } | |
319 time_wait_list_manager_.CleanUpOldConnectionIds(); | |
320 for (size_t connection_id = 1; connection_id <= kConnectionIdCount; | |
321 ++connection_id) { | |
322 EXPECT_EQ(connection_id > kOldConnectionIdCount, | |
323 IsConnectionIdInTimeWait(connection_id)) | |
324 << "kOldConnectionIdCount: " << kOldConnectionIdCount | |
325 << " connection_id: " << connection_id; | |
326 } | |
327 EXPECT_EQ(kConnectionIdCount - kOldConnectionIdCount, | |
328 time_wait_list_manager_.num_connections()); | |
329 } | |
330 | |
331 TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) { | |
332 QuicConnectionId connection_id = 1; | |
333 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); | |
334 AddConnectionId(connection_id); | |
335 QuicPacketSequenceNumber sequence_number = 234; | |
336 scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( | |
337 ENCRYPTION_NONE, connection_id, sequence_number)); | |
338 // Let first write through. | |
339 EXPECT_CALL(writer_, WritePacket(_, _, | |
340 server_address_.address(), | |
341 client_address_)) | |
342 .With(Args<0, 1>(PublicResetPacketEq(connection_id, | |
343 sequence_number))) | |
344 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); | |
345 ProcessPacket(connection_id, sequence_number); | |
346 | |
347 // write block for the next packet. | |
348 EXPECT_CALL(writer_, WritePacket(_, _, | |
349 server_address_.address(), | |
350 client_address_)) | |
351 .With(Args<0, 1>(PublicResetPacketEq(connection_id, | |
352 sequence_number))) | |
353 .WillOnce(DoAll( | |
354 Assign(&writer_is_blocked_, true), | |
355 Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN)))); | |
356 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); | |
357 ProcessPacket(connection_id, sequence_number); | |
358 // 3rd packet. No public reset should be sent; | |
359 ProcessPacket(connection_id, sequence_number); | |
360 | |
361 // write packet should not be called since we are write blocked but the | |
362 // should be queued. | |
363 QuicConnectionId other_connection_id = 2; | |
364 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(other_connection_id)); | |
365 AddConnectionId(other_connection_id); | |
366 QuicPacketSequenceNumber other_sequence_number = 23423; | |
367 scoped_ptr<QuicEncryptedPacket> other_packet( | |
368 ConstructEncryptedPacket( | |
369 ENCRYPTION_NONE, other_connection_id, other_sequence_number)); | |
370 EXPECT_CALL(writer_, WritePacket(_, _, _, _)) | |
371 .Times(0); | |
372 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); | |
373 ProcessPacket(other_connection_id, other_sequence_number); | |
374 EXPECT_EQ(2u, time_wait_list_manager_.num_connections()); | |
375 | |
376 // Now expect all the write blocked public reset packets to be sent again. | |
377 writer_is_blocked_ = false; | |
378 EXPECT_CALL(writer_, WritePacket(_, _, | |
379 server_address_.address(), | |
380 client_address_)) | |
381 .With(Args<0, 1>(PublicResetPacketEq(connection_id, | |
382 sequence_number))) | |
383 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); | |
384 EXPECT_CALL(writer_, WritePacket(_, _, | |
385 server_address_.address(), | |
386 client_address_)) | |
387 .With(Args<0, 1>(PublicResetPacketEq(other_connection_id, | |
388 other_sequence_number))) | |
389 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, | |
390 other_packet->length()))); | |
391 time_wait_list_manager_.OnCanWrite(); | |
392 } | |
393 | |
394 TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) { | |
395 const int kConnectionId1 = 123; | |
396 const int kConnectionId2 = 456; | |
397 const int kConnectionId3 = 789; | |
398 | |
399 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId1)); | |
400 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId2)); | |
401 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId3)); | |
402 AddConnectionId(kConnectionId1, QuicVersionMin(), nullptr); | |
403 AddConnectionId(kConnectionId2, QuicVersionMax(), nullptr); | |
404 AddConnectionId(kConnectionId3, QuicVersionMax(), nullptr); | |
405 | |
406 EXPECT_EQ(QuicVersionMin(), | |
407 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( | |
408 &time_wait_list_manager_, kConnectionId1)); | |
409 EXPECT_EQ(QuicVersionMax(), | |
410 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( | |
411 &time_wait_list_manager_, kConnectionId2)); | |
412 EXPECT_EQ(QuicVersionMax(), | |
413 QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( | |
414 &time_wait_list_manager_, kConnectionId3)); | |
415 } | |
416 | |
417 TEST_F(QuicTimeWaitListManagerTest, AddConnectionIdTwice) { | |
418 // Add connection_ids such that their expiry time is kTimeWaitPeriod_. | |
419 epoll_server_.set_now_in_usec(0); | |
420 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); | |
421 AddConnectionId(connection_id_); | |
422 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); | |
423 size_t kConnectionCloseLength = 100; | |
424 AddConnectionId( | |
425 connection_id_, | |
426 QuicVersionMax(), | |
427 new QuicEncryptedPacket( | |
428 new char[kConnectionCloseLength], kConnectionCloseLength, true)); | |
429 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); | |
430 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
431 | |
432 EXPECT_CALL(writer_, WritePacket(_, | |
433 kConnectionCloseLength, | |
434 server_address_.address(), | |
435 client_address_)) | |
436 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); | |
437 | |
438 const int kRandomSequenceNumber = 1; | |
439 ProcessPacket(connection_id_, kRandomSequenceNumber); | |
440 | |
441 const QuicTime::Delta time_wait_period = | |
442 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); | |
443 | |
444 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); | |
445 // Now set the current time as time_wait_period + offset usecs. | |
446 epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds()); | |
447 // After the connection_ids are cleaned up, check the next alarm interval. | |
448 int64 next_alarm_time = epoll_server_.ApproximateNowInUsec() + | |
449 time_wait_period.ToMicroseconds(); | |
450 | |
451 EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); | |
452 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(connection_id_)); | |
453 time_wait_list_manager_.CleanUpOldConnectionIds(); | |
454 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_)); | |
455 EXPECT_EQ(0u, time_wait_list_manager_.num_connections()); | |
456 } | |
457 | |
458 TEST_F(QuicTimeWaitListManagerTest, ConnectionIdsOrderedByTime) { | |
459 // Simple randomization: the values of connection_ids are swapped based on the | |
460 // current seconds on the clock. If the container is broken, the test will be | |
461 // 50% flaky. | |
462 int odd_second = static_cast<int>(epoll_server_.ApproximateNowInUsec()) % 2; | |
463 EXPECT_TRUE(odd_second == 0 || odd_second == 1); | |
464 const QuicConnectionId kConnectionId1 = odd_second; | |
465 const QuicConnectionId kConnectionId2 = 1 - odd_second; | |
466 | |
467 // 1 will hash lower than 2, but we add it later. They should come out in the | |
468 // add order, not hash order. | |
469 epoll_server_.set_now_in_usec(0); | |
470 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId1)); | |
471 AddConnectionId(kConnectionId1); | |
472 epoll_server_.set_now_in_usec(10); | |
473 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId2)); | |
474 AddConnectionId(kConnectionId2); | |
475 EXPECT_EQ(2u, time_wait_list_manager_.num_connections()); | |
476 | |
477 const QuicTime::Delta time_wait_period = | |
478 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); | |
479 epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds() + 1); | |
480 | |
481 EXPECT_CALL(epoll_server_, RegisterAlarm(_, _)); | |
482 | |
483 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(kConnectionId1)); | |
484 time_wait_list_manager_.CleanUpOldConnectionIds(); | |
485 EXPECT_FALSE(IsConnectionIdInTimeWait(kConnectionId1)); | |
486 EXPECT_TRUE(IsConnectionIdInTimeWait(kConnectionId2)); | |
487 EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); | |
488 } | |
489 | |
490 TEST_F(QuicTimeWaitListManagerTest, MaxConnectionsTest) { | |
491 ValueRestore<bool> old_flag(&FLAGS_quic_limit_time_wait_list_size, true); | |
492 // Basically, shut off time-based eviction. | |
493 FLAGS_quic_time_wait_list_seconds = 10000000000; | |
494 FLAGS_quic_time_wait_list_max_connections = 5; | |
495 | |
496 QuicConnectionId current_connection_id = 0; | |
497 // Add exactly the maximum number of connections | |
498 for (int64 i = 0; i < FLAGS_quic_time_wait_list_max_connections; ++i) { | |
499 ++current_connection_id; | |
500 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id)); | |
501 EXPECT_CALL(visitor_, | |
502 OnConnectionAddedToTimeWaitList(current_connection_id)); | |
503 AddConnectionId(current_connection_id); | |
504 EXPECT_EQ(current_connection_id, time_wait_list_manager_.num_connections()); | |
505 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id)); | |
506 } | |
507 | |
508 // Now keep adding. Since we're already at the max, every new connection-id | |
509 // will evict the oldest one. | |
510 for (int64 i = 0; i < FLAGS_quic_time_wait_list_max_connections; ++i) { | |
511 ++current_connection_id; | |
512 const QuicConnectionId id_to_evict = | |
513 current_connection_id - FLAGS_quic_time_wait_list_max_connections; | |
514 EXPECT_TRUE(IsConnectionIdInTimeWait(id_to_evict)); | |
515 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id)); | |
516 EXPECT_CALL(visitor_, OnConnectionRemovedFromTimeWaitList(id_to_evict)); | |
517 EXPECT_CALL(visitor_, | |
518 OnConnectionAddedToTimeWaitList(current_connection_id)); | |
519 AddConnectionId(current_connection_id); | |
520 EXPECT_EQ(static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections), | |
521 time_wait_list_manager_.num_connections()); | |
522 EXPECT_FALSE(IsConnectionIdInTimeWait(id_to_evict)); | |
523 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id)); | |
524 } | |
525 } | |
526 | |
527 } // namespace | |
528 } // namespace test | |
529 } // namespace tools | |
530 } // namespace net | |
OLD | NEW |