Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/public/test/test_launcher.h" | 5 #include "content/public/test/test_launcher.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/containers/hash_tables.h" | 11 #include "base/containers/hash_tables.h" |
| 12 #include "base/environment.h" | 12 #include "base/environment.h" |
| 13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 14 #include "base/files/scoped_temp_dir.h" | 14 #include "base/files/scoped_temp_dir.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/memory/linked_ptr.h" | 16 #include "base/memory/linked_ptr.h" |
| 17 #include "base/memory/scoped_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
| 18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
| 19 #include "base/stl_util.h" | |
| 19 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
| 21 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 23 #include "base/test/parallel_test_launcher.h" | |
| 22 #include "base/test/test_launcher.h" | 24 #include "base/test/test_launcher.h" |
| 23 #include "base/test/test_suite.h" | 25 #include "base/test/test_suite.h" |
| 26 #include "base/test/test_switches.h" | |
| 24 #include "base/test/test_timeouts.h" | 27 #include "base/test/test_timeouts.h" |
| 25 #include "base/time/time.h" | 28 #include "base/time/time.h" |
| 26 #include "content/public/app/content_main.h" | 29 #include "content/public/app/content_main.h" |
| 27 #include "content/public/app/content_main_delegate.h" | 30 #include "content/public/app/content_main_delegate.h" |
| 28 #include "content/public/app/startup_helper_win.h" | 31 #include "content/public/app/startup_helper_win.h" |
| 29 #include "content/public/common/content_switches.h" | 32 #include "content/public/common/content_switches.h" |
| 30 #include "content/public/common/sandbox_init.h" | 33 #include "content/public/common/sandbox_init.h" |
| 31 #include "content/public/test/browser_test.h" | 34 #include "content/public/test/browser_test.h" |
| 32 #include "net/base/escape.h" | 35 #include "net/base/escape.h" |
| 33 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 50 // that span browser restarts. | 53 // that span browser restarts. |
| 51 const char kPreTestPrefix[] = "PRE_"; | 54 const char kPreTestPrefix[] = "PRE_"; |
| 52 | 55 |
| 53 // Manual tests only run when --run-manual is specified. This allows writing | 56 // Manual tests only run when --run-manual is specified. This allows writing |
| 54 // tests that don't run automatically but are still in the same test binary. | 57 // tests that don't run automatically but are still in the same test binary. |
| 55 // This is useful so that a team that wants to run a few tests doesn't have to | 58 // This is useful so that a team that wants to run a few tests doesn't have to |
| 56 // add a new binary that must be compiled on all builds. | 59 // add a new binary that must be compiled on all builds. |
| 57 const char kManualTestPrefix[] = "MANUAL_"; | 60 const char kManualTestPrefix[] = "MANUAL_"; |
| 58 | 61 |
| 59 TestLauncherDelegate* g_launcher_delegate; | 62 TestLauncherDelegate* g_launcher_delegate; |
| 60 } | |
| 61 | 63 |
| 62 namespace { | 64 std::string RemoveAnyPrePrefixes(const std::string& test_name) { |
| 63 | 65 std::string result(test_name); |
| 64 int DoRunTestInternal(const testing::TestCase* test_case, | 66 ReplaceSubstringsAfterOffset(&result, 0, kPreTestPrefix, std::string()); |
| 65 const std::string& test_name, | 67 return result; |
| 66 const CommandLine& command_line, | |
| 67 base::TimeDelta default_timeout, | |
| 68 bool* was_timeout) { | |
| 69 if (test_case) { | |
| 70 std::string pre_test_name = test_name; | |
| 71 std::string replace_string = std::string(".") + kPreTestPrefix; | |
| 72 ReplaceFirstSubstringAfterOffset(&pre_test_name, 0, ".", replace_string); | |
| 73 for (int i = 0; i < test_case->total_test_count(); ++i) { | |
| 74 const testing::TestInfo* test_info = test_case->GetTestInfo(i); | |
| 75 std::string cur_test_name = test_info->test_case_name(); | |
| 76 cur_test_name.append("."); | |
| 77 cur_test_name.append(test_info->name()); | |
| 78 if (cur_test_name == pre_test_name) { | |
| 79 int exit_code = DoRunTestInternal(test_case, | |
| 80 pre_test_name, | |
| 81 command_line, | |
| 82 default_timeout, | |
| 83 was_timeout); | |
| 84 if (exit_code != 0) | |
| 85 return exit_code; | |
| 86 } | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 CommandLine new_cmd_line(command_line.GetProgram()); | |
| 91 CommandLine::SwitchMap switches = command_line.GetSwitches(); | |
| 92 | |
| 93 // Strip out gtest_output flag because otherwise we would overwrite results | |
| 94 // of the other tests. | |
| 95 switches.erase(base::kGTestOutputFlag); | |
| 96 | |
| 97 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); | |
| 98 iter != switches.end(); ++iter) { | |
| 99 new_cmd_line.AppendSwitchNative(iter->first, iter->second); | |
| 100 } | |
| 101 | |
| 102 // Always enable disabled tests. This method is not called with disabled | |
| 103 // tests unless this flag was specified to the browser test executable. | |
| 104 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); | |
| 105 new_cmd_line.AppendSwitchASCII("gtest_filter", test_name); | |
| 106 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); | |
| 107 | |
| 108 char* browser_wrapper = getenv("BROWSER_WRAPPER"); | |
| 109 int exit_code = base::LaunchChildGTestProcess( | |
| 110 new_cmd_line, | |
| 111 browser_wrapper ? browser_wrapper : std::string(), | |
| 112 default_timeout, | |
| 113 was_timeout); | |
| 114 if (*was_timeout) { | |
| 115 LOG(ERROR) << "Test timeout (" << default_timeout.InMilliseconds() | |
| 116 << " ms) exceeded for " << test_name; | |
| 117 } | |
| 118 | |
| 119 return exit_code; | |
| 120 } | |
| 121 | |
| 122 // Runs test specified by |test_name| in a child process, | |
| 123 // and returns the exit code. | |
| 124 int DoRunTest(TestLauncherDelegate* launcher_delegate, | |
| 125 const testing::TestCase* test_case, | |
| 126 const std::string& test_name, | |
| 127 base::TimeDelta default_timeout, | |
| 128 bool* was_timeout) { | |
| 129 if (was_timeout) | |
| 130 *was_timeout = false; | |
| 131 | |
| 132 #if defined(OS_MACOSX) | |
| 133 // Some of the below method calls will leak objects if there is no | |
| 134 // autorelease pool in place. | |
| 135 base::mac::ScopedNSAutoreleasePool pool; | |
| 136 #endif | |
| 137 | |
| 138 base::ScopedTempDir temp_dir; | |
| 139 // Create a new data dir and pass it to the child. | |
| 140 if (!temp_dir.CreateUniqueTempDir() || !temp_dir.IsValid()) { | |
| 141 LOG(ERROR) << "Error creating temp data directory"; | |
| 142 return -1; | |
| 143 } | |
| 144 | |
| 145 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); | |
| 146 if (!launcher_delegate->AdjustChildProcessCommandLine(&new_cmd_line, | |
| 147 temp_dir.path())) { | |
| 148 return -1; | |
| 149 } | |
| 150 | |
| 151 return DoRunTestInternal( | |
| 152 test_case, test_name, new_cmd_line, default_timeout, was_timeout); | |
| 153 } | 68 } |
| 154 | 69 |
| 155 void PrintUsage() { | 70 void PrintUsage() { |
| 156 fprintf(stdout, | 71 fprintf(stdout, |
| 157 "Runs tests using the gtest framework, each test being run in its own\n" | 72 "Runs tests using the gtest framework, each test being run in its own\n" |
| 158 "process. Any gtest flags can be specified.\n" | 73 "process. Any gtest flags can be specified.\n" |
| 159 " --single_process\n" | 74 " --single_process\n" |
| 160 " Runs the tests and the launcher in the same process. Useful for \n" | 75 " Runs the tests and the launcher in the same process. Useful for \n" |
| 161 " debugging a specific test in a debugger.\n" | 76 " debugging a specific test in a debugger.\n" |
| 162 " --single-process\n" | 77 " --single-process\n" |
| 163 " Same as above, and also runs Chrome in single-process mode.\n" | 78 " Same as above, and also runs Chrome in single-process mode.\n" |
| 164 " --help\n" | 79 " --help\n" |
| 165 " Shows this message.\n" | 80 " Shows this message.\n" |
| 166 " --gtest_help\n" | 81 " --gtest_help\n" |
| 167 " Shows the gtest help message.\n"); | 82 " Shows the gtest help message.\n"); |
| 168 } | 83 } |
| 169 | 84 |
| 170 // Implementation of base::TestLauncherDelegate. This is also a test launcher, | 85 // Implementation of base::TestLauncherDelegate. This is also a test launcher, |
| 171 // wrapping a lower-level test launcher with content-specific code. | 86 // wrapping a lower-level test launcher with content-specific code. |
| 172 class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { | 87 class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { |
| 173 public: | 88 public: |
| 174 explicit WrapperTestLauncherDelegate( | 89 WrapperTestLauncherDelegate(content::TestLauncherDelegate* launcher_delegate, |
| 175 content::TestLauncherDelegate* launcher_delegate) | 90 size_t jobs) |
| 176 : launcher_delegate_(launcher_delegate), | 91 : launcher_delegate_(launcher_delegate), |
| 177 timeout_count_(0), | 92 timeout_count_(0), |
| 178 printed_timeout_message_(false) { | 93 printed_timeout_message_(false), |
| 94 parallel_launcher_(jobs) { | |
| 95 CHECK(temp_dir_.CreateUniqueTempDir()); | |
| 179 } | 96 } |
| 180 | 97 |
| 181 // base::TestLauncherDelegate: | 98 // base::TestLauncherDelegate: |
| 99 virtual std::string GetTestNameForFiltering( | |
| 100 const testing::TestCase* test_case, | |
| 101 const testing::TestInfo* test_info) OVERRIDE; | |
| 182 virtual bool ShouldRunTest(const testing::TestCase* test_case, | 102 virtual bool ShouldRunTest(const testing::TestCase* test_case, |
| 183 const testing::TestInfo* test_info) OVERRIDE; | 103 const testing::TestInfo* test_info) OVERRIDE; |
| 184 virtual void RunTest( | 104 virtual void RunTest( |
| 185 const testing::TestCase* test_case, | 105 const testing::TestCase* test_case, |
| 186 const testing::TestInfo* test_info, | 106 const testing::TestInfo* test_info, |
| 187 const base::TestLauncherDelegate::TestResultCallback& callback) OVERRIDE; | 107 const base::TestLauncherDelegate::TestResultCallback& callback) OVERRIDE; |
| 188 virtual void RunRemainingTests() OVERRIDE; | 108 virtual void RunRemainingTests() OVERRIDE; |
| 189 | 109 |
| 190 private: | 110 private: |
| 111 struct TestInfo { | |
| 112 std::string test_case_name; | |
| 113 std::string test_name; | |
| 114 base::TestLauncherDelegate::TestResultCallback callback; | |
| 115 }; | |
| 116 | |
| 117 friend bool CompareTestInfo(const TestInfo& a, const TestInfo& b); | |
| 118 | |
| 119 // Launches test from |test_info| using |command_line| and parallel launcher. | |
| 120 void DoRunTest(const TestInfo& test_info, const CommandLine& command_line); | |
| 121 | |
| 122 // Callback to receive result of a test. | |
| 123 void GTestCallback( | |
| 124 const TestInfo& test_info, | |
| 125 int exit_code, | |
| 126 const base::TimeDelta& elapsed_time, | |
| 127 bool was_timeout, | |
| 128 const std::string& output); | |
| 129 | |
| 191 content::TestLauncherDelegate* launcher_delegate_; | 130 content::TestLauncherDelegate* launcher_delegate_; |
| 192 | 131 |
| 193 // Number of times a test timeout occurred. | 132 // Number of times a test timeout occurred. |
| 194 size_t timeout_count_; | 133 size_t timeout_count_; |
| 195 | 134 |
| 196 // True after a message about too many timeouts has been printed, | 135 // True after a message about too many timeouts has been printed, |
| 197 // to avoid doing it more than once. | 136 // to avoid doing it more than once. |
| 198 bool printed_timeout_message_; | 137 bool printed_timeout_message_; |
| 199 | 138 |
| 139 base::ParallelTestLauncher parallel_launcher_; | |
| 140 | |
| 141 // Store all tests to run before running any of them to properly | |
| 142 // handle PRE_ tests. | |
| 143 std::vector<TestInfo> tests_to_run_; | |
| 144 | |
| 145 // Temporary directory for user data directories. | |
| 146 base::ScopedTempDir temp_dir_; | |
| 147 | |
| 200 DISALLOW_COPY_AND_ASSIGN(WrapperTestLauncherDelegate); | 148 DISALLOW_COPY_AND_ASSIGN(WrapperTestLauncherDelegate); |
| 201 }; | 149 }; |
| 202 | 150 |
| 151 std::string WrapperTestLauncherDelegate::GetTestNameForFiltering( | |
| 152 const testing::TestCase* test_case, | |
| 153 const testing::TestInfo* test_info) { | |
| 154 return RemoveAnyPrePrefixes( | |
| 155 std::string(test_case->name()) + "." + test_info->name()); | |
| 156 } | |
| 157 | |
| 203 bool WrapperTestLauncherDelegate::ShouldRunTest( | 158 bool WrapperTestLauncherDelegate::ShouldRunTest( |
| 204 const testing::TestCase* test_case, | 159 const testing::TestCase* test_case, |
| 205 const testing::TestInfo* test_info) { | 160 const testing::TestInfo* test_info) { |
| 206 std::string test_name = | |
| 207 std::string(test_case->name()) + "." + test_info->name(); | |
| 208 | |
| 209 if (StartsWithASCII(test_info->name(), kPreTestPrefix, true)) | |
| 210 return false; | |
| 211 | |
| 212 if (StartsWithASCII(test_info->name(), kManualTestPrefix, true) && | 161 if (StartsWithASCII(test_info->name(), kManualTestPrefix, true) && |
| 213 !CommandLine::ForCurrentProcess()->HasSwitch(kRunManualTestsFlag)) { | 162 !CommandLine::ForCurrentProcess()->HasSwitch(kRunManualTestsFlag)) { |
| 214 return false; | 163 return false; |
| 215 } | 164 } |
| 216 | 165 |
| 217 // Stop test execution after too many timeouts. | 166 // Stop test execution after too many timeouts. |
| 218 if (timeout_count_ > 5) { | 167 if (timeout_count_ > 5) { |
| 219 if (!printed_timeout_message_) { | 168 if (!printed_timeout_message_) { |
| 220 printed_timeout_message_ = true; | 169 printed_timeout_message_ = true; |
| 221 printf("Too many timeouts, aborting test\n"); | 170 printf("Too many timeouts, aborting test\n"); |
| 222 } | 171 } |
| 223 return false; | 172 return false; |
| 224 } | 173 } |
| 225 | 174 |
| 226 return true; | 175 return true; |
| 227 } | 176 } |
| 228 | 177 |
| 229 void WrapperTestLauncherDelegate::RunTest( | 178 void WrapperTestLauncherDelegate::RunTest( |
| 230 const testing::TestCase* test_case, | 179 const testing::TestCase* test_case, |
| 231 const testing::TestInfo* test_info, | 180 const testing::TestInfo* test_info, |
| 232 const base::TestLauncherDelegate::TestResultCallback& callback) { | 181 const base::TestLauncherDelegate::TestResultCallback& callback) { |
| 233 base::TimeTicks start_time = base::TimeTicks::Now(); | 182 TestInfo run_test_info; |
| 234 bool was_timeout = false; | 183 run_test_info.test_case_name = test_case->name(); |
| 235 std::string test_name = | 184 run_test_info.test_name = test_info->name(); |
| 236 std::string(test_case->name()) + "." + test_info->name(); | 185 run_test_info.callback = callback; |
| 237 int exit_code = DoRunTest(launcher_delegate_, | 186 tests_to_run_.push_back(run_test_info); |
| 238 test_case, | 187 } |
| 239 test_name, | |
| 240 TestTimeouts::action_max_timeout(), | |
| 241 &was_timeout); | |
| 242 if (was_timeout) | |
| 243 timeout_count_++; | |
| 244 | 188 |
| 189 bool CompareTestInfo(const WrapperTestLauncherDelegate::TestInfo& a, | |
| 190 const WrapperTestLauncherDelegate::TestInfo& b) { | |
| 191 if (a.test_case_name == b.test_case_name) { | |
| 192 // Put PRE_ tests before tests that depend on them (e.g. PRE_Foo before Foo, | |
| 193 // and PRE_PRE_Foo before PRE_Foo). | |
| 194 if (std::string(kPreTestPrefix) + a.test_name == b.test_name) | |
|
loislo
2013/09/26 05:47:33
This comparer doesn't work properly. It doesn't Tr
jam
2013/09/26 21:36:03
Pawel: ping
can this cause PRE tests to run in the
Paweł Hajdan Jr.
2013/09/26 23:32:28
Given this comparator is not StrictWeakOrdering, a
| |
| 195 return false; | |
| 196 if (a.test_name == std::string(kPreTestPrefix) + b.test_name) | |
| 197 return true; | |
| 198 } | |
| 199 | |
| 200 // Otherwise sort by full names, disregarding PRE_ completely so that | |
| 201 // this can still be Strict Weak Ordering. | |
| 202 std::string a_full( | |
| 203 RemoveAnyPrePrefixes(a.test_case_name + "." + a.test_name)); | |
| 204 std::string b_full( | |
| 205 RemoveAnyPrePrefixes(b.test_case_name + "." + b.test_name)); | |
| 206 | |
| 207 return a_full < b_full; | |
| 208 } | |
| 209 | |
| 210 void WrapperTestLauncherDelegate::RunRemainingTests() { | |
| 211 std::sort(tests_to_run_.begin(), tests_to_run_.end(), CompareTestInfo); | |
| 212 | |
| 213 // PRE_ tests and tests that depend on them must share the same | |
| 214 // data directory. Using test name as directory name leads to too long | |
| 215 // names (exceeding UNIX_PATH_MAX, which creates a problem with | |
| 216 // process_singleton_linux). Create a randomly-named temporary directory | |
| 217 // and keep track of the names so that PRE_ tests can still re-use them. | |
| 218 std::map<std::string, base::FilePath> temp_directories; | |
| 219 | |
| 220 for (size_t i = 0; i < tests_to_run_.size(); i++) { | |
| 221 TestInfo test_info(tests_to_run_[i]); | |
| 222 | |
| 223 // Make sure PRE_ tests and tests that depend on them share the same | |
| 224 // data directory - based it on the test name without prefixes. | |
| 225 std::string test_name_no_pre = RemoveAnyPrePrefixes( | |
| 226 test_info.test_case_name + "." + test_info.test_name); | |
| 227 if (!ContainsKey(temp_directories, test_name_no_pre)) { | |
| 228 base::FilePath temp_dir; | |
| 229 CHECK(file_util::CreateTemporaryDirInDir( | |
| 230 temp_dir_.path(), FILE_PATH_LITERAL("d"), &temp_dir)); | |
| 231 temp_directories[test_name_no_pre] = temp_dir; | |
| 232 } | |
| 233 | |
| 234 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); | |
| 235 CHECK(launcher_delegate_->AdjustChildProcessCommandLine( | |
| 236 &new_cmd_line, temp_directories[test_name_no_pre])); | |
| 237 | |
| 238 DoRunTest(test_info, new_cmd_line); | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info, | |
| 243 const CommandLine& command_line) { | |
| 244 CommandLine new_cmd_line(command_line.GetProgram()); | |
| 245 CommandLine::SwitchMap switches = command_line.GetSwitches(); | |
| 246 | |
| 247 // Strip out gtest_output flag because otherwise we would overwrite results | |
| 248 // of the other tests. | |
| 249 switches.erase(base::kGTestOutputFlag); | |
| 250 | |
| 251 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); | |
| 252 iter != switches.end(); ++iter) { | |
| 253 new_cmd_line.AppendSwitchNative(iter->first, iter->second); | |
| 254 } | |
| 255 | |
| 256 // Always enable disabled tests. This method is not called with disabled | |
| 257 // tests unless this flag was specified to the browser test executable. | |
| 258 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); | |
| 259 new_cmd_line.AppendSwitchASCII( | |
| 260 "gtest_filter", | |
| 261 test_info.test_case_name + "." + test_info.test_name); | |
| 262 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); | |
| 263 | |
| 264 char* browser_wrapper = getenv("BROWSER_WRAPPER"); | |
| 265 | |
| 266 // PRE_ tests and tests that depend on them should share the sequence token | |
| 267 // name, so that they are run serially. | |
| 268 std::string test_name_no_pre = RemoveAnyPrePrefixes( | |
| 269 test_info.test_case_name + "." + test_info.test_name); | |
| 270 | |
| 271 parallel_launcher_.LaunchNamedSequencedChildGTestProcess( | |
| 272 test_name_no_pre, | |
| 273 new_cmd_line, | |
| 274 browser_wrapper ? browser_wrapper : std::string(), | |
| 275 TestTimeouts::action_max_timeout(), | |
| 276 base::Bind(&WrapperTestLauncherDelegate::GTestCallback, | |
| 277 base::Unretained(this), | |
| 278 test_info)); | |
| 279 } | |
| 280 | |
| 281 void WrapperTestLauncherDelegate::GTestCallback( | |
| 282 const TestInfo& test_info, | |
| 283 int exit_code, | |
| 284 const base::TimeDelta& elapsed_time, | |
| 285 bool was_timeout, | |
| 286 const std::string& output) { | |
| 245 base::TestResult result; | 287 base::TestResult result; |
| 246 result.test_case_name = test_case->name(); | 288 result.test_case_name = test_info.test_case_name; |
| 247 result.test_name = test_info->name(); | 289 result.test_name = test_info.test_name; |
| 248 | 290 |
| 249 // TODO(phajdan.jr): Recognize crashes. | 291 // TODO(phajdan.jr): Recognize crashes. |
| 250 if (exit_code == 0) | 292 if (exit_code == 0) |
| 251 result.status = base::TestResult::TEST_SUCCESS; | 293 result.status = base::TestResult::TEST_SUCCESS; |
| 252 else if (was_timeout) | 294 else if (was_timeout) |
| 253 result.status = base::TestResult::TEST_TIMEOUT; | 295 result.status = base::TestResult::TEST_TIMEOUT; |
| 254 else | 296 else |
| 255 result.status = base::TestResult::TEST_FAILURE; | 297 result.status = base::TestResult::TEST_FAILURE; |
| 256 | 298 |
| 257 result.elapsed_time = (base::TimeTicks::Now() - start_time); | 299 result.elapsed_time = elapsed_time; |
| 258 | 300 |
| 259 callback.Run(result); | 301 // TODO(phajdan.jr): Use base::PrintTestOutputSnippetOnFailure after migrating |
| 302 // away from run_test_cases.py (http://crbug.com/236893). | |
| 303 fprintf(stdout, "%s", output.c_str()); | |
| 304 fflush(stdout); | |
| 305 | |
| 306 test_info.callback.Run(result); | |
| 307 parallel_launcher_.ResetOutputWatchdog(); | |
| 260 } | 308 } |
| 261 | 309 |
| 262 void WrapperTestLauncherDelegate::RunRemainingTests() { | 310 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) { |
| 263 // No need to do anything else here, we launch tests synchronously. | 311 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) |
| 312 return true; | |
| 313 | |
| 314 std::string switch_value = | |
| 315 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name); | |
| 316 if (!base::StringToInt(switch_value, result) || *result < 1) { | |
| 317 LOG(ERROR) << "Invalid value for " << switch_name << ": " << switch_value; | |
| 318 return false; | |
| 319 } | |
| 320 | |
| 321 return true; | |
| 264 } | 322 } |
| 265 | 323 |
| 266 } // namespace | 324 } // namespace |
| 267 | 325 |
| 268 // The following is kept for historical reasons (so people that are used to | 326 // The following is kept for historical reasons (so people that are used to |
| 269 // using it don't get surprised). | 327 // using it don't get surprised). |
| 270 const char kChildProcessFlag[] = "child"; | 328 const char kChildProcessFlag[] = "child"; |
| 271 | 329 |
| 272 const char kHelpFlag[] = "help"; | 330 const char kHelpFlag[] = "help"; |
| 273 | 331 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 "For debugging a test inside a debugger, use the\n" | 408 "For debugging a test inside a debugger, use the\n" |
| 351 "--gtest_filter=<your_test_name> flag along with either\n" | 409 "--gtest_filter=<your_test_name> flag along with either\n" |
| 352 "--single_process (to run the test in one launcher/browser process) or\n" | 410 "--single_process (to run the test in one launcher/browser process) or\n" |
| 353 "--single-process (to do the above, and also run Chrome in single-" | 411 "--single-process (to do the above, and also run Chrome in single-" |
| 354 "process mode).\n"); | 412 "process mode).\n"); |
| 355 | 413 |
| 356 base::AtExitManager at_exit; | 414 base::AtExitManager at_exit; |
| 357 testing::InitGoogleTest(&argc, argv); | 415 testing::InitGoogleTest(&argc, argv); |
| 358 TestTimeouts::Initialize(); | 416 TestTimeouts::Initialize(); |
| 359 | 417 |
| 418 int jobs = 1; // TODO(phajdan.jr): Default to half the number of CPU cores. | |
| 419 if (!GetSwitchValueAsInt(switches::kTestLauncherJobs, &jobs)) | |
| 420 return 1; | |
| 421 | |
| 360 base::MessageLoopForIO message_loop; | 422 base::MessageLoopForIO message_loop; |
| 361 | 423 |
| 362 WrapperTestLauncherDelegate delegate(launcher_delegate); | 424 WrapperTestLauncherDelegate delegate(launcher_delegate, jobs); |
| 363 return base::LaunchTests(&delegate, argc, argv); | 425 return base::LaunchTests(&delegate, argc, argv); |
| 364 } | 426 } |
| 365 | 427 |
| 366 TestLauncherDelegate* GetCurrentTestLauncherDelegate() { | 428 TestLauncherDelegate* GetCurrentTestLauncherDelegate() { |
| 367 return g_launcher_delegate; | 429 return g_launcher_delegate; |
| 368 } | 430 } |
| 369 | 431 |
| 370 } // namespace content | 432 } // namespace content |
| OLD | NEW |