diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h index 5d22f24f..11798a1a 100644 --- a/include/gtest/internal/gtest-port.h +++ b/include/gtest/internal/gtest-port.h @@ -376,12 +376,13 @@ // (this is covered by GTEST_HAS_STD_STRING guard). // 3. abort() in a VC 7.1 application compiled as GUI in debug config // pops up a dialog window that cannot be suppressed programmatically. -#if GTEST_HAS_STD_STRING && (GTEST_HAS_CLONE || \ - GTEST_OS_WINDOWS && _MSC_VER >= 1400) +#if GTEST_HAS_STD_STRING && (GTEST_OS_LINUX || \ + GTEST_OS_MAC || \ + GTEST_OS_CYGWIN || \ + (GTEST_OS_WINDOWS && _MSC_VER >= 1400)) #define GTEST_HAS_DEATH_TEST 1 #include -#endif // GTEST_HAS_STD_STRING && (GTEST_HAS_CLONE || - // GTEST_OS_WINDOWS && _MSC_VER >= 1400) +#endif // Determines whether to support value-parameterized tests. diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc index d9695864..7e7dd608 100644 --- a/src/gtest-death-test.cc +++ b/src/gtest-death-test.cc @@ -35,6 +35,11 @@ #include #if GTEST_HAS_DEATH_TEST + +#if GTEST_OS_MAC +#include +#endif // GTEST_OS_MAC + #include #include #include @@ -44,6 +49,7 @@ #include #else #include +#include #endif // GTEST_OS_WINDOWS #endif // GTEST_HAS_DEATH_TEST @@ -80,8 +86,9 @@ GTEST_DEFINE_bool_( death_test_use_fork, internal::BoolFromGTestEnv("death_test_use_fork", false), "Instructs to use fork()/_exit() instead of clone() in death tests. " - "Useful when running under valgrind or similar tools if those " - "do not support clone(). Valgrind 3.3.1 will just fail if " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " "it sees an unsupported combination of clone() flags. " "It is not recommended to use this flag w/o valgrind though it will " "work in 99% of the cases. Once valgrind is fixed, this flag will " @@ -963,6 +970,22 @@ struct ExecDeathTestArgs { int close_fd; // File descriptor to close; the read end of a pipe }; +#if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +#else +extern "C" char** environ; // Some POSIX platforms expect you + // to declare environ. extern "C" makes + // it reside in the global namespace. +inline char** GetEnviron() { + return environ; +} +#endif // GTEST_OS_MAC + // The main function for a threadsafe-style death test child process. // This function is called in a clone()-ed process and thus must avoid // any potentially unsafe operations like malloc or libc functions. @@ -988,7 +1011,7 @@ static int ExecDeathTestChildMain(void* child_arg) { // unsafe. Since execve() doesn't search the PATH, the user must // invoke the test program via a valid path that contains at least // one path separator. - execve(args->argv[0], args->argv, environ); + execve(args->argv[0], args->argv, GetEnviron()); DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s", args->argv[0], original_dir, @@ -1001,12 +1024,12 @@ static int ExecDeathTestChildMain(void* child_arg) { // This could be accomplished more elegantly by a single recursive // function, but we want to guard against the unlikely possibility of // a smart compiler optimizing the recursion away. -static bool StackLowerThanAddress(const void* ptr) { +bool StackLowerThanAddress(const void* ptr) { int dummy; return &dummy < ptr; } -static bool StackGrowsDown() { +bool StackGrowsDown() { int dummy; return StackLowerThanAddress(&dummy); } @@ -1015,28 +1038,36 @@ static bool StackGrowsDown() { // that uses clone(2). It dies with an error message if anything goes // wrong. static pid_t ExecDeathTestFork(char* const* argv, int close_fd) { - static const bool stack_grows_down = StackGrowsDown(); - const size_t stack_size = getpagesize(); - void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); - void* const stack_top = - static_cast(stack) + (stack_grows_down ? stack_size : 0); ExecDeathTestArgs args = { argv, close_fd }; pid_t child_pid; - if (GTEST_FLAG(death_test_use_fork)) { - // Valgrind-friendly version. As of valgrind 3.3.1 the clone() call below - // is not supported (valgrind will fail with an error message). - if ((child_pid = fork()) == 0) { + +#if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + void* const stack_top = + static_cast(stack) + (stack_grows_down ? stack_size : 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +#else + const bool use_fork = true; +#endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { ExecDeathTestChildMain(&args); _exit(0); - } - } else { - child_pid = clone(&ExecDeathTestChildMain, stack_top, - SIGCHLD, &args); } + GTEST_DEATH_TEST_CHECK_(child_pid != -1); - GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); return child_pid; } diff --git a/test/gtest-death-test_test.cc b/test/gtest-death-test_test.cc index aa7e31cd..2c283b63 100644 --- a/test/gtest-death-test_test.cc +++ b/test/gtest-death-test_test.cc @@ -41,6 +41,7 @@ #include // For chdir(). #else #include +#include // For waitpid. #include // For std::numeric_limits. #endif // GTEST_OS_WINDOWS @@ -414,7 +415,7 @@ void SetPthreadFlag() { } // namespace -#if !GTEST_OS_WINDOWS +#if GTEST_HAS_CLONE TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) { if (!testing::GTEST_FLAG(death_test_use_fork)) { @@ -426,7 +427,7 @@ TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) { } } -#endif // !GTEST_OS_WINDOWS +#endif // GTEST_HAS_CLONE // Tests that a method of another class can be used in a death test. TEST_F(TestForDeathTest, MethodOfAnotherClass) { diff --git a/test/gtest_filter_unittest.py b/test/gtest_filter_unittest.py index c3a016cf..cd88cdf7 100755 --- a/test/gtest_filter_unittest.py +++ b/test/gtest_filter_unittest.py @@ -202,7 +202,7 @@ class GTestFilterUnitTest(unittest.TestCase): for slice_var in list_of_sets: full_partition.extend(slice_var) self.assertEqual(len(set_var), len(full_partition)) - self.assertEqual(sorted(set_var), sorted(full_partition)) + self.assertEqual(sets.Set(set_var), sets.Set(full_partition)) def RunAndVerify(self, gtest_filter, tests_to_run): """Runs gtest_flag_unittest_ with the given filter, and verifies