Connect PPAPI IPC channels for non-SFI mode.
[chromium-blink-merge.git] / net / tools / quic / quic_time_wait_list_manager_test.cc
blob9aac8b36bf0f5f3b85274d02a5cb1d76c21c4c40
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_data_reader.h"
14 #include "net/quic/quic_framer.h"
15 #include "net/quic/quic_packet_writer.h"
16 #include "net/quic/quic_protocol.h"
17 #include "net/quic/quic_utils.h"
18 #include "net/quic/test_tools/quic_test_utils.h"
19 #include "net/tools/quic/test_tools/mock_epoll_server.h"
20 #include "net/tools/quic/test_tools/quic_test_utils.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using net::test::FramerVisitorCapturingPublicReset;
25 using testing::_;
26 using testing::Args;
27 using testing::Assign;
28 using testing::DoAll;
29 using testing::Matcher;
30 using testing::MatcherInterface;
31 using testing::NiceMock;
32 using testing::Return;
33 using testing::ReturnPointee;
34 using testing::SetArgPointee;
35 using testing::StrictMock;
36 using testing::Truly;
38 namespace net {
39 namespace tools {
40 namespace test {
42 class QuicTimeWaitListManagerPeer {
43 public:
44 static bool ShouldSendResponse(QuicTimeWaitListManager* manager,
45 int received_packet_count) {
46 return manager->ShouldSendResponse(received_packet_count);
49 static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager) {
50 return manager->kTimeWaitPeriod_;
53 static QuicVersion GetQuicVersionFromGuid(QuicTimeWaitListManager* manager,
54 QuicGuid guid) {
55 return manager->GetQuicVersionFromGuid(guid);
59 namespace {
61 class MockFakeTimeEpollServer : public FakeTimeEpollServer {
62 public:
63 MOCK_METHOD2(RegisterAlarm, void(int64 timeout_in_us,
64 EpollAlarmCallbackInterface* alarm));
67 class QuicTimeWaitListManagerTest : public testing::Test {
68 protected:
69 QuicTimeWaitListManagerTest()
70 : time_wait_list_manager_(&writer_, &visitor_,
71 &epoll_server_, QuicSupportedVersions()),
72 framer_(QuicSupportedVersions(), QuicTime::Zero(), true),
73 guid_(45),
74 client_address_(net::test::TestPeerIPAddress(), kTestPort),
75 writer_is_blocked_(false) {}
77 virtual ~QuicTimeWaitListManagerTest() {}
79 virtual void SetUp() {
80 EXPECT_CALL(writer_, IsWriteBlocked())
81 .WillRepeatedly(ReturnPointee(&writer_is_blocked_));
82 EXPECT_CALL(writer_, IsWriteBlockedDataBuffered())
83 .WillRepeatedly(Return(false));
86 void AddGuid(QuicGuid guid) {
87 AddGuid(guid, net::test::QuicVersionMax(), NULL);
90 void AddGuid(QuicGuid guid,
91 QuicVersion version,
92 QuicEncryptedPacket* packet) {
93 time_wait_list_manager_.AddGuidToTimeWait(guid, version, packet);
96 bool IsGuidInTimeWait(QuicGuid guid) {
97 return time_wait_list_manager_.IsGuidInTimeWait(guid);
100 void ProcessPacket(QuicGuid guid, QuicPacketSequenceNumber sequence_number) {
101 time_wait_list_manager_.ProcessPacket(server_address_,
102 client_address_,
103 guid,
104 sequence_number);
107 QuicEncryptedPacket* ConstructEncryptedPacket(
108 EncryptionLevel level,
109 QuicGuid guid,
110 QuicPacketSequenceNumber sequence_number) {
111 QuicPacketHeader header;
112 header.public_header.guid = guid;
113 header.public_header.guid_length = PACKET_8BYTE_GUID;
114 header.public_header.version_flag = false;
115 header.public_header.reset_flag = false;
116 header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER;
117 header.packet_sequence_number = sequence_number;
118 header.entropy_flag = false;
119 header.entropy_hash = 0;
120 header.fec_flag = false;
121 header.is_in_fec_group = NOT_IN_FEC_GROUP;
122 header.fec_group = 0;
123 QuicStreamFrame stream_frame(1, false, 0, MakeIOVector("data"));
124 QuicFrame frame(&stream_frame);
125 QuicFrames frames;
126 frames.push_back(frame);
127 scoped_ptr<QuicPacket> packet(
128 framer_.BuildUnsizedDataPacket(header, frames).packet);
129 EXPECT_TRUE(packet != NULL);
130 QuicEncryptedPacket* encrypted = framer_.EncryptPacket(ENCRYPTION_NONE,
131 sequence_number,
132 *packet);
133 EXPECT_TRUE(encrypted != NULL);
134 return encrypted;
137 NiceMock<MockFakeTimeEpollServer> epoll_server_;
138 StrictMock<MockPacketWriter> writer_;
139 StrictMock<MockQuicServerSessionVisitor> visitor_;
140 QuicTimeWaitListManager time_wait_list_manager_;
141 QuicFramer framer_;
142 QuicGuid guid_;
143 IPEndPoint server_address_;
144 IPEndPoint client_address_;
145 bool writer_is_blocked_;
148 class ValidatePublicResetPacketPredicate
149 : public MatcherInterface<const std::tr1::tuple<const char*, int> > {
150 public:
151 explicit ValidatePublicResetPacketPredicate(QuicGuid guid,
152 QuicPacketSequenceNumber number)
153 : guid_(guid), sequence_number_(number) {
156 virtual bool MatchAndExplain(
157 const std::tr1::tuple<const char*, int> packet_buffer,
158 testing::MatchResultListener* /* listener */) const {
159 FramerVisitorCapturingPublicReset visitor;
160 QuicFramer framer(QuicSupportedVersions(),
161 QuicTime::Zero(),
162 false);
163 framer.set_visitor(&visitor);
164 QuicEncryptedPacket encrypted(std::tr1::get<0>(packet_buffer),
165 std::tr1::get<1>(packet_buffer));
166 framer.ProcessPacket(encrypted);
167 QuicPublicResetPacket packet = visitor.public_reset_packet();
168 return guid_ == packet.public_header.guid &&
169 packet.public_header.reset_flag && !packet.public_header.version_flag &&
170 sequence_number_ == packet.rejected_sequence_number &&
171 net::test::TestPeerIPAddress() == packet.client_address.address() &&
172 kTestPort == packet.client_address.port();
175 virtual void DescribeTo(::std::ostream* os) const { }
177 virtual void DescribeNegationTo(::std::ostream* os) const { }
179 private:
180 QuicGuid guid_;
181 QuicPacketSequenceNumber sequence_number_;
185 Matcher<const std::tr1::tuple<const char*, int> > PublicResetPacketEq(
186 QuicGuid guid,
187 QuicPacketSequenceNumber sequence_number) {
188 return MakeMatcher(new ValidatePublicResetPacketPredicate(guid,
189 sequence_number));
192 TEST_F(QuicTimeWaitListManagerTest, CheckGuidInTimeWait) {
193 EXPECT_FALSE(IsGuidInTimeWait(guid_));
194 AddGuid(guid_);
195 EXPECT_TRUE(IsGuidInTimeWait(guid_));
198 TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) {
199 size_t kConnectionCloseLength = 100;
200 AddGuid(guid_,
201 net::test::QuicVersionMax(),
202 new QuicEncryptedPacket(
203 new char[kConnectionCloseLength], kConnectionCloseLength, true));
204 const int kRandomSequenceNumber = 1;
205 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
206 server_address_.address(),
207 client_address_))
208 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
210 ProcessPacket(guid_, kRandomSequenceNumber);
213 TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) {
214 AddGuid(guid_);
215 const int kRandomSequenceNumber = 1;
216 EXPECT_CALL(writer_, WritePacket(_, _,
217 server_address_.address(),
218 client_address_))
219 .With(Args<0, 1>(PublicResetPacketEq(guid_,
220 kRandomSequenceNumber)))
221 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
223 ProcessPacket(guid_, kRandomSequenceNumber);
226 TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) {
227 AddGuid(guid_);
228 for (int sequence_number = 1; sequence_number < 101; ++sequence_number) {
229 if ((sequence_number & (sequence_number - 1)) == 0) {
230 EXPECT_CALL(writer_, WritePacket(_, _, _, _))
231 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
233 ProcessPacket(guid_, sequence_number);
234 // Send public reset with exponential back off.
235 if ((sequence_number & (sequence_number - 1)) == 0) {
236 EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
237 &time_wait_list_manager_, sequence_number));
238 } else {
239 EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
240 &time_wait_list_manager_, sequence_number));
245 TEST_F(QuicTimeWaitListManagerTest, CleanUpOldGuids) {
246 const int kGuidCount = 100;
247 const int kOldGuidCount = 31;
249 // Add guids such that their expiry time is kTimeWaitPeriod_.
250 epoll_server_.set_now_in_usec(0);
251 for (int guid = 1; guid <= kOldGuidCount; ++guid) {
252 AddGuid(guid);
255 // Add remaining guids such that their add time is 2 * kTimeWaitPeriod.
256 const QuicTime::Delta time_wait_period =
257 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
258 epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds());
259 for (int guid = kOldGuidCount + 1; guid <= kGuidCount; ++guid) {
260 AddGuid(guid);
263 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39);
264 // Now set the current time as time_wait_period + offset usecs.
265 epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds());
266 // After all the old guids are cleaned up, check the next alarm interval.
267 int64 next_alarm_time = epoll_server_.ApproximateNowInUsec() +
268 time_wait_period.Subtract(offset).ToMicroseconds();
269 EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _));
271 time_wait_list_manager_.CleanUpOldGuids();
272 for (int guid = 1; guid <= kGuidCount; ++guid) {
273 EXPECT_EQ(guid > kOldGuidCount, IsGuidInTimeWait(guid))
274 << "kOldGuidCount: " << kOldGuidCount
275 << " guid: " << guid;
279 TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
280 QuicGuid guid = 1;
281 AddGuid(guid);
282 QuicPacketSequenceNumber sequence_number = 234;
283 scoped_ptr<QuicEncryptedPacket> packet(
284 ConstructEncryptedPacket(ENCRYPTION_NONE, guid, sequence_number));
285 // Let first write through.
286 EXPECT_CALL(writer_, WritePacket(_, _,
287 server_address_.address(),
288 client_address_))
289 .With(Args<0, 1>(PublicResetPacketEq(guid,
290 sequence_number)))
291 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
292 ProcessPacket(guid, sequence_number);
294 // write block for the next packet.
295 EXPECT_CALL(writer_, WritePacket(_, _,
296 server_address_.address(),
297 client_address_))
298 .With(Args<0, 1>(PublicResetPacketEq(guid,
299 sequence_number)))
300 .WillOnce(DoAll(
301 Assign(&writer_is_blocked_, true),
302 Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))));
303 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
304 ProcessPacket(guid, sequence_number);
305 // 3rd packet. No public reset should be sent;
306 ProcessPacket(guid, sequence_number);
308 // write packet should not be called since we are write blocked but the
309 // should be queued.
310 QuicGuid other_guid = 2;
311 AddGuid(other_guid);
312 QuicPacketSequenceNumber other_sequence_number = 23423;
313 scoped_ptr<QuicEncryptedPacket> other_packet(
314 ConstructEncryptedPacket(
315 ENCRYPTION_NONE, other_guid, other_sequence_number));
316 EXPECT_CALL(writer_, WritePacket(_, _, _, _))
317 .Times(0);
318 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
319 ProcessPacket(other_guid, other_sequence_number);
321 // Now expect all the write blocked public reset packets to be sent again.
322 writer_is_blocked_ = false;
323 EXPECT_CALL(writer_, WritePacket(_, _,
324 server_address_.address(),
325 client_address_))
326 .With(Args<0, 1>(PublicResetPacketEq(guid,
327 sequence_number)))
328 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
329 EXPECT_CALL(writer_, WritePacket(_, _,
330 server_address_.address(),
331 client_address_))
332 .With(Args<0, 1>(PublicResetPacketEq(other_guid,
333 other_sequence_number)))
334 .WillOnce(Return(WriteResult(WRITE_STATUS_OK,
335 other_packet->length())));
336 time_wait_list_manager_.OnCanWrite();
339 TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) {
340 const int kGuid1 = 123;
341 const int kGuid2 = 456;
342 const int kGuid3 = 789;
344 AddGuid(kGuid1, net::test::QuicVersionMin(), NULL);
345 AddGuid(kGuid2, net::test::QuicVersionMax(), NULL);
346 AddGuid(kGuid3, net::test::QuicVersionMax(), NULL);
348 EXPECT_EQ(net::test::QuicVersionMin(),
349 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
350 &time_wait_list_manager_, kGuid1));
351 EXPECT_EQ(net::test::QuicVersionMax(),
352 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
353 &time_wait_list_manager_, kGuid2));
354 EXPECT_EQ(net::test::QuicVersionMax(),
355 QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
356 &time_wait_list_manager_, kGuid3));
359 TEST_F(QuicTimeWaitListManagerTest, AddGuidTwice) {
360 // Add guids such that their expiry time is kTimeWaitPeriod_.
361 epoll_server_.set_now_in_usec(0);
362 AddGuid(guid_);
363 EXPECT_TRUE(IsGuidInTimeWait(guid_));
364 size_t kConnectionCloseLength = 100;
365 AddGuid(guid_,
366 net::test::QuicVersionMax(),
367 new QuicEncryptedPacket(
368 new char[kConnectionCloseLength], kConnectionCloseLength, true));
369 EXPECT_TRUE(IsGuidInTimeWait(guid_));
371 EXPECT_CALL(writer_, WritePacket(_,
372 kConnectionCloseLength,
373 server_address_.address(),
374 client_address_))
375 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
377 const int kRandomSequenceNumber = 1;
378 ProcessPacket(guid_, kRandomSequenceNumber);
380 const QuicTime::Delta time_wait_period =
381 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
383 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39);
384 // Now set the current time as time_wait_period + offset usecs.
385 epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds());
386 // After the guids are cleaned up, check the next alarm interval.
387 int64 next_alarm_time = epoll_server_.ApproximateNowInUsec() +
388 time_wait_period.ToMicroseconds();
390 EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _));
391 time_wait_list_manager_.CleanUpOldGuids();
392 EXPECT_FALSE(IsGuidInTimeWait(guid_));
395 TEST_F(QuicTimeWaitListManagerTest, GuidsOrderedByTime) {
396 // Simple randomization: the values of guids are swapped based on the current
397 // seconds on the clock. If the container is broken, the test will be 50%
398 // flaky.
399 int odd_second = static_cast<int>(epoll_server_.ApproximateNowInUsec()) % 2;
400 EXPECT_TRUE(odd_second == 0 || odd_second == 1);
401 const QuicGuid kGuid1 = odd_second;
402 const QuicGuid kGuid2 = 1 - odd_second;
404 // 1 will hash lower than 2, but we add it later. They should come out in the
405 // add order, not hash order.
406 epoll_server_.set_now_in_usec(0);
407 AddGuid(kGuid1);
408 epoll_server_.set_now_in_usec(10);
409 AddGuid(kGuid2);
411 const QuicTime::Delta time_wait_period =
412 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
413 epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds() + 1);
415 EXPECT_CALL(epoll_server_, RegisterAlarm(_, _));
417 time_wait_list_manager_.CleanUpOldGuids();
418 EXPECT_FALSE(IsGuidInTimeWait(kGuid1));
419 EXPECT_TRUE(IsGuidInTimeWait(kGuid2));
421 } // namespace
422 } // namespace test
423 } // namespace tools
424 } // namespace net