Fix protobuf_lite_java action ordering in gyp.
[chromium-blink-merge.git] / ipc / ipc_tests.cc
blobcecbf45f574e4b272ea05fed5ed4f78e25731812
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(
242 process_handle, base::TimeDelta::FromSeconds(5)));
243 base::CloseProcessHandle(process_handle);
246 #if defined(OS_WIN)
247 TEST_F(IPCChannelTest, ChannelTestExistingPipe) {
248 MyChannelListener channel_listener;
249 // Setup IPC channel with existing pipe. Specify name in Chrome format.
250 std::string name("\\\\.\\pipe\\chrome.");
251 name.append(kTestClientChannel);
252 const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
253 FILE_FLAG_FIRST_PIPE_INSTANCE;
254 HANDLE pipe = CreateNamedPipeA(name.c_str(),
255 open_mode,
256 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
258 4096,
259 4096,
260 5000,
261 NULL);
262 IPC::Channel chan(IPC::ChannelHandle(pipe), IPC::Channel::MODE_SERVER,
263 &channel_listener);
264 // Channel will duplicate the handle.
265 CloseHandle(pipe);
266 ASSERT_TRUE(chan.Connect());
268 channel_listener.Init(&chan);
270 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan);
271 ASSERT_TRUE(process_handle);
273 Send(&chan, "hello from parent");
275 // Run message loop.
276 MessageLoop::current()->Run();
278 // Close Channel so client gets its OnChannelError() callback fired.
279 chan.Close();
281 // Cleanup child process.
282 EXPECT_TRUE(base::WaitForSingleProcess(
283 process_handle, base::TimeDelta::FromSeconds(5)));
284 base::CloseProcessHandle(process_handle);
286 #endif // defined (OS_WIN)
288 TEST_F(IPCChannelTest, ChannelProxyTest) {
289 MyChannelListener channel_listener;
291 // The thread needs to out-live the ChannelProxy.
292 base::Thread thread("ChannelProxyTestServer");
293 base::Thread::Options options;
294 options.message_loop_type = MessageLoop::TYPE_IO;
295 thread.StartWithOptions(options);
297 // setup IPC channel proxy
298 IPC::ChannelProxy chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
299 &channel_listener, thread.message_loop_proxy());
301 channel_listener.Init(&chan);
303 #if defined(OS_WIN)
304 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, NULL);
305 #elif defined(OS_POSIX)
306 bool debug_on_start = CommandLine::ForCurrentProcess()->HasSwitch(
307 switches::kDebugChildren);
308 base::FileHandleMappingVector fds_to_map;
309 const int ipcfd = chan.GetClientFileDescriptor();
310 if (ipcfd > -1) {
311 fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3));
314 base::ProcessHandle process_handle = MultiProcessTest::SpawnChild(
315 "RunTestClient",
316 fds_to_map,
317 debug_on_start);
318 #endif // defined(OS_POSIX)
320 ASSERT_TRUE(process_handle);
322 Send(&chan, "hello from parent");
324 // run message loop
325 MessageLoop::current()->Run();
327 // cleanup child process
328 EXPECT_TRUE(base::WaitForSingleProcess(
329 process_handle, base::TimeDelta::FromSeconds(5)));
330 base::CloseProcessHandle(process_handle);
332 thread.Stop();
335 class ChannelListenerWithOnConnectedSend : public IPC::Listener {
336 public:
337 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
338 SendNextMessage();
341 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
342 IPC::MessageIterator iter(message);
344 iter.NextInt();
345 const std::string data = iter.NextString();
346 const std::string big_string = iter.NextString();
347 EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length());
348 SendNextMessage();
349 return true;
352 virtual void OnChannelError() OVERRIDE {
353 // There is a race when closing the channel so the last message may be lost.
354 EXPECT_LE(messages_left_, 1);
355 MessageLoop::current()->Quit();
358 void Init(IPC::Sender* s) {
359 sender_ = s;
360 messages_left_ = 50;
363 private:
364 void SendNextMessage() {
365 if (--messages_left_ == 0) {
366 MessageLoop::current()->Quit();
367 } else {
368 Send(sender_, "Foo");
372 IPC::Sender* sender_;
373 int messages_left_;
376 #if defined(OS_WIN)
377 // Acting flakey in Windows. http://crbug.com/129595
378 #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnected
379 #else
380 #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected
381 #endif
382 TEST_F(IPCChannelTest, MAYBE_SendMessageInChannelConnected) {
383 // This tests the case of a listener sending back an event in it's
384 // OnChannelConnected handler.
386 ChannelListenerWithOnConnectedSend channel_listener;
387 // Setup IPC channel.
388 IPC::Channel channel(kTestClientChannel, IPC::Channel::MODE_SERVER,
389 &channel_listener);
390 channel_listener.Init(&channel);
391 ASSERT_TRUE(channel.Connect());
393 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &channel);
394 ASSERT_TRUE(process_handle);
396 Send(&channel, "hello from parent");
398 // Run message loop.
399 MessageLoop::current()->Run();
401 // Close Channel so client gets its OnChannelError() callback fired.
402 channel.Close();
404 // Cleanup child process.
405 EXPECT_TRUE(base::WaitForSingleProcess(
406 process_handle, base::TimeDelta::FromSeconds(5)));
407 base::CloseProcessHandle(process_handle);
410 MULTIPROCESS_IPC_TEST_MAIN(RunTestClient) {
411 MessageLoopForIO main_message_loop;
412 MyChannelListener channel_listener;
414 // setup IPC channel
415 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
416 &channel_listener);
417 CHECK(chan.Connect());
418 channel_listener.Init(&chan);
419 Send(&chan, "hello from child");
420 // run message loop
421 MessageLoop::current()->Run();
422 // return true;
423 return 0;
426 #endif // !PERFORMANCE_TEST
428 #ifdef PERFORMANCE_TEST
430 //-----------------------------------------------------------------------------
431 // Manually performance test
433 // This test times the roundtrip IPC message cycle. It is enabled with a
434 // special preprocessor define to enable it instead of the standard IPC
435 // unit tests. This works around some funny termination conditions in the
436 // regular unit tests.
438 // This test is not automated. To test, you will want to vary the message
439 // count and message size in TEST to get the numbers you want.
441 // FIXME(brettw): Automate this test and have it run by default.
443 // This channel listener just replies to all messages with the exact same
444 // message. It assumes each message has one string parameter. When the string
445 // "quit" is sent, it will exit.
446 class ChannelReflectorListener : public IPC::Listener {
447 public:
448 explicit ChannelReflectorListener(IPC::Channel *channel) :
449 channel_(channel),
450 count_messages_(0),
451 latency_messages_(0) {
452 std::cout << "Reflector up" << std::endl;
455 ~ChannelReflectorListener() {
456 std::cout << "Client Messages: " << count_messages_ << std::endl;
457 std::cout << "Client Latency: " << latency_messages_ << std::endl;
460 virtual bool OnMessageReceived(const IPC::Message& message) {
461 count_messages_++;
462 IPC::MessageIterator iter(message);
463 int time = iter.NextInt();
464 int msgid = iter.NextInt();
465 std::string payload = iter.NextString();
466 latency_messages_ += GetTickCount() - time;
468 // cout << "reflector msg received: " << msgid << endl;
469 if (payload == "quit")
470 MessageLoop::current()->Quit();
472 IPC::Message* msg = new IPC::Message(0,
474 IPC::Message::PRIORITY_NORMAL);
475 msg->WriteInt(GetTickCount());
476 msg->WriteInt(msgid);
477 msg->WriteString(payload);
478 channel_->Send(msg);
479 return true;
482 private:
483 IPC::Channel *channel_;
484 int count_messages_;
485 int latency_messages_;
488 class ChannelPerfListener : public IPC::Listener {
489 public:
490 ChannelPerfListener(IPC::Channel* channel, int msg_count, int msg_size) :
491 count_down_(msg_count),
492 channel_(channel),
493 count_messages_(0),
494 latency_messages_(0) {
495 payload_.resize(msg_size);
496 for (int i = 0; i < static_cast<int>(payload_.size()); i++)
497 payload_[i] = 'a';
498 std::cout << "perflistener up" << std::endl;
501 ~ChannelPerfListener() {
502 std::cout << "Server Messages: " << count_messages_ << std::endl;
503 std::cout << "Server Latency: " << latency_messages_ << std::endl;
506 virtual bool OnMessageReceived(const IPC::Message& message) {
507 count_messages_++;
508 // decode the string so this gets counted in the total time
509 IPC::MessageIterator iter(message);
510 int time = iter.NextInt();
511 int msgid = iter.NextInt();
512 std::string cur = iter.NextString();
513 latency_messages_ += GetTickCount() - time;
515 // cout << "perflistener got message" << endl;
517 count_down_--;
518 if (count_down_ == 0) {
519 IPC::Message* msg = new IPC::Message(0,
521 IPC::Message::PRIORITY_NORMAL);
522 msg->WriteInt(GetTickCount());
523 msg->WriteInt(count_down_);
524 msg->WriteString("quit");
525 channel_->Send(msg);
526 SetTimer(NULL, 1, 250, (TIMERPROC) PostQuitMessage);
527 return true;
530 IPC::Message* msg = new IPC::Message(0,
532 IPC::Message::PRIORITY_NORMAL);
533 msg->WriteInt(GetTickCount());
534 msg->WriteInt(count_down_);
535 msg->WriteString(payload_);
536 channel_->Send(msg);
537 return true;
540 private:
541 int count_down_;
542 std::string payload_;
543 IPC::Channel *channel_;
544 int count_messages_;
545 int latency_messages_;
548 TEST_F(IPCChannelTest, Performance) {
549 // setup IPC channel
550 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_SERVER, NULL);
551 ChannelPerfListener perf_listener(&chan, 10000, 100000);
552 chan.set_listener(&perf_listener);
553 ASSERT_TRUE(chan.Connect());
555 HANDLE process = SpawnChild(TEST_REFLECTOR, &chan);
556 ASSERT_TRUE(process);
558 PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
560 PerfTimeLogger logger("IPC_Perf");
562 // this initial message will kick-start the ping-pong of messages
563 IPC::Message* message = new IPC::Message(0,
565 IPC::Message::PRIORITY_NORMAL);
566 message->WriteInt(GetTickCount());
567 message->WriteInt(-1);
568 message->WriteString("Hello");
569 chan.Send(message);
571 // run message loop
572 MessageLoop::current()->Run();
574 // cleanup child process
575 WaitForSingleObject(process, 5000);
576 CloseHandle(process);
579 // This message loop bounces all messages back to the sender
580 MULTIPROCESS_IPC_TEST_MAIN(RunReflector) {
581 MessageLoopForIO main_message_loop;
582 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_CLIENT, NULL);
583 ChannelReflectorListener channel_reflector_listener(&chan);
584 chan.set_listener(&channel_reflector_listener);
585 ASSERT_TRUE(chan.Connect());
587 MessageLoop::current()->Run();
588 return true;
591 #endif // PERFORMANCE_TEST
593 int main(int argc, char** argv) {
594 #ifdef PERFORMANCE_TEST
595 int retval = base::PerfTestSuite(argc, argv).Run();
596 #else
597 int retval = base::TestSuite(argc, argv).Run();
598 #endif
599 return retval;