blob: 7360f123925b91d470c84b524bb9b61ae78d4eef [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
Yabin Cui294d1e22014-12-07 20:43:37 -080049namespace testing {
50namespace internal {
51
52// Reuse of testing::internal::ColoredPrintf in gtest.
53enum GTestColor {
54 COLOR_DEFAULT,
55 COLOR_RED,
56 COLOR_GREEN,
57 COLOR_YELLOW
58};
59
60void ColoredPrintf(GTestColor color, const char* fmt, ...);
61
Yabin Cuibe837362015-01-02 18:45:37 -080062} // namespace internal
63} // namespace testing
Yabin Cui294d1e22014-12-07 20:43:37 -080064
65using testing::internal::GTestColor;
66using testing::internal::COLOR_DEFAULT;
67using testing::internal::COLOR_RED;
68using testing::internal::COLOR_GREEN;
69using testing::internal::COLOR_YELLOW;
70using testing::internal::ColoredPrintf;
71
Christopher Ferrisdaaaed12015-09-24 18:45:53 -070072constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS = 90000;
Yabin Cui657b1f92015-01-22 19:26:12 -080073constexpr int DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS = 2000;
Yabin Cui294d1e22014-12-07 20:43:37 -080074
75// The time each test can run before killed for the reason of timeout.
76// It takes effect only with --isolate option.
Yabin Cui657b1f92015-01-22 19:26:12 -080077static int global_test_run_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
Yabin Cui294d1e22014-12-07 20:43:37 -080078
79// The time each test can run before be warned for too much running time.
80// It takes effect only with --isolate option.
Yabin Cui657b1f92015-01-22 19:26:12 -080081static int global_test_run_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
Yabin Cui294d1e22014-12-07 20:43:37 -080082
83// Return deadline duration for a test, in ms.
84static int GetDeadlineInfo(const std::string& /*test_name*/) {
Yabin Cui657b1f92015-01-22 19:26:12 -080085 return global_test_run_deadline_ms;
Yabin Cui294d1e22014-12-07 20:43:37 -080086}
87
88// Return warnline duration for a test, in ms.
89static int GetWarnlineInfo(const std::string& /*test_name*/) {
Yabin Cui657b1f92015-01-22 19:26:12 -080090 return global_test_run_warnline_ms;
Yabin Cui294d1e22014-12-07 20:43:37 -080091}
92
Yabin Cuibe837362015-01-02 18:45:37 -080093static void PrintHelpInfo() {
94 printf("Bionic Unit Test Options:\n"
Yabin Cui657b1f92015-01-22 19:26:12 -080095 " -j [JOB_COUNT] or -j[JOB_COUNT]\n"
Yabin Cuibe837362015-01-02 18:45:37 -080096 " Run up to JOB_COUNT tests in parallel.\n"
97 " Use isolation mode, Run each test in a separate process.\n"
98 " If JOB_COUNT is not given, it is set to the count of available processors.\n"
99 " --no-isolate\n"
100 " Don't use isolation mode, run all tests in a single process.\n"
101 " --deadline=[TIME_IN_MS]\n"
102 " Run each test in no longer than [TIME_IN_MS] time.\n"
Yabin Cuibc6379d2015-10-06 16:30:14 -0700103 " It takes effect only in isolation mode. Deafult deadline is 90000 ms.\n"
Yabin Cuibe837362015-01-02 18:45:37 -0800104 " --warnline=[TIME_IN_MS]\n"
105 " Test running longer than [TIME_IN_MS] will be warned.\n"
106 " It takes effect only in isolation mode. Default warnline is 2000 ms.\n"
Yabin Cui11c43532015-01-28 14:28:14 -0800107 " --gtest-filter=POSITIVE_PATTERNS[-NEGATIVE_PATTERNS]\n"
108 " Used as a synonym for --gtest_filter option in gtest.\n"
Yabin Cui1d4c7802015-02-02 19:14:05 -0800109 "Default bionic unit test option is -j.\n"
110 "In isolation mode, you can send SIGQUIT to the parent process to show current\n"
111 "running tests, or send SIGINT to the parent process to stop testing and\n"
112 "clean up current running tests.\n"
Yabin Cuibe837362015-01-02 18:45:37 -0800113 "\n");
114}
115
Yabin Cui294d1e22014-12-07 20:43:37 -0800116enum TestResult {
117 TEST_SUCCESS = 0,
118 TEST_FAILED,
119 TEST_TIMEOUT
120};
121
Yabin Cui657b1f92015-01-22 19:26:12 -0800122class Test {
123 public:
124 Test() {} // For std::vector<Test>.
125 explicit Test(const char* name) : name_(name) {}
126
127 const std::string& GetName() const { return name_; }
128
129 void SetResult(TestResult result) { result_ = result; }
130
131 TestResult GetResult() const { return result_; }
132
133 void SetTestTime(int64_t elapsed_time_ns) { elapsed_time_ns_ = elapsed_time_ns; }
134
135 int64_t GetTestTime() const { return elapsed_time_ns_; }
136
Yabin Cuiea9c9332015-02-24 14:39:19 -0800137 void AppendTestOutput(const std::string& s) { output_ += s; }
Yabin Cui657b1f92015-01-22 19:26:12 -0800138
Yabin Cuiea9c9332015-02-24 14:39:19 -0800139 const std::string& GetTestOutput() const { return output_; }
Yabin Cui657b1f92015-01-22 19:26:12 -0800140
141 private:
142 const std::string name_;
143 TestResult result_;
144 int64_t elapsed_time_ns_;
Yabin Cuiea9c9332015-02-24 14:39:19 -0800145 std::string output_;
Yabin Cui657b1f92015-01-22 19:26:12 -0800146};
147
Yabin Cui294d1e22014-12-07 20:43:37 -0800148class TestCase {
149 public:
150 TestCase() {} // For std::vector<TestCase>.
151 explicit TestCase(const char* name) : name_(name) {}
152
153 const std::string& GetName() const { return name_; }
154
Yabin Cui657b1f92015-01-22 19:26:12 -0800155 void AppendTest(const char* test_name) {
156 test_list_.push_back(Test(test_name));
Yabin Cui294d1e22014-12-07 20:43:37 -0800157 }
158
Yabin Cuibe837362015-01-02 18:45:37 -0800159 size_t TestCount() const { return test_list_.size(); }
Yabin Cui294d1e22014-12-07 20:43:37 -0800160
Yabin Cuibe837362015-01-02 18:45:37 -0800161 std::string GetTestName(size_t test_id) const {
Yabin Cui294d1e22014-12-07 20:43:37 -0800162 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800163 return name_ + "." + test_list_[test_id].GetName();
164 }
165
166 Test& GetTest(size_t test_id) {
167 VerifyTestId(test_id);
168 return test_list_[test_id];
169 }
170
171 const Test& GetTest(size_t test_id) const {
172 VerifyTestId(test_id);
173 return test_list_[test_id];
Yabin Cui294d1e22014-12-07 20:43:37 -0800174 }
175
Yabin Cuibe837362015-01-02 18:45:37 -0800176 void SetTestResult(size_t test_id, TestResult result) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800177 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800178 test_list_[test_id].SetResult(result);
Yabin Cui294d1e22014-12-07 20:43:37 -0800179 }
180
Yabin Cuibe837362015-01-02 18:45:37 -0800181 TestResult GetTestResult(size_t test_id) const {
Yabin Cui294d1e22014-12-07 20:43:37 -0800182 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800183 return test_list_[test_id].GetResult();
Yabin Cui294d1e22014-12-07 20:43:37 -0800184 }
185
Yabin Cui657b1f92015-01-22 19:26:12 -0800186 void SetTestTime(size_t test_id, int64_t elapsed_time_ns) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800187 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800188 test_list_[test_id].SetTestTime(elapsed_time_ns);
Yabin Cui294d1e22014-12-07 20:43:37 -0800189 }
190
Yabin Cuibe837362015-01-02 18:45:37 -0800191 int64_t GetTestTime(size_t test_id) const {
Yabin Cui294d1e22014-12-07 20:43:37 -0800192 VerifyTestId(test_id);
Yabin Cui657b1f92015-01-22 19:26:12 -0800193 return test_list_[test_id].GetTestTime();
Yabin Cui294d1e22014-12-07 20:43:37 -0800194 }
195
196 private:
Yabin Cuibe837362015-01-02 18:45:37 -0800197 void VerifyTestId(size_t test_id) const {
198 if(test_id >= test_list_.size()) {
199 fprintf(stderr, "test_id %zu out of range [0, %zu)\n", test_id, test_list_.size());
Yabin Cui294d1e22014-12-07 20:43:37 -0800200 exit(1);
201 }
202 }
203
204 private:
205 const std::string name_;
Yabin Cui657b1f92015-01-22 19:26:12 -0800206 std::vector<Test> test_list_;
Yabin Cui294d1e22014-12-07 20:43:37 -0800207};
208
Yabin Cui294d1e22014-12-07 20:43:37 -0800209class TestResultPrinter : public testing::EmptyTestEventListener {
210 public:
211 TestResultPrinter() : pinfo_(NULL) {}
212 virtual void OnTestStart(const testing::TestInfo& test_info) {
213 pinfo_ = &test_info; // Record test_info for use in OnTestPartResult.
214 }
215 virtual void OnTestPartResult(const testing::TestPartResult& result);
Yabin Cui294d1e22014-12-07 20:43:37 -0800216
217 private:
218 const testing::TestInfo* pinfo_;
219};
220
221// Called after an assertion failure.
222void TestResultPrinter::OnTestPartResult(const testing::TestPartResult& result) {
223 // If the test part succeeded, we don't need to do anything.
224 if (result.type() == testing::TestPartResult::kSuccess)
225 return;
226
227 // Print failure message from the assertion (e.g. expected this and got that).
Yabin Cuiea9c9332015-02-24 14:39:19 -0800228 printf("%s:(%d) Failure in test %s.%s\n%s\n", result.file_name(), result.line_number(),
229 pinfo_->test_case_name(), pinfo_->name(), result.message());
230 fflush(stdout);
Yabin Cui294d1e22014-12-07 20:43:37 -0800231}
232
Yabin Cui294d1e22014-12-07 20:43:37 -0800233static int64_t NanoTime() {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700234 std::chrono::nanoseconds duration(std::chrono::steady_clock::now().time_since_epoch());
235 return static_cast<int64_t>(duration.count());
Yabin Cui294d1e22014-12-07 20:43:37 -0800236}
237
238static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcase_list) {
239 std::string command;
240 for (int i = 0; i < argc; ++i) {
241 command += argv[i];
242 command += " ";
243 }
244 command += "--gtest_list_tests";
245 FILE* fp = popen(command.c_str(), "r");
246 if (fp == NULL) {
247 perror("popen");
248 return false;
249 }
250
251 char buf[200];
252 while (fgets(buf, sizeof(buf), fp) != NULL) {
253 char* p = buf;
254
255 while (*p != '\0' && isspace(*p)) {
256 ++p;
257 }
258 if (*p == '\0') continue;
259 char* start = p;
260 while (*p != '\0' && !isspace(*p)) {
261 ++p;
262 }
263 char* end = p;
264 while (*p != '\0' && isspace(*p)) {
265 ++p;
266 }
Yabin Cuibf830ad2015-08-10 12:12:39 -0700267 if (*p != '\0' && *p != '#') {
Yabin Cui294d1e22014-12-07 20:43:37 -0800268 // This is not we want, gtest must meet with some error when parsing the arguments.
269 fprintf(stderr, "argument error, check with --help\n");
270 return false;
271 }
272 *end = '\0';
273 if (*(end - 1) == '.') {
274 *(end - 1) = '\0';
275 testcase_list.push_back(TestCase(start));
276 } else {
277 testcase_list.back().AppendTest(start);
278 }
279 }
280 int result = pclose(fp);
281 return (result != -1 && WEXITSTATUS(result) == 0);
282}
283
Yabin Cui294d1e22014-12-07 20:43:37 -0800284// Part of the following *Print functions are copied from external/gtest/src/gtest.cc:
285// PrettyUnitTestResultPrinter. The reason for copy is that PrettyUnitTestResultPrinter
286// is defined and used in gtest.cc, which is hard to reuse.
Yabin Cuibe837362015-01-02 18:45:37 -0800287static void OnTestIterationStartPrint(const std::vector<TestCase>& testcase_list, size_t iteration,
Christopher Ferris119cb552015-04-02 12:02:55 -0700288 int iteration_count) {
289 if (iteration_count != 1) {
Yabin Cuibe837362015-01-02 18:45:37 -0800290 printf("\nRepeating all tests (iteration %zu) . . .\n\n", iteration);
Yabin Cui294d1e22014-12-07 20:43:37 -0800291 }
292 ColoredPrintf(COLOR_GREEN, "[==========] ");
293
Yabin Cuibe837362015-01-02 18:45:37 -0800294 size_t testcase_count = testcase_list.size();
295 size_t test_count = 0;
Yabin Cui294d1e22014-12-07 20:43:37 -0800296 for (const auto& testcase : testcase_list) {
Yabin Cuibe837362015-01-02 18:45:37 -0800297 test_count += testcase.TestCount();
Yabin Cui294d1e22014-12-07 20:43:37 -0800298 }
299
Yabin Cuibe837362015-01-02 18:45:37 -0800300 printf("Running %zu %s from %zu %s.\n",
301 test_count, (test_count == 1) ? "test" : "tests",
302 testcase_count, (testcase_count == 1) ? "test case" : "test cases");
Yabin Cui294d1e22014-12-07 20:43:37 -0800303 fflush(stdout);
304}
305
Yabin Cuif6237472015-02-26 19:03:54 -0800306// bionic cts test needs gtest output format.
307#if defined(USING_GTEST_OUTPUT_FORMAT)
308
309static void OnTestEndPrint(const TestCase& testcase, size_t test_id) {
310 ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
311 printf("%s\n", testcase.GetTestName(test_id).c_str());
312
313 const std::string& test_output = testcase.GetTest(test_id).GetTestOutput();
314 printf("%s", test_output.c_str());
315
316 TestResult result = testcase.GetTestResult(test_id);
317 if (result == TEST_SUCCESS) {
318 ColoredPrintf(COLOR_GREEN, "[ OK ] ");
319 } else {
320 ColoredPrintf(COLOR_RED, "[ FAILED ] ");
321 }
322 printf("%s", testcase.GetTestName(test_id).c_str());
323 if (testing::GTEST_FLAG(print_time)) {
324 printf(" (%" PRId64 " ms)", testcase.GetTestTime(test_id) / 1000000);
325 }
326 printf("\n");
327 fflush(stdout);
328}
329
330#else // !defined(USING_GTEST_OUTPUT_FORMAT)
331
Yabin Cui657b1f92015-01-22 19:26:12 -0800332static void OnTestEndPrint(const TestCase& testcase, size_t test_id) {
333 TestResult result = testcase.GetTestResult(test_id);
334 if (result == TEST_SUCCESS) {
335 ColoredPrintf(COLOR_GREEN, "[ OK ] ");
336 } else if (result == TEST_FAILED) {
337 ColoredPrintf(COLOR_RED, "[ FAILED ] ");
338 } else if (result == TEST_TIMEOUT) {
339 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
340 }
Yabin Cuibe837362015-01-02 18:45:37 -0800341
Yabin Cui657b1f92015-01-22 19:26:12 -0800342 printf("%s", testcase.GetTestName(test_id).c_str());
343 if (testing::GTEST_FLAG(print_time)) {
Yabin Cuif6237472015-02-26 19:03:54 -0800344 printf(" (%" PRId64 " ms)", testcase.GetTestTime(test_id) / 1000000);
Yabin Cui657b1f92015-01-22 19:26:12 -0800345 }
Yabin Cuif6237472015-02-26 19:03:54 -0800346 printf("\n");
Yabin Cui657b1f92015-01-22 19:26:12 -0800347
Yabin Cuiea9c9332015-02-24 14:39:19 -0800348 const std::string& test_output = testcase.GetTest(test_id).GetTestOutput();
349 printf("%s", test_output.c_str());
Yabin Cui294d1e22014-12-07 20:43:37 -0800350 fflush(stdout);
351}
352
Yabin Cuif6237472015-02-26 19:03:54 -0800353#endif // !defined(USING_GTEST_OUTPUT_FORMAT)
354
Yabin Cuibe837362015-01-02 18:45:37 -0800355static void OnTestIterationEndPrint(const std::vector<TestCase>& testcase_list, size_t /*iteration*/,
Yabin Cui657b1f92015-01-22 19:26:12 -0800356 int64_t elapsed_time_ns) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800357
358 std::vector<std::string> fail_test_name_list;
359 std::vector<std::pair<std::string, int64_t>> timeout_test_list;
360
361 // For tests run exceed warnline but not timeout.
Yabin Cui4a82ede2015-01-26 17:19:37 -0800362 std::vector<std::tuple<std::string, int64_t, int>> slow_test_list;
Yabin Cuibe837362015-01-02 18:45:37 -0800363 size_t testcase_count = testcase_list.size();
364 size_t test_count = 0;
365 size_t success_test_count = 0;
Yabin Cui294d1e22014-12-07 20:43:37 -0800366
367 for (const auto& testcase : testcase_list) {
Yabin Cuibe837362015-01-02 18:45:37 -0800368 test_count += testcase.TestCount();
369 for (size_t i = 0; i < testcase.TestCount(); ++i) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800370 TestResult result = testcase.GetTestResult(i);
371 if (result == TEST_SUCCESS) {
Yabin Cuibe837362015-01-02 18:45:37 -0800372 ++success_test_count;
Yabin Cui294d1e22014-12-07 20:43:37 -0800373 } else if (result == TEST_FAILED) {
374 fail_test_name_list.push_back(testcase.GetTestName(i));
375 } else if (result == TEST_TIMEOUT) {
376 timeout_test_list.push_back(std::make_pair(testcase.GetTestName(i),
377 testcase.GetTestTime(i)));
378 }
379 if (result != TEST_TIMEOUT &&
380 testcase.GetTestTime(i) / 1000000 >= GetWarnlineInfo(testcase.GetTestName(i))) {
Yabin Cui4a82ede2015-01-26 17:19:37 -0800381 slow_test_list.push_back(std::make_tuple(testcase.GetTestName(i),
382 testcase.GetTestTime(i),
383 GetWarnlineInfo(testcase.GetTestName(i))));
Yabin Cui294d1e22014-12-07 20:43:37 -0800384 }
385 }
386 }
387
Yabin Cui294d1e22014-12-07 20:43:37 -0800388 ColoredPrintf(COLOR_GREEN, "[==========] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800389 printf("%zu %s from %zu %s ran.", test_count, (test_count == 1) ? "test" : "tests",
390 testcase_count, (testcase_count == 1) ? "test case" : "test cases");
Yabin Cui294d1e22014-12-07 20:43:37 -0800391 if (testing::GTEST_FLAG(print_time)) {
Yabin Cui657b1f92015-01-22 19:26:12 -0800392 printf(" (%" PRId64 " ms total)", elapsed_time_ns / 1000000);
Yabin Cui294d1e22014-12-07 20:43:37 -0800393 }
394 printf("\n");
Yabin Cui4a82ede2015-01-26 17:19:37 -0800395 ColoredPrintf(COLOR_GREEN, "[ PASS ] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800396 printf("%zu %s.\n", success_test_count, (success_test_count == 1) ? "test" : "tests");
Yabin Cui294d1e22014-12-07 20:43:37 -0800397
398 // Print tests failed.
Yabin Cuibe837362015-01-02 18:45:37 -0800399 size_t fail_test_count = fail_test_name_list.size();
400 if (fail_test_count > 0) {
Yabin Cui4a82ede2015-01-26 17:19:37 -0800401 ColoredPrintf(COLOR_RED, "[ FAIL ] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800402 printf("%zu %s, listed below:\n", fail_test_count, (fail_test_count == 1) ? "test" : "tests");
Yabin Cui294d1e22014-12-07 20:43:37 -0800403 for (const auto& name : fail_test_name_list) {
Yabin Cui4a82ede2015-01-26 17:19:37 -0800404 ColoredPrintf(COLOR_RED, "[ FAIL ] ");
Yabin Cui294d1e22014-12-07 20:43:37 -0800405 printf("%s\n", name.c_str());
406 }
407 }
408
409 // Print tests run timeout.
Yabin Cuibe837362015-01-02 18:45:37 -0800410 size_t timeout_test_count = timeout_test_list.size();
411 if (timeout_test_count > 0) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800412 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
Yabin Cuibe837362015-01-02 18:45:37 -0800413 printf("%zu %s, listed below:\n", timeout_test_count, (timeout_test_count == 1) ? "test" : "tests");
Yabin Cui294d1e22014-12-07 20:43:37 -0800414 for (const auto& timeout_pair : timeout_test_list) {
415 ColoredPrintf(COLOR_RED, "[ TIMEOUT ] ");
Yabin Cui657b1f92015-01-22 19:26:12 -0800416 printf("%s (stopped at %" PRId64 " ms)\n", timeout_pair.first.c_str(),
417 timeout_pair.second / 1000000);
Yabin Cui294d1e22014-12-07 20:43:37 -0800418 }
419 }
420
421 // Print tests run exceed warnline.
Yabin Cui4a82ede2015-01-26 17:19:37 -0800422 size_t slow_test_count = slow_test_list.size();
423 if (slow_test_count > 0) {
424 ColoredPrintf(COLOR_YELLOW, "[ SLOW ] ");
425 printf("%zu %s, listed below:\n", slow_test_count, (slow_test_count == 1) ? "test" : "tests");
426 for (const auto& slow_tuple : slow_test_list) {
427 ColoredPrintf(COLOR_YELLOW, "[ SLOW ] ");
428 printf("%s (%" PRId64 " ms, exceed warnline %d ms)\n", std::get<0>(slow_tuple).c_str(),
429 std::get<1>(slow_tuple) / 1000000, std::get<2>(slow_tuple));
Yabin Cui294d1e22014-12-07 20:43:37 -0800430 }
431 }
432
Yabin Cuibe837362015-01-02 18:45:37 -0800433 if (fail_test_count > 0) {
434 printf("\n%2zu FAILED %s\n", fail_test_count, (fail_test_count == 1) ? "TEST" : "TESTS");
Yabin Cui294d1e22014-12-07 20:43:37 -0800435 }
Yabin Cuibe837362015-01-02 18:45:37 -0800436 if (timeout_test_count > 0) {
437 printf("%2zu TIMEOUT %s\n", timeout_test_count, (timeout_test_count == 1) ? "TEST" : "TESTS");
Yabin Cui294d1e22014-12-07 20:43:37 -0800438 }
Yabin Cui4a82ede2015-01-26 17:19:37 -0800439 if (slow_test_count > 0) {
440 printf("%2zu SLOW %s\n", slow_test_count, (slow_test_count == 1) ? "TEST" : "TESTS");
Yabin Cui294d1e22014-12-07 20:43:37 -0800441 }
442 fflush(stdout);
443}
444
Dan Albert09a99642016-01-13 21:48:56 -0800445std::string XmlEscape(const std::string& xml) {
446 std::string escaped;
447 escaped.reserve(xml.size());
448
449 for (auto c : xml) {
450 switch (c) {
451 case '<':
452 escaped.append("&lt;");
453 break;
454 case '>':
455 escaped.append("&gt;");
456 break;
457 case '&':
458 escaped.append("&amp;");
459 break;
460 case '\'':
461 escaped.append("&apos;");
462 break;
463 case '"':
464 escaped.append("&quot;");
465 break;
466 default:
467 escaped.append(1, c);
468 break;
469 }
470 }
471
472 return escaped;
473}
474
Yabin Cui657b1f92015-01-22 19:26:12 -0800475// Output xml file when --gtest_output is used, write this function as we can't reuse
476// gtest.cc:XmlUnitTestResultPrinter. The reason is XmlUnitTestResultPrinter is totally
477// defined in gtest.cc and not expose to outside. What's more, as we don't run gtest in
478// the parent process, we don't have gtest classes which are needed by XmlUnitTestResultPrinter.
479void OnTestIterationEndXmlPrint(const std::string& xml_output_filename,
480 const std::vector<TestCase>& testcase_list,
481 time_t epoch_iteration_start_time,
482 int64_t elapsed_time_ns) {
483 FILE* fp = fopen(xml_output_filename.c_str(), "w");
484 if (fp == NULL) {
485 fprintf(stderr, "failed to open '%s': %s\n", xml_output_filename.c_str(), strerror(errno));
486 exit(1);
487 }
488
489 size_t total_test_count = 0;
490 size_t total_failed_count = 0;
491 std::vector<size_t> failed_count_list(testcase_list.size(), 0);
492 std::vector<int64_t> elapsed_time_list(testcase_list.size(), 0);
493 for (size_t i = 0; i < testcase_list.size(); ++i) {
494 auto& testcase = testcase_list[i];
495 total_test_count += testcase.TestCount();
496 for (size_t j = 0; j < testcase.TestCount(); ++j) {
497 if (testcase.GetTestResult(j) != TEST_SUCCESS) {
498 ++failed_count_list[i];
499 }
500 elapsed_time_list[i] += testcase.GetTestTime(j);
501 }
502 total_failed_count += failed_count_list[i];
503 }
504
505 const tm* time_struct = localtime(&epoch_iteration_start_time);
506 char timestamp[40];
507 snprintf(timestamp, sizeof(timestamp), "%4d-%02d-%02dT%02d:%02d:%02d",
508 time_struct->tm_year + 1900, time_struct->tm_mon + 1, time_struct->tm_mday,
509 time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec);
510
511 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp);
512 fprintf(fp, "<testsuites tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
513 total_test_count, total_failed_count);
514 fprintf(fp, " timestamp=\"%s\" time=\"%.3lf\" name=\"AllTests\">\n", timestamp, elapsed_time_ns / 1e9);
515 for (size_t i = 0; i < testcase_list.size(); ++i) {
516 auto& testcase = testcase_list[i];
517 fprintf(fp, " <testsuite name=\"%s\" tests=\"%zu\" failures=\"%zu\" disabled=\"0\" errors=\"0\"",
518 testcase.GetName().c_str(), testcase.TestCount(), failed_count_list[i]);
519 fprintf(fp, " time=\"%.3lf\">\n", elapsed_time_list[i] / 1e9);
520
521 for (size_t j = 0; j < testcase.TestCount(); ++j) {
522 fprintf(fp, " <testcase name=\"%s\" status=\"run\" time=\"%.3lf\" classname=\"%s\"",
523 testcase.GetTest(j).GetName().c_str(), testcase.GetTestTime(j) / 1e9,
524 testcase.GetName().c_str());
525 if (testcase.GetTestResult(j) == TEST_SUCCESS) {
526 fputs(" />\n", fp);
527 } else {
528 fputs(">\n", fp);
Yabin Cuiea9c9332015-02-24 14:39:19 -0800529 const std::string& test_output = testcase.GetTest(j).GetTestOutput();
Dan Albert09a99642016-01-13 21:48:56 -0800530 const std::string escaped_test_output = XmlEscape(test_output);
531 fprintf(fp, " <failure message=\"%s\" type=\"\">\n", escaped_test_output.c_str());
Yabin Cui657b1f92015-01-22 19:26:12 -0800532 fputs(" </failure>\n", fp);
533 fputs(" </testcase>\n", fp);
534 }
535 }
536
537 fputs(" </testsuite>\n", fp);
538 }
539 fputs("</testsuites>\n", fp);
540 fclose(fp);
541}
542
Yabin Cui767fb1c2015-09-01 15:06:39 -0700543static bool sigint_flag;
544static bool sigquit_flag;
545
546static void signal_handler(int sig) {
547 if (sig == SIGINT) {
548 sigint_flag = true;
549 } else if (sig == SIGQUIT) {
550 sigquit_flag = true;
551 }
552}
553
554static bool RegisterSignalHandler() {
555 sigint_flag = false;
556 sigquit_flag = false;
557 sig_t ret = signal(SIGINT, signal_handler);
558 if (ret != SIG_ERR) {
559 ret = signal(SIGQUIT, signal_handler);
560 }
561 if (ret == SIG_ERR) {
562 perror("RegisterSignalHandler");
563 return false;
564 }
565 return true;
566}
567
568static bool UnregisterSignalHandler() {
569 sig_t ret = signal(SIGINT, SIG_DFL);
570 if (ret != SIG_ERR) {
571 ret = signal(SIGQUIT, SIG_DFL);
572 }
573 if (ret == SIG_ERR) {
574 perror("UnregisterSignalHandler");
575 return false;
576 }
577 return true;
578}
579
Yabin Cui1d4c7802015-02-02 19:14:05 -0800580struct ChildProcInfo {
581 pid_t pid;
582 int64_t start_time_ns;
583 int64_t end_time_ns;
584 int64_t deadline_end_time_ns; // The time when the test is thought of as timeout.
585 size_t testcase_id, test_id;
586 bool finished;
587 bool timed_out;
588 int exit_status;
589 int child_read_fd; // File descriptor to read child test failure info.
590};
591
Yabin Cui294d1e22014-12-07 20:43:37 -0800592// Forked Child process, run the single test.
593static void ChildProcessFn(int argc, char** argv, const std::string& test_name) {
Yabin Cui657b1f92015-01-22 19:26:12 -0800594 char** new_argv = new char*[argc + 2];
Yabin Cui294d1e22014-12-07 20:43:37 -0800595 memcpy(new_argv, argv, sizeof(char*) * argc);
596
597 char* filter_arg = new char [test_name.size() + 20];
598 strcpy(filter_arg, "--gtest_filter=");
599 strcat(filter_arg, test_name.c_str());
600 new_argv[argc] = filter_arg;
Yabin Cui657b1f92015-01-22 19:26:12 -0800601 new_argv[argc + 1] = NULL;
Yabin Cui294d1e22014-12-07 20:43:37 -0800602
603 int new_argc = argc + 1;
604 testing::InitGoogleTest(&new_argc, new_argv);
605 int result = RUN_ALL_TESTS();
606 exit(result);
607}
608
Yabin Cui1d4c7802015-02-02 19:14:05 -0800609static ChildProcInfo RunChildProcess(const std::string& test_name, int testcase_id, int test_id,
Yabin Cui767fb1c2015-09-01 15:06:39 -0700610 int argc, char** argv) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800611 int pipefd[2];
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800612 if (pipe(pipefd) == -1) {
613 perror("pipe in RunTestInSeparateProc");
614 exit(1);
615 }
616 if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1) {
617 perror("fcntl in RunTestInSeparateProc");
Yabin Cui1d4c7802015-02-02 19:14:05 -0800618 exit(1);
619 }
620 pid_t pid = fork();
621 if (pid == -1) {
622 perror("fork in RunTestInSeparateProc");
623 exit(1);
624 } else if (pid == 0) {
625 // In child process, run a single test.
626 close(pipefd[0]);
Yabin Cuiea9c9332015-02-24 14:39:19 -0800627 close(STDOUT_FILENO);
628 close(STDERR_FILENO);
629 dup2(pipefd[1], STDOUT_FILENO);
630 dup2(pipefd[1], STDERR_FILENO);
Yabin Cui294d1e22014-12-07 20:43:37 -0800631
Yabin Cui767fb1c2015-09-01 15:06:39 -0700632 if (!UnregisterSignalHandler()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800633 exit(1);
634 }
635 ChildProcessFn(argc, argv, test_name);
636 // Unreachable.
637 }
638 // In parent process, initialize child process info.
639 close(pipefd[1]);
640 ChildProcInfo child_proc;
641 child_proc.child_read_fd = pipefd[0];
642 child_proc.pid = pid;
643 child_proc.start_time_ns = NanoTime();
644 child_proc.deadline_end_time_ns = child_proc.start_time_ns + GetDeadlineInfo(test_name) * 1000000LL;
645 child_proc.testcase_id = testcase_id;
646 child_proc.test_id = test_id;
647 child_proc.finished = false;
648 return child_proc;
649}
Yabin Cui294d1e22014-12-07 20:43:37 -0800650
Yabin Cui1d4c7802015-02-02 19:14:05 -0800651static void HandleSignals(std::vector<TestCase>& testcase_list,
652 std::vector<ChildProcInfo>& child_proc_list) {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700653 if (sigquit_flag) {
654 sigquit_flag = false;
655 // Print current running tests.
656 printf("List of current running tests:\n");
Elliott Hughes0b2acdf2015-10-02 18:25:19 -0700657 for (const auto& child_proc : child_proc_list) {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700658 if (child_proc.pid != 0) {
659 std::string test_name = testcase_list[child_proc.testcase_id].GetTestName(child_proc.test_id);
660 int64_t current_time_ns = NanoTime();
661 int64_t run_time_ms = (current_time_ns - child_proc.start_time_ns) / 1000000;
662 printf(" %s (%" PRId64 " ms)\n", test_name.c_str(), run_time_ms);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800663 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800664 }
Yabin Cui767fb1c2015-09-01 15:06:39 -0700665 } else if (sigint_flag) {
666 sigint_flag = false;
667 // Kill current running tests.
Elliott Hughes0b2acdf2015-10-02 18:25:19 -0700668 for (const auto& child_proc : child_proc_list) {
Yabin Cui767fb1c2015-09-01 15:06:39 -0700669 if (child_proc.pid != 0) {
670 // Send SIGKILL to ensure the child process can be killed unconditionally.
671 kill(child_proc.pid, SIGKILL);
672 }
673 }
674 // SIGINT kills the parent process as well.
675 exit(1);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800676 }
677}
678
679static bool CheckChildProcExit(pid_t exit_pid, int exit_status,
680 std::vector<ChildProcInfo>& child_proc_list) {
681 for (size_t i = 0; i < child_proc_list.size(); ++i) {
682 if (child_proc_list[i].pid == exit_pid) {
683 child_proc_list[i].finished = true;
684 child_proc_list[i].timed_out = false;
685 child_proc_list[i].exit_status = exit_status;
686 child_proc_list[i].end_time_ns = NanoTime();
687 return true;
688 }
689 }
690 return false;
691}
692
693static size_t CheckChildProcTimeout(std::vector<ChildProcInfo>& child_proc_list) {
694 int64_t current_time_ns = NanoTime();
695 size_t timeout_child_count = 0;
696 for (size_t i = 0; i < child_proc_list.size(); ++i) {
697 if (child_proc_list[i].deadline_end_time_ns <= current_time_ns) {
698 child_proc_list[i].finished = true;
699 child_proc_list[i].timed_out = true;
700 child_proc_list[i].end_time_ns = current_time_ns;
701 ++timeout_child_count;
702 }
703 }
704 return timeout_child_count;
705}
706
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800707static void ReadChildProcOutput(std::vector<TestCase>& testcase_list,
708 std::vector<ChildProcInfo>& child_proc_list) {
709 for (const auto& child_proc : child_proc_list) {
710 TestCase& testcase = testcase_list[child_proc.testcase_id];
711 int test_id = child_proc.test_id;
712 while (true) {
713 char buf[1024];
714 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(child_proc.child_read_fd, buf, sizeof(buf) - 1));
715 if (bytes_read > 0) {
716 buf[bytes_read] = '\0';
717 testcase.GetTest(test_id).AppendTestOutput(buf);
718 } else if (bytes_read == 0) {
719 break; // Read end.
720 } else {
721 if (errno == EAGAIN) {
722 break;
723 }
724 perror("failed to read child_read_fd");
725 exit(1);
726 }
727 }
728 }
729}
730
Yabin Cui1d4c7802015-02-02 19:14:05 -0800731static void WaitChildProcs(std::vector<TestCase>& testcase_list,
732 std::vector<ChildProcInfo>& child_proc_list) {
733 size_t finished_child_count = 0;
734 while (true) {
735 int status;
736 pid_t result;
737 while ((result = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) {
738 if (CheckChildProcExit(result, status, child_proc_list)) {
739 ++finished_child_count;
Yabin Cui294d1e22014-12-07 20:43:37 -0800740 }
741 }
742
743 if (result == -1) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800744 if (errno == ECHILD) {
745 // This happens when we have no running child processes.
746 return;
747 } else {
748 perror("waitpid");
749 exit(1);
750 }
Yabin Cui294d1e22014-12-07 20:43:37 -0800751 } else if (result == 0) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800752 finished_child_count += CheckChildProcTimeout(child_proc_list);
Yabin Cui294d1e22014-12-07 20:43:37 -0800753 }
754
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800755 ReadChildProcOutput(testcase_list, child_proc_list);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800756 if (finished_child_count > 0) {
757 return;
758 }
759
760 HandleSignals(testcase_list, child_proc_list);
761
Yabin Cui294d1e22014-12-07 20:43:37 -0800762 // sleep 1 ms to avoid busy looping.
763 timespec sleep_time;
764 sleep_time.tv_sec = 0;
765 sleep_time.tv_nsec = 1000000;
766 nanosleep(&sleep_time, NULL);
767 }
768}
769
Yabin Cui1d4c7802015-02-02 19:14:05 -0800770static TestResult WaitForOneChild(pid_t pid) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800771 int exit_status;
Yabin Cui1d4c7802015-02-02 19:14:05 -0800772 pid_t result = TEMP_FAILURE_RETRY(waitpid(pid, &exit_status, 0));
Yabin Cui294d1e22014-12-07 20:43:37 -0800773
774 TestResult test_result = TEST_SUCCESS;
775 if (result != pid || WEXITSTATUS(exit_status) != 0) {
776 test_result = TEST_FAILED;
777 }
778 return test_result;
779}
780
Yabin Cui1d4c7802015-02-02 19:14:05 -0800781static void CollectChildTestResult(const ChildProcInfo& child_proc, TestCase& testcase) {
782 int test_id = child_proc.test_id;
783 testcase.SetTestTime(test_id, child_proc.end_time_ns - child_proc.start_time_ns);
784 if (child_proc.timed_out) {
785 // The child process marked as timed_out has not exited, and we should kill it manually.
786 kill(child_proc.pid, SIGKILL);
787 WaitForOneChild(child_proc.pid);
788 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800789 close(child_proc.child_read_fd);
790
791 if (child_proc.timed_out) {
792 testcase.SetTestResult(test_id, TEST_TIMEOUT);
793 char buf[1024];
794 snprintf(buf, sizeof(buf), "%s killed because of timeout at %" PRId64 " ms.\n",
795 testcase.GetTestName(test_id).c_str(), testcase.GetTestTime(test_id) / 1000000);
Yabin Cuiea9c9332015-02-24 14:39:19 -0800796 testcase.GetTest(test_id).AppendTestOutput(buf);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800797
798 } else if (WIFSIGNALED(child_proc.exit_status)) {
799 // Record signal terminated test as failed.
800 testcase.SetTestResult(test_id, TEST_FAILED);
801 char buf[1024];
802 snprintf(buf, sizeof(buf), "%s terminated by signal: %s.\n",
803 testcase.GetTestName(test_id).c_str(), strsignal(WTERMSIG(child_proc.exit_status)));
Yabin Cuiea9c9332015-02-24 14:39:19 -0800804 testcase.GetTest(test_id).AppendTestOutput(buf);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800805
806 } else {
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800807 int exitcode = WEXITSTATUS(child_proc.exit_status);
808 testcase.SetTestResult(test_id, exitcode == 0 ? TEST_SUCCESS : TEST_FAILED);
809 if (exitcode != 0) {
Yabin Cuia32fc862015-12-03 16:28:03 -0800810 char buf[1024];
811 snprintf(buf, sizeof(buf), "%s exited with exitcode %d.\n",
812 testcase.GetTestName(test_id).c_str(), exitcode);
813 testcase.GetTest(test_id).AppendTestOutput(buf);
Yabin Cuid4c9b9d2015-11-16 20:39:58 -0800814 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800815 }
816}
817
Yabin Cui294d1e22014-12-07 20:43:37 -0800818// We choose to use multi-fork and multi-wait here instead of multi-thread, because it always
819// makes deadlock to use fork in multi-thread.
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700820// Returns true if all tests run successfully, otherwise return false.
821static bool RunTestInSeparateProc(int argc, char** argv, std::vector<TestCase>& testcase_list,
Christopher Ferris119cb552015-04-02 12:02:55 -0700822 int iteration_count, size_t job_count,
Yabin Cui657b1f92015-01-22 19:26:12 -0800823 const std::string& xml_output_filename) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800824 // Stop default result printer to avoid environment setup/teardown information for each test.
825 testing::UnitTest::GetInstance()->listeners().Release(
826 testing::UnitTest::GetInstance()->listeners().default_result_printer());
827 testing::UnitTest::GetInstance()->listeners().Append(new TestResultPrinter);
828
Yabin Cui767fb1c2015-09-01 15:06:39 -0700829 if (!RegisterSignalHandler()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800830 exit(1);
831 }
832
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700833 bool all_tests_passed = true;
834
Christopher Ferris119cb552015-04-02 12:02:55 -0700835 for (size_t iteration = 1;
836 iteration_count < 0 || iteration <= static_cast<size_t>(iteration_count);
837 ++iteration) {
Yabin Cuibe837362015-01-02 18:45:37 -0800838 OnTestIterationStartPrint(testcase_list, iteration, iteration_count);
Yabin Cui657b1f92015-01-22 19:26:12 -0800839 int64_t iteration_start_time_ns = NanoTime();
840 time_t epoch_iteration_start_time = time(NULL);
Yabin Cui294d1e22014-12-07 20:43:37 -0800841
Yabin Cuibe837362015-01-02 18:45:37 -0800842 // Run up to job_count tests in parallel, each test in a child process.
Yabin Cui1d4c7802015-02-02 19:14:05 -0800843 std::vector<ChildProcInfo> child_proc_list;
Yabin Cui294d1e22014-12-07 20:43:37 -0800844
Yabin Cuibe837362015-01-02 18:45:37 -0800845 // Next test to run is [next_testcase_id:next_test_id].
846 size_t next_testcase_id = 0;
847 size_t next_test_id = 0;
848
849 // Record how many tests are finished.
850 std::vector<size_t> finished_test_count_list(testcase_list.size(), 0);
851 size_t finished_testcase_count = 0;
852
853 while (finished_testcase_count < testcase_list.size()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800854 // run up to job_count child processes.
855 while (child_proc_list.size() < job_count && next_testcase_id < testcase_list.size()) {
856 std::string test_name = testcase_list[next_testcase_id].GetTestName(next_test_id);
857 ChildProcInfo child_proc = RunChildProcess(test_name, next_testcase_id, next_test_id,
Yabin Cui767fb1c2015-09-01 15:06:39 -0700858 argc, argv);
Yabin Cui1d4c7802015-02-02 19:14:05 -0800859 child_proc_list.push_back(child_proc);
860 if (++next_test_id == testcase_list[next_testcase_id].TestCount()) {
861 next_test_id = 0;
862 ++next_testcase_id;
Yabin Cui294d1e22014-12-07 20:43:37 -0800863 }
864 }
865
866 // Wait for any child proc finish or timeout.
Yabin Cui1d4c7802015-02-02 19:14:05 -0800867 WaitChildProcs(testcase_list, child_proc_list);
Yabin Cui294d1e22014-12-07 20:43:37 -0800868
869 // Collect result.
Yabin Cui1d4c7802015-02-02 19:14:05 -0800870 auto it = child_proc_list.begin();
871 while (it != child_proc_list.end()) {
872 auto& child_proc = *it;
873 if (child_proc.finished == true) {
Yabin Cuibe837362015-01-02 18:45:37 -0800874 size_t testcase_id = child_proc.testcase_id;
875 size_t test_id = child_proc.test_id;
876 TestCase& testcase = testcase_list[testcase_id];
Yabin Cuibe837362015-01-02 18:45:37 -0800877
Yabin Cui1d4c7802015-02-02 19:14:05 -0800878 CollectChildTestResult(child_proc, testcase);
Yabin Cui657b1f92015-01-22 19:26:12 -0800879 OnTestEndPrint(testcase, test_id);
Yabin Cuibe837362015-01-02 18:45:37 -0800880
881 if (++finished_test_count_list[testcase_id] == testcase.TestCount()) {
882 ++finished_testcase_count;
Yabin Cui294d1e22014-12-07 20:43:37 -0800883 }
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700884 if (testcase.GetTestResult(test_id) != TEST_SUCCESS) {
885 all_tests_passed = false;
886 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800887
888 it = child_proc_list.erase(it);
889 } else {
890 ++it;
Yabin Cui294d1e22014-12-07 20:43:37 -0800891 }
892 }
893 }
894
Yabin Cui657b1f92015-01-22 19:26:12 -0800895 int64_t elapsed_time_ns = NanoTime() - iteration_start_time_ns;
896 OnTestIterationEndPrint(testcase_list, iteration, elapsed_time_ns);
897 if (!xml_output_filename.empty()) {
898 OnTestIterationEndXmlPrint(xml_output_filename, testcase_list, epoch_iteration_start_time,
899 elapsed_time_ns);
900 }
Yabin Cui294d1e22014-12-07 20:43:37 -0800901 }
Yabin Cui1d4c7802015-02-02 19:14:05 -0800902
Yabin Cui767fb1c2015-09-01 15:06:39 -0700903 if (!UnregisterSignalHandler()) {
Yabin Cui1d4c7802015-02-02 19:14:05 -0800904 exit(1);
905 }
Yabin Cui64a9c4f2015-03-12 22:16:03 -0700906
907 return all_tests_passed;
Yabin Cui294d1e22014-12-07 20:43:37 -0800908}
909
Christopher Ferrisdaaaed12015-09-24 18:45:53 -0700910static size_t GetDefaultJobCount() {
Yabin Cuibe837362015-01-02 18:45:37 -0800911 return static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
Yabin Cui294d1e22014-12-07 20:43:37 -0800912}
913
Yabin Cuiead08142015-02-04 20:53:56 -0800914static void AddPathSeparatorInTestProgramPath(std::vector<char*>& args) {
915 // To run DeathTest in threadsafe mode, gtest requires that the user must invoke the
916 // test program via a valid path that contains at least one path separator.
917 // The reason is that gtest uses clone() + execve() to run DeathTest in threadsafe mode,
918 // and execve() doesn't read environment variable PATH, so execve() will not success
919 // until we specify the absolute path or relative path of the test program directly.
920 if (strchr(args[0], '/') == NULL) {
921 char path[PATH_MAX];
922 ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
923 if (path_len <= 0 || path_len >= static_cast<ssize_t>(sizeof(path))) {
924 perror("readlink");
925 exit(1);
926 }
927 path[path_len] = '\0';
928 args[0] = strdup(path);
929 }
930}
931
Yabin Cui11c43532015-01-28 14:28:14 -0800932static void AddGtestFilterSynonym(std::vector<char*>& args) {
933 // Support --gtest-filter as a synonym for --gtest_filter.
934 for (size_t i = 1; i < args.size(); ++i) {
935 if (strncmp(args[i], "--gtest-filter", strlen("--gtest-filter")) == 0) {
936 args[i][7] = '_';
937 }
938 }
939}
940
Yabin Cui657b1f92015-01-22 19:26:12 -0800941struct IsolationTestOptions {
942 bool isolate;
943 size_t job_count;
944 int test_deadline_ms;
945 int test_warnline_ms;
946 std::string gtest_color;
947 bool gtest_print_time;
Christopher Ferris119cb552015-04-02 12:02:55 -0700948 int gtest_repeat;
Yabin Cui657b1f92015-01-22 19:26:12 -0800949 std::string gtest_output;
950};
951
952// 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 -0800953// as described in PrintHelpInfo(), the other part is handled by testing::InitGoogleTest() in
Yabin Cui657b1f92015-01-22 19:26:12 -0800954// gtest. PickOptions() picks the first part into IsolationTestOptions structure, leaving the second
955// part in args.
Yabin Cuibe837362015-01-02 18:45:37 -0800956// Arguments:
Yabin Cui657b1f92015-01-22 19:26:12 -0800957// args is used to pass in all command arguments, and pass out only the part of options for gtest.
958// options is used to pass out test options in isolation mode.
959// Return false if there is error in arguments.
960static bool PickOptions(std::vector<char*>& args, IsolationTestOptions& options) {
961 for (size_t i = 1; i < args.size(); ++i) {
962 if (strcmp(args[i], "--help") == 0 || strcmp(args[i], "-h") == 0) {
Yabin Cui294d1e22014-12-07 20:43:37 -0800963 PrintHelpInfo();
Yabin Cui657b1f92015-01-22 19:26:12 -0800964 options.isolate = false;
Yabin Cui294d1e22014-12-07 20:43:37 -0800965 return true;
966 }
967 }
968
Yabin Cuiead08142015-02-04 20:53:56 -0800969 AddPathSeparatorInTestProgramPath(args);
Yabin Cui11c43532015-01-28 14:28:14 -0800970 AddGtestFilterSynonym(args);
971
Yabin Cui657b1f92015-01-22 19:26:12 -0800972 // if --bionic-selftest argument is used, only enable self tests, otherwise remove self tests.
973 bool enable_selftest = false;
974 for (size_t i = 1; i < args.size(); ++i) {
975 if (strcmp(args[i], "--bionic-selftest") == 0) {
976 // This argument is to enable "bionic_selftest*" for self test, and is not shown in help info.
977 // Don't remove this option from arguments.
978 enable_selftest = true;
979 }
980 }
981 std::string gtest_filter_str;
982 for (size_t i = args.size() - 1; i >= 1; --i) {
983 if (strncmp(args[i], "--gtest_filter=", strlen("--gtest_filter=")) == 0) {
984 gtest_filter_str = std::string(args[i]);
985 args.erase(args.begin() + i);
Yabin Cui294d1e22014-12-07 20:43:37 -0800986 break;
987 }
988 }
Yabin Cui657b1f92015-01-22 19:26:12 -0800989 if (enable_selftest == true) {
990 args.push_back(strdup("--gtest_filter=bionic_selftest*"));
991 } else {
992 if (gtest_filter_str == "") {
993 gtest_filter_str = "--gtest_filter=-bionic_selftest*";
994 } else {
Yabin Cui0bc4e962015-01-27 11:22:46 -0800995 // Find if '-' for NEGATIVE_PATTERNS exists.
996 if (gtest_filter_str.find(":-") != std::string::npos) {
997 gtest_filter_str += ":bionic_selftest*";
998 } else {
999 gtest_filter_str += ":-bionic_selftest*";
1000 }
Yabin Cui657b1f92015-01-22 19:26:12 -08001001 }
1002 args.push_back(strdup(gtest_filter_str.c_str()));
1003 }
Yabin Cui294d1e22014-12-07 20:43:37 -08001004
Yabin Cui657b1f92015-01-22 19:26:12 -08001005 options.isolate = true;
1006 // Parse arguments that make us can't run in isolation mode.
1007 for (size_t i = 1; i < args.size(); ++i) {
1008 if (strcmp(args[i], "--no-isolate") == 0) {
1009 options.isolate = false;
1010 } else if (strcmp(args[i], "--gtest_list_tests") == 0) {
1011 options.isolate = false;
Yabin Cui294d1e22014-12-07 20:43:37 -08001012 }
1013 }
1014
Yabin Cui657b1f92015-01-22 19:26:12 -08001015 // Stop parsing if we will not run in isolation mode.
1016 if (options.isolate == false) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001017 return true;
1018 }
Yabin Cui657b1f92015-01-22 19:26:12 -08001019
1020 // Init default isolation test options.
Christopher Ferrisdaaaed12015-09-24 18:45:53 -07001021 options.job_count = GetDefaultJobCount();
Yabin Cui657b1f92015-01-22 19:26:12 -08001022 options.test_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
1023 options.test_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
1024 options.gtest_color = testing::GTEST_FLAG(color);
1025 options.gtest_print_time = testing::GTEST_FLAG(print_time);
1026 options.gtest_repeat = testing::GTEST_FLAG(repeat);
1027 options.gtest_output = testing::GTEST_FLAG(output);
1028
1029 // Parse arguments speficied for isolation mode.
1030 for (size_t i = 1; i < args.size(); ++i) {
1031 if (strncmp(args[i], "-j", strlen("-j")) == 0) {
1032 char* p = args[i] + strlen("-j");
1033 int count = 0;
1034 if (*p != '\0') {
1035 // Argument like -j5.
1036 count = atoi(p);
1037 } else if (args.size() > i + 1) {
1038 // Arguments like -j 5.
1039 count = atoi(args[i + 1]);
1040 ++i;
1041 }
1042 if (count <= 0) {
1043 fprintf(stderr, "invalid job count: %d\n", count);
1044 return false;
1045 }
1046 options.job_count = static_cast<size_t>(count);
1047 } else if (strncmp(args[i], "--deadline=", strlen("--deadline=")) == 0) {
1048 int time_ms = atoi(args[i] + strlen("--deadline="));
1049 if (time_ms <= 0) {
1050 fprintf(stderr, "invalid deadline: %d\n", time_ms);
1051 return false;
1052 }
1053 options.test_deadline_ms = time_ms;
1054 } else if (strncmp(args[i], "--warnline=", strlen("--warnline=")) == 0) {
1055 int time_ms = atoi(args[i] + strlen("--warnline="));
1056 if (time_ms <= 0) {
1057 fprintf(stderr, "invalid warnline: %d\n", time_ms);
1058 return false;
1059 }
1060 options.test_warnline_ms = time_ms;
1061 } else if (strncmp(args[i], "--gtest_color=", strlen("--gtest_color=")) == 0) {
1062 options.gtest_color = args[i] + strlen("--gtest_color=");
1063 } else if (strcmp(args[i], "--gtest_print_time=0") == 0) {
1064 options.gtest_print_time = false;
1065 } else if (strncmp(args[i], "--gtest_repeat=", strlen("--gtest_repeat=")) == 0) {
Christopher Ferris119cb552015-04-02 12:02:55 -07001066 // If the value of gtest_repeat is < 0, then it indicates the tests
1067 // should be repeated forever.
1068 options.gtest_repeat = atoi(args[i] + strlen("--gtest_repeat="));
Yabin Cui657b1f92015-01-22 19:26:12 -08001069 // Remove --gtest_repeat=xx from arguments, so child process only run one iteration for a single test.
1070 args.erase(args.begin() + i);
1071 --i;
1072 } else if (strncmp(args[i], "--gtest_output=", strlen("--gtest_output=")) == 0) {
1073 std::string output = args[i] + strlen("--gtest_output=");
1074 // generate output xml file path according to the strategy in gtest.
1075 bool success = true;
1076 if (strncmp(output.c_str(), "xml:", strlen("xml:")) == 0) {
1077 output = output.substr(strlen("xml:"));
1078 if (output.size() == 0) {
1079 success = false;
1080 }
1081 // Make absolute path.
1082 if (success && output[0] != '/') {
1083 char* cwd = getcwd(NULL, 0);
1084 if (cwd != NULL) {
1085 output = std::string(cwd) + "/" + output;
1086 free(cwd);
1087 } else {
1088 success = false;
1089 }
1090 }
1091 // Add file name if output is a directory.
1092 if (success && output.back() == '/') {
1093 output += "test_details.xml";
1094 }
1095 }
1096 if (success) {
1097 options.gtest_output = output;
1098 } else {
1099 fprintf(stderr, "invalid gtest_output file: %s\n", args[i]);
1100 return false;
1101 }
1102
1103 // Remove --gtest_output=xxx from arguments, so child process will not write xml file.
1104 args.erase(args.begin() + i);
1105 --i;
1106 }
1107 }
1108
1109 // Add --no-isolate in args to prevent child process from running in isolation mode again.
1110 // As DeathTest will try to call execve(), this argument should always be added.
1111 args.insert(args.begin() + 1, strdup("--no-isolate"));
Yabin Cui294d1e22014-12-07 20:43:37 -08001112 return true;
1113}
1114
1115int main(int argc, char** argv) {
Yabin Cuibe837362015-01-02 18:45:37 -08001116 std::vector<char*> arg_list;
1117 for (int i = 0; i < argc; ++i) {
1118 arg_list.push_back(argv[i]);
1119 }
Yabin Cuibe837362015-01-02 18:45:37 -08001120
Yabin Cui657b1f92015-01-22 19:26:12 -08001121 IsolationTestOptions options;
1122 if (PickOptions(arg_list, options) == false) {
1123 return 1;
Yabin Cui294d1e22014-12-07 20:43:37 -08001124 }
Yabin Cui657b1f92015-01-22 19:26:12 -08001125
1126 if (options.isolate == true) {
1127 // Set global variables.
1128 global_test_run_deadline_ms = options.test_deadline_ms;
1129 global_test_run_warnline_ms = options.test_warnline_ms;
1130 testing::GTEST_FLAG(color) = options.gtest_color.c_str();
1131 testing::GTEST_FLAG(print_time) = options.gtest_print_time;
1132 std::vector<TestCase> testcase_list;
1133
1134 argc = static_cast<int>(arg_list.size());
1135 arg_list.push_back(NULL);
1136 if (EnumerateTests(argc, arg_list.data(), testcase_list) == false) {
1137 return 1;
1138 }
Yabin Cui64a9c4f2015-03-12 22:16:03 -07001139 bool all_test_passed = RunTestInSeparateProc(argc, arg_list.data(), testcase_list,
1140 options.gtest_repeat, options.job_count, options.gtest_output);
1141 return all_test_passed ? 0 : 1;
Yabin Cui657b1f92015-01-22 19:26:12 -08001142 } else {
1143 argc = static_cast<int>(arg_list.size());
1144 arg_list.push_back(NULL);
1145 testing::InitGoogleTest(&argc, arg_list.data());
1146 return RUN_ALL_TESTS();
1147 }
Yabin Cui294d1e22014-12-07 20:43:37 -08001148}
1149
1150//################################################################################
Yabin Cuibe837362015-01-02 18:45:37 -08001151// Bionic Gtest self test, run this by --bionic-selftest option.
Yabin Cui294d1e22014-12-07 20:43:37 -08001152
Yabin Cuibe837362015-01-02 18:45:37 -08001153TEST(bionic_selftest, test_success) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001154 ASSERT_EQ(1, 1);
1155}
1156
Yabin Cuibe837362015-01-02 18:45:37 -08001157TEST(bionic_selftest, test_fail) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001158 ASSERT_EQ(0, 1);
1159}
1160
Yabin Cuibe837362015-01-02 18:45:37 -08001161TEST(bionic_selftest, test_time_warn) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001162 sleep(4);
1163}
1164
Yabin Cuibe837362015-01-02 18:45:37 -08001165TEST(bionic_selftest, test_timeout) {
Yabin Cui294d1e22014-12-07 20:43:37 -08001166 while (1) {}
1167}
Yabin Cuibe837362015-01-02 18:45:37 -08001168
1169TEST(bionic_selftest, test_signal_SEGV_terminated) {
1170 char* p = reinterpret_cast<char*>(static_cast<intptr_t>(atoi("0")));
1171 *p = 3;
1172}
Yabin Cui657b1f92015-01-22 19:26:12 -08001173
Yabin Cui767fb1c2015-09-01 15:06:39 -07001174class bionic_selftest_DeathTest : public ::testing::Test {
1175 protected:
1176 virtual void SetUp() {
1177 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
1178 }
1179};
Yabin Cui657b1f92015-01-22 19:26:12 -08001180
1181static void deathtest_helper_success() {
1182 ASSERT_EQ(1, 1);
1183 exit(0);
1184}
1185
1186TEST_F(bionic_selftest_DeathTest, success) {
1187 ASSERT_EXIT(deathtest_helper_success(), ::testing::ExitedWithCode(0), "");
1188}
1189
1190static void deathtest_helper_fail() {
1191 ASSERT_EQ(1, 0);
1192}
1193
1194TEST_F(bionic_selftest_DeathTest, fail) {
1195 ASSERT_EXIT(deathtest_helper_fail(), ::testing::ExitedWithCode(0), "");
1196}