OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/app/chrome_watcher_command_line_win.h" | |
6 | |
7 #include <windows.h> | |
8 | |
9 #include "base/command_line.h" | |
10 #include "base/files/file_path.h" | |
11 #include "base/process/process_handle.h" | |
12 #include "base/win/scoped_handle.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 class TestChromeWatcherCommandLineGenerator | |
16 : public ChromeWatcherCommandLineGenerator { | |
17 public: | |
18 explicit TestChromeWatcherCommandLineGenerator( | |
19 const base::FilePath& chrome_exe) | |
20 : ChromeWatcherCommandLineGenerator(chrome_exe) { | |
21 } | |
22 | |
23 void ReleaseHandlesWithoutClosing() { | |
24 on_initialized_event_handle_.Take(); | |
25 parent_process_handle_.Take(); | |
26 } | |
27 }; | |
28 | |
29 TEST(ChromeWatcherCommandLineTest, UseOfBadHandlesFails) { | |
30 // Handles are always machine word aligned so there is no way these are valid. | |
31 HANDLE bad_handle_1 = reinterpret_cast<HANDLE>(0x01FC00B1); | |
32 HANDLE bad_handle_2 = reinterpret_cast<HANDLE>(0x01FC00B3); | |
33 | |
34 // The above handles are duplicated by the generator. | |
35 TestChromeWatcherCommandLineGenerator generator( | |
36 base::FilePath(L"example.exe")); | |
grt (UTC plus 2)
2015/12/22 16:31:31
nit: FILE_PATH_LITERAL("example.exe") here and els
chrisha
2015/12/23 14:08:23
Done.
| |
37 EXPECT_FALSE(generator.SetOnInitializedEventHandle(bad_handle_1)); | |
38 EXPECT_FALSE(generator.SetParentProcessHandle(bad_handle_2)); | |
39 | |
40 // Expect there to be two inherited handles created by the generator. | |
grt (UTC plus 2)
2015/12/22 16:31:32
two -> no?
chrisha
2015/12/23 14:08:23
Done.
| |
41 std::vector<HANDLE> handles; | |
42 generator.GetInheritedHandles(&handles); | |
43 EXPECT_TRUE(handles.empty()); | |
44 } | |
45 | |
46 TEST(ChromeWatcherCommandLineTest, BadCommandLineFailsInterpretation) { | |
47 // Create an invalid command-line that is missing several fields. | |
48 base::CommandLine cmd_line(base::FilePath(L"example.exe")); | |
49 | |
50 // Parse the command line. | |
51 auto interpreted = ChromeWatcherCommandLine::InterpretCommandLine(cmd_line); | |
52 EXPECT_FALSE(interpreted.get()); | |
grt (UTC plus 2)
2015/12/22 16:31:31
scoped_ptr can be used directly in boolean express
chrisha
2015/12/23 14:08:23
Done.
| |
53 } | |
54 | |
55 TEST(ChromeWatcherCommandLineDeathTest, HandlesLeftUntakenCausesDeath) { | |
56 base::win::ScopedHandle process(::OpenProcess( | |
grt (UTC plus 2)
2015/12/22 16:31:31
can you use base::Process for this and other proce
chrisha
2015/12/23 14:08:23
Done.
| |
57 PROCESS_QUERY_INFORMATION | SYNCHRONIZE, | |
58 FALSE, // Not inheritable. | |
59 ::GetCurrentProcessId())); | |
60 ASSERT_TRUE(process.Get()); | |
61 | |
62 base::win::ScopedHandle event(::CreateEvent(nullptr, FALSE, FALSE, nullptr)); | |
63 ASSERT_TRUE(event.Get()); | |
grt (UTC plus 2)
2015/12/22 16:31:32
use IsValid() rather than Get() if these assertion
chrisha
2015/12/23 14:08:23
Done.
| |
64 | |
65 // The above handles are duplicated by the generator. | |
66 TestChromeWatcherCommandLineGenerator generator( | |
67 base::FilePath(L"example.exe")); | |
68 generator.SetOnInitializedEventHandle(event.Get()); | |
69 generator.SetParentProcessHandle(process.Get()); | |
70 | |
71 // Expect there to be two inherited handles created by the generator. | |
72 std::vector<HANDLE> handles; | |
73 generator.GetInheritedHandles(&handles); | |
74 EXPECT_EQ(2u, handles.size()); | |
grt (UTC plus 2)
2015/12/22 16:31:32
nit: 2U here and line 118
chrisha
2015/12/23 14:08:23
Done.
| |
75 | |
76 base::CommandLine cmd_line = generator.GenerateCommandLine(); | |
77 | |
78 // Release the handles from the generator. Ownership will be picked up by the | |
79 // interpreter, and this prevents the handle tracking from complaining about | |
80 // there being two owners of the same handle. | |
81 generator.ReleaseHandlesWithoutClosing(); | |
82 | |
83 // Parse the command line. This creates scoped handles around the same handles | |
84 // that are currently owned by the generator. | |
85 auto interpreted = ChromeWatcherCommandLine::InterpretCommandLine(cmd_line); | |
86 EXPECT_TRUE(interpreted.get()); | |
87 | |
88 // Leave the handles in the interpreter and expect it to explode upon | |
89 // destruction. | |
90 EXPECT_DEATH(interpreted.reset(), "Handles left untaken."); | |
91 | |
92 // The above call to the destructor only runs in the context of the death test | |
93 // child process. To prevent the parent process from exploding in a similar | |
94 // fashion, release the handles so the destructor is happy. | |
95 interpreted->on_initialized_event_handle().Close(); | |
96 interpreted->parent_process_handle().Close(); | |
97 } | |
98 | |
99 TEST(ChromeWatcherCommandLineTest, SuccessfulParse) { | |
100 base::win::ScopedHandle process(::OpenProcess( | |
101 PROCESS_QUERY_INFORMATION | SYNCHRONIZE, | |
102 FALSE, // Not inheritable. | |
103 ::GetCurrentProcessId())); | |
104 ASSERT_TRUE(process.Get()); | |
105 | |
106 base::win::ScopedHandle event(::CreateEvent(nullptr, FALSE, FALSE, nullptr)); | |
107 ASSERT_TRUE(event.Get()); | |
108 | |
109 // The above handles are duplicated by the generator. | |
110 TestChromeWatcherCommandLineGenerator generator( | |
111 base::FilePath(L"example.exe")); | |
112 generator.SetOnInitializedEventHandle(event.Get()); | |
113 generator.SetParentProcessHandle(process.Get()); | |
114 | |
115 // Expect there to be two inherited handles created by the generator. | |
116 std::vector<HANDLE> handles; | |
117 generator.GetInheritedHandles(&handles); | |
118 EXPECT_EQ(2u, handles.size()); | |
119 | |
120 base::CommandLine cmd_line = generator.GenerateCommandLine(); | |
121 | |
122 // Release the handles from the generator. Ownership will be picked up by the | |
123 // interpreter, and this prevents the handle tracking from complaining about | |
124 // there being two owners of the same handle. | |
125 generator.ReleaseHandlesWithoutClosing(); | |
126 | |
127 // Parse the command line. This creates scoped handles around the same handles | |
128 // that are currently owned by the generator. | |
129 auto interpreted = ChromeWatcherCommandLine::InterpretCommandLine(cmd_line); | |
130 EXPECT_TRUE(interpreted.get()); | |
131 | |
132 EXPECT_EQ(::GetCurrentThreadId(), interpreted->main_thread_id()); | |
133 | |
134 // Explicitly take the handles from the interpreter so it doesn't explode. | |
135 base::win::ScopedHandle on_init, proc; | |
136 on_init.Set(interpreted->on_initialized_event_handle().Take()); | |
grt (UTC plus 2)
2015/12/22 16:31:31
with moving, this can be:
on_init = interpreted-
chrisha
2015/12/23 14:08:23
Done.
| |
137 proc.Set(interpreted->parent_process_handle().Take()); | |
138 } | |
139 | |
140 TEST(ChromeWatcherCommandLineTest, BasicTest) { | |
141 // Ownership of these handles is passed to the ScopedHandles below via | |
142 // InterpretChromeWatcherCommandLine(). | |
143 base::ProcessHandle current = | |
144 ::OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, | |
145 TRUE, // Inheritable | |
146 ::GetCurrentProcessId()); | |
147 ASSERT_NE(nullptr, current); | |
148 | |
149 HANDLE event = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); | |
150 ASSERT_NE(nullptr, event); | |
151 DWORD current_thread_id = ::GetCurrentThreadId(); | |
152 base::CommandLine cmd_line = GenerateChromeWatcherCommandLine( | |
153 base::FilePath(L"example.exe"), current, current_thread_id, event); | |
154 | |
155 base::win::ScopedHandle current_result; | |
156 DWORD current_thread_id_result = 0; | |
157 base::win::ScopedHandle event_result; | |
158 ASSERT_TRUE(InterpretChromeWatcherCommandLine( | |
159 cmd_line, ¤t_result, ¤t_thread_id_result, &event_result)); | |
160 ASSERT_EQ(current, current_result.Get()); | |
161 ASSERT_EQ(current_thread_id, current_thread_id_result); | |
162 ASSERT_EQ(event, event_result.Get()); | |
163 } | |
OLD | NEW |