blob: 58283fdfb9f3797be0d37c18ee072707beaa85bf [file] [log] [blame]
Christopher Ferris1a993562018-08-21 12:43:50 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <errno.h>
18#include <fcntl.h>
19#include <inttypes.h>
20#include <poll.h>
21#include <signal.h>
22#include <stdio.h>
23#include <string.h>
24#include <unistd.h>
25
26#include <atomic>
27#include <string>
28#include <tuple>
29#include <vector>
30
31#include <android-base/logging.h>
32#include <android-base/strings.h>
33#include <android-base/unique_fd.h>
34#include <gtest/gtest.h>
35
36#include "Color.h"
37#include "Isolate.h"
38#include "NanoTime.h"
39#include "Test.h"
40
41namespace android {
42namespace gtest_extras {
43
44static std::atomic_int g_signal;
45
46static void SignalHandler(int sig) {
47 g_signal = sig;
48}
49
50static void RegisterSignalHandler() {
Christopher Ferris23a3db02018-09-07 07:39:18 -070051 auto ret = signal(SIGINT, SignalHandler);
Christopher Ferris1a993562018-08-21 12:43:50 -070052 if (ret == SIG_ERR) {
53 PLOG(FATAL) << "Setting up SIGINT handler failed";
54 }
55 ret = signal(SIGQUIT, SignalHandler);
56 if (ret == SIG_ERR) {
57 PLOG(FATAL) << "Setting up SIGQUIT handler failed";
58 }
59}
60
61static void UnregisterSignalHandler() {
Christopher Ferris23a3db02018-09-07 07:39:18 -070062 auto ret = signal(SIGINT, SIG_DFL);
Christopher Ferris1a993562018-08-21 12:43:50 -070063 if (ret == SIG_ERR) {
64 PLOG(FATAL) << "Disabling SIGINT handler failed";
65 }
66 ret = signal(SIGQUIT, SIG_DFL);
67 if (ret == SIG_ERR) {
68 PLOG(FATAL) << "Disabling SIGQUIT handler failed";
69 }
70}
71
72static std::string PluralizeString(size_t value, const char* name, bool uppercase = false) {
73 std::string string(std::to_string(value) + name);
74 if (value != 1) {
75 if (uppercase) {
76 string += 'S';
77 } else {
78 string += 's';
79 }
80 }
81 return string;
82}
83
84void Isolate::EnumerateTests() {
85 // Only apply --gtest_filter if present. This is the only option that changes
86 // what tests are listed.
87 std::string command(child_args_[0]);
88 if (!options_.filter().empty()) {
89 command += " --gtest_filter=" + options_.filter();
90 }
91 command += " --gtest_list_tests";
Christopher Ferris23a3db02018-09-07 07:39:18 -070092#if defined(__APPLE__)
93 FILE* fp = popen(command.c_str(), "r");
94#else
Christopher Ferris1a993562018-08-21 12:43:50 -070095 FILE* fp = popen(command.c_str(), "re");
Christopher Ferris23a3db02018-09-07 07:39:18 -070096#endif
Christopher Ferris1a993562018-08-21 12:43:50 -070097 if (fp == nullptr) {
98 PLOG(FATAL) << "Unexpected failure from popen";
99 }
100
101 bool skip_until_next_case = false;
102 std::string case_name;
103 char* buffer = nullptr;
104 size_t buffer_len = 0;
105 bool new_case = false;
106 while (getline(&buffer, &buffer_len, fp) > 0) {
107 if (buffer[0] != ' ') {
108 // This is the case name.
109 case_name = buffer;
110 auto space_index = case_name.find(' ');
111 if (space_index != std::string::npos) {
112 case_name.erase(space_index);
113 }
114 if (case_name.back() == '\n') {
115 case_name.resize(case_name.size() - 1);
116 }
117
118 if (!options_.allow_disabled_tests() && android::base::StartsWith(case_name, "DISABLED_")) {
119 // This whole set of tests have been disabled, skip them all.
120 skip_until_next_case = true;
121 } else {
122 new_case = true;
123 skip_until_next_case = false;
124 }
125 } else if (buffer[0] == ' ' && buffer[1] == ' ') {
126 if (!skip_until_next_case) {
127 std::string test_name = &buffer[2];
128 auto space_index = test_name.find(' ');
129 if (space_index != std::string::npos) {
130 test_name.erase(space_index);
131 }
132 if (test_name.back() == '\n') {
133 test_name.resize(test_name.size() - 1);
134 }
135 if (options_.allow_disabled_tests() || !android::base::StartsWith(test_name, "DISABLED_")) {
136 tests_.push_back(std::make_tuple(case_name, test_name));
137 total_tests_++;
138 if (new_case) {
139 // Only increment the number of cases when we find at least one test
140 // for the cases.
141 total_cases_++;
142 new_case = false;
143 }
144 } else {
145 total_disable_tests_++;
146 }
147 } else {
148 total_disable_tests_++;
149 }
150 } else {
151 printf("Unexpected output from test listing.\nCommand:\n%s\nLine:\n%s\n", command.c_str(),
152 buffer);
153 exit(1);
154 }
155 }
156 free(buffer);
157 if (pclose(fp) == -1) {
158 PLOG(FATAL) << "Unexpected failure from pclose";
159 }
160}
161
162int Isolate::ChildProcessFn(const std::tuple<std::string, std::string>& test) {
163 // Make sure the filter is only coming from our command-line option.
164 unsetenv("GTEST_FILTER");
165
166 // Add the filter argument.
167 std::vector<const char*> args(child_args_);
168 std::string filter("--gtest_filter=" + GetTestName(test));
169 args.push_back(filter.c_str());
170
171 int argc = args.size();
172 // Add the null terminator.
173 args.push_back(nullptr);
174 ::testing::InitGoogleTest(&argc, const_cast<char**>(args.data()));
175 return RUN_ALL_TESTS();
176}
177
178void Isolate::LaunchTests() {
179 while (!running_indices_.empty() && cur_test_index_ < tests_.size()) {
180 android::base::unique_fd read_fd, write_fd;
181 if (!Pipe(&read_fd, &write_fd)) {
182 PLOG(FATAL) << "Unexpected failure from pipe";
183 }
184 if (fcntl(read_fd.get(), F_SETFL, O_NONBLOCK) == -1) {
185 PLOG(FATAL) << "Unexpected failure from fcntl";
186 }
187
188 pid_t pid = fork();
189 if (pid == -1) {
190 PLOG(FATAL) << "Unexpected failure from fork";
191 }
192 if (pid == 0) {
193 read_fd.reset();
194 close(STDOUT_FILENO);
195 close(STDERR_FILENO);
196 if (dup2(write_fd, STDOUT_FILENO) == -1) {
197 exit(1);
198 }
199 if (dup2(write_fd, STDERR_FILENO) == -1) {
200 exit(1);
201 }
202 UnregisterSignalHandler();
203 exit(ChildProcessFn(tests_[cur_test_index_]));
204 }
205
Christopher Ferrisee59d492018-09-17 15:52:20 -0700206 size_t run_index = running_indices_.back();
207 running_indices_.pop_back();
Christopher Ferris1a993562018-08-21 12:43:50 -0700208 Test* test = new Test(tests_[cur_test_index_], cur_test_index_, run_index, read_fd.release());
Christopher Ferrisee59d492018-09-17 15:52:20 -0700209 running_by_pid_.emplace(pid, test);
Christopher Ferris1a993562018-08-21 12:43:50 -0700210 running_[run_index] = test;
Christopher Ferris1a993562018-08-21 12:43:50 -0700211 running_by_test_index_[cur_test_index_] = test;
212
213 pollfd* pollfd = &running_pollfds_[run_index];
214 pollfd->fd = test->fd();
215 pollfd->events = POLLIN;
216 cur_test_index_++;
217 }
218}
219
220void Isolate::ReadTestsOutput() {
221 int ready = poll(running_pollfds_.data(), running_pollfds_.size(), 0);
222 if (ready <= 0) {
223 return;
224 }
225
226 for (size_t i = 0; i < running_pollfds_.size(); i++) {
227 pollfd* pfd = &running_pollfds_[i];
228 if (pfd->revents & POLLIN) {
229 Test* test = running_[i];
230 if (!test->Read()) {
231 test->CloseFd();
232 pfd->fd = 0;
233 pfd->events = 0;
234 }
235 }
236 pfd->revents = 0;
237 }
238}
239
240size_t Isolate::CheckTestsFinished() {
241 size_t finished_tests = 0;
242 int status;
243 pid_t pid;
244 while ((pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) {
245 auto entry = running_by_pid_.find(pid);
246 if (entry == running_by_pid_.end()) {
247 LOG(FATAL) << "Pid " << pid << " was not spawned by the isolation framework.";
248 }
249
Christopher Ferrisee59d492018-09-17 15:52:20 -0700250 std::unique_ptr<Test>& test_ptr = entry->second;
251 Test* test = test_ptr.get();
Christopher Ferris1a993562018-08-21 12:43:50 -0700252 test->Stop();
253
254 // Read any leftover data.
255 test->ReadUntilClosed();
256 if (test->result() == TEST_NONE) {
257 if (WIFSIGNALED(status)) {
258 std::string output(test->name() + " terminated by signal: " + strsignal(WTERMSIG(status)) +
259 ".\n");
260 test->AppendOutput(output);
261 test->set_result(TEST_FAIL);
262 } else {
263 int exit_code = WEXITSTATUS(status);
264 if (exit_code != 0) {
265 std::string output(test->name() + " exited with exitcode " + std::to_string(exit_code) +
266 ".\n");
267 test->AppendOutput(output);
268 test->set_result(TEST_FAIL);
269 } else {
270 test->set_result(TEST_PASS);
271 }
272 }
273 } else if (test->result() == TEST_TIMEOUT) {
274 uint64_t time_ms = options_.deadline_threshold_ms();
275 std::string timeout_str(test->name() + " killed because of timeout at " +
276 std::to_string(time_ms) + " ms.\n");
277 test->AppendOutput(timeout_str);
278 }
279
280 if (test->ExpectFail()) {
281 if (test->result() == TEST_FAIL) {
282 // The test is expected to fail, it failed.
283 test->set_result(TEST_XFAIL);
284 } else if (test->result() == TEST_PASS) {
285 // The test is expected to fail, it passed.
286 test->set_result(TEST_XPASS);
287 }
288 }
289
290 test->Print(options_.gtest_format());
291
292 switch (test->result()) {
293 case TEST_PASS:
294 total_pass_tests_++;
295 if (test->slow()) {
296 total_slow_tests_++;
297 }
298 break;
299 case TEST_XPASS:
300 total_xpass_tests_++;
301 break;
302 case TEST_FAIL:
303 total_fail_tests_++;
304 break;
305 case TEST_TIMEOUT:
306 total_timeout_tests_++;
307 break;
308 case TEST_XFAIL:
309 total_xfail_tests_++;
310 break;
311 case TEST_NONE:
312 LOG(FATAL) << "Test result is TEST_NONE, this should not be possible.";
313 }
314 finished_tests++;
315 size_t test_index = test->test_index();
Christopher Ferrisee59d492018-09-17 15:52:20 -0700316 finished_.emplace(test_index, test_ptr.release());
317 running_indices_.push_back(test->run_index());
Christopher Ferris1a993562018-08-21 12:43:50 -0700318
319 // Remove it from all of the running indices.
320 size_t run_index = test->run_index();
321 if (running_by_pid_.erase(pid) != 1) {
322 printf("Internal error: Erasing pid %d from running_by_pid_ incorrect\n", pid);
323 }
324 if (running_by_test_index_.erase(test_index) == 0) {
325 printf("Internal error: Erasing test_index %zu from running_by_pid_ incorrect\n", test_index);
326 }
327 running_[run_index] = nullptr;
328 running_pollfds_[run_index] = {};
329 }
330
331 // The only valid error case is if ECHILD is returned because there are
332 // no more processes left running.
333 if (pid == -1 && errno != ECHILD) {
334 PLOG(FATAL) << "Unexpected failure from waitpid";
335 }
336 return finished_tests;
337}
338
339void Isolate::CheckTestsTimeout() {
340 for (auto& entry : running_by_pid_) {
Christopher Ferrisee59d492018-09-17 15:52:20 -0700341 Test* test = entry.second.get();
Christopher Ferris1a993562018-08-21 12:43:50 -0700342 if (test->result() == TEST_TIMEOUT) {
343 continue;
344 }
345
346 if (NanoTime() > test->start_ns() + deadline_threshold_ns_) {
347 test->set_result(TEST_TIMEOUT);
348 // Do not mark this as slow and timed out.
349 test->set_slow(false);
350 // Test gets cleaned up in CheckTestsFinished.
351 kill(entry.first, SIGKILL);
352 } else if (!test->slow() && NanoTime() > test->start_ns() + slow_threshold_ns_) {
353 // Mark the test as running slow.
354 test->set_slow(true);
355 }
356 }
357}
358
359void Isolate::HandleSignals() {
360 int signal = g_signal.exchange(0);
361 if (signal == SIGINT) {
362 printf("Terminating due to signal...\n");
363 for (auto& entry : running_by_pid_) {
364 kill(entry.first, SIGKILL);
365 }
366 exit(1);
367 } else if (signal == SIGQUIT) {
368 printf("List of current running tests:\n");
369 for (const auto& entry : running_by_test_index_) {
370 const Test* test = entry.second;
371 uint64_t run_time_ms = (NanoTime() - test->start_ns()) / kNsPerMs;
372 printf(" %s (elapsed time %" PRId64 " ms)\n", test->name().c_str(), run_time_ms);
373 }
374 }
375}
376
377void Isolate::RunAllTests() {
378 total_pass_tests_ = 0;
379 total_xpass_tests_ = 0;
380 total_fail_tests_ = 0;
381 total_xfail_tests_ = 0;
382 total_timeout_tests_ = 0;
383 total_slow_tests_ = 0;
384
385 running_by_test_index_.clear();
386
387 size_t job_count = options_.job_count();
388 running_.clear();
389 running_.resize(job_count);
390 running_pollfds_.resize(job_count);
391 memset(running_pollfds_.data(), 0, running_pollfds_.size() * sizeof(pollfd));
Christopher Ferrisee59d492018-09-17 15:52:20 -0700392 running_indices_.clear();
Christopher Ferris1a993562018-08-21 12:43:50 -0700393 for (size_t i = 0; i < job_count; i++) {
Christopher Ferrisee59d492018-09-17 15:52:20 -0700394 running_indices_.push_back(i);
Christopher Ferris1a993562018-08-21 12:43:50 -0700395 }
396
397 finished_.clear();
398
399 size_t finished = 0;
400 cur_test_index_ = 0;
401 while (finished < tests_.size()) {
402 LaunchTests();
403
404 ReadTestsOutput();
405
406 finished += CheckTestsFinished();
407
408 CheckTestsTimeout();
409
410 HandleSignals();
411
412 usleep(MIN_USECONDS_WAIT);
413 }
414}
415
Christopher Ferrisef982172018-09-27 15:19:07 -0700416void Isolate::PrintResults(size_t total, const ResultsType& results, std::string* footer) {
417 ColoredPrintf(results.color, results.prefix);
418 printf(" %s %s, listed below:\n", PluralizeString(total, " test").c_str(), results.list_desc);
Christopher Ferris1a993562018-08-21 12:43:50 -0700419 for (const auto& entry : finished_) {
Christopher Ferrisee59d492018-09-17 15:52:20 -0700420 const Test* test = entry.second.get();
Christopher Ferrisef982172018-09-27 15:19:07 -0700421 if (results.match_func(*test)) {
422 ColoredPrintf(results.color, results.prefix);
Christopher Ferris1a993562018-08-21 12:43:50 -0700423 printf(" %s", test->name().c_str());
Christopher Ferrisef982172018-09-27 15:19:07 -0700424 if (results.print_func != nullptr) {
425 results.print_func(options_, *test);
Christopher Ferris1a993562018-08-21 12:43:50 -0700426 }
427 printf("\n");
428 }
429 }
430 if (total < 10) {
431 *footer += ' ';
432 }
Christopher Ferrisef982172018-09-27 15:19:07 -0700433 *footer +=
434 PluralizeString(total, (std::string(" ") + results.title + " TEST").c_str(), true) + '\n';
Christopher Ferris1a993562018-08-21 12:43:50 -0700435}
436
Christopher Ferrisef982172018-09-27 15:19:07 -0700437Isolate::ResultsType Isolate::SlowResults = {
438 .color = COLOR_YELLOW,
439 .prefix = "[ SLOW ]",
440 .list_desc = "slow",
441 .title = "SLOW",
442 .match_func = [](const Test& test) { return test.slow(); },
443 .print_func =
444 [](const Options& options, const Test& test) {
445 printf(" (%" PRIu64 " ms, exceeded %" PRIu64 " ms)", test.RunTimeNs() / kNsPerMs,
446 options.slow_threshold_ms());
447 },
448};
449
450Isolate::ResultsType Isolate::XpassFailResults = {
451 .color = COLOR_RED,
452 .prefix = "[ FAIL ]",
453 .list_desc = "should have failed",
454 .title = "SHOULD HAVE FAILED",
455 .match_func = [](const Test& test) { return test.result() == TEST_XPASS; },
456 .print_func = nullptr,
457};
458
459Isolate::ResultsType Isolate::FailResults = {
460 .color = COLOR_RED,
461 .prefix = "[ FAIL ]",
462 .list_desc = "failed",
463 .title = "FAILED",
464 .match_func = [](const Test& test) { return test.result() == TEST_FAIL; },
465 .print_func = nullptr,
466};
467
468Isolate::ResultsType Isolate::TimeoutResults = {
469 .color = COLOR_RED,
470 .prefix = "[ TIMEOUT ]",
471 .list_desc = "timed out",
472 .title = "TIMEOUT",
473 .match_func = [](const Test& test) { return test.result() == TEST_TIMEOUT; },
474 .print_func =
475 [](const Options&, const Test& test) {
476 printf(" (stopped at %" PRIu64 " ms)", test.RunTimeNs() / kNsPerMs);
477 },
478};
479
Christopher Ferris1a993562018-08-21 12:43:50 -0700480void Isolate::PrintFooter(uint64_t elapsed_time_ns) {
481 ColoredPrintf(COLOR_GREEN, "[==========]");
482 printf(" %s from %s ran. (%" PRId64 " ms total)\n",
483 PluralizeString(total_tests_, " test").c_str(),
484 PluralizeString(total_cases_, " test case").c_str(), elapsed_time_ns / kNsPerMs);
485
486 ColoredPrintf(COLOR_GREEN, "[ PASS ]");
487 printf(" %s.", PluralizeString(total_pass_tests_ + total_xfail_tests_, " test").c_str());
488 if (total_xfail_tests_ != 0) {
489 printf(" (%s)", PluralizeString(total_xfail_tests_, " expected failure").c_str());
490 }
491 printf("\n");
492
493 std::string footer;
494 // Tests that ran slow.
495 if (total_slow_tests_ != 0) {
Christopher Ferrisef982172018-09-27 15:19:07 -0700496 PrintResults(total_slow_tests_, SlowResults, &footer);
Christopher Ferris1a993562018-08-21 12:43:50 -0700497 }
498
499 // Tests that passed but should have failed.
500 if (total_xpass_tests_ != 0) {
Christopher Ferrisef982172018-09-27 15:19:07 -0700501 PrintResults(total_xpass_tests_, XpassFailResults, &footer);
Christopher Ferris1a993562018-08-21 12:43:50 -0700502 }
503
504 // Tests that timed out.
505 if (total_timeout_tests_ != 0) {
Christopher Ferrisef982172018-09-27 15:19:07 -0700506 PrintResults(total_timeout_tests_, TimeoutResults, &footer);
Christopher Ferris1a993562018-08-21 12:43:50 -0700507 }
508
509 // Tests that failed.
510 if (total_fail_tests_ != 0) {
Christopher Ferrisef982172018-09-27 15:19:07 -0700511 PrintResults(total_fail_tests_, FailResults, &footer);
Christopher Ferris1a993562018-08-21 12:43:50 -0700512 }
513
514 if (!footer.empty()) {
515 printf("\n%s", footer.c_str());
516 }
517
518 if (total_disable_tests_ != 0) {
519 if (footer.empty()) {
520 printf("\n");
521 }
522 ColoredPrintf(COLOR_YELLOW, " YOU HAVE %s\n\n",
523 PluralizeString(total_disable_tests_, " DISABLED TEST", true).c_str());
524 }
525
526 fflush(stdout);
527}
528
529std::string XmlEscape(const std::string& xml) {
530 std::string escaped;
531 escaped.reserve(xml.size());
532
533 for (auto c : xml) {
534 switch (c) {
535 case '<':
536 escaped.append("&lt;");
537 break;
538 case '>':
539 escaped.append("&gt;");
540 break;
541 case '&':
542 escaped.append("&amp;");
543 break;
544 case '\'':
545 escaped.append("&apos;");
546 break;
547 case '"':
548 escaped.append("&quot;");
549 break;
550 default:
551 escaped.append(1, c);
552 break;
553 }
554 }
555
556 return escaped;
557}
558
559class TestResultPrinter : public ::testing::EmptyTestEventListener {
560 public:
561 TestResultPrinter() : pinfo_(nullptr) {}
562 virtual void OnTestStart(const ::testing::TestInfo& test_info) {
563 pinfo_ = &test_info; // Record test_info for use in OnTestPartResult.
564 }
565 virtual void OnTestPartResult(const ::testing::TestPartResult& result);
566
567 private:
568 const ::testing::TestInfo* pinfo_;
569};
570
571// Called after an assertion failure.
572void TestResultPrinter::OnTestPartResult(const ::testing::TestPartResult& result) {
573 // If the test part succeeded, we don't need to do anything.
574 if (result.type() == ::testing::TestPartResult::kSuccess) {
575 return;
576 }
577
578 // Print failure message from the assertion (e.g. expected this and got that).
579 printf("%s:(%d) Failure in test %s.%s\n%s\n", result.file_name(), result.line_number(),
580 pinfo_->test_case_name(), pinfo_->name(), result.message());
581 fflush(stdout);
582}
583
584// Output xml file when --gtest_output is used, write this function as we can't reuse
585// gtest.cc:XmlUnitTestResultPrinter. The reason is XmlUnitTestResultPrinter is totally
586// defined in gtest.cc and not expose to outside. What's more, as we don't run gtest in
587// the parent process, we don't have gtest classes which are needed by XmlUnitTestResultPrinter.
588void Isolate::WriteXmlResults(uint64_t elapsed_time_ns, time_t start_time) {
589 FILE* fp = fopen(options_.xml_file().c_str(), "w");
590 if (fp == nullptr) {
591 printf("Cannot open xml file '%s': %s\n", options_.xml_file().c_str(), strerror(errno));
592 exit(1);
593 }
594
595 const tm* time_struct = localtime(&start_time);
596 if (time_struct == nullptr) {
597 PLOG(FATAL) << "Unexpected failure from localtime";
598 }
599 char timestamp[40];
600 snprintf(timestamp, sizeof(timestamp), "%4d-%02d-%02dT%02d:%02d:%02d",
601 time_struct->tm_year + 1900, time_struct->tm_mon + 1, time_struct->tm_mday,
602 time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec);
603
604 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp);
605 fprintf(fp, "<testsuites tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
606 tests_.size(), total_fail_tests_ + total_timeout_tests_ + total_xpass_tests_);
607 fprintf(fp, " timestamp=\"%s\" time=\"%.3lf\" name=\"AllTests\">\n", timestamp,
608 double(elapsed_time_ns) / kNsPerMs);
609
610 // Construct the cases information.
611 struct CaseInfo {
612 std::string case_name;
613 size_t fails = 0;
614 double elapsed_ms = 0;
615 std::vector<const Test*> tests;
616 };
617 std::string last_case_name;
618 std::vector<CaseInfo> cases;
619 CaseInfo* info = nullptr;
620 for (const auto& entry : finished_) {
Christopher Ferrisee59d492018-09-17 15:52:20 -0700621 const Test* test = entry.second.get();
Christopher Ferris1a993562018-08-21 12:43:50 -0700622 const std::string& case_name = test->case_name();
623 if (test->result() == TEST_XFAIL) {
624 // Skip XFAIL tests.
625 continue;
626 }
627 if (last_case_name != case_name) {
628 CaseInfo case_info{.case_name = case_name.substr(0, case_name.size() - 1)};
629 last_case_name = case_name;
630 cases.push_back(case_info);
631 info = &cases.back();
632 }
633 info->tests.push_back(test);
634 info->elapsed_ms += double(test->RunTimeNs()) / kNsPerMs;
635 if (test->result() != TEST_PASS) {
636 info->fails++;
637 }
638 }
639
640 for (auto& case_entry : cases) {
641 fprintf(fp,
642 " <testsuite name=\"%s\" tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
643 case_entry.case_name.c_str(), case_entry.tests.size(), case_entry.fails);
644 fprintf(fp, " time=\"%.3lf\">\n", case_entry.elapsed_ms);
645
646 for (auto test : case_entry.tests) {
647 fprintf(fp, " <testcase name=\"%s\" status=\"run\" time=\"%.3lf\" classname=\"%s\"",
648 test->test_name().c_str(), double(test->RunTimeNs()) / kNsPerMs,
649 case_entry.case_name.c_str());
650 if (test->result() == TEST_PASS) {
651 fputs(" />\n", fp);
652 } else {
653 fputs(">\n", fp);
654 const std::string escaped_output = XmlEscape(test->output());
655 fprintf(fp, " <failure message=\"%s\" type=\"\">\n", escaped_output.c_str());
656 fputs(" </failure>\n", fp);
657 fputs(" </testcase>\n", fp);
658 }
659 }
660 fputs(" </testsuite>\n", fp);
661 }
662 fputs("</testsuites>\n", fp);
663 fclose(fp);
664}
665
666int Isolate::Run() {
667 slow_threshold_ns_ = options_.slow_threshold_ms() * kNsPerMs;
668 deadline_threshold_ns_ = options_.deadline_threshold_ms() * kNsPerMs;
669
670 EnumerateTests();
671
672 // Stop default result printer to avoid environment setup/teardown information for each test.
673 ::testing::UnitTest::GetInstance()->listeners().Release(
674 ::testing::UnitTest::GetInstance()->listeners().default_result_printer());
675 ::testing::UnitTest::GetInstance()->listeners().Append(new TestResultPrinter);
676 RegisterSignalHandler();
677
678 std::string job_info("Running " + PluralizeString(total_tests_, " test") + " from " +
679 PluralizeString(total_cases_, " test case") + " (" +
680 PluralizeString(options_.job_count(), " job") + ").");
681
682 int exit_code = 0;
683 for (int i = 0; options_.num_iterations() < 0 || i < options_.num_iterations(); i++) {
684 if (i > 0) {
685 printf("\nRepeating all tests (iteration %d) . . .\n\n", i + 1);
686 }
687 ColoredPrintf(COLOR_GREEN, "[==========]");
688 printf(" %s\n", job_info.c_str());
689 fflush(stdout);
690
691 time_t start_time = time(nullptr);
692 uint64_t time_ns = NanoTime();
693 RunAllTests();
694 time_ns = NanoTime() - time_ns;
695
696 PrintFooter(time_ns);
697
698 if (!options_.xml_file().empty()) {
699 WriteXmlResults(time_ns, start_time);
700 }
701
702 if (total_pass_tests_ + total_xfail_tests_ != tests_.size()) {
703 exit_code = 1;
704 }
705 }
706
707 return exit_code;
708}
709
710} // namespace gtest_extras
711} // namespace android