OLD | NEW |
| (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 "content/renderer/p2p/p2p_transport_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/compiler_specific.h" | |
9 #include "base/memory/ref_counted.h" | |
10 #include "base/message_loop.h" | |
11 #include "base/test/test_timeouts.h" | |
12 #include "jingle/glue/fake_network_manager.h" | |
13 #include "jingle/glue/fake_socket_factory.h" | |
14 #include "jingle/glue/thread_wrapper.h" | |
15 #include "net/base/completion_callback.h" | |
16 #include "net/base/io_buffer.h" | |
17 #include "net/base/net_errors.h" | |
18 #include "net/base/net_util.h" | |
19 #include "net/socket/socket.h" | |
20 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 using testing::_; | |
24 using testing::AtMost; | |
25 using testing::Exactly; | |
26 using testing::InvokeWithoutArgs; | |
27 | |
28 using webkit_glue::P2PTransport; | |
29 | |
30 namespace { | |
31 const char kTestAddress1[] = "192.168.15.12"; | |
32 const char kTestAddress2[] = "192.168.15.33"; | |
33 | |
34 const char kTransportName1[] = "tr1"; | |
35 const char kTransportName2[] = "tr2"; | |
36 | |
37 // Send 10 packets 10 bytes each. Packets are sent with 10ms delay | |
38 // between packets (about 100 ms for 10 messages). | |
39 const int kMessageSize = 10; | |
40 const int kMessages = 10; | |
41 const int kUdpWriteDelayMs = 10; | |
42 const int kTcpDataSize = 10 * 1024; | |
43 const int kTcpWriteDelayMs = 1; | |
44 | |
45 class UdpChannelTester : public base::RefCountedThreadSafe<UdpChannelTester> { | |
46 public: | |
47 UdpChannelTester(MessageLoop* message_loop, | |
48 net::Socket* write_socket, | |
49 net::Socket* read_socket) | |
50 : message_loop_(message_loop), | |
51 write_socket_(write_socket), | |
52 read_socket_(read_socket), | |
53 done_(false), | |
54 write_errors_(0), | |
55 read_errors_(0), | |
56 packets_sent_(0), | |
57 packets_received_(0), | |
58 broken_packets_(0) { | |
59 } | |
60 | |
61 void Start() { | |
62 message_loop_->PostTask( | |
63 FROM_HERE, base::Bind(&UdpChannelTester::DoStart, this)); | |
64 } | |
65 | |
66 void CheckResults() { | |
67 EXPECT_EQ(0, write_errors_); | |
68 EXPECT_EQ(0, read_errors_); | |
69 | |
70 EXPECT_EQ(0, broken_packets_); | |
71 | |
72 // Verify that we've received at least one packet. | |
73 EXPECT_GT(packets_received_, 0); | |
74 LOG(INFO) << "Received " << packets_received_ << " packets out of " | |
75 << kMessages; | |
76 } | |
77 | |
78 protected: | |
79 friend class base::RefCountedThreadSafe<UdpChannelTester>; | |
80 virtual ~UdpChannelTester() {} | |
81 | |
82 void Done() { | |
83 done_ = true; | |
84 message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
85 } | |
86 | |
87 void DoStart() { | |
88 DoRead(); | |
89 DoWrite(); | |
90 } | |
91 | |
92 void DoWrite() { | |
93 if (packets_sent_ >= kMessages) { | |
94 Done(); | |
95 return; | |
96 } | |
97 | |
98 scoped_refptr<net::IOBuffer> packet(new net::IOBuffer(kMessageSize)); | |
99 memset(packet->data(), 123, kMessageSize); | |
100 sent_packets_[packets_sent_] = packet; | |
101 // Put index of this packet in the beginning of the packet body. | |
102 memcpy(packet->data(), &packets_sent_, sizeof(packets_sent_)); | |
103 | |
104 int result = write_socket_->Write(packet, kMessageSize, | |
105 base::Bind(&UdpChannelTester::OnWritten, | |
106 base::Unretained(this))); | |
107 HandleWriteResult(result); | |
108 } | |
109 | |
110 void OnWritten(int result) { | |
111 HandleWriteResult(result); | |
112 } | |
113 | |
114 void HandleWriteResult(int result) { | |
115 if (result <= 0 && result != net::ERR_IO_PENDING) { | |
116 LOG(ERROR) << "Received error " << result << " when trying to write"; | |
117 write_errors_++; | |
118 Done(); | |
119 } else if (result > 0) { | |
120 EXPECT_EQ(kMessageSize, result); | |
121 packets_sent_++; | |
122 message_loop_->PostDelayedTask( | |
123 FROM_HERE, base::Bind(&UdpChannelTester::DoWrite, this), | |
124 base::TimeDelta::FromMilliseconds(kUdpWriteDelayMs)); | |
125 } | |
126 } | |
127 | |
128 void DoRead() { | |
129 int result = 1; | |
130 while (result > 0) { | |
131 int kReadSize = kMessageSize * 2; | |
132 read_buffer_ = new net::IOBuffer(kReadSize); | |
133 | |
134 result = read_socket_->Read(read_buffer_, kReadSize, | |
135 base::Bind(&UdpChannelTester::OnRead, | |
136 base::Unretained(this))); | |
137 HandleReadResult(result); | |
138 }; | |
139 } | |
140 | |
141 void OnRead(int result) { | |
142 HandleReadResult(result); | |
143 DoRead(); | |
144 } | |
145 | |
146 void HandleReadResult(int result) { | |
147 if (result <= 0 && result != net::ERR_IO_PENDING) { | |
148 // Error will be received after the socket is closed. | |
149 if (!done_) { | |
150 LOG(ERROR) << "Received error " << result << " when trying to read"; | |
151 read_errors_++; | |
152 Done(); | |
153 } | |
154 } else if (result > 0) { | |
155 packets_received_++; | |
156 if (kMessageSize != result) { | |
157 // Invalid packet size; | |
158 broken_packets_++; | |
159 } else { | |
160 // Validate packet body. | |
161 int packet_id; | |
162 memcpy(&packet_id, read_buffer_->data(), sizeof(packet_id)); | |
163 if (packet_id < 0 || packet_id >= kMessages) { | |
164 broken_packets_++; | |
165 } else { | |
166 if (memcmp(read_buffer_->data(), sent_packets_[packet_id]->data(), | |
167 kMessageSize) != 0) | |
168 broken_packets_++; | |
169 } | |
170 } | |
171 } | |
172 } | |
173 | |
174 private: | |
175 MessageLoop* message_loop_; | |
176 net::Socket* write_socket_; | |
177 net::Socket* read_socket_; | |
178 bool done_; | |
179 | |
180 scoped_refptr<net::IOBuffer> sent_packets_[kMessages]; | |
181 scoped_refptr<net::IOBuffer> read_buffer_; | |
182 | |
183 int write_errors_; | |
184 int read_errors_; | |
185 int packets_sent_; | |
186 int packets_received_; | |
187 int broken_packets_; | |
188 }; | |
189 | |
190 class TcpChannelTester : public base::RefCountedThreadSafe<TcpChannelTester> { | |
191 public: | |
192 TcpChannelTester(MessageLoop* message_loop, | |
193 net::Socket* write_socket, | |
194 net::Socket* read_socket) | |
195 : message_loop_(message_loop), | |
196 write_socket_(write_socket), | |
197 read_socket_(read_socket), | |
198 done_(false), | |
199 write_errors_(0), | |
200 read_errors_(0) { | |
201 } | |
202 | |
203 void Init() { | |
204 // Initialize |send_buffer_|. | |
205 send_buffer_ = new net::DrainableIOBuffer(new net::IOBuffer(kTcpDataSize), | |
206 kTcpDataSize); | |
207 for (int i = 0; i < kTcpDataSize; ++i) { | |
208 send_buffer_->data()[i] = rand() % 256; | |
209 } | |
210 } | |
211 | |
212 void StartRead() { | |
213 message_loop_->PostTask( | |
214 FROM_HERE, base::Bind(&TcpChannelTester::DoRead, this)); | |
215 } | |
216 | |
217 void StartWrite() { | |
218 message_loop_->PostTask( | |
219 FROM_HERE, base::Bind(&TcpChannelTester::DoWrite, this)); | |
220 } | |
221 | |
222 void CheckResults() { | |
223 EXPECT_EQ(0, write_errors_); | |
224 EXPECT_EQ(0, read_errors_); | |
225 | |
226 EXPECT_EQ(0, send_buffer_->BytesRemaining()); | |
227 | |
228 send_buffer_->SetOffset(0); | |
229 EXPECT_EQ(kTcpDataSize, static_cast<int>(received_data_.size())); | |
230 EXPECT_EQ(0, memcmp(send_buffer_->data(), | |
231 &received_data_[0], received_data_.size())); | |
232 } | |
233 | |
234 protected: | |
235 friend class base::RefCountedThreadSafe<TcpChannelTester>; | |
236 virtual ~TcpChannelTester() {} | |
237 | |
238 void Done() { | |
239 done_ = true; | |
240 message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
241 } | |
242 | |
243 void DoWrite() { | |
244 if (send_buffer_->BytesRemaining() == 0) { | |
245 return; | |
246 } | |
247 | |
248 int result = write_socket_->Write( | |
249 send_buffer_, send_buffer_->BytesRemaining(), | |
250 base::Bind(&TcpChannelTester::OnWritten, base::Unretained(this))); | |
251 HandleWriteResult(result); | |
252 } | |
253 | |
254 void OnWritten(int result) { | |
255 HandleWriteResult(result); | |
256 } | |
257 | |
258 void HandleWriteResult(int result) { | |
259 if (result <= 0 && result != net::ERR_IO_PENDING) { | |
260 LOG(ERROR) << "Received error " << result << " when trying to write"; | |
261 write_errors_++; | |
262 Done(); | |
263 } else if (result > 0) { | |
264 send_buffer_->DidConsume(result); | |
265 message_loop_->PostDelayedTask( | |
266 FROM_HERE, base::Bind(&TcpChannelTester::DoWrite, this), | |
267 base::TimeDelta::FromMilliseconds(kTcpWriteDelayMs)); | |
268 } | |
269 } | |
270 | |
271 void DoRead() { | |
272 int result = 1; | |
273 while (result > 0) { | |
274 int kReadSize = kMessageSize * 2; | |
275 read_buffer_ = new net::IOBuffer(kReadSize); | |
276 | |
277 result = read_socket_->Read( | |
278 read_buffer_, kReadSize, | |
279 base::Bind(&TcpChannelTester::OnRead, base::Unretained(this))); | |
280 HandleReadResult(result); | |
281 }; | |
282 } | |
283 | |
284 void OnRead(int result) { | |
285 HandleReadResult(result); | |
286 DoRead(); | |
287 } | |
288 | |
289 void HandleReadResult(int result) { | |
290 if (result <= 0 && result != net::ERR_IO_PENDING) { | |
291 // Error will be received after the socket is closed. | |
292 if (!done_) { | |
293 LOG(ERROR) << "Received error " << result << " when trying to read"; | |
294 read_errors_++; | |
295 Done(); | |
296 } | |
297 } else if (result > 0) { | |
298 received_data_.insert(received_data_.end(), read_buffer_->data(), | |
299 read_buffer_->data() + result); | |
300 if (static_cast<int>(received_data_.size()) == kTcpDataSize) | |
301 Done(); | |
302 } | |
303 } | |
304 | |
305 private: | |
306 MessageLoop* message_loop_; | |
307 net::Socket* write_socket_; | |
308 net::Socket* read_socket_; | |
309 bool done_; | |
310 | |
311 scoped_refptr<net::DrainableIOBuffer> send_buffer_; | |
312 scoped_refptr<net::IOBuffer> read_buffer_; | |
313 | |
314 std::vector<char> sent_data_; | |
315 std::vector<char> received_data_; | |
316 | |
317 int write_errors_; | |
318 int read_errors_; | |
319 }; | |
320 | |
321 } // namespace | |
322 | |
323 namespace content { | |
324 | |
325 class MockP2PEventHandler : public P2PTransport::EventHandler { | |
326 public: | |
327 MOCK_METHOD1(OnCandidateReady, void(const std::string& address)); | |
328 MOCK_METHOD1(OnStateChange, void(P2PTransport::State state)); | |
329 MOCK_METHOD1(OnError, void(int error)); | |
330 }; | |
331 | |
332 class P2PTransportImplTest : public testing::Test { | |
333 public: | |
334 void DestroyTransport() { | |
335 transport1_.reset(); | |
336 transport2_.reset(); | |
337 } | |
338 | |
339 protected: | |
340 virtual void SetUp() OVERRIDE { | |
341 socket_manager_ = new jingle_glue::FakeSocketManager(); | |
342 | |
343 net::IPAddressNumber ip; | |
344 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestAddress1, &ip)); | |
345 transport1_.reset(new P2PTransportImpl( | |
346 new jingle_glue::FakeNetworkManager(ip), | |
347 new jingle_glue::FakeSocketFactory(socket_manager_, ip))); | |
348 | |
349 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestAddress2, &ip)); | |
350 transport2_.reset(new P2PTransportImpl( | |
351 new jingle_glue::FakeNetworkManager(ip), | |
352 new jingle_glue::FakeSocketFactory(socket_manager_, ip))); | |
353 } | |
354 | |
355 virtual void TearDown() OVERRIDE { | |
356 DestroyTransport(); | |
357 message_loop_.RunAllPending(); | |
358 } | |
359 | |
360 void Init(P2PTransport::Protocol protocol) { | |
361 P2PTransport::Config config; | |
362 ASSERT_TRUE(transport1_->Init( | |
363 NULL, kTransportName1, protocol, config, &event_handler1_)); | |
364 ASSERT_TRUE(transport2_->Init( | |
365 NULL, kTransportName2, protocol, config, &event_handler2_)); | |
366 } | |
367 | |
368 MessageLoop message_loop_; | |
369 | |
370 scoped_refptr<jingle_glue::FakeSocketManager> socket_manager_; | |
371 scoped_ptr<P2PTransportImpl> transport1_; | |
372 MockP2PEventHandler event_handler1_; | |
373 scoped_ptr<P2PTransportImpl> transport2_; | |
374 MockP2PEventHandler event_handler2_; | |
375 }; | |
376 | |
377 TEST_F(P2PTransportImplTest, Create) { | |
378 Init(P2PTransport::PROTOCOL_UDP); | |
379 | |
380 EXPECT_CALL(event_handler1_, OnCandidateReady(_)); | |
381 EXPECT_CALL(event_handler2_, OnCandidateReady(_)); | |
382 | |
383 message_loop_.RunAllPending(); | |
384 } | |
385 | |
386 ACTION_P(AddRemoteCandidate, transport) { | |
387 EXPECT_TRUE(transport->AddRemoteCandidate(arg0)); | |
388 } | |
389 | |
390 TEST_F(P2PTransportImplTest, ConnectUdp) { | |
391 Init(P2PTransport::PROTOCOL_UDP); | |
392 | |
393 EXPECT_CALL(event_handler1_, OnCandidateReady(_)).WillRepeatedly( | |
394 AddRemoteCandidate(transport2_.get())); | |
395 EXPECT_CALL(event_handler2_, OnCandidateReady(_)).WillRepeatedly( | |
396 AddRemoteCandidate(transport1_.get())); | |
397 | |
398 message_loop_.RunAllPending(); | |
399 } | |
400 | |
401 TEST_F(P2PTransportImplTest, ConnectTcp) { | |
402 Init(P2PTransport::PROTOCOL_TCP); | |
403 | |
404 EXPECT_CALL(event_handler1_, OnCandidateReady(_)).WillRepeatedly( | |
405 AddRemoteCandidate(transport2_.get())); | |
406 EXPECT_CALL(event_handler2_, OnCandidateReady(_)).WillRepeatedly( | |
407 AddRemoteCandidate(transport1_.get())); | |
408 | |
409 message_loop_.RunAllPending(); | |
410 } | |
411 | |
412 TEST_F(P2PTransportImplTest, SendDataUdp) { | |
413 Init(P2PTransport::PROTOCOL_UDP); | |
414 | |
415 EXPECT_CALL(event_handler1_, OnCandidateReady(_)).WillRepeatedly( | |
416 AddRemoteCandidate(transport2_.get())); | |
417 EXPECT_CALL(event_handler2_, OnCandidateReady(_)).WillRepeatedly( | |
418 AddRemoteCandidate(transport1_.get())); | |
419 | |
420 // Transport may first become ether readable or writable, but | |
421 // eventually it must be readable and writable. | |
422 EXPECT_CALL(event_handler1_, OnStateChange(P2PTransport::STATE_READABLE)) | |
423 .Times(AtMost(1)); | |
424 EXPECT_CALL(event_handler1_, OnStateChange(P2PTransport::STATE_WRITABLE)) | |
425 .Times(AtMost(1)); | |
426 EXPECT_CALL(event_handler1_, OnStateChange( | |
427 static_cast<P2PTransport::State>(P2PTransport::STATE_READABLE | | |
428 P2PTransport::STATE_WRITABLE))) | |
429 .Times(Exactly(1)); | |
430 | |
431 EXPECT_CALL(event_handler2_, OnStateChange(P2PTransport::STATE_READABLE)) | |
432 .Times(AtMost(1)); | |
433 EXPECT_CALL(event_handler2_, OnStateChange(P2PTransport::STATE_WRITABLE)) | |
434 .Times(AtMost(1)); | |
435 EXPECT_CALL(event_handler2_, OnStateChange( | |
436 static_cast<P2PTransport::State>(P2PTransport::STATE_READABLE | | |
437 P2PTransport::STATE_WRITABLE))) | |
438 .Times(Exactly(1)); | |
439 | |
440 scoped_refptr<UdpChannelTester> channel_tester = new UdpChannelTester( | |
441 &message_loop_, transport1_->GetChannel(), transport2_->GetChannel()); | |
442 | |
443 message_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | |
444 TestTimeouts::action_max_timeout()); | |
445 | |
446 channel_tester->Start(); | |
447 message_loop_.Run(); | |
448 channel_tester->CheckResults(); | |
449 } | |
450 | |
451 TEST_F(P2PTransportImplTest, SendDataTcp) { | |
452 Init(P2PTransport::PROTOCOL_TCP); | |
453 | |
454 EXPECT_CALL(event_handler1_, OnCandidateReady(_)).WillRepeatedly( | |
455 AddRemoteCandidate(transport2_.get())); | |
456 EXPECT_CALL(event_handler2_, OnCandidateReady(_)).WillRepeatedly( | |
457 AddRemoteCandidate(transport1_.get())); | |
458 | |
459 scoped_refptr<TcpChannelTester> channel_tester = new TcpChannelTester( | |
460 &message_loop_, transport1_->GetChannel(), transport2_->GetChannel()); | |
461 | |
462 // Transport may first become ether readable or writable, but | |
463 // eventually it must be readable and writable. | |
464 EXPECT_CALL(event_handler1_, OnStateChange(P2PTransport::STATE_READABLE)) | |
465 .Times(AtMost(1)); | |
466 EXPECT_CALL(event_handler1_, OnStateChange(P2PTransport::STATE_WRITABLE)) | |
467 .Times(AtMost(1)); | |
468 EXPECT_CALL(event_handler1_, OnStateChange( | |
469 static_cast<P2PTransport::State>(P2PTransport::STATE_READABLE | | |
470 P2PTransport::STATE_WRITABLE))) | |
471 .Times(Exactly(1)) | |
472 .WillOnce(InvokeWithoutArgs(channel_tester.get(), | |
473 &TcpChannelTester::StartWrite)) | |
474 .RetiresOnSaturation(); | |
475 | |
476 EXPECT_CALL(event_handler2_, OnStateChange(P2PTransport::STATE_READABLE)) | |
477 .Times(AtMost(1)); | |
478 EXPECT_CALL(event_handler2_, OnStateChange(P2PTransport::STATE_WRITABLE)) | |
479 .Times(AtMost(1)); | |
480 EXPECT_CALL(event_handler2_, OnStateChange( | |
481 static_cast<P2PTransport::State>(P2PTransport::STATE_READABLE | | |
482 P2PTransport::STATE_WRITABLE))) | |
483 .Times(Exactly(1)) | |
484 .WillOnce(InvokeWithoutArgs(channel_tester.get(), | |
485 &TcpChannelTester::StartRead)) | |
486 .RetiresOnSaturation(); | |
487 | |
488 message_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | |
489 TestTimeouts::action_max_timeout()); | |
490 | |
491 channel_tester->Init(); | |
492 message_loop_.Run(); | |
493 channel_tester->CheckResults(); | |
494 } | |
495 | |
496 TEST_F(P2PTransportImplTest, DeleteFromCallback) { | |
497 Init(P2PTransport::PROTOCOL_TCP); | |
498 | |
499 EXPECT_CALL(event_handler1_, OnCandidateReady(_)).WillRepeatedly( | |
500 AddRemoteCandidate(transport2_.get())); | |
501 EXPECT_CALL(event_handler2_, OnCandidateReady(_)).WillRepeatedly( | |
502 AddRemoteCandidate(transport1_.get())); | |
503 | |
504 // Transport may first become ether readable or writable, but | |
505 // eventually it must be readable and writable. | |
506 EXPECT_CALL(event_handler1_, OnStateChange(P2PTransport::STATE_READABLE)) | |
507 .Times(AtMost(1)); | |
508 EXPECT_CALL(event_handler1_, OnStateChange(P2PTransport::STATE_WRITABLE)) | |
509 .Times(AtMost(1)); | |
510 EXPECT_CALL(event_handler1_, OnStateChange( | |
511 static_cast<P2PTransport::State>(P2PTransport::STATE_READABLE | | |
512 P2PTransport::STATE_WRITABLE))) | |
513 .Times(AtMost(1)); | |
514 | |
515 EXPECT_CALL(event_handler2_, OnStateChange(P2PTransport::STATE_READABLE)) | |
516 .Times(AtMost(1)); | |
517 EXPECT_CALL(event_handler2_, OnStateChange(P2PTransport::STATE_WRITABLE)) | |
518 .Times(AtMost(1)); | |
519 EXPECT_CALL(event_handler2_, OnStateChange( | |
520 static_cast<P2PTransport::State>(P2PTransport::STATE_READABLE | | |
521 P2PTransport::STATE_WRITABLE))) | |
522 .Times(Exactly(1)) | |
523 .WillOnce(DoAll( | |
524 InvokeWithoutArgs(this, &P2PTransportImplTest::DestroyTransport), | |
525 InvokeWithoutArgs(&message_loop_, &MessageLoop::Quit))); | |
526 | |
527 message_loop_.Run(); | |
528 } | |
529 | |
530 } // namespace content | |
OLD | NEW |