summaryrefslogtreecommitdiffstats
path: root/chrome/common/service_process_util_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common/service_process_util_unittest.cc')
-rw-r--r--chrome/common/service_process_util_unittest.cc142
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;
}