blob: a08a2e1543c0cad1ec0cdce9c89f725d42b94755 [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
Yabin Cuiead08142015-02-04 20:53:56 -080019#include <ctype.h>
Yabin Cui294d1e22014-12-07 20:43:37 -080020#include <errno.h>
Yabin Cui657b1f92015-01-22 19:26:12 -080021#include <fcntl.h>
22#include <inttypes.h>
Yabin Cuiead08142015-02-04 20:53:56 -080023#include <limits.h>
Yabin Cui1d4c7802015-02-02 19:14:05 -080024#include <signal.h>
Yabin Cui294d1e22014-12-07 20:43:37 -080025#include <stdarg.h>
26#include <stdio.h>
27#include <string.h>
28#include <sys/wait.h>
Yabin Cui294d1e22014-12-07 20:43:37 -080029#include <unistd.h>
30
Yabin Cui767fb1c2015-09-01 15:06:39 -070031#include <chrono>
Yabin Cui294d1e22014-12-07 20:43:37 -080032#include <string>
33#include <tuple>
34#include <utility>
35#include <vector>
36
Yabin Cui767fb1c2015-09-01 15:06:39 -070037#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
Yabin Cui657b1f92015-01-22 19:26:12 -080048
Dimitry Ivanov2ba1cf32016-05-17 13:29:37 -070049static std::string g_executable_path;
Dimitry Ivanov55437462016-07-20 15:33:07 -070050static int g_argc;
51static char** g_argv;
52static char** g_envp;
Dimitry Ivanovd17a3772016-03-01 13:11:28 -080053
Dimitry Ivanov2ba1cf32016-05-17 13:29:37 -070054const std::string& get_executable_path() {
55 return g_executable_path;
Dimitry Ivanovd17a3772016-03-01 13:11:28 -080056}
57
Dimitry Ivanov55437462016-07-20 15:33:07 -070058int get_argc() {
59 return g_argc;
60}
61
62char** get_argv() {
63 return g_argv;
64}
65
66char** get_envp() {
67 return g_envp;
68}
69
Yabin Cui294d1e22014-12-07 20:43:37 -080070namespace testing {
71namespace internal {
72
73// Reuse of testing::internal::ColoredPrintf in gtest.
74enum GTestColor {
75 COLOR_DEFAULT,
76 COLOR_RED,
77 COLOR_GREEN,
78 COLOR_YELLOW
79};
80
81void ColoredPrintf(GTestColor color, const char* fmt, ...);
82
Yabin Cuibe837362015-01-02 18:45:37 -080083} // namespace internal
84} // namespace testing
Yabin Cui294d1e22014-12-07 20:43:37 -080085
86using testing::internal::GTestColor;
87using testing::internal::COLOR_DEFAULT;
88using testing::internal::COLOR_RED;
89using testing::internal::COLOR_GREEN;
90using testing::internal::COLOR_YELLOW;
91using testing::internal::ColoredPrintf;
92
Christopher Ferrisdaaaed12015-09-24 18:45:53 -070093constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS = 90000;
Yabin Cui657b1f92015-01-22 19:26:12 -080094constexpr int DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS = 2000;
Yabin Cui294d1e22014-12-07 20:43:37 -080095
96// The time each test can run before killed for the reason of timeout.
97// It takes effect only with --isolate option.
Yabin Cui657b1f92015-01-22 19:26:12 -080098static int global_test_run_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
Yabin Cui294d1e22014-12-07 20:43:37 -080099
100// The time each test can run before be warned for too much running time.
101// It takes effect only with --isolate option.
Yabin Cui657b1f92015-01-22 19:26:12 -0800102static int global_test_run_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
Yabin Cui294d1e22014-12-07 20:43:37 -0800103
104// Return deadline duration for a test, in ms.
105static int GetDeadlineInfo(const std::string& /*test_name*/) {
Yabin Cui657b1f92015-01-22 19:26:12 -0800106 return global_test_run_deadline_ms;
Yabin Cui294d1e22014-12-07 20:43:37 -0800107}
108
109// Return warnline duration for a test, in ms.
110static int GetWarnlineInfo(const std::string& /*test_name*/) {
Yabin Cui657b1f92015-01-22 19:26:12 -0800111 return global_test_run_warnline_ms;
Yabin Cui294d1e22014-12-07 20:43:37 -0800112}
113
Yabin Cuibe837362015-01-02 18:45:37 -0800114static void PrintHelpInfo() {
115 printf("Bionic Unit Test Options:\n"
Yabin Cui657b1f92015-01-22 19:26:12 -0800116 " -j [JOB_COUNT] or -j[JOB_COUNT]\n"
Yabin Cuibe837362015-01-02 18:45:37 -0800117 " 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 processors.\n"
120 " --no-isolate\n"
121 " Don't use isolation mode, run all tests in a single process.\n"
122 " --deadline=[TIME_IN_MS]\n"
123 " Run each test in no longer than [TIME_IN_MS] time.\n"
Yabin Cuibc6379d2015-10-06 16:30:14 -0700124 " It takes effect only in isolation mode. Deafult deadline is 90000 ms.\n"
Yabin Cuibe837362015-01-02 18:45:37 -0800125 " --warnline=[TIME_IN_MS]\n"
126 " Test running longer than [TIME_IN_MS] will be warned.\n"
127 " It takes effect only in isolation mode. Default warnline is 2000 ms.\n"
Yabin Cui11c43532015-01-28 14:28:14 -0800128 " --gtest-filter=POSITIVE_PATTERNS[-NEGATIVE_PATTERNS]\n"
129 " Used as a synonym for --gtest_filter option in gtest.\n"
Yabin Cui1d4c7802015-02-02 19:14:05 -0800130 "Default bionic unit test option is -j.\n"
131 "In isolation mode, you can send SIGQUIT to the parent process to show current\n"
132 "running tests, or send SIGINT to the parent process to stop testing and\n"
133 "clean up current running tests.\n"
Yabin Cuibe837362015-01-02 18:45:37 -0800134 "\n");
135}
136
Yabin Cui294d1e22014-12-07 20:43:37 -0800137enum TestResult {
138 TEST_SUCCESS = 0,
139 TEST_FAILED,
140 TEST_TIMEOUT
141};
142
Yabin Cui657b1f92015-01-22 19:26:12 -0800143class Test {
144 public:
145 Test() {} // For std::vector<Test>.
146 explicit Test(const char* name) : name_(name) {}
147
148 const std::string& GetName() const { return name_; }
149
150 void SetResult(TestResult result) { result_ = result; }
151
152 TestResult GetResult() const { return result_; }
153
154 void SetTestTime(int64_t elapsed_time_ns) { elapsed_time_ns_ = elapsed_time_ns; }
155
156 int64_t GetTestTime() const { return elapsed_time_ns_; }
157
Yabin Cuiea9c9332015-02-24 14:39:19 -0800158 void AppendTestOutput(const std::string& s) { output_ += s; }
Yabin Cui657b1f92015-01-22 19:26:12 -0800159
Yabin Cuiea9c9332015-02-24 14:39:19 -0800160 const std::string& GetTestOutput() const { return output_; }
Yabin Cui657b1f92015-01-22 19:26:12 -0800161
162 private:
163 const std::string name_;
164 TestResult result_;
165 int64_t elapsed_time_ns_;
Yabin Cuiea9c9332015-02-24 14:39:19 -0800166 std::string output_;
Yabin Cui657b1f92015-01-22 19:26:12 -0800167};
168
Yabin Cui294d1e22014-12-07 20:43:37 -0800169class TestCase {
170 public:
171 TestCase() {} // For std::vector<TestCase>.
172 explicit TestCase(const char* name) : name_(name) {}
173
174 const std::string& GetName() const { return name_; }
175
Yabin Cui657b1f92015-01-22 19:26:12 -0800176 void AppendTest(const char* test_name) {
177 test_list_.push_back(Test(test_name));
Yabin Cui294d1e22014-12-07 20:43:37 -0800178 }
179
Yabin Cuibe837362015-01-02 18:45:37 -0800180 size_t TestCount() const { return test_list_.size(); }
Yabin Cui294d1e22014-12-07 20:43:37 -0800181
Yabin Cuibe837362015-01-02 18:45:37 -0800182 std::string GetTestName(size_t test_id) const {
Yabin Cui294d1e22014-12-07 20:43:37 -0800183 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800184 return name_ + "." + test_list_[test_id].GetName();
185 }
186
187 Test& GetTest(size_t test_id) {
188 VerifyTestId(test_id);
189 return test_list_[test_id];
190 }
191
192 const Test& GetTest(size_t test_id) const {
193 VerifyTestId(test_id);
194 return test_list_[test_id];
Yabin Cui294d1e22014-12-07 20:43:37 -0800195 }
196
Yabin Cuibe837362015-01-02 18:45:37 -0800197 void SetTestResult(size_t test_id, TestResult result) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800198 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800199 test_list_[test_id].SetResult(result);
Yabin Cui294d1e22014-12-07 20:43:37 -0800200 }
201
Yabin Cuibe837362015-01-02 18:45:37 -0800202 TestResult GetTestResult(size_t test_id) const {
Yabin Cui294d1e22014-12-07 20:43:37 -0800203 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800204 return test_list_[test_id].GetResult();
Yabin Cui294d1e22014-12-07 20:43:37 -0800205 }
206
Yabin Cui657b1f92015-01-22 19:26:12 -0800207 void SetTestTime(size_t test_id, int64_t elapsed_time_ns) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800208 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800209 test_list_[test_id].SetTestTime(elapsed_time_ns);
Yabin Cui294d1e22014-12-07 20:43:37 -0800210 }
211
Yabin Cuibe837362015-01-02 18:45:37 -0800212 int64_t GetTestTime(size_t test_id) const {
Yabin Cui294d1e22014-12-07 20:43:37 -0800213 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800214 return test_list_[test_id].GetTestTime();
Yabin Cui294d1e22014-12-07 20:43:37 -0800215 }
216
217 private:
Yabin Cuibe837362015-01-02 18:45:37 -0800218 void VerifyTestId(size_t test_id) const {
219 if(test_id >= test_list_.size()) {
220 fprintf(stderr, "test_id %zu out of range [0, %zu)\n", test_id, test_list_.size());
Yabin Cui294d1e22014-12-07 20:43:37 -0800221 exit(1);
222 }
223 }
224
225 private:
226 const std::string name_;
Yabin Cui657b1f92015-01-22 19:26:12 -0800227 std::vector<Test> test_list_;
Yabin Cui294d1e22014-12-07 20:43:37 -0800228};
229
Yabin Cui294d1e22014-12-07 20:43:37 -0800230class TestResultPrinter : public testing::EmptyTestEventListener {
231 public:
232 TestResultPrinter() : pinfo_(NULL) {}
233 virtual void OnTestStart(const testing::TestInfo& test_info) {
234 pinfo_ = &test_info; // Record test_info for use in OnTestPartResult.
235 }
236 virtual void OnTestPartResult(const testing::TestPartResult& result);
Yabin Cui294d1e22014-12-07 20:43:37 -0800237
238 private:
239 const testing::TestInfo* pinfo_;
240};
241
242// Called after an assertion failure.
243void TestResultPrinter::OnTestPartResult(const testing::TestPartResult& result) {
244 // If the test part succeeded, we don't need to do anything.
245 if (result.type() == testing::TestPartResult::kSuccess)
246 return;
247
248 // Print failure message from the assertion (e.g. expected this and got that).
Yabin Cuiea9c9332015-02-24 14:39:19 -0800249 printf("%s:(%d) Failure in test %s.%s\n%s\n", result.file_name(), result.line_number(),
250 pinfo_->test_case_name(), pinfo_->name(), result.message());
251 fflush(stdout);
Yabin Cui294d1e22014-12-07 20:43:37 -0800252}
253
Yabin Cui294d1e22014-12-07 20:43:37 -0800254static int64_t NanoTime() {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700255 std::chrono::nanoseconds duration(std::chrono::steady_clock::now().time_since_epoch());
256 return static_cast<int64_t>(duration.count());
Yabin Cui294d1e22014-12-07 20:43:37 -0800257}
258
259static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcase_list) {
260 std::string command;
261 for (int i = 0; i < argc; ++i) {
262 command += argv[i];
263 command += " ";
264 }
265 command += "--gtest_list_tests";
266 FILE* fp = popen(command.c_str(), "r");
267 if (fp == NULL) {
268 perror("popen");
269 return false;
270 }
271
272 char buf[200];
273 while (fgets(buf, sizeof(buf), fp) != NULL) {
274 char* p = buf;
275
276 while (*p != '\0' && isspace(*p)) {
277 ++p;
278 }
279 if (*p == '\0') continue;
280 char* start = p;
281 while (*p != '\0' && !isspace(*p)) {
282 ++p;
283 }
284 char* end = p;
285 while (*p != '\0' && isspace(*p)) {
286 ++p;
287 }
Yabin Cuibf830ad2015-08-10 12:12:39 -0700288 if (*p != '\0' && *p != '#') {
Yabin Cui294d1e22014-12-07 20:43:37 -0800289 // This is not we want, gtest must meet with some error when parsing the arguments.
290 fprintf(stderr, "argument error, check with --help\n");
291 return false;
292 }
293 *end = '\0';
294 if (*(end - 1) == '.') {
295 *(end - 1) = '\0';
296 testcase_list.push_back(TestCase(start));
297 } else {
298 testcase_list.back().AppendTest(start);
299 }
300 }
301 int result = pclose(fp);
302 return (result != -1 && WEXITSTATUS(result) == 0);
303}
304
Yabin Cui294d1e22014-12-07 20:43:37 -0800305// Part of the following *Print functions are copied from external/gtest/src/gtest.cc:
306// PrettyUnitTestResultPrinter. The reason for copy is that PrettyUnitTestResultPrinter
307// is defined and used in gtest.cc, which is hard to reuse.
Yabin Cuibe837362015-01-02 18:45:37 -0800308static void OnTestIterationStartPrint(const std::vector<TestCase>& testcase_list, size_t iteration,
Christopher Ferris119cb552015-04-02 12:02:55 -0700309 int iteration_count) {
310 if (iteration_count != 1) {
Yabin Cuibe837362015-01-02 18:45:37 -0800311 printf("\nRepeating all tests (iteration %zu) . . .\n\n", iteration);
Yabin Cui294d1e22014-12-07 20:43:37 -0800312 }
313 ColoredPrintf(COLOR_GREEN, "[==========] ");
314
Yabin Cuibe837362015-01-02 18:45:37 -0800315 size_t testcase_count = testcase_list.size();
316 size_t test_count = 0;
Yabin Cui294d1e22014-12-07 20:43:37 -0800317 for (const auto& testcase : testcase_list) {
Yabin Cuibe837362015-01-02 18:45:37 -0800318 test_count += testcase.TestCount();
Yabin Cui294d1e22014-12-07 20:43:37 -0800319 }
320
Yabin Cuibe837362015-01-02 18:45:37 -0800321 printf("Running %zu %s from %zu %s.\n",
322 test_count, (test_count == 1) ? "test" : "tests",
323 testcase_count, (testcase_count == 1) ? "test case" : "test cases");
Yabin Cui294d1e22014-12-07 20:43:37 -0800324 fflush(stdout);
325}
326
Yabin Cuif6237472015-02-26 19:03:54 -0800327// bionic cts test needs gtest output format.
328#if defined(USING_GTEST_OUTPUT_FORMAT)
329
330static void OnTestEndPrint(const TestCase& testcase, size_t test_id) {
331 ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
332 printf("%s\n", testcase.GetTestName(test_id).c_str());
333
334 const std::string& test_output = testcase.GetTest(test_id).GetTestOutput();
335 printf("%s", test_output.c_str());
336
337 TestResult result = testcase.GetTestResult(test_id);
338 if (result == TEST_SUCCESS) {
339 ColoredPrintf(COLOR_GREEN, "[ OK ] ");
340 } else {
341 ColoredPrintf(COLOR_RED, "[ FAILED ] ");
342 }
343 printf("%s", testcase.GetTestName(test_id).c_str());
344 if (testing::GTEST_FLAG(print_time)) {
345 printf(" (%" PRId64 " ms)", testcase.GetTestTime(test_id) / 1000000);
346 }
347 printf("\n");
348 fflush(stdout);
349}
350
351#else // !defined(USING_GTEST_OUTPUT_FORMAT)
352
Yabin Cui657b1f92015-01-22 19:26:12 -0800353static void OnTestEndPrint(const TestCase& testcase, size_t test_id) {
354 TestResult result = testcase.GetTestResult(test_id);
355 if (result == TEST_SUCCESS) {
356 ColoredPrintf(COLOR_GREEN, "[ OK ] ");
357 } else if (result == TEST_FAILED) {
358 ColoredPrintf(COLOR_RED, "[ FAILED ] ");
359 } else if (result == TEST_TIMEOUT) {
360 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
361 }
Yabin Cuibe837362015-01-02 18:45:37 -0800362
Yabin Cui657b1f92015-01-22 19:26:12 -0800363 printf("%s", testcase.GetTestName(test_id).c_str());
364 if (testing::GTEST_FLAG(print_time)) {
Yabin Cuif6237472015-02-26 19:03:54 -0800365 printf(" (%" PRId64 " ms)", testcase.GetTestTime(test_id) / 1000000);
Yabin Cui657b1f92015-01-22 19:26:12 -0800366 }
Yabin Cuif6237472015-02-26 19:03:54 -0800367 printf("\n");
Yabin Cui657b1f92015-01-22 19:26:12 -0800368
Yabin Cuiea9c9332015-02-24 14:39:19 -0800369 const std::string& test_output = testcase.GetTest(test_id).GetTestOutput();
370 printf("%s", test_output.c_str());
Yabin Cui294d1e22014-12-07 20:43:37 -0800371 fflush(stdout);
372}
373
Yabin Cuif6237472015-02-26 19:03:54 -0800374#endif // !defined(USING_GTEST_OUTPUT_FORMAT)
375
Yabin Cuibe837362015-01-02 18:45:37 -0800376static void OnTestIterationEndPrint(const std::vector<TestCase>& testcase_list, size_t /*iteration*/,
Yabin Cui657b1f92015-01-22 19:26:12 -0800377 int64_t elapsed_time_ns) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800378
379 std::vector<std::string> fail_test_name_list;
380 std::vector<std::pair<std::string, int64_t>> timeout_test_list;
381
382 // For tests run exceed warnline but not timeout.
Yabin Cui4a82ede2015-01-26 17:19:37 -0800383 std::vector<std::tuple<std::string, int64_t, int>> slow_test_list;
Yabin Cuibe837362015-01-02 18:45:37 -0800384 size_t testcase_count = testcase_list.size();
385 size_t test_count = 0;
386 size_t success_test_count = 0;
Yabin Cui294d1e22014-12-07 20:43:37 -0800387
388 for (const auto& testcase : testcase_list) {
Yabin Cuibe837362015-01-02 18:45:37 -0800389 test_count += testcase.TestCount();
390 for (size_t i = 0; i < testcase.TestCount(); ++i) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800391 TestResult result = testcase.GetTestResult(i);
392 if (result == TEST_SUCCESS) {
Yabin Cuibe837362015-01-02 18:45:37 -0800393 ++success_test_count;
Yabin Cui294d1e22014-12-07 20:43:37 -0800394 } else if (result == TEST_FAILED) {
395 fail_test_name_list.push_back(testcase.GetTestName(i));
396 } else if (result == TEST_TIMEOUT) {
397 timeout_test_list.push_back(std::make_pair(testcase.GetTestName(i),
398 testcase.GetTestTime(i)));
399 }
400 if (result != TEST_TIMEOUT &&
401 testcase.GetTestTime(i) / 1000000 >= GetWarnlineInfo(testcase.GetTestName(i))) {
Yabin Cui4a82ede2015-01-26 17:19:37 -0800402 slow_test_list.push_back(std::make_tuple(testcase.GetTestName(i),
403 testcase.GetTestTime(i),
404 GetWarnlineInfo(testcase.GetTestName(i))));
Yabin Cui294d1e22014-12-07 20:43:37 -0800405 }
406 }
407 }
408
Yabin Cui294d1e22014-12-07 20:43:37 -0800409 ColoredPrintf(COLOR_GREEN, "[==========] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800410 printf("%zu %s from %zu %s ran.", test_count, (test_count == 1) ? "test" : "tests",
411 testcase_count, (testcase_count == 1) ? "test case" : "test cases");
Yabin Cui294d1e22014-12-07 20:43:37 -0800412 if (testing::GTEST_FLAG(print_time)) {
Yabin Cui657b1f92015-01-22 19:26:12 -0800413 printf(" (%" PRId64 " ms total)", elapsed_time_ns / 1000000);
Yabin Cui294d1e22014-12-07 20:43:37 -0800414 }
415 printf("\n");
Yabin Cui4a82ede2015-01-26 17:19:37 -0800416 ColoredPrintf(COLOR_GREEN, "[ PASS ] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800417 printf("%zu %s.\n", success_test_count, (success_test_count == 1) ? "test" : "tests");
Yabin Cui294d1e22014-12-07 20:43:37 -0800418
419 // Print tests failed.
Yabin Cuibe837362015-01-02 18:45:37 -0800420 size_t fail_test_count = fail_test_name_list.size();
421 if (fail_test_count > 0) {
Yabin Cui4a82ede2015-01-26 17:19:37 -0800422 ColoredPrintf(COLOR_RED, "[ FAIL ] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800423 printf("%zu %s, listed below:\n", fail_test_count, (fail_test_count == 1) ? "test" : "tests");
Yabin Cui294d1e22014-12-07 20:43:37 -0800424 for (const auto& name : fail_test_name_list) {
Yabin Cui4a82ede2015-01-26 17:19:37 -0800425 ColoredPrintf(COLOR_RED, "[ FAIL ] ");
Yabin Cui294d1e22014-12-07 20:43:37 -0800426 printf("%s\n", name.c_str());
427 }
428 }
429
430 // Print tests run timeout.
Yabin Cuibe837362015-01-02 18:45:37 -0800431 size_t timeout_test_count = timeout_test_list.size();
432 if (timeout_test_count > 0) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800433 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800434 printf("%zu %s, listed below:\n", timeout_test_count, (timeout_test_count == 1) ? "test" : "tests");
Yabin Cui294d1e22014-12-07 20:43:37 -0800435 for (const auto& timeout_pair : timeout_test_list) {
436 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
Yabin Cui657b1f92015-01-22 19:26:12 -0800437 printf("%s (stopped at %" PRId64 " ms)\n", timeout_pair.first.c_str(),
438 timeout_pair.second / 1000000);
Yabin Cui294d1e22014-12-07 20:43:37 -0800439 }
440 }
441
442 // Print tests run exceed warnline.
Yabin Cui4a82ede2015-01-26 17:19:37 -0800443 size_t slow_test_count = slow_test_list.size();
444 if (slow_test_count > 0) {
445 ColoredPrintf(COLOR_YELLOW, "[ SLOW ] ");
446 printf("%zu %s, listed below:\n", slow_test_count, (slow_test_count == 1) ? "test" : "tests");
447 for (const auto& slow_tuple : slow_test_list) {
448 ColoredPrintf(COLOR_YELLOW, "[ SLOW ] ");
449 printf("%s (%" PRId64 " ms, exceed warnline %d ms)\n", std::get<0>(slow_tuple).c_str(),
450 std::get<1>(slow_tuple) / 1000000, std::get<2>(slow_tuple));
Yabin Cui294d1e22014-12-07 20:43:37 -0800451 }
452 }
453
Yabin Cuibe837362015-01-02 18:45:37 -0800454 if (fail_test_count > 0) {
455 printf("\n%2zu FAILED %s\n", fail_test_count, (fail_test_count == 1) ? "TEST" : "TESTS");
Yabin Cui294d1e22014-12-07 20:43:37 -0800456 }
Yabin Cuibe837362015-01-02 18:45:37 -0800457 if (timeout_test_count > 0) {
458 printf("%2zu TIMEOUT %s\n", timeout_test_count, (timeout_test_count == 1) ? "TEST" : "TESTS");
Yabin Cui294d1e22014-12-07 20:43:37 -0800459 }
Yabin Cui4a82ede2015-01-26 17:19:37 -0800460 if (slow_test_count > 0) {
461 printf("%2zu SLOW %s\n", slow_test_count, (slow_test_count == 1) ? "TEST" : "TESTS");
Yabin Cui294d1e22014-12-07 20:43:37 -0800462 }
463 fflush(stdout);
464}
465
Dan Albert09a99642016-01-13 21:48:56 -0800466std::string XmlEscape(const std::string& xml) {
467 std::string escaped;
468 escaped.reserve(xml.size());
469
470 for (auto c : xml) {
471 switch (c) {
472 case '<':
473 escaped.append("&lt;");
474 break;
475 case '>':
476 escaped.append("&gt;");
477 break;
478 case '&':
479 escaped.append("&amp;");
480 break;
481 case '\'':
482 escaped.append("&apos;");
483 break;
484 case '"':
485 escaped.append("&quot;");
486 break;
487 default:
488 escaped.append(1, c);
489 break;
490 }
491 }
492
493 return escaped;
494}
495
Yabin Cui657b1f92015-01-22 19:26:12 -0800496// Output xml file when --gtest_output is used, write this function as we can't reuse
497// gtest.cc:XmlUnitTestResultPrinter. The reason is XmlUnitTestResultPrinter is totally
498// defined in gtest.cc and not expose to outside. What's more, as we don't run gtest in
499// the parent process, we don't have gtest classes which are needed by XmlUnitTestResultPrinter.
500void OnTestIterationEndXmlPrint(const std::string& xml_output_filename,
501 const std::vector<TestCase>& testcase_list,
502 time_t epoch_iteration_start_time,
503 int64_t elapsed_time_ns) {
504 FILE* fp = fopen(xml_output_filename.c_str(), "w");
505 if (fp == NULL) {
506 fprintf(stderr, "failed to open '%s': %s\n", xml_output_filename.c_str(), strerror(errno));
507 exit(1);
508 }
509
510 size_t total_test_count = 0;
511 size_t total_failed_count = 0;
512 std::vector<size_t> failed_count_list(testcase_list.size(), 0);
513 std::vector<int64_t> elapsed_time_list(testcase_list.size(), 0);
514 for (size_t i = 0; i < testcase_list.size(); ++i) {
515 auto& testcase = testcase_list[i];
516 total_test_count += testcase.TestCount();
517 for (size_t j = 0; j < testcase.TestCount(); ++j) {
518 if (testcase.GetTestResult(j) != TEST_SUCCESS) {
519 ++failed_count_list[i];
520 }
521 elapsed_time_list[i] += testcase.GetTestTime(j);
522 }
523 total_failed_count += failed_count_list[i];
524 }
525
526 const tm* time_struct = localtime(&epoch_iteration_start_time);
527 char timestamp[40];
528 snprintf(timestamp, sizeof(timestamp), "%4d-%02d-%02dT%02d:%02d:%02d",
529 time_struct->tm_year + 1900, time_struct->tm_mon + 1, time_struct->tm_mday,
530 time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec);
531
532 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp);
533 fprintf(fp, "<testsuites tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
534 total_test_count, total_failed_count);
535 fprintf(fp, " timestamp=\"%s\" time=\"%.3lf\" name=\"AllTests\">\n", timestamp, elapsed_time_ns / 1e9);
536 for (size_t i = 0; i < testcase_list.size(); ++i) {
537 auto& testcase = testcase_list[i];
538 fprintf(fp, " <testsuite name=\"%s\" tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
539 testcase.GetName().c_str(), testcase.TestCount(), failed_count_list[i]);
540 fprintf(fp, " time=\"%.3lf\">\n", elapsed_time_list[i] / 1e9);
541
542 for (size_t j = 0; j < testcase.TestCount(); ++j) {
543 fprintf(fp, " <testcase name=\"%s\" status=\"run\" time=\"%.3lf\" classname=\"%s\"",
544 testcase.GetTest(j).GetName().c_str(), testcase.GetTestTime(j) / 1e9,
545 testcase.GetName().c_str());
546 if (testcase.GetTestResult(j) == TEST_SUCCESS) {
547 fputs(" />\n", fp);
548 } else {
549 fputs(">\n", fp);
Yabin Cuiea9c9332015-02-24 14:39:19 -0800550 const std::string& test_output = testcase.GetTest(j).GetTestOutput();
Dan Albert09a99642016-01-13 21:48:56 -0800551 const std::string escaped_test_output = XmlEscape(test_output);
552 fprintf(fp, " <failure message=\"%s\" type=\"\">\n", escaped_test_output.c_str());
Yabin Cui657b1f92015-01-22 19:26:12 -0800553 fputs(" </failure>\n", fp);
554 fputs(" </testcase>\n", fp);
555 }
556 }
557
558 fputs(" </testsuite>\n", fp);
559 }
560 fputs("</testsuites>\n", fp);
561 fclose(fp);
562}
563
Yabin Cui767fb1c2015-09-01 15:06:39 -0700564static bool sigint_flag;
565static bool sigquit_flag;
566
567static void signal_handler(int sig) {
568 if (sig == SIGINT) {
569 sigint_flag = true;
570 } else if (sig == SIGQUIT) {
571 sigquit_flag = true;
572 }
573}
574
575static bool RegisterSignalHandler() {
576 sigint_flag = false;
577 sigquit_flag = false;
578 sig_t ret = signal(SIGINT, signal_handler);
579 if (ret != SIG_ERR) {
580 ret = signal(SIGQUIT, signal_handler);
581 }
582 if (ret == SIG_ERR) {
583 perror("RegisterSignalHandler");
584 return false;
585 }
586 return true;
587}
588
589static bool UnregisterSignalHandler() {
590 sig_t ret = signal(SIGINT, SIG_DFL);
591 if (ret != SIG_ERR) {
592 ret = signal(SIGQUIT, SIG_DFL);
593 }
594 if (ret == SIG_ERR) {
595 perror("UnregisterSignalHandler");
596 return false;
597 }
598 return true;
599}
600
Yabin Cui1d4c7802015-02-02 19:14:05 -0800601struct ChildProcInfo {
602 pid_t pid;
603 int64_t start_time_ns;
604 int64_t end_time_ns;
605 int64_t deadline_end_time_ns; // The time when the test is thought of as timeout.
606 size_t testcase_id, test_id;
607 bool finished;
608 bool timed_out;
609 int exit_status;
610 int child_read_fd; // File descriptor to read child test failure info.
611};
612
Yabin Cui294d1e22014-12-07 20:43:37 -0800613// Forked Child process, run the single test.
614static void ChildProcessFn(int argc, char** argv, const std::string& test_name) {
Yabin Cui657b1f92015-01-22 19:26:12 -0800615 char** new_argv = new char*[argc + 2];
Yabin Cui294d1e22014-12-07 20:43:37 -0800616 memcpy(new_argv, argv, sizeof(char*) * argc);
617
618 char* filter_arg = new char [test_name.size() + 20];
619 strcpy(filter_arg, "--gtest_filter=");
620 strcat(filter_arg, test_name.c_str());
621 new_argv[argc] = filter_arg;
Yabin Cui657b1f92015-01-22 19:26:12 -0800622 new_argv[argc + 1] = NULL;
Yabin Cui294d1e22014-12-07 20:43:37 -0800623
624 int new_argc = argc + 1;
625 testing::InitGoogleTest(&new_argc, new_argv);
626 int result = RUN_ALL_TESTS();
627 exit(result);
628}
629
Yabin Cui1d4c7802015-02-02 19:14:05 -0800630static ChildProcInfo RunChildProcess(const std::string& test_name, int testcase_id, int test_id,
Yabin Cui767fb1c2015-09-01 15:06:39 -0700631 int argc, char** argv) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800632 int pipefd[2];
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800633 if (pipe(pipefd) == -1) {
634 perror("pipe in RunTestInSeparateProc");
635 exit(1);
636 }
637 if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1) {
638 perror("fcntl in RunTestInSeparateProc");
Yabin Cui1d4c7802015-02-02 19:14:05 -0800639 exit(1);
640 }
641 pid_t pid = fork();
642 if (pid == -1) {
643 perror("fork in RunTestInSeparateProc");
644 exit(1);
645 } else if (pid == 0) {
646 // In child process, run a single test.
647 close(pipefd[0]);
Yabin Cuiea9c9332015-02-24 14:39:19 -0800648 close(STDOUT_FILENO);
649 close(STDERR_FILENO);
650 dup2(pipefd[1], STDOUT_FILENO);
651 dup2(pipefd[1], STDERR_FILENO);
Yabin Cui294d1e22014-12-07 20:43:37 -0800652
Yabin Cui767fb1c2015-09-01 15:06:39 -0700653 if (!UnregisterSignalHandler()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800654 exit(1);
655 }
656 ChildProcessFn(argc, argv, test_name);
657 // Unreachable.
658 }
659 // In parent process, initialize child process info.
660 close(pipefd[1]);
661 ChildProcInfo child_proc;
662 child_proc.child_read_fd = pipefd[0];
663 child_proc.pid = pid;
664 child_proc.start_time_ns = NanoTime();
665 child_proc.deadline_end_time_ns = child_proc.start_time_ns + GetDeadlineInfo(test_name) * 1000000LL;
666 child_proc.testcase_id = testcase_id;
667 child_proc.test_id = test_id;
668 child_proc.finished = false;
669 return child_proc;
670}
Yabin Cui294d1e22014-12-07 20:43:37 -0800671
Yabin Cui1d4c7802015-02-02 19:14:05 -0800672static void HandleSignals(std::vector<TestCase>& testcase_list,
673 std::vector<ChildProcInfo>& child_proc_list) {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700674 if (sigquit_flag) {
675 sigquit_flag = false;
676 // Print current running tests.
677 printf("List of current running tests:\n");
Elliott Hughes0b2acdf2015-10-02 18:25:19 -0700678 for (const auto& child_proc : child_proc_list) {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700679 if (child_proc.pid != 0) {
680 std::string test_name = testcase_list[child_proc.testcase_id].GetTestName(child_proc.test_id);
681 int64_t current_time_ns = NanoTime();
682 int64_t run_time_ms = (current_time_ns - child_proc.start_time_ns) / 1000000;
683 printf(" %s (%" PRId64 " ms)\n", test_name.c_str(), run_time_ms);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800684 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800685 }
Yabin Cui767fb1c2015-09-01 15:06:39 -0700686 } else if (sigint_flag) {
687 sigint_flag = false;
688 // Kill current running tests.
Elliott Hughes0b2acdf2015-10-02 18:25:19 -0700689 for (const auto& child_proc : child_proc_list) {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700690 if (child_proc.pid != 0) {
691 // Send SIGKILL to ensure the child process can be killed unconditionally.
692 kill(child_proc.pid, SIGKILL);
693 }
694 }
695 // SIGINT kills the parent process as well.
696 exit(1);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800697 }
698}
699
700static bool CheckChildProcExit(pid_t exit_pid, int exit_status,
701 std::vector<ChildProcInfo>& child_proc_list) {
702 for (size_t i = 0; i < child_proc_list.size(); ++i) {
703 if (child_proc_list[i].pid == exit_pid) {
704 child_proc_list[i].finished = true;
705 child_proc_list[i].timed_out = false;
706 child_proc_list[i].exit_status = exit_status;
707 child_proc_list[i].end_time_ns = NanoTime();
708 return true;
709 }
710 }
711 return false;
712}
713
714static size_t CheckChildProcTimeout(std::vector<ChildProcInfo>& child_proc_list) {
715 int64_t current_time_ns = NanoTime();
716 size_t timeout_child_count = 0;
717 for (size_t i = 0; i < child_proc_list.size(); ++i) {
718 if (child_proc_list[i].deadline_end_time_ns <= current_time_ns) {
719 child_proc_list[i].finished = true;
720 child_proc_list[i].timed_out = true;
721 child_proc_list[i].end_time_ns = current_time_ns;
722 ++timeout_child_count;
723 }
724 }
725 return timeout_child_count;
726}
727
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800728static void ReadChildProcOutput(std::vector<TestCase>& testcase_list,
729 std::vector<ChildProcInfo>& child_proc_list) {
730 for (const auto& child_proc : child_proc_list) {
731 TestCase& testcase = testcase_list[child_proc.testcase_id];
732 int test_id = child_proc.test_id;
733 while (true) {
734 char buf[1024];
735 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(child_proc.child_read_fd, buf, sizeof(buf) - 1));
736 if (bytes_read > 0) {
737 buf[bytes_read] = '\0';
738 testcase.GetTest(test_id).AppendTestOutput(buf);
739 } else if (bytes_read == 0) {
740 break; // Read end.
741 } else {
742 if (errno == EAGAIN) {
743 break;
744 }
745 perror("failed to read child_read_fd");
746 exit(1);
747 }
748 }
749 }
750}
751
Yabin Cui1d4c7802015-02-02 19:14:05 -0800752static void WaitChildProcs(std::vector<TestCase>& testcase_list,
753 std::vector<ChildProcInfo>& child_proc_list) {
754 size_t finished_child_count = 0;
755 while (true) {
756 int status;
757 pid_t result;
758 while ((result = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) {
759 if (CheckChildProcExit(result, status, child_proc_list)) {
760 ++finished_child_count;
Yabin Cui294d1e22014-12-07 20:43:37 -0800761 }
762 }
763
764 if (result == -1) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800765 if (errno == ECHILD) {
766 // This happens when we have no running child processes.
767 return;
768 } else {
769 perror("waitpid");
770 exit(1);
771 }
Yabin Cui294d1e22014-12-07 20:43:37 -0800772 } else if (result == 0) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800773 finished_child_count += CheckChildProcTimeout(child_proc_list);
Yabin Cui294d1e22014-12-07 20:43:37 -0800774 }
775
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800776 ReadChildProcOutput(testcase_list, child_proc_list);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800777 if (finished_child_count > 0) {
778 return;
779 }
780
781 HandleSignals(testcase_list, child_proc_list);
782
Yabin Cui294d1e22014-12-07 20:43:37 -0800783 // sleep 1 ms to avoid busy looping.
784 timespec sleep_time;
785 sleep_time.tv_sec = 0;
786 sleep_time.tv_nsec = 1000000;
787 nanosleep(&sleep_time, NULL);
788 }
789}
790
Yabin Cui1d4c7802015-02-02 19:14:05 -0800791static TestResult WaitForOneChild(pid_t pid) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800792 int exit_status;
Yabin Cui1d4c7802015-02-02 19:14:05 -0800793 pid_t result = TEMP_FAILURE_RETRY(waitpid(pid, &exit_status, 0));
Yabin Cui294d1e22014-12-07 20:43:37 -0800794
795 TestResult test_result = TEST_SUCCESS;
796 if (result != pid || WEXITSTATUS(exit_status) != 0) {
797 test_result = TEST_FAILED;
798 }
799 return test_result;
800}
801
Yabin Cui1d4c7802015-02-02 19:14:05 -0800802static void CollectChildTestResult(const ChildProcInfo& child_proc, TestCase& testcase) {
803 int test_id = child_proc.test_id;
804 testcase.SetTestTime(test_id, child_proc.end_time_ns - child_proc.start_time_ns);
805 if (child_proc.timed_out) {
806 // The child process marked as timed_out has not exited, and we should kill it manually.
807 kill(child_proc.pid, SIGKILL);
808 WaitForOneChild(child_proc.pid);
809 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800810 close(child_proc.child_read_fd);
811
812 if (child_proc.timed_out) {
813 testcase.SetTestResult(test_id, TEST_TIMEOUT);
814 char buf[1024];
815 snprintf(buf, sizeof(buf), "%s killed because of timeout at %" PRId64 " ms.\n",
816 testcase.GetTestName(test_id).c_str(), testcase.GetTestTime(test_id) / 1000000);
Yabin Cuiea9c9332015-02-24 14:39:19 -0800817 testcase.GetTest(test_id).AppendTestOutput(buf);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800818
819 } else if (WIFSIGNALED(child_proc.exit_status)) {
820 // Record signal terminated test as failed.
821 testcase.SetTestResult(test_id, TEST_FAILED);
822 char buf[1024];
823 snprintf(buf, sizeof(buf), "%s terminated by signal: %s.\n",
824 testcase.GetTestName(test_id).c_str(), strsignal(WTERMSIG(child_proc.exit_status)));
Yabin Cuiea9c9332015-02-24 14:39:19 -0800825 testcase.GetTest(test_id).AppendTestOutput(buf);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800826
827 } else {
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800828 int exitcode = WEXITSTATUS(child_proc.exit_status);
829 testcase.SetTestResult(test_id, exitcode == 0 ? TEST_SUCCESS : TEST_FAILED);
830 if (exitcode != 0) {
Yabin Cuia32fc862015-12-03 16:28:03 -0800831 char buf[1024];
832 snprintf(buf, sizeof(buf), "%s exited with exitcode %d.\n",
833 testcase.GetTestName(test_id).c_str(), exitcode);
834 testcase.GetTest(test_id).AppendTestOutput(buf);
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800835 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800836 }
837}
838
Yabin Cui294d1e22014-12-07 20:43:37 -0800839// We choose to use multi-fork and multi-wait here instead of multi-thread, because it always
840// makes deadlock to use fork in multi-thread.
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700841// Returns true if all tests run successfully, otherwise return false.
842static bool RunTestInSeparateProc(int argc, char** argv, std::vector<TestCase>& testcase_list,
Christopher Ferris119cb552015-04-02 12:02:55 -0700843 int iteration_count, size_t job_count,
Yabin Cui657b1f92015-01-22 19:26:12 -0800844 const std::string& xml_output_filename) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800845 // Stop default result printer to avoid environment setup/teardown information for each test.
846 testing::UnitTest::GetInstance()->listeners().Release(
847 testing::UnitTest::GetInstance()->listeners().default_result_printer());
848 testing::UnitTest::GetInstance()->listeners().Append(new TestResultPrinter);
849
Yabin Cui767fb1c2015-09-01 15:06:39 -0700850 if (!RegisterSignalHandler()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800851 exit(1);
852 }
853
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700854 bool all_tests_passed = true;
855
Christopher Ferris119cb552015-04-02 12:02:55 -0700856 for (size_t iteration = 1;
857 iteration_count < 0 || iteration <= static_cast<size_t>(iteration_count);
858 ++iteration) {
Yabin Cuibe837362015-01-02 18:45:37 -0800859 OnTestIterationStartPrint(testcase_list, iteration, iteration_count);
Yabin Cui657b1f92015-01-22 19:26:12 -0800860 int64_t iteration_start_time_ns = NanoTime();
861 time_t epoch_iteration_start_time = time(NULL);
Yabin Cui294d1e22014-12-07 20:43:37 -0800862
Yabin Cuibe837362015-01-02 18:45:37 -0800863 // Run up to job_count tests in parallel, each test in a child process.
Yabin Cui1d4c7802015-02-02 19:14:05 -0800864 std::vector<ChildProcInfo> child_proc_list;
Yabin Cui294d1e22014-12-07 20:43:37 -0800865
Yabin Cuibe837362015-01-02 18:45:37 -0800866 // Next test to run is [next_testcase_id:next_test_id].
867 size_t next_testcase_id = 0;
868 size_t next_test_id = 0;
869
870 // Record how many tests are finished.
871 std::vector<size_t> finished_test_count_list(testcase_list.size(), 0);
872 size_t finished_testcase_count = 0;
873
874 while (finished_testcase_count < testcase_list.size()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800875 // run up to job_count child processes.
876 while (child_proc_list.size() < job_count && next_testcase_id < testcase_list.size()) {
877 std::string test_name = testcase_list[next_testcase_id].GetTestName(next_test_id);
878 ChildProcInfo child_proc = RunChildProcess(test_name, next_testcase_id, next_test_id,
Yabin Cui767fb1c2015-09-01 15:06:39 -0700879 argc, argv);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800880 child_proc_list.push_back(child_proc);
881 if (++next_test_id == testcase_list[next_testcase_id].TestCount()) {
882 next_test_id = 0;
883 ++next_testcase_id;
Yabin Cui294d1e22014-12-07 20:43:37 -0800884 }
885 }
886
887 // Wait for any child proc finish or timeout.
Yabin Cui1d4c7802015-02-02 19:14:05 -0800888 WaitChildProcs(testcase_list, child_proc_list);
Yabin Cui294d1e22014-12-07 20:43:37 -0800889
890 // Collect result.
Yabin Cui1d4c7802015-02-02 19:14:05 -0800891 auto it = child_proc_list.begin();
892 while (it != child_proc_list.end()) {
893 auto& child_proc = *it;
894 if (child_proc.finished == true) {
Yabin Cuibe837362015-01-02 18:45:37 -0800895 size_t testcase_id = child_proc.testcase_id;
896 size_t test_id = child_proc.test_id;
897 TestCase& testcase = testcase_list[testcase_id];
Yabin Cuibe837362015-01-02 18:45:37 -0800898
Yabin Cui1d4c7802015-02-02 19:14:05 -0800899 CollectChildTestResult(child_proc, testcase);
Yabin Cui657b1f92015-01-22 19:26:12 -0800900 OnTestEndPrint(testcase, test_id);
Yabin Cuibe837362015-01-02 18:45:37 -0800901
902 if (++finished_test_count_list[testcase_id] == testcase.TestCount()) {
903 ++finished_testcase_count;
Yabin Cui294d1e22014-12-07 20:43:37 -0800904 }
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700905 if (testcase.GetTestResult(test_id) != TEST_SUCCESS) {
906 all_tests_passed = false;
907 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800908
909 it = child_proc_list.erase(it);
910 } else {
911 ++it;
Yabin Cui294d1e22014-12-07 20:43:37 -0800912 }
913 }
914 }
915
Yabin Cui657b1f92015-01-22 19:26:12 -0800916 int64_t elapsed_time_ns = NanoTime() - iteration_start_time_ns;
917 OnTestIterationEndPrint(testcase_list, iteration, elapsed_time_ns);
918 if (!xml_output_filename.empty()) {
919 OnTestIterationEndXmlPrint(xml_output_filename, testcase_list, epoch_iteration_start_time,
920 elapsed_time_ns);
921 }
Yabin Cui294d1e22014-12-07 20:43:37 -0800922 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800923
Yabin Cui767fb1c2015-09-01 15:06:39 -0700924 if (!UnregisterSignalHandler()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800925 exit(1);
926 }
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700927
928 return all_tests_passed;
Yabin Cui294d1e22014-12-07 20:43:37 -0800929}
930
Christopher Ferrisdaaaed12015-09-24 18:45:53 -0700931static size_t GetDefaultJobCount() {
Yabin Cuibe837362015-01-02 18:45:37 -0800932 return static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
Yabin Cui294d1e22014-12-07 20:43:37 -0800933}
934
Yabin Cuiead08142015-02-04 20:53:56 -0800935static void AddPathSeparatorInTestProgramPath(std::vector<char*>& args) {
936 // To run DeathTest in threadsafe mode, gtest requires that the user must invoke the
937 // test program via a valid path that contains at least one path separator.
938 // The reason is that gtest uses clone() + execve() to run DeathTest in threadsafe mode,
939 // and execve() doesn't read environment variable PATH, so execve() will not success
940 // until we specify the absolute path or relative path of the test program directly.
Dimitry Ivanov2ba1cf32016-05-17 13:29:37 -0700941 if (strchr(args[0], '/') == nullptr) {
942 args[0] = strdup(g_executable_path.c_str());
Yabin Cuiead08142015-02-04 20:53:56 -0800943 }
944}
945
Yabin Cui11c43532015-01-28 14:28:14 -0800946static void AddGtestFilterSynonym(std::vector<char*>& args) {
947 // Support --gtest-filter as a synonym for --gtest_filter.
948 for (size_t i = 1; i < args.size(); ++i) {
949 if (strncmp(args[i], "--gtest-filter", strlen("--gtest-filter")) == 0) {
950 args[i][7] = '_';
951 }
952 }
953}
954
Yabin Cui657b1f92015-01-22 19:26:12 -0800955struct IsolationTestOptions {
956 bool isolate;
957 size_t job_count;
958 int test_deadline_ms;
959 int test_warnline_ms;
960 std::string gtest_color;
961 bool gtest_print_time;
Christopher Ferris119cb552015-04-02 12:02:55 -0700962 int gtest_repeat;
Yabin Cui657b1f92015-01-22 19:26:12 -0800963 std::string gtest_output;
964};
965
966// Pick options not for gtest: There are two parts in args, one part is used in isolation test mode
Yabin Cuibe837362015-01-02 18:45:37 -0800967// as described in PrintHelpInfo(), the other part is handled by testing::InitGoogleTest() in
Yabin Cui657b1f92015-01-22 19:26:12 -0800968// gtest. PickOptions() picks the first part into IsolationTestOptions structure, leaving the second
969// part in args.
Yabin Cuibe837362015-01-02 18:45:37 -0800970// Arguments:
Yabin Cui657b1f92015-01-22 19:26:12 -0800971// args is used to pass in all command arguments, and pass out only the part of options for gtest.
972// options is used to pass out test options in isolation mode.
973// Return false if there is error in arguments.
974static bool PickOptions(std::vector<char*>& args, IsolationTestOptions& options) {
975 for (size_t i = 1; i < args.size(); ++i) {
976 if (strcmp(args[i], "--help") == 0 || strcmp(args[i], "-h") == 0) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800977 PrintHelpInfo();
Yabin Cui657b1f92015-01-22 19:26:12 -0800978 options.isolate = false;
Yabin Cui294d1e22014-12-07 20:43:37 -0800979 return true;
980 }
981 }
982
Yabin Cuiead08142015-02-04 20:53:56 -0800983 AddPathSeparatorInTestProgramPath(args);
Yabin Cui11c43532015-01-28 14:28:14 -0800984 AddGtestFilterSynonym(args);
985
Yabin Cui657b1f92015-01-22 19:26:12 -0800986 // if --bionic-selftest argument is used, only enable self tests, otherwise remove self tests.
987 bool enable_selftest = false;
988 for (size_t i = 1; i < args.size(); ++i) {
989 if (strcmp(args[i], "--bionic-selftest") == 0) {
990 // This argument is to enable "bionic_selftest*" for self test, and is not shown in help info.
991 // Don't remove this option from arguments.
992 enable_selftest = true;
993 }
994 }
995 std::string gtest_filter_str;
996 for (size_t i = args.size() - 1; i >= 1; --i) {
997 if (strncmp(args[i], "--gtest_filter=", strlen("--gtest_filter=")) == 0) {
998 gtest_filter_str = std::string(args[i]);
999 args.erase(args.begin() + i);
Yabin Cui294d1e22014-12-07 20:43:37 -08001000 break;
1001 }
1002 }
Yabin Cui657b1f92015-01-22 19:26:12 -08001003 if (enable_selftest == true) {
1004 args.push_back(strdup("--gtest_filter=bionic_selftest*"));
1005 } else {
1006 if (gtest_filter_str == "") {
1007 gtest_filter_str = "--gtest_filter=-bionic_selftest*";
1008 } else {
Yabin Cui0bc4e962015-01-27 11:22:46 -08001009 // Find if '-' for NEGATIVE_PATTERNS exists.
1010 if (gtest_filter_str.find(":-") != std::string::npos) {
1011 gtest_filter_str += ":bionic_selftest*";
1012 } else {
1013 gtest_filter_str += ":-bionic_selftest*";
1014 }
Yabin Cui657b1f92015-01-22 19:26:12 -08001015 }
1016 args.push_back(strdup(gtest_filter_str.c_str()));
1017 }
Yabin Cui294d1e22014-12-07 20:43:37 -08001018
Yabin Cui657b1f92015-01-22 19:26:12 -08001019 options.isolate = true;
1020 // Parse arguments that make us can't run in isolation mode.
1021 for (size_t i = 1; i < args.size(); ++i) {
1022 if (strcmp(args[i], "--no-isolate") == 0) {
1023 options.isolate = false;
1024 } else if (strcmp(args[i], "--gtest_list_tests") == 0) {
1025 options.isolate = false;
Yabin Cui294d1e22014-12-07 20:43:37 -08001026 }
1027 }
1028
Yabin Cui657b1f92015-01-22 19:26:12 -08001029 // Stop parsing if we will not run in isolation mode.
1030 if (options.isolate == false) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001031 return true;
1032 }
Yabin Cui657b1f92015-01-22 19:26:12 -08001033
1034 // Init default isolation test options.
Christopher Ferrisdaaaed12015-09-24 18:45:53 -07001035 options.job_count = GetDefaultJobCount();
Yabin Cui657b1f92015-01-22 19:26:12 -08001036 options.test_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
1037 options.test_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
1038 options.gtest_color = testing::GTEST_FLAG(color);
1039 options.gtest_print_time = testing::GTEST_FLAG(print_time);
1040 options.gtest_repeat = testing::GTEST_FLAG(repeat);
1041 options.gtest_output = testing::GTEST_FLAG(output);
1042
1043 // Parse arguments speficied for isolation mode.
1044 for (size_t i = 1; i < args.size(); ++i) {
1045 if (strncmp(args[i], "-j", strlen("-j")) == 0) {
1046 char* p = args[i] + strlen("-j");
1047 int count = 0;
1048 if (*p != '\0') {
1049 // Argument like -j5.
1050 count = atoi(p);
1051 } else if (args.size() > i + 1) {
1052 // Arguments like -j 5.
1053 count = atoi(args[i + 1]);
1054 ++i;
1055 }
1056 if (count <= 0) {
1057 fprintf(stderr, "invalid job count: %d\n", count);
1058 return false;
1059 }
1060 options.job_count = static_cast<size_t>(count);
1061 } else if (strncmp(args[i], "--deadline=", strlen("--deadline=")) == 0) {
1062 int time_ms = atoi(args[i] + strlen("--deadline="));
1063 if (time_ms <= 0) {
1064 fprintf(stderr, "invalid deadline: %d\n", time_ms);
1065 return false;
1066 }
1067 options.test_deadline_ms = time_ms;
1068 } else if (strncmp(args[i], "--warnline=", strlen("--warnline=")) == 0) {
1069 int time_ms = atoi(args[i] + strlen("--warnline="));
1070 if (time_ms <= 0) {
1071 fprintf(stderr, "invalid warnline: %d\n", time_ms);
1072 return false;
1073 }
1074 options.test_warnline_ms = time_ms;
1075 } else if (strncmp(args[i], "--gtest_color=", strlen("--gtest_color=")) == 0) {
1076 options.gtest_color = args[i] + strlen("--gtest_color=");
1077 } else if (strcmp(args[i], "--gtest_print_time=0") == 0) {
1078 options.gtest_print_time = false;
1079 } else if (strncmp(args[i], "--gtest_repeat=", strlen("--gtest_repeat=")) == 0) {
Christopher Ferris119cb552015-04-02 12:02:55 -07001080 // If the value of gtest_repeat is < 0, then it indicates the tests
1081 // should be repeated forever.
1082 options.gtest_repeat = atoi(args[i] + strlen("--gtest_repeat="));
Yabin Cui657b1f92015-01-22 19:26:12 -08001083 // Remove --gtest_repeat=xx from arguments, so child process only run one iteration for a single test.
1084 args.erase(args.begin() + i);
1085 --i;
1086 } else if (strncmp(args[i], "--gtest_output=", strlen("--gtest_output=")) == 0) {
1087 std::string output = args[i] + strlen("--gtest_output=");
1088 // generate output xml file path according to the strategy in gtest.
1089 bool success = true;
1090 if (strncmp(output.c_str(), "xml:", strlen("xml:")) == 0) {
1091 output = output.substr(strlen("xml:"));
1092 if (output.size() == 0) {
1093 success = false;
1094 }
1095 // Make absolute path.
1096 if (success && output[0] != '/') {
1097 char* cwd = getcwd(NULL, 0);
1098 if (cwd != NULL) {
1099 output = std::string(cwd) + "/" + output;
1100 free(cwd);
1101 } else {
1102 success = false;
1103 }
1104 }
1105 // Add file name if output is a directory.
1106 if (success && output.back() == '/') {
1107 output += "test_details.xml";
1108 }
1109 }
1110 if (success) {
1111 options.gtest_output = output;
1112 } else {
1113 fprintf(stderr, "invalid gtest_output file: %s\n", args[i]);
1114 return false;
1115 }
1116
1117 // Remove --gtest_output=xxx from arguments, so child process will not write xml file.
1118 args.erase(args.begin() + i);
1119 --i;
1120 }
1121 }
1122
1123 // Add --no-isolate in args to prevent child process from running in isolation mode again.
1124 // As DeathTest will try to call execve(), this argument should always be added.
1125 args.insert(args.begin() + 1, strdup("--no-isolate"));
Yabin Cui294d1e22014-12-07 20:43:37 -08001126 return true;
1127}
1128
Dimitry Ivanov2ba1cf32016-05-17 13:29:37 -07001129static std::string get_proc_self_exe() {
1130 char path[PATH_MAX];
1131 ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
1132 if (path_len <= 0 || path_len >= static_cast<ssize_t>(sizeof(path))) {
1133 perror("readlink");
1134 exit(1);
1135 }
1136
1137 return std::string(path, path_len);
1138}
1139
Dimitry Ivanov55437462016-07-20 15:33:07 -07001140int main(int argc, char** argv, char** envp) {
Dimitry Ivanov2ba1cf32016-05-17 13:29:37 -07001141 g_executable_path = get_proc_self_exe();
Dimitry Ivanov55437462016-07-20 15:33:07 -07001142 g_argc = argc;
1143 g_argv = argv;
1144 g_envp = envp;
Yabin Cuibe837362015-01-02 18:45:37 -08001145 std::vector<char*> arg_list;
1146 for (int i = 0; i < argc; ++i) {
1147 arg_list.push_back(argv[i]);
1148 }
Yabin Cuibe837362015-01-02 18:45:37 -08001149
Yabin Cui657b1f92015-01-22 19:26:12 -08001150 IsolationTestOptions options;
1151 if (PickOptions(arg_list, options) == false) {
1152 return 1;
Yabin Cui294d1e22014-12-07 20:43:37 -08001153 }
Yabin Cui657b1f92015-01-22 19:26:12 -08001154
1155 if (options.isolate == true) {
1156 // Set global variables.
1157 global_test_run_deadline_ms = options.test_deadline_ms;
1158 global_test_run_warnline_ms = options.test_warnline_ms;
1159 testing::GTEST_FLAG(color) = options.gtest_color.c_str();
1160 testing::GTEST_FLAG(print_time) = options.gtest_print_time;
1161 std::vector<TestCase> testcase_list;
1162
1163 argc = static_cast<int>(arg_list.size());
1164 arg_list.push_back(NULL);
1165 if (EnumerateTests(argc, arg_list.data(), testcase_list) == false) {
1166 return 1;
1167 }
Yabin Cui64a9c4f2015-03-12 22:16:03 -07001168 bool all_test_passed = RunTestInSeparateProc(argc, arg_list.data(), testcase_list,
1169 options.gtest_repeat, options.job_count, options.gtest_output);
1170 return all_test_passed ? 0 : 1;
Yabin Cui657b1f92015-01-22 19:26:12 -08001171 } else {
1172 argc = static_cast<int>(arg_list.size());
1173 arg_list.push_back(NULL);
1174 testing::InitGoogleTest(&argc, arg_list.data());
1175 return RUN_ALL_TESTS();
1176 }
Yabin Cui294d1e22014-12-07 20:43:37 -08001177}
1178
1179//################################################################################
Yabin Cuibe837362015-01-02 18:45:37 -08001180// Bionic Gtest self test, run this by --bionic-selftest option.
Yabin Cui294d1e22014-12-07 20:43:37 -08001181
Yabin Cuibe837362015-01-02 18:45:37 -08001182TEST(bionic_selftest, test_success) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001183 ASSERT_EQ(1, 1);
1184}
1185
Yabin Cuibe837362015-01-02 18:45:37 -08001186TEST(bionic_selftest, test_fail) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001187 ASSERT_EQ(0, 1);
1188}
1189
Yabin Cuibe837362015-01-02 18:45:37 -08001190TEST(bionic_selftest, test_time_warn) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001191 sleep(4);
1192}
1193
Yabin Cuibe837362015-01-02 18:45:37 -08001194TEST(bionic_selftest, test_timeout) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001195 while (1) {}
1196}
Yabin Cuibe837362015-01-02 18:45:37 -08001197
1198TEST(bionic_selftest, test_signal_SEGV_terminated) {
1199 char* p = reinterpret_cast<char*>(static_cast<intptr_t>(atoi("0")));
1200 *p = 3;
1201}
Yabin Cui657b1f92015-01-22 19:26:12 -08001202
Yabin Cui767fb1c2015-09-01 15:06:39 -07001203class bionic_selftest_DeathTest : public ::testing::Test {
1204 protected:
1205 virtual void SetUp() {
1206 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
1207 }
1208};
Yabin Cui657b1f92015-01-22 19:26:12 -08001209
1210static void deathtest_helper_success() {
1211 ASSERT_EQ(1, 1);
1212 exit(0);
1213}
1214
1215TEST_F(bionic_selftest_DeathTest, success) {
1216 ASSERT_EXIT(deathtest_helper_success(), ::testing::ExitedWithCode(0), "");
1217}
1218
1219static void deathtest_helper_fail() {
1220 ASSERT_EQ(1, 0);
1221}
1222
1223TEST_F(bionic_selftest_DeathTest, fail) {
1224 ASSERT_EXIT(deathtest_helper_fail(), ::testing::ExitedWithCode(0), "");
1225}