| OLD | NEW |
| 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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 222 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
| 223 const TestLauncher::LaunchChildGTestProcessCallback& callback) { | 223 const TestLauncher::LaunchChildGTestProcessCallback& callback) { |
| 224 TimeTicks start_time = TimeTicks::Now(); | 224 TimeTicks start_time = TimeTicks::Now(); |
| 225 | 225 |
| 226 // Redirect child process output to a file. | 226 // Redirect child process output to a file. |
| 227 base::FilePath output_file; | 227 base::FilePath output_file; |
| 228 CHECK(file_util::CreateTemporaryFile(&output_file)); | 228 CHECK(file_util::CreateTemporaryFile(&output_file)); |
| 229 | 229 |
| 230 LaunchOptions options; | 230 LaunchOptions options; |
| 231 #if defined(OS_WIN) | 231 #if defined(OS_WIN) |
| 232 // Make the file handle inheritable by the child. | 232 win::ScopedHandle handle; |
| 233 SECURITY_ATTRIBUTES sa_attr; | |
| 234 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES); | |
| 235 sa_attr.lpSecurityDescriptor = NULL; | |
| 236 sa_attr.bInheritHandle = TRUE; | |
| 237 | 233 |
| 238 win::ScopedHandle handle(CreateFile(output_file.value().c_str(), | 234 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
| 239 GENERIC_WRITE, | 235 switches::kTestLauncherDeveloperMode)) { |
| 240 FILE_SHARE_READ | FILE_SHARE_DELETE, | 236 // Make the file handle inheritable by the child. |
| 241 &sa_attr, | 237 SECURITY_ATTRIBUTES sa_attr; |
| 242 OPEN_EXISTING, | 238 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES); |
| 243 FILE_ATTRIBUTE_TEMPORARY, | 239 sa_attr.lpSecurityDescriptor = NULL; |
| 244 NULL)); | 240 sa_attr.bInheritHandle = TRUE; |
| 245 CHECK(handle.IsValid()); | 241 |
| 246 options.inherit_handles = true; | 242 handle.Set(CreateFile(output_file.value().c_str(), |
| 247 options.stdin_handle = INVALID_HANDLE_VALUE; | 243 GENERIC_WRITE, |
| 248 options.stdout_handle = handle.Get(); | 244 FILE_SHARE_READ | FILE_SHARE_DELETE, |
| 249 options.stderr_handle = handle.Get(); | 245 &sa_attr, |
| 246 OPEN_EXISTING, |
| 247 FILE_ATTRIBUTE_TEMPORARY, |
| 248 NULL)); |
| 249 CHECK(handle.IsValid()); |
| 250 options.inherit_handles = true; |
| 251 options.stdin_handle = INVALID_HANDLE_VALUE; |
| 252 options.stdout_handle = handle.Get(); |
| 253 options.stderr_handle = handle.Get(); |
| 254 } |
| 250 #elif defined(OS_POSIX) | 255 #elif defined(OS_POSIX) |
| 251 options.new_process_group = true; | 256 options.new_process_group = true; |
| 252 | 257 |
| 253 int output_file_fd = open(output_file.value().c_str(), O_RDWR); | 258 base::FileHandleMappingVector fds_mapping; |
| 254 CHECK_GE(output_file_fd, 0); | 259 file_util::ScopedFD output_file_fd_closer; |
| 255 | 260 |
| 256 file_util::ScopedFD output_file_fd_closer(&output_file_fd); | 261 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
| 262 switches::kTestLauncherDeveloperMode)) { |
| 263 int output_file_fd = open(output_file.value().c_str(), O_RDWR); |
| 264 CHECK_GE(output_file_fd, 0); |
| 257 | 265 |
| 258 base::FileHandleMappingVector fds_mapping; | 266 output_file_fd_closer.reset(&output_file_fd); |
| 259 fds_mapping.push_back(std::make_pair(output_file_fd, STDOUT_FILENO)); | 267 |
| 260 fds_mapping.push_back(std::make_pair(output_file_fd, STDERR_FILENO)); | 268 fds_mapping.push_back(std::make_pair(output_file_fd, STDOUT_FILENO)); |
| 261 options.fds_to_remap = &fds_mapping; | 269 fds_mapping.push_back(std::make_pair(output_file_fd, STDERR_FILENO)); |
| 270 options.fds_to_remap = &fds_mapping; |
| 271 } |
| 262 #endif | 272 #endif |
| 263 | 273 |
| 264 bool was_timeout = false; | 274 bool was_timeout = false; |
| 265 int exit_code = LaunchChildTestProcessWithOptions( | 275 int exit_code = LaunchChildTestProcessWithOptions( |
| 266 command_line, options, timeout, &was_timeout); | 276 command_line, options, timeout, &was_timeout); |
| 267 | 277 |
| 278 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
| 279 switches::kTestLauncherDeveloperMode)) { |
| 268 #if defined(OS_WIN) | 280 #if defined(OS_WIN) |
| 269 FlushFileBuffers(handle.Get()); | 281 FlushFileBuffers(handle.Get()); |
| 270 handle.Close(); | 282 handle.Close(); |
| 271 #elif defined(OS_POSIX) | 283 #elif defined(OS_POSIX) |
| 272 output_file_fd_closer.reset(); | 284 output_file_fd_closer.reset(); |
| 273 #endif | 285 #endif |
| 286 } |
| 274 | 287 |
| 275 std::string output_file_contents; | 288 std::string output_file_contents; |
| 276 CHECK(base::ReadFileToString(output_file, &output_file_contents)); | 289 CHECK(base::ReadFileToString(output_file, &output_file_contents)); |
| 277 | 290 |
| 278 if (!base::DeleteFile(output_file, false)) { | 291 if (!base::DeleteFile(output_file, false)) { |
| 279 // This needs to be non-fatal at least for Windows. | 292 // This needs to be non-fatal at least for Windows. |
| 280 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); | 293 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); |
| 281 } | 294 } |
| 282 | 295 |
| 283 // Run target callback on the thread it was originating from, not on | 296 // Run target callback on the thread it was originating from, not on |
| (...skipping 29 matching lines...) Expand all Loading... |
| 313 test_started_count_(0), | 326 test_started_count_(0), |
| 314 test_finished_count_(0), | 327 test_finished_count_(0), |
| 315 test_success_count_(0), | 328 test_success_count_(0), |
| 316 test_broken_count_(0), | 329 test_broken_count_(0), |
| 317 retry_count_(0), | 330 retry_count_(0), |
| 318 retry_limit_(3), // TODO(phajdan.jr): Make a flag control this. | 331 retry_limit_(3), // TODO(phajdan.jr): Make a flag control this. |
| 319 run_result_(true), | 332 run_result_(true), |
| 320 watchdog_timer_(FROM_HERE, | 333 watchdog_timer_(FROM_HERE, |
| 321 TimeDelta::FromSeconds(kOutputTimeoutSeconds), | 334 TimeDelta::FromSeconds(kOutputTimeoutSeconds), |
| 322 this, | 335 this, |
| 323 &TestLauncher::OnOutputTimeout), | 336 &TestLauncher::OnOutputTimeout) { |
| 324 worker_pool_owner_( | 337 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 325 new SequencedWorkerPoolOwner(parallel_jobs, "test_launcher")) { | 338 switches::kTestLauncherDeveloperMode)) { |
| 339 parallel_jobs = 1; |
| 340 retry_limit_ = 0; |
| 341 fprintf(stdout, |
| 342 "Forcing serial test execution in developer mode.\n" |
| 343 "Disabling test retries in developer mode.\n"); |
| 344 fflush(stdout); |
| 345 } |
| 346 worker_pool_owner_.reset( |
| 347 new SequencedWorkerPoolOwner(parallel_jobs, "test_launcher")); |
| 326 } | 348 } |
| 327 | 349 |
| 328 TestLauncher::~TestLauncher() { | 350 TestLauncher::~TestLauncher() { |
| 329 worker_pool_owner_->pool()->Shutdown(); | 351 worker_pool_owner_->pool()->Shutdown(); |
| 330 } | 352 } |
| 331 | 353 |
| 332 bool TestLauncher::Run(int argc, char** argv) { | 354 bool TestLauncher::Run(int argc, char** argv) { |
| 333 if (!Init()) | 355 if (!Init()) |
| 334 return false; | 356 return false; |
| 335 | 357 |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 | 918 |
| 897 g_live_processes.Get().erase(process_handle); | 919 g_live_processes.Get().erase(process_handle); |
| 898 } | 920 } |
| 899 | 921 |
| 900 base::CloseProcessHandle(process_handle); | 922 base::CloseProcessHandle(process_handle); |
| 901 | 923 |
| 902 return exit_code; | 924 return exit_code; |
| 903 } | 925 } |
| 904 | 926 |
| 905 } // namespace base | 927 } // namespace base |
| OLD | NEW |