diff options
Diffstat (limited to 'chrome/common/service_process_util_unittest.cc')
-rw-r--r-- | chrome/common/service_process_util_unittest.cc | 142 |
1 files changed, 114 insertions, 28 deletions
diff --git a/chrome/common/service_process_util_unittest.cc b/chrome/common/service_process_util_unittest.cc index 58b68e1..ad6b257 100644 --- a/chrome/common/service_process_util_unittest.cc +++ b/chrome/common/service_process_util_unittest.cc @@ -5,10 +5,25 @@ #include "base/at_exit.h" #include "base/process_util.h" #include "base/string_util.h" +#include "base/test/multiprocess_test.h" +#include "base/test/test_timeouts.h" +#include "base/threading/thread.h" #include "chrome/common/chrome_version_info.h" #include "chrome/common/service_process_util.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "testing/multiprocess_func_list.h" +namespace { + +bool g_good_shutdown = false; + +void ShutdownTask(MessageLoop* loop) { + // Quit the main message loop. + ASSERT_FALSE(g_good_shutdown); + g_good_shutdown = true; + loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); +} + +} // namespace TEST(ServiceProcessUtilTest, ScopedVersionedName) { std::string test_str = "test"; @@ -19,55 +34,126 @@ TEST(ServiceProcessUtilTest, ScopedVersionedName) { EXPECT_NE(std::string::npos, scoped_name.find(version_info.Version())); } -class ServiceProcessStateTest : public testing::Test { +class ServiceProcessStateTest : public base::MultiProcessTest { + public: + ServiceProcessStateTest(); + ~ServiceProcessStateTest(); + virtual void SetUp(); + base::MessageLoopProxy* IOMessageLoopProxy() { + return io_thread_.message_loop_proxy(); + } + void LaunchAndWait(const std::string& name); + private: // This is used to release the ServiceProcessState singleton after each test. base::ShadowingAtExitManager at_exit_manager_; + base::Thread io_thread_; }; -#if defined(OS_WIN) -// Singleton-ness is only implemented on Windows. -// TODO(sanjeev): Rewrite this test to spawn a new process and test using the -// ServiceProcessState singleton across processes. -/* +ServiceProcessStateTest::ServiceProcessStateTest() + : io_thread_("ServiceProcessStateTestThread") { +} + +ServiceProcessStateTest::~ServiceProcessStateTest() { +} + +void ServiceProcessStateTest::SetUp() { + base::Thread::Options options(MessageLoop::TYPE_IO, 0); + ASSERT_TRUE(io_thread_.StartWithOptions(options)); +} + +void ServiceProcessStateTest::LaunchAndWait(const std::string& name) { + base::ProcessHandle handle = SpawnChild(name, false); + ASSERT_TRUE(handle); + int exit_code = 0; + ASSERT_TRUE(base::WaitForExitCode(handle, &exit_code)); + ASSERT_EQ(exit_code, 0); +} + TEST_F(ServiceProcessStateTest, Singleton) { - ServiceProcessState state; - EXPECT_TRUE(state.Initialize()); - // The second instance should fail to Initialize. - ServiceProcessState another_state; - EXPECT_FALSE(another_state.Initialize()); + ServiceProcessState* state = ServiceProcessState::GetInstance(); + ASSERT_TRUE(state->Initialize()); + LaunchAndWait("ServiceProcessStateTestSingleton"); } -*/ -#endif // defined(OS_WIN) TEST_F(ServiceProcessStateTest, ReadyState) { -#if defined(OS_WIN) - // On Posix, we use a lock file on disk to signal readiness. This lock file - // could be lying around from previous crashes which could cause - // CheckServiceProcessReady to lie. On Windows, we use a named event so we - // don't have this issue. Until we have a more stable signalling mechanism on - // Posix, this check will only execute on Windows. - EXPECT_FALSE(CheckServiceProcessReady()); -#endif // defined(OS_WIN) + ASSERT_FALSE(CheckServiceProcessReady()); ServiceProcessState* state = ServiceProcessState::GetInstance(); - EXPECT_TRUE(state->Initialize()); - state->SignalReady(NULL); - EXPECT_TRUE(CheckServiceProcessReady()); + ASSERT_TRUE(state->Initialize()); + ASSERT_TRUE(state->SignalReady(IOMessageLoopProxy(), NULL)); + LaunchAndWait("ServiceProcessStateTestReadyTrue"); state->SignalStopped(); - EXPECT_FALSE(CheckServiceProcessReady()); + LaunchAndWait("ServiceProcessStateTestReadyFalse"); } TEST_F(ServiceProcessStateTest, SharedMem) { + std::string version; + base::ProcessId pid; #if defined(OS_WIN) // On Posix, named shared memory uses a file on disk. This file // could be lying around from previous crashes which could cause // GetServiceProcessPid to lie. On Windows, we use a named event so we // don't have this issue. Until we have a more stable shared memory // implementation on Posix, this check will only execute on Windows. - EXPECT_EQ(0, GetServiceProcessPid()); + ASSERT_FALSE(GetServiceProcessSharedData(&version, &pid)); #endif // defined(OS_WIN) ServiceProcessState* state = ServiceProcessState::GetInstance(); + ASSERT_TRUE(state->Initialize()); + ASSERT_TRUE(GetServiceProcessSharedData(&version, &pid)); + ASSERT_EQ(base::GetCurrentProcId(), pid); +} + +TEST_F(ServiceProcessStateTest, ForceShutdown) { + base::ProcessHandle handle = SpawnChild("ServiceProcessStateTestShutdown", + true); + ASSERT_TRUE(handle); + for (int i = 0; !CheckServiceProcessReady() && i < 10; ++i) { + base::PlatformThread::Sleep(TestTimeouts::tiny_timeout_ms()); + } + ASSERT_TRUE(CheckServiceProcessReady()); + std::string version; + base::ProcessId pid; + ASSERT_TRUE(GetServiceProcessSharedData(&version, &pid)); + ASSERT_TRUE(ForceServiceProcessShutdown(version, pid)); + int exit_code = 0; + ASSERT_TRUE(base::WaitForExitCodeWithTimeout(handle, + &exit_code, TestTimeouts::action_timeout_ms() * 2)); + ASSERT_EQ(exit_code, 0); +} + +MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestSingleton) { + ServiceProcessState* state = ServiceProcessState::GetInstance(); + EXPECT_FALSE(state->Initialize()); + return 0; +} + +MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyTrue) { + EXPECT_TRUE(CheckServiceProcessReady()); + return 0; +} + +MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyFalse) { + EXPECT_FALSE(CheckServiceProcessReady()); + return 0; +} + +MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestShutdown) { + MessageLoop message_loop; + message_loop.set_thread_name("ServiceProcessStateTestShutdownMainThread"); + base::Thread io_thread_("ServiceProcessStateTestShutdownIOThread"); + base::Thread::Options options(MessageLoop::TYPE_IO, 0); + EXPECT_TRUE(io_thread_.StartWithOptions(options)); + ServiceProcessState* state = ServiceProcessState::GetInstance(); EXPECT_TRUE(state->Initialize()); - EXPECT_EQ(base::GetCurrentProcId(), GetServiceProcessPid()); + EXPECT_TRUE(state->SignalReady(io_thread_.message_loop_proxy(), + NewRunnableFunction(&ShutdownTask, + MessageLoop::current()))); + message_loop.PostDelayedTask(FROM_HERE, + new MessageLoop::QuitTask(), + TestTimeouts::action_max_timeout_ms()); + EXPECT_FALSE(g_good_shutdown); + message_loop.Run(); + EXPECT_TRUE(g_good_shutdown); + return 0; } |