- add sources.
[platform/framework/web/crosswalk.git] / src / net / tools / quic / quic_dispatcher_test.cc
1 // Copyright (c) 2012 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_dispatcher.h"
6
7 #include <string>
8
9 #include "base/strings/string_piece.h"
10 #include "net/quic/crypto/crypto_handshake.h"
11 #include "net/quic/crypto/quic_crypto_server_config.h"
12 #include "net/quic/crypto/quic_random.h"
13 #include "net/quic/quic_crypto_stream.h"
14 #include "net/quic/test_tools/quic_test_utils.h"
15 #include "net/tools/epoll_server/epoll_server.h"
16 #include "net/tools/quic/quic_time_wait_list_manager.h"
17 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
18 #include "net/tools/quic/test_tools/quic_test_utils.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using base::StringPiece;
23 using net::EpollServer;
24 using net::test::MockSession;
25 using net::tools::test::MockConnection;
26 using std::make_pair;
27 using testing::_;
28 using testing::DoAll;
29 using testing::Invoke;
30 using testing::InSequence;
31 using testing::Return;
32 using testing::WithoutArgs;
33
34 namespace net {
35 namespace tools {
36 namespace test {
37 namespace {
38
39 class TestDispatcher : public QuicDispatcher {
40  public:
41   explicit TestDispatcher(const QuicConfig& config,
42                           const QuicCryptoServerConfig& crypto_config,
43                           EpollServer* eps)
44       : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), 1, eps) {
45   }
46
47   MOCK_METHOD2(CreateQuicSession, QuicSession*(
48       QuicGuid guid,
49       const IPEndPoint& client_address));
50   using QuicDispatcher::write_blocked_list;
51 };
52
53 // A Connection class which unregisters the session from the dispatcher
54 // when sending connection close.
55 // It'd be slightly more realistic to do this from the Session but it would
56 // involve a lot more mocking.
57 class MockServerConnection : public MockConnection {
58  public:
59   MockServerConnection(QuicGuid guid,
60                        IPEndPoint address,
61                        int fd,
62                        EpollServer* eps,
63                        QuicDispatcher* dispatcher)
64       : MockConnection(guid, address, fd, eps, true),
65         dispatcher_(dispatcher) {
66   }
67   void UnregisterOnConnectionClosed() {
68     LOG(ERROR) << "Unregistering " << guid();
69     dispatcher_->OnConnectionClosed(guid(), QUIC_NO_ERROR);
70   }
71  private:
72   QuicDispatcher* dispatcher_;
73 };
74
75 QuicSession* CreateSession(QuicDispatcher* dispatcher,
76                            QuicGuid guid,
77                            const IPEndPoint& addr,
78                            MockSession** session,
79                            EpollServer* eps) {
80   MockServerConnection* connection =
81       new MockServerConnection(guid, addr, 0, eps, dispatcher);
82   *session = new MockSession(connection, true);
83   ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
84       WithoutArgs(Invoke(
85           connection, &MockServerConnection::UnregisterOnConnectionClosed)));
86   EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
87               ProcessUdpPacket(_, addr, _));
88
89   return *session;
90 }
91
92 class QuicDispatcherTest : public ::testing::Test {
93  public:
94   QuicDispatcherTest()
95       : crypto_config_(QuicCryptoServerConfig::TESTING,
96                        QuicRandom::GetInstance()),
97         dispatcher_(config_, crypto_config_, &eps_),
98         session1_(NULL),
99         session2_(NULL) {
100   }
101
102   virtual ~QuicDispatcherTest() {}
103
104   MockConnection* connection1() {
105     return reinterpret_cast<MockConnection*>(session1_->connection());
106   }
107
108   MockConnection* connection2() {
109     return reinterpret_cast<MockConnection*>(session2_->connection());
110   }
111
112   void ProcessPacket(IPEndPoint addr,
113                      QuicGuid guid,
114                      const string& data) {
115     QuicEncryptedPacket packet(data.data(), data.length());
116     dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, packet);
117   }
118
119   void ValidatePacket(const QuicEncryptedPacket& packet) {
120     EXPECT_TRUE(packet.AsStringPiece().find(data_) != StringPiece::npos);
121   }
122
123   IPAddressNumber Loopback4() {
124     net::IPAddressNumber addr;
125     CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr));
126     return addr;
127   }
128
129   EpollServer eps_;
130   QuicConfig config_;
131   QuicCryptoServerConfig crypto_config_;
132   TestDispatcher dispatcher_;
133   MockSession* session1_;
134   MockSession* session2_;
135   string data_;
136 };
137
138 TEST_F(QuicDispatcherTest, ProcessPackets) {
139   IPEndPoint addr(Loopback4(), 1);
140
141   EXPECT_CALL(dispatcher_, CreateQuicSession(1, addr))
142       .WillOnce(testing::Return(CreateSession(
143           &dispatcher_, 1, addr, &session1_, &eps_)));
144   ProcessPacket(addr, 1, "foo");
145
146   EXPECT_CALL(dispatcher_, CreateQuicSession(2, addr))
147       .WillOnce(testing::Return(CreateSession(
148                     &dispatcher_, 2, addr, &session2_, &eps_)));
149   ProcessPacket(addr, 2, "bar");
150
151   data_ = "eep";
152   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
153               ProcessUdpPacket(_, _, _)).Times(1).
154       WillOnce(testing::WithArgs<2>(Invoke(
155           this, &QuicDispatcherTest::ValidatePacket)));
156   ProcessPacket(addr, 1, "eep");
157 }
158
159 TEST_F(QuicDispatcherTest, Shutdown) {
160   IPEndPoint addr(Loopback4(), 1);
161
162   EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr))
163       .WillOnce(testing::Return(CreateSession(
164                     &dispatcher_, 1, addr, &session1_, &eps_)));
165
166   ProcessPacket(addr, 1, "foo");
167
168   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
169               SendConnectionClose(QUIC_PEER_GOING_AWAY));
170
171   dispatcher_.Shutdown();
172 }
173
174 class MockTimeWaitListManager : public QuicTimeWaitListManager {
175  public:
176   MockTimeWaitListManager(QuicPacketWriter* writer,
177                           EpollServer* eps)
178       : QuicTimeWaitListManager(writer, eps, QuicSupportedVersions()) {
179   }
180
181   MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
182                                    const IPEndPoint& client_address,
183                                    QuicGuid guid,
184                                    const QuicEncryptedPacket& packet));
185 };
186
187 TEST_F(QuicDispatcherTest, TimeWaitListManager) {
188   MockTimeWaitListManager* time_wait_list_manager =
189       new MockTimeWaitListManager(
190           QuicDispatcherPeer::GetWriter(&dispatcher_), &eps_);
191   // dispatcher takes the ownership of time_wait_list_manager.
192   QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
193                                              time_wait_list_manager);
194   // Create a new session.
195   IPEndPoint addr(Loopback4(), 1);
196   QuicGuid guid = 1;
197   EXPECT_CALL(dispatcher_, CreateQuicSession(guid, addr))
198       .WillOnce(testing::Return(CreateSession(
199                     &dispatcher_, guid, addr, &session1_, &eps_)));
200   ProcessPacket(addr, guid, "foo");
201
202   // Close the connection by sending public reset packet.
203   QuicPublicResetPacket packet;
204   packet.public_header.guid = guid;
205   packet.public_header.reset_flag = true;
206   packet.public_header.version_flag = false;
207   packet.rejected_sequence_number = 19191;
208   packet.nonce_proof = 132232;
209   scoped_ptr<QuicEncryptedPacket> encrypted(
210       QuicFramer::BuildPublicResetPacket(packet));
211   EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
212       .WillOnce(WithoutArgs(Invoke(
213           reinterpret_cast<MockServerConnection*>(session1_->connection()),
214           &MockServerConnection::UnregisterOnConnectionClosed)));
215   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
216               ProcessUdpPacket(_, _, _))
217       .WillOnce(Invoke(
218           reinterpret_cast<MockConnection*>(session1_->connection()),
219           &MockConnection::ReallyProcessUdpPacket));
220   dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, *encrypted);
221   EXPECT_TRUE(time_wait_list_manager->IsGuidInTimeWait(guid));
222
223   // Dispatcher forwards subsequent packets for this guid to the time wait list
224   // manager.
225   EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
226   ProcessPacket(addr, guid, "foo");
227 }
228
229 class QuicWriteBlockedListTest : public QuicDispatcherTest {
230  public:
231   virtual void SetUp() {
232     IPEndPoint addr(Loopback4(), 1);
233
234     EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr))
235         .WillOnce(testing::Return(CreateSession(
236                       &dispatcher_, 1, addr, &session1_, &eps_)));
237     ProcessPacket(addr, 1, "foo");
238
239     EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr))
240         .WillOnce(testing::Return(CreateSession(
241                       &dispatcher_, 2, addr, &session2_, &eps_)));
242     ProcessPacket(addr, 2, "bar");
243
244     blocked_list_ = dispatcher_.write_blocked_list();
245   }
246
247   virtual void TearDown() {
248     EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
249     EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
250     dispatcher_.Shutdown();
251   }
252
253   bool SetBlocked() {
254     QuicDispatcherPeer::SetWriteBlocked(&dispatcher_);
255     return true;
256   }
257
258  protected:
259   QuicDispatcher::WriteBlockedList* blocked_list_;
260 };
261
262 TEST_F(QuicWriteBlockedListTest, BasicOnCanWrite) {
263   // No OnCanWrite calls because no connections are blocked.
264   dispatcher_.OnCanWrite();
265
266   // Register connection 1 for events, and make sure it's nofitied.
267   blocked_list_->insert(make_pair(connection1(), true));
268   EXPECT_CALL(*connection1(), OnCanWrite());
269   dispatcher_.OnCanWrite();
270
271   // It should get only one notification.
272   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
273   EXPECT_FALSE(dispatcher_.OnCanWrite());
274 }
275
276 TEST_F(QuicWriteBlockedListTest, OnCanWriteOrder) {
277   // Make sure we handle events in order.
278   InSequence s;
279   blocked_list_->insert(make_pair(connection1(), true));
280   blocked_list_->insert(make_pair(connection2(), true));
281   EXPECT_CALL(*connection1(), OnCanWrite());
282   EXPECT_CALL(*connection2(), OnCanWrite());
283   dispatcher_.OnCanWrite();
284
285   // Check the other ordering.
286   blocked_list_->insert(make_pair(connection2(), true));
287   blocked_list_->insert(make_pair(connection1(), true));
288   EXPECT_CALL(*connection2(), OnCanWrite());
289   EXPECT_CALL(*connection1(), OnCanWrite());
290   dispatcher_.OnCanWrite();
291 }
292
293 TEST_F(QuicWriteBlockedListTest, OnCanWriteRemove) {
294   // Add and remove one connction.
295   blocked_list_->insert(make_pair(connection1(), true));
296   blocked_list_->erase(connection1());
297   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
298   dispatcher_.OnCanWrite();
299
300   // Add and remove one connction and make sure it doesn't affect others.
301   blocked_list_->insert(make_pair(connection1(), true));
302   blocked_list_->insert(make_pair(connection2(), true));
303   blocked_list_->erase(connection1());
304   EXPECT_CALL(*connection2(), OnCanWrite());
305   dispatcher_.OnCanWrite();
306
307   // Add it, remove it, and add it back and make sure things are OK.
308   blocked_list_->insert(make_pair(connection1(), true));
309   blocked_list_->erase(connection1());
310   blocked_list_->insert(make_pair(connection1(), true));
311   EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
312   dispatcher_.OnCanWrite();
313 }
314
315 TEST_F(QuicWriteBlockedListTest, DoubleAdd) {
316   // Make sure a double add does not necessitate a double remove.
317   blocked_list_->insert(make_pair(connection1(), true));
318   blocked_list_->insert(make_pair(connection1(), true));
319   blocked_list_->erase(connection1());
320   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
321   dispatcher_.OnCanWrite();
322
323   // Make sure a double add does not result in two OnCanWrite calls.
324   blocked_list_->insert(make_pair(connection1(), true));
325   blocked_list_->insert(make_pair(connection1(), true));
326   EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
327   dispatcher_.OnCanWrite();
328 }
329
330 TEST_F(QuicWriteBlockedListTest, OnCanWriteHandleBlock) {
331   // Finally make sure if we write block on a write call, we stop calling.
332   InSequence s;
333   blocked_list_->insert(make_pair(connection1(), true));
334   blocked_list_->insert(make_pair(connection2(), true));
335   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
336       Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
337   EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
338   dispatcher_.OnCanWrite();
339
340   // And we'll resume where we left off when we get another call.
341   EXPECT_CALL(*connection2(), OnCanWrite());
342   dispatcher_.OnCanWrite();
343 }
344
345 TEST_F(QuicWriteBlockedListTest, LimitedWrites) {
346   // Make sure we call both writers.  The first will register for more writing
347   // but should not be immediately called due to limits.
348   InSequence s;
349   blocked_list_->insert(make_pair(connection1(), true));
350   blocked_list_->insert(make_pair(connection2(), true));
351   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true));
352   EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false));
353   dispatcher_.OnCanWrite();
354
355   // Now call OnCanWrite again, and connection1 should get its second chance
356   EXPECT_CALL(*connection1(), OnCanWrite());
357   dispatcher_.OnCanWrite();
358 }
359
360 TEST_F(QuicWriteBlockedListTest, TestWriteLimits) {
361   // Finally make sure if we write block on a write call, we stop calling.
362   InSequence s;
363   blocked_list_->insert(make_pair(connection1(), true));
364   blocked_list_->insert(make_pair(connection2(), true));
365   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
366       Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
367   EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
368   dispatcher_.OnCanWrite();
369
370   // And we'll resume where we left off when we get another call.
371   EXPECT_CALL(*connection2(), OnCanWrite());
372   dispatcher_.OnCanWrite();
373 }
374
375
376 }  // namespace
377 }  // namespace test
378 }  // namespace tools
379 }  // namespace net