OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "base/test/unit_test_launcher.h" | 5 #include "base/test/unit_test_launcher.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 struct TestLaunchInfo { | 92 struct TestLaunchInfo { |
93 std::string GetFullName() const { | 93 std::string GetFullName() const { |
94 return test_case_name + "." + test_name; | 94 return test_case_name + "." + test_name; |
95 } | 95 } |
96 | 96 |
97 std::string test_case_name; | 97 std::string test_case_name; |
98 std::string test_name; | 98 std::string test_name; |
99 TestResultCallback callback; | 99 TestResultCallback callback; |
100 }; | 100 }; |
101 | 101 |
| 102 virtual std::string GetTestNameForFiltering( |
| 103 const testing::TestCase* test_case, |
| 104 const testing::TestInfo* test_info) OVERRIDE { |
| 105 DCHECK(thread_checker_.CalledOnValidThread()); |
| 106 |
| 107 return std::string(test_case->name()) + "." + test_info->name(); |
| 108 } |
| 109 |
102 virtual bool ShouldRunTest(const testing::TestCase* test_case, | 110 virtual bool ShouldRunTest(const testing::TestCase* test_case, |
103 const testing::TestInfo* test_info) OVERRIDE { | 111 const testing::TestInfo* test_info) OVERRIDE { |
104 DCHECK(thread_checker_.CalledOnValidThread()); | 112 DCHECK(thread_checker_.CalledOnValidThread()); |
105 | 113 |
106 // There is no additional logic to disable specific tests. | 114 // There is no additional logic to disable specific tests. |
107 return true; | 115 return true; |
108 } | 116 } |
109 | 117 |
110 virtual void RunTest(const testing::TestCase* test_case, | 118 virtual void RunTest(const testing::TestCase* test_case, |
111 const testing::TestInfo* test_info, | 119 const testing::TestInfo* test_info, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 Bind(&UnitTestLauncherDelegate::GTestCallback, | 168 Bind(&UnitTestLauncherDelegate::GTestCallback, |
161 base::Unretained(this), | 169 base::Unretained(this), |
162 tests_, | 170 tests_, |
163 output_file)); | 171 output_file)); |
164 tests_.clear(); | 172 tests_.clear(); |
165 } | 173 } |
166 | 174 |
167 void GTestCallback(const std::vector<TestLaunchInfo>& tests, | 175 void GTestCallback(const std::vector<TestLaunchInfo>& tests, |
168 const FilePath& output_file, | 176 const FilePath& output_file, |
169 int exit_code, | 177 int exit_code, |
| 178 const TimeDelta& elapsed_time, |
170 bool was_timeout, | 179 bool was_timeout, |
171 const std::string& output) { | 180 const std::string& output) { |
172 DCHECK(thread_checker_.CalledOnValidThread()); | 181 DCHECK(thread_checker_.CalledOnValidThread()); |
173 std::vector<TestLaunchInfo> tests_to_relaunch_after_interruption; | 182 std::vector<TestLaunchInfo> tests_to_relaunch_after_interruption; |
174 bool called_any_callbacks = | 183 bool called_any_callbacks = |
175 ProcessTestResults(tests, | 184 ProcessTestResults(tests, |
176 output_file, | 185 output_file, |
177 output, | 186 output, |
178 exit_code, | 187 exit_code, |
179 was_timeout, | 188 was_timeout, |
180 &tests_to_relaunch_after_interruption); | 189 &tests_to_relaunch_after_interruption); |
181 | 190 |
182 for (size_t i = 0; i < tests_to_relaunch_after_interruption.size(); i++) | 191 for (size_t i = 0; i < tests_to_relaunch_after_interruption.size(); i++) |
183 tests_.push_back(tests_to_relaunch_after_interruption[i]); | 192 tests_.push_back(tests_to_relaunch_after_interruption[i]); |
184 RunRemainingTests(); | 193 RunRemainingTests(); |
185 | 194 |
186 if (called_any_callbacks) | 195 if (called_any_callbacks) |
187 parallel_launcher_.ResetOutputWatchdog(); | 196 parallel_launcher_.ResetOutputWatchdog(); |
188 | 197 |
189 // The temporary file's directory is also temporary. | 198 // The temporary file's directory is also temporary. |
190 DeleteFile(output_file.DirName(), true); | 199 DeleteFile(output_file.DirName(), true); |
191 } | 200 } |
192 | 201 |
193 static void MaybePrintTestOutputSnippet(const TestResult& result, | |
194 const std::string& full_output) { | |
195 if (result.status == TestResult::TEST_SUCCESS) | |
196 return; | |
197 | |
198 size_t run_pos = full_output.find(std::string("[ RUN ] ") + | |
199 result.GetFullName()); | |
200 if (run_pos == std::string::npos) | |
201 return; | |
202 | |
203 size_t end_pos = full_output.find(std::string("[ FAILED ] ") + | |
204 result.GetFullName(), | |
205 run_pos); | |
206 if (end_pos != std::string::npos) { | |
207 size_t newline_pos = full_output.find("\n", end_pos); | |
208 if (newline_pos != std::string::npos) | |
209 end_pos = newline_pos + 1; | |
210 } | |
211 | |
212 std::string snippet(full_output.substr(run_pos)); | |
213 if (end_pos != std::string::npos) | |
214 snippet = full_output.substr(run_pos, end_pos - run_pos); | |
215 | |
216 // TODO(phajdan.jr): Indent each line of the snippet so it's more | |
217 // noticeable. | |
218 fprintf(stdout, "%s", snippet.c_str()); | |
219 fflush(stdout); | |
220 } | |
221 | |
222 static bool ProcessTestResults( | 202 static bool ProcessTestResults( |
223 const std::vector<TestLaunchInfo>& tests, | 203 const std::vector<TestLaunchInfo>& tests, |
224 const base::FilePath& output_file, | 204 const base::FilePath& output_file, |
225 const std::string& output, | 205 const std::string& output, |
226 int exit_code, | 206 int exit_code, |
227 bool was_timeout, | 207 bool was_timeout, |
228 std::vector<TestLaunchInfo>* tests_to_relaunch_after_interruption) { | 208 std::vector<TestLaunchInfo>* tests_to_relaunch_after_interruption) { |
229 std::vector<TestResult> test_results; | 209 std::vector<TestResult> test_results; |
230 bool crashed = false; | 210 bool crashed = false; |
231 bool have_test_results = | 211 bool have_test_results = |
(...skipping 16 matching lines...) Expand all Loading... |
248 if (test_result.status == TestResult::TEST_CRASH) { | 228 if (test_result.status == TestResult::TEST_CRASH) { |
249 had_interrupted_test = true; | 229 had_interrupted_test = true; |
250 | 230 |
251 if (was_timeout) { | 231 if (was_timeout) { |
252 // Fix up the test status: we forcibly kill the child process | 232 // Fix up the test status: we forcibly kill the child process |
253 // after the timeout, so from XML results it looks just like | 233 // after the timeout, so from XML results it looks just like |
254 // a crash. | 234 // a crash. |
255 test_result.status = TestResult::TEST_TIMEOUT; | 235 test_result.status = TestResult::TEST_TIMEOUT; |
256 } | 236 } |
257 } | 237 } |
258 MaybePrintTestOutputSnippet(test_result, output); | 238 PrintTestOutputSnippetOnFailure(test_result, output); |
259 tests[i].callback.Run(test_result); | 239 tests[i].callback.Run(test_result); |
260 called_any_callback = true; | 240 called_any_callback = true; |
261 } else if (had_interrupted_test) { | 241 } else if (had_interrupted_test) { |
262 tests_to_relaunch_after_interruption->push_back(tests[i]); | 242 tests_to_relaunch_after_interruption->push_back(tests[i]); |
263 } else { | 243 } else { |
264 // TODO(phajdan.jr): Explicitly pass the info that the test didn't | 244 // TODO(phajdan.jr): Explicitly pass the info that the test didn't |
265 // run for a mysterious reason. | 245 // run for a mysterious reason. |
266 LOG(ERROR) << "no test result for " << tests[i].GetFullName(); | 246 LOG(ERROR) << "no test result for " << tests[i].GetFullName(); |
267 TestResult test_result; | 247 TestResult test_result; |
268 test_result.test_case_name = tests[i].test_case_name; | 248 test_result.test_case_name = tests[i].test_case_name; |
269 test_result.test_name = tests[i].test_name; | 249 test_result.test_name = tests[i].test_name; |
270 test_result.status = TestResult::TEST_UNKNOWN; | 250 test_result.status = TestResult::TEST_UNKNOWN; |
271 MaybePrintTestOutputSnippet(test_result, output); | 251 PrintTestOutputSnippetOnFailure(test_result, output); |
272 tests[i].callback.Run(test_result); | 252 tests[i].callback.Run(test_result); |
273 called_any_callback = true; | 253 called_any_callback = true; |
274 } | 254 } |
275 } | 255 } |
276 | 256 |
277 // TODO(phajdan.jr): Handle the case where processing XML output | 257 // TODO(phajdan.jr): Handle the case where processing XML output |
278 // indicates a crash but none of the test results is marked as crashing. | 258 // indicates a crash but none of the test results is marked as crashing. |
279 | 259 |
280 // TODO(phajdan.jr): Handle the case where the exit code is non-zero | 260 // TODO(phajdan.jr): Handle the case where the exit code is non-zero |
281 // but results file indicates that all tests passed (e.g. crash during | 261 // but results file indicates that all tests passed (e.g. crash during |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 | 354 |
375 fprintf(stdout, | 355 fprintf(stdout, |
376 "Tests took %" PRId64 " seconds.\n", | 356 "Tests took %" PRId64 " seconds.\n", |
377 (base::TimeTicks::Now() - start_time).InSeconds()); | 357 (base::TimeTicks::Now() - start_time).InSeconds()); |
378 fflush(stdout); | 358 fflush(stdout); |
379 | 359 |
380 return exit_code; | 360 return exit_code; |
381 } | 361 } |
382 | 362 |
383 } // namespace base | 363 } // namespace base |
OLD | NEW |