Land Recent QUIC Changes.
[chromium-blink-merge.git] / net / tools / quic / quic_dispatcher_test.cc
blobe894e1b52005cb5735bcd9e29a64284f73b30320
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/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"
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;
36 namespace net {
37 namespace tools {
38 namespace test {
39 namespace {
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) {
49 MOCK_METHOD3(CreateQuicSession, QuicSession*(
50 QuicConnectionId connection_id,
51 const IPEndPoint& server_address,
52 const IPEndPoint& client_address));
53 using QuicDispatcher::write_blocked_list;
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(QuicConnectionId connection_id,
63 QuicDispatcher* dispatcher)
64 : MockConnection(connection_id, true),
65 dispatcher_(dispatcher) {}
67 void UnregisterOnConnectionClosed() {
68 LOG(ERROR) << "Unregistering " << connection_id();
69 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR);
71 private:
72 QuicDispatcher* dispatcher_;
75 QuicSession* CreateSession(QuicDispatcher* dispatcher,
76 QuicConnectionId connection_id,
77 const IPEndPoint& addr,
78 MockSession** session) {
79 MockServerConnection* connection =
80 new MockServerConnection(connection_id, dispatcher);
81 *session = new MockSession(connection);
82 ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
83 WithoutArgs(Invoke(
84 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
85 EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
86 ProcessUdpPacket(_, addr, _));
88 return *session;
91 class QuicDispatcherTest : public ::testing::Test {
92 public:
93 QuicDispatcherTest()
94 : crypto_config_(QuicCryptoServerConfig::TESTING,
95 QuicRandom::GetInstance()),
96 dispatcher_(config_, crypto_config_, &eps_),
97 session1_(NULL),
98 session2_(NULL) {
99 dispatcher_.Initialize(1);
102 virtual ~QuicDispatcherTest() {}
104 MockConnection* connection1() {
105 return reinterpret_cast<MockConnection*>(session1_->connection());
108 MockConnection* connection2() {
109 return reinterpret_cast<MockConnection*>(session2_->connection());
112 QuicEncryptedPacket* ConstructEncryptedPacket(
113 QuicConnectionId connection_id,
114 bool version_flag,
115 bool reset_flag,
116 QuicPacketSequenceNumber sequence_number,
117 const string& data) {
118 QuicPacketHeader header;
119 header.public_header.connection_id = connection_id;
120 header.public_header.connection_id_length = PACKET_8BYTE_CONNECTION_ID;
121 header.public_header.version_flag = version_flag;
122 header.public_header.reset_flag = reset_flag;
123 header.public_header.sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER;
124 header.packet_sequence_number = sequence_number;
125 header.entropy_flag = false;
126 header.entropy_hash = 0;
127 header.fec_flag = false;
128 header.is_in_fec_group = NOT_IN_FEC_GROUP;
129 header.fec_group = 0;
130 QuicStreamFrame stream_frame(1, false, 0, MakeIOVector(data));
131 QuicFrame frame(&stream_frame);
132 QuicFrames frames;
133 frames.push_back(frame);
134 QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
135 scoped_ptr<QuicPacket> packet(
136 framer.BuildUnsizedDataPacket(header, frames).packet);
137 EXPECT_TRUE(packet != NULL);
138 QuicEncryptedPacket* encrypted = framer.EncryptPacket(ENCRYPTION_NONE,
139 sequence_number,
140 *packet);
141 EXPECT_TRUE(encrypted != NULL);
142 data_ = string(encrypted->data(), encrypted->length());
143 return encrypted;
146 void ProcessPacket(IPEndPoint addr,
147 QuicConnectionId connection_id,
148 bool has_version_flag,
149 const string& data) {
150 scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
151 connection_id, has_version_flag, false, 1, data));
152 dispatcher_.ProcessPacket(IPEndPoint(), addr, *packet.get());
155 void ValidatePacket(const QuicEncryptedPacket& packet) {
156 EXPECT_EQ(data_.length(), packet.AsStringPiece().length());
157 EXPECT_EQ(data_, packet.AsStringPiece());
160 EpollServer eps_;
161 QuicConfig config_;
162 QuicCryptoServerConfig crypto_config_;
163 TestDispatcher dispatcher_;
164 MockSession* session1_;
165 MockSession* session2_;
166 string data_;
169 TEST_F(QuicDispatcherTest, ProcessPackets) {
170 IPEndPoint addr(net::test::Loopback4(), 1);
172 EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, addr))
173 .WillOnce(testing::Return(CreateSession(
174 &dispatcher_, 1, addr, &session1_)));
175 ProcessPacket(addr, 1, true, "foo");
177 EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, addr))
178 .WillOnce(testing::Return(CreateSession(
179 &dispatcher_, 2, addr, &session2_)));
180 ProcessPacket(addr, 2, true, "bar");
182 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
183 ProcessUdpPacket(_, _, _)).Times(1).
184 WillOnce(testing::WithArgs<2>(Invoke(
185 this, &QuicDispatcherTest::ValidatePacket)));
186 ProcessPacket(addr, 1, false, "eep");
189 TEST_F(QuicDispatcherTest, Shutdown) {
190 IPEndPoint addr(net::test::Loopback4(), 1);
192 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
193 .WillOnce(testing::Return(CreateSession(
194 &dispatcher_, 1, addr, &session1_)));
196 ProcessPacket(addr, 1, true, "foo");
198 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
199 SendConnectionClose(QUIC_PEER_GOING_AWAY));
201 dispatcher_.Shutdown();
204 class MockTimeWaitListManager : public QuicTimeWaitListManager {
205 public:
206 MockTimeWaitListManager(QuicPacketWriter* writer,
207 QuicServerSessionVisitor* visitor,
208 EpollServer* eps)
209 : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
212 MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
213 const IPEndPoint& client_address,
214 QuicConnectionId connection_id,
215 QuicPacketSequenceNumber sequence_number));
218 TEST_F(QuicDispatcherTest, TimeWaitListManager) {
219 MockTimeWaitListManager* time_wait_list_manager =
220 new MockTimeWaitListManager(
221 QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
222 // dispatcher takes the ownership of time_wait_list_manager.
223 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
224 time_wait_list_manager);
225 // Create a new session.
226 IPEndPoint addr(net::test::Loopback4(), 1);
227 QuicConnectionId connection_id = 1;
228 EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, addr))
229 .WillOnce(testing::Return(CreateSession(
230 &dispatcher_, connection_id, addr, &session1_)));
231 ProcessPacket(addr, connection_id, true, "foo");
233 // Close the connection by sending public reset packet.
234 QuicPublicResetPacket packet;
235 packet.public_header.connection_id = connection_id;
236 packet.public_header.reset_flag = true;
237 packet.public_header.version_flag = false;
238 packet.rejected_sequence_number = 19191;
239 packet.nonce_proof = 132232;
240 scoped_ptr<QuicEncryptedPacket> encrypted(
241 QuicFramer::BuildPublicResetPacket(packet));
242 EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
243 .WillOnce(WithoutArgs(Invoke(
244 reinterpret_cast<MockServerConnection*>(session1_->connection()),
245 &MockServerConnection::UnregisterOnConnectionClosed)));
246 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
247 ProcessUdpPacket(_, _, _))
248 .WillOnce(Invoke(
249 reinterpret_cast<MockConnection*>(session1_->connection()),
250 &MockConnection::ReallyProcessUdpPacket));
251 dispatcher_.ProcessPacket(IPEndPoint(), addr, *encrypted);
252 EXPECT_TRUE(time_wait_list_manager->IsConnectionIdInTimeWait(connection_id));
254 // Dispatcher forwards subsequent packets for this connection_id to the time
255 // wait list manager.
256 EXPECT_CALL(*time_wait_list_manager,
257 ProcessPacket(_, _, connection_id, _)).Times(1);
258 ProcessPacket(addr, connection_id, true, "foo");
261 TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
262 MockTimeWaitListManager* time_wait_list_manager =
263 new MockTimeWaitListManager(
264 QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
265 // dispatcher takes the ownership of time_wait_list_manager.
266 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
267 time_wait_list_manager);
269 IPEndPoint addr(net::test::Loopback4(), 1);
270 QuicConnectionId connection_id = 1;
271 // Dispatcher forwards all packets for this connection_id to the time wait
272 // list manager.
273 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
274 EXPECT_CALL(*time_wait_list_manager,
275 ProcessPacket(_, _, connection_id, _)).Times(1);
276 string data = "foo";
277 ProcessPacket(addr, connection_id, false, "foo");
280 class BlockingWriter : public QuicPacketWriterWrapper {
281 public:
282 BlockingWriter() : write_blocked_(false) {}
284 virtual bool IsWriteBlocked() const OVERRIDE { return write_blocked_; }
285 virtual void SetWritable() OVERRIDE { write_blocked_ = false; }
287 virtual WriteResult WritePacket(
288 const char* buffer,
289 size_t buf_len,
290 const IPAddressNumber& self_address,
291 const IPEndPoint& peer_address) OVERRIDE {
292 if (write_blocked_) {
293 return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
294 } else {
295 return QuicPacketWriterWrapper::WritePacket(
296 buffer, buf_len, self_address, peer_address);
300 bool write_blocked_;
303 class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
304 public:
305 virtual void SetUp() {
306 writer_ = new BlockingWriter;
307 QuicDispatcherPeer::UseWriter(&dispatcher_, writer_);
309 IPEndPoint addr(net::test::Loopback4(), 1);
311 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
312 .WillOnce(testing::Return(CreateSession(
313 &dispatcher_, 1, addr, &session1_)));
314 ProcessPacket(addr, 1, true, "foo");
316 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
317 .WillOnce(testing::Return(CreateSession(
318 &dispatcher_, 2, addr, &session2_)));
319 ProcessPacket(addr, 2, true, "bar");
321 blocked_list_ = dispatcher_.write_blocked_list();
324 virtual void TearDown() {
325 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
326 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
327 dispatcher_.Shutdown();
330 void SetBlocked() {
331 writer_->write_blocked_ = true;
334 void BlockConnection2() {
335 writer_->write_blocked_ = true;
336 dispatcher_.OnWriteBlocked(connection2());
339 protected:
340 BlockingWriter* writer_;
341 QuicDispatcher::WriteBlockedList* blocked_list_;
344 TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
345 // No OnCanWrite calls because no connections are blocked.
346 dispatcher_.OnCanWrite();
348 // Register connection 1 for events, and make sure it's notified.
349 SetBlocked();
350 dispatcher_.OnWriteBlocked(connection1());
351 EXPECT_CALL(*connection1(), OnCanWrite());
352 dispatcher_.OnCanWrite();
354 // It should get only one notification.
355 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
356 dispatcher_.OnCanWrite();
357 EXPECT_FALSE(dispatcher_.HasPendingWrites());
360 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
361 // Make sure we handle events in order.
362 InSequence s;
363 SetBlocked();
364 dispatcher_.OnWriteBlocked(connection1());
365 dispatcher_.OnWriteBlocked(connection2());
366 EXPECT_CALL(*connection1(), OnCanWrite());
367 EXPECT_CALL(*connection2(), OnCanWrite());
368 dispatcher_.OnCanWrite();
370 // Check the other ordering.
371 SetBlocked();
372 dispatcher_.OnWriteBlocked(connection2());
373 dispatcher_.OnWriteBlocked(connection1());
374 EXPECT_CALL(*connection2(), OnCanWrite());
375 EXPECT_CALL(*connection1(), OnCanWrite());
376 dispatcher_.OnCanWrite();
379 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
380 // Add and remove one connction.
381 SetBlocked();
382 dispatcher_.OnWriteBlocked(connection1());
383 blocked_list_->erase(connection1());
384 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
385 dispatcher_.OnCanWrite();
387 // Add and remove one connction and make sure it doesn't affect others.
388 SetBlocked();
389 dispatcher_.OnWriteBlocked(connection1());
390 dispatcher_.OnWriteBlocked(connection2());
391 blocked_list_->erase(connection1());
392 EXPECT_CALL(*connection2(), OnCanWrite());
393 dispatcher_.OnCanWrite();
395 // Add it, remove it, and add it back and make sure things are OK.
396 SetBlocked();
397 dispatcher_.OnWriteBlocked(connection1());
398 blocked_list_->erase(connection1());
399 dispatcher_.OnWriteBlocked(connection1());
400 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
401 dispatcher_.OnCanWrite();
404 TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
405 // Make sure a double add does not necessitate a double remove.
406 SetBlocked();
407 dispatcher_.OnWriteBlocked(connection1());
408 dispatcher_.OnWriteBlocked(connection1());
409 blocked_list_->erase(connection1());
410 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
411 dispatcher_.OnCanWrite();
413 // Make sure a double add does not result in two OnCanWrite calls.
414 SetBlocked();
415 dispatcher_.OnWriteBlocked(connection1());
416 dispatcher_.OnWriteBlocked(connection1());
417 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
418 dispatcher_.OnCanWrite();
421 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
422 // Finally make sure if we write block on a write call, we stop calling.
423 InSequence s;
424 SetBlocked();
425 dispatcher_.OnWriteBlocked(connection1());
426 dispatcher_.OnWriteBlocked(connection2());
427 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
428 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
429 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
430 dispatcher_.OnCanWrite();
432 // And we'll resume where we left off when we get another call.
433 EXPECT_CALL(*connection2(), OnCanWrite());
434 dispatcher_.OnCanWrite();
437 TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
438 // Make sure we call both writers. The first will register for more writing
439 // but should not be immediately called due to limits.
440 InSequence s;
441 SetBlocked();
442 dispatcher_.OnWriteBlocked(connection1());
443 dispatcher_.OnWriteBlocked(connection2());
444 EXPECT_CALL(*connection1(), OnCanWrite());
445 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(
446 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
447 dispatcher_.OnCanWrite();
448 EXPECT_TRUE(dispatcher_.HasPendingWrites());
450 // Now call OnCanWrite again, and connection1 should get its second chance
451 EXPECT_CALL(*connection2(), OnCanWrite());
452 dispatcher_.OnCanWrite();
453 EXPECT_FALSE(dispatcher_.HasPendingWrites());
456 TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
457 // Finally make sure if we write block on a write call, we stop calling.
458 InSequence s;
459 SetBlocked();
460 dispatcher_.OnWriteBlocked(connection1());
461 dispatcher_.OnWriteBlocked(connection2());
462 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
463 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
464 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
465 dispatcher_.OnCanWrite();
466 EXPECT_TRUE(dispatcher_.HasPendingWrites());
468 // And we'll resume where we left off when we get another call.
469 EXPECT_CALL(*connection2(), OnCanWrite());
470 dispatcher_.OnCanWrite();
471 EXPECT_FALSE(dispatcher_.HasPendingWrites());
474 } // namespace
475 } // namespace test
476 } // namespace tools
477 } // namespace net