Connect PPAPI IPC channels for non-SFI mode.
[chromium-blink-merge.git] / net / tools / quic / quic_dispatcher_test.cc
blob5ab7b29bdf5f73fec27bb62ea0087685aa327d14
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 QuicGuid guid,
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(QuicGuid guid,
63 QuicDispatcher* dispatcher)
64 : MockConnection(guid, true),
65 dispatcher_(dispatcher) {}
67 void UnregisterOnConnectionClosed() {
68 LOG(ERROR) << "Unregistering " << guid();
69 dispatcher_->OnConnectionClosed(guid(), QUIC_NO_ERROR);
71 private:
72 QuicDispatcher* dispatcher_;
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, _));
87 return *session;
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);
101 virtual ~QuicDispatcherTest() {}
103 MockConnection* connection1() {
104 return reinterpret_cast<MockConnection*>(session1_->connection());
107 MockConnection* connection2() {
108 return reinterpret_cast<MockConnection*>(session2_->connection());
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;
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());
154 void ValidatePacket(const QuicEncryptedPacket& packet) {
155 EXPECT_EQ(data_.length(), packet.AsStringPiece().length());
156 EXPECT_EQ(data_, packet.AsStringPiece());
159 EpollServer eps_;
160 QuicConfig config_;
161 QuicCryptoServerConfig crypto_config_;
162 TestDispatcher dispatcher_;
163 MockSession* session1_;
164 MockSession* session2_;
165 string data_;
168 TEST_F(QuicDispatcherTest, ProcessPackets) {
169 IPEndPoint addr(net::test::Loopback4(), 1);
171 EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, addr))
172 .WillOnce(testing::Return(CreateSession(
173 &dispatcher_, 1, addr, &session1_)));
174 ProcessPacket(addr, 1, true, "foo");
176 EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, addr))
177 .WillOnce(testing::Return(CreateSession(
178 &dispatcher_, 2, addr, &session2_)));
179 ProcessPacket(addr, 2, true, "bar");
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");
188 TEST_F(QuicDispatcherTest, Shutdown) {
189 IPEndPoint addr(net::test::Loopback4(), 1);
191 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
192 .WillOnce(testing::Return(CreateSession(
193 &dispatcher_, 1, addr, &session1_)));
195 ProcessPacket(addr, 1, true, "foo");
197 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
198 SendConnectionClose(QUIC_PEER_GOING_AWAY));
200 dispatcher_.Shutdown();
203 class MockTimeWaitListManager : public QuicTimeWaitListManager {
204 public:
205 MockTimeWaitListManager(QuicPacketWriter* writer,
206 QuicServerSessionVisitor* visitor,
207 EpollServer* eps)
208 : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
211 MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
212 const IPEndPoint& client_address,
213 QuicGuid guid,
214 QuicPacketSequenceNumber sequence_number));
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");
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));
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");
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);
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");
277 class BlockingWriter : public QuicPacketWriterWrapper {
278 public:
279 BlockingWriter() : write_blocked_(false) {}
281 virtual bool IsWriteBlocked() const OVERRIDE { return write_blocked_; }
282 virtual void SetWritable() OVERRIDE { write_blocked_ = false; }
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);
297 bool write_blocked_;
300 class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
301 public:
302 virtual void SetUp() {
303 writer_ = new BlockingWriter;
304 QuicDispatcherPeer::UseWriter(&dispatcher_, writer_);
306 IPEndPoint addr(net::test::Loopback4(), 1);
308 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
309 .WillOnce(testing::Return(CreateSession(
310 &dispatcher_, 1, addr, &session1_)));
311 ProcessPacket(addr, 1, true, "foo");
313 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
314 .WillOnce(testing::Return(CreateSession(
315 &dispatcher_, 2, addr, &session2_)));
316 ProcessPacket(addr, 2, true, "bar");
318 blocked_list_ = dispatcher_.write_blocked_list();
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();
327 void SetBlocked() {
328 writer_->write_blocked_ = true;
331 void BlockConnection2() {
332 writer_->write_blocked_ = true;
333 dispatcher_.OnWriteBlocked(connection2());
336 protected:
337 BlockingWriter* writer_;
338 QuicDispatcher::WriteBlockedList* blocked_list_;
341 TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
342 // No OnCanWrite calls because no connections are blocked.
343 dispatcher_.OnCanWrite();
345 // Register connection 1 for events, and make sure it's notified.
346 SetBlocked();
347 dispatcher_.OnWriteBlocked(connection1());
348 EXPECT_CALL(*connection1(), OnCanWrite());
349 dispatcher_.OnCanWrite();
351 // It should get only one notification.
352 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
353 dispatcher_.OnCanWrite();
354 EXPECT_FALSE(dispatcher_.HasPendingWrites());
357 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
358 // Make sure we handle events in order.
359 InSequence s;
360 SetBlocked();
361 dispatcher_.OnWriteBlocked(connection1());
362 dispatcher_.OnWriteBlocked(connection2());
363 EXPECT_CALL(*connection1(), OnCanWrite());
364 EXPECT_CALL(*connection2(), OnCanWrite());
365 dispatcher_.OnCanWrite();
367 // Check the other ordering.
368 SetBlocked();
369 dispatcher_.OnWriteBlocked(connection2());
370 dispatcher_.OnWriteBlocked(connection1());
371 EXPECT_CALL(*connection2(), OnCanWrite());
372 EXPECT_CALL(*connection1(), OnCanWrite());
373 dispatcher_.OnCanWrite();
376 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
377 // Add and remove one connction.
378 SetBlocked();
379 dispatcher_.OnWriteBlocked(connection1());
380 blocked_list_->erase(connection1());
381 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
382 dispatcher_.OnCanWrite();
384 // Add and remove one connction and make sure it doesn't affect others.
385 SetBlocked();
386 dispatcher_.OnWriteBlocked(connection1());
387 dispatcher_.OnWriteBlocked(connection2());
388 blocked_list_->erase(connection1());
389 EXPECT_CALL(*connection2(), OnCanWrite());
390 dispatcher_.OnCanWrite();
392 // Add it, remove it, and add it back and make sure things are OK.
393 SetBlocked();
394 dispatcher_.OnWriteBlocked(connection1());
395 blocked_list_->erase(connection1());
396 dispatcher_.OnWriteBlocked(connection1());
397 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
398 dispatcher_.OnCanWrite();
401 TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
402 // Make sure a double add does not necessitate a double remove.
403 SetBlocked();
404 dispatcher_.OnWriteBlocked(connection1());
405 dispatcher_.OnWriteBlocked(connection1());
406 blocked_list_->erase(connection1());
407 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
408 dispatcher_.OnCanWrite();
410 // Make sure a double add does not result in two OnCanWrite calls.
411 SetBlocked();
412 dispatcher_.OnWriteBlocked(connection1());
413 dispatcher_.OnWriteBlocked(connection1());
414 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
415 dispatcher_.OnCanWrite();
418 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
419 // Finally make sure if we write block on a write call, we stop calling.
420 InSequence s;
421 SetBlocked();
422 dispatcher_.OnWriteBlocked(connection1());
423 dispatcher_.OnWriteBlocked(connection2());
424 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
425 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
426 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
427 dispatcher_.OnCanWrite();
429 // And we'll resume where we left off when we get another call.
430 EXPECT_CALL(*connection2(), OnCanWrite());
431 dispatcher_.OnCanWrite();
434 TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
435 // Make sure we call both writers. The first will register for more writing
436 // but should not be immediately called due to limits.
437 InSequence s;
438 SetBlocked();
439 dispatcher_.OnWriteBlocked(connection1());
440 dispatcher_.OnWriteBlocked(connection2());
441 EXPECT_CALL(*connection1(), OnCanWrite());
442 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(
443 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
444 dispatcher_.OnCanWrite();
445 EXPECT_TRUE(dispatcher_.HasPendingWrites());
447 // Now call OnCanWrite again, and connection1 should get its second chance
448 EXPECT_CALL(*connection2(), OnCanWrite());
449 dispatcher_.OnCanWrite();
450 EXPECT_FALSE(dispatcher_.HasPendingWrites());
453 TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
454 // Finally make sure if we write block on a write call, we stop calling.
455 InSequence s;
456 SetBlocked();
457 dispatcher_.OnWriteBlocked(connection1());
458 dispatcher_.OnWriteBlocked(connection2());
459 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
460 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
461 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
462 dispatcher_.OnCanWrite();
463 EXPECT_TRUE(dispatcher_.HasPendingWrites());
465 // And we'll resume where we left off when we get another call.
466 EXPECT_CALL(*connection2(), OnCanWrite());
467 dispatcher_.OnCanWrite();
468 EXPECT_FALSE(dispatcher_.HasPendingWrites());
471 } // namespace
472 } // namespace test
473 } // namespace tools
474 } // namespace net