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 "build/build_config.h" | |
6 | |
7 #if defined(OS_WIN) | |
8 #include <windows.h> | |
9 #elif defined(OS_POSIX) | |
10 #include <sys/types.h> | |
11 #include <unistd.h> | |
12 #endif | |
13 | |
14 #include <stdio.h> | |
15 #include <string> | |
16 #include <utility> | |
17 | |
18 #include "ipc/ipc_tests.h" | |
19 | |
20 #include "base/base_switches.h" | |
21 #include "base/command_line.h" | |
22 #include "base/debug/debug_on_start_win.h" | |
23 #include "base/perftimer.h" | |
24 #include "base/pickle.h" | |
25 #include "base/test/perf_test_suite.h" | |
26 #include "base/test/test_suite.h" | |
27 #include "base/threading/thread.h" | |
28 #include "base/time.h" | |
29 #include "ipc/ipc_descriptors.h" | |
30 #include "ipc/ipc_channel.h" | |
31 #include "ipc/ipc_channel_proxy.h" | |
32 #include "ipc/ipc_message_utils.h" | |
33 #include "ipc/ipc_multiprocess_test.h" | |
34 #include "ipc/ipc_sender.h" | |
35 #include "ipc/ipc_switches.h" | |
36 #include "testing/multiprocess_func_list.h" | |
37 | |
38 // Define to enable IPC performance testing instead of the regular unit tests | |
39 // #define PERFORMANCE_TEST | |
40 | |
41 const char kTestClientChannel[] = "T1"; | |
42 const char kReflectorChannel[] = "T2"; | |
43 const char kFuzzerChannel[] = "F3"; | |
44 const char kSyncSocketChannel[] = "S4"; | |
45 | |
46 const size_t kLongMessageStringNumBytes = 50000; | |
47 | |
48 void IPCChannelTest::SetUp() { | |
49 MultiProcessTest::SetUp(); | |
50 | |
51 // Construct a fresh IO Message loop for the duration of each test. | |
52 message_loop_ = new MessageLoopForIO(); | |
53 } | |
54 | |
55 void IPCChannelTest::TearDown() { | |
56 delete message_loop_; | |
57 message_loop_ = NULL; | |
58 | |
59 MultiProcessTest::TearDown(); | |
60 } | |
61 | |
62 #if defined(OS_WIN) | |
63 base::ProcessHandle IPCChannelTest::SpawnChild(ChildType child_type, | |
64 IPC::Channel *channel) { | |
65 // kDebugChildren support. | |
66 bool debug_on_start = | |
67 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren); | |
68 | |
69 switch (child_type) { | |
70 case TEST_CLIENT: | |
71 return MultiProcessTest::SpawnChild("RunTestClient", debug_on_start); | |
72 case TEST_REFLECTOR: | |
73 return MultiProcessTest::SpawnChild("RunReflector", debug_on_start); | |
74 case FUZZER_SERVER: | |
75 return MultiProcessTest::SpawnChild("RunFuzzServer", debug_on_start); | |
76 case SYNC_SOCKET_SERVER: | |
77 return MultiProcessTest::SpawnChild("RunSyncSocketServer", debug_on_start); | |
78 default: | |
79 return NULL; | |
80 } | |
81 } | |
82 #elif defined(OS_POSIX) | |
83 base::ProcessHandle IPCChannelTest::SpawnChild(ChildType child_type, | |
84 IPC::Channel *channel) { | |
85 // kDebugChildren support. | |
86 bool debug_on_start = | |
87 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren); | |
88 | |
89 base::FileHandleMappingVector fds_to_map; | |
90 const int ipcfd = channel->GetClientFileDescriptor(); | |
91 if (ipcfd > -1) { | |
92 fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3)); | |
93 } | |
94 | |
95 base::ProcessHandle ret = base::kNullProcessHandle; | |
96 switch (child_type) { | |
97 case TEST_CLIENT: | |
98 ret = MultiProcessTest::SpawnChild("RunTestClient", | |
99 fds_to_map, | |
100 debug_on_start); | |
101 break; | |
102 case TEST_DESCRIPTOR_CLIENT: | |
103 ret = MultiProcessTest::SpawnChild("RunTestDescriptorClient", | |
104 fds_to_map, | |
105 debug_on_start); | |
106 break; | |
107 case TEST_DESCRIPTOR_CLIENT_SANDBOXED: | |
108 ret = MultiProcessTest::SpawnChild("RunTestDescriptorClientSandboxed", | |
109 fds_to_map, | |
110 debug_on_start); | |
111 break; | |
112 case TEST_REFLECTOR: | |
113 ret = MultiProcessTest::SpawnChild("RunReflector", | |
114 fds_to_map, | |
115 debug_on_start); | |
116 break; | |
117 case FUZZER_SERVER: | |
118 ret = MultiProcessTest::SpawnChild("RunFuzzServer", | |
119 fds_to_map, | |
120 debug_on_start); | |
121 break; | |
122 case SYNC_SOCKET_SERVER: | |
123 ret = MultiProcessTest::SpawnChild("RunSyncSocketServer", | |
124 fds_to_map, | |
125 debug_on_start); | |
126 break; | |
127 default: | |
128 return base::kNullProcessHandle; | |
129 break; | |
130 } | |
131 return ret; | |
132 } | |
133 #endif // defined(OS_POSIX) | |
134 | |
135 #ifndef PERFORMANCE_TEST | |
136 TEST_F(IPCChannelTest, BasicMessageTest) { | |
137 int v1 = 10; | |
138 std::string v2("foobar"); | |
139 std::wstring v3(L"hello world"); | |
140 | |
141 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); | |
142 EXPECT_TRUE(m.WriteInt(v1)); | |
143 EXPECT_TRUE(m.WriteString(v2)); | |
144 EXPECT_TRUE(m.WriteWString(v3)); | |
145 | |
146 PickleIterator iter(m); | |
147 | |
148 int vi; | |
149 std::string vs; | |
150 std::wstring vw; | |
151 | |
152 EXPECT_TRUE(m.ReadInt(&iter, &vi)); | |
153 EXPECT_EQ(v1, vi); | |
154 | |
155 EXPECT_TRUE(m.ReadString(&iter, &vs)); | |
156 EXPECT_EQ(v2, vs); | |
157 | |
158 EXPECT_TRUE(m.ReadWString(&iter, &vw)); | |
159 EXPECT_EQ(v3, vw); | |
160 | |
161 // should fail | |
162 EXPECT_FALSE(m.ReadInt(&iter, &vi)); | |
163 EXPECT_FALSE(m.ReadString(&iter, &vs)); | |
164 EXPECT_FALSE(m.ReadWString(&iter, &vw)); | |
165 } | |
166 | |
167 static void Send(IPC::Sender* sender, const char* text) { | |
168 static int message_index = 0; | |
169 | |
170 IPC::Message* message = new IPC::Message(0, | |
171 2, | |
172 IPC::Message::PRIORITY_NORMAL); | |
173 message->WriteInt(message_index++); | |
174 message->WriteString(std::string(text)); | |
175 | |
176 // Make sure we can handle large messages. | |
177 char junk[kLongMessageStringNumBytes]; | |
178 memset(junk, 'a', sizeof(junk)-1); | |
179 junk[sizeof(junk)-1] = 0; | |
180 message->WriteString(std::string(junk)); | |
181 | |
182 // DEBUG: printf("[%u] sending message [%s]\n", GetCurrentProcessId(), text); | |
183 sender->Send(message); | |
184 } | |
185 | |
186 class MyChannelListener : public IPC::Listener { | |
187 public: | |
188 virtual bool OnMessageReceived(const IPC::Message& message) { | |
189 PickleIterator iter(message); | |
190 | |
191 int ignored; | |
192 EXPECT_TRUE(iter.ReadInt(&ignored)); | |
193 std::string data; | |
194 EXPECT_TRUE(iter.ReadString(&data)); | |
195 std::string big_string; | |
196 EXPECT_TRUE(iter.ReadString(&big_string)); | |
197 EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length()); | |
198 | |
199 | |
200 if (--messages_left_ == 0) { | |
201 MessageLoop::current()->Quit(); | |
202 } else { | |
203 Send(sender_, "Foo"); | |
204 } | |
205 return true; | |
206 } | |
207 | |
208 virtual void OnChannelError() { | |
209 // There is a race when closing the channel so the last message may be lost. | |
210 EXPECT_LE(messages_left_, 1); | |
211 MessageLoop::current()->Quit(); | |
212 } | |
213 | |
214 void Init(IPC::Sender* s) { | |
215 sender_ = s; | |
216 messages_left_ = 50; | |
217 } | |
218 | |
219 private: | |
220 IPC::Sender* sender_; | |
221 int messages_left_; | |
222 }; | |
223 | |
224 TEST_F(IPCChannelTest, ChannelTest) { | |
225 MyChannelListener channel_listener; | |
226 // Setup IPC channel. | |
227 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER, | |
228 &channel_listener); | |
229 ASSERT_TRUE(chan.Connect()); | |
230 | |
231 channel_listener.Init(&chan); | |
232 | |
233 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan); | |
234 ASSERT_TRUE(process_handle); | |
235 | |
236 Send(&chan, "hello from parent"); | |
237 | |
238 // Run message loop. | |
239 MessageLoop::current()->Run(); | |
240 | |
241 // Close Channel so client gets its OnChannelError() callback fired. | |
242 chan.Close(); | |
243 | |
244 // Cleanup child process. | |
245 EXPECT_TRUE(base::WaitForSingleProcess( | |
246 process_handle, base::TimeDelta::FromSeconds(5))); | |
247 base::CloseProcessHandle(process_handle); | |
248 } | |
249 | |
250 #if defined(OS_WIN) | |
251 TEST_F(IPCChannelTest, ChannelTestExistingPipe) { | |
252 MyChannelListener channel_listener; | |
253 // Setup IPC channel with existing pipe. Specify name in Chrome format. | |
254 std::string name("\\\\.\\pipe\\chrome."); | |
255 name.append(kTestClientChannel); | |
256 const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | | |
257 FILE_FLAG_FIRST_PIPE_INSTANCE; | |
258 HANDLE pipe = CreateNamedPipeA(name.c_str(), | |
259 open_mode, | |
260 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, | |
261 1, | |
262 4096, | |
263 4096, | |
264 5000, | |
265 NULL); | |
266 IPC::Channel chan(IPC::ChannelHandle(pipe), IPC::Channel::MODE_SERVER, | |
267 &channel_listener); | |
268 // Channel will duplicate the handle. | |
269 CloseHandle(pipe); | |
270 ASSERT_TRUE(chan.Connect()); | |
271 | |
272 channel_listener.Init(&chan); | |
273 | |
274 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan); | |
275 ASSERT_TRUE(process_handle); | |
276 | |
277 Send(&chan, "hello from parent"); | |
278 | |
279 // Run message loop. | |
280 MessageLoop::current()->Run(); | |
281 | |
282 // Close Channel so client gets its OnChannelError() callback fired. | |
283 chan.Close(); | |
284 | |
285 // Cleanup child process. | |
286 EXPECT_TRUE(base::WaitForSingleProcess( | |
287 process_handle, base::TimeDelta::FromSeconds(5))); | |
288 base::CloseProcessHandle(process_handle); | |
289 } | |
290 #endif // defined (OS_WIN) | |
291 | |
292 TEST_F(IPCChannelTest, ChannelProxyTest) { | |
293 MyChannelListener channel_listener; | |
294 | |
295 // The thread needs to out-live the ChannelProxy. | |
296 base::Thread thread("ChannelProxyTestServer"); | |
297 base::Thread::Options options; | |
298 options.message_loop_type = MessageLoop::TYPE_IO; | |
299 thread.StartWithOptions(options); | |
300 { | |
301 // setup IPC channel proxy | |
302 IPC::ChannelProxy chan(kTestClientChannel, IPC::Channel::MODE_SERVER, | |
303 &channel_listener, thread.message_loop_proxy()); | |
304 | |
305 channel_listener.Init(&chan); | |
306 | |
307 #if defined(OS_WIN) | |
308 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, NULL); | |
309 #elif defined(OS_POSIX) | |
310 bool debug_on_start = CommandLine::ForCurrentProcess()->HasSwitch( | |
311 switches::kDebugChildren); | |
312 base::FileHandleMappingVector fds_to_map; | |
313 const int ipcfd = chan.GetClientFileDescriptor(); | |
314 if (ipcfd > -1) { | |
315 fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3)); | |
316 } | |
317 | |
318 base::ProcessHandle process_handle = MultiProcessTest::SpawnChild( | |
319 "RunTestClient", | |
320 fds_to_map, | |
321 debug_on_start); | |
322 #endif // defined(OS_POSIX) | |
323 | |
324 ASSERT_TRUE(process_handle); | |
325 | |
326 Send(&chan, "hello from parent"); | |
327 | |
328 // run message loop | |
329 MessageLoop::current()->Run(); | |
330 | |
331 // cleanup child process | |
332 EXPECT_TRUE(base::WaitForSingleProcess( | |
333 process_handle, base::TimeDelta::FromSeconds(5))); | |
334 base::CloseProcessHandle(process_handle); | |
335 } | |
336 thread.Stop(); | |
337 } | |
338 | |
339 class ChannelListenerWithOnConnectedSend : public IPC::Listener { | |
340 public: | |
341 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { | |
342 SendNextMessage(); | |
343 } | |
344 | |
345 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | |
346 PickleIterator iter(message); | |
347 | |
348 int ignored; | |
349 EXPECT_TRUE(iter.ReadInt(&ignored)); | |
350 std::string data; | |
351 EXPECT_TRUE(iter.ReadString(&data)); | |
352 std::string big_string; | |
353 EXPECT_TRUE(iter.ReadString(&big_string)); | |
354 EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length()); | |
355 SendNextMessage(); | |
356 return true; | |
357 } | |
358 | |
359 virtual void OnChannelError() OVERRIDE { | |
360 // There is a race when closing the channel so the last message may be lost. | |
361 EXPECT_LE(messages_left_, 1); | |
362 MessageLoop::current()->Quit(); | |
363 } | |
364 | |
365 void Init(IPC::Sender* s) { | |
366 sender_ = s; | |
367 messages_left_ = 50; | |
368 } | |
369 | |
370 private: | |
371 void SendNextMessage() { | |
372 if (--messages_left_ == 0) { | |
373 MessageLoop::current()->Quit(); | |
374 } else { | |
375 Send(sender_, "Foo"); | |
376 } | |
377 } | |
378 | |
379 IPC::Sender* sender_; | |
380 int messages_left_; | |
381 }; | |
382 | |
383 #if defined(OS_WIN) | |
384 // Acting flakey in Windows. http://crbug.com/129595 | |
385 #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnect
ed | |
386 #else | |
387 #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected | |
388 #endif | |
389 TEST_F(IPCChannelTest, MAYBE_SendMessageInChannelConnected) { | |
390 // This tests the case of a listener sending back an event in it's | |
391 // OnChannelConnected handler. | |
392 | |
393 ChannelListenerWithOnConnectedSend channel_listener; | |
394 // Setup IPC channel. | |
395 IPC::Channel channel(kTestClientChannel, IPC::Channel::MODE_SERVER, | |
396 &channel_listener); | |
397 channel_listener.Init(&channel); | |
398 ASSERT_TRUE(channel.Connect()); | |
399 | |
400 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &channel); | |
401 ASSERT_TRUE(process_handle); | |
402 | |
403 Send(&channel, "hello from parent"); | |
404 | |
405 // Run message loop. | |
406 MessageLoop::current()->Run(); | |
407 | |
408 // Close Channel so client gets its OnChannelError() callback fired. | |
409 channel.Close(); | |
410 | |
411 // Cleanup child process. | |
412 EXPECT_TRUE(base::WaitForSingleProcess( | |
413 process_handle, base::TimeDelta::FromSeconds(5))); | |
414 base::CloseProcessHandle(process_handle); | |
415 } | |
416 | |
417 MULTIPROCESS_IPC_TEST_MAIN(RunTestClient) { | |
418 MessageLoopForIO main_message_loop; | |
419 MyChannelListener channel_listener; | |
420 | |
421 // setup IPC channel | |
422 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT, | |
423 &channel_listener); | |
424 CHECK(chan.Connect()); | |
425 channel_listener.Init(&chan); | |
426 Send(&chan, "hello from child"); | |
427 // run message loop | |
428 MessageLoop::current()->Run(); | |
429 return 0; | |
430 } | |
431 | |
432 #endif // !PERFORMANCE_TEST | |
433 | |
434 #ifdef PERFORMANCE_TEST | |
435 | |
436 //----------------------------------------------------------------------------- | |
437 // Manually performance test | |
438 // | |
439 // This test times the roundtrip IPC message cycle. It is enabled with a | |
440 // special preprocessor define to enable it instead of the standard IPC | |
441 // unit tests. This works around some funny termination conditions in the | |
442 // regular unit tests. | |
443 // | |
444 // This test is not automated. To test, you will want to vary the message | |
445 // count and message size in TEST to get the numbers you want. | |
446 // | |
447 // FIXME(brettw): Automate this test and have it run by default. | |
448 | |
449 // This channel listener just replies to all messages with the exact same | |
450 // message. It assumes each message has one string parameter. When the string | |
451 // "quit" is sent, it will exit. | |
452 class ChannelReflectorListener : public IPC::Listener { | |
453 public: | |
454 explicit ChannelReflectorListener(IPC::Channel *channel) : | |
455 channel_(channel), | |
456 count_messages_(0) { | |
457 std::cout << "Reflector up" << std::endl; | |
458 } | |
459 | |
460 ~ChannelReflectorListener() { | |
461 std::cout << "Client Messages: " << count_messages_ << std::endl; | |
462 std::cout << "Client Latency: " << latency_messages_.InMilliseconds() | |
463 << std::endl; | |
464 } | |
465 | |
466 virtual bool OnMessageReceived(const IPC::Message& message) { | |
467 count_messages_++; | |
468 PickleIterator iter(message); | |
469 int64 time_internal; | |
470 EXPECT_TRUE(iter.ReadInt64(&time_internal)); | |
471 int msgid; | |
472 EXPECT_TRUE(iter.ReadInt(&msgid)); | |
473 std::string payload; | |
474 EXPECT_TRUE(iter.ReadString(&payload)); | |
475 // TODO(vtl): Should we use |HighResNow()| instead of |Now()|? | |
476 latency_messages_ += base::TimeTicks::Now() - | |
477 base::TimeTicks::FromInternalValue(time_internal); | |
478 | |
479 // cout << "reflector msg received: " << msgid << endl; | |
480 if (payload == "quit") | |
481 MessageLoop::current()->Quit(); | |
482 | |
483 IPC::Message* msg = new IPC::Message(0, | |
484 2, | |
485 IPC::Message::PRIORITY_NORMAL); | |
486 msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); | |
487 msg->WriteInt(msgid); | |
488 msg->WriteString(payload); | |
489 channel_->Send(msg); | |
490 return true; | |
491 } | |
492 | |
493 private: | |
494 IPC::Channel *channel_; | |
495 int count_messages_; | |
496 base::TimeDelta latency_messages_; | |
497 }; | |
498 | |
499 class ChannelPerfListener : public IPC::Listener { | |
500 public: | |
501 ChannelPerfListener(IPC::Channel* channel, int msg_count, int msg_size) : | |
502 count_down_(msg_count), | |
503 channel_(channel), | |
504 count_messages_(0) { | |
505 payload_.resize(msg_size); | |
506 for (int i = 0; i < static_cast<int>(payload_.size()); i++) | |
507 payload_[i] = 'a'; | |
508 std::cout << "perflistener up" << std::endl; | |
509 } | |
510 | |
511 ~ChannelPerfListener() { | |
512 std::cout << "Server Messages: " << count_messages_ << std::endl; | |
513 std::cout << "Server Latency: " << latency_messages_.InMilliseconds() | |
514 << std::endl; | |
515 } | |
516 | |
517 virtual bool OnMessageReceived(const IPC::Message& message) { | |
518 count_messages_++; | |
519 // Decode the string so this gets counted in the total time. | |
520 PickleIterator iter(message); | |
521 int64 time_internal; | |
522 EXPECT_TRUE(iter.ReadInt64(&time_internal)); | |
523 int msgid; | |
524 EXPECT_TRUE(iter.ReadInt(&msgid)); | |
525 std::string cur; | |
526 EXPECT_TRUE(iter.ReadString(&cur)); | |
527 latency_messages_ += base::TimeTicks::Now() - | |
528 base::TimeTicks::FromInternalValue(time_internal); | |
529 | |
530 count_down_--; | |
531 if (count_down_ == 0) { | |
532 IPC::Message* msg = new IPC::Message(0, | |
533 2, | |
534 IPC::Message::PRIORITY_NORMAL); | |
535 msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); | |
536 msg->WriteInt(count_down_); | |
537 msg->WriteString("quit"); | |
538 channel_->Send(msg); | |
539 | |
540 MessageLoop::current()->QuitWhenIdle(); | |
541 return true; | |
542 } | |
543 | |
544 IPC::Message* msg = new IPC::Message(0, | |
545 2, | |
546 IPC::Message::PRIORITY_NORMAL); | |
547 msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); | |
548 msg->WriteInt(count_down_); | |
549 msg->WriteString(payload_); | |
550 channel_->Send(msg); | |
551 return true; | |
552 } | |
553 | |
554 private: | |
555 int count_down_; | |
556 std::string payload_; | |
557 IPC::Channel *channel_; | |
558 int count_messages_; | |
559 base::TimeDelta latency_messages_; | |
560 }; | |
561 | |
562 TEST_F(IPCChannelTest, Performance) { | |
563 // setup IPC channel | |
564 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_SERVER, NULL); | |
565 ChannelPerfListener perf_listener(&chan, 10000, 100000); | |
566 chan.set_listener(&perf_listener); | |
567 ASSERT_TRUE(chan.Connect()); | |
568 | |
569 base::ProcessHandle process_handle = SpawnChild(TEST_REFLECTOR, &chan); | |
570 ASSERT_TRUE(process_handle); | |
571 | |
572 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); | |
573 | |
574 PerfTimeLogger logger("IPC_Perf"); | |
575 | |
576 // this initial message will kick-start the ping-pong of messages | |
577 IPC::Message* message = new IPC::Message(0, | |
578 2, | |
579 IPC::Message::PRIORITY_NORMAL); | |
580 message->WriteInt64(base::TimeTicks::Now().ToInternalValue()); | |
581 message->WriteInt(-1); | |
582 message->WriteString("Hello"); | |
583 chan.Send(message); | |
584 | |
585 // run message loop | |
586 MessageLoop::current()->Run(); | |
587 | |
588 // Clean up child process. | |
589 EXPECT_TRUE(base::WaitForSingleProcess( | |
590 process_handle, base::TimeDelta::FromSeconds(5))); | |
591 base::CloseProcessHandle(process_handle); | |
592 } | |
593 | |
594 // This message loop bounces all messages back to the sender | |
595 MULTIPROCESS_IPC_TEST_MAIN(RunReflector) { | |
596 MessageLoopForIO main_message_loop; | |
597 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_CLIENT, NULL); | |
598 ChannelReflectorListener channel_reflector_listener(&chan); | |
599 chan.set_listener(&channel_reflector_listener); | |
600 CHECK(chan.Connect()); | |
601 | |
602 MessageLoop::current()->Run(); | |
603 return 0; | |
604 } | |
605 | |
606 #endif // PERFORMANCE_TEST | |
607 | |
608 int main(int argc, char** argv) { | |
609 #ifdef PERFORMANCE_TEST | |
610 int retval = base::PerfTestSuite(argc, argv).Run(); | |
611 #else | |
612 int retval = base::TestSuite(argc, argv).Run(); | |
613 #endif | |
614 return retval; | |
615 } | |
OLD | NEW |