Index: content/public/test/test_launcher.cc |
diff --git a/content/public/test/test_launcher.cc b/content/public/test/test_launcher.cc |
index 5964d55f9a349994c92569c4fa0a6f92b1d2e331..12374514850a776bf87f7004a43fde3b1d88d12b 100644 |
--- a/content/public/test/test_launcher.cc |
+++ b/content/public/test/test_launcher.cc |
@@ -4,6 +4,7 @@ |
#include "content/public/test/test_launcher.h" |
+#include <map> |
#include <string> |
#include <vector> |
@@ -109,16 +110,22 @@ class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { |
private: |
struct TestInfo { |
+ std::string GetFullName() const { return test_case_name + "." + test_name; } |
+ |
std::string test_case_name; |
std::string test_name; |
- base::TestLauncherDelegate::TestResultCallback callback; |
+ std::vector<base::TestLauncherDelegate::TestResultCallback> callbacks; |
}; |
- friend bool CompareTestInfo(const TestInfo& a, const TestInfo& b); |
- |
// Launches test from |test_info| using |command_line| and parallel launcher. |
void DoRunTest(const TestInfo& test_info, const CommandLine& command_line); |
+ // Launches test named |test_name| using |command_line| and parallel launcher, |
+ // given result of PRE_ test |pre_test_result|. |
+ void RunDependentTest(const std::string test_name, |
+ const CommandLine& command_line, |
+ const base::TestResult& pre_test_result); |
+ |
// Callback to receive result of a test. |
void GTestCallback( |
const TestInfo& test_info, |
@@ -139,8 +146,9 @@ class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { |
base::ParallelTestLauncher parallel_launcher_; |
// Store all tests to run before running any of them to properly |
- // handle PRE_ tests. |
- std::vector<TestInfo> tests_to_run_; |
+ // 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_; |
// Temporary directory for user data directories. |
base::ScopedTempDir temp_dir_; |
@@ -182,34 +190,13 @@ void WrapperTestLauncherDelegate::RunTest( |
TestInfo run_test_info; |
run_test_info.test_case_name = test_case->name(); |
run_test_info.test_name = test_info->name(); |
- run_test_info.callback = callback; |
- tests_to_run_.push_back(run_test_info); |
-} |
+ run_test_info.callbacks.push_back(callback); |
-bool CompareTestInfo(const WrapperTestLauncherDelegate::TestInfo& a, |
- const WrapperTestLauncherDelegate::TestInfo& b) { |
- if (a.test_case_name == b.test_case_name) { |
- // Put PRE_ tests before tests that depend on them (e.g. PRE_Foo before Foo, |
- // and PRE_PRE_Foo before PRE_Foo). |
- if (std::string(kPreTestPrefix) + a.test_name == b.test_name) |
- return false; |
- if (a.test_name == std::string(kPreTestPrefix) + b.test_name) |
- return true; |
- } |
- |
- // Otherwise sort by full names, disregarding PRE_ completely so that |
- // this can still be Strict Weak Ordering. |
- std::string a_full( |
- RemoveAnyPrePrefixes(a.test_case_name + "." + a.test_name)); |
- std::string b_full( |
- RemoveAnyPrePrefixes(b.test_case_name + "." + b.test_name)); |
- |
- return a_full < b_full; |
+ DCHECK(!ContainsKey(tests_to_run_, run_test_info.GetFullName())); |
+ tests_to_run_[run_test_info.GetFullName()] = run_test_info; |
} |
void WrapperTestLauncherDelegate::RunRemainingTests() { |
- std::sort(tests_to_run_.begin(), tests_to_run_.end(), CompareTestInfo); |
- |
// 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 |
@@ -217,13 +204,17 @@ void WrapperTestLauncherDelegate::RunRemainingTests() { |
// and keep track of the names so that PRE_ tests can still re-use them. |
std::map<std::string, base::FilePath> temp_directories; |
- for (size_t i = 0; i < tests_to_run_.size(); i++) { |
- TestInfo test_info(tests_to_run_[i]); |
+ // 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; |
+ |
+ for (TestInfoMap::iterator i = tests_to_run_.begin(); |
+ i != tests_to_run_.end(); |
+ ++i) { |
+ const TestInfo& test_info = i->second; |
// 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.test_case_name + "." + test_info.test_name); |
+ std::string test_name_no_pre(RemoveAnyPrePrefixes(test_info.GetFullName())); |
if (!ContainsKey(temp_directories, test_name_no_pre)) { |
base::FilePath temp_dir; |
CHECK(file_util::CreateTemporaryDirInDir( |
@@ -235,7 +226,24 @@ void WrapperTestLauncherDelegate::RunRemainingTests() { |
CHECK(launcher_delegate_->AdjustChildProcessCommandLine( |
&new_cmd_line, temp_directories[test_name_no_pre])); |
- DoRunTest(test_info, new_cmd_line); |
+ 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)); |
+ } else { |
+ tests_to_run_now.push_back( |
+ std::make_pair(test_info.GetFullName(), new_cmd_line)); |
+ } |
+ } |
+ |
+ 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); |
} |
} |
@@ -268,8 +276,7 @@ void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info, |
std::string test_name_no_pre = RemoveAnyPrePrefixes( |
test_info.test_case_name + "." + test_info.test_name); |
- parallel_launcher_.LaunchNamedSequencedChildGTestProcess( |
- test_name_no_pre, |
+ parallel_launcher_.LaunchChildGTestProcess( |
new_cmd_line, |
browser_wrapper ? browser_wrapper : std::string(), |
TestTimeouts::action_max_timeout(), |
@@ -278,6 +285,25 @@ void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info, |
test_info)); |
} |
+void WrapperTestLauncherDelegate::RunDependentTest( |
+ 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); |
+ } 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.status = base::TestResult::TEST_SKIPPED; |
+ for (size_t i = 0; i < test_info.callbacks.size(); i++) |
+ test_info.callbacks[i].Run(test_result); |
+ } |
+} |
+ |
void WrapperTestLauncherDelegate::GTestCallback( |
const TestInfo& test_info, |
int exit_code, |
@@ -303,7 +329,8 @@ void WrapperTestLauncherDelegate::GTestCallback( |
fprintf(stdout, "%s", output.c_str()); |
fflush(stdout); |
- test_info.callback.Run(result); |
+ for (size_t i = 0; i < test_info.callbacks.size(); i++) |
+ test_info.callbacks[i].Run(result); |
parallel_launcher_.ResetOutputWatchdog(); |
} |