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

Side by Side Diff: base/test/launcher/test_launcher.cc

Issue 531003002: Cleanup in base/test/launcher: move more code to anonymous namespace (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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
« no previous file with comments | « base/test/launcher/test_launcher.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/test/launcher/test_launcher.h" 5 #include "base/test/launcher/test_launcher.h"
6 6
7 #if defined(OS_POSIX) 7 #if defined(OS_POSIX)
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #endif 9 #endif
10 10
(...skipping 29 matching lines...) Expand all
40 #if defined(OS_MACOSX) 40 #if defined(OS_MACOSX)
41 #include "base/mac/scoped_nsautorelease_pool.h" 41 #include "base/mac/scoped_nsautorelease_pool.h"
42 #endif 42 #endif
43 43
44 #if defined(OS_WIN) 44 #if defined(OS_WIN)
45 #include "base/win/windows_version.h" 45 #include "base/win/windows_version.h"
46 #endif 46 #endif
47 47
48 namespace base { 48 namespace base {
49 49
50 // Launches a child process using |command_line|. If the child process is still
51 // running after |timeout|, it is terminated and |*was_timeout| is set to true.
52 // Returns exit code of the process.
53 int LaunchChildTestProcessWithOptions(const CommandLine& command_line,
54 const LaunchOptions& options,
55 int flags,
56 base::TimeDelta timeout,
57 bool* was_timeout);
58
59 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u T3FaE_sgkAJ . 50 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u T3FaE_sgkAJ .
60 using ::operator<<; 51 using ::operator<<;
61 52
62 // The environment variable name for the total number of test shards. 53 // The environment variable name for the total number of test shards.
63 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; 54 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
64 // The environment variable name for the test shard index. 55 // The environment variable name for the test shard index.
65 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; 56 const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
66 57
67 namespace { 58 namespace {
68 59
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 // Returns true if bot mode has been requested, i.e. defaults optimized 199 // Returns true if bot mode has been requested, i.e. defaults optimized
209 // for continuous integration bots. This way developers don't have to remember 200 // for continuous integration bots. This way developers don't have to remember
210 // special command-line flags. 201 // special command-line flags.
211 bool BotModeEnabled() { 202 bool BotModeEnabled() {
212 scoped_ptr<Environment> env(Environment::Create()); 203 scoped_ptr<Environment> env(Environment::Create());
213 return CommandLine::ForCurrentProcess()->HasSwitch( 204 return CommandLine::ForCurrentProcess()->HasSwitch(
214 switches::kTestLauncherBotMode) || 205 switches::kTestLauncherBotMode) ||
215 env->HasVar("CHROMIUM_TEST_LAUNCHER_BOT_MODE"); 206 env->HasVar("CHROMIUM_TEST_LAUNCHER_BOT_MODE");
216 } 207 }
217 208
209 // Returns command line command line after gtest-specific processing
210 // and applying |wrapper|.
211 CommandLine PrepareCommandLineForGTest(const CommandLine& command_line,
212 const std::string& wrapper) {
213 CommandLine new_command_line(command_line.GetProgram());
214 CommandLine::SwitchMap switches = command_line.GetSwitches();
215
216 // Strip out gtest_repeat flag - this is handled by the launcher process.
217 switches.erase(kGTestRepeatFlag);
218
219 // Don't try to write the final XML report in child processes.
220 switches.erase(kGTestOutputFlag);
221
222 for (CommandLine::SwitchMap::const_iterator iter = switches.begin();
223 iter != switches.end(); ++iter) {
224 new_command_line.AppendSwitchNative((*iter).first, (*iter).second);
225 }
226
227 // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine
228 // does not really support removing switches well, and trying to do that
229 // on a CommandLine with a wrapper is known to break.
230 // TODO(phajdan.jr): Give it a try to support CommandLine removing switches.
231 #if defined(OS_WIN)
232 new_command_line.PrependWrapper(ASCIIToWide(wrapper));
233 #elif defined(OS_POSIX)
234 new_command_line.PrependWrapper(wrapper);
235 #endif
236
237 return new_command_line;
238 }
239
240 // Launches a child process using |command_line|. If the child process is still
241 // running after |timeout|, it is terminated and |*was_timeout| is set to true.
242 // Returns exit code of the process.
243 int LaunchChildTestProcessWithOptions(const CommandLine& command_line,
244 const LaunchOptions& options,
245 int flags,
246 base::TimeDelta timeout,
247 bool* was_timeout) {
248 #if defined(OS_POSIX)
249 // Make sure an option we rely on is present - see LaunchChildGTestProcess.
250 DCHECK(options.new_process_group);
251 #endif
252
253 LaunchOptions new_options(options);
254
255 #if defined(OS_WIN)
256 DCHECK(!new_options.job_handle);
257
258 win::ScopedHandle job_handle;
259 if (flags & TestLauncher::USE_JOB_OBJECTS) {
260 job_handle.Set(CreateJobObject(NULL, NULL));
261 if (!job_handle.IsValid()) {
262 LOG(ERROR) << "Could not create JobObject.";
263 return -1;
264 }
265
266 DWORD job_flags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
267
268 // Allow break-away from job since sandbox and few other places rely on it
269 // on Windows versions prior to Windows 8 (which supports nested jobs).
270 if (win::GetVersion() < win::VERSION_WIN8 &&
271 flags & TestLauncher::ALLOW_BREAKAWAY_FROM_JOB) {
272 job_flags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK;
273 }
274
275 if (!SetJobObjectLimitFlags(job_handle.Get(), job_flags)) {
276 LOG(ERROR) << "Could not SetJobObjectLimitFlags.";
277 return -1;
278 }
279
280 new_options.job_handle = job_handle.Get();
281 }
282 #endif // defined(OS_WIN)
283
284 #if defined(OS_LINUX)
285 // To prevent accidental privilege sharing to an untrusted child, processes
286 // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this
287 // new child will be privileged and trusted.
288 new_options.allow_new_privs = true;
289 #endif
290
291 base::ProcessHandle process_handle;
292
293 {
294 // Note how we grab the lock before the process possibly gets created.
295 // This ensures that when the lock is held, ALL the processes are registered
296 // in the set.
297 AutoLock lock(g_live_processes_lock.Get());
298
299 if (!base::LaunchProcess(command_line, new_options, &process_handle))
300 return -1;
301
302 g_live_processes.Get().insert(std::make_pair(process_handle, command_line));
303 }
304
305 int exit_code = 0;
306 if (!base::WaitForExitCodeWithTimeout(process_handle,
307 &exit_code,
308 timeout)) {
309 *was_timeout = true;
310 exit_code = -1; // Set a non-zero exit code to signal a failure.
311
312 // Ensure that the process terminates.
313 base::KillProcess(process_handle, -1, true);
314 }
315
316 {
317 // Note how we grab the log before issuing a possibly broad process kill.
318 // Other code parts that grab the log kill processes, so avoid trying
319 // to do that twice and trigger all kinds of log messages.
320 AutoLock lock(g_live_processes_lock.Get());
321
322 #if defined(OS_POSIX)
323 if (exit_code != 0) {
324 // On POSIX, in case the test does not exit cleanly, either due to a crash
325 // or due to it timing out, we need to clean up any child processes that
326 // it might have created. On Windows, child processes are automatically
327 // cleaned up using JobObjects.
328 base::KillProcessGroup(process_handle);
329 }
330 #endif
331
332 g_live_processes.Get().erase(process_handle);
333 }
334
335 base::CloseProcessHandle(process_handle);
336
337 return exit_code;
338 }
339
218 void RunCallback( 340 void RunCallback(
219 const TestLauncher::LaunchChildGTestProcessCallback& callback, 341 const TestLauncher::LaunchChildGTestProcessCallback& callback,
220 int exit_code, 342 int exit_code,
221 const TimeDelta& elapsed_time, 343 const TimeDelta& elapsed_time,
222 bool was_timeout, 344 bool was_timeout,
223 const std::string& output) { 345 const std::string& output) {
224 callback.Run(exit_code, elapsed_time, was_timeout, output); 346 callback.Run(exit_code, elapsed_time, was_timeout, output);
225 } 347 }
226 348
227 void DoLaunchChildTestProcess( 349 void DoLaunchChildTestProcess(
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 end_pos = newline_pos + 1; 1089 end_pos = newline_pos + 1;
968 } 1090 }
969 1091
970 std::string snippet(full_output.substr(run_pos)); 1092 std::string snippet(full_output.substr(run_pos));
971 if (end_pos != std::string::npos) 1093 if (end_pos != std::string::npos)
972 snippet = full_output.substr(run_pos, end_pos - run_pos); 1094 snippet = full_output.substr(run_pos, end_pos - run_pos);
973 1095
974 return snippet; 1096 return snippet;
975 } 1097 }
976 1098
977 CommandLine PrepareCommandLineForGTest(const CommandLine& command_line,
978 const std::string& wrapper) {
979 CommandLine new_command_line(command_line.GetProgram());
980 CommandLine::SwitchMap switches = command_line.GetSwitches();
981
982 // Strip out gtest_repeat flag - this is handled by the launcher process.
983 switches.erase(kGTestRepeatFlag);
984
985 // Don't try to write the final XML report in child processes.
986 switches.erase(kGTestOutputFlag);
987
988 for (CommandLine::SwitchMap::const_iterator iter = switches.begin();
989 iter != switches.end(); ++iter) {
990 new_command_line.AppendSwitchNative((*iter).first, (*iter).second);
991 }
992
993 // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine
994 // does not really support removing switches well, and trying to do that
995 // on a CommandLine with a wrapper is known to break.
996 // TODO(phajdan.jr): Give it a try to support CommandLine removing switches.
997 #if defined(OS_WIN)
998 new_command_line.PrependWrapper(ASCIIToWide(wrapper));
999 #elif defined(OS_POSIX)
1000 new_command_line.PrependWrapper(wrapper);
1001 #endif
1002
1003 return new_command_line;
1004 }
1005
1006 // TODO(phajdan.jr): Move to anonymous namespace.
1007 int LaunchChildTestProcessWithOptions(const CommandLine& command_line,
1008 const LaunchOptions& options,
1009 int flags,
1010 base::TimeDelta timeout,
1011 bool* was_timeout) {
1012 #if defined(OS_POSIX)
1013 // Make sure an option we rely on is present - see LaunchChildGTestProcess.
1014 DCHECK(options.new_process_group);
1015 #endif
1016
1017 LaunchOptions new_options(options);
1018
1019 #if defined(OS_WIN)
1020 DCHECK(!new_options.job_handle);
1021
1022 win::ScopedHandle job_handle;
1023 if (flags & TestLauncher::USE_JOB_OBJECTS) {
1024 job_handle.Set(CreateJobObject(NULL, NULL));
1025 if (!job_handle.IsValid()) {
1026 LOG(ERROR) << "Could not create JobObject.";
1027 return -1;
1028 }
1029
1030 DWORD job_flags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
1031
1032 // Allow break-away from job since sandbox and few other places rely on it
1033 // on Windows versions prior to Windows 8 (which supports nested jobs).
1034 if (win::GetVersion() < win::VERSION_WIN8 &&
1035 flags & TestLauncher::ALLOW_BREAKAWAY_FROM_JOB) {
1036 job_flags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK;
1037 }
1038
1039 if (!SetJobObjectLimitFlags(job_handle.Get(), job_flags)) {
1040 LOG(ERROR) << "Could not SetJobObjectLimitFlags.";
1041 return -1;
1042 }
1043
1044 new_options.job_handle = job_handle.Get();
1045 }
1046 #endif // defined(OS_WIN)
1047
1048 #if defined(OS_LINUX)
1049 // To prevent accidental privilege sharing to an untrusted child, processes
1050 // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this
1051 // new child will be privileged and trusted.
1052 new_options.allow_new_privs = true;
1053 #endif
1054
1055 base::ProcessHandle process_handle;
1056
1057 {
1058 // Note how we grab the lock before the process possibly gets created.
1059 // This ensures that when the lock is held, ALL the processes are registered
1060 // in the set.
1061 AutoLock lock(g_live_processes_lock.Get());
1062
1063 if (!base::LaunchProcess(command_line, new_options, &process_handle))
1064 return -1;
1065
1066 g_live_processes.Get().insert(std::make_pair(process_handle, command_line));
1067 }
1068
1069 int exit_code = 0;
1070 if (!base::WaitForExitCodeWithTimeout(process_handle,
1071 &exit_code,
1072 timeout)) {
1073 *was_timeout = true;
1074 exit_code = -1; // Set a non-zero exit code to signal a failure.
1075
1076 // Ensure that the process terminates.
1077 base::KillProcess(process_handle, -1, true);
1078 }
1079
1080 {
1081 // Note how we grab the log before issuing a possibly broad process kill.
1082 // Other code parts that grab the log kill processes, so avoid trying
1083 // to do that twice and trigger all kinds of log messages.
1084 AutoLock lock(g_live_processes_lock.Get());
1085
1086 #if defined(OS_POSIX)
1087 if (exit_code != 0) {
1088 // On POSIX, in case the test does not exit cleanly, either due to a crash
1089 // or due to it timing out, we need to clean up any child processes that
1090 // it might have created. On Windows, child processes are automatically
1091 // cleaned up using JobObjects.
1092 base::KillProcessGroup(process_handle);
1093 }
1094 #endif
1095
1096 g_live_processes.Get().erase(process_handle);
1097 }
1098
1099 base::CloseProcessHandle(process_handle);
1100
1101 return exit_code;
1102 }
1103
1104 } // namespace base 1099 } // namespace base
OLDNEW
« no previous file with comments | « base/test/launcher/test_launcher.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698