forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwatcher_client_win_unittest.cc
132 lines (102 loc) · 4.01 KB
/
watcher_client_win_unittest.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 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_client_win.h"
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string>
#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_reg_util_win.h"
#include "base/win/scoped_handle.h"
#include "components/browser_watcher/exit_code_watcher_win.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
namespace browser_watcher {
namespace {
// Command line switch used to communiate to the child test.
const char kParentHandle[] = "parent-handle";
bool IsValidParentProcessHandle(base::CommandLine& cmd_line,
const char* switch_name) {
std::string str_handle =
cmd_line.GetSwitchValueASCII(switch_name);
size_t integer_handle = 0;
if (!base::StringToSizeT(str_handle, &integer_handle))
return false;
base::ProcessHandle handle =
reinterpret_cast<base::ProcessHandle>(integer_handle);
// Verify that we can get the associated process id.
base::ProcessId parent_id = base::GetProcId(handle);
if (parent_id == 0) {
// Unable to get the parent pid - perhaps insufficient permissions.
return false;
}
// Make sure the handle grants SYNCHRONIZE by waiting on it.
DWORD err = ::WaitForSingleObject(handle, 0);
if (err != WAIT_OBJECT_0 && err != WAIT_TIMEOUT) {
// Unable to wait on the handle - perhaps insufficient permissions.
return false;
}
return true;
}
std::string HandleToString(HANDLE handle) {
// A HANDLE is a void* pointer, which is the same size as a size_t,
// so we can use reinterpret_cast<> on it.
size_t integer_handle = reinterpret_cast<size_t>(handle);
return base::SizeTToString(integer_handle);
}
MULTIPROCESS_TEST_MAIN(VerifyParentHandle) {
base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
// Make sure we got a valid parent process handle from the watcher client.
if (!IsValidParentProcessHandle(*cmd_line, kParentHandle)) {
LOG(ERROR) << "Invalid or missing parent-handle.";
return 1;
}
return 0;
}
class WatcherClientTest : public base::MultiProcessTest {
public:
void SetUp() override {
// Open an inheritable handle on our own process to test handle leakage.
self_.Set(::OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
TRUE, // Ineritable handle.
base::GetCurrentProcId()));
ASSERT_TRUE(self_.IsValid());
}
// Get a base command line to launch back into this test fixture.
base::CommandLine GetBaseCommandLine(HANDLE parent_handle) {
base::CommandLine ret = base::GetMultiProcessTestChildBaseCommandLine();
ret.AppendSwitchASCII(switches::kTestChildProcess, "VerifyParentHandle");
ret.AppendSwitchASCII(kParentHandle, HandleToString(parent_handle));
return ret;
}
WatcherClient::CommandLineGenerator GetBaseCommandLineGenerator() {
return base::Bind(&WatcherClientTest::GetBaseCommandLine,
base::Unretained(this));
}
void AssertSuccessfulExitCode(base::Process process) {
ASSERT_TRUE(process.IsValid());
int exit_code = 0;
if (!process.WaitForExit(&exit_code))
FAIL() << "Process::WaitForExit failed.";
ASSERT_EQ(0, exit_code);
}
// Inheritable process handle used for testing.
base::win::ScopedHandle self_;
};
} // namespace
// TODO(siggi): More testing - test WatcherClient base implementation.
TEST_F(WatcherClientTest, LaunchWatcherSucceeds) {
WatcherClient client(GetBaseCommandLineGenerator());
client.LaunchWatcher();
ASSERT_NO_FATAL_FAILURE(
AssertSuccessfulExitCode(client.process().Duplicate()));
}
} // namespace browser_watcher