chromeos: Fix StartupBrowserCreatorImpl::Launch crash.
[chromium-blink-merge.git] / ipc / ipc_tests.cc
blob5b23fa6de844a8ef5f667243c521f30f096ae89a
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 "build/build_config.h"
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
14 #include <stdio.h>
15 #include <string>
16 #include <utility>
18 #include "ipc/ipc_tests.h"
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/test/perf_test_suite.h"
25 #include "base/test/test_suite.h"
26 #include "base/threading/thread.h"
27 #include "ipc/ipc_descriptors.h"
28 #include "ipc/ipc_channel.h"
29 #include "ipc/ipc_channel_proxy.h"
30 #include "ipc/ipc_message_utils.h"
31 #include "ipc/ipc_multiprocess_test.h"
32 #include "ipc/ipc_sender.h"
33 #include "ipc/ipc_switches.h"
34 #include "testing/multiprocess_func_list.h"
36 // Define to enable IPC performance testing instead of the regular unit tests
37 // #define PERFORMANCE_TEST
39 const char kTestClientChannel[] = "T1";
40 const char kReflectorChannel[] = "T2";
41 const char kFuzzerChannel[] = "F3";
42 const char kSyncSocketChannel[] = "S4";
44 const size_t kLongMessageStringNumBytes = 50000;
46 #ifndef PERFORMANCE_TEST
48 void IPCChannelTest::SetUp() {
49 MultiProcessTest::SetUp();
51 // Construct a fresh IO Message loop for the duration of each test.
52 message_loop_ = new MessageLoopForIO();
55 void IPCChannelTest::TearDown() {
56 delete message_loop_;
57 message_loop_ = NULL;
59 MultiProcessTest::TearDown();
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);
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;
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);
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));
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;
131 return ret;
133 #endif // defined(OS_POSIX)
135 TEST_F(IPCChannelTest, BasicMessageTest) {
136 int v1 = 10;
137 std::string v2("foobar");
138 std::wstring v3(L"hello world");
140 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
141 EXPECT_TRUE(m.WriteInt(v1));
142 EXPECT_TRUE(m.WriteString(v2));
143 EXPECT_TRUE(m.WriteWString(v3));
145 PickleIterator iter(m);
147 int vi;
148 std::string vs;
149 std::wstring vw;
151 EXPECT_TRUE(m.ReadInt(&iter, &vi));
152 EXPECT_EQ(v1, vi);
154 EXPECT_TRUE(m.ReadString(&iter, &vs));
155 EXPECT_EQ(v2, vs);
157 EXPECT_TRUE(m.ReadWString(&iter, &vw));
158 EXPECT_EQ(v3, vw);
160 // should fail
161 EXPECT_FALSE(m.ReadInt(&iter, &vi));
162 EXPECT_FALSE(m.ReadString(&iter, &vs));
163 EXPECT_FALSE(m.ReadWString(&iter, &vw));
166 static void Send(IPC::Sender* sender, const char* text) {
167 static int message_index = 0;
169 IPC::Message* message = new IPC::Message(0,
171 IPC::Message::PRIORITY_NORMAL);
172 message->WriteInt(message_index++);
173 message->WriteString(std::string(text));
175 // Make sure we can handle large messages.
176 char junk[kLongMessageStringNumBytes];
177 memset(junk, 'a', sizeof(junk)-1);
178 junk[sizeof(junk)-1] = 0;
179 message->WriteString(std::string(junk));
181 // DEBUG: printf("[%u] sending message [%s]\n", GetCurrentProcessId(), text);
182 sender->Send(message);
185 class MyChannelListener : public IPC::Listener {
186 public:
187 virtual bool OnMessageReceived(const IPC::Message& message) {
188 IPC::MessageIterator iter(message);
190 iter.NextInt();
191 const std::string data = iter.NextString();
192 const std::string big_string = iter.NextString();
193 EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length());
196 if (--messages_left_ == 0) {
197 MessageLoop::current()->Quit();
198 } else {
199 Send(sender_, "Foo");
201 return true;
204 virtual void OnChannelError() {
205 // There is a race when closing the channel so the last message may be lost.
206 EXPECT_LE(messages_left_, 1);
207 MessageLoop::current()->Quit();
210 void Init(IPC::Sender* s) {
211 sender_ = s;
212 messages_left_ = 50;
215 private:
216 IPC::Sender* sender_;
217 int messages_left_;
220 TEST_F(IPCChannelTest, ChannelTest) {
221 MyChannelListener channel_listener;
222 // Setup IPC channel.
223 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
224 &channel_listener);
225 ASSERT_TRUE(chan.Connect());
227 channel_listener.Init(&chan);
229 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan);
230 ASSERT_TRUE(process_handle);
232 Send(&chan, "hello from parent");
234 // Run message loop.
235 MessageLoop::current()->Run();
237 // Close Channel so client gets its OnChannelError() callback fired.
238 chan.Close();
240 // Cleanup child process.
241 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
242 base::CloseProcessHandle(process_handle);
245 #if defined(OS_WIN)
246 TEST_F(IPCChannelTest, ChannelTestExistingPipe) {
247 MyChannelListener channel_listener;
248 // Setup IPC channel with existing pipe. Specify name in Chrome format.
249 std::string name("\\\\.\\pipe\\chrome.");
250 name.append(kTestClientChannel);
251 const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
252 FILE_FLAG_FIRST_PIPE_INSTANCE;
253 HANDLE pipe = CreateNamedPipeA(name.c_str(),
254 open_mode,
255 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
257 4096,
258 4096,
259 5000,
260 NULL);
261 IPC::Channel chan(IPC::ChannelHandle(pipe), IPC::Channel::MODE_SERVER,
262 &channel_listener);
263 // Channel will duplicate the handle.
264 CloseHandle(pipe);
265 ASSERT_TRUE(chan.Connect());
267 channel_listener.Init(&chan);
269 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan);
270 ASSERT_TRUE(process_handle);
272 Send(&chan, "hello from parent");
274 // Run message loop.
275 MessageLoop::current()->Run();
277 // Close Channel so client gets its OnChannelError() callback fired.
278 chan.Close();
280 // Cleanup child process.
281 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
282 base::CloseProcessHandle(process_handle);
284 #endif // defined (OS_WIN)
286 TEST_F(IPCChannelTest, ChannelProxyTest) {
287 MyChannelListener channel_listener;
289 // The thread needs to out-live the ChannelProxy.
290 base::Thread thread("ChannelProxyTestServer");
291 base::Thread::Options options;
292 options.message_loop_type = MessageLoop::TYPE_IO;
293 thread.StartWithOptions(options);
295 // setup IPC channel proxy
296 IPC::ChannelProxy chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
297 &channel_listener, thread.message_loop_proxy());
299 channel_listener.Init(&chan);
301 #if defined(OS_WIN)
302 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, NULL);
303 #elif defined(OS_POSIX)
304 bool debug_on_start = CommandLine::ForCurrentProcess()->HasSwitch(
305 switches::kDebugChildren);
306 base::FileHandleMappingVector fds_to_map;
307 const int ipcfd = chan.GetClientFileDescriptor();
308 if (ipcfd > -1) {
309 fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3));
312 base::ProcessHandle process_handle = MultiProcessTest::SpawnChild(
313 "RunTestClient",
314 fds_to_map,
315 debug_on_start);
316 #endif // defined(OS_POSIX)
318 ASSERT_TRUE(process_handle);
320 Send(&chan, "hello from parent");
322 // run message loop
323 MessageLoop::current()->Run();
325 // cleanup child process
326 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
327 base::CloseProcessHandle(process_handle);
329 thread.Stop();
332 class ChannelListenerWithOnConnectedSend : public IPC::Listener {
333 public:
334 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
335 SendNextMessage();
338 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
339 IPC::MessageIterator iter(message);
341 iter.NextInt();
342 const std::string data = iter.NextString();
343 const std::string big_string = iter.NextString();
344 EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length());
345 SendNextMessage();
346 return true;
349 virtual void OnChannelError() OVERRIDE {
350 // There is a race when closing the channel so the last message may be lost.
351 EXPECT_LE(messages_left_, 1);
352 MessageLoop::current()->Quit();
355 void Init(IPC::Sender* s) {
356 sender_ = s;
357 messages_left_ = 50;
360 private:
361 void SendNextMessage() {
362 if (--messages_left_ == 0) {
363 MessageLoop::current()->Quit();
364 } else {
365 Send(sender_, "Foo");
369 IPC::Sender* sender_;
370 int messages_left_;
373 #if defined(OS_WIN)
374 // Acting flakey in Windows. http://crbug.com/129595
375 #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnected
376 #else
377 #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected
378 #endif
379 TEST_F(IPCChannelTest, MAYBE_SendMessageInChannelConnected) {
380 // This tests the case of a listener sending back an event in it's
381 // OnChannelConnected handler.
383 ChannelListenerWithOnConnectedSend channel_listener;
384 // Setup IPC channel.
385 IPC::Channel channel(kTestClientChannel, IPC::Channel::MODE_SERVER,
386 &channel_listener);
387 channel_listener.Init(&channel);
388 ASSERT_TRUE(channel.Connect());
390 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &channel);
391 ASSERT_TRUE(process_handle);
393 Send(&channel, "hello from parent");
395 // Run message loop.
396 MessageLoop::current()->Run();
398 // Close Channel so client gets its OnChannelError() callback fired.
399 channel.Close();
401 // Cleanup child process.
402 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
403 base::CloseProcessHandle(process_handle);
406 MULTIPROCESS_IPC_TEST_MAIN(RunTestClient) {
407 MessageLoopForIO main_message_loop;
408 MyChannelListener channel_listener;
410 // setup IPC channel
411 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
412 &channel_listener);
413 CHECK(chan.Connect());
414 channel_listener.Init(&chan);
415 Send(&chan, "hello from child");
416 // run message loop
417 MessageLoop::current()->Run();
418 // return true;
419 return 0;
422 #endif // !PERFORMANCE_TEST
424 #ifdef PERFORMANCE_TEST
426 //-----------------------------------------------------------------------------
427 // Manually performance test
429 // This test times the roundtrip IPC message cycle. It is enabled with a
430 // special preprocessor define to enable it instead of the standard IPC
431 // unit tests. This works around some funny termination conditions in the
432 // regular unit tests.
434 // This test is not automated. To test, you will want to vary the message
435 // count and message size in TEST to get the numbers you want.
437 // FIXME(brettw): Automate this test and have it run by default.
439 // This channel listener just replies to all messages with the exact same
440 // message. It assumes each message has one string parameter. When the string
441 // "quit" is sent, it will exit.
442 class ChannelReflectorListener : public IPC::Listener {
443 public:
444 explicit ChannelReflectorListener(IPC::Channel *channel) :
445 channel_(channel),
446 count_messages_(0),
447 latency_messages_(0) {
448 std::cout << "Reflector up" << std::endl;
451 ~ChannelReflectorListener() {
452 std::cout << "Client Messages: " << count_messages_ << std::endl;
453 std::cout << "Client Latency: " << latency_messages_ << std::endl;
456 virtual bool OnMessageReceived(const IPC::Message& message) {
457 count_messages_++;
458 IPC::MessageIterator iter(message);
459 int time = iter.NextInt();
460 int msgid = iter.NextInt();
461 std::string payload = iter.NextString();
462 latency_messages_ += GetTickCount() - time;
464 // cout << "reflector msg received: " << msgid << endl;
465 if (payload == "quit")
466 MessageLoop::current()->Quit();
468 IPC::Message* msg = new IPC::Message(0,
470 IPC::Message::PRIORITY_NORMAL);
471 msg->WriteInt(GetTickCount());
472 msg->WriteInt(msgid);
473 msg->WriteString(payload);
474 channel_->Send(msg);
475 return true;
478 private:
479 IPC::Channel *channel_;
480 int count_messages_;
481 int latency_messages_;
484 class ChannelPerfListener : public IPC::Listener {
485 public:
486 ChannelPerfListener(IPC::Channel* channel, int msg_count, int msg_size) :
487 count_down_(msg_count),
488 channel_(channel),
489 count_messages_(0),
490 latency_messages_(0) {
491 payload_.resize(msg_size);
492 for (int i = 0; i < static_cast<int>(payload_.size()); i++)
493 payload_[i] = 'a';
494 std::cout << "perflistener up" << std::endl;
497 ~ChannelPerfListener() {
498 std::cout << "Server Messages: " << count_messages_ << std::endl;
499 std::cout << "Server Latency: " << latency_messages_ << std::endl;
502 virtual bool OnMessageReceived(const IPC::Message& message) {
503 count_messages_++;
504 // decode the string so this gets counted in the total time
505 IPC::MessageIterator iter(message);
506 int time = iter.NextInt();
507 int msgid = iter.NextInt();
508 std::string cur = iter.NextString();
509 latency_messages_ += GetTickCount() - time;
511 // cout << "perflistener got message" << endl;
513 count_down_--;
514 if (count_down_ == 0) {
515 IPC::Message* msg = new IPC::Message(0,
517 IPC::Message::PRIORITY_NORMAL);
518 msg->WriteInt(GetTickCount());
519 msg->WriteInt(count_down_);
520 msg->WriteString("quit");
521 channel_->Send(msg);
522 SetTimer(NULL, 1, 250, (TIMERPROC) PostQuitMessage);
523 return true;
526 IPC::Message* msg = new IPC::Message(0,
528 IPC::Message::PRIORITY_NORMAL);
529 msg->WriteInt(GetTickCount());
530 msg->WriteInt(count_down_);
531 msg->WriteString(payload_);
532 channel_->Send(msg);
533 return true;
536 private:
537 int count_down_;
538 std::string payload_;
539 IPC::Channel *channel_;
540 int count_messages_;
541 int latency_messages_;
544 TEST_F(IPCChannelTest, Performance) {
545 // setup IPC channel
546 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_SERVER, NULL);
547 ChannelPerfListener perf_listener(&chan, 10000, 100000);
548 chan.set_listener(&perf_listener);
549 ASSERT_TRUE(chan.Connect());
551 HANDLE process = SpawnChild(TEST_REFLECTOR, &chan);
552 ASSERT_TRUE(process);
554 PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
556 PerfTimeLogger logger("IPC_Perf");
558 // this initial message will kick-start the ping-pong of messages
559 IPC::Message* message = new IPC::Message(0,
561 IPC::Message::PRIORITY_NORMAL);
562 message->WriteInt(GetTickCount());
563 message->WriteInt(-1);
564 message->WriteString("Hello");
565 chan.Send(message);
567 // run message loop
568 MessageLoop::current()->Run();
570 // cleanup child process
571 WaitForSingleObject(process, 5000);
572 CloseHandle(process);
575 // This message loop bounces all messages back to the sender
576 MULTIPROCESS_IPC_TEST_MAIN(RunReflector) {
577 MessageLoopForIO main_message_loop;
578 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_CLIENT, NULL);
579 ChannelReflectorListener channel_reflector_listener(&chan);
580 chan.set_listener(&channel_reflector_listener);
581 ASSERT_TRUE(chan.Connect());
583 MessageLoop::current()->Run();
584 return true;
587 #endif // PERFORMANCE_TEST
589 int main(int argc, char** argv) {
590 #ifdef PERFORMANCE_TEST
591 int retval = base::PerfTestSuite(argc, argv).Run();
592 #else
593 int retval = base::TestSuite(argc, argv).Run();
594 #endif
595 return retval;