Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: content/public/test/test_launcher.cc

Issue 24892002: GTTF: Fix handling of PRE_ tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/test/test_launcher.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <map>
7 #include <string> 8 #include <string>
8 #include <vector> 9 #include <vector>
9 10
10 #include "base/command_line.h" 11 #include "base/command_line.h"
11 #include "base/containers/hash_tables.h" 12 #include "base/containers/hash_tables.h"
12 #include "base/environment.h" 13 #include "base/environment.h"
13 #include "base/file_util.h" 14 #include "base/file_util.h"
14 #include "base/files/scoped_temp_dir.h" 15 #include "base/files/scoped_temp_dir.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/memory/linked_ptr.h" 17 #include "base/memory/linked_ptr.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 virtual bool ShouldRunTest(const testing::TestCase* test_case, 103 virtual bool ShouldRunTest(const testing::TestCase* test_case,
103 const testing::TestInfo* test_info) OVERRIDE; 104 const testing::TestInfo* test_info) OVERRIDE;
104 virtual void RunTest( 105 virtual void RunTest(
105 const testing::TestCase* test_case, 106 const testing::TestCase* test_case,
106 const testing::TestInfo* test_info, 107 const testing::TestInfo* test_info,
107 const base::TestLauncherDelegate::TestResultCallback& callback) OVERRIDE; 108 const base::TestLauncherDelegate::TestResultCallback& callback) OVERRIDE;
108 virtual void RunRemainingTests() OVERRIDE; 109 virtual void RunRemainingTests() OVERRIDE;
109 110
110 private: 111 private:
111 struct TestInfo { 112 struct TestInfo {
113 std::string GetFullName() const { return test_case_name + "." + test_name; }
114
112 std::string test_case_name; 115 std::string test_case_name;
113 std::string test_name; 116 std::string test_name;
114 base::TestLauncherDelegate::TestResultCallback callback; 117 std::vector<base::TestLauncherDelegate::TestResultCallback> callbacks;
115 }; 118 };
116 119
117 friend bool CompareTestInfo(const TestInfo& a, const TestInfo& b);
118
119 // Launches test from |test_info| using |command_line| and parallel launcher. 120 // Launches test from |test_info| using |command_line| and parallel launcher.
120 void DoRunTest(const TestInfo& test_info, const CommandLine& command_line); 121 void DoRunTest(const TestInfo& test_info, const CommandLine& command_line);
121 122
123 // Launches test named |test_name| using |command_line| and parallel launcher,
124 // given result of PRE_ test |pre_test_result|.
125 void RunDependentTest(const std::string test_name,
126 const CommandLine& command_line,
127 const base::TestResult& pre_test_result);
128
122 // Callback to receive result of a test. 129 // Callback to receive result of a test.
123 void GTestCallback( 130 void GTestCallback(
124 const TestInfo& test_info, 131 const TestInfo& test_info,
125 int exit_code, 132 int exit_code,
126 const base::TimeDelta& elapsed_time, 133 const base::TimeDelta& elapsed_time,
127 bool was_timeout, 134 bool was_timeout,
128 const std::string& output); 135 const std::string& output);
129 136
130 content::TestLauncherDelegate* launcher_delegate_; 137 content::TestLauncherDelegate* launcher_delegate_;
131 138
132 // Number of times a test timeout occurred. 139 // Number of times a test timeout occurred.
133 size_t timeout_count_; 140 size_t timeout_count_;
134 141
135 // True after a message about too many timeouts has been printed, 142 // True after a message about too many timeouts has been printed,
136 // to avoid doing it more than once. 143 // to avoid doing it more than once.
137 bool printed_timeout_message_; 144 bool printed_timeout_message_;
138 145
139 base::ParallelTestLauncher parallel_launcher_; 146 base::ParallelTestLauncher parallel_launcher_;
140 147
141 // Store all tests to run before running any of them to properly 148 // Store all tests to run before running any of them to properly
142 // handle PRE_ tests. 149 // handle PRE_ tests. The map is indexed by test full name (e.g. "A.B").
143 std::vector<TestInfo> tests_to_run_; 150 typedef std::map<std::string, TestInfo> TestInfoMap;
151 TestInfoMap tests_to_run_;
144 152
145 // Temporary directory for user data directories. 153 // Temporary directory for user data directories.
146 base::ScopedTempDir temp_dir_; 154 base::ScopedTempDir temp_dir_;
147 155
148 DISALLOW_COPY_AND_ASSIGN(WrapperTestLauncherDelegate); 156 DISALLOW_COPY_AND_ASSIGN(WrapperTestLauncherDelegate);
149 }; 157 };
150 158
151 std::string WrapperTestLauncherDelegate::GetTestNameForFiltering( 159 std::string WrapperTestLauncherDelegate::GetTestNameForFiltering(
152 const testing::TestCase* test_case, 160 const testing::TestCase* test_case,
153 const testing::TestInfo* test_info) { 161 const testing::TestInfo* test_info) {
(...skipping 21 matching lines...) Expand all
175 return true; 183 return true;
176 } 184 }
177 185
178 void WrapperTestLauncherDelegate::RunTest( 186 void WrapperTestLauncherDelegate::RunTest(
179 const testing::TestCase* test_case, 187 const testing::TestCase* test_case,
180 const testing::TestInfo* test_info, 188 const testing::TestInfo* test_info,
181 const base::TestLauncherDelegate::TestResultCallback& callback) { 189 const base::TestLauncherDelegate::TestResultCallback& callback) {
182 TestInfo run_test_info; 190 TestInfo run_test_info;
183 run_test_info.test_case_name = test_case->name(); 191 run_test_info.test_case_name = test_case->name();
184 run_test_info.test_name = test_info->name(); 192 run_test_info.test_name = test_info->name();
185 run_test_info.callback = callback; 193 run_test_info.callbacks.push_back(callback);
186 tests_to_run_.push_back(run_test_info);
187 }
188 194
189 bool CompareTestInfo(const WrapperTestLauncherDelegate::TestInfo& a, 195 DCHECK(!ContainsKey(tests_to_run_, run_test_info.GetFullName()));
190 const WrapperTestLauncherDelegate::TestInfo& b) { 196 tests_to_run_[run_test_info.GetFullName()] = run_test_info;
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)
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 } 197 }
209 198
210 void WrapperTestLauncherDelegate::RunRemainingTests() { 199 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 200 // 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 201 // data directory. Using test name as directory name leads to too long
215 // names (exceeding UNIX_PATH_MAX, which creates a problem with 202 // names (exceeding UNIX_PATH_MAX, which creates a problem with
216 // process_singleton_linux). Create a randomly-named temporary directory 203 // 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. 204 // and keep track of the names so that PRE_ tests can still re-use them.
218 std::map<std::string, base::FilePath> temp_directories; 205 std::map<std::string, base::FilePath> temp_directories;
219 206
220 for (size_t i = 0; i < tests_to_run_.size(); i++) { 207 // List of tests we can kick off right now, depending on no other tests.
221 TestInfo test_info(tests_to_run_[i]); 208 std::vector<std::pair<std::string, CommandLine> > tests_to_run_now;
209
210 for (TestInfoMap::iterator i = tests_to_run_.begin();
211 i != tests_to_run_.end();
212 ++i) {
213 const TestInfo& test_info = i->second;
222 214
223 // Make sure PRE_ tests and tests that depend on them share the same 215 // Make sure PRE_ tests and tests that depend on them share the same
224 // data directory - based it on the test name without prefixes. 216 // data directory - based it on the test name without prefixes.
225 std::string test_name_no_pre = RemoveAnyPrePrefixes( 217 std::string test_name_no_pre(RemoveAnyPrePrefixes(test_info.GetFullName()));
226 test_info.test_case_name + "." + test_info.test_name);
227 if (!ContainsKey(temp_directories, test_name_no_pre)) { 218 if (!ContainsKey(temp_directories, test_name_no_pre)) {
228 base::FilePath temp_dir; 219 base::FilePath temp_dir;
229 CHECK(file_util::CreateTemporaryDirInDir( 220 CHECK(file_util::CreateTemporaryDirInDir(
230 temp_dir_.path(), FILE_PATH_LITERAL("d"), &temp_dir)); 221 temp_dir_.path(), FILE_PATH_LITERAL("d"), &temp_dir));
231 temp_directories[test_name_no_pre] = temp_dir; 222 temp_directories[test_name_no_pre] = temp_dir;
232 } 223 }
233 224
234 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); 225 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess());
235 CHECK(launcher_delegate_->AdjustChildProcessCommandLine( 226 CHECK(launcher_delegate_->AdjustChildProcessCommandLine(
236 &new_cmd_line, temp_directories[test_name_no_pre])); 227 &new_cmd_line, temp_directories[test_name_no_pre]));
237 228
238 DoRunTest(test_info, new_cmd_line); 229 std::string pre_test_name(
230 test_info.test_case_name + "." + kPreTestPrefix + test_info.test_name);
231 if (ContainsKey(tests_to_run_, pre_test_name)) {
232 tests_to_run_[pre_test_name].callbacks.push_back(
233 base::Bind(&WrapperTestLauncherDelegate::RunDependentTest,
234 base::Unretained(this),
235 test_info.GetFullName(),
236 new_cmd_line));
237 } else {
238 tests_to_run_now.push_back(
239 std::make_pair(test_info.GetFullName(), new_cmd_line));
240 }
241 }
242
243 for (size_t i = 0; i < tests_to_run_now.size(); i++) {
244 const TestInfo& test_info = tests_to_run_[tests_to_run_now[i].first];
245 const CommandLine& cmd_line = tests_to_run_now[i].second;
246 DoRunTest(test_info, cmd_line);
239 } 247 }
240 } 248 }
241 249
242 void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info, 250 void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info,
243 const CommandLine& command_line) { 251 const CommandLine& command_line) {
244 CommandLine new_cmd_line(command_line.GetProgram()); 252 CommandLine new_cmd_line(command_line.GetProgram());
245 CommandLine::SwitchMap switches = command_line.GetSwitches(); 253 CommandLine::SwitchMap switches = command_line.GetSwitches();
246 254
247 // Strip out gtest_output flag because otherwise we would overwrite results 255 // Strip out gtest_output flag because otherwise we would overwrite results
248 // of the other tests. 256 // of the other tests.
(...skipping 12 matching lines...) Expand all
261 test_info.test_case_name + "." + test_info.test_name); 269 test_info.test_case_name + "." + test_info.test_name);
262 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); 270 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag);
263 271
264 char* browser_wrapper = getenv("BROWSER_WRAPPER"); 272 char* browser_wrapper = getenv("BROWSER_WRAPPER");
265 273
266 // PRE_ tests and tests that depend on them should share the sequence token 274 // PRE_ tests and tests that depend on them should share the sequence token
267 // name, so that they are run serially. 275 // name, so that they are run serially.
268 std::string test_name_no_pre = RemoveAnyPrePrefixes( 276 std::string test_name_no_pre = RemoveAnyPrePrefixes(
269 test_info.test_case_name + "." + test_info.test_name); 277 test_info.test_case_name + "." + test_info.test_name);
270 278
271 parallel_launcher_.LaunchNamedSequencedChildGTestProcess( 279 parallel_launcher_.LaunchChildGTestProcess(
272 test_name_no_pre,
273 new_cmd_line, 280 new_cmd_line,
274 browser_wrapper ? browser_wrapper : std::string(), 281 browser_wrapper ? browser_wrapper : std::string(),
275 TestTimeouts::action_max_timeout(), 282 TestTimeouts::action_max_timeout(),
276 base::Bind(&WrapperTestLauncherDelegate::GTestCallback, 283 base::Bind(&WrapperTestLauncherDelegate::GTestCallback,
277 base::Unretained(this), 284 base::Unretained(this),
278 test_info)); 285 test_info));
279 } 286 }
280 287
288 void WrapperTestLauncherDelegate::RunDependentTest(
289 const std::string test_name,
290 const CommandLine& command_line,
291 const base::TestResult& pre_test_result) {
292 const TestInfo& test_info = tests_to_run_[test_name];
293 if (pre_test_result.status == base::TestResult::TEST_SUCCESS) {
294 // Only run the dependent test if PRE_ test succeeded.
295 DoRunTest(test_info, command_line);
296 } else {
297 // Otherwise skip the test.
298 base::TestResult test_result;
299 test_result.test_case_name = test_info.test_case_name;
300 test_result.test_name = test_info.test_name;
301 test_result.status = base::TestResult::TEST_SKIPPED;
302 for (size_t i = 0; i < test_info.callbacks.size(); i++)
303 test_info.callbacks[i].Run(test_result);
304 }
305 }
306
281 void WrapperTestLauncherDelegate::GTestCallback( 307 void WrapperTestLauncherDelegate::GTestCallback(
282 const TestInfo& test_info, 308 const TestInfo& test_info,
283 int exit_code, 309 int exit_code,
284 const base::TimeDelta& elapsed_time, 310 const base::TimeDelta& elapsed_time,
285 bool was_timeout, 311 bool was_timeout,
286 const std::string& output) { 312 const std::string& output) {
287 base::TestResult result; 313 base::TestResult result;
288 result.test_case_name = test_info.test_case_name; 314 result.test_case_name = test_info.test_case_name;
289 result.test_name = test_info.test_name; 315 result.test_name = test_info.test_name;
290 316
291 // TODO(phajdan.jr): Recognize crashes. 317 // TODO(phajdan.jr): Recognize crashes.
292 if (exit_code == 0) 318 if (exit_code == 0)
293 result.status = base::TestResult::TEST_SUCCESS; 319 result.status = base::TestResult::TEST_SUCCESS;
294 else if (was_timeout) 320 else if (was_timeout)
295 result.status = base::TestResult::TEST_TIMEOUT; 321 result.status = base::TestResult::TEST_TIMEOUT;
296 else 322 else
297 result.status = base::TestResult::TEST_FAILURE; 323 result.status = base::TestResult::TEST_FAILURE;
298 324
299 result.elapsed_time = elapsed_time; 325 result.elapsed_time = elapsed_time;
300 326
301 // TODO(phajdan.jr): Use base::PrintTestOutputSnippetOnFailure after migrating 327 // TODO(phajdan.jr): Use base::PrintTestOutputSnippetOnFailure after migrating
302 // away from run_test_cases.py (http://crbug.com/236893). 328 // away from run_test_cases.py (http://crbug.com/236893).
303 fprintf(stdout, "%s", output.c_str()); 329 fprintf(stdout, "%s", output.c_str());
304 fflush(stdout); 330 fflush(stdout);
305 331
306 test_info.callback.Run(result); 332 for (size_t i = 0; i < test_info.callbacks.size(); i++)
333 test_info.callbacks[i].Run(result);
307 parallel_launcher_.ResetOutputWatchdog(); 334 parallel_launcher_.ResetOutputWatchdog();
308 } 335 }
309 336
310 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) { 337 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) {
311 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) 338 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name))
312 return true; 339 return true;
313 340
314 std::string switch_value = 341 std::string switch_value =
315 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name); 342 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name);
316 if (!base::StringToInt(switch_value, result) || *result < 1) { 343 if (!base::StringToInt(switch_value, result) || *result < 1) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 446
420 WrapperTestLauncherDelegate delegate(launcher_delegate, jobs); 447 WrapperTestLauncherDelegate delegate(launcher_delegate, jobs);
421 return base::LaunchTests(&delegate, argc, argv); 448 return base::LaunchTests(&delegate, argc, argv);
422 } 449 }
423 450
424 TestLauncherDelegate* GetCurrentTestLauncherDelegate() { 451 TestLauncherDelegate* GetCurrentTestLauncherDelegate() {
425 return g_launcher_delegate; 452 return g_launcher_delegate;
426 } 453 }
427 454
428 } // namespace content 455 } // namespace content
OLDNEW
« no previous file with comments | « base/test/test_launcher.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698