blob: 4304d8cf8bd51e6dd7ceba4e2e4e2307b3502768 [file] [log] [blame]
Yabin Cui294d1e22014-12-07 20:43:37 -08001/*
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 <errno.h>
20#include <stdarg.h>
21#include <stdio.h>
22#include <string.h>
23#include <sys/wait.h>
24#include <time.h>
25#include <unistd.h>
26
27#include <string>
28#include <tuple>
29#include <utility>
30#include <vector>
31
32namespace testing {
33namespace internal {
34
35// Reuse of testing::internal::ColoredPrintf in gtest.
36enum GTestColor {
37 COLOR_DEFAULT,
38 COLOR_RED,
39 COLOR_GREEN,
40 COLOR_YELLOW
41};
42
43void ColoredPrintf(GTestColor color, const char* fmt, ...);
44
45} // namespace internal
46} // namespace testing
47
48using testing::internal::GTestColor;
49using testing::internal::COLOR_DEFAULT;
50using testing::internal::COLOR_RED;
51using testing::internal::COLOR_GREEN;
52using testing::internal::COLOR_YELLOW;
53using testing::internal::ColoredPrintf;
54
55constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_IN_MS = 60000;
56constexpr int DEFAULT_GLOBAL_TEST_RUN_WARNLINE_IN_MS = 2000;
57
58// The time each test can run before killed for the reason of timeout.
59// It takes effect only with --isolate option.
60static int global_test_run_deadline_in_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_IN_MS;
61
62// The time each test can run before be warned for too much running time.
63// It takes effect only with --isolate option.
64static int global_test_run_warnline_in_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_IN_MS;
65
66// Return deadline duration for a test, in ms.
67static int GetDeadlineInfo(const std::string& /*test_name*/) {
68 return global_test_run_deadline_in_ms;
69}
70
71// Return warnline duration for a test, in ms.
72static int GetWarnlineInfo(const std::string& /*test_name*/) {
73 return global_test_run_warnline_in_ms;
74}
75
76enum TestResult {
77 TEST_SUCCESS = 0,
78 TEST_FAILED,
79 TEST_TIMEOUT
80};
81
82class TestCase {
83 public:
84 TestCase() {} // For std::vector<TestCase>.
85 explicit TestCase(const char* name) : name_(name) {}
86
87 const std::string& GetName() const { return name_; }
88
89 void AppendTest(const std::string& test_name) {
90 test_list_.push_back(std::make_tuple(test_name, TEST_FAILED, 0LL));
91 }
92
93 int NumTests() const { return test_list_.size(); }
94
95 std::string GetTestName(int test_id) const {
96 VerifyTestId(test_id);
97 return name_ + "." + std::get<0>(test_list_[test_id]);
98 }
99
100 void SetTestResult(int test_id, TestResult result) {
101 VerifyTestId(test_id);
102 std::get<1>(test_list_[test_id]) = result;
103 }
104
105 TestResult GetTestResult(int test_id) const {
106 VerifyTestId(test_id);
107 return std::get<1>(test_list_[test_id]);
108 }
109
110 void SetTestTime(int test_id, int64_t elapsed_time) {
111 VerifyTestId(test_id);
112 std::get<2>(test_list_[test_id]) = elapsed_time;
113 }
114
115 int64_t GetTestTime(int test_id) const {
116 VerifyTestId(test_id);
117 return std::get<2>(test_list_[test_id]);
118 }
119
120 private:
121 void VerifyTestId(int test_id) const {
122 if(test_id < 0 || test_id >= static_cast<int>(test_list_.size())) {
123 fprintf(stderr, "test_id %d out of range [0, %zu)\n", test_id, test_list_.size());
124 exit(1);
125 }
126 }
127
128 private:
129 const std::string name_;
130 std::vector<std::tuple<std::string, TestResult, int64_t> > test_list_;
131};
132
133// TestResultPrinter is copied from part of external/gtest/src/gtest.cc:PrettyUnitTestResultPrinter.
134// The reason for copy is that PrettyUnitTestResultPrinter is defined and used in gtest.cc, which
135// is hard to reuse.
136// TestResultPrinter only print information for a single test, which is used in child process.
137// The information of test_iteration/environment/testcase is left for parent process to print.
138class TestResultPrinter : public testing::EmptyTestEventListener {
139 public:
140 TestResultPrinter() : pinfo_(NULL) {}
141 virtual void OnTestStart(const testing::TestInfo& test_info) {
142 pinfo_ = &test_info; // Record test_info for use in OnTestPartResult.
143 }
144 virtual void OnTestPartResult(const testing::TestPartResult& result);
145 virtual void OnTestEnd(const testing::TestInfo& test_info);
146
147 private:
148 const testing::TestInfo* pinfo_;
149};
150
151// Called after an assertion failure.
152void TestResultPrinter::OnTestPartResult(const testing::TestPartResult& result) {
153 // If the test part succeeded, we don't need to do anything.
154 if (result.type() == testing::TestPartResult::kSuccess)
155 return;
156
157 // Print failure message from the assertion (e.g. expected this and got that).
158 char buf[1024];
159 snprintf(buf, sizeof(buf), "%s:(%d) Failure in test %s.%s\n%s\n", result.file_name(),
160 result.line_number(),
161 pinfo_->test_case_name(),
162 pinfo_->name(),
163 result.message());
164
165 // Use write() to skip line buffer of printf, thus can avoid getting interleaved when
166 // several processes are printing at the same time.
167 int towrite = strlen(buf);
168 char* p = buf;
169 while (towrite > 0) {
170 ssize_t num_write = write(fileno(stdout), p, towrite);
171 if (num_write == -1) {
172 if (errno != EINTR) {
173 fprintf(stderr, "write, errno = %d\n", errno);
174 break;
175 }
176 } else {
177 towrite -= num_write;
178 p += num_write;
179 }
180 }
181}
182
183void TestResultPrinter::OnTestEnd(const testing::TestInfo& test_info) {
184 if (test_info.result()->Passed()) {
185 ColoredPrintf(COLOR_GREEN, "[ OK ] ");
186 } else {
187 ColoredPrintf(COLOR_RED, "[ FAILED ] ");
188 }
189 printf("%s.%s", test_info.test_case_name(), test_info.name());
190 if (test_info.result()->Failed()) {
191 const char* const type_param = test_info.type_param();
192 const char* const value_param = test_info.value_param();
193 if (type_param != NULL || value_param != NULL) {
194 printf(", where ");
195 if (type_param != NULL) {
196 printf("TypeParam = %s", type_param);
197 if (value_param != NULL) {
198 printf(" and ");
199 }
200 }
201 if (value_param != NULL) {
202 printf("GetParam() = %s", value_param);
203 }
204 }
205 }
206
207 if (testing::GTEST_FLAG(print_time)) {
208 printf(" (%lld ms)\n", test_info.result()->elapsed_time());
209 } else {
210 printf("\n");
211 }
212 fflush(stdout);
213}
214
215static int64_t NanoTime() {
216 struct timespec t;
217 t.tv_sec = t.tv_nsec = 0;
218 clock_gettime(CLOCK_MONOTONIC, &t);
219 return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
220}
221
222static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcase_list) {
223 std::string command;
224 for (int i = 0; i < argc; ++i) {
225 command += argv[i];
226 command += " ";
227 }
228 command += "--gtest_list_tests";
229 FILE* fp = popen(command.c_str(), "r");
230 if (fp == NULL) {
231 perror("popen");
232 return false;
233 }
234
235 char buf[200];
236 while (fgets(buf, sizeof(buf), fp) != NULL) {
237 char* p = buf;
238
239 while (*p != '\0' && isspace(*p)) {
240 ++p;
241 }
242 if (*p == '\0') continue;
243 char* start = p;
244 while (*p != '\0' && !isspace(*p)) {
245 ++p;
246 }
247 char* end = p;
248 while (*p != '\0' && isspace(*p)) {
249 ++p;
250 }
251 if (*p != '\0') {
252 // This is not we want, gtest must meet with some error when parsing the arguments.
253 fprintf(stderr, "argument error, check with --help\n");
254 return false;
255 }
256 *end = '\0';
257 if (*(end - 1) == '.') {
258 *(end - 1) = '\0';
259 testcase_list.push_back(TestCase(start));
260 } else {
261 testcase_list.back().AppendTest(start);
262 }
263 }
264 int result = pclose(fp);
265 return (result != -1 && WEXITSTATUS(result) == 0);
266}
267
268static void PrintHelpInfo() {
269 printf("Bionic Unit Test Options:\n"
270 " --isolate\n"
271 " Use isolation mode, Run each test in a separate process.\n"
272 " --deadline=[TIME_IN_MS]\n"
273 " Run each test in no longer than [TIME_IN_MS] time.\n"
274 " It takes effect only in isolation mode. Deafult deadline is 60000 ms.\n"
275 " --warnline=[TIME_IN_MS]\n"
276 " Test running longer than [TIME_IN_MS] will be warned.\n"
277 " It takes effect only in isolation mode. Default warnline is 2000 ms.\n"
278 " -j [JOB_NUM]\n"
279 " Run up to JOB_NUM tests in parallel.\n"
280 " Use isolation mode, Run each test in a separate process.\n"
281 " If JOB_NUM is not given, it is set to the number of cpus available.\n"
282 "\n");
283}
284
285// Part of the following *Print functions are copied from external/gtest/src/gtest.cc:
286// PrettyUnitTestResultPrinter. The reason for copy is that PrettyUnitTestResultPrinter
287// is defined and used in gtest.cc, which is hard to reuse.
288static void OnTestIterationStartPrint(const std::vector<TestCase>& testcase_list, int iteration,
289 int num_iterations) {
290 if (num_iterations > 1) {
291 printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration);
292 }
293 ColoredPrintf(COLOR_GREEN, "[==========] ");
294
295 int num_testcases = testcase_list.size();
296 int num_tests = 0;
297 for (const auto& testcase : testcase_list) {
298 num_tests += testcase.NumTests();
299 }
300
301 printf("Running %d %s from %d %s.\n",
302 num_tests, (num_tests == 1) ? "test" : "tests",
303 num_testcases, (num_testcases == 1) ? "test case" : "test cases");
304 fflush(stdout);
305}
306
307static void OnTestTimeoutPrint(const TestCase& testcase, int test_id) {
308 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
309 printf("%s (killed by timeout at %lld ms)\n", testcase.GetTestName(test_id).c_str(),
310 testcase.GetTestTime(test_id) / 1000000LL);
311 fflush(stdout);
312}
313
314static void TestcaseTimePrint(const TestCase& testcase) {
315 int64_t testcase_time = 0;
316 for (int i = 0; i < testcase.NumTests(); ++i) {
317 testcase_time += testcase.GetTestTime(i);
318 }
319 printf("%d %s from %s (%lld ms total)\n", testcase.NumTests(),
320 (testcase.NumTests() == 1) ? "test" : "tests",
321 testcase.GetName().c_str(),
322 testcase_time / 1000000LL);
323 fflush(stdout);
324}
325
326static void OnTestIterationEndPrint(const std::vector<TestCase>& testcase_list, int /*iteration*/,
327 int64_t elapsed_time) {
328
329 std::vector<std::string> fail_test_name_list;
330 std::vector<std::pair<std::string, int64_t>> timeout_test_list;
331
332 // For tests run exceed warnline but not timeout.
333 std::vector<std::tuple<std::string, int64_t, int>> timewarn_test_list;
334 int num_testcases = testcase_list.size();
335 int num_tests = 0;
336 int num_success_tests = 0;
337
338 for (const auto& testcase : testcase_list) {
339 num_tests += testcase.NumTests();
340 for (int i = 0; i < testcase.NumTests(); ++i) {
341 TestResult result = testcase.GetTestResult(i);
342 if (result == TEST_SUCCESS) {
343 ++num_success_tests;
344 } else if (result == TEST_FAILED) {
345 fail_test_name_list.push_back(testcase.GetTestName(i));
346 } else if (result == TEST_TIMEOUT) {
347 timeout_test_list.push_back(std::make_pair(testcase.GetTestName(i),
348 testcase.GetTestTime(i)));
349 }
350 if (result != TEST_TIMEOUT &&
351 testcase.GetTestTime(i) / 1000000 >= GetWarnlineInfo(testcase.GetTestName(i))) {
352 timewarn_test_list.push_back(std::make_tuple(testcase.GetTestName(i),
353 testcase.GetTestTime(i),
354 GetWarnlineInfo(testcase.GetTestName(i))));
355 }
356 }
357 }
358
359 for (auto const& testcase : testcase_list) {
360 TestcaseTimePrint(testcase);
361 }
362
363 ColoredPrintf(COLOR_GREEN, "[==========] ");
364 printf("%d %s from %d %s ran.", num_tests, (num_tests == 1) ? "test" : "tests",
365 num_testcases, (num_testcases == 1) ? "test case" : "test cases");
366 if (testing::GTEST_FLAG(print_time)) {
367 printf(" (%lld ms total)", elapsed_time / 1000000LL);
368 }
369 printf("\n");
370 ColoredPrintf(COLOR_GREEN, "[ PASSED ] ");
371 printf("%d %s.\n", num_success_tests, (num_success_tests == 1) ? "test" : "tests");
372
373 // Print tests failed.
374 int num_fail_tests = fail_test_name_list.size();
375 if (num_fail_tests > 0) {
376 ColoredPrintf(COLOR_RED, "[ FAILED ] ");
377 printf("%d %s, listed below:\n", num_fail_tests, (num_fail_tests == 1) ? "test" : "tests");
378 for (const auto& name : fail_test_name_list) {
379 ColoredPrintf(COLOR_RED, "[ FAILED ] ");
380 printf("%s\n", name.c_str());
381 }
382 }
383
384 // Print tests run timeout.
385 int num_timeout_tests = timeout_test_list.size();
386 if (num_timeout_tests > 0) {
387 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
388 printf("%d %s, listed below:\n", num_timeout_tests, (num_timeout_tests == 1) ? "test" : "tests");
389 for (const auto& timeout_pair : timeout_test_list) {
390 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
391 printf("%s (stopped at %lld ms)\n", timeout_pair.first.c_str(),
392 timeout_pair.second / 1000000LL);
393 }
394 }
395
396 // Print tests run exceed warnline.
397 int num_timewarn_tests = timewarn_test_list.size();
398 if (num_timewarn_tests > 0) {
399 ColoredPrintf(COLOR_YELLOW, "[ TIMEWARN ] ");
400 printf("%d %s, listed below:\n", num_timewarn_tests, (num_timewarn_tests == 1) ? "test" : "tests");
401 for (const auto& timewarn_tuple : timewarn_test_list) {
402 ColoredPrintf(COLOR_YELLOW, "[ TIMEWARN ] ");
403 printf("%s (%lld ms, exceed warnline %d ms)\n", std::get<0>(timewarn_tuple).c_str(),
404 std::get<1>(timewarn_tuple) / 1000000LL,
405 std::get<2>(timewarn_tuple));
406 }
407 }
408
409 if (num_fail_tests > 0) {
410 printf("\n%2d FAILED %s\n", num_fail_tests, (num_fail_tests == 1) ? "TEST" : "TESTS");
411 }
412 if (num_timeout_tests > 0) {
413 printf("%2d TIMEOUT %s\n", num_timeout_tests, (num_timeout_tests == 1) ? "TEST" : "TESTS");
414 }
415 if (num_timewarn_tests > 0) {
416 printf("%2d TIMEWARN %s\n", num_timewarn_tests, (num_timewarn_tests == 1) ? "TEST" : "TESTS");
417 }
418 fflush(stdout);
419}
420
421// Forked Child process, run the single test.
422static void ChildProcessFn(int argc, char** argv, const std::string& test_name) {
423 char** new_argv = new char*[argc + 1];
424 memcpy(new_argv, argv, sizeof(char*) * argc);
425
426 char* filter_arg = new char [test_name.size() + 20];
427 strcpy(filter_arg, "--gtest_filter=");
428 strcat(filter_arg, test_name.c_str());
429 new_argv[argc] = filter_arg;
430
431 int new_argc = argc + 1;
432 testing::InitGoogleTest(&new_argc, new_argv);
433 int result = RUN_ALL_TESTS();
434 exit(result);
435}
436
437struct ChildProcInfo {
438 pid_t pid;
439 int64_t start_time;
440 int64_t deadline_time;
441 int testcase_id, test_id;
442 bool done_flag;
443 TestResult test_result;
444 ChildProcInfo() : pid(0) {}
445};
446
447static void WaitChildProcs(std::vector<ChildProcInfo>& child_proc_list) {
448 pid_t result;
449 int exit_status;
450 bool loop_flag = true;
451
452 while (true) {
453 while ((result = waitpid(-1, &exit_status, WNOHANG)) == -1) {
454 if (errno != EINTR) {
455 break;
456 }
457 }
458
459 if (result == -1) {
460 perror("waitpid");
461 exit(1);
462 } else if (result == 0) {
463 // Check child timeout.
464 int64_t current_time = NanoTime();
465 for (size_t i = 0; i < child_proc_list.size(); ++i) {
466 if (child_proc_list[i].deadline_time <= current_time) {
467 child_proc_list[i].done_flag = true;
468 child_proc_list[i].test_result = TEST_TIMEOUT;
469 loop_flag = false;
470 }
471 }
472 } else {
473 // Check child finish.
474 for (size_t i = 0; i < child_proc_list.size(); ++i) {
475 if (child_proc_list[i].pid == result) {
476 child_proc_list[i].done_flag = true;
477 child_proc_list[i].test_result = (WEXITSTATUS(exit_status) == 0) ? TEST_SUCCESS :
478 TEST_FAILED;
479 loop_flag = false;
480 break;
481 }
482 }
483 }
484
485 if (!loop_flag) break;
486 // sleep 1 ms to avoid busy looping.
487 timespec sleep_time;
488 sleep_time.tv_sec = 0;
489 sleep_time.tv_nsec = 1000000;
490 nanosleep(&sleep_time, NULL);
491 }
492}
493
494static TestResult WaitChildProc(pid_t pid) {
495 pid_t result;
496 int exit_status;
497
498 while ((result = waitpid(pid, &exit_status, 0)) == -1) {
499 if (errno != EINTR) {
500 break;
501 }
502 }
503
504 TestResult test_result = TEST_SUCCESS;
505 if (result != pid || WEXITSTATUS(exit_status) != 0) {
506 test_result = TEST_FAILED;
507 }
508 return test_result;
509}
510
511// We choose to use multi-fork and multi-wait here instead of multi-thread, because it always
512// makes deadlock to use fork in multi-thread.
513static void RunTestInSeparateProc(int argc, char** argv, std::vector<TestCase>& testcase_list,
514 int num_iterations, int num_jobs) {
515 // Stop default result printer to avoid environment setup/teardown information for each test.
516 testing::UnitTest::GetInstance()->listeners().Release(
517 testing::UnitTest::GetInstance()->listeners().default_result_printer());
518 testing::UnitTest::GetInstance()->listeners().Append(new TestResultPrinter);
519
520 for (int iteration = 1; iteration <= num_iterations; ++iteration) {
521 OnTestIterationStartPrint(testcase_list, iteration, num_iterations);
522 int64_t iteration_start_time = NanoTime();
523
524 std::vector<ChildProcInfo> child_proc_list(num_jobs);
525 int assign_testcase = 0, assign_test = 0;
526 std::vector<int> finish_test_num_list(testcase_list.size(), 0);
527 int num_finish_testcases = 0;
528
529 while (num_finish_testcases < static_cast<int>(testcase_list.size())) {
530 // Fork child process up to num_jobs.
531 for (auto& child_proc : child_proc_list) {
532 if (child_proc.pid == 0 && assign_testcase < static_cast<int>(testcase_list.size())) {
533 std::string test_name = testcase_list[assign_testcase].GetTestName(assign_test);
534 pid_t pid = fork();
535 if (pid == -1) {
536 perror("fork in RunTestInSeparateProc");
537 exit(1);
538 } else if (pid == 0) {
539 // Run child process test, never return.
540 ChildProcessFn(argc, argv, test_name);
541 }
542 // Parent process
543 child_proc.pid = pid;
544 child_proc.start_time = NanoTime();
545 child_proc.deadline_time = child_proc.start_time + GetDeadlineInfo(test_name) * 1000000LL;
546 child_proc.testcase_id = assign_testcase;
547 child_proc.test_id = assign_test;
548 child_proc.done_flag = false;
549 if (++assign_test == testcase_list[assign_testcase].NumTests()) {
550 assign_test = 0;
551 ++assign_testcase;
552 }
553 }
554 }
555
556 // Wait for any child proc finish or timeout.
557 WaitChildProcs(child_proc_list);
558
559 // Collect result.
560 for (auto& child_proc : child_proc_list) {
561 if (child_proc.pid != 0 && child_proc.done_flag == true) {
562 int testcase_id = child_proc.testcase_id;
563 int test_id = child_proc.test_id;
564 TestResult test_result = child_proc.test_result;
565 if (test_result == TEST_TIMEOUT) {
566 // Kill and wait the child process.
567 kill(child_proc.pid, SIGKILL);
568 WaitChildProc(child_proc.pid);
569 }
570 TestCase& testcase = testcase_list[testcase_id];
571 testcase.SetTestResult(test_id, test_result);
572 testcase.SetTestTime(test_id, NanoTime() - child_proc.start_time);
573 if (test_result == TEST_TIMEOUT) {
574 OnTestTimeoutPrint(testcase, test_id);
575 }
576 if (++finish_test_num_list[testcase_id] == testcase.NumTests()) {
577 ++num_finish_testcases;
578 }
579 child_proc.pid = 0;
580 child_proc.done_flag = false;
581 }
582 }
583 }
584
585 OnTestIterationEndPrint(testcase_list, iteration, NanoTime() - iteration_start_time);
586 }
587}
588
589static int GetCpuNumber() {
590 FILE* fp = popen("cat /proc/cpuinfo | grep processor | wc -l", "r");
591 int result = 1; // Return 1 if we can't get the exact cpu number.
592 if (fp != NULL) {
593 fscanf(fp, "%d", &result);
594 if (result < 1) {
595 result = 1;
596 }
597 pclose(fp);
598 }
599 return result;
600}
601
602// Pick options not for gtest; Return false if run error.
603// Use exit_flag to indicate whether we need to run gtest flow after PickOptions.
604static bool PickOptions(int* pargc, char*** pargv, bool* exit_flag) {
605 int argc = *pargc;
606 char** argv = *pargv;
607 *exit_flag = false;
608 for (int i = 0; i < argc; ++i) {
609 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
610 PrintHelpInfo();
611 return true;
612 }
613 }
614
615 // Move --gtest_filter option to last, and add "-bionic_gtest*" to disable self test.
616 int gtest_filter_option_pos = 0;
617 for (int i = argc - 1; i >= 1; --i) {
618 if (strncmp(argv[i], "--gtest_filter=", sizeof("--gtest_filter=") - 1) == 0) {
619 gtest_filter_option_pos = i;
620 break;
621 }
622 }
623 if (gtest_filter_option_pos != 0) {
624 char* gtest_filter_arg = argv[gtest_filter_option_pos];
625 for (int i = gtest_filter_option_pos; i < argc - 1; ++i) {
626 argv[i] = argv[i + 1];
627 }
628 char* new_arg = new char[strlen(gtest_filter_arg) + sizeof(":-bionic_gtest*")];
629 strcpy(new_arg, gtest_filter_arg);
630 strcat(new_arg, ":-bionic_gtest*");
631 argv[argc - 1] = new_arg;
632 } else {
633 char** new_argv = new char* [argc + 1];
634 for (int i = 0; i < argc; ++i) {
635 new_argv[i] = argv[i];
636 }
637 new_argv[argc++] = const_cast<char*>("--gtest_filter=-bionic_gtest*");
638 *pargv = argv = new_argv;
639 }
640
641 // Parse bionic_gtest specific options.
642 bool isolate_option = false;
643 int job_num_option = 1;
644
645 int deadline_option_len = sizeof("--deadline=") - 1;
646 int warnline_option_len = sizeof("--warnline=") - 1;
647 int gtest_color_option_len = sizeof("--gtest_color=") - 1;
648
649 for (int i = 1; i < argc; ++i) {
650 int remove_arg_num = 0;
651
652 // If running in isolation mode, main process doesn't call testing::InitGoogleTest(&argc, argv).
653 // So we should parse gtest options for printing here.
654 if (strncmp(argv[i], "--gtest_color=", gtest_color_option_len) == 0) {
655 testing::GTEST_FLAG(color) = argv[i] + gtest_color_option_len;
656
657 } else if (strcmp(argv[i], "--gtest_print_time=0") == 0) {
658 testing::GTEST_FLAG(print_time) = false;
659
660 } else if (strcmp(argv[i], "--isolate") == 0) {
661 isolate_option = true;
662 remove_arg_num = 1;
663
664 } else if (strncmp(argv[i], "--deadline=", deadline_option_len) == 0) {
665 global_test_run_deadline_in_ms = atoi(argv[i] + deadline_option_len);
666 if (global_test_run_deadline_in_ms <= 0) {
667 fprintf(stderr, "value for --deadline option should be positive: %s\n",
668 argv[i] + deadline_option_len);
669 exit(1);
670 }
671 remove_arg_num = 1;
672
673 } else if (strncmp(argv[i], "--warnline=", warnline_option_len) == 0) {
674 global_test_run_warnline_in_ms = atoi(argv[i] + warnline_option_len);
675 if (global_test_run_warnline_in_ms <= 0) {
676 fprintf(stderr, "value for --warnline option should be positive: %s\n",
677 argv[i] + warnline_option_len);
678 exit(1);
679 }
680 remove_arg_num = 1;
681
682 } else if (strcmp(argv[i], "--bionic_gtest") == 0) {
683 // Enable "bionic_gtest*" for self test.
684 // Don't remove this option from argument list.
685 argv[argc - 1] = const_cast<char*>("--gtest_filter=bionic_gtest*");
686
687 } else if (strcmp(argv[i], "-j") == 0) {
688 isolate_option = true; // Enable isolation mode when -j is used.
689 if (i + 1 < argc && (job_num_option = atoi(argv[i + 1])) > 0) {
690 remove_arg_num = 2;
691 } else {
692 job_num_option = GetCpuNumber();
693 remove_arg_num = 1;
694 }
695 }
696
697 if (remove_arg_num != 0) {
698 for (int j = i; j < argc - remove_arg_num; ++j) {
699 argv[j] = argv[j + remove_arg_num];
700 }
701 argc -= remove_arg_num;
702 --i;
703 }
704 }
705
706 // Handle --gtest_repeat=[COUNT] option if we are in isolation mode.
707 // We should check and remove this option to avoid child process running single test for several
708 // iterations.
709 int gtest_repeat_num = 1;
710 if (isolate_option == true) {
711 int len = sizeof("--gtest_repeat=") - 1;
712 for (int i = 1; i < argc; ++i) {
713 if (strncmp(argv[i], "--gtest_repeat=", len) == 0) {
714 gtest_repeat_num = atoi(argv[i] + len);
715 if (gtest_repeat_num < 0) {
716 fprintf(stderr, "error count for option --gtest_repeat=[COUNT]\n");
717 return false;
718 }
719 for (int j = i; j < argc - 1; ++j) {
720 argv[j] = argv[j + 1];
721 }
722 --argc;
723 break;
724 }
725 }
726 }
727
728 *pargc = argc;
729
730 // Run tests in isolation mode.
731 if (isolate_option) {
732 *exit_flag = true;
733
734 std::vector<TestCase> testcase_list;
735 if (EnumerateTests(argc, argv, testcase_list) == false) {
736 return false;
737 }
738 RunTestInSeparateProc(argc, argv, testcase_list, gtest_repeat_num, job_num_option);
739 return true;
740 }
741 return true;
742}
743
744int main(int argc, char** argv) {
745 bool exit_flag;
746 int return_result = 0;
747
748 if (PickOptions(&argc, &argv, &exit_flag) == false) {
749 return_result = 1;
750 } else if (!exit_flag) {
751 testing::InitGoogleTest(&argc, argv);
752 return_result = RUN_ALL_TESTS();
753 }
754 return return_result;
755}
756
757//################################################################################
758// Bionic Gtest self test, run this by --bionic_gtest --isolate option.
759
760TEST(bionic_gtest, test_success) {
761 ASSERT_EQ(1, 1);
762}
763
764TEST(bionic_gtest, test_fail) {
765 ASSERT_EQ(0, 1);
766}
767
768TEST(bionic_gtest, test_time_warn) {
769 sleep(4);
770}
771
772TEST(bionic_gtest, test_timeout) {
773 while (1) {}
774}