QNX compatibility patch (by Haruka Iwao).
This commit is contained in:
parent
f3cf0a2316
commit
386da2037d
|
@ -92,6 +92,7 @@
|
||||||
// GTEST_OS_MAC - Mac OS X
|
// GTEST_OS_MAC - Mac OS X
|
||||||
// GTEST_OS_NACL - Google Native Client (NaCl)
|
// GTEST_OS_NACL - Google Native Client (NaCl)
|
||||||
// GTEST_OS_OPENBSD - OpenBSD
|
// GTEST_OS_OPENBSD - OpenBSD
|
||||||
|
// GTEST_OS_QNX - QNX
|
||||||
// GTEST_OS_SOLARIS - Sun Solaris
|
// GTEST_OS_SOLARIS - Sun Solaris
|
||||||
// GTEST_OS_SYMBIAN - Symbian
|
// GTEST_OS_SYMBIAN - Symbian
|
||||||
// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
|
// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
|
||||||
|
@ -245,6 +246,8 @@
|
||||||
# define GTEST_OS_NACL 1
|
# define GTEST_OS_NACL 1
|
||||||
#elif defined __OpenBSD__
|
#elif defined __OpenBSD__
|
||||||
# define GTEST_OS_OPENBSD 1
|
# define GTEST_OS_OPENBSD 1
|
||||||
|
#elif defined __QNX__
|
||||||
|
# define GTEST_OS_QNX 1
|
||||||
#endif // __CYGWIN__
|
#endif // __CYGWIN__
|
||||||
|
|
||||||
// Brings in definitions for functions used in the testing::internal::posix
|
// Brings in definitions for functions used in the testing::internal::posix
|
||||||
|
@ -420,7 +423,8 @@
|
||||||
//
|
//
|
||||||
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
|
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
|
||||||
// to your compiler flags.
|
// to your compiler flags.
|
||||||
# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
|
# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \
|
||||||
|
|| GTEST_OS_QNX)
|
||||||
#endif // GTEST_HAS_PTHREAD
|
#endif // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
#if GTEST_HAS_PTHREAD
|
#if GTEST_HAS_PTHREAD
|
||||||
|
@ -452,8 +456,9 @@
|
||||||
// defining __GNUC__ and friends, but cannot compile GCC's tuple
|
// defining __GNUC__ and friends, but cannot compile GCC's tuple
|
||||||
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
|
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
|
||||||
// Feature Pack download, which we cannot assume the user has.
|
// Feature Pack download, which we cannot assume the user has.
|
||||||
# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \
|
// QNX's QCC compiler is a modified GCC but it doesn't support TR1 tuple.
|
||||||
|| _MSC_VER >= 1600
|
# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \
|
||||||
|
&& !GTEST_OS_QNX) || _MSC_VER >= 1600
|
||||||
# define GTEST_USE_OWN_TR1_TUPLE 0
|
# define GTEST_USE_OWN_TR1_TUPLE 0
|
||||||
# else
|
# else
|
||||||
# define GTEST_USE_OWN_TR1_TUPLE 1
|
# define GTEST_USE_OWN_TR1_TUPLE 1
|
||||||
|
@ -544,7 +549,7 @@
|
||||||
#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
|
#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
|
||||||
(GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
|
(GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
|
||||||
GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
|
GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
|
||||||
GTEST_OS_OPENBSD)
|
GTEST_OS_OPENBSD || GTEST_OS_QNX)
|
||||||
# define GTEST_HAS_DEATH_TEST 1
|
# define GTEST_HAS_DEATH_TEST 1
|
||||||
# include <vector> // NOLINT
|
# include <vector> // NOLINT
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,6 +52,10 @@
|
||||||
# include <sys/wait.h>
|
# include <sys/wait.h>
|
||||||
# endif // GTEST_OS_WINDOWS
|
# endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
|
# if GTEST_OS_QNX
|
||||||
|
# include <spawn.h>
|
||||||
|
# endif // GTEST_OS_QNX
|
||||||
|
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
#include "gtest/gtest-message.h"
|
#include "gtest/gtest-message.h"
|
||||||
|
@ -894,6 +898,7 @@ extern "C" char** environ;
|
||||||
inline char** GetEnviron() { return environ; }
|
inline char** GetEnviron() { return environ; }
|
||||||
# endif // GTEST_OS_MAC
|
# endif // GTEST_OS_MAC
|
||||||
|
|
||||||
|
# if !GTEST_OS_QNX
|
||||||
// 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.
|
||||||
|
@ -926,6 +931,7 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||||
GetLastErrnoDescription().c_str()));
|
GetLastErrnoDescription().c_str()));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
# endif // !GTEST_OS_QNX
|
||||||
|
|
||||||
// Two utility routines that together determine the direction the stack
|
// Two utility routines that together determine the direction the stack
|
||||||
// grows.
|
// grows.
|
||||||
|
@ -949,14 +955,51 @@ bool StackGrowsDown() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A threadsafe implementation of fork(2) for threadsafe-style death tests
|
// Spawns a child process with the same executable as the current process in
|
||||||
// that uses clone(2). It dies with an error message if anything goes
|
// a thread-safe manner and instructs it to run the death test. The
|
||||||
// wrong.
|
// implementation uses fork(2) + exec. On systems where clone(2) is
|
||||||
static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
// available, it is used instead, being slightly more thread-safe. On QNX,
|
||||||
|
// fork supports only single-threaded environments, so this function uses
|
||||||
|
// spawn(2) there instead. The function dies with an error message if
|
||||||
|
// anything goes wrong.
|
||||||
|
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
ExecDeathTestArgs args = { argv, close_fd };
|
ExecDeathTestArgs args = { argv, close_fd };
|
||||||
pid_t child_pid = -1;
|
pid_t child_pid = -1;
|
||||||
|
|
||||||
# if GTEST_HAS_CLONE
|
# if GTEST_OS_QNX
|
||||||
|
// Obtains the current directory and sets it to be closed in the child
|
||||||
|
// process.
|
||||||
|
const int cwd_fd = open(".", O_RDONLY);
|
||||||
|
GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
|
||||||
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
|
||||||
|
// We need to execute the test program in the same environment where
|
||||||
|
// it was originally invoked. Therefore we change to the original
|
||||||
|
// working directory first.
|
||||||
|
const char* const original_dir =
|
||||||
|
UnitTest::GetInstance()->original_working_dir();
|
||||||
|
// We can safely call chdir() as it's a direct system call.
|
||||||
|
if (chdir(original_dir) != 0) {
|
||||||
|
DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
|
||||||
|
original_dir,
|
||||||
|
GetLastErrnoDescription().c_str()));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd_flags;
|
||||||
|
// Set close_fd to be closed after spawn.
|
||||||
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
|
||||||
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
|
||||||
|
fd_flags | FD_CLOEXEC));
|
||||||
|
struct inheritance inherit = {0};
|
||||||
|
// spawn is a system call.
|
||||||
|
child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
|
||||||
|
// Restores the current working directory.
|
||||||
|
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||||
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||||
|
|
||||||
|
# else // GTEST_OS_QNX
|
||||||
|
|
||||||
|
# if GTEST_HAS_CLONE
|
||||||
const bool use_fork = GTEST_FLAG(death_test_use_fork);
|
const bool use_fork = GTEST_FLAG(death_test_use_fork);
|
||||||
|
|
||||||
if (!use_fork) {
|
if (!use_fork) {
|
||||||
|
@ -973,14 +1016,15 @@ static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
||||||
|
|
||||||
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
||||||
}
|
}
|
||||||
# else
|
# else
|
||||||
const bool use_fork = true;
|
const bool use_fork = true;
|
||||||
# endif // GTEST_HAS_CLONE
|
# endif // GTEST_HAS_CLONE
|
||||||
|
|
||||||
if (use_fork && (child_pid = fork()) == 0) {
|
if (use_fork && (child_pid = fork()) == 0) {
|
||||||
ExecDeathTestChildMain(&args);
|
ExecDeathTestChildMain(&args);
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
# endif // GTEST_OS_QNX
|
||||||
|
|
||||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||||
return child_pid;
|
return child_pid;
|
||||||
|
@ -1028,7 +1072,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||||
// is necessary.
|
// is necessary.
|
||||||
FlushInfoLog();
|
FlushInfoLog();
|
||||||
|
|
||||||
const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
|
const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
||||||
set_child_pid(child_pid);
|
set_child_pid(child_pid);
|
||||||
set_read_fd(pipe_fd[0]);
|
set_read_fd(pipe_fd[0]);
|
||||||
|
|
|
@ -51,6 +51,11 @@
|
||||||
# include <mach/vm_map.h>
|
# include <mach/vm_map.h>
|
||||||
#endif // GTEST_OS_MAC
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
|
#if GTEST_OS_QNX
|
||||||
|
# include <devctl.h>
|
||||||
|
# include <sys/procfs.h>
|
||||||
|
#endif // GTEST_OS_QNX
|
||||||
|
|
||||||
#include "gtest/gtest-spi.h"
|
#include "gtest/gtest-spi.h"
|
||||||
#include "gtest/gtest-message.h"
|
#include "gtest/gtest-message.h"
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
@ -98,6 +103,26 @@ size_t GetThreadCount() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif GTEST_OS_QNX
|
||||||
|
|
||||||
|
// Returns the number of threads running in the process, or 0 to indicate that
|
||||||
|
// we cannot detect it.
|
||||||
|
size_t GetThreadCount() {
|
||||||
|
const int fd = open("/proc/self/as", O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
procfs_info process_info;
|
||||||
|
const int status =
|
||||||
|
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
|
||||||
|
close(fd);
|
||||||
|
if (status == EOK) {
|
||||||
|
return static_cast<size_t>(process_info.num_threads);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
size_t GetThreadCount() {
|
size_t GetThreadCount() {
|
||||||
|
|
|
@ -267,7 +267,7 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
|
||||||
EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(NULL, -1));
|
EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(NULL, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_OS_MAC
|
#if GTEST_OS_MAC || GTEST_OS_QNX
|
||||||
void* ThreadFunc(void* data) {
|
void* ThreadFunc(void* data) {
|
||||||
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data);
|
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data);
|
||||||
pthread_mutex_lock(mutex);
|
pthread_mutex_lock(mutex);
|
||||||
|
@ -297,6 +297,8 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
||||||
void* dummy;
|
void* dummy;
|
||||||
ASSERT_EQ(0, pthread_join(thread_id, &dummy));
|
ASSERT_EQ(0, pthread_join(thread_id, &dummy));
|
||||||
|
|
||||||
|
# if GTEST_OS_MAC
|
||||||
|
|
||||||
// MacOS X may not immediately report the updated thread count after
|
// MacOS X may not immediately report the updated thread count after
|
||||||
// joining a thread, causing flakiness in this test. To counter that, we
|
// joining a thread, causing flakiness in this test. To counter that, we
|
||||||
// wait for up to .5 seconds for the OS to report the correct value.
|
// wait for up to .5 seconds for the OS to report the correct value.
|
||||||
|
@ -306,6 +308,9 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
||||||
|
|
||||||
SleepMilliseconds(100);
|
SleepMilliseconds(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# endif // GTEST_OS_MAC
|
||||||
|
|
||||||
EXPECT_EQ(1U, GetThreadCount());
|
EXPECT_EQ(1U, GetThreadCount());
|
||||||
pthread_mutex_destroy(&mutex);
|
pthread_mutex_destroy(&mutex);
|
||||||
}
|
}
|
||||||
|
@ -313,7 +318,7 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
||||||
TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
|
TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
|
||||||
EXPECT_EQ(0U, GetThreadCount());
|
EXPECT_EQ(0U, GetThreadCount());
|
||||||
}
|
}
|
||||||
#endif // GTEST_OS_MAC
|
#endif // GTEST_OS_MAC || GTEST_OS_QNX
|
||||||
|
|
||||||
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
|
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
|
||||||
const bool a_false_condition = false;
|
const bool a_false_condition = false;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user