summaryrefslogtreecommitdiff
path: root/chromium/chrome/common/service_process_util_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/common/service_process_util_unittest.cc')
-rw-r--r--chromium/chrome/common/service_process_util_unittest.cc253
1 files changed, 253 insertions, 0 deletions
diff --git a/chromium/chrome/common/service_process_util_unittest.cc b/chromium/chrome/common/service_process_util_unittest.cc
new file mode 100644
index 00000000000..99ccc2c2476
--- /dev/null
+++ b/chromium/chrome/common/service_process_util_unittest.cc
@@ -0,0 +1,253 @@
+// Copyright (c) 2012 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/common/service_process_util.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/location.h"
+#include "base/process/kill.h"
+#include "base/process/launch.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_split.h"
+#include "base/test/task_environment.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/branding_buildflags.h"
+#include "build/build_config.h"
+
+#if !defined(OS_MACOSX)
+#include "base/at_exit.h"
+#include "base/message_loop/message_pump_type.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/thread.h"
+#include "chrome/common/chrome_switches.h"
+#include "components/version_info/version_info.h"
+#include "content/public/common/content_switches.h"
+#include "testing/multiprocess_func_list.h"
+
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif
+
+#if defined(OS_POSIX)
+#include "chrome/common/auto_start_linux.h"
+#endif
+
+#if defined(USE_AURA)
+// This test fails http://crbug.com/84854, and is very flaky on CrOS and
+// somewhat flaky on other Linux.
+#define MAYBE_ForceShutdown DISABLED_ForceShutdown
+#else
+#if defined(OS_LINUX) || defined(OS_WIN)
+#define MAYBE_ForceShutdown DISABLED_ForceShutdown
+#else
+#define MAYBE_ForceShutdown ForceShutdown
+#endif
+#endif
+
+namespace {
+
+bool g_good_shutdown = false;
+
+void ShutdownTask(base::RunLoop* loop) {
+ // Quit the main message loop.
+ ASSERT_FALSE(g_good_shutdown);
+ g_good_shutdown = true;
+ loop->QuitWhenIdle();
+}
+
+} // namespace
+
+TEST(ServiceProcessUtilTest, ScopedVersionedName) {
+ std::string test_str = "test";
+ std::string scoped_name = GetServiceProcessScopedVersionedName(test_str);
+ EXPECT_TRUE(base::EndsWith(scoped_name, test_str,
+ base::CompareCase::SENSITIVE));
+ EXPECT_NE(std::string::npos,
+ scoped_name.find(version_info::GetVersionNumber()));
+}
+
+class ServiceProcessStateTest : public base::MultiProcessTest {
+ public:
+ ServiceProcessStateTest();
+ ~ServiceProcessStateTest() override;
+ void SetUp() override;
+ base::SingleThreadTaskRunner* IOTaskRunner() {
+ return io_thread_.task_runner().get();
+ }
+ 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_;
+};
+
+ServiceProcessStateTest::ServiceProcessStateTest()
+ : io_thread_("ServiceProcessStateTestThread") {
+}
+
+ServiceProcessStateTest::~ServiceProcessStateTest() {
+}
+
+void ServiceProcessStateTest::SetUp() {
+ base::Thread::Options options(base::MessagePumpType::IO, 0);
+ ASSERT_TRUE(io_thread_.StartWithOptions(options));
+}
+
+void ServiceProcessStateTest::LaunchAndWait(const std::string& name) {
+ base::Process process = SpawnChild(name);
+ ASSERT_TRUE(process.IsValid());
+ int exit_code = 0;
+ ASSERT_TRUE(process.WaitForExit(&exit_code));
+ ASSERT_EQ(exit_code, 0);
+}
+
+TEST_F(ServiceProcessStateTest, Singleton) {
+ ServiceProcessState state;
+ ASSERT_TRUE(state.Initialize());
+ LaunchAndWait("ServiceProcessStateTestSingleton");
+}
+
+// http://crbug.com/396390
+TEST_F(ServiceProcessStateTest, DISABLED_ReadyState) {
+ ASSERT_FALSE(CheckServiceProcessReady());
+ ServiceProcessState state;
+ ASSERT_TRUE(state.Initialize());
+ ASSERT_TRUE(state.SignalReady(IOTaskRunner(), base::Closure()));
+ LaunchAndWait("ServiceProcessStateTestReadyTrue");
+ state.SignalStopped();
+ LaunchAndWait("ServiceProcessStateTestReadyFalse");
+}
+
+TEST_F(ServiceProcessStateTest, AutoRun) {
+ ServiceProcessState state;
+ ASSERT_TRUE(state.AddToAutoRun());
+ std::unique_ptr<base::CommandLine> autorun_command_line;
+#if defined(OS_WIN)
+ std::string value_name = GetServiceProcessScopedName("_service_run");
+ base::string16 value;
+ EXPECT_TRUE(base::win::ReadCommandFromAutoRun(HKEY_CURRENT_USER,
+ base::UTF8ToWide(value_name),
+ &value));
+ autorun_command_line.reset(
+ new base::CommandLine(base::CommandLine::FromString(value)));
+#elif defined(OS_POSIX) && !defined(OS_MACOSX)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ std::string base_desktop_name = "google-chrome-service.desktop";
+#else // BUILDFLAG(CHROMIUM_BRANDING)
+ std::string base_desktop_name = "chromium-service.desktop";
+#endif
+ std::string exec_value;
+ EXPECT_TRUE(AutoStart::GetAutostartFileValue(
+ GetServiceProcessScopedName(base_desktop_name), "Exec", &exec_value));
+
+ // Make sure |exec_value| doesn't contain strings a shell would
+ // treat specially.
+ ASSERT_EQ(std::string::npos, exec_value.find('#'));
+ ASSERT_EQ(std::string::npos, exec_value.find('\n'));
+ ASSERT_EQ(std::string::npos, exec_value.find('"'));
+ ASSERT_EQ(std::string::npos, exec_value.find('\''));
+
+ base::CommandLine::StringVector argv = base::SplitString(
+ exec_value, base::CommandLine::StringType(1, ' '),
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ ASSERT_GE(argv.size(), 2U)
+ << "Expected at least one command-line option in: " << exec_value;
+ autorun_command_line.reset(new base::CommandLine(argv));
+#endif // defined(OS_WIN)
+ if (autorun_command_line.get()) {
+ EXPECT_EQ(autorun_command_line->GetSwitchValueASCII(switches::kProcessType),
+ std::string(switches::kCloudPrintServiceProcess));
+ }
+ ASSERT_TRUE(state.RemoveFromAutoRun());
+#if defined(OS_WIN)
+ EXPECT_FALSE(base::win::ReadCommandFromAutoRun(HKEY_CURRENT_USER,
+ base::UTF8ToWide(value_name),
+ &value));
+#elif defined(OS_POSIX) && !defined(OS_MACOSX)
+ EXPECT_FALSE(AutoStart::GetAutostartFileValue(
+ GetServiceProcessScopedName(base_desktop_name), "Exec", &exec_value));
+#endif // defined(OS_WIN)
+}
+
+TEST_F(ServiceProcessStateTest, SharedMem) {
+ std::string version;
+ base::ProcessId pid;
+#if defined(OS_POSIX)
+ // 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,
+ // so we aggressively delete it before testing. On Windows, we use a named
+ // event so we don't have this issue.
+ ServiceProcessState::DeleteServiceProcessDataRegion();
+#endif // defined(OS_POSIX)
+ ASSERT_FALSE(ServiceProcessState::GetServiceProcessData(&version, &pid));
+ ServiceProcessState state;
+ ASSERT_TRUE(state.Initialize());
+ ASSERT_TRUE(ServiceProcessState::GetServiceProcessData(&version, &pid));
+ ASSERT_EQ(base::GetCurrentProcId(), pid);
+}
+
+TEST_F(ServiceProcessStateTest, MAYBE_ForceShutdown) {
+ base::Process process = SpawnChild("ServiceProcessStateTestShutdown");
+ ASSERT_TRUE(process.IsValid());
+ for (int i = 0; !CheckServiceProcessReady() && i < 10; ++i) {
+ base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
+ }
+ ASSERT_TRUE(CheckServiceProcessReady());
+ std::string version;
+ base::ProcessId pid;
+ ASSERT_TRUE(ServiceProcessState::GetServiceProcessData(&version, &pid));
+ ASSERT_TRUE(ForceServiceProcessShutdown(version, pid));
+ int exit_code = 0;
+ ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
+ &exit_code));
+ ASSERT_EQ(exit_code, 0);
+}
+
+MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestSingleton) {
+ ServiceProcessState state;
+ 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) {
+ base::PlatformThread::SetName("ServiceProcessStateTestShutdownMainThread");
+ base::test::SingleThreadTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+ base::Thread io_thread_("ServiceProcessStateTestShutdownIOThread");
+ base::Thread::Options options(base::MessagePumpType::IO, 0);
+ EXPECT_TRUE(io_thread_.StartWithOptions(options));
+ ServiceProcessState state;
+ EXPECT_TRUE(state.Initialize());
+ EXPECT_TRUE(state.SignalReady(io_thread_.task_runner().get(),
+ base::Bind(&ShutdownTask, &run_loop)));
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitWhenIdleClosure(),
+ TestTimeouts::action_max_timeout());
+ EXPECT_FALSE(g_good_shutdown);
+ run_loop.Run();
+ EXPECT_TRUE(g_good_shutdown);
+ return 0;
+}
+
+#endif // !OS_MACOSX