Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: base/win/scoped_process_information_unittest.cc

Issue 9700038: ScopedProcessInformation protects against process/thread handle leaks from CreateProcess calls. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add tests for new functions. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 <windows.h>
6
7 #include <string>
8
9 #include "base/command_line.h"
10 #include "base/process_util.h"
11 #include "base/test/multiprocess_test.h"
12 #include "base/win/scoped_process_information.h"
13 #include "testing/multiprocess_func_list.h"
14
15 class ScopedProcessInformationTest : public base::MultiProcessTest {
16 protected:
17 void DoCreateProcess(const std::string& main_id,
18 PROCESS_INFORMATION* process_handle);
19 };
20
21 MULTIPROCESS_TEST_MAIN(ReturnSeven) {
22 return 7;
23 }
24
25 MULTIPROCESS_TEST_MAIN(ReturnNine) {
26 return 9;
27 }
28
29 void ScopedProcessInformationTest::DoCreateProcess(
30 const std::string& main_id, PROCESS_INFORMATION* process_handle) {
31 std::wstring cmd_line =
32 this->MakeCmdLine(main_id, false).GetCommandLineString();
33 STARTUPINFO startup_info = {};
34 startup_info.cb = sizeof(startup_info);
35
36 EXPECT_TRUE(::CreateProcess(NULL,
37 const_cast<wchar_t*>(cmd_line.c_str()),
38 NULL, NULL, false, 0, NULL, NULL,
39 &startup_info, process_handle));
40 }
41
42 TEST_F(ScopedProcessInformationTest, TakeProcess) {
43 base::win::ScopedProcessInformation process_info;
44 DoCreateProcess("ReturnSeven", process_info.Receive());
45 int exit_code = 0;
46 ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
47 &exit_code));
48 ASSERT_EQ(7, exit_code);
49 ASSERT_TRUE(process_info.IsValid());
50 ASSERT_EQ(0u, process_info.process_id());
51 ASSERT_TRUE(process_info.process_handle() == NULL);
52 ASSERT_NE(0u, process_info.thread_id());
53 ASSERT_FALSE(process_info.thread_handle() == NULL);
54 }
55
56 TEST_F(ScopedProcessInformationTest, TakeThread) {
57 base::win::ScopedProcessInformation process_info;
58 DoCreateProcess("ReturnSeven", process_info.Receive());
59 ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
60 ASSERT_TRUE(process_info.IsValid());
61 ASSERT_NE(0u, process_info.process_id());
62 ASSERT_FALSE(process_info.process_handle() == NULL);
63 ASSERT_EQ(0u, process_info.thread_id());
64 ASSERT_TRUE(process_info.thread_handle() == NULL);
65 }
66
67 TEST_F(ScopedProcessInformationTest, TakeBoth) {
68 base::win::ScopedProcessInformation process_info;
69 DoCreateProcess("ReturnSeven", process_info.Receive());
70 int exit_code = 0;
71 ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
72 &exit_code));
73 ASSERT_EQ(7, exit_code);
74 ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
75 ASSERT_FALSE(process_info.IsValid());
76 ASSERT_EQ(0u, process_info.process_id());
77 ASSERT_TRUE(process_info.process_handle() == NULL);
78 ASSERT_EQ(0u, process_info.thread_id());
79 ASSERT_TRUE(process_info.thread_handle() == NULL);
80 }
81
82 TEST_F(ScopedProcessInformationTest, TakeNothing) {
83 base::win::ScopedProcessInformation process_info;
84 DoCreateProcess("ReturnSeven", process_info.Receive());
85 ASSERT_TRUE(process_info.IsValid());
86 ASSERT_NE(0u, process_info.thread_id());
87 ASSERT_FALSE(process_info.thread_handle() == NULL);
88 ASSERT_NE(0u, process_info.process_id());
89 ASSERT_FALSE(process_info.process_handle() == NULL);
90 }
91
92 TEST_F(ScopedProcessInformationTest, TakeWholeStruct) {
93 base::win::ScopedProcessInformation process_info;
94 DoCreateProcess("ReturnSeven", process_info.Receive());
95 base::win::ScopedProcessInformation other;
96 *other.Receive() = process_info.Take();
97
98 ASSERT_FALSE(process_info.IsValid());
99 ASSERT_EQ(0u, process_info.process_id());
100 ASSERT_TRUE(process_info.process_handle() == NULL);
101 ASSERT_EQ(0u, process_info.thread_id());
102 ASSERT_TRUE(process_info.thread_handle() == NULL);
103
104 // Validate that what was taken is good.
105 ASSERT_NE(0u, other.thread_id());
106 ASSERT_NE(0u, other.process_id());
107 int exit_code = 0;
108 ASSERT_TRUE(base::WaitForExitCode(other.TakeProcessHandle(),
109 &exit_code));
110 ASSERT_EQ(7, exit_code);
111 ASSERT_TRUE(::CloseHandle(other.TakeThreadHandle()));
112 }
113
114 TEST_F(ScopedProcessInformationTest, Duplicate) {
115 base::win::ScopedProcessInformation process_info;
116 DoCreateProcess("ReturnSeven", process_info.Receive());
117 base::win::ScopedProcessInformation duplicate;
118 duplicate.DuplicateFrom(process_info);
119
120 ASSERT_TRUE(process_info.IsValid());
121 ASSERT_NE(0u, process_info.process_id());
122 ASSERT_EQ(duplicate.process_id(), process_info.process_id());
123 ASSERT_NE(0u, process_info.thread_id());
124 ASSERT_EQ(duplicate.thread_id(), process_info.thread_id());
125
126 // Validate that we have separate handles that are good.
127 int exit_code = 0;
128 ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
129 &exit_code));
130 ASSERT_EQ(7, exit_code);
131
132 exit_code = 0;
133 ASSERT_TRUE(base::WaitForExitCode(duplicate.TakeProcessHandle(),
134 &exit_code));
135 ASSERT_EQ(7, exit_code);
136
137 ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
138 ASSERT_TRUE(::CloseHandle(duplicate.TakeThreadHandle()));
139 }
140
141 TEST_F(ScopedProcessInformationTest, Swap) {
142 base::win::ScopedProcessInformation seven_to_nine_info;
143 DoCreateProcess("ReturnSeven", seven_to_nine_info.Receive());
144 base::win::ScopedProcessInformation nine_to_seven_info;
145 DoCreateProcess("ReturnNine", nine_to_seven_info.Receive());
146
147 HANDLE seven_process = seven_to_nine_info.process_handle();
148 DWORD seven_process_id = seven_to_nine_info.process_id();
149 HANDLE seven_thread = seven_to_nine_info.thread_handle();
150 DWORD seven_thread_id = seven_to_nine_info.thread_id();
151 HANDLE nine_process = nine_to_seven_info.process_handle();
152 DWORD nine_process_id = nine_to_seven_info.process_id();
153 HANDLE nine_thread = nine_to_seven_info.thread_handle();
154 DWORD nine_thread_id = nine_to_seven_info.thread_id();
155
156 seven_to_nine_info.Swap(&nine_to_seven_info);
157
158 ASSERT_EQ(seven_process, nine_to_seven_info.process_handle());
159 ASSERT_EQ(seven_process_id, nine_to_seven_info.process_id());
160 ASSERT_EQ(seven_thread, nine_to_seven_info.thread_handle());
161 ASSERT_EQ(seven_thread_id, nine_to_seven_info.thread_id());
162 ASSERT_EQ(nine_process, seven_to_nine_info.process_handle());
163 ASSERT_EQ(nine_process_id, seven_to_nine_info.process_id());
164 ASSERT_EQ(nine_thread, seven_to_nine_info.thread_handle());
165 ASSERT_EQ(nine_thread_id, seven_to_nine_info.thread_id());
166
167 int exit_code = 0;
168 ASSERT_TRUE(base::WaitForExitCode(seven_to_nine_info.TakeProcessHandle(),
169 &exit_code));
170 ASSERT_EQ(9, exit_code);
171
172 ASSERT_TRUE(base::WaitForExitCode(nine_to_seven_info.TakeProcessHandle(),
173 &exit_code));
174 ASSERT_EQ(7, exit_code);
175
176 }
177
178 TEST_F(ScopedProcessInformationTest, InitiallyInvalid) {
179 base::win::ScopedProcessInformation process_info;
180 ASSERT_FALSE(process_info.IsValid());
181 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698