blob: e2e2f330735f0d443a3a538858857548a6d4474a [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
416void Isolate::PrintResults(size_t total, const char* color, const char* prefix, const char* title,
417 std::string* footer, bool (*match_func)(const Test&),
418 void (*print_func)(const Options&, const Test&)) {
419 ColoredPrintf(color, prefix);
420 printf(" %s, listed below:\n", PluralizeString(total, " test").c_str());
421 for (const auto& entry : finished_) {
Christopher Ferrisee59d492018-09-17 15:52:20 -0700422 const Test* test = entry.second.get();
Christopher Ferris1a993562018-08-21 12:43:50 -0700423 if (match_func(*test)) {
424 ColoredPrintf(color, prefix);
425 printf(" %s", test->name().c_str());
426 if (print_func) {
427 print_func(options_, *test);
428 }
429 printf("\n");
430 }
431 }
432 if (total < 10) {
433 *footer += ' ';
434 }
435 *footer += PluralizeString(total, (std::string(" ") + title + " TEST").c_str(), true) + '\n';
436}
437
438void Isolate::PrintFooter(uint64_t elapsed_time_ns) {
439 ColoredPrintf(COLOR_GREEN, "[==========]");
440 printf(" %s from %s ran. (%" PRId64 " ms total)\n",
441 PluralizeString(total_tests_, " test").c_str(),
442 PluralizeString(total_cases_, " test case").c_str(), elapsed_time_ns / kNsPerMs);
443
444 ColoredPrintf(COLOR_GREEN, "[ PASS ]");
445 printf(" %s.", PluralizeString(total_pass_tests_ + total_xfail_tests_, " test").c_str());
446 if (total_xfail_tests_ != 0) {
447 printf(" (%s)", PluralizeString(total_xfail_tests_, " expected failure").c_str());
448 }
449 printf("\n");
450
451 std::string footer;
452 // Tests that ran slow.
453 if (total_slow_tests_ != 0) {
454 PrintResults(total_slow_tests_, COLOR_YELLOW, "[ SLOW ]", "SLOW", &footer,
455 [](const Test& test) { return test.slow(); },
456 [](const Options& options, const Test& test) {
457 printf(" (%" PRIu64 " ms, exceeded %" PRIu64 " ms)", test.RunTimeNs() / kNsPerMs,
458 options.slow_threshold_ms());
459 });
460 }
461
462 // Tests that passed but should have failed.
463 if (total_xpass_tests_ != 0) {
464 PrintResults(total_xpass_tests_, COLOR_RED, "[ XPASS ]", "SHOULD HAVE FAILED", &footer,
465 [](const Test& test) { return test.result() == TEST_XPASS; }, nullptr);
466 }
467
468 // Tests that timed out.
469 if (total_timeout_tests_ != 0) {
470 PrintResults(total_timeout_tests_, COLOR_RED, "[ TIMEOUT ]", "TIMEOUT", &footer,
471 [](const Test& test) { return test.result() == TEST_TIMEOUT; },
472 [](const Options&, const Test& test) {
473 printf(" (stopped at %" PRIu64 " ms)", test.RunTimeNs() / kNsPerMs);
474 });
475 }
476
477 // Tests that failed.
478 if (total_fail_tests_ != 0) {
479 PrintResults(total_fail_tests_, COLOR_RED, "[ FAIL ]", "FAILED", &footer,
480 [](const Test& test) { return test.result() == TEST_FAIL; }, nullptr);
481 }
482
483 if (!footer.empty()) {
484 printf("\n%s", footer.c_str());
485 }
486
487 if (total_disable_tests_ != 0) {
488 if (footer.empty()) {
489 printf("\n");
490 }
491 ColoredPrintf(COLOR_YELLOW, " YOU HAVE %s\n\n",
492 PluralizeString(total_disable_tests_, " DISABLED TEST", true).c_str());
493 }
494
495 fflush(stdout);
496}
497
498std::string XmlEscape(const std::string& xml) {
499 std::string escaped;
500 escaped.reserve(xml.size());
501
502 for (auto c : xml) {
503 switch (c) {
504 case '<':
505 escaped.append("&lt;");
506 break;
507 case '>':
508 escaped.append("&gt;");
509 break;
510 case '&':
511 escaped.append("&amp;");
512 break;
513 case '\'':
514 escaped.append("&apos;");
515 break;
516 case '"':
517 escaped.append("&quot;");
518 break;
519 default:
520 escaped.append(1, c);
521 break;
522 }
523 }
524
525 return escaped;
526}
527
528class TestResultPrinter : public ::testing::EmptyTestEventListener {
529 public:
530 TestResultPrinter() : pinfo_(nullptr) {}
531 virtual void OnTestStart(const ::testing::TestInfo& test_info) {
532 pinfo_ = &test_info; // Record test_info for use in OnTestPartResult.
533 }
534 virtual void OnTestPartResult(const ::testing::TestPartResult& result);
535
536 private:
537 const ::testing::TestInfo* pinfo_;
538};
539
540// Called after an assertion failure.
541void TestResultPrinter::OnTestPartResult(const ::testing::TestPartResult& result) {
542 // If the test part succeeded, we don't need to do anything.
543 if (result.type() == ::testing::TestPartResult::kSuccess) {
544 return;
545 }
546
547 // Print failure message from the assertion (e.g. expected this and got that).
548 printf("%s:(%d) Failure in test %s.%s\n%s\n", result.file_name(), result.line_number(),
549 pinfo_->test_case_name(), pinfo_->name(), result.message());
550 fflush(stdout);
551}
552
553// Output xml file when --gtest_output is used, write this function as we can't reuse
554// gtest.cc:XmlUnitTestResultPrinter. The reason is XmlUnitTestResultPrinter is totally
555// defined in gtest.cc and not expose to outside. What's more, as we don't run gtest in
556// the parent process, we don't have gtest classes which are needed by XmlUnitTestResultPrinter.
557void Isolate::WriteXmlResults(uint64_t elapsed_time_ns, time_t start_time) {
558 FILE* fp = fopen(options_.xml_file().c_str(), "w");
559 if (fp == nullptr) {
560 printf("Cannot open xml file '%s': %s\n", options_.xml_file().c_str(), strerror(errno));
561 exit(1);
562 }
563
564 const tm* time_struct = localtime(&start_time);
565 if (time_struct == nullptr) {
566 PLOG(FATAL) << "Unexpected failure from localtime";
567 }
568 char timestamp[40];
569 snprintf(timestamp, sizeof(timestamp), "%4d-%02d-%02dT%02d:%02d:%02d",
570 time_struct->tm_year + 1900, time_struct->tm_mon + 1, time_struct->tm_mday,
571 time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec);
572
573 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp);
574 fprintf(fp, "<testsuites tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
575 tests_.size(), total_fail_tests_ + total_timeout_tests_ + total_xpass_tests_);
576 fprintf(fp, " timestamp=\"%s\" time=\"%.3lf\" name=\"AllTests\">\n", timestamp,
577 double(elapsed_time_ns) / kNsPerMs);
578
579 // Construct the cases information.
580 struct CaseInfo {
581 std::string case_name;
582 size_t fails = 0;
583 double elapsed_ms = 0;
584 std::vector<const Test*> tests;
585 };
586 std::string last_case_name;
587 std::vector<CaseInfo> cases;
588 CaseInfo* info = nullptr;
589 for (const auto& entry : finished_) {
Christopher Ferrisee59d492018-09-17 15:52:20 -0700590 const Test* test = entry.second.get();
Christopher Ferris1a993562018-08-21 12:43:50 -0700591 const std::string& case_name = test->case_name();
592 if (test->result() == TEST_XFAIL) {
593 // Skip XFAIL tests.
594 continue;
595 }
596 if (last_case_name != case_name) {
597 CaseInfo case_info{.case_name = case_name.substr(0, case_name.size() - 1)};
598 last_case_name = case_name;
599 cases.push_back(case_info);
600 info = &cases.back();
601 }
602 info->tests.push_back(test);
603 info->elapsed_ms += double(test->RunTimeNs()) / kNsPerMs;
604 if (test->result() != TEST_PASS) {
605 info->fails++;
606 }
607 }
608
609 for (auto& case_entry : cases) {
610 fprintf(fp,
611 " <testsuite name=\"%s\" tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
612 case_entry.case_name.c_str(), case_entry.tests.size(), case_entry.fails);
613 fprintf(fp, " time=\"%.3lf\">\n", case_entry.elapsed_ms);
614
615 for (auto test : case_entry.tests) {
616 fprintf(fp, " <testcase name=\"%s\" status=\"run\" time=\"%.3lf\" classname=\"%s\"",
617 test->test_name().c_str(), double(test->RunTimeNs()) / kNsPerMs,
618 case_entry.case_name.c_str());
619 if (test->result() == TEST_PASS) {
620 fputs(" />\n", fp);
621 } else {
622 fputs(">\n", fp);
623 const std::string escaped_output = XmlEscape(test->output());
624 fprintf(fp, " <failure message=\"%s\" type=\"\">\n", escaped_output.c_str());
625 fputs(" </failure>\n", fp);
626 fputs(" </testcase>\n", fp);
627 }
628 }
629 fputs(" </testsuite>\n", fp);
630 }
631 fputs("</testsuites>\n", fp);
632 fclose(fp);
633}
634
635int Isolate::Run() {
636 slow_threshold_ns_ = options_.slow_threshold_ms() * kNsPerMs;
637 deadline_threshold_ns_ = options_.deadline_threshold_ms() * kNsPerMs;
638
639 EnumerateTests();
640
641 // Stop default result printer to avoid environment setup/teardown information for each test.
642 ::testing::UnitTest::GetInstance()->listeners().Release(
643 ::testing::UnitTest::GetInstance()->listeners().default_result_printer());
644 ::testing::UnitTest::GetInstance()->listeners().Append(new TestResultPrinter);
645 RegisterSignalHandler();
646
647 std::string job_info("Running " + PluralizeString(total_tests_, " test") + " from " +
648 PluralizeString(total_cases_, " test case") + " (" +
649 PluralizeString(options_.job_count(), " job") + ").");
650
651 int exit_code = 0;
652 for (int i = 0; options_.num_iterations() < 0 || i < options_.num_iterations(); i++) {
653 if (i > 0) {
654 printf("\nRepeating all tests (iteration %d) . . .\n\n", i + 1);
655 }
656 ColoredPrintf(COLOR_GREEN, "[==========]");
657 printf(" %s\n", job_info.c_str());
658 fflush(stdout);
659
660 time_t start_time = time(nullptr);
661 uint64_t time_ns = NanoTime();
662 RunAllTests();
663 time_ns = NanoTime() - time_ns;
664
665 PrintFooter(time_ns);
666
667 if (!options_.xml_file().empty()) {
668 WriteXmlResults(time_ns, start_time);
669 }
670
671 if (total_pass_tests_ + total_xfail_tests_ != tests_.size()) {
672 exit_code = 1;
673 }
674 }
675
676 return exit_code;
677}
678
679} // namespace gtest_extras
680} // namespace android