1 /* 2 * Copyright (C) 2014 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 <gtest/gtest.h> 18 19 #include <ctype.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <inttypes.h> 23 #include <limits.h> 24 #include <signal.h> 25 #include <stdarg.h> 26 #include <stdio.h> 27 #include <string.h> 28 #include <sys/wait.h> 29 #include <unistd.h> 30 31 #include <chrono> 32 #include <string> 33 #include <tuple> 34 #include <utility> 35 #include <vector> 36 37 #ifndef TEMP_FAILURE_RETRY 38 39 /* Used to retry syscalls that can return EINTR. */ 40 #define TEMP_FAILURE_RETRY(exp) ({ \ 41 __typeof__(exp) _rc; \ 42 do { \ 43 _rc = (exp); \ 44 } while (_rc == -1 && errno == EINTR); \ 45 _rc; }) 46 47 #endif 48 49 static std::string g_executable_path; 50 51 const std::string& get_executable_path() { 52 return g_executable_path; 53 } 54 55 namespace testing { 56 namespace internal { 57 58 // Reuse of testing::internal::ColoredPrintf in gtest. 59 enum GTestColor { 60 COLOR_DEFAULT, 61 COLOR_RED, 62 COLOR_GREEN, 63 COLOR_YELLOW 64 }; 65 66 void ColoredPrintf(GTestColor color, const char* fmt, ...); 67 68 } // namespace internal 69 } // namespace testing 70 71 using testing::internal::GTestColor; 72 using testing::internal::COLOR_DEFAULT; 73 using testing::internal::COLOR_RED; 74 using testing::internal::COLOR_GREEN; 75 using testing::internal::COLOR_YELLOW; 76 using testing::internal::ColoredPrintf; 77 78 constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS = 90000; 79 constexpr int DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS = 2000; 80 81 // The time each test can run before killed for the reason of timeout. 82 // It takes effect only with --isolate option. 83 static int global_test_run_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS; 84 85 // The time each test can run before be warned for too much running time. 86 // It takes effect only with --isolate option. 87 static int global_test_run_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS; 88 89 // Return deadline duration for a test, in ms. 90 static int GetDeadlineInfo(const std::string& /*test_name*/) { 91 return global_test_run_deadline_ms; 92 } 93 94 // Return warnline duration for a test, in ms. 95 static int GetWarnlineInfo(const std::string& /*test_name*/) { 96 return global_test_run_warnline_ms; 97 } 98 99 static void PrintHelpInfo() { 100 printf("Bionic Unit Test Options:\n" 101 " -j [JOB_COUNT] or -j[JOB_COUNT]\n" 102 " Run up to JOB_COUNT tests in parallel.\n" 103 " Use isolation mode, Run each test in a separate process.\n" 104 " If JOB_COUNT is not given, it is set to the count of available processors.\n" 105 " --no-isolate\n" 106 " Don't use isolation mode, run all tests in a single process.\n" 107 " --deadline=[TIME_IN_MS]\n" 108 " Run each test in no longer than [TIME_IN_MS] time.\n" 109 " It takes effect only in isolation mode. Deafult deadline is 90000 ms.\n" 110 " --warnline=[TIME_IN_MS]\n" 111 " Test running longer than [TIME_IN_MS] will be warned.\n" 112 " It takes effect only in isolation mode. Default warnline is 2000 ms.\n" 113 " --gtest-filter=POSITIVE_PATTERNS[-NEGATIVE_PATTERNS]\n" 114 " Used as a synonym for --gtest_filter option in gtest.\n" 115 "Default bionic unit test option is -j.\n" 116 "In isolation mode, you can send SIGQUIT to the parent process to show current\n" 117 "running tests, or send SIGINT to the parent process to stop testing and\n" 118 "clean up current running tests.\n" 119 "\n"); 120 } 121 122 enum TestResult { 123 TEST_SUCCESS = 0, 124 TEST_FAILED, 125 TEST_TIMEOUT 126 }; 127 128 class Test { 129 public: 130 Test() {} // For std::vector<Test>. 131 explicit Test(const char* name) : name_(name) {} 132 133 const std::string& GetName() const { return name_; } 134 135 void SetResult(TestResult result) { result_ = result; } 136 137 TestResult GetResult() const { return result_; } 138 139 void SetTestTime(int64_t elapsed_time_ns) { elapsed_time_ns_ = elapsed_time_ns; } 140 141 int64_t GetTestTime() const { return elapsed_time_ns_; } 142 143 void AppendTestOutput(const std::string& s) { output_ += s; } 144 145 const std::string& GetTestOutput() const { return output_; } 146 147 private: 148 const std::string name_; 149 TestResult result_; 150 int64_t elapsed_time_ns_; 151 std::string output_; 152 }; 153 154 class TestCase { 155 public: 156 TestCase() {} // For std::vector<TestCase>. 157 explicit TestCase(const char* name) : name_(name) {} 158 159 const std::string& GetName() const { return name_; } 160 161 void AppendTest(const char* test_name) { 162 test_list_.push_back(Test(test_name)); 163 } 164 165 size_t TestCount() const { return test_list_.size(); } 166 167 std::string GetTestName(size_t test_id) const { 168 VerifyTestId(test_id); 169 return name_ + "." + test_list_[test_id].GetName(); 170 } 171 172 Test& GetTest(size_t test_id) { 173 VerifyTestId(test_id); 174 return test_list_[test_id]; 175 } 176 177 const Test& GetTest(size_t test_id) const { 178 VerifyTestId(test_id); 179 return test_list_[test_id]; 180 } 181 182 void SetTestResult(size_t test_id, TestResult result) { 183 VerifyTestId(test_id); 184 test_list_[test_id].SetResult(result); 185 } 186 187 TestResult GetTestResult(size_t test_id) const { 188 VerifyTestId(test_id); 189 return test_list_[test_id].GetResult(); 190 } 191 192 void SetTestTime(size_t test_id, int64_t elapsed_time_ns) { 193 VerifyTestId(test_id); 194 test_list_[test_id].SetTestTime(elapsed_time_ns); 195 } 196 197 int64_t GetTestTime(size_t test_id) const { 198 VerifyTestId(test_id); 199 return test_list_[test_id].GetTestTime(); 200 } 201 202 private: 203 void VerifyTestId(size_t test_id) const { 204 if(test_id >= test_list_.size()) { 205 fprintf(stderr, "test_id %zu out of range [0, %zu)\n", test_id, test_list_.size()); 206 exit(1); 207 } 208 } 209 210 private: 211 const std::string name_; 212 std::vector<Test> test_list_; 213 }; 214 215 class TestResultPrinter : public testing::EmptyTestEventListener { 216 public: 217 TestResultPrinter() : pinfo_(NULL) {} 218 virtual void OnTestStart(const testing::TestInfo& test_info) { 219 pinfo_ = &test_info; // Record test_info for use in OnTestPartResult. 220 } 221 virtual void OnTestPartResult(const testing::TestPartResult& result); 222 223 private: 224 const testing::TestInfo* pinfo_; 225 }; 226 227 // Called after an assertion failure. 228 void TestResultPrinter::OnTestPartResult(const testing::TestPartResult& result) { 229 // If the test part succeeded, we don't need to do anything. 230 if (result.type() == testing::TestPartResult::kSuccess) 231 return; 232 233 // Print failure message from the assertion (e.g. expected this and got that). 234 printf("%s:(%d) Failure in test %s.%s\n%s\n", result.file_name(), result.line_number(), 235 pinfo_->test_case_name(), pinfo_->name(), result.message()); 236 fflush(stdout); 237 } 238 239 static int64_t NanoTime() { 240 std::chrono::nanoseconds duration(std::chrono::steady_clock::now().time_since_epoch()); 241 return static_cast<int64_t>(duration.count()); 242 } 243 244 static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcase_list) { 245 std::string command; 246 for (int i = 0; i < argc; ++i) { 247 command += argv[i]; 248 command += " "; 249 } 250 command += "--gtest_list_tests"; 251 FILE* fp = popen(command.c_str(), "r"); 252 if (fp == NULL) { 253 perror("popen"); 254 return false; 255 } 256 257 char buf[200]; 258 while (fgets(buf, sizeof(buf), fp) != NULL) { 259 char* p = buf; 260 261 while (*p != '\0' && isspace(*p)) { 262 ++p; 263 } 264 if (*p == '\0') continue; 265 char* start = p; 266 while (*p != '\0' && !isspace(*p)) { 267 ++p; 268 } 269 char* end = p; 270 while (*p != '\0' && isspace(*p)) { 271 ++p; 272 } 273 if (*p != '\0' && *p != '#') { 274 // This is not we want, gtest must meet with some error when parsing the arguments. 275 fprintf(stderr, "argument error, check with --help\n"); 276 return false; 277 } 278 *end = '\0'; 279 if (*(end - 1) == '.') { 280 *(end - 1) = '\0'; 281 testcase_list.push_back(TestCase(start)); 282 } else { 283 testcase_list.back().AppendTest(start); 284 } 285 } 286 int result = pclose(fp); 287 return (result != -1 && WEXITSTATUS(result) == 0); 288 } 289 290 // Part of the following *Print functions are copied from external/gtest/src/gtest.cc: 291 // PrettyUnitTestResultPrinter. The reason for copy is that PrettyUnitTestResultPrinter 292 // is defined and used in gtest.cc, which is hard to reuse. 293 static void OnTestIterationStartPrint(const std::vector<TestCase>& testcase_list, size_t iteration, 294 int iteration_count) { 295 if (iteration_count != 1) { 296 printf("\nRepeating all tests (iteration %zu) . . .\n\n", iteration); 297 } 298 ColoredPrintf(COLOR_GREEN, "[==========] "); 299 300 size_t testcase_count = testcase_list.size(); 301 size_t test_count = 0; 302 for (const auto& testcase : testcase_list) { 303 test_count += testcase.TestCount(); 304 } 305 306 printf("Running %zu %s from %zu %s.\n", 307 test_count, (test_count == 1) ? "test" : "tests", 308 testcase_count, (testcase_count == 1) ? "test case" : "test cases"); 309 fflush(stdout); 310 } 311 312 // bionic cts test needs gtest output format. 313 #if defined(USING_GTEST_OUTPUT_FORMAT) 314 315 static void OnTestEndPrint(const TestCase& testcase, size_t test_id) { 316 ColoredPrintf(COLOR_GREEN, "[ RUN ] "); 317 printf("%s\n", testcase.GetTestName(test_id).c_str()); 318 319 const std::string& test_output = testcase.GetTest(test_id).GetTestOutput(); 320 printf("%s", test_output.c_str()); 321 322 TestResult result = testcase.GetTestResult(test_id); 323 if (result == TEST_SUCCESS) { 324 ColoredPrintf(COLOR_GREEN, "[ OK ] "); 325 } else { 326 ColoredPrintf(COLOR_RED, "[ FAILED ] "); 327 } 328 printf("%s", testcase.GetTestName(test_id).c_str()); 329 if (testing::GTEST_FLAG(print_time)) { 330 printf(" (%" PRId64 " ms)", testcase.GetTestTime(test_id) / 1000000); 331 } 332 printf("\n"); 333 fflush(stdout); 334 } 335 336 #else // !defined(USING_GTEST_OUTPUT_FORMAT) 337 338 static void OnTestEndPrint(const TestCase& testcase, size_t test_id) { 339 TestResult result = testcase.GetTestResult(test_id); 340 if (result == TEST_SUCCESS) { 341 ColoredPrintf(COLOR_GREEN, "[ OK ] "); 342 } else if (result == TEST_FAILED) { 343 ColoredPrintf(COLOR_RED, "[ FAILED ] "); 344 } else if (result == TEST_TIMEOUT) { 345 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] "); 346 } 347 348 printf("%s", testcase.GetTestName(test_id).c_str()); 349 if (testing::GTEST_FLAG(print_time)) { 350 printf(" (%" PRId64 " ms)", testcase.GetTestTime(test_id) / 1000000); 351 } 352 printf("\n"); 353 354 const std::string& test_output = testcase.GetTest(test_id).GetTestOutput(); 355 printf("%s", test_output.c_str()); 356 fflush(stdout); 357 } 358 359 #endif // !defined(USING_GTEST_OUTPUT_FORMAT) 360 361 static void OnTestIterationEndPrint(const std::vector<TestCase>& testcase_list, size_t /*iteration*/, 362 int64_t elapsed_time_ns) { 363 364 std::vector<std::string> fail_test_name_list; 365 std::vector<std::pair<std::string, int64_t>> timeout_test_list; 366 367 // For tests run exceed warnline but not timeout. 368 std::vector<std::tuple<std::string, int64_t, int>> slow_test_list; 369 size_t testcase_count = testcase_list.size(); 370 size_t test_count = 0; 371 size_t success_test_count = 0; 372 373 for (const auto& testcase : testcase_list) { 374 test_count += testcase.TestCount(); 375 for (size_t i = 0; i < testcase.TestCount(); ++i) { 376 TestResult result = testcase.GetTestResult(i); 377 if (result == TEST_SUCCESS) { 378 ++success_test_count; 379 } else if (result == TEST_FAILED) { 380 fail_test_name_list.push_back(testcase.GetTestName(i)); 381 } else if (result == TEST_TIMEOUT) { 382 timeout_test_list.push_back(std::make_pair(testcase.GetTestName(i), 383 testcase.GetTestTime(i))); 384 } 385 if (result != TEST_TIMEOUT && 386 testcase.GetTestTime(i) / 1000000 >= GetWarnlineInfo(testcase.GetTestName(i))) { 387 slow_test_list.push_back(std::make_tuple(testcase.GetTestName(i), 388 testcase.GetTestTime(i), 389 GetWarnlineInfo(testcase.GetTestName(i)))); 390 } 391 } 392 } 393 394 ColoredPrintf(COLOR_GREEN, "[==========] "); 395 printf("%zu %s from %zu %s ran.", test_count, (test_count == 1) ? "test" : "tests", 396 testcase_count, (testcase_count == 1) ? "test case" : "test cases"); 397 if (testing::GTEST_FLAG(print_time)) { 398 printf(" (%" PRId64 " ms total)", elapsed_time_ns / 1000000); 399 } 400 printf("\n"); 401 ColoredPrintf(COLOR_GREEN, "[ PASS ] "); 402 printf("%zu %s.\n", success_test_count, (success_test_count == 1) ? "test" : "tests"); 403 404 // Print tests failed. 405 size_t fail_test_count = fail_test_name_list.size(); 406 if (fail_test_count > 0) { 407 ColoredPrintf(COLOR_RED, "[ FAIL ] "); 408 printf("%zu %s, listed below:\n", fail_test_count, (fail_test_count == 1) ? "test" : "tests"); 409 for (const auto& name : fail_test_name_list) { 410 ColoredPrintf(COLOR_RED, "[ FAIL ] "); 411 printf("%s\n", name.c_str()); 412 } 413 } 414 415 // Print tests run timeout. 416 size_t timeout_test_count = timeout_test_list.size(); 417 if (timeout_test_count > 0) { 418 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] "); 419 printf("%zu %s, listed below:\n", timeout_test_count, (timeout_test_count == 1) ? "test" : "tests"); 420 for (const auto& timeout_pair : timeout_test_list) { 421 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] "); 422 printf("%s (stopped at %" PRId64 " ms)\n", timeout_pair.first.c_str(), 423 timeout_pair.second / 1000000); 424 } 425 } 426 427 // Print tests run exceed warnline. 428 size_t slow_test_count = slow_test_list.size(); 429 if (slow_test_count > 0) { 430 ColoredPrintf(COLOR_YELLOW, "[ SLOW ] "); 431 printf("%zu %s, listed below:\n", slow_test_count, (slow_test_count == 1) ? "test" : "tests"); 432 for (const auto& slow_tuple : slow_test_list) { 433 ColoredPrintf(COLOR_YELLOW, "[ SLOW ] "); 434 printf("%s (%" PRId64 " ms, exceed warnline %d ms)\n", std::get<0>(slow_tuple).c_str(), 435 std::get<1>(slow_tuple) / 1000000, std::get<2>(slow_tuple)); 436 } 437 } 438 439 if (fail_test_count > 0) { 440 printf("\n%2zu FAILED %s\n", fail_test_count, (fail_test_count == 1) ? "TEST" : "TESTS"); 441 } 442 if (timeout_test_count > 0) { 443 printf("%2zu TIMEOUT %s\n", timeout_test_count, (timeout_test_count == 1) ? "TEST" : "TESTS"); 444 } 445 if (slow_test_count > 0) { 446 printf("%2zu SLOW %s\n", slow_test_count, (slow_test_count == 1) ? "TEST" : "TESTS"); 447 } 448 fflush(stdout); 449 } 450 451 std::string XmlEscape(const std::string& xml) { 452 std::string escaped; 453 escaped.reserve(xml.size()); 454 455 for (auto c : xml) { 456 switch (c) { 457 case '<': 458 escaped.append("<"); 459 break; 460 case '>': 461 escaped.append(">"); 462 break; 463 case '&': 464 escaped.append("&"); 465 break; 466 case '\'': 467 escaped.append("'"); 468 break; 469 case '"': 470 escaped.append("""); 471 break; 472 default: 473 escaped.append(1, c); 474 break; 475 } 476 } 477 478 return escaped; 479 } 480 481 // Output xml file when --gtest_output is used, write this function as we can't reuse 482 // gtest.cc:XmlUnitTestResultPrinter. The reason is XmlUnitTestResultPrinter is totally 483 // defined in gtest.cc and not expose to outside. What's more, as we don't run gtest in 484 // the parent process, we don't have gtest classes which are needed by XmlUnitTestResultPrinter. 485 void OnTestIterationEndXmlPrint(const std::string& xml_output_filename, 486 const std::vector<TestCase>& testcase_list, 487 time_t epoch_iteration_start_time, 488 int64_t elapsed_time_ns) { 489 FILE* fp = fopen(xml_output_filename.c_str(), "w"); 490 if (fp == NULL) { 491 fprintf(stderr, "failed to open '%s': %s\n", xml_output_filename.c_str(), strerror(errno)); 492 exit(1); 493 } 494 495 size_t total_test_count = 0; 496 size_t total_failed_count = 0; 497 std::vector<size_t> failed_count_list(testcase_list.size(), 0); 498 std::vector<int64_t> elapsed_time_list(testcase_list.size(), 0); 499 for (size_t i = 0; i < testcase_list.size(); ++i) { 500 auto& testcase = testcase_list[i]; 501 total_test_count += testcase.TestCount(); 502 for (size_t j = 0; j < testcase.TestCount(); ++j) { 503 if (testcase.GetTestResult(j) != TEST_SUCCESS) { 504 ++failed_count_list[i]; 505 } 506 elapsed_time_list[i] += testcase.GetTestTime(j); 507 } 508 total_failed_count += failed_count_list[i]; 509 } 510 511 const tm* time_struct = localtime(&epoch_iteration_start_time); 512 char timestamp[40]; 513 snprintf(timestamp, sizeof(timestamp), "%4d-%02d-%02dT%02d:%02d:%02d", 514 time_struct->tm_year + 1900, time_struct->tm_mon + 1, time_struct->tm_mday, 515 time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec); 516 517 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp); 518 fprintf(fp, "<testsuites tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"", 519 total_test_count, total_failed_count); 520 fprintf(fp, " timestamp=\"%s\" time=\"%.3lf\" name=\"AllTests\">\n", timestamp, elapsed_time_ns / 1e9); 521 for (size_t i = 0; i < testcase_list.size(); ++i) { 522 auto& testcase = testcase_list[i]; 523 fprintf(fp, " <testsuite name=\"%s\" tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"", 524 testcase.GetName().c_str(), testcase.TestCount(), failed_count_list[i]); 525 fprintf(fp, " time=\"%.3lf\">\n", elapsed_time_list[i] / 1e9); 526 527 for (size_t j = 0; j < testcase.TestCount(); ++j) { 528 fprintf(fp, " <testcase name=\"%s\" status=\"run\" time=\"%.3lf\" classname=\"%s\"", 529 testcase.GetTest(j).GetName().c_str(), testcase.GetTestTime(j) / 1e9, 530 testcase.GetName().c_str()); 531 if (testcase.GetTestResult(j) == TEST_SUCCESS) { 532 fputs(" />\n", fp); 533 } else { 534 fputs(">\n", fp); 535 const std::string& test_output = testcase.GetTest(j).GetTestOutput(); 536 const std::string escaped_test_output = XmlEscape(test_output); 537 fprintf(fp, " <failure message=\"%s\" type=\"\">\n", escaped_test_output.c_str()); 538 fputs(" </failure>\n", fp); 539 fputs(" </testcase>\n", fp); 540 } 541 } 542 543 fputs(" </testsuite>\n", fp); 544 } 545 fputs("</testsuites>\n", fp); 546 fclose(fp); 547 } 548 549 static bool sigint_flag; 550 static bool sigquit_flag; 551 552 static void signal_handler(int sig) { 553 if (sig == SIGINT) { 554 sigint_flag = true; 555 } else if (sig == SIGQUIT) { 556 sigquit_flag = true; 557 } 558 } 559 560 static bool RegisterSignalHandler() { 561 sigint_flag = false; 562 sigquit_flag = false; 563 sig_t ret = signal(SIGINT, signal_handler); 564 if (ret != SIG_ERR) { 565 ret = signal(SIGQUIT, signal_handler); 566 } 567 if (ret == SIG_ERR) { 568 perror("RegisterSignalHandler"); 569 return false; 570 } 571 return true; 572 } 573 574 static bool UnregisterSignalHandler() { 575 sig_t ret = signal(SIGINT, SIG_DFL); 576 if (ret != SIG_ERR) { 577 ret = signal(SIGQUIT, SIG_DFL); 578 } 579 if (ret == SIG_ERR) { 580 perror("UnregisterSignalHandler"); 581 return false; 582 } 583 return true; 584 } 585 586 struct ChildProcInfo { 587 pid_t pid; 588 int64_t start_time_ns; 589 int64_t end_time_ns; 590 int64_t deadline_end_time_ns; // The time when the test is thought of as timeout. 591 size_t testcase_id, test_id; 592 bool finished; 593 bool timed_out; 594 int exit_status; 595 int child_read_fd; // File descriptor to read child test failure info. 596 }; 597 598 // Forked Child process, run the single test. 599 static void ChildProcessFn(int argc, char** argv, const std::string& test_name) { 600 char** new_argv = new char*[argc + 2]; 601 memcpy(new_argv, argv, sizeof(char*) * argc); 602 603 char* filter_arg = new char [test_name.size() + 20]; 604 strcpy(filter_arg, "--gtest_filter="); 605 strcat(filter_arg, test_name.c_str()); 606 new_argv[argc] = filter_arg; 607 new_argv[argc + 1] = NULL; 608 609 int new_argc = argc + 1; 610 testing::InitGoogleTest(&new_argc, new_argv); 611 int result = RUN_ALL_TESTS(); 612 exit(result); 613 } 614 615 static ChildProcInfo RunChildProcess(const std::string& test_name, int testcase_id, int test_id, 616 int argc, char** argv) { 617 int pipefd[2]; 618 if (pipe(pipefd) == -1) { 619 perror("pipe in RunTestInSeparateProc"); 620 exit(1); 621 } 622 if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1) { 623 perror("fcntl in RunTestInSeparateProc"); 624 exit(1); 625 } 626 pid_t pid = fork(); 627 if (pid == -1) { 628 perror("fork in RunTestInSeparateProc"); 629 exit(1); 630 } else if (pid == 0) { 631 // In child process, run a single test. 632 close(pipefd[0]); 633 close(STDOUT_FILENO); 634 close(STDERR_FILENO); 635 dup2(pipefd[1], STDOUT_FILENO); 636 dup2(pipefd[1], STDERR_FILENO); 637 638 if (!UnregisterSignalHandler()) { 639 exit(1); 640 } 641 ChildProcessFn(argc, argv, test_name); 642 // Unreachable. 643 } 644 // In parent process, initialize child process info. 645 close(pipefd[1]); 646 ChildProcInfo child_proc; 647 child_proc.child_read_fd = pipefd[0]; 648 child_proc.pid = pid; 649 child_proc.start_time_ns = NanoTime(); 650 child_proc.deadline_end_time_ns = child_proc.start_time_ns + GetDeadlineInfo(test_name) * 1000000LL; 651 child_proc.testcase_id = testcase_id; 652 child_proc.test_id = test_id; 653 child_proc.finished = false; 654 return child_proc; 655 } 656 657 static void HandleSignals(std::vector<TestCase>& testcase_list, 658 std::vector<ChildProcInfo>& child_proc_list) { 659 if (sigquit_flag) { 660 sigquit_flag = false; 661 // Print current running tests. 662 printf("List of current running tests:\n"); 663 for (const auto& child_proc : child_proc_list) { 664 if (child_proc.pid != 0) { 665 std::string test_name = testcase_list[child_proc.testcase_id].GetTestName(child_proc.test_id); 666 int64_t current_time_ns = NanoTime(); 667 int64_t run_time_ms = (current_time_ns - child_proc.start_time_ns) / 1000000; 668 printf(" %s (%" PRId64 " ms)\n", test_name.c_str(), run_time_ms); 669 } 670 } 671 } else if (sigint_flag) { 672 sigint_flag = false; 673 // Kill current running tests. 674 for (const auto& child_proc : child_proc_list) { 675 if (child_proc.pid != 0) { 676 // Send SIGKILL to ensure the child process can be killed unconditionally. 677 kill(child_proc.pid, SIGKILL); 678 } 679 } 680 // SIGINT kills the parent process as well. 681 exit(1); 682 } 683 } 684 685 static bool CheckChildProcExit(pid_t exit_pid, int exit_status, 686 std::vector<ChildProcInfo>& child_proc_list) { 687 for (size_t i = 0; i < child_proc_list.size(); ++i) { 688 if (child_proc_list[i].pid == exit_pid) { 689 child_proc_list[i].finished = true; 690 child_proc_list[i].timed_out = false; 691 child_proc_list[i].exit_status = exit_status; 692 child_proc_list[i].end_time_ns = NanoTime(); 693 return true; 694 } 695 } 696 return false; 697 } 698 699 static size_t CheckChildProcTimeout(std::vector<ChildProcInfo>& child_proc_list) { 700 int64_t current_time_ns = NanoTime(); 701 size_t timeout_child_count = 0; 702 for (size_t i = 0; i < child_proc_list.size(); ++i) { 703 if (child_proc_list[i].deadline_end_time_ns <= current_time_ns) { 704 child_proc_list[i].finished = true; 705 child_proc_list[i].timed_out = true; 706 child_proc_list[i].end_time_ns = current_time_ns; 707 ++timeout_child_count; 708 } 709 } 710 return timeout_child_count; 711 } 712 713 static void ReadChildProcOutput(std::vector<TestCase>& testcase_list, 714 std::vector<ChildProcInfo>& child_proc_list) { 715 for (const auto& child_proc : child_proc_list) { 716 TestCase& testcase = testcase_list[child_proc.testcase_id]; 717 int test_id = child_proc.test_id; 718 while (true) { 719 char buf[1024]; 720 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(child_proc.child_read_fd, buf, sizeof(buf) - 1)); 721 if (bytes_read > 0) { 722 buf[bytes_read] = '\0'; 723 testcase.GetTest(test_id).AppendTestOutput(buf); 724 } else if (bytes_read == 0) { 725 break; // Read end. 726 } else { 727 if (errno == EAGAIN) { 728 break; 729 } 730 perror("failed to read child_read_fd"); 731 exit(1); 732 } 733 } 734 } 735 } 736 737 static void WaitChildProcs(std::vector<TestCase>& testcase_list, 738 std::vector<ChildProcInfo>& child_proc_list) { 739 size_t finished_child_count = 0; 740 while (true) { 741 int status; 742 pid_t result; 743 while ((result = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) { 744 if (CheckChildProcExit(result, status, child_proc_list)) { 745 ++finished_child_count; 746 } 747 } 748 749 if (result == -1) { 750 if (errno == ECHILD) { 751 // This happens when we have no running child processes. 752 return; 753 } else { 754 perror("waitpid"); 755 exit(1); 756 } 757 } else if (result == 0) { 758 finished_child_count += CheckChildProcTimeout(child_proc_list); 759 } 760 761 ReadChildProcOutput(testcase_list, child_proc_list); 762 if (finished_child_count > 0) { 763 return; 764 } 765 766 HandleSignals(testcase_list, child_proc_list); 767 768 // sleep 1 ms to avoid busy looping. 769 timespec sleep_time; 770 sleep_time.tv_sec = 0; 771 sleep_time.tv_nsec = 1000000; 772 nanosleep(&sleep_time, NULL); 773 } 774 } 775 776 static TestResult WaitForOneChild(pid_t pid) { 777 int exit_status; 778 pid_t result = TEMP_FAILURE_RETRY(waitpid(pid, &exit_status, 0)); 779 780 TestResult test_result = TEST_SUCCESS; 781 if (result != pid || WEXITSTATUS(exit_status) != 0) { 782 test_result = TEST_FAILED; 783 } 784 return test_result; 785 } 786 787 static void CollectChildTestResult(const ChildProcInfo& child_proc, TestCase& testcase) { 788 int test_id = child_proc.test_id; 789 testcase.SetTestTime(test_id, child_proc.end_time_ns - child_proc.start_time_ns); 790 if (child_proc.timed_out) { 791 // The child process marked as timed_out has not exited, and we should kill it manually. 792 kill(child_proc.pid, SIGKILL); 793 WaitForOneChild(child_proc.pid); 794 } 795 close(child_proc.child_read_fd); 796 797 if (child_proc.timed_out) { 798 testcase.SetTestResult(test_id, TEST_TIMEOUT); 799 char buf[1024]; 800 snprintf(buf, sizeof(buf), "%s killed because of timeout at %" PRId64 " ms.\n", 801 testcase.GetTestName(test_id).c_str(), testcase.GetTestTime(test_id) / 1000000); 802 testcase.GetTest(test_id).AppendTestOutput(buf); 803 804 } else if (WIFSIGNALED(child_proc.exit_status)) { 805 // Record signal terminated test as failed. 806 testcase.SetTestResult(test_id, TEST_FAILED); 807 char buf[1024]; 808 snprintf(buf, sizeof(buf), "%s terminated by signal: %s.\n", 809 testcase.GetTestName(test_id).c_str(), strsignal(WTERMSIG(child_proc.exit_status))); 810 testcase.GetTest(test_id).AppendTestOutput(buf); 811 812 } else { 813 int exitcode = WEXITSTATUS(child_proc.exit_status); 814 testcase.SetTestResult(test_id, exitcode == 0 ? TEST_SUCCESS : TEST_FAILED); 815 if (exitcode != 0) { 816 char buf[1024]; 817 snprintf(buf, sizeof(buf), "%s exited with exitcode %d.\n", 818 testcase.GetTestName(test_id).c_str(), exitcode); 819 testcase.GetTest(test_id).AppendTestOutput(buf); 820 } 821 } 822 } 823 824 // We choose to use multi-fork and multi-wait here instead of multi-thread, because it always 825 // makes deadlock to use fork in multi-thread. 826 // Returns true if all tests run successfully, otherwise return false. 827 static bool RunTestInSeparateProc(int argc, char** argv, std::vector<TestCase>& testcase_list, 828 int iteration_count, size_t job_count, 829 const std::string& xml_output_filename) { 830 // Stop default result printer to avoid environment setup/teardown information for each test. 831 testing::UnitTest::GetInstance()->listeners().Release( 832 testing::UnitTest::GetInstance()->listeners().default_result_printer()); 833 testing::UnitTest::GetInstance()->listeners().Append(new TestResultPrinter); 834 835 if (!RegisterSignalHandler()) { 836 exit(1); 837 } 838 839 bool all_tests_passed = true; 840 841 for (size_t iteration = 1; 842 iteration_count < 0 || iteration <= static_cast<size_t>(iteration_count); 843 ++iteration) { 844 OnTestIterationStartPrint(testcase_list, iteration, iteration_count); 845 int64_t iteration_start_time_ns = NanoTime(); 846 time_t epoch_iteration_start_time = time(NULL); 847 848 // Run up to job_count tests in parallel, each test in a child process. 849 std::vector<ChildProcInfo> child_proc_list; 850 851 // Next test to run is [next_testcase_id:next_test_id]. 852 size_t next_testcase_id = 0; 853 size_t next_test_id = 0; 854 855 // Record how many tests are finished. 856 std::vector<size_t> finished_test_count_list(testcase_list.size(), 0); 857 size_t finished_testcase_count = 0; 858 859 while (finished_testcase_count < testcase_list.size()) { 860 // run up to job_count child processes. 861 while (child_proc_list.size() < job_count && next_testcase_id < testcase_list.size()) { 862 std::string test_name = testcase_list[next_testcase_id].GetTestName(next_test_id); 863 ChildProcInfo child_proc = RunChildProcess(test_name, next_testcase_id, next_test_id, 864 argc, argv); 865 child_proc_list.push_back(child_proc); 866 if (++next_test_id == testcase_list[next_testcase_id].TestCount()) { 867 next_test_id = 0; 868 ++next_testcase_id; 869 } 870 } 871 872 // Wait for any child proc finish or timeout. 873 WaitChildProcs(testcase_list, child_proc_list); 874 875 // Collect result. 876 auto it = child_proc_list.begin(); 877 while (it != child_proc_list.end()) { 878 auto& child_proc = *it; 879 if (child_proc.finished == true) { 880 size_t testcase_id = child_proc.testcase_id; 881 size_t test_id = child_proc.test_id; 882 TestCase& testcase = testcase_list[testcase_id]; 883 884 CollectChildTestResult(child_proc, testcase); 885 OnTestEndPrint(testcase, test_id); 886 887 if (++finished_test_count_list[testcase_id] == testcase.TestCount()) { 888 ++finished_testcase_count; 889 } 890 if (testcase.GetTestResult(test_id) != TEST_SUCCESS) { 891 all_tests_passed = false; 892 } 893 894 it = child_proc_list.erase(it); 895 } else { 896 ++it; 897 } 898 } 899 } 900 901 int64_t elapsed_time_ns = NanoTime() - iteration_start_time_ns; 902 OnTestIterationEndPrint(testcase_list, iteration, elapsed_time_ns); 903 if (!xml_output_filename.empty()) { 904 OnTestIterationEndXmlPrint(xml_output_filename, testcase_list, epoch_iteration_start_time, 905 elapsed_time_ns); 906 } 907 } 908 909 if (!UnregisterSignalHandler()) { 910 exit(1); 911 } 912 913 return all_tests_passed; 914 } 915 916 static size_t GetDefaultJobCount() { 917 return static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN)); 918 } 919 920 static void AddPathSeparatorInTestProgramPath(std::vector<char*>& args) { 921 // To run DeathTest in threadsafe mode, gtest requires that the user must invoke the 922 // test program via a valid path that contains at least one path separator. 923 // The reason is that gtest uses clone() + execve() to run DeathTest in threadsafe mode, 924 // and execve() doesn't read environment variable PATH, so execve() will not success 925 // until we specify the absolute path or relative path of the test program directly. 926 if (strchr(args[0], '/') == nullptr) { 927 args[0] = strdup(g_executable_path.c_str()); 928 } 929 } 930 931 static void AddGtestFilterSynonym(std::vector<char*>& args) { 932 // Support --gtest-filter as a synonym for --gtest_filter. 933 for (size_t i = 1; i < args.size(); ++i) { 934 if (strncmp(args[i], "--gtest-filter", strlen("--gtest-filter")) == 0) { 935 args[i][7] = '_'; 936 } 937 } 938 } 939 940 struct IsolationTestOptions { 941 bool isolate; 942 size_t job_count; 943 int test_deadline_ms; 944 int test_warnline_ms; 945 std::string gtest_color; 946 bool gtest_print_time; 947 int gtest_repeat; 948 std::string gtest_output; 949 }; 950 951 // Pick options not for gtest: There are two parts in args, one part is used in isolation test mode 952 // as described in PrintHelpInfo(), the other part is handled by testing::InitGoogleTest() in 953 // gtest. PickOptions() picks the first part into IsolationTestOptions structure, leaving the second 954 // part in args. 955 // Arguments: 956 // args is used to pass in all command arguments, and pass out only the part of options for gtest. 957 // options is used to pass out test options in isolation mode. 958 // Return false if there is error in arguments. 959 static bool PickOptions(std::vector<char*>& args, IsolationTestOptions& options) { 960 for (size_t i = 1; i < args.size(); ++i) { 961 if (strcmp(args[i], "--help") == 0 || strcmp(args[i], "-h") == 0) { 962 PrintHelpInfo(); 963 options.isolate = false; 964 return true; 965 } 966 } 967 968 AddPathSeparatorInTestProgramPath(args); 969 AddGtestFilterSynonym(args); 970 971 // if --bionic-selftest argument is used, only enable self tests, otherwise remove self tests. 972 bool enable_selftest = false; 973 for (size_t i = 1; i < args.size(); ++i) { 974 if (strcmp(args[i], "--bionic-selftest") == 0) { 975 // This argument is to enable "bionic_selftest*" for self test, and is not shown in help info. 976 // Don't remove this option from arguments. 977 enable_selftest = true; 978 } 979 } 980 std::string gtest_filter_str; 981 for (size_t i = args.size() - 1; i >= 1; --i) { 982 if (strncmp(args[i], "--gtest_filter=", strlen("--gtest_filter=")) == 0) { 983 gtest_filter_str = std::string(args[i]); 984 args.erase(args.begin() + i); 985 break; 986 } 987 } 988 if (enable_selftest == true) { 989 args.push_back(strdup("--gtest_filter=bionic_selftest*")); 990 } else { 991 if (gtest_filter_str == "") { 992 gtest_filter_str = "--gtest_filter=-bionic_selftest*"; 993 } else { 994 // Find if '-' for NEGATIVE_PATTERNS exists. 995 if (gtest_filter_str.find(":-") != std::string::npos) { 996 gtest_filter_str += ":bionic_selftest*"; 997 } else { 998 gtest_filter_str += ":-bionic_selftest*"; 999 } 1000 } 1001 args.push_back(strdup(gtest_filter_str.c_str())); 1002 } 1003 1004 options.isolate = true; 1005 // Parse arguments that make us can't run in isolation mode. 1006 for (size_t i = 1; i < args.size(); ++i) { 1007 if (strcmp(args[i], "--no-isolate") == 0) { 1008 options.isolate = false; 1009 } else if (strcmp(args[i], "--gtest_list_tests") == 0) { 1010 options.isolate = false; 1011 } 1012 } 1013 1014 // Stop parsing if we will not run in isolation mode. 1015 if (options.isolate == false) { 1016 return true; 1017 } 1018 1019 // Init default isolation test options. 1020 options.job_count = GetDefaultJobCount(); 1021 options.test_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS; 1022 options.test_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS; 1023 options.gtest_color = testing::GTEST_FLAG(color); 1024 options.gtest_print_time = testing::GTEST_FLAG(print_time); 1025 options.gtest_repeat = testing::GTEST_FLAG(repeat); 1026 options.gtest_output = testing::GTEST_FLAG(output); 1027 1028 // Parse arguments speficied for isolation mode. 1029 for (size_t i = 1; i < args.size(); ++i) { 1030 if (strncmp(args[i], "-j", strlen("-j")) == 0) { 1031 char* p = args[i] + strlen("-j"); 1032 int count = 0; 1033 if (*p != '\0') { 1034 // Argument like -j5. 1035 count = atoi(p); 1036 } else if (args.size() > i + 1) { 1037 // Arguments like -j 5. 1038 count = atoi(args[i + 1]); 1039 ++i; 1040 } 1041 if (count <= 0) { 1042 fprintf(stderr, "invalid job count: %d\n", count); 1043 return false; 1044 } 1045 options.job_count = static_cast<size_t>(count); 1046 } else if (strncmp(args[i], "--deadline=", strlen("--deadline=")) == 0) { 1047 int time_ms = atoi(args[i] + strlen("--deadline=")); 1048 if (time_ms <= 0) { 1049 fprintf(stderr, "invalid deadline: %d\n", time_ms); 1050 return false; 1051 } 1052 options.test_deadline_ms = time_ms; 1053 } else if (strncmp(args[i], "--warnline=", strlen("--warnline=")) == 0) { 1054 int time_ms = atoi(args[i] + strlen("--warnline=")); 1055 if (time_ms <= 0) { 1056 fprintf(stderr, "invalid warnline: %d\n", time_ms); 1057 return false; 1058 } 1059 options.test_warnline_ms = time_ms; 1060 } else if (strncmp(args[i], "--gtest_color=", strlen("--gtest_color=")) == 0) { 1061 options.gtest_color = args[i] + strlen("--gtest_color="); 1062 } else if (strcmp(args[i], "--gtest_print_time=0") == 0) { 1063 options.gtest_print_time = false; 1064 } else if (strncmp(args[i], "--gtest_repeat=", strlen("--gtest_repeat=")) == 0) { 1065 // If the value of gtest_repeat is < 0, then it indicates the tests 1066 // should be repeated forever. 1067 options.gtest_repeat = atoi(args[i] + strlen("--gtest_repeat=")); 1068 // Remove --gtest_repeat=xx from arguments, so child process only run one iteration for a single test. 1069 args.erase(args.begin() + i); 1070 --i; 1071 } else if (strncmp(args[i], "--gtest_output=", strlen("--gtest_output=")) == 0) { 1072 std::string output = args[i] + strlen("--gtest_output="); 1073 // generate output xml file path according to the strategy in gtest. 1074 bool success = true; 1075 if (strncmp(output.c_str(), "xml:", strlen("xml:")) == 0) { 1076 output = output.substr(strlen("xml:")); 1077 if (output.size() == 0) { 1078 success = false; 1079 } 1080 // Make absolute path. 1081 if (success && output[0] != '/') { 1082 char* cwd = getcwd(NULL, 0); 1083 if (cwd != NULL) { 1084 output = std::string(cwd) + "/" + output; 1085 free(cwd); 1086 } else { 1087 success = false; 1088 } 1089 } 1090 // Add file name if output is a directory. 1091 if (success && output.back() == '/') { 1092 output += "test_details.xml"; 1093 } 1094 } 1095 if (success) { 1096 options.gtest_output = output; 1097 } else { 1098 fprintf(stderr, "invalid gtest_output file: %s\n", args[i]); 1099 return false; 1100 } 1101 1102 // Remove --gtest_output=xxx from arguments, so child process will not write xml file. 1103 args.erase(args.begin() + i); 1104 --i; 1105 } 1106 } 1107 1108 // Add --no-isolate in args to prevent child process from running in isolation mode again. 1109 // As DeathTest will try to call execve(), this argument should always be added. 1110 args.insert(args.begin() + 1, strdup("--no-isolate")); 1111 return true; 1112 } 1113 1114 static std::string get_proc_self_exe() { 1115 char path[PATH_MAX]; 1116 ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path)); 1117 if (path_len <= 0 || path_len >= static_cast<ssize_t>(sizeof(path))) { 1118 perror("readlink"); 1119 exit(1); 1120 } 1121 1122 return std::string(path, path_len); 1123 } 1124 1125 int main(int argc, char** argv) { 1126 g_executable_path = get_proc_self_exe(); 1127 std::vector<char*> arg_list; 1128 for (int i = 0; i < argc; ++i) { 1129 arg_list.push_back(argv[i]); 1130 } 1131 1132 IsolationTestOptions options; 1133 if (PickOptions(arg_list, options) == false) { 1134 return 1; 1135 } 1136 1137 if (options.isolate == true) { 1138 // Set global variables. 1139 global_test_run_deadline_ms = options.test_deadline_ms; 1140 global_test_run_warnline_ms = options.test_warnline_ms; 1141 testing::GTEST_FLAG(color) = options.gtest_color.c_str(); 1142 testing::GTEST_FLAG(print_time) = options.gtest_print_time; 1143 std::vector<TestCase> testcase_list; 1144 1145 argc = static_cast<int>(arg_list.size()); 1146 arg_list.push_back(NULL); 1147 if (EnumerateTests(argc, arg_list.data(), testcase_list) == false) { 1148 return 1; 1149 } 1150 bool all_test_passed = RunTestInSeparateProc(argc, arg_list.data(), testcase_list, 1151 options.gtest_repeat, options.job_count, options.gtest_output); 1152 return all_test_passed ? 0 : 1; 1153 } else { 1154 argc = static_cast<int>(arg_list.size()); 1155 arg_list.push_back(NULL); 1156 testing::InitGoogleTest(&argc, arg_list.data()); 1157 return RUN_ALL_TESTS(); 1158 } 1159 } 1160 1161 //################################################################################ 1162 // Bionic Gtest self test, run this by --bionic-selftest option. 1163 1164 TEST(bionic_selftest, test_success) { 1165 ASSERT_EQ(1, 1); 1166 } 1167 1168 TEST(bionic_selftest, test_fail) { 1169 ASSERT_EQ(0, 1); 1170 } 1171 1172 TEST(bionic_selftest, test_time_warn) { 1173 sleep(4); 1174 } 1175 1176 TEST(bionic_selftest, test_timeout) { 1177 while (1) {} 1178 } 1179 1180 TEST(bionic_selftest, test_signal_SEGV_terminated) { 1181 char* p = reinterpret_cast<char*>(static_cast<intptr_t>(atoi("0"))); 1182 *p = 3; 1183 } 1184 1185 class bionic_selftest_DeathTest : public ::testing::Test { 1186 protected: 1187 virtual void SetUp() { 1188 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 1189 } 1190 }; 1191 1192 static void deathtest_helper_success() { 1193 ASSERT_EQ(1, 1); 1194 exit(0); 1195 } 1196 1197 TEST_F(bionic_selftest_DeathTest, success) { 1198 ASSERT_EXIT(deathtest_helper_success(), ::testing::ExitedWithCode(0), ""); 1199 } 1200 1201 static void deathtest_helper_fail() { 1202 ASSERT_EQ(1, 0); 1203 } 1204 1205 TEST_F(bionic_selftest_DeathTest, fail) { 1206 ASSERT_EXIT(deathtest_helper_fail(), ::testing::ExitedWithCode(0), ""); 1207 } 1208