blob: 14259fa5b69d6c3dc739029d0a8ea600778a9bc1 [file] [log] [blame]
[email protected]b5393332012-01-13 00:11:011// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]645aaa52009-02-07 01:03:055#include "build/build_config.h"
6
[email protected]d4651ff2008-12-02 16:51:587#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:298#include <windows.h>
[email protected]43cf8152009-02-07 00:57:459#elif defined(OS_POSIX)
10#include <sys/types.h>
[email protected]43cf8152009-02-07 00:57:4511#include <unistd.h>
[email protected]d4651ff2008-12-02 16:51:5812#endif
[email protected]43cf8152009-02-07 00:57:4513
initial.commit09911bf2008-07-26 23:55:2914#include <stdio.h>
initial.commit09911bf2008-07-26 23:55:2915#include <string>
[email protected]b7243c42010-07-23 05:23:1316#include <utility>
initial.commit09911bf2008-07-26 23:55:2917
[email protected]946d1b22009-07-22 23:57:2118#include "ipc/ipc_tests.h"
initial.commit09911bf2008-07-26 23:55:2919
20#include "base/base_switches.h"
21#include "base/command_line.h"
[email protected]10f33b1b2011-01-01 19:55:2222#include "base/debug/debug_on_start_win.h"
initial.commit09911bf2008-07-26 23:55:2923#include "base/perftimer.h"
[email protected]fb895c62009-10-09 18:20:3024#include "base/test/perf_test_suite.h"
25#include "base/test/test_suite.h"
[email protected]34b99632011-01-01 01:01:0626#include "base/threading/thread.h"
[email protected]946d1b22009-07-22 23:57:2127#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_switches.h"
[email protected]95cb7fb92008-12-09 22:00:4732#include "testing/multiprocess_func_list.h"
initial.commit09911bf2008-07-26 23:55:2933
34// Define to enable IPC performance testing instead of the regular unit tests
35// #define PERFORMANCE_TEST
36
[email protected]9a3a293b2009-06-04 22:28:1637const char kTestClientChannel[] = "T1";
38const char kReflectorChannel[] = "T2";
39const char kFuzzerChannel[] = "F3";
[email protected]0840cc72009-11-24 16:14:5340const char kSyncSocketChannel[] = "S4";
initial.commit09911bf2008-07-26 23:55:2941
[email protected]c2f10ed2009-02-10 00:52:5742const size_t kLongMessageStringNumBytes = 50000;
43
initial.commit09911bf2008-07-26 23:55:2944#ifndef PERFORMANCE_TEST
45
[email protected]95cb7fb92008-12-09 22:00:4746void IPCChannelTest::SetUp() {
47 MultiProcessTest::SetUp();
48
49 // Construct a fresh IO Message loop for the duration of each test.
50 message_loop_ = new MessageLoopForIO();
51}
52
53void IPCChannelTest::TearDown() {
54 delete message_loop_;
55 message_loop_ = NULL;
56
57 MultiProcessTest::TearDown();
58}
59
[email protected]df3c1ca12008-12-19 21:37:0160#if defined(OS_WIN)
61base::ProcessHandle IPCChannelTest::SpawnChild(ChildType child_type,
62 IPC::Channel *channel) {
[email protected]95cb7fb92008-12-09 22:00:4763 // kDebugChildren support.
[email protected]bb975362009-01-21 01:00:2264 bool debug_on_start =
65 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren);
[email protected]95cb7fb92008-12-09 22:00:4766
67 switch (child_type) {
68 case TEST_CLIENT:
[email protected]d420c31e2010-07-30 02:14:2269 return MultiProcessTest::SpawnChild("RunTestClient", debug_on_start);
[email protected]95cb7fb92008-12-09 22:00:4770 case TEST_REFLECTOR:
[email protected]d420c31e2010-07-30 02:14:2271 return MultiProcessTest::SpawnChild("RunReflector", debug_on_start);
[email protected]95cb7fb92008-12-09 22:00:4772 case FUZZER_SERVER:
[email protected]d420c31e2010-07-30 02:14:2273 return MultiProcessTest::SpawnChild("RunFuzzServer", debug_on_start);
[email protected]0840cc72009-11-24 16:14:5374 case SYNC_SOCKET_SERVER:
[email protected]d420c31e2010-07-30 02:14:2275 return MultiProcessTest::SpawnChild("RunSyncSocketServer", debug_on_start);
[email protected]95cb7fb92008-12-09 22:00:4776 default:
77 return NULL;
[email protected]95cb7fb92008-12-09 22:00:4778 }
79}
[email protected]df3c1ca12008-12-19 21:37:0180#elif defined(OS_POSIX)
81base::ProcessHandle IPCChannelTest::SpawnChild(ChildType child_type,
82 IPC::Channel *channel) {
83 // kDebugChildren support.
[email protected]bb975362009-01-21 01:00:2284 bool debug_on_start =
85 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren);
[email protected]df3c1ca12008-12-19 21:37:0186
[email protected]a82af392012-02-24 04:40:2087 base::FileHandleMappingVector fds_to_map;
[email protected]cc8f1462009-06-12 17:36:5588 const int ipcfd = channel->GetClientFileDescriptor();
89 if (ipcfd > -1) {
[email protected]b7243c42010-07-23 05:23:1390 fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3));
[email protected]df3c1ca12008-12-19 21:37:0191 }
92
[email protected]8b8fab972011-01-13 16:27:1893 base::ProcessHandle ret = base::kNullProcessHandle;
[email protected]df3c1ca12008-12-19 21:37:0194 switch (child_type) {
95 case TEST_CLIENT:
[email protected]d420c31e2010-07-30 02:14:2296 ret = MultiProcessTest::SpawnChild("RunTestClient",
[email protected]df3c1ca12008-12-19 21:37:0197 fds_to_map,
98 debug_on_start);
[email protected]df3c1ca12008-12-19 21:37:0199 break;
[email protected]526776c2009-02-07 00:39:26100 case TEST_DESCRIPTOR_CLIENT:
[email protected]d420c31e2010-07-30 02:14:22101 ret = MultiProcessTest::SpawnChild("RunTestDescriptorClient",
[email protected]526776c2009-02-07 00:39:26102 fds_to_map,
103 debug_on_start);
[email protected]526776c2009-02-07 00:39:26104 break;
[email protected]e8351b7e2009-02-10 22:25:39105 case TEST_DESCRIPTOR_CLIENT_SANDBOXED:
[email protected]d420c31e2010-07-30 02:14:22106 ret = MultiProcessTest::SpawnChild("RunTestDescriptorClientSandboxed",
[email protected]e8351b7e2009-02-10 22:25:39107 fds_to_map,
108 debug_on_start);
[email protected]e8351b7e2009-02-10 22:25:39109 break;
[email protected]df3c1ca12008-12-19 21:37:01110 case TEST_REFLECTOR:
[email protected]d420c31e2010-07-30 02:14:22111 ret = MultiProcessTest::SpawnChild("RunReflector",
[email protected]df3c1ca12008-12-19 21:37:01112 fds_to_map,
113 debug_on_start);
[email protected]df3c1ca12008-12-19 21:37:01114 break;
115 case FUZZER_SERVER:
[email protected]d420c31e2010-07-30 02:14:22116 ret = MultiProcessTest::SpawnChild("RunFuzzServer",
[email protected]df3c1ca12008-12-19 21:37:01117 fds_to_map,
118 debug_on_start);
[email protected]df3c1ca12008-12-19 21:37:01119 break;
[email protected]0840cc72009-11-24 16:14:53120 case SYNC_SOCKET_SERVER:
[email protected]d420c31e2010-07-30 02:14:22121 ret = MultiProcessTest::SpawnChild("RunSyncSocketServer",
[email protected]0840cc72009-11-24 16:14:53122 fds_to_map,
123 debug_on_start);
124 break;
[email protected]df3c1ca12008-12-19 21:37:01125 default:
[email protected]8b8fab972011-01-13 16:27:18126 return base::kNullProcessHandle;
[email protected]df3c1ca12008-12-19 21:37:01127 break;
128 }
129 return ret;
130}
131#endif // defined(OS_POSIX)
[email protected]95cb7fb92008-12-09 22:00:47132
133TEST_F(IPCChannelTest, BasicMessageTest) {
initial.commit09911bf2008-07-26 23:55:29134 int v1 = 10;
135 std::string v2("foobar");
136 std::wstring v3(L"hello world");
137
138 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
139 EXPECT_TRUE(m.WriteInt(v1));
140 EXPECT_TRUE(m.WriteString(v2));
141 EXPECT_TRUE(m.WriteWString(v3));
142
[email protected]ce208f872012-03-07 20:42:56143 PickleIterator iter(m);
initial.commit09911bf2008-07-26 23:55:29144
145 int vi;
146 std::string vs;
147 std::wstring vw;
148
149 EXPECT_TRUE(m.ReadInt(&iter, &vi));
150 EXPECT_EQ(v1, vi);
151
152 EXPECT_TRUE(m.ReadString(&iter, &vs));
153 EXPECT_EQ(v2, vs);
154
155 EXPECT_TRUE(m.ReadWString(&iter, &vw));
156 EXPECT_EQ(v3, vw);
157
158 // should fail
159 EXPECT_FALSE(m.ReadInt(&iter, &vi));
160 EXPECT_FALSE(m.ReadString(&iter, &vs));
161 EXPECT_FALSE(m.ReadWString(&iter, &vw));
162}
163
164static void Send(IPC::Message::Sender* sender, const char* text) {
165 static int message_index = 0;
166
167 IPC::Message* message = new IPC::Message(0,
168 2,
169 IPC::Message::PRIORITY_NORMAL);
170 message->WriteInt(message_index++);
171 message->WriteString(std::string(text));
172
[email protected]3d1b6662009-01-29 17:03:11173 // Make sure we can handle large messages.
[email protected]c2f10ed2009-02-10 00:52:57174 char junk[kLongMessageStringNumBytes];
[email protected]3d1b6662009-01-29 17:03:11175 memset(junk, 'a', sizeof(junk)-1);
initial.commit09911bf2008-07-26 23:55:29176 junk[sizeof(junk)-1] = 0;
177 message->WriteString(std::string(junk));
178
179 // DEBUG: printf("[%u] sending message [%s]\n", GetCurrentProcessId(), text);
180 sender->Send(message);
181}
182
183class MyChannelListener : public IPC::Channel::Listener {
184 public:
[email protected]a95986a82010-12-24 06:19:28185 virtual bool OnMessageReceived(const IPC::Message& message) {
initial.commit09911bf2008-07-26 23:55:29186 IPC::MessageIterator iter(message);
187
[email protected]d4651ff2008-12-02 16:51:58188 iter.NextInt();
initial.commit09911bf2008-07-26 23:55:29189 const std::string data = iter.NextString();
[email protected]c2f10ed2009-02-10 00:52:57190 const std::string big_string = iter.NextString();
191 EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length());
192
193
initial.commit09911bf2008-07-26 23:55:29194 if (--messages_left_ == 0) {
195 MessageLoop::current()->Quit();
196 } else {
197 Send(sender_, "Foo");
198 }
[email protected]a95986a82010-12-24 06:19:28199 return true;
initial.commit09911bf2008-07-26 23:55:29200 }
201
[email protected]b6be5882008-11-07 21:53:03202 virtual void OnChannelError() {
203 // There is a race when closing the channel so the last message may be lost.
204 EXPECT_LE(messages_left_, 1);
205 MessageLoop::current()->Quit();
206 }
207
initial.commit09911bf2008-07-26 23:55:29208 void Init(IPC::Message::Sender* s) {
209 sender_ = s;
210 messages_left_ = 50;
211 }
212
213 private:
214 IPC::Message::Sender* sender_;
215 int messages_left_;
216};
initial.commit09911bf2008-07-26 23:55:29217
[email protected]95cb7fb92008-12-09 22:00:47218TEST_F(IPCChannelTest, ChannelTest) {
[email protected]c2f10ed2009-02-10 00:52:57219 MyChannelListener channel_listener;
[email protected]3d1b6662009-01-29 17:03:11220 // Setup IPC channel.
initial.commit09911bf2008-07-26 23:55:29221 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
222 &channel_listener);
[email protected]39703fb2010-10-19 19:11:15223 ASSERT_TRUE(chan.Connect());
initial.commit09911bf2008-07-26 23:55:29224
225 channel_listener.Init(&chan);
226
[email protected]df3c1ca12008-12-19 21:37:01227 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan);
initial.commit09911bf2008-07-26 23:55:29228 ASSERT_TRUE(process_handle);
229
230 Send(&chan, "hello from parent");
231
[email protected]3d1b6662009-01-29 17:03:11232 // Run message loop.
initial.commit09911bf2008-07-26 23:55:29233 MessageLoop::current()->Run();
234
[email protected]3d1b6662009-01-29 17:03:11235 // Close Channel so client gets its OnChannelError() callback fired.
236 chan.Close();
237
238 // Cleanup child process.
[email protected]95cb7fb92008-12-09 22:00:47239 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
[email protected]cd4fd152009-02-09 19:28:41240 base::CloseProcessHandle(process_handle);
initial.commit09911bf2008-07-26 23:55:29241}
242
[email protected]a7c03d4f32012-01-24 02:36:05243#if defined(OS_WIN)
244TEST_F(IPCChannelTest, ChannelTestExistingPipe) {
245 MyChannelListener channel_listener;
246 // Setup IPC channel with existing pipe. Specify name in Chrome format.
247 std::string name("\\\\.\\pipe\\chrome.");
248 name.append(kTestClientChannel);
249 const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
250 FILE_FLAG_FIRST_PIPE_INSTANCE;
251 HANDLE pipe = CreateNamedPipeA(name.c_str(),
252 open_mode,
253 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
254 1,
255 4096,
256 4096,
257 5000,
258 NULL);
259 IPC::Channel chan(IPC::ChannelHandle(pipe), IPC::Channel::MODE_SERVER,
260 &channel_listener);
261 // Channel will duplicate the handle.
262 CloseHandle(pipe);
263 ASSERT_TRUE(chan.Connect());
264
265 channel_listener.Init(&chan);
266
267 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan);
268 ASSERT_TRUE(process_handle);
269
270 Send(&chan, "hello from parent");
271
272 // Run message loop.
273 MessageLoop::current()->Run();
274
275 // Close Channel so client gets its OnChannelError() callback fired.
276 chan.Close();
277
278 // Cleanup child process.
279 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
280 base::CloseProcessHandle(process_handle);
281}
282#endif // defined (OS_WIN)
283
[email protected]95cb7fb92008-12-09 22:00:47284TEST_F(IPCChannelTest, ChannelProxyTest) {
[email protected]c2f10ed2009-02-10 00:52:57285 MyChannelListener channel_listener;
286
initial.commit09911bf2008-07-26 23:55:29287 // The thread needs to out-live the ChannelProxy.
[email protected]ab820df2008-08-26 05:55:10288 base::Thread thread("ChannelProxyTestServer");
289 base::Thread::Options options;
290 options.message_loop_type = MessageLoop::TYPE_IO;
291 thread.StartWithOptions(options);
initial.commit09911bf2008-07-26 23:55:29292 {
293 // setup IPC channel proxy
294 IPC::ChannelProxy chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
[email protected]bf84c582011-08-23 03:17:02295 &channel_listener, thread.message_loop_proxy());
initial.commit09911bf2008-07-26 23:55:29296
297 channel_listener.Init(&chan);
298
[email protected]e74488c2008-12-22 22:43:41299#if defined(OS_WIN)
[email protected]bb975362009-01-21 01:00:22300 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, NULL);
[email protected]e74488c2008-12-22 22:43:41301#elif defined(OS_POSIX)
[email protected]bb975362009-01-21 01:00:22302 bool debug_on_start = CommandLine::ForCurrentProcess()->HasSwitch(
303 switches::kDebugChildren);
[email protected]a82af392012-02-24 04:40:20304 base::FileHandleMappingVector fds_to_map;
[email protected]cc8f1462009-06-12 17:36:55305 const int ipcfd = chan.GetClientFileDescriptor();
306 if (ipcfd > -1) {
[email protected]b7243c42010-07-23 05:23:13307 fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3));
[email protected]e74488c2008-12-22 22:43:41308 }
309
[email protected]df3c1ca12008-12-19 21:37:01310 base::ProcessHandle process_handle = MultiProcessTest::SpawnChild(
[email protected]d420c31e2010-07-30 02:14:22311 "RunTestClient",
[email protected]e74488c2008-12-22 22:43:41312 fds_to_map,
[email protected]df3c1ca12008-12-19 21:37:01313 debug_on_start);
[email protected]1db97ce72009-08-21 21:53:54314#endif // defined(OS_POSIX)
[email protected]e74488c2008-12-22 22:43:41315
initial.commit09911bf2008-07-26 23:55:29316 ASSERT_TRUE(process_handle);
317
318 Send(&chan, "hello from parent");
319
320 // run message loop
321 MessageLoop::current()->Run();
322
323 // cleanup child process
[email protected]df3c1ca12008-12-19 21:37:01324 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
[email protected]cd4fd152009-02-09 19:28:41325 base::CloseProcessHandle(process_handle);
initial.commit09911bf2008-07-26 23:55:29326 }
327 thread.Stop();
328}
329
[email protected]052fd452009-09-23 17:56:25330class ChannelListenerWithOnConnectedSend : public IPC::Channel::Listener {
331 public:
[email protected]da1bd182011-08-16 21:09:25332 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
[email protected]052fd452009-09-23 17:56:25333 SendNextMessage();
334 }
335
[email protected]da1bd182011-08-16 21:09:25336 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
[email protected]052fd452009-09-23 17:56:25337 IPC::MessageIterator iter(message);
338
339 iter.NextInt();
340 const std::string data = iter.NextString();
341 const std::string big_string = iter.NextString();
342 EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length());
343 SendNextMessage();
[email protected]a95986a82010-12-24 06:19:28344 return true;
[email protected]052fd452009-09-23 17:56:25345 }
346
[email protected]da1bd182011-08-16 21:09:25347 virtual void OnChannelError() OVERRIDE {
[email protected]052fd452009-09-23 17:56:25348 // There is a race when closing the channel so the last message may be lost.
349 EXPECT_LE(messages_left_, 1);
350 MessageLoop::current()->Quit();
351 }
352
353 void Init(IPC::Message::Sender* s) {
354 sender_ = s;
355 messages_left_ = 50;
356 }
357
358 private:
359 void SendNextMessage() {
360 if (--messages_left_ == 0) {
361 MessageLoop::current()->Quit();
362 } else {
363 Send(sender_, "Foo");
364 }
365 }
366
367 IPC::Message::Sender* sender_;
368 int messages_left_;
369};
370
371TEST_F(IPCChannelTest, SendMessageInChannelConnected) {
372 // This tests the case of a listener sending back an event in it's
373 // OnChannelConnected handler.
374
375 ChannelListenerWithOnConnectedSend channel_listener;
376 // Setup IPC channel.
377 IPC::Channel channel(kTestClientChannel, IPC::Channel::MODE_SERVER,
378 &channel_listener);
379 channel_listener.Init(&channel);
[email protected]39703fb2010-10-19 19:11:15380 ASSERT_TRUE(channel.Connect());
[email protected]052fd452009-09-23 17:56:25381
382 base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &channel);
383 ASSERT_TRUE(process_handle);
384
385 Send(&channel, "hello from parent");
386
387 // Run message loop.
388 MessageLoop::current()->Run();
389
390 // Close Channel so client gets its OnChannelError() callback fired.
391 channel.Close();
392
393 // Cleanup child process.
394 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
395 base::CloseProcessHandle(process_handle);
396}
397
[email protected]95cb7fb92008-12-09 22:00:47398MULTIPROCESS_TEST_MAIN(RunTestClient) {
399 MessageLoopForIO main_message_loop;
[email protected]c2f10ed2009-02-10 00:52:57400 MyChannelListener channel_listener;
[email protected]95cb7fb92008-12-09 22:00:47401
initial.commit09911bf2008-07-26 23:55:29402 // setup IPC channel
403 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
404 &channel_listener);
[email protected]39703fb2010-10-19 19:11:15405 CHECK(chan.Connect());
initial.commit09911bf2008-07-26 23:55:29406 channel_listener.Init(&chan);
407 Send(&chan, "hello from child");
408 // run message loop
409 MessageLoop::current()->Run();
[email protected]95cb7fb92008-12-09 22:00:47410 // return true;
[email protected]8b8fab972011-01-13 16:27:18411 return 0;
initial.commit09911bf2008-07-26 23:55:29412}
[email protected]526776c2009-02-07 00:39:26413
initial.commit09911bf2008-07-26 23:55:29414#endif // !PERFORMANCE_TEST
415
416#ifdef PERFORMANCE_TEST
417
418//-----------------------------------------------------------------------------
419// Manually performance test
420//
421// This test times the roundtrip IPC message cycle. It is enabled with a
422// special preprocessor define to enable it instead of the standard IPC
423// unit tests. This works around some funny termination conditions in the
424// regular unit tests.
425//
426// This test is not automated. To test, you will want to vary the message
427// count and message size in TEST to get the numbers you want.
428//
429// FIXME(brettw): Automate this test and have it run by default.
430
431// This channel listener just replies to all messages with the exact same
432// message. It assumes each message has one string parameter. When the string
433// "quit" is sent, it will exit.
434class ChannelReflectorListener : public IPC::Channel::Listener {
435 public:
[email protected]95cb7fb92008-12-09 22:00:47436 explicit ChannelReflectorListener(IPC::Channel *channel) :
initial.commit09911bf2008-07-26 23:55:29437 channel_(channel),
438 count_messages_(0),
439 latency_messages_(0) {
440 std::cout << "Reflector up" << std::endl;
441 }
442
443 ~ChannelReflectorListener() {
444 std::cout << "Client Messages: " << count_messages_ << std::endl;
445 std::cout << "Client Latency: " << latency_messages_ << std::endl;
446 }
447
[email protected]a95986a82010-12-24 06:19:28448 virtual bool OnMessageReceived(const IPC::Message& message) {
initial.commit09911bf2008-07-26 23:55:29449 count_messages_++;
450 IPC::MessageIterator iter(message);
451 int time = iter.NextInt();
452 int msgid = iter.NextInt();
453 std::string payload = iter.NextString();
454 latency_messages_ += GetTickCount() - time;
455
456 // cout << "reflector msg received: " << msgid << endl;
457 if (payload == "quit")
458 MessageLoop::current()->Quit();
459
460 IPC::Message* msg = new IPC::Message(0,
461 2,
462 IPC::Message::PRIORITY_NORMAL);
463 msg->WriteInt(GetTickCount());
464 msg->WriteInt(msgid);
465 msg->WriteString(payload);
466 channel_->Send(msg);
[email protected]a95986a82010-12-24 06:19:28467 return true;
initial.commit09911bf2008-07-26 23:55:29468 }
[email protected]a82af392012-02-24 04:40:20469
initial.commit09911bf2008-07-26 23:55:29470 private:
471 IPC::Channel *channel_;
472 int count_messages_;
473 int latency_messages_;
474};
475
476class ChannelPerfListener : public IPC::Channel::Listener {
477 public:
478 ChannelPerfListener(IPC::Channel* channel, int msg_count, int msg_size) :
479 count_down_(msg_count),
480 channel_(channel),
481 count_messages_(0),
482 latency_messages_(0) {
483 payload_.resize(msg_size);
484 for (int i = 0; i < static_cast<int>(payload_.size()); i++)
485 payload_[i] = 'a';
486 std::cout << "perflistener up" << std::endl;
487 }
488
489 ~ChannelPerfListener() {
490 std::cout << "Server Messages: " << count_messages_ << std::endl;
491 std::cout << "Server Latency: " << latency_messages_ << std::endl;
492 }
493
[email protected]a95986a82010-12-24 06:19:28494 virtual bool OnMessageReceived(const IPC::Message& message) {
initial.commit09911bf2008-07-26 23:55:29495 count_messages_++;
496 // decode the string so this gets counted in the total time
497 IPC::MessageIterator iter(message);
498 int time = iter.NextInt();
499 int msgid = iter.NextInt();
500 std::string cur = iter.NextString();
501 latency_messages_ += GetTickCount() - time;
502
503 // cout << "perflistener got message" << endl;
504
505 count_down_--;
506 if (count_down_ == 0) {
507 IPC::Message* msg = new IPC::Message(0,
508 2,
509 IPC::Message::PRIORITY_NORMAL);
510 msg->WriteInt(GetTickCount());
511 msg->WriteInt(count_down_);
512 msg->WriteString("quit");
513 channel_->Send(msg);
514 SetTimer(NULL, 1, 250, (TIMERPROC) PostQuitMessage);
[email protected]a95986a82010-12-24 06:19:28515 return true;
initial.commit09911bf2008-07-26 23:55:29516 }
517
518 IPC::Message* msg = new IPC::Message(0,
519 2,
520 IPC::Message::PRIORITY_NORMAL);
521 msg->WriteInt(GetTickCount());
522 msg->WriteInt(count_down_);
523 msg->WriteString(payload_);
524 channel_->Send(msg);
[email protected]a95986a82010-12-24 06:19:28525 return true;
initial.commit09911bf2008-07-26 23:55:29526 }
527
528 private:
529 int count_down_;
530 std::string payload_;
531 IPC::Channel *channel_;
532 int count_messages_;
533 int latency_messages_;
534};
535
[email protected]95cb7fb92008-12-09 22:00:47536TEST_F(IPCChannelTest, Performance) {
initial.commit09911bf2008-07-26 23:55:29537 // setup IPC channel
538 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_SERVER, NULL);
539 ChannelPerfListener perf_listener(&chan, 10000, 100000);
540 chan.set_listener(&perf_listener);
[email protected]39703fb2010-10-19 19:11:15541 ASSERT_TRUE(chan.Connect());
initial.commit09911bf2008-07-26 23:55:29542
[email protected]df3c1ca12008-12-19 21:37:01543 HANDLE process = SpawnChild(TEST_REFLECTOR, &chan);
initial.commit09911bf2008-07-26 23:55:29544 ASSERT_TRUE(process);
545
[email protected]b5393332012-01-13 00:11:01546 PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
initial.commit09911bf2008-07-26 23:55:29547
548 PerfTimeLogger logger("IPC_Perf");
549
550 // this initial message will kick-start the ping-pong of messages
551 IPC::Message* message = new IPC::Message(0,
552 2,
553 IPC::Message::PRIORITY_NORMAL);
554 message->WriteInt(GetTickCount());
555 message->WriteInt(-1);
556 message->WriteString("Hello");
557 chan.Send(message);
558
559 // run message loop
560 MessageLoop::current()->Run();
561
562 // cleanup child process
563 WaitForSingleObject(process, 5000);
564 CloseHandle(process);
565}
566
567// This message loop bounces all messages back to the sender
[email protected]95cb7fb92008-12-09 22:00:47568MULTIPROCESS_TEST_MAIN(RunReflector) {
569 MessageLoopForIO main_message_loop;
initial.commit09911bf2008-07-26 23:55:29570 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_CLIENT, NULL);
571 ChannelReflectorListener channel_reflector_listener(&chan);
572 chan.set_listener(&channel_reflector_listener);
[email protected]39703fb2010-10-19 19:11:15573 ASSERT_TRUE(chan.Connect());
initial.commit09911bf2008-07-26 23:55:29574
575 MessageLoop::current()->Run();
576 return true;
577}
578
579#endif // PERFORMANCE_TEST
580
initial.commit09911bf2008-07-26 23:55:29581int main(int argc, char** argv) {
[email protected]95cb7fb92008-12-09 22:00:47582#ifdef PERFORMANCE_TEST
[email protected]99cc51e2010-10-10 00:21:35583 int retval = base::PerfTestSuite(argc, argv).Run();
[email protected]302831b2009-01-13 22:35:10584#else
[email protected]20e14912010-08-17 19:40:11585 int retval = base::TestSuite(argc, argv).Run();
initial.commit09911bf2008-07-26 23:55:29586#endif
[email protected]95cb7fb92008-12-09 22:00:47587 return retval;
initial.commit09911bf2008-07-26 23:55:29588}