Land Recent QUIC changes.
[chromium-blink-merge.git] / net / tools / quic / quic_dispatcher_test.cc
blob0d7407acf9f2c7fcc387703411ca3aa3c90a5f76
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.
5 #include "net/tools/quic/quic_dispatcher.h"
7 #include <string>
9 #include "base/strings/string_piece.h"
10 #include "net/quic/crypto/crypto_handshake.h"
11 #include "net/quic/crypto/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"
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;
34 namespace net {
35 namespace tools {
36 namespace test {
37 namespace {
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, 1, eps) {}
46 MOCK_METHOD4(CreateQuicSession, QuicSession*(
47 QuicGuid guid,
48 const IPEndPoint& client_address,
49 int fd,
50 EpollServer* eps));
51 using QuicDispatcher::write_blocked_list;
54 // A Connection class which unregisters the session from the dispatcher
55 // when sending connection close.
56 // It'd be slightly more realistic to do this from the Session but it would
57 // involve a lot more mocking.
58 class MockServerConnection : public MockConnection {
59 public:
60 MockServerConnection(QuicGuid guid,
61 IPEndPoint address,
62 int fd,
63 EpollServer* eps,
64 QuicDispatcher* dispatcher)
65 : MockConnection(guid, address, fd, eps, true),
66 dispatcher_(dispatcher) {
68 void UnregisterOnConnectionClose() {
69 LOG(ERROR) << "Unregistering " << guid();
70 dispatcher_->OnConnectionClose(guid(), QUIC_NO_ERROR);
72 private:
73 QuicDispatcher* dispatcher_;
76 QuicSession* CreateSession(QuicDispatcher* dispatcher,
77 QuicGuid guid,
78 const IPEndPoint& addr,
79 MockSession** session,
80 EpollServer* eps) {
81 MockServerConnection* connection =
82 new MockServerConnection(guid, addr, 0, eps, dispatcher);
83 *session = new MockSession(connection, true);
84 ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
85 WithoutArgs(Invoke(
86 connection, &MockServerConnection::UnregisterOnConnectionClose)));
87 EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
88 ProcessUdpPacket(_, addr, _));
90 return *session;
93 class QuicDispatcherTest : public ::testing::Test {
94 public:
95 QuicDispatcherTest()
96 : crypto_config_(QuicCryptoServerConfig::TESTING,
97 QuicRandom::GetInstance()),
98 dispatcher_(config_, crypto_config_, &eps_),
99 session1_(NULL),
100 session2_(NULL) {
103 virtual ~QuicDispatcherTest() {}
105 MockConnection* connection1() {
106 return reinterpret_cast<MockConnection*>(session1_->connection());
109 MockConnection* connection2() {
110 return reinterpret_cast<MockConnection*>(session2_->connection());
113 void ProcessPacket(IPEndPoint addr,
114 QuicGuid guid,
115 const string& data) {
116 QuicEncryptedPacket packet(data.data(), data.length());
117 dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, packet);
120 void ValidatePacket(const QuicEncryptedPacket& packet) {
121 EXPECT_TRUE(packet.AsStringPiece().find(data_) != StringPiece::npos);
124 IPAddressNumber Loopback4() {
125 net::IPAddressNumber addr;
126 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr));
127 return addr;
130 EpollServer eps_;
131 QuicConfig config_;
132 QuicCryptoServerConfig crypto_config_;
133 TestDispatcher dispatcher_;
134 MockSession* session1_;
135 MockSession* session2_;
136 string data_;
139 TEST_F(QuicDispatcherTest, ProcessPackets) {
140 IPEndPoint addr(Loopback4(), 1);
142 EXPECT_CALL(dispatcher_, CreateQuicSession(1, addr, _, &eps_))
143 .WillOnce(testing::Return(CreateSession(
144 &dispatcher_, 1, addr, &session1_, &eps_)));
145 ProcessPacket(addr, 1, "foo");
147 EXPECT_CALL(dispatcher_, CreateQuicSession(2, addr, _, &eps_))
148 .WillOnce(testing::Return(CreateSession(
149 &dispatcher_, 2, addr, &session2_, &eps_)));
150 ProcessPacket(addr, 2, "bar");
152 data_ = "eep";
153 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
154 ProcessUdpPacket(_, _, _)).Times(1).
155 WillOnce(testing::WithArgs<2>(Invoke(
156 this, &QuicDispatcherTest::ValidatePacket)));
157 ProcessPacket(addr, 1, "eep");
160 TEST_F(QuicDispatcherTest, Shutdown) {
161 IPEndPoint addr(Loopback4(), 1);
163 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
164 .WillOnce(testing::Return(CreateSession(
165 &dispatcher_, 1, addr, &session1_, &eps_)));
167 ProcessPacket(addr, 1, "foo");
169 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
170 SendConnectionClose(QUIC_PEER_GOING_AWAY));
172 dispatcher_.Shutdown();
175 class MockTimeWaitListManager : public QuicTimeWaitListManager {
176 public:
177 MockTimeWaitListManager(QuicPacketWriter* writer,
178 EpollServer* eps)
179 : QuicTimeWaitListManager(writer, eps) {
182 MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
183 const IPEndPoint& client_address,
184 QuicGuid guid,
185 const QuicEncryptedPacket& packet));
188 TEST_F(QuicDispatcherTest, TimeWaitListManager) {
189 MockTimeWaitListManager* time_wait_list_manager =
190 new MockTimeWaitListManager(
191 QuicDispatcherPeer::GetWriter(&dispatcher_), &eps_);
192 // dispatcher takes the ownership of time_wait_list_manager.
193 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
194 time_wait_list_manager);
195 // Create a new session.
196 IPEndPoint addr(Loopback4(), 1);
197 QuicGuid guid = 1;
198 EXPECT_CALL(dispatcher_, CreateQuicSession(guid, addr, _, &eps_))
199 .WillOnce(testing::Return(CreateSession(
200 &dispatcher_, guid, addr, &session1_, &eps_)));
201 ProcessPacket(addr, guid, "foo");
203 // Close the connection by sending public reset packet.
204 QuicPublicResetPacket packet;
205 packet.public_header.guid = guid;
206 packet.public_header.reset_flag = true;
207 packet.public_header.version_flag = false;
208 packet.rejected_sequence_number = 19191;
209 packet.nonce_proof = 132232;
210 scoped_ptr<QuicEncryptedPacket> encrypted(
211 QuicFramer::BuildPublicResetPacket(packet));
212 EXPECT_CALL(*session1_, ConnectionClose(QUIC_PUBLIC_RESET, true)).Times(1)
213 .WillOnce(WithoutArgs(Invoke(
214 reinterpret_cast<MockServerConnection*>(session1_->connection()),
215 &MockServerConnection::UnregisterOnConnectionClose)));
216 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
217 ProcessUdpPacket(_, _, _))
218 .WillOnce(Invoke(
219 reinterpret_cast<MockConnection*>(session1_->connection()),
220 &MockConnection::ReallyProcessUdpPacket));
221 dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, *encrypted);
222 EXPECT_TRUE(time_wait_list_manager->IsGuidInTimeWait(guid));
224 // Dispatcher forwards subsequent packets for this guid to the time wait list
225 // manager.
226 EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
227 ProcessPacket(addr, guid, "foo");
230 class QuicWriteBlockedListTest : public QuicDispatcherTest {
231 public:
232 virtual void SetUp() {
233 IPEndPoint addr(Loopback4(), 1);
235 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
236 .WillOnce(testing::Return(CreateSession(
237 &dispatcher_, 1, addr, &session1_, &eps_)));
238 ProcessPacket(addr, 1, "foo");
240 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
241 .WillOnce(testing::Return(CreateSession(
242 &dispatcher_, 2, addr, &session2_, &eps_)));
243 ProcessPacket(addr, 2, "bar");
245 blocked_list_ = dispatcher_.write_blocked_list();
248 virtual void TearDown() {
249 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
250 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
251 dispatcher_.Shutdown();
254 bool SetBlocked() {
255 QuicDispatcherPeer::SetWriteBlocked(&dispatcher_);
256 return true;
259 protected:
260 QuicDispatcher::WriteBlockedList* blocked_list_;
263 TEST_F(QuicWriteBlockedListTest, BasicOnCanWrite) {
264 // No OnCanWrite calls because no connections are blocked.
265 dispatcher_.OnCanWrite();
267 // Register connection 1 for events, and make sure it's nofitied.
268 blocked_list_->insert(make_pair(connection1(), true));
269 EXPECT_CALL(*connection1(), OnCanWrite());
270 dispatcher_.OnCanWrite();
272 // It should get only one notification.
273 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
274 EXPECT_FALSE(dispatcher_.OnCanWrite());
277 TEST_F(QuicWriteBlockedListTest, OnCanWriteOrder) {
278 // Make sure we handle events in order.
279 InSequence s;
280 blocked_list_->insert(make_pair(connection1(), true));
281 blocked_list_->insert(make_pair(connection2(), true));
282 EXPECT_CALL(*connection1(), OnCanWrite());
283 EXPECT_CALL(*connection2(), OnCanWrite());
284 dispatcher_.OnCanWrite();
286 // Check the other ordering.
287 blocked_list_->insert(make_pair(connection2(), true));
288 blocked_list_->insert(make_pair(connection1(), true));
289 EXPECT_CALL(*connection2(), OnCanWrite());
290 EXPECT_CALL(*connection1(), OnCanWrite());
291 dispatcher_.OnCanWrite();
294 TEST_F(QuicWriteBlockedListTest, OnCanWriteRemove) {
295 // Add and remove one connction.
296 blocked_list_->insert(make_pair(connection1(), true));
297 blocked_list_->erase(connection1());
298 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
299 dispatcher_.OnCanWrite();
301 // Add and remove one connction and make sure it doesn't affect others.
302 blocked_list_->insert(make_pair(connection1(), true));
303 blocked_list_->insert(make_pair(connection2(), true));
304 blocked_list_->erase(connection1());
305 EXPECT_CALL(*connection2(), OnCanWrite());
306 dispatcher_.OnCanWrite();
308 // Add it, remove it, and add it back and make sure things are OK.
309 blocked_list_->insert(make_pair(connection1(), true));
310 blocked_list_->erase(connection1());
311 blocked_list_->insert(make_pair(connection1(), true));
312 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
313 dispatcher_.OnCanWrite();
316 TEST_F(QuicWriteBlockedListTest, DoubleAdd) {
317 // Make sure a double add does not necessitate a double remove.
318 blocked_list_->insert(make_pair(connection1(), true));
319 blocked_list_->insert(make_pair(connection1(), true));
320 blocked_list_->erase(connection1());
321 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
322 dispatcher_.OnCanWrite();
324 // Make sure a double add does not result in two OnCanWrite calls.
325 blocked_list_->insert(make_pair(connection1(), true));
326 blocked_list_->insert(make_pair(connection1(), true));
327 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
328 dispatcher_.OnCanWrite();
331 TEST_F(QuicWriteBlockedListTest, OnCanWriteHandleBlock) {
332 // Finally make sure if we write block on a write call, we stop calling.
333 InSequence s;
334 blocked_list_->insert(make_pair(connection1(), true));
335 blocked_list_->insert(make_pair(connection2(), true));
336 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
337 Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
338 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
339 dispatcher_.OnCanWrite();
341 // And we'll resume where we left off when we get another call.
342 EXPECT_CALL(*connection2(), OnCanWrite());
343 dispatcher_.OnCanWrite();
346 TEST_F(QuicWriteBlockedListTest, LimitedWrites) {
347 // Make sure we call both writers. The first will register for more writing
348 // but should not be immediately called due to limits.
349 InSequence s;
350 blocked_list_->insert(make_pair(connection1(), true));
351 blocked_list_->insert(make_pair(connection2(), true));
352 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true));
353 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false));
354 dispatcher_.OnCanWrite();
356 // Now call OnCanWrite again, and connection1 should get its second chance
357 EXPECT_CALL(*connection1(), OnCanWrite());
358 dispatcher_.OnCanWrite();
361 TEST_F(QuicWriteBlockedListTest, TestWriteLimits) {
362 // Finally make sure if we write block on a write call, we stop calling.
363 InSequence s;
364 blocked_list_->insert(make_pair(connection1(), true));
365 blocked_list_->insert(make_pair(connection2(), true));
366 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
367 Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
368 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
369 dispatcher_.OnCanWrite();
371 // And we'll resume where we left off when we get another call.
372 EXPECT_CALL(*connection2(), OnCanWrite());
373 dispatcher_.OnCanWrite();
377 } // namespace
378 } // namespace test
379 } // namespace tools
380 } // namespace net