Upstream version 5.34.104.0
[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/quic_utils.h"
15 #include "net/quic/test_tools/quic_test_utils.h"
16 #include "net/tools/epoll_server/epoll_server.h"
17 #include "net/tools/quic/quic_packet_writer_wrapper.h"
18 #include "net/tools/quic/quic_time_wait_list_manager.h"
19 #include "net/tools/quic/test_tools/quic_dispatcher_peer.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 base::StringPiece;
25 using net::EpollServer;
26 using net::test::MockSession;
27 using net::tools::test::MockConnection;
28 using std::make_pair;
29 using testing::_;
30 using testing::DoAll;
31 using testing::Invoke;
32 using testing::InSequence;
33 using testing::Return;
34 using testing::WithoutArgs;
35
36 namespace net {
37 namespace tools {
38 namespace test {
39 namespace {
40
41 class TestDispatcher : public QuicDispatcher {
42  public:
43   explicit TestDispatcher(const QuicConfig& config,
44                           const QuicCryptoServerConfig& crypto_config,
45                           EpollServer* eps)
46       : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), eps) {
47   }
48
49   MOCK_METHOD3(CreateQuicSession, QuicSession*(
50       QuicGuid guid,
51       const IPEndPoint& server_address,
52       const IPEndPoint& client_address));
53   using QuicDispatcher::write_blocked_list;
54 };
55
56 // A Connection class which unregisters the session from the dispatcher
57 // when sending connection close.
58 // It'd be slightly more realistic to do this from the Session but it would
59 // involve a lot more mocking.
60 class MockServerConnection : public MockConnection {
61  public:
62   MockServerConnection(QuicGuid guid,
63                        QuicDispatcher* dispatcher)
64       : MockConnection(guid, 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   MockServerConnection* connection = new MockServerConnection(guid, dispatcher);
80   *session = new MockSession(connection);
81   ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
82       WithoutArgs(Invoke(
83           connection, &MockServerConnection::UnregisterOnConnectionClosed)));
84   EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
85               ProcessUdpPacket(_, addr, _));
86
87   return *session;
88 }
89
90 class QuicDispatcherTest : public ::testing::Test {
91  public:
92   QuicDispatcherTest()
93       : crypto_config_(QuicCryptoServerConfig::TESTING,
94                        QuicRandom::GetInstance()),
95         dispatcher_(config_, crypto_config_, &eps_),
96         session1_(NULL),
97         session2_(NULL) {
98     dispatcher_.Initialize(1);
99   }
100
101   virtual ~QuicDispatcherTest() {}
102
103   MockConnection* connection1() {
104     return reinterpret_cast<MockConnection*>(session1_->connection());
105   }
106
107   MockConnection* connection2() {
108     return reinterpret_cast<MockConnection*>(session2_->connection());
109   }
110
111   QuicEncryptedPacket* ConstructEncryptedPacket(
112       QuicGuid guid,
113       bool version_flag,
114       bool reset_flag,
115       QuicPacketSequenceNumber sequence_number,
116       const string& data) {
117     QuicPacketHeader header;
118     header.public_header.guid = guid;
119     header.public_header.guid_length = PACKET_8BYTE_GUID;
120     header.public_header.version_flag = version_flag;
121     header.public_header.reset_flag = reset_flag;
122     header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER;
123     header.packet_sequence_number = sequence_number;
124     header.entropy_flag = false;
125     header.entropy_hash = 0;
126     header.fec_flag = false;
127     header.is_in_fec_group = NOT_IN_FEC_GROUP;
128     header.fec_group = 0;
129     QuicStreamFrame stream_frame(1, false, 0, MakeIOVector(data));
130     QuicFrame frame(&stream_frame);
131     QuicFrames frames;
132     frames.push_back(frame);
133     QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
134     scoped_ptr<QuicPacket> packet(
135         framer.BuildUnsizedDataPacket(header, frames).packet);
136     EXPECT_TRUE(packet != NULL);
137     QuicEncryptedPacket* encrypted = framer.EncryptPacket(ENCRYPTION_NONE,
138                                                           sequence_number,
139                                                           *packet);
140     EXPECT_TRUE(encrypted != NULL);
141     data_ = string(encrypted->data(), encrypted->length());
142     return encrypted;
143   }
144
145   void ProcessPacket(IPEndPoint addr,
146                      QuicGuid guid,
147                      bool has_version_flag,
148                      const string& data) {
149     scoped_ptr<QuicEncryptedPacket> packet(
150         ConstructEncryptedPacket(guid, has_version_flag, false, 1, data));
151     dispatcher_.ProcessPacket(IPEndPoint(), addr, *packet.get());
152   }
153
154   void ValidatePacket(const QuicEncryptedPacket& packet) {
155     EXPECT_EQ(data_.length(), packet.AsStringPiece().length());
156     EXPECT_EQ(data_, packet.AsStringPiece());
157   }
158
159   EpollServer eps_;
160   QuicConfig config_;
161   QuicCryptoServerConfig crypto_config_;
162   TestDispatcher dispatcher_;
163   MockSession* session1_;
164   MockSession* session2_;
165   string data_;
166 };
167
168 TEST_F(QuicDispatcherTest, ProcessPackets) {
169   IPEndPoint addr(net::test::Loopback4(), 1);
170
171   EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, addr))
172       .WillOnce(testing::Return(CreateSession(
173           &dispatcher_, 1, addr, &session1_)));
174   ProcessPacket(addr, 1, true, "foo");
175
176   EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, addr))
177       .WillOnce(testing::Return(CreateSession(
178                     &dispatcher_, 2, addr, &session2_)));
179   ProcessPacket(addr, 2, true, "bar");
180
181   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
182               ProcessUdpPacket(_, _, _)).Times(1).
183       WillOnce(testing::WithArgs<2>(Invoke(
184           this, &QuicDispatcherTest::ValidatePacket)));
185   ProcessPacket(addr, 1, false, "eep");
186 }
187
188 TEST_F(QuicDispatcherTest, Shutdown) {
189   IPEndPoint addr(net::test::Loopback4(), 1);
190
191   EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
192       .WillOnce(testing::Return(CreateSession(
193                     &dispatcher_, 1, addr, &session1_)));
194
195   ProcessPacket(addr, 1, true, "foo");
196
197   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
198               SendConnectionClose(QUIC_PEER_GOING_AWAY));
199
200   dispatcher_.Shutdown();
201 }
202
203 class MockTimeWaitListManager : public QuicTimeWaitListManager {
204  public:
205   MockTimeWaitListManager(QuicPacketWriter* writer,
206                           QuicServerSessionVisitor* visitor,
207                           EpollServer* eps)
208       : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
209   }
210
211   MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
212                                    const IPEndPoint& client_address,
213                                    QuicGuid guid,
214                                    QuicPacketSequenceNumber sequence_number));
215 };
216
217 TEST_F(QuicDispatcherTest, TimeWaitListManager) {
218   MockTimeWaitListManager* time_wait_list_manager =
219       new MockTimeWaitListManager(
220           QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
221   // dispatcher takes the ownership of time_wait_list_manager.
222   QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
223                                              time_wait_list_manager);
224   // Create a new session.
225   IPEndPoint addr(net::test::Loopback4(), 1);
226   QuicGuid guid = 1;
227   EXPECT_CALL(dispatcher_, CreateQuicSession(guid, _, addr))
228       .WillOnce(testing::Return(CreateSession(
229                     &dispatcher_, guid, addr, &session1_)));
230   ProcessPacket(addr, guid, true, "foo");
231
232   // Close the connection by sending public reset packet.
233   QuicPublicResetPacket packet;
234   packet.public_header.guid = guid;
235   packet.public_header.reset_flag = true;
236   packet.public_header.version_flag = false;
237   packet.rejected_sequence_number = 19191;
238   packet.nonce_proof = 132232;
239   scoped_ptr<QuicEncryptedPacket> encrypted(
240       QuicFramer::BuildPublicResetPacket(packet));
241   EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
242       .WillOnce(WithoutArgs(Invoke(
243           reinterpret_cast<MockServerConnection*>(session1_->connection()),
244           &MockServerConnection::UnregisterOnConnectionClosed)));
245   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
246               ProcessUdpPacket(_, _, _))
247       .WillOnce(Invoke(
248           reinterpret_cast<MockConnection*>(session1_->connection()),
249           &MockConnection::ReallyProcessUdpPacket));
250   dispatcher_.ProcessPacket(IPEndPoint(), addr, *encrypted);
251   EXPECT_TRUE(time_wait_list_manager->IsGuidInTimeWait(guid));
252
253   // Dispatcher forwards subsequent packets for this guid to the time wait list
254   // manager.
255   EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
256   ProcessPacket(addr, guid, true, "foo");
257 }
258
259 TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
260   MockTimeWaitListManager* time_wait_list_manager =
261       new MockTimeWaitListManager(
262           QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
263   // dispatcher takes the ownership of time_wait_list_manager.
264   QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
265                                              time_wait_list_manager);
266
267   IPEndPoint addr(net::test::Loopback4(), 1);
268   QuicGuid guid = 1;
269   // Dispatcher forwards all packets for this guid to the time wait list
270   // manager.
271   EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
272   EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
273   string data = "foo";
274   ProcessPacket(addr, guid, false, "foo");
275 }
276
277 class BlockingWriter : public QuicPacketWriterWrapper {
278  public:
279   BlockingWriter() : write_blocked_(false) {}
280
281   virtual bool IsWriteBlocked() const OVERRIDE { return write_blocked_; }
282   virtual void SetWritable() OVERRIDE { write_blocked_ = false; }
283
284   virtual WriteResult WritePacket(
285       const char* buffer,
286       size_t buf_len,
287       const IPAddressNumber& self_address,
288       const IPEndPoint& peer_address) OVERRIDE {
289     if (write_blocked_) {
290       return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
291     } else {
292       return QuicPacketWriterWrapper::WritePacket(
293           buffer, buf_len, self_address, peer_address);
294     }
295   }
296
297   bool write_blocked_;
298 };
299
300 class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
301  public:
302   virtual void SetUp() {
303     writer_ = new BlockingWriter;
304     QuicDispatcherPeer::UseWriter(&dispatcher_, writer_);
305
306     IPEndPoint addr(net::test::Loopback4(), 1);
307
308     EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
309         .WillOnce(testing::Return(CreateSession(
310                       &dispatcher_, 1, addr, &session1_)));
311     ProcessPacket(addr, 1, true, "foo");
312
313     EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
314         .WillOnce(testing::Return(CreateSession(
315                       &dispatcher_, 2, addr, &session2_)));
316     ProcessPacket(addr, 2, true, "bar");
317
318     blocked_list_ = dispatcher_.write_blocked_list();
319   }
320
321   virtual void TearDown() {
322     EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
323     EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
324     dispatcher_.Shutdown();
325   }
326
327   bool SetBlocked() {
328     writer_->write_blocked_ = true;
329     return true;
330   }
331
332  protected:
333   BlockingWriter* writer_;
334   QuicDispatcher::WriteBlockedList* blocked_list_;
335 };
336
337 TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
338   // No OnCanWrite calls because no connections are blocked.
339   dispatcher_.OnCanWrite();
340
341   // Register connection 1 for events, and make sure it's notified.
342   SetBlocked();
343   dispatcher_.OnWriteBlocked(connection1());
344   EXPECT_CALL(*connection1(), OnCanWrite());
345   dispatcher_.OnCanWrite();
346
347   // It should get only one notification.
348   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
349   EXPECT_FALSE(dispatcher_.OnCanWrite());
350 }
351
352 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
353   // Make sure we handle events in order.
354   InSequence s;
355   SetBlocked();
356   dispatcher_.OnWriteBlocked(connection1());
357   dispatcher_.OnWriteBlocked(connection2());
358   EXPECT_CALL(*connection1(), OnCanWrite());
359   EXPECT_CALL(*connection2(), OnCanWrite());
360   dispatcher_.OnCanWrite();
361
362   // Check the other ordering.
363   SetBlocked();
364   dispatcher_.OnWriteBlocked(connection2());
365   dispatcher_.OnWriteBlocked(connection1());
366   EXPECT_CALL(*connection2(), OnCanWrite());
367   EXPECT_CALL(*connection1(), OnCanWrite());
368   dispatcher_.OnCanWrite();
369 }
370
371 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
372   // Add and remove one connction.
373   SetBlocked();
374   dispatcher_.OnWriteBlocked(connection1());
375   blocked_list_->erase(connection1());
376   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
377   dispatcher_.OnCanWrite();
378
379   // Add and remove one connction and make sure it doesn't affect others.
380   SetBlocked();
381   dispatcher_.OnWriteBlocked(connection1());
382   dispatcher_.OnWriteBlocked(connection2());
383   blocked_list_->erase(connection1());
384   EXPECT_CALL(*connection2(), OnCanWrite());
385   dispatcher_.OnCanWrite();
386
387   // Add it, remove it, and add it back and make sure things are OK.
388   SetBlocked();
389   dispatcher_.OnWriteBlocked(connection1());
390   blocked_list_->erase(connection1());
391   dispatcher_.OnWriteBlocked(connection1());
392   EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
393   dispatcher_.OnCanWrite();
394 }
395
396 TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
397   // Make sure a double add does not necessitate a double remove.
398   SetBlocked();
399   dispatcher_.OnWriteBlocked(connection1());
400   dispatcher_.OnWriteBlocked(connection1());
401   blocked_list_->erase(connection1());
402   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
403   dispatcher_.OnCanWrite();
404
405   // Make sure a double add does not result in two OnCanWrite calls.
406   SetBlocked();
407   dispatcher_.OnWriteBlocked(connection1());
408   dispatcher_.OnWriteBlocked(connection1());
409   EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
410   dispatcher_.OnCanWrite();
411 }
412
413 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
414   // Finally make sure if we write block on a write call, we stop calling.
415   InSequence s;
416   SetBlocked();
417   dispatcher_.OnWriteBlocked(connection1());
418   dispatcher_.OnWriteBlocked(connection2());
419   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
420       Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
421   EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
422   dispatcher_.OnCanWrite();
423
424   // And we'll resume where we left off when we get another call.
425   EXPECT_CALL(*connection2(), OnCanWrite());
426   dispatcher_.OnCanWrite();
427 }
428
429 TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
430   // Make sure we call both writers.  The first will register for more writing
431   // but should not be immediately called due to limits.
432   InSequence s;
433   SetBlocked();
434   dispatcher_.OnWriteBlocked(connection1());
435   dispatcher_.OnWriteBlocked(connection2());
436   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true));
437   EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false));
438   dispatcher_.OnCanWrite();
439
440   // Now call OnCanWrite again, and connection1 should get its second chance
441   EXPECT_CALL(*connection1(), OnCanWrite());
442   dispatcher_.OnCanWrite();
443 }
444
445 TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
446   // Finally make sure if we write block on a write call, we stop calling.
447   InSequence s;
448   SetBlocked();
449   dispatcher_.OnWriteBlocked(connection1());
450   dispatcher_.OnWriteBlocked(connection2());
451   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
452       Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
453   EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
454   dispatcher_.OnCanWrite();
455
456   // And we'll resume where we left off when we get another call.
457   EXPECT_CALL(*connection2(), OnCanWrite());
458   dispatcher_.OnCanWrite();
459 }
460
461 }  // namespace
462 }  // namespace test
463 }  // namespace tools
464 }  // namespace net