OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "build/build_config.h" | 5 #include "build/build_config.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <windows.h> | 8 #include <windows.h> |
9 #elif defined(OS_POSIX) | 9 #elif defined(OS_POSIX) |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
11 #include <unistd.h> | 11 #include <unistd.h> |
12 #endif | 12 #endif |
13 | 13 |
14 #include <stdio.h> | 14 #include <stdio.h> |
15 #include <string> | 15 #include <string> |
16 #include <utility> | 16 #include <utility> |
17 | 17 |
18 #include "ipc/ipc_tests.h" | 18 #include "ipc/ipc_tests.h" |
19 | 19 |
20 #include "base/base_switches.h" | 20 #include "base/base_switches.h" |
21 #include "base/command_line.h" | 21 #include "base/command_line.h" |
22 #include "base/debug/debug_on_start_win.h" | 22 #include "base/debug/debug_on_start_win.h" |
23 #include "base/perftimer.h" | 23 #include "base/perftimer.h" |
24 #include "base/pickle.h" | 24 #include "base/pickle.h" |
25 #include "base/test/perf_test_suite.h" | 25 #include "base/test/perf_test_suite.h" |
26 #include "base/test/test_suite.h" | 26 #include "base/test/test_suite.h" |
27 #include "base/threading/thread.h" | 27 #include "base/threading/thread.h" |
| 28 #include "base/time.h" |
28 #include "ipc/ipc_descriptors.h" | 29 #include "ipc/ipc_descriptors.h" |
29 #include "ipc/ipc_channel.h" | 30 #include "ipc/ipc_channel.h" |
30 #include "ipc/ipc_channel_proxy.h" | 31 #include "ipc/ipc_channel_proxy.h" |
31 #include "ipc/ipc_message_utils.h" | 32 #include "ipc/ipc_message_utils.h" |
32 #include "ipc/ipc_multiprocess_test.h" | 33 #include "ipc/ipc_multiprocess_test.h" |
33 #include "ipc/ipc_sender.h" | 34 #include "ipc/ipc_sender.h" |
34 #include "ipc/ipc_switches.h" | 35 #include "ipc/ipc_switches.h" |
35 #include "testing/multiprocess_func_list.h" | 36 #include "testing/multiprocess_func_list.h" |
36 | 37 |
37 // Define to enable IPC performance testing instead of the regular unit tests | 38 // Define to enable IPC performance testing instead of the regular unit tests |
38 // #define PERFORMANCE_TEST | 39 // #define PERFORMANCE_TEST |
39 | 40 |
40 const char kTestClientChannel[] = "T1"; | 41 const char kTestClientChannel[] = "T1"; |
41 const char kReflectorChannel[] = "T2"; | 42 const char kReflectorChannel[] = "T2"; |
42 const char kFuzzerChannel[] = "F3"; | 43 const char kFuzzerChannel[] = "F3"; |
43 const char kSyncSocketChannel[] = "S4"; | 44 const char kSyncSocketChannel[] = "S4"; |
44 | 45 |
45 const size_t kLongMessageStringNumBytes = 50000; | 46 const size_t kLongMessageStringNumBytes = 50000; |
46 | 47 |
47 #ifndef PERFORMANCE_TEST | |
48 | |
49 void IPCChannelTest::SetUp() { | 48 void IPCChannelTest::SetUp() { |
50 MultiProcessTest::SetUp(); | 49 MultiProcessTest::SetUp(); |
51 | 50 |
52 // Construct a fresh IO Message loop for the duration of each test. | 51 // Construct a fresh IO Message loop for the duration of each test. |
53 message_loop_ = new MessageLoopForIO(); | 52 message_loop_ = new MessageLoopForIO(); |
54 } | 53 } |
55 | 54 |
56 void IPCChannelTest::TearDown() { | 55 void IPCChannelTest::TearDown() { |
57 delete message_loop_; | 56 delete message_loop_; |
58 message_loop_ = NULL; | 57 message_loop_ = NULL; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 debug_on_start); | 125 debug_on_start); |
127 break; | 126 break; |
128 default: | 127 default: |
129 return base::kNullProcessHandle; | 128 return base::kNullProcessHandle; |
130 break; | 129 break; |
131 } | 130 } |
132 return ret; | 131 return ret; |
133 } | 132 } |
134 #endif // defined(OS_POSIX) | 133 #endif // defined(OS_POSIX) |
135 | 134 |
| 135 #ifndef PERFORMANCE_TEST |
136 TEST_F(IPCChannelTest, BasicMessageTest) { | 136 TEST_F(IPCChannelTest, BasicMessageTest) { |
137 int v1 = 10; | 137 int v1 = 10; |
138 std::string v2("foobar"); | 138 std::string v2("foobar"); |
139 std::wstring v3(L"hello world"); | 139 std::wstring v3(L"hello world"); |
140 | 140 |
141 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); | 141 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); |
142 EXPECT_TRUE(m.WriteInt(v1)); | 142 EXPECT_TRUE(m.WriteInt(v1)); |
143 EXPECT_TRUE(m.WriteString(v2)); | 143 EXPECT_TRUE(m.WriteString(v2)); |
144 EXPECT_TRUE(m.WriteWString(v3)); | 144 EXPECT_TRUE(m.WriteWString(v3)); |
145 | 145 |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 MyChannelListener channel_listener; | 419 MyChannelListener channel_listener; |
420 | 420 |
421 // setup IPC channel | 421 // setup IPC channel |
422 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT, | 422 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT, |
423 &channel_listener); | 423 &channel_listener); |
424 CHECK(chan.Connect()); | 424 CHECK(chan.Connect()); |
425 channel_listener.Init(&chan); | 425 channel_listener.Init(&chan); |
426 Send(&chan, "hello from child"); | 426 Send(&chan, "hello from child"); |
427 // run message loop | 427 // run message loop |
428 MessageLoop::current()->Run(); | 428 MessageLoop::current()->Run(); |
429 // return true; | |
430 return 0; | 429 return 0; |
431 } | 430 } |
432 | 431 |
433 #endif // !PERFORMANCE_TEST | 432 #endif // !PERFORMANCE_TEST |
434 | 433 |
435 #ifdef PERFORMANCE_TEST | 434 #ifdef PERFORMANCE_TEST |
436 | 435 |
437 //----------------------------------------------------------------------------- | 436 //----------------------------------------------------------------------------- |
438 // Manually performance test | 437 // Manually performance test |
439 // | 438 // |
440 // This test times the roundtrip IPC message cycle. It is enabled with a | 439 // This test times the roundtrip IPC message cycle. It is enabled with a |
441 // special preprocessor define to enable it instead of the standard IPC | 440 // special preprocessor define to enable it instead of the standard IPC |
442 // unit tests. This works around some funny termination conditions in the | 441 // unit tests. This works around some funny termination conditions in the |
443 // regular unit tests. | 442 // regular unit tests. |
444 // | 443 // |
445 // This test is not automated. To test, you will want to vary the message | 444 // This test is not automated. To test, you will want to vary the message |
446 // count and message size in TEST to get the numbers you want. | 445 // count and message size in TEST to get the numbers you want. |
447 // | 446 // |
448 // FIXME(brettw): Automate this test and have it run by default. | 447 // FIXME(brettw): Automate this test and have it run by default. |
449 | 448 |
450 // This channel listener just replies to all messages with the exact same | 449 // This channel listener just replies to all messages with the exact same |
451 // message. It assumes each message has one string parameter. When the string | 450 // message. It assumes each message has one string parameter. When the string |
452 // "quit" is sent, it will exit. | 451 // "quit" is sent, it will exit. |
453 class ChannelReflectorListener : public IPC::Listener { | 452 class ChannelReflectorListener : public IPC::Listener { |
454 public: | 453 public: |
455 explicit ChannelReflectorListener(IPC::Channel *channel) : | 454 explicit ChannelReflectorListener(IPC::Channel *channel) : |
456 channel_(channel), | 455 channel_(channel), |
457 count_messages_(0), | 456 count_messages_(0) { |
458 latency_messages_(0) { | |
459 std::cout << "Reflector up" << std::endl; | 457 std::cout << "Reflector up" << std::endl; |
460 } | 458 } |
461 | 459 |
462 ~ChannelReflectorListener() { | 460 ~ChannelReflectorListener() { |
463 std::cout << "Client Messages: " << count_messages_ << std::endl; | 461 std::cout << "Client Messages: " << count_messages_ << std::endl; |
464 std::cout << "Client Latency: " << latency_messages_ << std::endl; | 462 std::cout << "Client Latency: " << latency_messages_.InMilliseconds() |
| 463 << std::endl; |
465 } | 464 } |
466 | 465 |
467 virtual bool OnMessageReceived(const IPC::Message& message) { | 466 virtual bool OnMessageReceived(const IPC::Message& message) { |
468 count_messages_++; | 467 count_messages_++; |
469 PickleIterator iter(message); | 468 PickleIterator iter(message); |
470 int time; | 469 int64 time_internal; |
471 EXPECT_TRUE(iter.ReadInt(&time)); | 470 EXPECT_TRUE(iter.ReadInt64(&time_internal)); |
472 int msgid; | 471 int msgid; |
473 EXPECT_TRUE(iter.ReadInt(&msgid)); | 472 EXPECT_TRUE(iter.ReadInt(&msgid)); |
474 std::string payload = iter.NextString(); | 473 std::string payload; |
475 latency_messages_ += GetTickCount() - time; | 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); |
476 | 478 |
477 // cout << "reflector msg received: " << msgid << endl; | 479 // cout << "reflector msg received: " << msgid << endl; |
478 if (payload == "quit") | 480 if (payload == "quit") |
479 MessageLoop::current()->Quit(); | 481 MessageLoop::current()->Quit(); |
480 | 482 |
481 IPC::Message* msg = new IPC::Message(0, | 483 IPC::Message* msg = new IPC::Message(0, |
482 2, | 484 2, |
483 IPC::Message::PRIORITY_NORMAL); | 485 IPC::Message::PRIORITY_NORMAL); |
484 msg->WriteInt(GetTickCount()); | 486 msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); |
485 msg->WriteInt(msgid); | 487 msg->WriteInt(msgid); |
486 msg->WriteString(payload); | 488 msg->WriteString(payload); |
487 channel_->Send(msg); | 489 channel_->Send(msg); |
488 return true; | 490 return true; |
489 } | 491 } |
490 | 492 |
491 private: | 493 private: |
492 IPC::Channel *channel_; | 494 IPC::Channel *channel_; |
493 int count_messages_; | 495 int count_messages_; |
494 int latency_messages_; | 496 base::TimeDelta latency_messages_; |
495 }; | 497 }; |
496 | 498 |
497 class ChannelPerfListener : public IPC::Listener { | 499 class ChannelPerfListener : public IPC::Listener { |
498 public: | 500 public: |
499 ChannelPerfListener(IPC::Channel* channel, int msg_count, int msg_size) : | 501 ChannelPerfListener(IPC::Channel* channel, int msg_count, int msg_size) : |
500 count_down_(msg_count), | 502 count_down_(msg_count), |
501 channel_(channel), | 503 channel_(channel), |
502 count_messages_(0), | 504 count_messages_(0) { |
503 latency_messages_(0) { | |
504 payload_.resize(msg_size); | 505 payload_.resize(msg_size); |
505 for (int i = 0; i < static_cast<int>(payload_.size()); i++) | 506 for (int i = 0; i < static_cast<int>(payload_.size()); i++) |
506 payload_[i] = 'a'; | 507 payload_[i] = 'a'; |
507 std::cout << "perflistener up" << std::endl; | 508 std::cout << "perflistener up" << std::endl; |
508 } | 509 } |
509 | 510 |
510 ~ChannelPerfListener() { | 511 ~ChannelPerfListener() { |
511 std::cout << "Server Messages: " << count_messages_ << std::endl; | 512 std::cout << "Server Messages: " << count_messages_ << std::endl; |
512 std::cout << "Server Latency: " << latency_messages_ << std::endl; | 513 std::cout << "Server Latency: " << latency_messages_.InMilliseconds() |
| 514 << std::endl; |
513 } | 515 } |
514 | 516 |
515 virtual bool OnMessageReceived(const IPC::Message& message) { | 517 virtual bool OnMessageReceived(const IPC::Message& message) { |
516 count_messages_++; | 518 count_messages_++; |
517 // Decode the string so this gets counted in the total time. | 519 // Decode the string so this gets counted in the total time. |
518 PickleIterator iter(message); | 520 PickleIterator iter(message); |
519 int time; | 521 int64 time_internal; |
520 EXPECT_TRUE(iter.ReadInt(&time)); | 522 EXPECT_TRUE(iter.ReadInt64(&time_internal)); |
521 int msgid; | 523 int msgid; |
522 EXPECT_TRUE(iter.ReadInt(&msgid)); | 524 EXPECT_TRUE(iter.ReadInt(&msgid)); |
523 std::string cur = iter.NextString(); | 525 std::string cur; |
524 latency_messages_ += GetTickCount() - time; | 526 EXPECT_TRUE(iter.ReadString(&cur)); |
| 527 latency_messages_ += base::TimeTicks::Now() - |
| 528 base::TimeTicks::FromInternalValue(time_internal); |
525 | 529 |
526 count_down_--; | 530 count_down_--; |
527 if (count_down_ == 0) { | 531 if (count_down_ == 0) { |
528 IPC::Message* msg = new IPC::Message(0, | 532 IPC::Message* msg = new IPC::Message(0, |
529 2, | 533 2, |
530 IPC::Message::PRIORITY_NORMAL); | 534 IPC::Message::PRIORITY_NORMAL); |
531 msg->WriteInt(GetTickCount()); | 535 msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); |
532 msg->WriteInt(count_down_); | 536 msg->WriteInt(count_down_); |
533 msg->WriteString("quit"); | 537 msg->WriteString("quit"); |
534 channel_->Send(msg); | 538 channel_->Send(msg); |
535 SetTimer(NULL, 1, 250, (TIMERPROC) PostQuitMessage); | 539 |
| 540 MessageLoop::current()->QuitWhenIdle(); |
536 return true; | 541 return true; |
537 } | 542 } |
538 | 543 |
539 IPC::Message* msg = new IPC::Message(0, | 544 IPC::Message* msg = new IPC::Message(0, |
540 2, | 545 2, |
541 IPC::Message::PRIORITY_NORMAL); | 546 IPC::Message::PRIORITY_NORMAL); |
542 msg->WriteInt(GetTickCount()); | 547 msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); |
543 msg->WriteInt(count_down_); | 548 msg->WriteInt(count_down_); |
544 msg->WriteString(payload_); | 549 msg->WriteString(payload_); |
545 channel_->Send(msg); | 550 channel_->Send(msg); |
546 return true; | 551 return true; |
547 } | 552 } |
548 | 553 |
549 private: | 554 private: |
550 int count_down_; | 555 int count_down_; |
551 std::string payload_; | 556 std::string payload_; |
552 IPC::Channel *channel_; | 557 IPC::Channel *channel_; |
553 int count_messages_; | 558 int count_messages_; |
554 int latency_messages_; | 559 base::TimeDelta latency_messages_; |
555 }; | 560 }; |
556 | 561 |
557 TEST_F(IPCChannelTest, Performance) { | 562 TEST_F(IPCChannelTest, Performance) { |
558 // setup IPC channel | 563 // setup IPC channel |
559 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_SERVER, NULL); | 564 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_SERVER, NULL); |
560 ChannelPerfListener perf_listener(&chan, 10000, 100000); | 565 ChannelPerfListener perf_listener(&chan, 10000, 100000); |
561 chan.set_listener(&perf_listener); | 566 chan.set_listener(&perf_listener); |
562 ASSERT_TRUE(chan.Connect()); | 567 ASSERT_TRUE(chan.Connect()); |
563 | 568 |
564 HANDLE process = SpawnChild(TEST_REFLECTOR, &chan); | 569 base::ProcessHandle process_handle = SpawnChild(TEST_REFLECTOR, &chan); |
565 ASSERT_TRUE(process); | 570 ASSERT_TRUE(process_handle); |
566 | 571 |
567 PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); | 572 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); |
568 | 573 |
569 PerfTimeLogger logger("IPC_Perf"); | 574 PerfTimeLogger logger("IPC_Perf"); |
570 | 575 |
571 // this initial message will kick-start the ping-pong of messages | 576 // this initial message will kick-start the ping-pong of messages |
572 IPC::Message* message = new IPC::Message(0, | 577 IPC::Message* message = new IPC::Message(0, |
573 2, | 578 2, |
574 IPC::Message::PRIORITY_NORMAL); | 579 IPC::Message::PRIORITY_NORMAL); |
575 message->WriteInt(GetTickCount()); | 580 message->WriteInt64(base::TimeTicks::Now().ToInternalValue()); |
576 message->WriteInt(-1); | 581 message->WriteInt(-1); |
577 message->WriteString("Hello"); | 582 message->WriteString("Hello"); |
578 chan.Send(message); | 583 chan.Send(message); |
579 | 584 |
580 // run message loop | 585 // run message loop |
581 MessageLoop::current()->Run(); | 586 MessageLoop::current()->Run(); |
582 | 587 |
583 // cleanup child process | 588 // Clean up child process. |
584 WaitForSingleObject(process, 5000); | 589 EXPECT_TRUE(base::WaitForSingleProcess( |
585 CloseHandle(process); | 590 process_handle, base::TimeDelta::FromSeconds(5))); |
| 591 base::CloseProcessHandle(process_handle); |
586 } | 592 } |
587 | 593 |
588 // This message loop bounces all messages back to the sender | 594 // This message loop bounces all messages back to the sender |
589 MULTIPROCESS_IPC_TEST_MAIN(RunReflector) { | 595 MULTIPROCESS_IPC_TEST_MAIN(RunReflector) { |
590 MessageLoopForIO main_message_loop; | 596 MessageLoopForIO main_message_loop; |
591 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_CLIENT, NULL); | 597 IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_CLIENT, NULL); |
592 ChannelReflectorListener channel_reflector_listener(&chan); | 598 ChannelReflectorListener channel_reflector_listener(&chan); |
593 chan.set_listener(&channel_reflector_listener); | 599 chan.set_listener(&channel_reflector_listener); |
594 ASSERT_TRUE(chan.Connect()); | 600 CHECK(chan.Connect()); |
595 | 601 |
596 MessageLoop::current()->Run(); | 602 MessageLoop::current()->Run(); |
597 return true; | 603 return 0; |
598 } | 604 } |
599 | 605 |
600 #endif // PERFORMANCE_TEST | 606 #endif // PERFORMANCE_TEST |
601 | 607 |
602 int main(int argc, char** argv) { | 608 int main(int argc, char** argv) { |
603 #ifdef PERFORMANCE_TEST | 609 #ifdef PERFORMANCE_TEST |
604 int retval = base::PerfTestSuite(argc, argv).Run(); | 610 int retval = base::PerfTestSuite(argc, argv).Run(); |
605 #else | 611 #else |
606 int retval = base::TestSuite(argc, argv).Run(); | 612 int retval = base::TestSuite(argc, argv).Run(); |
607 #endif | 613 #endif |
608 return retval; | 614 return retval; |
609 } | 615 } |
OLD | NEW |