aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2017-11-14 13:11:41 -0800
committerElliott Hughes <enh@google.com>2017-11-15 09:30:16 -0800
commit10ba4bd6d1e99faf05f058ab0de7708210d1f33e (patch)
tree97ac05daefae6d069e801ba609a8a408181f7a29
parent40a5cfa8d11c7a36c546eb9acff19975a99450ce (diff)
downloadbionic-10ba4bd6d1e99faf05f058ab0de7708210d1f33e.tar.gz
Reduce unnecessary quoting for --gtest_filter.
Use posix_spawn rather than popen, to remove a surprising extra shell. Bug: http://b/68949647 Test: /data/nativetest64/bionic-unit-tests/bionic-unit-tests --gtest_filter=stdio.swprintf_1$ju_UINTMAX_MAX Change-Id: Id90afab04ee799932de9f5ca7e580e61ecfde7a4
-rw-r--r--tests/Android.bp6
-rw-r--r--tests/gtest_main.cpp86
2 files changed, 56 insertions, 36 deletions
diff --git a/tests/Android.bp b/tests/Android.bp
index 6ec3c3c01..c045c1ec5 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -286,8 +286,9 @@ cc_test_library {
"gtest_main.cpp",
"gtest_globals.cpp",
],
- static_libs: [
+ whole_static_libs: [
"libbase",
+ "liblog",
],
include_dirs: [
"bionic/libc",
@@ -354,6 +355,9 @@ cc_test_library {
"gtest_main.cpp",
"gtest_globals_cts.cpp",
],
+ static_libs: [
+ "libbase",
+ ],
cppflags: ["-DUSING_GTEST_OUTPUT_FORMAT"],
shared: {
enabled: false,
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 9dcc000a0..781acce8c 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -23,6 +23,7 @@
#include <libgen.h>
#include <limits.h>
#include <signal.h>
+#include <spawn.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@@ -35,6 +36,10 @@
#include <utility>
#include <vector>
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+
#ifndef TEMP_FAILURE_RETRY
/* Used to retry syscalls that can return EINTR. */
@@ -269,49 +274,60 @@ static int64_t NanoTime() {
}
static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcase_list) {
- std::string command;
- for (int i = 0; i < argc; ++i) {
- command += argv[i];
- command += " ";
+ std::vector<const char*> args;
+ for (int i = 0; i < argc; ++i) args.push_back(argv[i]);
+ args.push_back("--gtest_list_tests");
+ args.push_back(nullptr);
+
+ // We use posix_spawn(3) rather than the simpler popen(3) because we don't want an intervening
+ // surprise shell invocation making quoting interesting for --gtest_filter (http://b/68949647).
+
+ android::base::unique_fd read_fd;
+ android::base::unique_fd write_fd;
+ if (!android::base::Pipe(&read_fd, &write_fd)) {
+ perror("pipe");
+ return false;
}
- command += "--gtest_list_tests";
- FILE* fp = popen(command.c_str(), "r");
- if (fp == NULL) {
- perror("popen");
+
+ posix_spawn_file_actions_t fa;
+ posix_spawn_file_actions_init(&fa);
+ posix_spawn_file_actions_addclose(&fa, read_fd);
+ posix_spawn_file_actions_adddup2(&fa, write_fd, 1);
+ posix_spawn_file_actions_adddup2(&fa, write_fd, 2);
+ posix_spawn_file_actions_addclose(&fa, write_fd);
+
+ pid_t pid;
+ int result = posix_spawnp(&pid, argv[0], &fa, nullptr, const_cast<char**>(args.data()), nullptr);
+ posix_spawn_file_actions_destroy(&fa);
+ if (result == -1) {
+ perror("posix_spawn");
return false;
}
+ write_fd.reset();
- char buf[200];
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- char* p = buf;
+ std::string content;
+ if (!android::base::ReadFdToString(read_fd, &content)) {
+ perror("ReadFdToString");
+ return false;
+ }
- while (*p != '\0' && isspace(*p)) {
- ++p;
- }
- if (*p == '\0') continue;
- char* start = p;
- while (*p != '\0' && !isspace(*p)) {
- ++p;
- }
- char* end = p;
- while (*p != '\0' && isspace(*p)) {
- ++p;
- }
- if (*p != '\0' && *p != '#') {
- // This is not we want, gtest must meet with some error when parsing the arguments.
- fprintf(stderr, "argument error, check with --help\n");
- return false;
- }
- *end = '\0';
- if (*(end - 1) == '.') {
- *(end - 1) = '\0';
- testcase_list.push_back(TestCase(start));
+ for (auto& line : android::base::Split(content, "\n")) {
+ line = android::base::Trim(line);
+ if (line.empty()) continue;
+ if (android::base::EndsWith(line, ".")) {
+ line.pop_back();
+ testcase_list.push_back(TestCase(line.c_str()));
} else {
- testcase_list.back().AppendTest(start);
+ testcase_list.back().AppendTest(line.c_str());
}
}
- int result = pclose(fp);
- return (result != -1 && WEXITSTATUS(result) == 0);
+
+ int status;
+ if (waitpid(pid, &status, 0) != pid) {
+ perror("waitpid");
+ return false;
+ }
+ return (WIFEXITED(status) && WEXITSTATUS(status) == 0);
}
// Part of the following *Print functions are copied from external/gtest/src/gtest.cc: