Index: components/browser_watcher/watcher_win_unittest.cc |
diff --git a/components/browser_watcher/watcher_win_unittest.cc b/components/browser_watcher/watcher_win_unittest.cc |
deleted file mode 100644 |
index 03c59115753aef5e23a227685ff3e05948ab3e08..0000000000000000000000000000000000000000 |
--- a/components/browser_watcher/watcher_win_unittest.cc |
+++ /dev/null |
@@ -1,227 +0,0 @@ |
-// Copyright (c) 2014 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 "components/browser_watcher/watcher_win.h" |
- |
-#include "base/command_line.h" |
-#include "base/process/kill.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "base/test/multiprocess_test.h" |
-#include "base/test/test_reg_util_win.h" |
-#include "base/threading/platform_thread.h" |
-#include "base/time/time.h" |
-#include "base/win/scoped_handle.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
-#include "testing/multiprocess_func_list.h" |
- |
-namespace browser_watcher { |
- |
-namespace { |
- |
-const wchar_t kRegistryPath[] = L"Software\\BrowserWatcherTest"; |
- |
-MULTIPROCESS_TEST_MAIN(Sleeper) { |
- // Sleep forever - the test harness will kill this process to give it an |
- // exit code. |
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(INFINITE)); |
- return 1; |
-} |
- |
-class ScopedSleeperProcess { |
- public: |
- ScopedSleeperProcess() : |
- process_(base::kNullProcessHandle), |
- process_id_(base::kNullProcessId), |
- is_killed_(false) { |
- } |
- |
- ~ScopedSleeperProcess() { |
- if (process_ != base::kNullProcessHandle) { |
- base::KillProcess(process_, -1, true); |
- base::CloseProcessHandle(process_); |
- } |
- } |
- |
- void Launch() { |
- ASSERT_EQ(base::kNullProcessHandle, process_); |
- |
- base::CommandLine cmd_line(base::GetMultiProcessTestChildBaseCommandLine()); |
- base::LaunchOptions options; |
- options.start_hidden = true; |
- process_ = base::SpawnMultiProcessTestChild("Sleeper", cmd_line, options); |
- process_id_ = base::GetProcId(process_); |
- ASSERT_NE(base::kNullProcessHandle, process_); |
- } |
- |
- void Kill(int exit_code, bool wait) { |
- ASSERT_NE(process_, base::kNullProcessHandle); |
- ASSERT_FALSE(is_killed_); |
- ASSERT_TRUE(base::KillProcess(process_, exit_code, wait)); |
- is_killed_ = true; |
- } |
- |
- void GetNewHandle(base::ProcessHandle* output) { |
- ASSERT_NE(process_, base::kNullProcessHandle); |
- |
- ASSERT_TRUE(DuplicateHandle(::GetCurrentProcess(), |
- process_, |
- ::GetCurrentProcess(), |
- output, |
- 0, |
- FALSE, |
- DUPLICATE_SAME_ACCESS)); |
- } |
- |
- base::ProcessHandle process() const { return process_; } |
- base::ProcessId process_id() const { return process_id_; } |
- |
- private: |
- base::ProcessHandle process_; |
- base::ProcessId process_id_; |
- bool is_killed_; |
-}; |
- |
-class BrowserWatcherTest : public testing::Test { |
- public: |
- typedef testing::Test Super; |
- |
- static const int kExitCode = 0xCAFEBABE; |
- |
- BrowserWatcherTest() : |
- cmd_line_(base::CommandLine::NO_PROGRAM), |
- process_(base::kNullProcessHandle) { |
- } |
- |
- virtual void SetUp() override { |
- Super::SetUp(); |
- |
- override_manager_.OverrideRegistry(HKEY_CURRENT_USER); |
- } |
- |
- virtual void TearDown() override { |
- if (process_ != base::kNullProcessHandle) { |
- base::CloseProcessHandle(process_); |
- process_ = base::kNullProcessHandle; |
- } |
- |
- Super::TearDown(); |
- } |
- |
- void OpenSelfWithAccess(uint32 access) { |
- ASSERT_EQ(base::kNullProcessHandle, process_); |
- ASSERT_TRUE(base::OpenProcessHandleWithAccess( |
- base::GetCurrentProcId(), access, &process_)); |
- } |
- |
- void VerifyWroteExitCode(base::ProcessId proc_id, int exit_code) { |
- base::win::RegistryValueIterator it( |
- HKEY_CURRENT_USER, kRegistryPath); |
- |
- ASSERT_EQ(1, it.ValueCount()); |
- base::win::RegKey key(HKEY_CURRENT_USER, |
- kRegistryPath, |
- KEY_QUERY_VALUE); |
- |
- // The value name should encode the process id at the start. |
- EXPECT_TRUE(StartsWith(it.Name(), |
- base::StringPrintf(L"%d-", proc_id), |
- false)); |
- DWORD value = 0; |
- ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(it.Name(), &value)); |
- ASSERT_EQ(exit_code, value); |
- } |
- |
- protected: |
- base::CommandLine cmd_line_; |
- base::ProcessHandle process_; |
- registry_util::RegistryOverrideManager override_manager_; |
-}; |
- |
-} // namespace |
- |
-TEST_F(BrowserWatcherTest, ExitCodeWatcherInvalidCmdLineFailsInit) { |
- ExitCodeWatcher watcher(kRegistryPath); |
- |
- // An empty command line should fail. |
- EXPECT_FALSE(watcher.ParseArguments(cmd_line_)); |
- |
- // A non-numeric parent-handle argument should fail. |
- cmd_line_.AppendSwitchASCII(ExitCodeWatcher::kParenthHandleSwitch, "asdf"); |
- EXPECT_FALSE(watcher.ParseArguments(cmd_line_)); |
-} |
- |
-TEST_F(BrowserWatcherTest, ExitCodeWatcherInvalidHandleFailsInit) { |
- ExitCodeWatcher watcher(kRegistryPath); |
- |
- // A waitable event has a non process-handle. |
- base::WaitableEvent event(false, false); |
- |
- // A non-process handle should fail. |
- cmd_line_.AppendSwitchASCII(ExitCodeWatcher::kParenthHandleSwitch, |
- base::StringPrintf("%d", event.handle())); |
- EXPECT_FALSE(watcher.ParseArguments(cmd_line_)); |
-} |
- |
-TEST_F(BrowserWatcherTest, ExitCodeWatcherNoAccessHandleFailsInit) { |
- ExitCodeWatcher watcher(kRegistryPath); |
- |
- // Open a SYNCHRONIZE-only handle to this process. |
- ASSERT_NO_FATAL_FAILURE(OpenSelfWithAccess(SYNCHRONIZE)); |
- |
- // A process handle with insufficient access should fail. |
- cmd_line_.AppendSwitchASCII(ExitCodeWatcher::kParenthHandleSwitch, |
- base::StringPrintf("%d", process_)); |
- EXPECT_FALSE(watcher.ParseArguments(cmd_line_)); |
-} |
- |
-TEST_F(BrowserWatcherTest, ExitCodeWatcherSucceedsInit) { |
- ExitCodeWatcher watcher(kRegistryPath); |
- |
- // Open a handle to this process with sufficient access for the watcher. |
- ASSERT_NO_FATAL_FAILURE( |
- OpenSelfWithAccess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION)); |
- |
- // A process handle with sufficient access should succeed init. |
- cmd_line_.AppendSwitchASCII(ExitCodeWatcher::kParenthHandleSwitch, |
- base::StringPrintf("%d", process_)); |
- EXPECT_TRUE(watcher.ParseArguments(cmd_line_)); |
- |
- ASSERT_EQ(process_, watcher.process()); |
- |
- // The watcher takes ownership of the handle, make sure it's not |
- // double-closed. |
- process_ = base::kNullProcessHandle; |
-} |
- |
-TEST_F(BrowserWatcherTest, ExitCodeWatcherOnExitedProcess) { |
- ScopedSleeperProcess sleeper; |
- ASSERT_NO_FATAL_FAILURE(sleeper.Launch()); |
- |
- // Create a new handle to the sleeper process. This handle will leak in |
- // the case this test fails. A ScopedHandle cannot be used here, as the |
- // ownership would momentarily be held by two of them, which is disallowed. |
- base::ProcessHandle sleeper_handle; |
- sleeper.GetNewHandle(&sleeper_handle); |
- |
- ExitCodeWatcher watcher(kRegistryPath); |
- |
- cmd_line_.AppendSwitchASCII(ExitCodeWatcher::kParenthHandleSwitch, |
- base::StringPrintf("%d", sleeper_handle)); |
- EXPECT_TRUE(watcher.ParseArguments(cmd_line_)); |
- ASSERT_EQ(sleeper_handle, watcher.process()); |
- |
- // Verify that the watcher wrote a sentinel for the process. |
- VerifyWroteExitCode(sleeper.process_id(), STILL_ACTIVE); |
- |
- // Kill the sleeper, and make sure it's exited before we continue. |
- ASSERT_NO_FATAL_FAILURE(sleeper.Kill(kExitCode, true)); |
- |
- watcher.WaitForExit(); |
- |
- VerifyWroteExitCode(sleeper.process_id(), kExitCode); |
-} |
- |
-} // namespace browser_watcher |