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