diff options
author | Elliott Hughes <enh@google.com> | 2017-11-14 13:11:41 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2017-11-15 09:30:16 -0800 |
commit | 10ba4bd6d1e99faf05f058ab0de7708210d1f33e (patch) | |
tree | 97ac05daefae6d069e801ba609a8a408181f7a29 | |
parent | 40a5cfa8d11c7a36c546eb9acff19975a99450ce (diff) | |
download | bionic-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.bp | 6 | ||||
-rw-r--r-- | tests/gtest_main.cpp | 86 |
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: |