diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-24 01:05:24 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-24 01:05:24 +0000 |
commit | a849fe38ede485987714d71ea32738586eafd30e (patch) | |
tree | 620f6aa89239ebe30bbd57be9b1cf52d3139acce /content/public/test | |
parent | c974d5d74d83ca4a1d5a5624878f0b3b9be2d8be (diff) | |
download | chromium_src-a849fe38ede485987714d71ea32738586eafd30e.zip chromium_src-a849fe38ede485987714d71ea32738586eafd30e.tar.gz chromium_src-a849fe38ede485987714d71ea32738586eafd30e.tar.bz2 |
Revert "Revert "GTTF: refactor interface..." and Revert "GTTF: Implement test retries.""
This reverts commit ad079af85f8d5a6545ead008db256657b9770096.
TBR=kouhei
BUG=236893
Review URL: https://codereview.chromium.org/38973002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230580 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/public/test')
-rw-r--r-- | content/public/test/test_launcher.cc | 230 |
1 files changed, 135 insertions, 95 deletions
diff --git a/content/public/test/test_launcher.cc b/content/public/test/test_launcher.cc index 0e75b52..31dbef2 100644 --- a/content/public/test/test_launcher.cc +++ b/content/public/test/test_launcher.cc @@ -103,33 +103,26 @@ class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { const testing::TestInfo* test_info) OVERRIDE; virtual bool ShouldRunTest(const testing::TestCase* test_case, const testing::TestInfo* test_info) OVERRIDE; - virtual void RunTest( - const testing::TestCase* test_case, - const testing::TestInfo* test_info, - const base::TestLauncherDelegate::TestResultCallback& callback) OVERRIDE; - virtual void RunRemainingTests() OVERRIDE; + virtual void RunTests(base::TestLauncher* test_launcher, + const std::vector<std::string>& test_names) OVERRIDE; + virtual size_t RetryTests( + base::TestLauncher* test_launcher, + const std::vector<std::string>& test_names) OVERRIDE; private: - struct TestInfo { - std::string GetFullName() const { return test_case_name + "." + test_name; } - - std::string test_case_name; - std::string test_name; - std::vector<base::TestLauncherDelegate::TestResultCallback> callbacks; - }; - - // Launches test from |test_info| using |command_line| and parallel launcher. - void DoRunTest(const TestInfo& test_info, const CommandLine& command_line); + void DoRunTest(base::TestLauncher* test_launcher, + const std::string& test_name); - // Launches test named |test_name| using |command_line| and parallel launcher, + // Launches test named |test_name| using parallel launcher, // given result of PRE_ test |pre_test_result|. - void RunDependentTest(const std::string test_name, - const CommandLine& command_line, + void RunDependentTest(base::TestLauncher* test_launcher, + const std::string test_name, const base::TestResult& pre_test_result); // Callback to receive result of a test. void GTestCallback( - const TestInfo& test_info, + base::TestLauncher* test_launcher, + const std::string& test_name, int exit_code, const base::TimeDelta& elapsed_time, bool was_timeout, @@ -146,10 +139,19 @@ class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { base::ParallelTestLauncher parallel_launcher_; - // Store all tests to run before running any of them to properly - // handle PRE_ tests. The map is indexed by test full name (e.g. "A.B"). - typedef std::map<std::string, TestInfo> TestInfoMap; - TestInfoMap tests_to_run_; + // Store dependent test name (map is indexed by full test name). + typedef std::map<std::string, std::string> DependentTestMap; + DependentTestMap dependent_test_map_; + DependentTestMap reverse_dependent_test_map_; + + // Store unique data directory prefix for test names (without PRE_ prefixes). + // PRE_ tests and tests that depend on them must share the same + // data directory. Using test name as directory name leads to too long + // names (exceeding UNIX_PATH_MAX, which creates a problem with + // process_singleton_linux). Create a randomly-named temporary directory + // and keep track of the names so that PRE_ tests can still re-use them. + typedef std::map<std::string, base::FilePath> UserDataDirMap; + UserDataDirMap user_data_dir_map_; // Temporary directory for user data directories. base::ScopedTempDir temp_dir_; @@ -158,7 +160,8 @@ class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { }; void WrapperTestLauncherDelegate::OnTestIterationStarting() { - tests_to_run_.clear(); + dependent_test_map_.clear(); + user_data_dir_map_.clear(); } std::string WrapperTestLauncherDelegate::GetTestNameForFiltering( @@ -188,74 +191,112 @@ bool WrapperTestLauncherDelegate::ShouldRunTest( return true; } -void WrapperTestLauncherDelegate::RunTest( - const testing::TestCase* test_case, - const testing::TestInfo* test_info, - const base::TestLauncherDelegate::TestResultCallback& callback) { - TestInfo run_test_info; - run_test_info.test_case_name = test_case->name(); - run_test_info.test_name = test_info->name(); - run_test_info.callbacks.push_back(callback); - - DCHECK(!ContainsKey(tests_to_run_, run_test_info.GetFullName())); - tests_to_run_[run_test_info.GetFullName()] = run_test_info; -} - -void WrapperTestLauncherDelegate::RunRemainingTests() { - // PRE_ tests and tests that depend on them must share the same - // data directory. Using test name as directory name leads to too long - // names (exceeding UNIX_PATH_MAX, which creates a problem with - // process_singleton_linux). Create a randomly-named temporary directory - // and keep track of the names so that PRE_ tests can still re-use them. - std::map<std::string, base::FilePath> temp_directories; - +void WrapperTestLauncherDelegate::RunTests( + base::TestLauncher* test_launcher, + const std::vector<std::string>& test_names) { // List of tests we can kick off right now, depending on no other tests. - std::vector<std::pair<std::string, CommandLine> > tests_to_run_now; + std::vector<std::string> tests_to_run_now; - for (TestInfoMap::iterator i = tests_to_run_.begin(); - i != tests_to_run_.end(); - ++i) { - const TestInfo& test_info = i->second; + std::set<std::string> test_names_set(test_names.begin(), test_names.end()); + + for (size_t i = 0; i < test_names.size(); i++) { + std::string full_name(test_names[i]); // Make sure PRE_ tests and tests that depend on them share the same // data directory - based it on the test name without prefixes. - std::string test_name_no_pre(RemoveAnyPrePrefixes(test_info.GetFullName())); - if (!ContainsKey(temp_directories, test_name_no_pre)) { + std::string test_name_no_pre(RemoveAnyPrePrefixes(full_name)); + if (!ContainsKey(user_data_dir_map_, test_name_no_pre)) { base::FilePath temp_dir; CHECK(file_util::CreateTemporaryDirInDir( temp_dir_.path(), FILE_PATH_LITERAL("d"), &temp_dir)); - temp_directories[test_name_no_pre] = temp_dir; + user_data_dir_map_[test_name_no_pre] = temp_dir; } - CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); - CHECK(launcher_delegate_->AdjustChildProcessCommandLine( - &new_cmd_line, temp_directories[test_name_no_pre])); - + size_t dot_pos = full_name.find('.'); + CHECK_NE(dot_pos, std::string::npos); + std::string test_case_name = full_name.substr(0, dot_pos); + std::string test_name = full_name.substr(dot_pos + 1); std::string pre_test_name( - test_info.test_case_name + "." + kPreTestPrefix + test_info.test_name); - if (ContainsKey(tests_to_run_, pre_test_name)) { - tests_to_run_[pre_test_name].callbacks.push_back( - base::Bind(&WrapperTestLauncherDelegate::RunDependentTest, - base::Unretained(this), - test_info.GetFullName(), - new_cmd_line)); + test_case_name + "." + kPreTestPrefix + test_name); + if (ContainsKey(test_names_set, pre_test_name)) { + DCHECK(!ContainsKey(dependent_test_map_, pre_test_name)); + dependent_test_map_[pre_test_name] = full_name; + + DCHECK(!ContainsKey(reverse_dependent_test_map_, full_name)); + reverse_dependent_test_map_[full_name] = pre_test_name; } else { - tests_to_run_now.push_back( - std::make_pair(test_info.GetFullName(), new_cmd_line)); + tests_to_run_now.push_back(full_name); } } - for (size_t i = 0; i < tests_to_run_now.size(); i++) { - const TestInfo& test_info = tests_to_run_[tests_to_run_now[i].first]; - const CommandLine& cmd_line = tests_to_run_now[i].second; - DoRunTest(test_info, cmd_line); + for (size_t i = 0; i < tests_to_run_now.size(); i++) + DoRunTest(test_launcher, tests_to_run_now[i]); +} + +size_t WrapperTestLauncherDelegate::RetryTests( + base::TestLauncher* test_launcher, + const std::vector<std::string>& test_names) { + // List of tests we can kick off right now, depending on no other tests. + std::vector<std::string> tests_to_run_now; + + // We retry at least the tests requested to retry. + std::set<std::string> test_names_set(test_names.begin(), test_names.end()); + + // In the face of PRE_ tests, we need to retry the entire chain of tests, + // from the very first one. + for (size_t i = 0; i < test_names.size(); i++) { + std::string test_name(test_names[i]); + while (ContainsKey(reverse_dependent_test_map_, test_name)) { + test_name = reverse_dependent_test_map_[test_name]; + test_names_set.insert(test_name); + } } + + // Discard user data directories from any previous runs. Start with + // fresh state. + user_data_dir_map_.clear(); + + for (std::set<std::string>::const_iterator i = test_names_set.begin(); + i != test_names_set.end(); + ++i) { + std::string full_name(*i); + + // Make sure PRE_ tests and tests that depend on them share the same + // data directory - based it on the test name without prefixes. + std::string test_name_no_pre(RemoveAnyPrePrefixes(full_name)); + if (!ContainsKey(user_data_dir_map_, test_name_no_pre)) { + base::FilePath temp_dir; + CHECK(file_util::CreateTemporaryDirInDir( + temp_dir_.path(), FILE_PATH_LITERAL("d"), &temp_dir)); + user_data_dir_map_[test_name_no_pre] = temp_dir; + } + + size_t dot_pos = full_name.find('.'); + CHECK_NE(dot_pos, std::string::npos); + std::string test_case_name = full_name.substr(0, dot_pos); + std::string test_name = full_name.substr(dot_pos + 1); + std::string pre_test_name( + test_case_name + "." + kPreTestPrefix + test_name); + if (!ContainsKey(test_names_set, pre_test_name)) + tests_to_run_now.push_back(full_name); + } + + for (size_t i = 0; i < tests_to_run_now.size(); i++) + DoRunTest(test_launcher, tests_to_run_now[i]); + + return test_names_set.size(); } -void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info, - const CommandLine& command_line) { - CommandLine new_cmd_line(command_line.GetProgram()); - CommandLine::SwitchMap switches = command_line.GetSwitches(); +void WrapperTestLauncherDelegate::DoRunTest(base::TestLauncher* test_launcher, + const std::string& test_name) { + std::string test_name_no_pre(RemoveAnyPrePrefixes(test_name)); + + CommandLine cmd_line(*CommandLine::ForCurrentProcess()); + CHECK(launcher_delegate_->AdjustChildProcessCommandLine( + &cmd_line, user_data_dir_map_[test_name_no_pre])); + + CommandLine new_cmd_line(cmd_line.GetProgram()); + CommandLine::SwitchMap switches = cmd_line.GetSwitches(); // Strip out gtest_output flag because otherwise we would overwrite results // of the other tests. @@ -269,55 +310,52 @@ void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info, // Always enable disabled tests. This method is not called with disabled // tests unless this flag was specified to the browser test executable. new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); - new_cmd_line.AppendSwitchASCII( - "gtest_filter", - test_info.test_case_name + "." + test_info.test_name); + new_cmd_line.AppendSwitchASCII("gtest_filter", test_name); new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); char* browser_wrapper = getenv("BROWSER_WRAPPER"); - // PRE_ tests and tests that depend on them should share the sequence token - // name, so that they are run serially. - std::string test_name_no_pre = RemoveAnyPrePrefixes( - test_info.test_case_name + "." + test_info.test_name); - parallel_launcher_.LaunchChildGTestProcess( new_cmd_line, browser_wrapper ? browser_wrapper : std::string(), TestTimeouts::action_max_timeout(), base::Bind(&WrapperTestLauncherDelegate::GTestCallback, base::Unretained(this), - test_info)); + test_launcher, + test_name)); } void WrapperTestLauncherDelegate::RunDependentTest( + base::TestLauncher* test_launcher, const std::string test_name, - const CommandLine& command_line, const base::TestResult& pre_test_result) { - const TestInfo& test_info = tests_to_run_[test_name]; if (pre_test_result.status == base::TestResult::TEST_SUCCESS) { // Only run the dependent test if PRE_ test succeeded. - DoRunTest(test_info, command_line); + DoRunTest(test_launcher, test_name); } else { // Otherwise skip the test. base::TestResult test_result; - test_result.test_case_name = test_info.test_case_name; - test_result.test_name = test_info.test_name; + test_result.full_name = test_name; test_result.status = base::TestResult::TEST_SKIPPED; - for (size_t i = 0; i < test_info.callbacks.size(); i++) - test_info.callbacks[i].Run(test_result); + test_launcher->OnTestFinished(test_result); + + if (ContainsKey(dependent_test_map_, test_name)) { + RunDependentTest(test_launcher, + dependent_test_map_[test_name], + test_result); + } } } void WrapperTestLauncherDelegate::GTestCallback( - const TestInfo& test_info, + base::TestLauncher* test_launcher, + const std::string& test_name, int exit_code, const base::TimeDelta& elapsed_time, bool was_timeout, const std::string& output) { base::TestResult result; - result.test_case_name = test_info.test_case_name; - result.test_name = test_info.test_name; + result.full_name = test_name; // TODO(phajdan.jr): Recognize crashes. if (exit_code == 0) @@ -334,8 +372,10 @@ void WrapperTestLauncherDelegate::GTestCallback( fprintf(stdout, "%s", output.c_str()); fflush(stdout); - for (size_t i = 0; i < test_info.callbacks.size(); i++) - test_info.callbacks[i].Run(result); + if (ContainsKey(dependent_test_map_, test_name)) + RunDependentTest(test_launcher, dependent_test_map_[test_name], result); + + test_launcher->OnTestFinished(result); parallel_launcher_.ResetOutputWatchdog(); } |