Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: net/tools/quic/quic_dispatcher_test.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/tools/quic/quic_dispatcher.cc ('k') | net/tools/quic/quic_epoll_clock.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_flags.h"
15 #include "net/quic/quic_utils.h"
16 #include "net/quic/test_tools/quic_test_utils.h"
17 #include "net/tools/epoll_server/epoll_server.h"
18 #include "net/tools/quic/quic_packet_writer_wrapper.h"
19 #include "net/tools/quic/quic_time_wait_list_manager.h"
20 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
21 #include "net/tools/quic/test_tools/quic_test_utils.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using base::StringPiece;
26 using net::EpollServer;
27 using net::test::ConstructEncryptedPacket;
28 using net::test::MockSession;
29 using net::test::ValueRestore;
30 using net::tools::test::MockConnection;
31 using std::make_pair;
32 using std::string;
33 using testing::DoAll;
34 using testing::InSequence;
35 using testing::Invoke;
36 using testing::WithoutArgs;
37 using testing::_;
38
39 namespace net {
40 namespace tools {
41 namespace test {
42 namespace {
43
44 class TestDispatcher : public QuicDispatcher {
45 public:
46 explicit TestDispatcher(const QuicConfig& config,
47 const QuicCryptoServerConfig& crypto_config,
48 EpollServer* eps)
49 : QuicDispatcher(config,
50 crypto_config,
51 QuicSupportedVersions(),
52 new QuicDispatcher::DefaultPacketWriterFactory(),
53 eps) {
54 }
55
56 MOCK_METHOD3(CreateQuicSession, QuicSession*(
57 QuicConnectionId connection_id,
58 const IPEndPoint& server_address,
59 const IPEndPoint& client_address));
60
61 using QuicDispatcher::current_server_address;
62 using QuicDispatcher::current_client_address;
63 };
64
65 // A Connection class which unregisters the session from the dispatcher
66 // when sending connection close.
67 // It'd be slightly more realistic to do this from the Session but it would
68 // involve a lot more mocking.
69 class MockServerConnection : public MockConnection {
70 public:
71 MockServerConnection(QuicConnectionId connection_id,
72 QuicDispatcher* dispatcher)
73 : MockConnection(connection_id, true),
74 dispatcher_(dispatcher) {}
75
76 void UnregisterOnConnectionClosed() {
77 LOG(ERROR) << "Unregistering " << connection_id();
78 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR);
79 }
80 private:
81 QuicDispatcher* dispatcher_;
82 };
83
84 QuicSession* CreateSession(QuicDispatcher* dispatcher,
85 QuicConnectionId connection_id,
86 const IPEndPoint& client_address,
87 MockSession** session) {
88 MockServerConnection* connection =
89 new MockServerConnection(connection_id, dispatcher);
90 *session = new MockSession(connection);
91 ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
92 WithoutArgs(Invoke(
93 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
94 EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
95 ProcessUdpPacket(_, client_address, _));
96
97 return *session;
98 }
99
100 class MockTimeWaitListManager : public QuicTimeWaitListManager {
101 public:
102 MockTimeWaitListManager(QuicPacketWriter* writer,
103 QuicServerSessionVisitor* visitor,
104 EpollServer* eps)
105 : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
106 }
107
108 MOCK_METHOD5(ProcessPacket,
109 void(const IPEndPoint& server_address,
110 const IPEndPoint& client_address,
111 QuicConnectionId connection_id,
112 QuicPacketSequenceNumber sequence_number,
113 const QuicEncryptedPacket& packet));
114 };
115
116 class QuicDispatcherTest : public ::testing::Test {
117 public:
118 QuicDispatcherTest()
119 : crypto_config_(QuicCryptoServerConfig::TESTING,
120 QuicRandom::GetInstance()),
121 dispatcher_(config_, crypto_config_, &eps_),
122 time_wait_list_manager_(nullptr),
123 session1_(nullptr),
124 session2_(nullptr) {
125 dispatcher_.Initialize(1);
126 }
127
128 ~QuicDispatcherTest() override {}
129
130 MockConnection* connection1() {
131 return reinterpret_cast<MockConnection*>(session1_->connection());
132 }
133
134 MockConnection* connection2() {
135 return reinterpret_cast<MockConnection*>(session2_->connection());
136 }
137
138 void ProcessPacket(IPEndPoint client_address,
139 QuicConnectionId connection_id,
140 bool has_version_flag,
141 const string& data) {
142 scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
143 connection_id, has_version_flag, false, 1, data));
144 data_ = string(packet->data(), packet->length());
145 dispatcher_.ProcessPacket(server_address_, client_address, *packet);
146 }
147
148 void ValidatePacket(const QuicEncryptedPacket& packet) {
149 EXPECT_EQ(data_.length(), packet.AsStringPiece().length());
150 EXPECT_EQ(data_, packet.AsStringPiece());
151 }
152
153 void CreateTimeWaitListManager() {
154 time_wait_list_manager_ = new MockTimeWaitListManager(
155 QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
156 // dispatcher takes the ownership of time_wait_list_manager.
157 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
158 time_wait_list_manager_);
159 }
160
161 EpollServer eps_;
162 QuicConfig config_;
163 QuicCryptoServerConfig crypto_config_;
164 IPEndPoint server_address_;
165 TestDispatcher dispatcher_;
166 MockTimeWaitListManager* time_wait_list_manager_;
167 MockSession* session1_;
168 MockSession* session2_;
169 string data_;
170 };
171
172 TEST_F(QuicDispatcherTest, ProcessPackets) {
173 IPEndPoint client_address(net::test::Loopback4(), 1);
174 IPAddressNumber any4;
175 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
176 server_address_ = IPEndPoint(any4, 5);
177
178 EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address))
179 .WillOnce(testing::Return(CreateSession(
180 &dispatcher_, 1, client_address, &session1_)));
181 ProcessPacket(client_address, 1, true, "foo");
182 EXPECT_EQ(client_address, dispatcher_.current_client_address());
183 EXPECT_EQ(server_address_, dispatcher_.current_server_address());
184
185
186 EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, client_address))
187 .WillOnce(testing::Return(CreateSession(
188 &dispatcher_, 2, client_address, &session2_)));
189 ProcessPacket(client_address, 2, true, "bar");
190
191 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
192 ProcessUdpPacket(_, _, _)).Times(1).
193 WillOnce(testing::WithArgs<2>(Invoke(
194 this, &QuicDispatcherTest::ValidatePacket)));
195 ProcessPacket(client_address, 1, false, "eep");
196 }
197
198 TEST_F(QuicDispatcherTest, Shutdown) {
199 IPEndPoint client_address(net::test::Loopback4(), 1);
200
201 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
202 .WillOnce(testing::Return(CreateSession(
203 &dispatcher_, 1, client_address, &session1_)));
204
205 ProcessPacket(client_address, 1, true, "foo");
206
207 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
208 SendConnectionClose(QUIC_PEER_GOING_AWAY));
209
210 dispatcher_.Shutdown();
211 }
212
213 TEST_F(QuicDispatcherTest, TimeWaitListManager) {
214 CreateTimeWaitListManager();
215
216 // Create a new session.
217 IPEndPoint client_address(net::test::Loopback4(), 1);
218 QuicConnectionId connection_id = 1;
219 EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, client_address))
220 .WillOnce(testing::Return(CreateSession(
221 &dispatcher_, connection_id, client_address, &session1_)));
222 ProcessPacket(client_address, connection_id, true, "foo");
223
224 // Close the connection by sending public reset packet.
225 QuicPublicResetPacket packet;
226 packet.public_header.connection_id = connection_id;
227 packet.public_header.reset_flag = true;
228 packet.public_header.version_flag = false;
229 packet.rejected_sequence_number = 19191;
230 packet.nonce_proof = 132232;
231 scoped_ptr<QuicEncryptedPacket> encrypted(
232 QuicFramer::BuildPublicResetPacket(packet));
233 EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
234 .WillOnce(WithoutArgs(Invoke(
235 reinterpret_cast<MockServerConnection*>(session1_->connection()),
236 &MockServerConnection::UnregisterOnConnectionClosed)));
237 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
238 ProcessUdpPacket(_, _, _))
239 .WillOnce(Invoke(
240 reinterpret_cast<MockConnection*>(session1_->connection()),
241 &MockConnection::ReallyProcessUdpPacket));
242 dispatcher_.ProcessPacket(IPEndPoint(), client_address, *encrypted);
243 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
244
245 // Dispatcher forwards subsequent packets for this connection_id to the time
246 // wait list manager.
247 EXPECT_CALL(*time_wait_list_manager_,
248 ProcessPacket(_, _, connection_id, _, _)).Times(1);
249 ProcessPacket(client_address, connection_id, true, "foo");
250 }
251
252 TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
253 CreateTimeWaitListManager();
254
255 IPEndPoint client_address(net::test::Loopback4(), 1);
256 QuicConnectionId connection_id = 1;
257 // Dispatcher forwards all packets for this connection_id to the time wait
258 // list manager.
259 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
260 EXPECT_CALL(*time_wait_list_manager_,
261 ProcessPacket(_, _, connection_id, _, _)).Times(1);
262 string data = "foo";
263 ProcessPacket(client_address, connection_id, false, "foo");
264 }
265
266 TEST_F(QuicDispatcherTest, ProcessPacketWithBogusPort) {
267 CreateTimeWaitListManager();
268
269 IPEndPoint client_address(net::test::Loopback4(), 0);
270 IPAddressNumber any4;
271 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
272 server_address_ = IPEndPoint(any4, 5);
273
274 EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address)).Times(0);
275 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
276 ProcessPacket(client_address, 1, true, "foo");
277 EXPECT_EQ(client_address, dispatcher_.current_client_address());
278 EXPECT_EQ(server_address_, dispatcher_.current_server_address());
279 }
280
281 class BlockingWriter : public QuicPacketWriterWrapper {
282 public:
283 BlockingWriter() : write_blocked_(false) {}
284
285 bool IsWriteBlocked() const override { return write_blocked_; }
286 void SetWritable() override { write_blocked_ = false; }
287
288 WriteResult WritePacket(const char* buffer,
289 size_t buf_len,
290 const IPAddressNumber& self_client_address,
291 const IPEndPoint& peer_client_address) override {
292 // It would be quite possible to actually implement this method here with
293 // the fake blocked status, but it would be significantly more work in
294 // Chromium, and since it's not called anyway, don't bother.
295 LOG(DFATAL) << "Not supported";
296 return WriteResult();
297 }
298
299 bool write_blocked_;
300 };
301
302 class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
303 public:
304 void SetUp() override {
305 writer_ = new BlockingWriter;
306 QuicDispatcherPeer::SetPacketWriterFactory(&dispatcher_,
307 new TestWriterFactory());
308 QuicDispatcherPeer::UseWriter(&dispatcher_, writer_);
309
310 IPEndPoint client_address(net::test::Loopback4(), 1);
311
312 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
313 .WillOnce(testing::Return(CreateSession(
314 &dispatcher_, 1, client_address, &session1_)));
315 ProcessPacket(client_address, 1, true, "foo");
316
317 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
318 .WillOnce(testing::Return(CreateSession(
319 &dispatcher_, 2, client_address, &session2_)));
320 ProcessPacket(client_address, 2, true, "bar");
321
322 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(&dispatcher_);
323 }
324
325 void TearDown() override {
326 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
327 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
328 dispatcher_.Shutdown();
329 }
330
331 void SetBlocked() {
332 writer_->write_blocked_ = true;
333 }
334
335 void BlockConnection2() {
336 writer_->write_blocked_ = true;
337 dispatcher_.OnWriteBlocked(connection2());
338 }
339
340 protected:
341 BlockingWriter* writer_;
342 QuicDispatcher::WriteBlockedList* blocked_list_;
343 };
344
345 TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
346 // No OnCanWrite calls because no connections are blocked.
347 dispatcher_.OnCanWrite();
348
349 // Register connection 1 for events, and make sure it's notified.
350 SetBlocked();
351 dispatcher_.OnWriteBlocked(connection1());
352 EXPECT_CALL(*connection1(), OnCanWrite());
353 dispatcher_.OnCanWrite();
354
355 // It should get only one notification.
356 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
357 dispatcher_.OnCanWrite();
358 EXPECT_FALSE(dispatcher_.HasPendingWrites());
359 }
360
361 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
362 // Make sure we handle events in order.
363 InSequence s;
364 SetBlocked();
365 dispatcher_.OnWriteBlocked(connection1());
366 dispatcher_.OnWriteBlocked(connection2());
367 EXPECT_CALL(*connection1(), OnCanWrite());
368 EXPECT_CALL(*connection2(), OnCanWrite());
369 dispatcher_.OnCanWrite();
370
371 // Check the other ordering.
372 SetBlocked();
373 dispatcher_.OnWriteBlocked(connection2());
374 dispatcher_.OnWriteBlocked(connection1());
375 EXPECT_CALL(*connection2(), OnCanWrite());
376 EXPECT_CALL(*connection1(), OnCanWrite());
377 dispatcher_.OnCanWrite();
378 }
379
380 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
381 // Add and remove one connction.
382 SetBlocked();
383 dispatcher_.OnWriteBlocked(connection1());
384 blocked_list_->erase(connection1());
385 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
386 dispatcher_.OnCanWrite();
387
388 // Add and remove one connction and make sure it doesn't affect others.
389 SetBlocked();
390 dispatcher_.OnWriteBlocked(connection1());
391 dispatcher_.OnWriteBlocked(connection2());
392 blocked_list_->erase(connection1());
393 EXPECT_CALL(*connection2(), OnCanWrite());
394 dispatcher_.OnCanWrite();
395
396 // Add it, remove it, and add it back and make sure things are OK.
397 SetBlocked();
398 dispatcher_.OnWriteBlocked(connection1());
399 blocked_list_->erase(connection1());
400 dispatcher_.OnWriteBlocked(connection1());
401 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
402 dispatcher_.OnCanWrite();
403 }
404
405 TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
406 // Make sure a double add does not necessitate a double remove.
407 SetBlocked();
408 dispatcher_.OnWriteBlocked(connection1());
409 dispatcher_.OnWriteBlocked(connection1());
410 blocked_list_->erase(connection1());
411 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
412 dispatcher_.OnCanWrite();
413
414 // Make sure a double add does not result in two OnCanWrite calls.
415 SetBlocked();
416 dispatcher_.OnWriteBlocked(connection1());
417 dispatcher_.OnWriteBlocked(connection1());
418 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
419 dispatcher_.OnCanWrite();
420 }
421
422 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
423 // Finally make sure if we write block on a write call, we stop calling.
424 InSequence s;
425 SetBlocked();
426 dispatcher_.OnWriteBlocked(connection1());
427 dispatcher_.OnWriteBlocked(connection2());
428 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
429 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
430 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
431 dispatcher_.OnCanWrite();
432
433 // And we'll resume where we left off when we get another call.
434 EXPECT_CALL(*connection2(), OnCanWrite());
435 dispatcher_.OnCanWrite();
436 }
437
438 TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
439 // Make sure we call both writers. The first will register for more writing
440 // but should not be immediately called due to limits.
441 InSequence s;
442 SetBlocked();
443 dispatcher_.OnWriteBlocked(connection1());
444 dispatcher_.OnWriteBlocked(connection2());
445 EXPECT_CALL(*connection1(), OnCanWrite());
446 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(
447 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
448 dispatcher_.OnCanWrite();
449 EXPECT_TRUE(dispatcher_.HasPendingWrites());
450
451 // Now call OnCanWrite again, and connection1 should get its second chance
452 EXPECT_CALL(*connection2(), OnCanWrite());
453 dispatcher_.OnCanWrite();
454 EXPECT_FALSE(dispatcher_.HasPendingWrites());
455 }
456
457 TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
458 // Finally make sure if we write block on a write call, we stop calling.
459 InSequence s;
460 SetBlocked();
461 dispatcher_.OnWriteBlocked(connection1());
462 dispatcher_.OnWriteBlocked(connection2());
463 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
464 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
465 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
466 dispatcher_.OnCanWrite();
467 EXPECT_TRUE(dispatcher_.HasPendingWrites());
468
469 // And we'll resume where we left off when we get another call.
470 EXPECT_CALL(*connection2(), OnCanWrite());
471 dispatcher_.OnCanWrite();
472 EXPECT_FALSE(dispatcher_.HasPendingWrites());
473 }
474
475 } // namespace
476 } // namespace test
477 } // namespace tools
478 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/quic/quic_dispatcher.cc ('k') | net/tools/quic/quic_epoll_clock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698