| 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/unit_test_launcher.h" | 5 #include "base/test/launcher/unit_test_launcher.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 " auto means to print it when the test failed.\n" | 78 " auto means to print it when the test failed.\n" |
| 79 "\n" | 79 "\n" |
| 80 " --test-launcher-total-shards=N\n" | 80 " --test-launcher-total-shards=N\n" |
| 81 " Sets the total number of shards to N.\n" | 81 " Sets the total number of shards to N.\n" |
| 82 "\n" | 82 "\n" |
| 83 " --test-launcher-shard-index=N\n" | 83 " --test-launcher-shard-index=N\n" |
| 84 " Sets the shard index to run to N (from 0 to TOTAL - 1).\n"); | 84 " Sets the shard index to run to N (from 0 to TOTAL - 1).\n"); |
| 85 fflush(stdout); | 85 fflush(stdout); |
| 86 } | 86 } |
| 87 | 87 |
| 88 // Returns command line for child GTest process based on the command line | 88 class DefaultUnitTestPlatformDelegate : public UnitTestPlatformDelegate { |
| 89 // of current process. |test_names| is a vector of test full names | 89 public: |
| 90 // (e.g. "A.B"), |output_file| is path to the GTest XML output file. | 90 DefaultUnitTestPlatformDelegate() { |
| 91 CommandLine GetCommandLineForChildGTestProcess( | 91 } |
| 92 const std::vector<std::string>& test_names, | |
| 93 const base::FilePath& output_file) { | |
| 94 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); | |
| 95 | 92 |
| 96 new_cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); | 93 private: |
| 97 new_cmd_line.AppendSwitchASCII(kGTestFilterFlag, JoinString(test_names, ":")); | 94 // UnitTestPlatformDelegate: |
| 98 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); | 95 bool GetTests(std::vector<SplitTestName>* output) override { |
| 96 *output = GetCompiledInTests(); |
| 97 return true; |
| 98 } |
| 99 | 99 |
| 100 return new_cmd_line; | 100 bool CreateTemporaryFile(base::FilePath* path) override { |
| 101 } | 101 if (!CreateNewTempDirectory(FilePath::StringType(), path)) |
| 102 return false; |
| 103 *path = path->AppendASCII("test_results.xml"); |
| 104 return true; |
| 105 } |
| 106 |
| 107 CommandLine GetCommandLineForChildGTestProcess( |
| 108 const std::vector<std::string>& test_names, |
| 109 const base::FilePath& output_file) override { |
| 110 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); |
| 111 |
| 112 new_cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); |
| 113 new_cmd_line.AppendSwitchASCII(kGTestFilterFlag, |
| 114 JoinString(test_names, ":")); |
| 115 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); |
| 116 |
| 117 return new_cmd_line; |
| 118 } |
| 119 |
| 120 std::string GetWrapperForChildGTestProcess() override { |
| 121 return std::string(); |
| 122 } |
| 123 |
| 124 DISALLOW_COPY_AND_ASSIGN(DefaultUnitTestPlatformDelegate); |
| 125 }; |
| 102 | 126 |
| 103 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) { | 127 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) { |
| 104 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) | 128 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) |
| 105 return true; | 129 return true; |
| 106 | 130 |
| 107 std::string switch_value = | 131 std::string switch_value = |
| 108 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name); | 132 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name); |
| 109 if (!StringToInt(switch_value, result) || *result < 1) { | 133 if (!StringToInt(switch_value, result) || *result < 1) { |
| 110 LOG(ERROR) << "Invalid value for " << switch_name << ": " << switch_value; | 134 LOG(ERROR) << "Invalid value for " << switch_name << ": " << switch_value; |
| 111 return false; | 135 return false; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 | 186 |
| 163 fprintf(stdout, | 187 fprintf(stdout, |
| 164 "IMPORTANT DEBUGGING NOTE: batches of tests are run inside their\n" | 188 "IMPORTANT DEBUGGING NOTE: batches of tests are run inside their\n" |
| 165 "own process. For debugging a test inside a debugger, use the\n" | 189 "own process. For debugging a test inside a debugger, use the\n" |
| 166 "--gtest_filter=<your_test_name> flag along with\n" | 190 "--gtest_filter=<your_test_name> flag along with\n" |
| 167 "--single-process-tests.\n"); | 191 "--single-process-tests.\n"); |
| 168 fflush(stdout); | 192 fflush(stdout); |
| 169 | 193 |
| 170 MessageLoopForIO message_loop; | 194 MessageLoopForIO message_loop; |
| 171 | 195 |
| 172 UnitTestLauncherDelegate delegate(batch_limit, use_job_objects); | 196 DefaultUnitTestPlatformDelegate platform_delegate; |
| 197 UnitTestLauncherDelegate delegate( |
| 198 &platform_delegate, batch_limit, use_job_objects); |
| 173 base::TestLauncher launcher(&delegate, default_jobs); | 199 base::TestLauncher launcher(&delegate, default_jobs); |
| 174 bool success = launcher.Run(); | 200 bool success = launcher.Run(); |
| 175 | 201 |
| 176 fprintf(stdout, "Tests took %" PRId64 " seconds.\n", | 202 fprintf(stdout, "Tests took %" PRId64 " seconds.\n", |
| 177 (base::TimeTicks::Now() - start_time).InSeconds()); | 203 (base::TimeTicks::Now() - start_time).InSeconds()); |
| 178 fflush(stdout); | 204 fflush(stdout); |
| 179 | 205 |
| 180 return (success ? 0 : 1); | 206 return (success ? 0 : 1); |
| 181 } | 207 } |
| 182 | 208 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 bool use_job_objects, | 240 bool use_job_objects, |
| 215 const RunTestSuiteCallback& run_test_suite) { | 241 const RunTestSuiteCallback& run_test_suite) { |
| 216 // Windows CommandLine::Init ignores argv anyway. | 242 // Windows CommandLine::Init ignores argv anyway. |
| 217 CommandLine::Init(argc, NULL); | 243 CommandLine::Init(argc, NULL); |
| 218 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(), | 244 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(), |
| 219 use_job_objects, | 245 use_job_objects, |
| 220 Bind(&InitGoogleTestWChar, &argc, argv)); | 246 Bind(&InitGoogleTestWChar, &argc, argv)); |
| 221 } | 247 } |
| 222 #endif // defined(OS_WIN) | 248 #endif // defined(OS_WIN) |
| 223 | 249 |
| 224 UnitTestLauncherDelegate::UnitTestLauncherDelegate(size_t batch_limit, | 250 UnitTestLauncherDelegate::UnitTestLauncherDelegate( |
| 225 bool use_job_objects) | 251 UnitTestPlatformDelegate* platform_delegate, |
| 226 : batch_limit_(batch_limit), use_job_objects_(use_job_objects) { | 252 size_t batch_limit, |
| 253 bool use_job_objects) |
| 254 : platform_delegate_(platform_delegate), |
| 255 batch_limit_(batch_limit), |
| 256 use_job_objects_(use_job_objects) { |
| 227 } | 257 } |
| 228 | 258 |
| 229 UnitTestLauncherDelegate::~UnitTestLauncherDelegate() { | 259 UnitTestLauncherDelegate::~UnitTestLauncherDelegate() { |
| 230 DCHECK(thread_checker_.CalledOnValidThread()); | 260 DCHECK(thread_checker_.CalledOnValidThread()); |
| 231 } | 261 } |
| 232 | 262 |
| 233 UnitTestLauncherDelegate::GTestCallbackState::GTestCallbackState() { | 263 UnitTestLauncherDelegate::GTestCallbackState::GTestCallbackState() { |
| 234 } | 264 } |
| 235 | 265 |
| 236 UnitTestLauncherDelegate::GTestCallbackState::~GTestCallbackState() { | 266 UnitTestLauncherDelegate::GTestCallbackState::~GTestCallbackState() { |
| 237 } | 267 } |
| 238 | 268 |
| 239 bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) { | 269 bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) { |
| 240 DCHECK(thread_checker_.CalledOnValidThread()); | 270 DCHECK(thread_checker_.CalledOnValidThread()); |
| 241 *output = GetCompiledInTests(); | 271 return platform_delegate_->GetTests(output); |
| 242 return true; | |
| 243 } | 272 } |
| 244 | 273 |
| 245 bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name, | 274 bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name, |
| 246 const std::string& test_name) { | 275 const std::string& test_name) { |
| 247 DCHECK(thread_checker_.CalledOnValidThread()); | 276 DCHECK(thread_checker_.CalledOnValidThread()); |
| 248 | 277 |
| 249 // There is no additional logic to disable specific tests. | 278 // There is no additional logic to disable specific tests. |
| 250 return true; | 279 return true; |
| 251 } | 280 } |
| 252 | 281 |
| 253 size_t UnitTestLauncherDelegate::RunTests( | 282 size_t UnitTestLauncherDelegate::RunTests( |
| 254 TestLauncher* test_launcher, | 283 TestLauncher* test_launcher, |
| 255 const std::vector<std::string>& test_names) { | 284 const std::vector<std::string>& test_names) { |
| 256 DCHECK(thread_checker_.CalledOnValidThread()); | 285 DCHECK(thread_checker_.CalledOnValidThread()); |
| 257 | 286 |
| 258 std::vector<std::string> batch; | 287 std::vector<std::string> batch; |
| 259 for (size_t i = 0; i < test_names.size(); i++) { | 288 for (size_t i = 0; i < test_names.size(); i++) { |
| 260 batch.push_back(test_names[i]); | 289 batch.push_back(test_names[i]); |
| 261 | 290 |
| 262 if (batch.size() >= batch_limit_) { | 291 // Use 0 to indicate unlimited batch size. |
| 292 if (batch.size() >= batch_limit_ && batch_limit_ != 0) { |
| 263 RunBatch(test_launcher, batch); | 293 RunBatch(test_launcher, batch); |
| 264 batch.clear(); | 294 batch.clear(); |
| 265 } | 295 } |
| 266 } | 296 } |
| 267 | 297 |
| 268 RunBatch(test_launcher, batch); | 298 RunBatch(test_launcher, batch); |
| 269 | 299 |
| 270 return test_names.size(); | 300 return test_names.size(); |
| 271 } | 301 } |
| 272 | 302 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 286 return; | 316 return; |
| 287 | 317 |
| 288 std::vector<std::string> new_test_names(test_names); | 318 std::vector<std::string> new_test_names(test_names); |
| 289 std::string test_name(new_test_names.back()); | 319 std::string test_name(new_test_names.back()); |
| 290 new_test_names.pop_back(); | 320 new_test_names.pop_back(); |
| 291 | 321 |
| 292 // Create a dedicated temporary directory to store the xml result data | 322 // Create a dedicated temporary directory to store the xml result data |
| 293 // per run to ensure clean state and make it possible to launch multiple | 323 // per run to ensure clean state and make it possible to launch multiple |
| 294 // processes in parallel. | 324 // processes in parallel. |
| 295 base::FilePath output_file; | 325 base::FilePath output_file; |
| 296 CHECK(CreateNewTempDirectory(FilePath::StringType(), &output_file)); | 326 CHECK(platform_delegate_->CreateTemporaryFile(&output_file)); |
| 297 output_file = output_file.AppendASCII("test_results.xml"); | |
| 298 | 327 |
| 299 std::vector<std::string> current_test_names; | 328 std::vector<std::string> current_test_names; |
| 300 current_test_names.push_back(test_name); | 329 current_test_names.push_back(test_name); |
| 301 CommandLine cmd_line( | 330 CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess( |
| 302 GetCommandLineForChildGTestProcess(current_test_names, output_file)); | 331 current_test_names, output_file)); |
| 303 | 332 |
| 304 GTestCallbackState callback_state; | 333 GTestCallbackState callback_state; |
| 305 callback_state.test_launcher = test_launcher; | 334 callback_state.test_launcher = test_launcher; |
| 306 callback_state.test_names = current_test_names; | 335 callback_state.test_names = current_test_names; |
| 307 callback_state.output_file = output_file; | 336 callback_state.output_file = output_file; |
| 308 | 337 |
| 309 test_launcher->LaunchChildGTestProcess( | 338 test_launcher->LaunchChildGTestProcess( |
| 310 cmd_line, std::string(), TestTimeouts::test_launcher_timeout(), | 339 cmd_line, |
| 340 platform_delegate_->GetWrapperForChildGTestProcess(), |
| 341 TestTimeouts::test_launcher_timeout(), |
| 311 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, | 342 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, |
| 312 Bind(&UnitTestLauncherDelegate::SerialGTestCallback, Unretained(this), | 343 Bind(&UnitTestLauncherDelegate::SerialGTestCallback, Unretained(this), |
| 313 callback_state, new_test_names)); | 344 callback_state, new_test_names)); |
| 314 } | 345 } |
| 315 | 346 |
| 316 void UnitTestLauncherDelegate::RunBatch( | 347 void UnitTestLauncherDelegate::RunBatch( |
| 317 TestLauncher* test_launcher, | 348 TestLauncher* test_launcher, |
| 318 const std::vector<std::string>& test_names) { | 349 const std::vector<std::string>& test_names) { |
| 319 DCHECK(thread_checker_.CalledOnValidThread()); | 350 DCHECK(thread_checker_.CalledOnValidThread()); |
| 320 | 351 |
| 321 if (test_names.empty()) | 352 if (test_names.empty()) |
| 322 return; | 353 return; |
| 323 | 354 |
| 324 // Create a dedicated temporary directory to store the xml result data | 355 // Create a dedicated temporary directory to store the xml result data |
| 325 // per run to ensure clean state and make it possible to launch multiple | 356 // per run to ensure clean state and make it possible to launch multiple |
| 326 // processes in parallel. | 357 // processes in parallel. |
| 327 base::FilePath output_file; | 358 base::FilePath output_file; |
| 328 CHECK(CreateNewTempDirectory(FilePath::StringType(), &output_file)); | 359 CHECK(platform_delegate_->CreateTemporaryFile(&output_file)); |
| 329 output_file = output_file.AppendASCII("test_results.xml"); | |
| 330 | 360 |
| 331 CommandLine cmd_line( | 361 CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess( |
| 332 GetCommandLineForChildGTestProcess(test_names, output_file)); | 362 test_names, output_file)); |
| 333 | 363 |
| 334 // Adjust the timeout depending on how many tests we're running | 364 // Adjust the timeout depending on how many tests we're running |
| 335 // (note that e.g. the last batch of tests will be smaller). | 365 // (note that e.g. the last batch of tests will be smaller). |
| 336 // TODO(phajdan.jr): Consider an adaptive timeout, which can change | 366 // TODO(phajdan.jr): Consider an adaptive timeout, which can change |
| 337 // depending on how many tests ran and how many remain. | 367 // depending on how many tests ran and how many remain. |
| 338 // Note: do NOT parse child's stdout to do that, it's known to be | 368 // Note: do NOT parse child's stdout to do that, it's known to be |
| 339 // unreliable (e.g. buffering issues can mix up the output). | 369 // unreliable (e.g. buffering issues can mix up the output). |
| 340 base::TimeDelta timeout = | 370 base::TimeDelta timeout = |
| 341 test_names.size() * TestTimeouts::test_launcher_timeout(); | 371 test_names.size() * TestTimeouts::test_launcher_timeout(); |
| 342 | 372 |
| 343 GTestCallbackState callback_state; | 373 GTestCallbackState callback_state; |
| 344 callback_state.test_launcher = test_launcher; | 374 callback_state.test_launcher = test_launcher; |
| 345 callback_state.test_names = test_names; | 375 callback_state.test_names = test_names; |
| 346 callback_state.output_file = output_file; | 376 callback_state.output_file = output_file; |
| 347 | 377 |
| 348 test_launcher->LaunchChildGTestProcess( | 378 test_launcher->LaunchChildGTestProcess( |
| 349 cmd_line, std::string(), timeout, | 379 cmd_line, |
| 380 platform_delegate_->GetWrapperForChildGTestProcess(), |
| 381 timeout, |
| 350 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, | 382 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, |
| 351 Bind(&UnitTestLauncherDelegate::GTestCallback, Unretained(this), | 383 Bind(&UnitTestLauncherDelegate::GTestCallback, Unretained(this), |
| 352 callback_state)); | 384 callback_state)); |
| 353 } | 385 } |
| 354 | 386 |
| 355 void UnitTestLauncherDelegate::GTestCallback( | 387 void UnitTestLauncherDelegate::GTestCallback( |
| 356 const GTestCallbackState& callback_state, | 388 const GTestCallbackState& callback_state, |
| 357 int exit_code, | 389 int exit_code, |
| 358 const TimeDelta& elapsed_time, | 390 const TimeDelta& elapsed_time, |
| 359 bool was_timeout, | 391 bool was_timeout, |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 test_result.status = TestResult::TEST_UNKNOWN; | 568 test_result.status = TestResult::TEST_UNKNOWN; |
| 537 test_launcher->OnTestFinished(test_result); | 569 test_launcher->OnTestFinished(test_result); |
| 538 called_any_callback = true; | 570 called_any_callback = true; |
| 539 } | 571 } |
| 540 } | 572 } |
| 541 | 573 |
| 542 return called_any_callback; | 574 return called_any_callback; |
| 543 } | 575 } |
| 544 | 576 |
| 545 } // namespace base | 577 } // namespace base |
| OLD | NEW |