Index: chrome/browser/multi_process_notification_unittest.cc |
diff --git a/chrome/browser/multi_process_notification_unittest.cc b/chrome/browser/multi_process_notification_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8c42fcb5387b4d3374f2cc230aa03d048547f96f |
--- /dev/null |
+++ b/chrome/browser/multi_process_notification_unittest.cc |
@@ -0,0 +1,352 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/multi_process_notification.h" |
+ |
+#include "base/basictypes.h" |
+#include "base/compiler_specific.h" |
+#include "base/environment.h" |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/test/multiprocess_test.h" |
+#include "base/test/test_timeouts.h" |
+#include "base/time.h" |
+#include "chrome/browser/browser_thread.h" |
+#include "testing/multiprocess_func_list.h" |
+ |
+#if defined(OS_MACOSX) |
+// TODO(dmaclach): Remove defined(OS_MACOSX) once |
+// MultiProcessNotification is implemented on Win/Linux. |
+ |
+namespace { |
+ |
+const char kStartedNotificationName[] = "MultiProcessTestStartedNotification"; |
+const char kQuitNotificationName[] = "MultiProcessTestQuitNotification"; |
+ |
+void SpinRunLoop(int milliseconds) { |
+ MessageLoop *loop = MessageLoop::current(); |
+ |
+ // Post a quit task so that this loop eventually ends and we don't hang |
+ // in the case of a bad test. Usually, the run loop will quit sooner than |
+ // that because all tests use a MultiProcessNotificationTestQuit which quits |
+ // the current run loop when it gets a notification. |
+ loop->PostDelayedTask(FROM_HERE, new MessageLoop::QuitTask(), milliseconds); |
+ loop->Run(); |
+} |
+ |
+class SimpleDelegate |
+ : public multi_process_notification::Listener::Delegate { |
+ public: |
+ SimpleDelegate() |
+ : notification_received_(false), started_received_(false) { } |
+ virtual ~SimpleDelegate(); |
+ |
+ virtual void OnNotificationReceived( |
+ const std::string& name, |
+ multi_process_notification::Domain domain) OVERRIDE; |
+ virtual void OnListenerStarted( |
+ const std::string& name, multi_process_notification::Domain domain, |
+ bool success) OVERRIDE; |
+ |
+ bool WasNotificationReceived() { return notification_received_; } |
+ bool WasStartedReceived() { return started_received_; } |
+ |
+ private: |
+ bool notification_received_; |
+ bool started_received_; |
+ DISALLOW_COPY_AND_ASSIGN(SimpleDelegate); |
+}; |
+ |
+SimpleDelegate::~SimpleDelegate() { |
+} |
+ |
+void SimpleDelegate::OnNotificationReceived( |
+ const std::string& name, multi_process_notification::Domain domain) { |
+ notification_received_ = true; |
+} |
+ |
+void SimpleDelegate::OnListenerStarted( |
+ const std::string& name, multi_process_notification::Domain domain, |
+ bool success) { |
+ ASSERT_TRUE(success); |
+ started_received_ = true; |
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+} |
+ |
+class QuitterDelegate : public SimpleDelegate { |
+ public: |
+ QuitterDelegate() : SimpleDelegate() { } |
+ virtual ~QuitterDelegate(); |
+ |
+ virtual void OnNotificationReceived( |
+ const std::string& name, |
+ multi_process_notification::Domain domain) OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(QuitterDelegate); |
+}; |
+ |
+QuitterDelegate::~QuitterDelegate() { |
+} |
+ |
+void QuitterDelegate::OnNotificationReceived( |
+ const std::string& name, multi_process_notification::Domain domain) { |
+ SimpleDelegate::OnNotificationReceived(name, domain); |
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+} |
+ |
+int MultiProcessNotificationMain(multi_process_notification::Domain domain) { |
+ BrowserThread browser_thread(BrowserThread::IO); |
+ base::Thread::Options options(MessageLoop::TYPE_IO, 0); |
+ EXPECT_TRUE(browser_thread.StartWithOptions(options)); |
+ MessageLoop loop; |
+ QuitterDelegate quitter; |
+ multi_process_notification::Listener listener( |
+ kQuitNotificationName, domain, &quitter); |
+ EXPECT_TRUE(listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ EXPECT_TRUE(quitter.WasStartedReceived()); |
+ EXPECT_TRUE(multi_process_notification::Post(kStartedNotificationName, |
+ domain)); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ EXPECT_TRUE(quitter.WasNotificationReceived()); |
+ return 0; |
+} |
+ |
+} // namespace |
+ |
+class MultiProcessNotificationTest : public base::MultiProcessTest { |
+ public: |
+ MultiProcessNotificationTest(); |
+ |
+ void PostNotificationTest(multi_process_notification::Domain domain); |
+ void CrossPostNotificationTest(multi_process_notification::Domain domain); |
+ |
+ static void SetUpTestCase(); |
+ static void TearDownTestCase(); |
+ |
+ private: |
+ MessageLoop loop_; |
+ static BrowserThread* g_io_thread; |
+}; |
+ |
+MultiProcessNotificationTest::MultiProcessNotificationTest() { |
+} |
+ |
+BrowserThread* MultiProcessNotificationTest::g_io_thread = NULL; |
+ |
+void MultiProcessNotificationTest::SetUpTestCase() { |
+ g_io_thread = new BrowserThread(BrowserThread::IO); |
+ base::Thread::Options options(MessageLoop::TYPE_IO, 0); |
+ ASSERT_TRUE(g_io_thread->StartWithOptions(options)); |
+} |
+ |
+void MultiProcessNotificationTest::TearDownTestCase() { |
+ delete g_io_thread; |
+} |
+ |
+void MultiProcessNotificationTest::PostNotificationTest( |
+ multi_process_notification::Domain domain) { |
+ QuitterDelegate process_started; |
+ multi_process_notification::Listener listener( |
+ kStartedNotificationName, domain, &process_started); |
+ ASSERT_TRUE(listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(process_started.WasStartedReceived()); |
+ std::string process_name; |
+ switch (domain) { |
+ case multi_process_notification::ProfileDomain: |
+ process_name = "MultiProcessProfileNotificationMain"; |
+ break; |
+ |
+ case multi_process_notification::UserDomain: |
+ process_name = "MultiProcessUserNotificationMain"; |
+ break; |
+ |
+ case multi_process_notification::SystemDomain: |
+ process_name = "MultiProcessSystemNotificationMain"; |
+ break; |
+ } |
+ base::ProcessHandle handle = SpawnChild(process_name, false); |
+ ASSERT_TRUE(handle); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(process_started.WasNotificationReceived()); |
+ ASSERT_TRUE(multi_process_notification::Post(kQuitNotificationName, domain)); |
+ int exit_code = 0; |
+ EXPECT_TRUE(base::WaitForExitCodeWithTimeout( |
+ handle, &exit_code, TestTimeouts::action_max_timeout_ms())); |
+} |
+ |
+void MultiProcessNotificationTest::CrossPostNotificationTest( |
+ multi_process_notification::Domain domain) { |
+ // Check to make sure notifications sent to user domain aren't picked up |
+ // by system domain listeners and vice versa. |
+ std::string local_notification("QuitLocalNotification"); |
+ std::string final_notification("FinalQuitLocalNotification"); |
+ QuitterDelegate profile_quitter; |
+ QuitterDelegate user_quitter; |
+ QuitterDelegate system_quitter; |
+ QuitterDelegate final_quitter; |
+ multi_process_notification::Listener profile_listener( |
+ local_notification, multi_process_notification::ProfileDomain, |
+ &profile_quitter); |
+ multi_process_notification::Listener user_listener( |
+ local_notification, multi_process_notification::UserDomain, |
+ &user_quitter); |
+ multi_process_notification::Listener system_listener( |
+ local_notification, multi_process_notification::SystemDomain, |
+ &system_quitter); |
+ multi_process_notification::Listener final_listener( |
+ final_notification, multi_process_notification::UserDomain, |
+ &final_quitter); |
+ |
+ ASSERT_TRUE(profile_listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(profile_quitter.WasStartedReceived()); |
+ ASSERT_TRUE(user_listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(user_quitter.WasStartedReceived()); |
+ ASSERT_TRUE(system_listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(system_quitter.WasStartedReceived()); |
+ |
+ ASSERT_TRUE(multi_process_notification::Post(local_notification, domain)); |
+ SpinRunLoop(TestTimeouts::action_timeout_ms()); |
+ |
+ // Now send out a final_notification to queue up a notification |
+ // after the local_notification and make sure that all listeners have had a |
+ // chance to process local_notification before we check to see if they |
+ // were called. |
+ ASSERT_TRUE(final_listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ EXPECT_TRUE(final_quitter.WasStartedReceived()); |
+ ASSERT_TRUE(multi_process_notification::Post( |
+ final_notification, multi_process_notification::UserDomain)); |
+ SpinRunLoop(TestTimeouts::action_timeout_ms()); |
+ ASSERT_TRUE(final_quitter.WasNotificationReceived()); |
+ switch (domain) { |
+ case multi_process_notification::ProfileDomain: |
+ ASSERT_TRUE(profile_quitter.WasNotificationReceived()); |
+ ASSERT_FALSE(user_quitter.WasNotificationReceived()); |
+ ASSERT_FALSE(system_quitter.WasNotificationReceived()); |
+ break; |
+ |
+ case multi_process_notification::UserDomain: |
+ ASSERT_FALSE(profile_quitter.WasNotificationReceived()); |
+ ASSERT_TRUE(user_quitter.WasNotificationReceived()); |
+ ASSERT_FALSE(system_quitter.WasNotificationReceived()); |
+ break; |
+ |
+ case multi_process_notification::SystemDomain: |
+ ASSERT_FALSE(profile_quitter.WasNotificationReceived()); |
+ ASSERT_FALSE(user_quitter.WasNotificationReceived()); |
+ ASSERT_TRUE(system_quitter.WasNotificationReceived()); |
+ break; |
+ } |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, BasicCreationTest) { |
+ QuitterDelegate quitter; |
+ multi_process_notification::Listener local_listener( |
+ "BasicCreationTest", multi_process_notification::UserDomain, &quitter); |
+ ASSERT_TRUE(local_listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(quitter.WasStartedReceived()); |
+ multi_process_notification::Listener system_listener( |
+ "BasicCreationTest", multi_process_notification::SystemDomain, &quitter); |
+ ASSERT_TRUE(system_listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(quitter.WasStartedReceived()); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, PostInProcessNotification) { |
+ std::string local_notification("QuitLocalNotification"); |
+ QuitterDelegate quitter; |
+ multi_process_notification::Listener listener( |
+ local_notification, multi_process_notification::UserDomain, &quitter); |
+ |
+ ASSERT_TRUE(listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(quitter.WasStartedReceived()); |
+ ASSERT_TRUE(multi_process_notification::Post( |
+ local_notification, multi_process_notification::UserDomain)); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(quitter.WasNotificationReceived()); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, MultiListener) { |
+ std::string local_notification("LocalNotification"); |
+ std::string quit_local_notification("QuitLocalNotification"); |
+ |
+ SimpleDelegate delegate1; |
+ SimpleDelegate delegate2; |
+ multi_process_notification::Listener local_listener1( |
+ local_notification, multi_process_notification::UserDomain, |
+ &delegate1); |
+ multi_process_notification::Listener local_listener2( |
+ local_notification, multi_process_notification::UserDomain, |
+ &delegate2); |
+ |
+ QuitterDelegate quitter; |
+ |
+ multi_process_notification::Listener quit_listener(quit_local_notification, |
+ multi_process_notification::UserDomain, &quitter); |
+ |
+ ASSERT_TRUE(local_listener1.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(delegate1.WasStartedReceived()); |
+ ASSERT_TRUE(local_listener2.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(delegate2.WasStartedReceived()); |
+ ASSERT_TRUE(quit_listener.Start()); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(quitter.WasStartedReceived()); |
+ ASSERT_TRUE(multi_process_notification::Post( |
+ local_notification, multi_process_notification::UserDomain)); |
+ ASSERT_TRUE(multi_process_notification::Post( |
+ quit_local_notification, multi_process_notification::UserDomain)); |
+ SpinRunLoop(TestTimeouts::action_max_timeout_ms()); |
+ ASSERT_TRUE(delegate1.WasNotificationReceived()); |
+ ASSERT_TRUE(delegate2.WasNotificationReceived()); |
+ ASSERT_TRUE(quitter.WasNotificationReceived()); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, PostProfileNotification) { |
+ PostNotificationTest(multi_process_notification::ProfileDomain); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, PostUserNotification) { |
+ PostNotificationTest(multi_process_notification::UserDomain); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, PostSystemNotification) { |
+ PostNotificationTest(multi_process_notification::SystemDomain); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, ProfileCrossDomainPosting) { |
+ CrossPostNotificationTest(multi_process_notification::ProfileDomain); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, UserCrossDomainPosting) { |
+ CrossPostNotificationTest(multi_process_notification::UserDomain); |
+} |
+ |
+TEST_F(MultiProcessNotificationTest, SystemCrossDomainPosting) { |
+ CrossPostNotificationTest(multi_process_notification::SystemDomain); |
+} |
+ |
+MULTIPROCESS_TEST_MAIN(MultiProcessProfileNotificationMain) { |
+ return MultiProcessNotificationMain( |
+ multi_process_notification::ProfileDomain); |
+} |
+ |
+MULTIPROCESS_TEST_MAIN(MultiProcessUserNotificationMain) { |
+ return MultiProcessNotificationMain(multi_process_notification::UserDomain); |
+} |
+ |
+MULTIPROCESS_TEST_MAIN(MultiProcessSystemNotificationMain) { |
+ return MultiProcessNotificationMain(multi_process_notification::SystemDomain); |
+} |
+ |
+#endif // defined(OS_MACOSX) |