Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / tools / quic / quic_time_wait_list_manager_test.cc
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_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"
23
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;
37
38 namespace net {
39 namespace tools {
40 namespace test {
41
42 class QuicTimeWaitListManagerPeer {
43  public:
44   static bool ShouldSendResponse(QuicTimeWaitListManager* manager,
45                                  int received_packet_count) {
46     return manager->ShouldSendResponse(received_packet_count);
47   }
48
49   static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager) {
50     return manager->kTimeWaitPeriod_;
51   }
52
53   static QuicVersion GetQuicVersionFromGuid(QuicTimeWaitListManager* manager,
54                                             QuicGuid guid) {
55     return manager->GetQuicVersionFromGuid(guid);
56   }
57 };
58
59 namespace {
60
61 class MockFakeTimeEpollServer : public FakeTimeEpollServer {
62  public:
63   MOCK_METHOD2(RegisterAlarm, void(int64 timeout_in_us,
64                                    EpollAlarmCallbackInterface* alarm));
65 };
66
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) {}
76
77   virtual ~QuicTimeWaitListManagerTest() {}
78
79   virtual void SetUp() {
80     EXPECT_CALL(writer_, IsWriteBlocked())
81         .WillRepeatedly(ReturnPointee(&writer_is_blocked_));
82     EXPECT_CALL(writer_, IsWriteBlockedDataBuffered())
83         .WillRepeatedly(Return(false));
84   }
85
86   void AddGuid(QuicGuid guid) {
87     AddGuid(guid, net::test::QuicVersionMax(), NULL);
88   }
89
90   void AddGuid(QuicGuid guid,
91                QuicVersion version,
92                QuicEncryptedPacket* packet) {
93     time_wait_list_manager_.AddGuidToTimeWait(guid, version, packet);
94   }
95
96   bool IsGuidInTimeWait(QuicGuid guid) {
97     return time_wait_list_manager_.IsGuidInTimeWait(guid);
98   }
99
100   void ProcessPacket(QuicGuid guid, QuicPacketSequenceNumber sequence_number) {
101     time_wait_list_manager_.ProcessPacket(server_address_,
102                                           client_address_,
103                                           guid,
104                                           sequence_number);
105   }
106
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;
135   }
136
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_;
146 };
147
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) {
154   }
155
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();
173   }
174
175   virtual void DescribeTo(::std::ostream* os) const { }
176
177   virtual void DescribeNegationTo(::std::ostream* os) const { }
178
179  private:
180   QuicGuid guid_;
181   QuicPacketSequenceNumber sequence_number_;
182 };
183
184
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));
190 }
191
192 TEST_F(QuicTimeWaitListManagerTest, CheckGuidInTimeWait) {
193   EXPECT_FALSE(IsGuidInTimeWait(guid_));
194   AddGuid(guid_);
195   EXPECT_TRUE(IsGuidInTimeWait(guid_));
196 }
197
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)));
209
210   ProcessPacket(guid_, kRandomSequenceNumber);
211 }
212
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)));
222
223   ProcessPacket(guid_, kRandomSequenceNumber);
224 }
225
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)));
232     }
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));
241     }
242   }
243 }
244
245 TEST_F(QuicTimeWaitListManagerTest, CleanUpOldGuids) {
246   const int kGuidCount = 100;
247   const int kOldGuidCount = 31;
248
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);
253   }
254
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);
261   }
262
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, _));
270
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;
276   }
277 }
278
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);
293
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);
307
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);
320
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();
337 }
338
339 TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) {
340   const int kGuid1 = 123;
341   const int kGuid2 = 456;
342   const int kGuid3 = 789;
343
344   AddGuid(kGuid1, net::test::QuicVersionMin(), NULL);
345   AddGuid(kGuid2, net::test::QuicVersionMax(), NULL);
346   AddGuid(kGuid3, net::test::QuicVersionMax(), NULL);
347
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));
357 }
358
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_));
370
371   EXPECT_CALL(writer_, WritePacket(_,
372                                    kConnectionCloseLength,
373                                    server_address_.address(),
374                                    client_address_))
375       .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
376
377   const int kRandomSequenceNumber = 1;
378   ProcessPacket(guid_, kRandomSequenceNumber);
379
380   const QuicTime::Delta time_wait_period =
381       QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
382
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();
389
390   EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _));
391   time_wait_list_manager_.CleanUpOldGuids();
392   EXPECT_FALSE(IsGuidInTimeWait(guid_));
393 }
394
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;
403
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);
410
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);
414
415   EXPECT_CALL(epoll_server_, RegisterAlarm(_, _));
416
417   time_wait_list_manager_.CleanUpOldGuids();
418   EXPECT_FALSE(IsGuidInTimeWait(kGuid1));
419   EXPECT_TRUE(IsGuidInTimeWait(kGuid2));
420 }
421 }  // namespace
422 }  // namespace test
423 }  // namespace tools
424 }  // namespace net