| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <string> | 5 #include <string> |
| 6 #include <vector> | 6 #include <vector> |
| 7 | 7 |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/environment.h" | 9 #include "base/environment.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/hash_tables.h" | 11 #include "base/hash_tables.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac/scoped_nsautorelease_pool.h" | 13 #include "base/mac/scoped_nsautorelease_pool.h" |
| 14 #include "base/memory/linked_ptr.h" | 14 #include "base/memory/linked_ptr.h" |
| 15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/process_util.h" | 16 #include "base/process_util.h" |
| 17 #include "base/scoped_temp_dir.h" | 17 #include "base/scoped_temp_dir.h" |
| 18 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
| 19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
| 20 #include "base/test/test_suite.h" | 20 #include "base/test/test_suite.h" |
| 21 #include "base/test/test_timeouts.h" | 21 #include "base/test/test_timeouts.h" |
| 22 #include "base/time.h" | 22 #include "base/time.h" |
| 23 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
| 24 #include "chrome/common/chrome_switches.h" | 24 #include "content/test/browser_test.h" |
| 25 #include "chrome/test/base/chrome_test_suite.h" | 25 #include "content/test/browser_test_suite.h" |
| 26 #include "chrome/test/base/in_process_browser_test.h" | |
| 27 #include "chrome/test/base/test_launcher_utils.h" | |
| 28 #include "net/base/escape.h" | 26 #include "net/base/escape.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 30 | 28 |
| 31 #if defined(OS_WIN) | 29 #if defined(OS_WIN) |
| 32 #include "base/base_switches.h" | 30 #include "base/base_switches.h" |
| 33 #include "chrome/common/chrome_constants.h" | |
| 34 #include "content/common/sandbox_policy.h" | 31 #include "content/common/sandbox_policy.h" |
| 35 #include "sandbox/src/dep.h" | 32 #include "sandbox/src/dep.h" |
| 36 #include "sandbox/src/sandbox_factory.h" | 33 #include "sandbox/src/sandbox_factory.h" |
| 37 #include "sandbox/src/sandbox_types.h" | 34 #include "sandbox/src/sandbox_types.h" |
| 38 #endif // defined(OS_WIN) | 35 #endif // defined(OS_WIN) |
| 39 | 36 |
| 37 #if defined(BROWSER_TESTS_USE_CHROME) |
| 38 #include "chrome/common/chrome_switches.h" |
| 39 #include "chrome/common/chrome_constants.h" |
| 40 |
| 40 #if defined(OS_MACOSX) | 41 #if defined(OS_MACOSX) |
| 41 #include "chrome/browser/chrome_browser_application_mac.h" | 42 #include "chrome/browser/chrome_browser_application_mac.h" |
| 42 #endif // defined(OS_MACOSX) | 43 #endif // defined(OS_MACOSX) |
| 43 | 44 |
| 45 #endif // defined(BROWSER_TESTS_USE_CHROME) |
| 46 |
| 44 #if defined(OS_WIN) | 47 #if defined(OS_WIN) |
| 45 // The entry point signature of chrome.dll. | 48 // The entry point signature of chrome.dll. |
| 46 typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*, wchar_t*); | 49 typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*, wchar_t*); |
| 47 #endif // defined(OS_WIN) | 50 #endif // defined(OS_WIN) |
| 48 | 51 |
| 49 namespace { | 52 namespace { |
| 50 | 53 |
| 51 const char kGTestFilterFlag[] = "gtest_filter"; | 54 const char kGTestFilterFlag[] = "gtest_filter"; |
| 52 const char kGTestHelpFlag[] = "gtest_help"; | 55 const char kGTestHelpFlag[] = "gtest_help"; |
| 53 const char kGTestListTestsFlag[] = "gtest_list_tests"; | 56 const char kGTestListTestsFlag[] = "gtest_list_tests"; |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 // Returns if no more pattern can be found. | 299 // Returns if no more pattern can be found. |
| 297 if (cur_pattern == NULL) { | 300 if (cur_pattern == NULL) { |
| 298 return false; | 301 return false; |
| 299 } | 302 } |
| 300 | 303 |
| 301 // Skips the pattern separater (the ':' character). | 304 // Skips the pattern separater (the ':' character). |
| 302 cur_pattern++; | 305 cur_pattern++; |
| 303 } | 306 } |
| 304 } | 307 } |
| 305 | 308 |
| 309 namespace { |
| 310 |
| 311 // A multiplier for slow tests. We generally avoid multiplying |
| 312 // test timeouts by any constants. Here it is used as last resort |
| 313 // to implement the SLOW_ test prefix. |
| 314 static const int kSlowTestTimeoutMultiplier = 5; |
| 315 |
| 316 } // namespace |
| 317 |
| 318 int GetTestTerminationTimeout(const std::string& test_name, |
| 319 int default_timeout_ms) { |
| 320 int timeout_ms = default_timeout_ms; |
| 321 |
| 322 // Make it possible for selected tests to request a longer timeout. |
| 323 // Generally tests should really avoid doing too much, and splitting |
| 324 // a test instead of using SLOW prefix is strongly preferred. |
| 325 if (test_name.find("SLOW_") != std::string::npos) |
| 326 timeout_ms *= kSlowTestTimeoutMultiplier; |
| 327 |
| 328 return timeout_ms; |
| 329 } |
| 330 |
| 306 // Runs test specified by |test_name| in a child process, | 331 // Runs test specified by |test_name| in a child process, |
| 307 // and returns the exit code. | 332 // and returns the exit code. |
| 308 int RunTest(const std::string& test_name, int default_timeout_ms) { | 333 int RunTest(const std::string& test_name, int default_timeout_ms) { |
| 309 // Some of the below method calls will leak objects if there is no | 334 // Some of the below method calls will leak objects if there is no |
| 310 // autorelease pool in place. | 335 // autorelease pool in place. |
| 311 base::mac::ScopedNSAutoreleasePool pool; | 336 base::mac::ScopedNSAutoreleasePool pool; |
| 312 | 337 |
| 313 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | 338 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
| 314 CommandLine new_cmd_line(cmd_line->GetProgram()); | 339 CommandLine new_cmd_line(cmd_line->GetProgram()); |
| 315 CommandLine::SwitchMap switches = cmd_line->GetSwitches(); | 340 CommandLine::SwitchMap switches = cmd_line->GetSwitches(); |
| 316 | 341 |
| 317 // Strip out gtest_output flag because otherwise we would overwrite results | 342 // Strip out gtest_output flag because otherwise we would overwrite results |
| 318 // of the previous test. We will generate the final output file later | 343 // of the previous test. We will generate the final output file later |
| 319 // in RunTests(). | 344 // in RunTests(). |
| 320 switches.erase(kGTestOutputFlag); | 345 switches.erase(kGTestOutputFlag); |
| 321 | 346 |
| 322 // Strip out gtest_repeat flag because we can only run one test in the child | 347 // Strip out gtest_repeat flag because we can only run one test in the child |
| 323 // process (restarting the browser in the same process is illegal after it | 348 // process (restarting the browser in the same process is illegal after it |
| 324 // has been shut down and will actually crash). | 349 // has been shut down and will actually crash). |
| 325 switches.erase(kGTestRepeatFlag); | 350 switches.erase(kGTestRepeatFlag); |
| 326 | 351 |
| 352 #if defined(BROWSER_TESTS_USE_CHROME) |
| 327 // Strip out user-data-dir if present. We will add it back in again later. | 353 // Strip out user-data-dir if present. We will add it back in again later. |
| 328 switches.erase(switches::kUserDataDir); | 354 switches.erase(switches::kUserDataDir); |
| 355 #endif // defined(BROWSER_TESTS_USE_CHROME) |
| 329 | 356 |
| 330 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); | 357 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); |
| 331 iter != switches.end(); ++iter) { | 358 iter != switches.end(); ++iter) { |
| 332 new_cmd_line.AppendSwitchNative((*iter).first, (*iter).second); | 359 new_cmd_line.AppendSwitchNative((*iter).first, (*iter).second); |
| 333 } | 360 } |
| 334 | 361 |
| 335 // Always enable disabled tests. This method is not called with disabled | 362 // Always enable disabled tests. This method is not called with disabled |
| 336 // tests unless this flag was specified to the browser test executable. | 363 // tests unless this flag was specified to the browser test executable. |
| 337 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); | 364 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); |
| 338 new_cmd_line.AppendSwitchASCII("gtest_filter", test_name); | 365 new_cmd_line.AppendSwitchASCII("gtest_filter", test_name); |
| 339 new_cmd_line.AppendSwitch(kChildProcessFlag); | 366 new_cmd_line.AppendSwitch(kChildProcessFlag); |
| 340 | 367 |
| 341 // Do not let the child ignore failures. We need to propagate the | 368 // Do not let the child ignore failures. We need to propagate the |
| 342 // failure status back to the parent. | 369 // failure status back to the parent. |
| 343 new_cmd_line.AppendSwitch(base::TestSuite::kStrictFailureHandling); | 370 new_cmd_line.AppendSwitch(base::TestSuite::kStrictFailureHandling); |
| 344 | 371 |
| 372 #if defined(BROWSER_TESTS_USE_CHROME) |
| 345 // Create a new user data dir and pass it to the child. | 373 // Create a new user data dir and pass it to the child. |
| 346 ScopedTempDir temp_dir; | 374 ScopedTempDir temp_dir; |
| 347 if (!temp_dir.CreateUniqueTempDir() || !temp_dir.IsValid()) { | 375 if (!temp_dir.CreateUniqueTempDir() || !temp_dir.IsValid()) { |
| 348 LOG(ERROR) << "Error creating temp profile directory"; | 376 LOG(ERROR) << "Error creating temp profile directory"; |
| 349 return false; | 377 return false; |
| 350 } | 378 } |
| 351 new_cmd_line.AppendSwitchPath(switches::kUserDataDir, temp_dir.path()); | 379 new_cmd_line.AppendSwitchPath(switches::kUserDataDir, temp_dir.path()); |
| 352 | 380 |
| 353 // file:// access for ChromeOS. | 381 // file:// access for ChromeOS. |
| 354 new_cmd_line.AppendSwitch(switches::kAllowFileAccess); | 382 new_cmd_line.AppendSwitch(switches::kAllowFileAccess); |
| 383 #endif // defined(BROWSER_TESTS_USE_CHROME) |
| 355 | 384 |
| 356 const char* browser_wrapper = getenv("BROWSER_WRAPPER"); | 385 const char* browser_wrapper = getenv("BROWSER_WRAPPER"); |
| 357 if (browser_wrapper) { | 386 if (browser_wrapper) { |
| 358 #if defined(OS_WIN) | 387 #if defined(OS_WIN) |
| 359 new_cmd_line.PrependWrapper(ASCIIToWide(browser_wrapper)); | 388 new_cmd_line.PrependWrapper(ASCIIToWide(browser_wrapper)); |
| 360 #elif defined(OS_POSIX) | 389 #elif defined(OS_POSIX) |
| 361 new_cmd_line.PrependWrapper(browser_wrapper); | 390 new_cmd_line.PrependWrapper(browser_wrapper); |
| 362 #endif | 391 #endif |
| 363 VLOG(1) << "BROWSER_WRAPPER was set, prefixing command_line with " | 392 VLOG(1) << "BROWSER_WRAPPER was set, prefixing command_line with " |
| 364 << browser_wrapper; | 393 << browser_wrapper; |
| 365 } | 394 } |
| 366 | 395 |
| 367 base::ProcessHandle process_handle; | 396 base::ProcessHandle process_handle; |
| 368 base::LaunchOptions options; | 397 base::LaunchOptions options; |
| 369 | 398 |
| 370 #if defined(OS_POSIX) | 399 #if defined(OS_POSIX) |
| 371 // On POSIX, we launch the test in a new process group with pgid equal to | 400 // On POSIX, we launch the test in a new process group with pgid equal to |
| 372 // its pid. Any child processes that the test may create will inherit the | 401 // its pid. Any child processes that the test may create will inherit the |
| 373 // same pgid. This way, if the test is abruptly terminated, we can clean up | 402 // same pgid. This way, if the test is abruptly terminated, we can clean up |
| 374 // any orphaned child processes it may have left behind. | 403 // any orphaned child processes it may have left behind. |
| 375 options.new_process_group = true; | 404 options.new_process_group = true; |
| 376 #endif | 405 #endif |
| 377 | 406 |
| 378 if (!base::LaunchProcess(new_cmd_line, options, &process_handle)) | 407 if (!base::LaunchProcess(new_cmd_line, options, &process_handle)) |
| 379 return false; | 408 return false; |
| 380 | 409 |
| 381 int timeout_ms = | 410 int timeout_ms = GetTestTerminationTimeout(test_name, |
| 382 test_launcher_utils::GetTestTerminationTimeout(test_name, | 411 default_timeout_ms); |
| 383 default_timeout_ms); | |
| 384 | 412 |
| 385 int exit_code = 0; | 413 int exit_code = 0; |
| 386 if (!base::WaitForExitCodeWithTimeout(process_handle, &exit_code, | 414 if (!base::WaitForExitCodeWithTimeout(process_handle, &exit_code, |
| 387 timeout_ms)) { | 415 timeout_ms)) { |
| 388 LOG(ERROR) << "Test timeout (" << timeout_ms | 416 LOG(ERROR) << "Test timeout (" << timeout_ms |
| 389 << " ms) exceeded for " << test_name; | 417 << " ms) exceeded for " << test_name; |
| 390 | 418 |
| 391 exit_code = -1; // Set a non-zero exit code to signal a failure. | 419 exit_code = -1; // Set a non-zero exit code to signal a failure. |
| 392 | 420 |
| 393 // Ensure that the process terminates. | 421 // Ensure that the process terminates. |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 if (broker_services) { | 597 if (broker_services) { |
| 570 sandbox::InitBrokerServices(broker_services); | 598 sandbox::InitBrokerServices(broker_services); |
| 571 // Precreate the desktop and window station used by the renderers. | 599 // Precreate the desktop and window station used by the renderers. |
| 572 sandbox::TargetPolicy* policy = broker_services->CreatePolicy(); | 600 sandbox::TargetPolicy* policy = broker_services->CreatePolicy(); |
| 573 sandbox::ResultCode result = policy->CreateAlternateDesktop(true); | 601 sandbox::ResultCode result = policy->CreateAlternateDesktop(true); |
| 574 CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result); | 602 CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result); |
| 575 policy->Release(); | 603 policy->Release(); |
| 576 } | 604 } |
| 577 } | 605 } |
| 578 #endif | 606 #endif |
| 579 return ChromeTestSuite(argc, argv).Run(); | 607 return BrowserTestSuite(argc, argv).Run(); |
| 580 } | 608 } |
| 581 | 609 |
| 582 #if defined(OS_WIN) | 610 #if defined(OS_WIN) && defined(BROWSER_TESTS_USE_CHROME) |
| 583 if (command_line->HasSwitch(switches::kProcessType)) { | 611 if (command_line->HasSwitch(switches::kProcessType)) { |
| 584 // This is a child process, call ChromeMain. | 612 // This is a child process, call ChromeMain. |
| 585 FilePath chrome_path(command_line->GetProgram().DirName()); | 613 FilePath chrome_path(command_line->GetProgram().DirName()); |
| 586 chrome_path = chrome_path.Append(chrome::kBrowserResourcesDll); | 614 chrome_path = chrome_path.Append(chrome::kBrowserResourcesDll); |
| 587 HMODULE dll = LoadLibrary(chrome_path.value().c_str()); | 615 HMODULE dll = LoadLibrary(chrome_path.value().c_str()); |
| 588 DLL_MAIN entry_point = | 616 DLL_MAIN entry_point = |
| 589 reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll, "ChromeMain")); | 617 reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll, "ChromeMain")); |
| 590 if (!entry_point) | 618 if (!entry_point) |
| 591 return -1; | 619 return -1; |
| 592 | 620 |
| 593 // Initialize the sandbox services. | 621 // Initialize the sandbox services. |
| 594 sandbox::SandboxInterfaceInfo sandbox_info = {0}; | 622 sandbox::SandboxInterfaceInfo sandbox_info = {0}; |
| 595 sandbox_info.target_services = sandbox::SandboxFactory::GetTargetServices(); | 623 sandbox_info.target_services = sandbox::SandboxFactory::GetTargetServices(); |
| 596 return entry_point(GetModuleHandle(NULL), &sandbox_info, GetCommandLineW()); | 624 return entry_point(GetModuleHandle(NULL), &sandbox_info, GetCommandLineW()); |
| 597 } | 625 } |
| 598 #endif | 626 #endif // defined(OS_WIN) && defined(BROWSER_TESTS_USE_CHROME) |
| 599 | 627 |
| 600 int32 total_shards; | 628 int32 total_shards; |
| 601 int32 shard_index; | 629 int32 shard_index; |
| 602 bool should_shard = ShouldShard(&total_shards, &shard_index); | 630 bool should_shard = ShouldShard(&total_shards, &shard_index); |
| 603 | 631 |
| 604 fprintf(stdout, | 632 fprintf(stdout, |
| 605 "Starting tests...\n" | 633 "Starting tests...\n" |
| 606 "IMPORTANT DEBUGGING NOTE: each test is run inside its own process.\n" | 634 "IMPORTANT DEBUGGING NOTE: each test is run inside its own process.\n" |
| 607 "For debugging a test inside a debugger, use the\n" | 635 "For debugging a test inside a debugger, use the\n" |
| 608 "--gtest_filter=<your_test_name> flag along with either\n" | 636 "--gtest_filter=<your_test_name> flag along with either\n" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 631 exit_code = 1; | 659 exit_code = 1; |
| 632 break; | 660 break; |
| 633 } | 661 } |
| 634 | 662 |
| 635 // Special value "-1" means "repeat indefinitely". | 663 // Special value "-1" means "repeat indefinitely". |
| 636 if (cycles != -1) | 664 if (cycles != -1) |
| 637 cycles--; | 665 cycles--; |
| 638 } | 666 } |
| 639 return exit_code; | 667 return exit_code; |
| 640 } | 668 } |
| OLD | NEW |