Enables death tests on Cygwin and Mac (by Vlad Losev); fixes a python test on Mac.

This commit is contained in:
zhanyong.wan 2009-03-17 21:03:35 +00:00
parent 62f8d28c0b
commit 9623aed82c
4 changed files with 61 additions and 28 deletions

View File

@ -376,12 +376,13 @@
// (this is covered by GTEST_HAS_STD_STRING guard). // (this is covered by GTEST_HAS_STD_STRING guard).
// 3. abort() in a VC 7.1 application compiled as GUI in debug config // 3. abort() in a VC 7.1 application compiled as GUI in debug config
// pops up a dialog window that cannot be suppressed programmatically. // pops up a dialog window that cannot be suppressed programmatically.
#if GTEST_HAS_STD_STRING && (GTEST_HAS_CLONE || \ #if GTEST_HAS_STD_STRING && (GTEST_OS_LINUX || \
GTEST_OS_WINDOWS && _MSC_VER >= 1400) GTEST_OS_MAC || \
GTEST_OS_CYGWIN || \
(GTEST_OS_WINDOWS && _MSC_VER >= 1400))
#define GTEST_HAS_DEATH_TEST 1 #define GTEST_HAS_DEATH_TEST 1
#include <vector> #include <vector>
#endif // GTEST_HAS_STD_STRING && (GTEST_HAS_CLONE || #endif
// GTEST_OS_WINDOWS && _MSC_VER >= 1400)
// Determines whether to support value-parameterized tests. // Determines whether to support value-parameterized tests.

View File

@ -35,6 +35,11 @@
#include <gtest/internal/gtest-port.h> #include <gtest/internal/gtest-port.h>
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
#if GTEST_OS_MAC
#include <crt_externs.h>
#endif // GTEST_OS_MAC
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
@ -44,6 +49,7 @@
#include <windows.h> #include <windows.h>
#else #else
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/wait.h>
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
@ -80,8 +86,9 @@ GTEST_DEFINE_bool_(
death_test_use_fork, death_test_use_fork,
internal::BoolFromGTestEnv("death_test_use_fork", false), internal::BoolFromGTestEnv("death_test_use_fork", false),
"Instructs to use fork()/_exit() instead of clone() in death tests. " "Instructs to use fork()/_exit() instead of clone() in death tests. "
"Useful when running under valgrind or similar tools if those " "Ignored and always uses fork() on POSIX systems where clone() is not "
"do not support clone(). Valgrind 3.3.1 will just fail if " "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 sees an unsupported combination of clone() flags. "
"It is not recommended to use this flag w/o valgrind though it will " "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 " "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 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. // The main function for a threadsafe-style death test child process.
// This function is called in a clone()-ed process and thus must avoid // This function is called in a clone()-ed process and thus must avoid
// any potentially unsafe operations like malloc or libc functions. // 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 // unsafe. Since execve() doesn't search the PATH, the user must
// invoke the test program via a valid path that contains at least // invoke the test program via a valid path that contains at least
// one path separator. // 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", DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s",
args->argv[0], args->argv[0],
original_dir, original_dir,
@ -1001,12 +1024,12 @@ static int ExecDeathTestChildMain(void* child_arg) {
// This could be accomplished more elegantly by a single recursive // This could be accomplished more elegantly by a single recursive
// function, but we want to guard against the unlikely possibility of // function, but we want to guard against the unlikely possibility of
// a smart compiler optimizing the recursion away. // a smart compiler optimizing the recursion away.
static bool StackLowerThanAddress(const void* ptr) { bool StackLowerThanAddress(const void* ptr) {
int dummy; int dummy;
return &dummy < ptr; return &dummy < ptr;
} }
static bool StackGrowsDown() { bool StackGrowsDown() {
int dummy; int dummy;
return StackLowerThanAddress(&dummy); return StackLowerThanAddress(&dummy);
} }
@ -1015,28 +1038,36 @@ static bool StackGrowsDown() {
// that uses clone(2). It dies with an error message if anything goes // that uses clone(2). It dies with an error message if anything goes
// wrong. // wrong.
static pid_t ExecDeathTestFork(char* const* argv, int close_fd) { 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<char*>(stack) + (stack_grows_down ? stack_size : 0);
ExecDeathTestArgs args = { argv, close_fd }; ExecDeathTestArgs args = { argv, close_fd };
pid_t child_pid; pid_t child_pid;
if (GTEST_FLAG(death_test_use_fork)) {
// Valgrind-friendly version. As of valgrind 3.3.1 the clone() call below #if GTEST_HAS_CLONE
// is not supported (valgrind will fail with an error message). const bool use_fork = GTEST_FLAG(death_test_use_fork);
if ((child_pid = fork()) == 0) {
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<char*>(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); ExecDeathTestChildMain(&args);
_exit(0); _exit(0);
}
} else {
child_pid = clone(&ExecDeathTestChildMain, stack_top,
SIGCHLD, &args);
} }
GTEST_DEATH_TEST_CHECK_(child_pid != -1); GTEST_DEATH_TEST_CHECK_(child_pid != -1);
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
return child_pid; return child_pid;
} }

View File

@ -41,6 +41,7 @@
#include <direct.h> // For chdir(). #include <direct.h> // For chdir().
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> // For waitpid.
#include <limits> // For std::numeric_limits. #include <limits> // For std::numeric_limits.
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
@ -414,7 +415,7 @@ void SetPthreadFlag() {
} // namespace } // namespace
#if !GTEST_OS_WINDOWS #if GTEST_HAS_CLONE
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) { TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
if (!testing::GTEST_FLAG(death_test_use_fork)) { 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. // Tests that a method of another class can be used in a death test.
TEST_F(TestForDeathTest, MethodOfAnotherClass) { TEST_F(TestForDeathTest, MethodOfAnotherClass) {

View File

@ -202,7 +202,7 @@ class GTestFilterUnitTest(unittest.TestCase):
for slice_var in list_of_sets: for slice_var in list_of_sets:
full_partition.extend(slice_var) full_partition.extend(slice_var)
self.assertEqual(len(set_var), len(full_partition)) 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): def RunAndVerify(self, gtest_filter, tests_to_run):
"""Runs gtest_flag_unittest_ with the given filter, and verifies """Runs gtest_flag_unittest_ with the given filter, and verifies