"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "googletest/src/gtest-death-test.cc" between
googletest-release-1.11.0.tar.gz and googletest-release-1.12.0.tar.gz

About: GoogleTest is Google's (unit) testing and mocking framework for C++ tests.

gtest-death-test.cc  (googletest-release-1.11.0):gtest-death-test.cc  (googletest-release-1.12.0)
skipping to change at line 38 skipping to change at line 38
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// This file implements death tests. // This file implements death tests.
#include "gtest/gtest-death-test.h" #include "gtest/gtest-death-test.h"
#include <functional> #include <functional>
#include <utility> #include <utility>
#include "gtest/internal/gtest-port.h"
#include "gtest/internal/custom/gtest.h" #include "gtest/internal/custom/gtest.h"
#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
# if GTEST_OS_MAC #if GTEST_OS_MAC
# include <crt_externs.h> #include <crt_externs.h>
# endif // GTEST_OS_MAC #endif // GTEST_OS_MAC
# include <errno.h> #include <errno.h>
# include <fcntl.h> #include <fcntl.h>
# include <limits.h> #include <limits.h>
# if GTEST_OS_LINUX #if GTEST_OS_LINUX
# include <signal.h> #include <signal.h>
# endif // GTEST_OS_LINUX #endif // GTEST_OS_LINUX
# include <stdarg.h> #include <stdarg.h>
# if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
# include <windows.h> #include <windows.h>
# else #else
# include <sys/mman.h> #include <sys/mman.h>
# include <sys/wait.h> #include <sys/wait.h>
# endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
# if GTEST_OS_QNX #if GTEST_OS_QNX
# include <spawn.h> #include <spawn.h>
# endif // GTEST_OS_QNX #endif // GTEST_OS_QNX
# if GTEST_OS_FUCHSIA #if GTEST_OS_FUCHSIA
# include <lib/fdio/fd.h> #include <lib/fdio/fd.h>
# include <lib/fdio/io.h> #include <lib/fdio/io.h>
# include <lib/fdio/spawn.h> #include <lib/fdio/spawn.h>
# include <lib/zx/channel.h> #include <lib/zx/channel.h>
# include <lib/zx/port.h> #include <lib/zx/port.h>
# include <lib/zx/process.h> #include <lib/zx/process.h>
# include <lib/zx/socket.h> #include <lib/zx/socket.h>
# include <zircon/processargs.h> #include <zircon/processargs.h>
# include <zircon/syscalls.h> #include <zircon/syscalls.h>
# include <zircon/syscalls/policy.h> #include <zircon/syscalls/policy.h>
# include <zircon/syscalls/port.h> #include <zircon/syscalls/port.h>
# endif // GTEST_OS_FUCHSIA #endif // GTEST_OS_FUCHSIA
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
namespace testing { namespace testing {
// Constants. // Constants.
// The default death test style. // The default death test style.
// //
// This is defined in internal/gtest-port.h as "fast", but can be overridden by // This is defined in internal/gtest-port.h as "fast", but can be overridden by
// a definition in internal/custom/gtest-port.h. The recommended value, which is // a definition in internal/custom/gtest-port.h. The recommended value, which is
// used internally at Google, is "threadsafe". // used internally at Google, is "threadsafe".
static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE; static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
} // namespace testing
GTEST_DEFINE_string_( GTEST_DEFINE_string_(
death_test_style, death_test_style,
internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), testing::internal::StringFromGTestEnv("death_test_style",
testing::kDefaultDeathTestStyle),
"Indicates how to run a death test in a forked child process: " "Indicates how to run a death test in a forked child process: "
"\"threadsafe\" (child process re-executes the test binary " "\"threadsafe\" (child process re-executes the test binary "
"from the beginning, running only the specific death test) or " "from the beginning, running only the specific death test) or "
"\"fast\" (child process runs the death test immediately " "\"fast\" (child process runs the death test immediately "
"after forking)."); "after forking).");
GTEST_DEFINE_bool_( GTEST_DEFINE_bool_(
death_test_use_fork, death_test_use_fork,
internal::BoolFromGTestEnv("death_test_use_fork", false), testing::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. "
"Ignored and always uses fork() on POSIX systems where clone() is not " "Ignored and always uses fork() on POSIX systems where clone() is not "
"implemented. Useful when running under valgrind or similar tools if " "implemented. Useful when running under valgrind or similar tools if "
"those do not support clone(). Valgrind 3.3.1 will just fail 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 "
"most likely be removed."); "most likely be removed.");
namespace internal {
GTEST_DEFINE_string_( GTEST_DEFINE_string_(
internal_run_death_test, "", internal_run_death_test, "",
"Indicates the file, line number, temporal index of " "Indicates the file, line number, temporal index of "
"the single death test to run, and a file descriptor to " "the single death test to run, and a file descriptor to "
"which a success code may be sent, all separated by " "which a success code may be sent, all separated by "
"the '|' characters. This flag is specified if and only if the " "the '|' characters. This flag is specified if and only if the "
"current process is a sub-process launched for running a thread-safe " "current process is a sub-process launched for running a thread-safe "
"death test. FOR INTERNAL USE ONLY."); "death test. FOR INTERNAL USE ONLY.");
} // namespace internal
namespace testing {
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
namespace internal { namespace internal {
// Valid only for fast death tests. Indicates the code is running in the // Valid only for fast death tests. Indicates the code is running in the
// child process of a fast style death test. // child process of a fast style death test.
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA #if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
static bool g_in_fast_death_test_child = false; static bool g_in_fast_death_test_child = false;
# endif #endif
// Returns a Boolean value indicating whether the caller is currently // Returns a Boolean value indicating whether the caller is currently
// executing in the context of the death test child process. Tools such as // executing in the context of the death test child process. Tools such as
// Valgrind heap checkers may need this to modify their behavior in death // Valgrind heap checkers may need this to modify their behavior in death
// tests. IMPORTANT: This is an internal utility. Using it may break the // tests. IMPORTANT: This is an internal utility. Using it may break the
// implementation of death tests. User code MUST NOT use it. // implementation of death tests. User code MUST NOT use it.
bool InDeathTestChild() { bool InDeathTestChild() {
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA #if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
// On Windows and Fuchsia, death tests are thread-safe regardless of the value // On Windows and Fuchsia, death tests are thread-safe regardless of the value
// of the death_test_style flag. // of the death_test_style flag.
return !GTEST_FLAG(internal_run_death_test).empty(); return !GTEST_FLAG_GET(internal_run_death_test).empty();
# else #else
if (GTEST_FLAG(death_test_style) == "threadsafe") if (GTEST_FLAG_GET(death_test_style) == "threadsafe")
return !GTEST_FLAG(internal_run_death_test).empty(); return !GTEST_FLAG_GET(internal_run_death_test).empty();
else else
return g_in_fast_death_test_child; return g_in_fast_death_test_child;
#endif #endif
} }
} // namespace internal } // namespace internal
// ExitedWithCode constructor. // ExitedWithCode constructor.
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {}
}
// ExitedWithCode function-call operator. // ExitedWithCode function-call operator.
bool ExitedWithCode::operator()(int exit_status) const { bool ExitedWithCode::operator()(int exit_status) const {
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA #if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
return exit_status == exit_code_; return exit_status == exit_code_;
# else #else
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA #endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
} }
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA #if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
// KilledBySignal constructor. // KilledBySignal constructor.
KilledBySignal::KilledBySignal(int signum) : signum_(signum) { KilledBySignal::KilledBySignal(int signum) : signum_(signum) {}
}
// KilledBySignal function-call operator. // KilledBySignal function-call operator.
bool KilledBySignal::operator()(int exit_status) const { bool KilledBySignal::operator()(int exit_status) const {
# if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_) #if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
{ {
bool result; bool result;
if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) { if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
return result; return result;
} }
} }
# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_) #endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
} }
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA #endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
namespace internal { namespace internal {
// Utilities needed for death tests. // Utilities needed for death tests.
// Generates a textual description of a given exit code, in the format // Generates a textual description of a given exit code, in the format
// specified by wait(2). // specified by wait(2).
static std::string ExitSummary(int exit_code) { static std::string ExitSummary(int exit_code) {
Message m; Message m;
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA #if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
m << "Exited with exit status " << exit_code; m << "Exited with exit status " << exit_code;
# else #else
if (WIFEXITED(exit_code)) { if (WIFEXITED(exit_code)) {
m << "Exited with exit status " << WEXITSTATUS(exit_code); m << "Exited with exit status " << WEXITSTATUS(exit_code);
} else if (WIFSIGNALED(exit_code)) { } else if (WIFSIGNALED(exit_code)) {
m << "Terminated by signal " << WTERMSIG(exit_code); m << "Terminated by signal " << WTERMSIG(exit_code);
} }
# ifdef WCOREDUMP #ifdef WCOREDUMP
if (WCOREDUMP(exit_code)) { if (WCOREDUMP(exit_code)) {
m << " (core dumped)"; m << " (core dumped)";
} }
# endif #endif
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA #endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
return m.GetString(); return m.GetString();
} }
// Returns true if exit_status describes a process that was terminated // Returns true if exit_status describes a process that was terminated
// by a signal, or exited normally with a nonzero exit code. // by a signal, or exited normally with a nonzero exit code.
bool ExitedUnsuccessfully(int exit_status) { bool ExitedUnsuccessfully(int exit_status) {
return !ExitedWithCode(0)(exit_status); return !ExitedWithCode(0)(exit_status);
} }
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA #if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
// Generates a textual failure message when a death test finds more than // Generates a textual failure message when a death test finds more than
// one thread running, or cannot determine the number of threads, prior // one thread running, or cannot determine the number of threads, prior
// to executing the given statement. It is the responsibility of the // to executing the given statement. It is the responsibility of the
// caller not to pass a thread_count of 1. // caller not to pass a thread_count of 1.
static std::string DeathTestThreadWarning(size_t thread_count) { static std::string DeathTestThreadWarning(size_t thread_count) {
Message msg; Message msg;
msg << "Death tests use fork(), which is unsafe particularly" msg << "Death tests use fork(), which is unsafe particularly"
<< " in a threaded context. For this test, " << GTEST_NAME_ << " "; << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
if (thread_count == 0) { if (thread_count == 0) {
msg << "couldn't detect the number of threads."; msg << "couldn't detect the number of threads.";
} else { } else {
msg << "detected " << thread_count << " threads."; msg << "detected " << thread_count << " threads.";
} }
msg << " See " msg << " See "
"https://github.com/google/googletest/blob/master/docs/" "https://github.com/google/googletest/blob/master/docs/"
"advanced.md#death-tests-and-threads" "advanced.md#death-tests-and-threads"
<< " for more explanation and suggested solutions, especially if" << " for more explanation and suggested solutions, especially if"
<< " this is the last message you see before your test times out."; << " this is the last message you see before your test times out.";
return msg.GetString(); return msg.GetString();
} }
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA #endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
// Flag characters for reporting a death test that did not die. // Flag characters for reporting a death test that did not die.
static const char kDeathTestLived = 'L'; static const char kDeathTestLived = 'L';
static const char kDeathTestReturned = 'R'; static const char kDeathTestReturned = 'R';
static const char kDeathTestThrew = 'T'; static const char kDeathTestThrew = 'T';
static const char kDeathTestInternalError = 'I'; static const char kDeathTestInternalError = 'I';
#if GTEST_OS_FUCHSIA #if GTEST_OS_FUCHSIA
// File descriptor used for the pipe in the child process. // File descriptor used for the pipe in the child process.
skipping to change at line 307 skipping to change at line 308
_exit(1); _exit(1);
} else { } else {
fprintf(stderr, "%s", message.c_str()); fprintf(stderr, "%s", message.c_str());
fflush(stderr); fflush(stderr);
posix::Abort(); posix::Abort();
} }
} }
// A replacement for CHECK that calls DeathTestAbort if the assertion // A replacement for CHECK that calls DeathTestAbort if the assertion
// fails. // fails.
# define GTEST_DEATH_TEST_CHECK_(expression) \ #define GTEST_DEATH_TEST_CHECK_(expression) \
do { \ do { \
if (!::testing::internal::IsTrue(expression)) { \ if (!::testing::internal::IsTrue(expression)) { \
DeathTestAbort( \ DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ + \
::std::string("CHECK failed: File ") + __FILE__ + ", line " \ ", line " + \
+ ::testing::internal::StreamableToString(__LINE__) + ": " \ ::testing::internal::StreamableToString(__LINE__) + \
+ #expression); \ ": " + #expression); \
} \ } \
} while (::testing::internal::AlwaysFalse()) } while (::testing::internal::AlwaysFalse())
// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for // This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
// evaluating any system call that fulfills two conditions: it must return // evaluating any system call that fulfills two conditions: it must return
// -1 on failure, and set errno to EINTR when it is interrupted and // -1 on failure, and set errno to EINTR when it is interrupted and
// should be tried again. The macro expands to a loop that repeatedly // should be tried again. The macro expands to a loop that repeatedly
// evaluates the expression as long as it evaluates to -1 and sets // evaluates the expression as long as it evaluates to -1 and sets
// errno to EINTR. If the expression evaluates to -1 but errno is // errno to EINTR. If the expression evaluates to -1 but errno is
// something other than EINTR, DeathTestAbort is called. // something other than EINTR, DeathTestAbort is called.
# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ #define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
do { \ do { \
int gtest_retval; \ int gtest_retval; \
do { \ do { \
gtest_retval = (expression); \ gtest_retval = (expression); \
} while (gtest_retval == -1 && errno == EINTR); \ } while (gtest_retval == -1 && errno == EINTR); \
if (gtest_retval == -1) { \ if (gtest_retval == -1) { \
DeathTestAbort( \ DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ + \
::std::string("CHECK failed: File ") + __FILE__ + ", line " \ ", line " + \
+ ::testing::internal::StreamableToString(__LINE__) + ": " \ ::testing::internal::StreamableToString(__LINE__) + \
+ #expression + " != -1"); \ ": " + #expression + " != -1"); \
} \ } \
} while (::testing::internal::AlwaysFalse()) } while (::testing::internal::AlwaysFalse())
// Returns the message describing the last system error in errno. // Returns the message describing the last system error in errno.
std::string GetLastErrnoDescription() { std::string GetLastErrnoDescription() {
return errno == 0 ? "" : posix::StrError(errno); return errno == 0 ? "" : posix::StrError(errno);
} }
// This is called from a death test parent process to read a failure // This is called from a death test parent process to read a failure
// message from the death test child process and log it with the FATAL // message from the death test child process and log it with the FATAL
// severity. On Windows, the message is read from a pipe handle. On other // severity. On Windows, the message is read from a pipe handle. On other
// platforms, it is read from a file descriptor. // platforms, it is read from a file descriptor.
static void FailFromInternalError(int fd) { static void FailFromInternalError(int fd) {
Message error; Message error;
char buffer[256]; char buffer[256];
int num_read; int num_read;
skipping to change at line 373 skipping to change at line 374
GTEST_LOG_(FATAL) << "Error while reading death test internal: " GTEST_LOG_(FATAL) << "Error while reading death test internal: "
<< GetLastErrnoDescription() << " [" << last_error << "]"; << GetLastErrnoDescription() << " [" << last_error << "]";
} }
} }
// Death test constructor. Increments the running death test count // Death test constructor. Increments the running death test count
// for the current test. // for the current test.
DeathTest::DeathTest() { DeathTest::DeathTest() {
TestInfo* const info = GetUnitTestImpl()->current_test_info(); TestInfo* const info = GetUnitTestImpl()->current_test_info();
if (info == nullptr) { if (info == nullptr) {
DeathTestAbort("Cannot run a death test outside of a TEST or " DeathTestAbort(
"TEST_F construct"); "Cannot run a death test outside of a TEST or "
"TEST_F construct");
} }
} }
// Creates and returns a death test by dispatching to the current // Creates and returns a death test by dispatching to the current
// death test factory. // death test factory.
bool DeathTest::Create(const char* statement, bool DeathTest::Create(const char* statement,
Matcher<const std::string&> matcher, const char* file, Matcher<const std::string&> matcher, const char* file,
int line, DeathTest** test) { int line, DeathTest** test) {
return GetUnitTestImpl()->death_test_factory()->Create( return GetUnitTestImpl()->death_test_factory()->Create(
statement, std::move(matcher), file, line, test); statement, std::move(matcher), file, line, test);
skipping to change at line 503 skipping to change at line 505
<< static_cast<unsigned int>(flag) << ")"; << static_cast<unsigned int>(flag) << ")";
} }
} else { } else {
GTEST_LOG_(FATAL) << "Read from death test child process failed: " GTEST_LOG_(FATAL) << "Read from death test child process failed: "
<< GetLastErrnoDescription(); << GetLastErrnoDescription();
} }
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
set_read_fd(-1); set_read_fd(-1);
} }
std::string DeathTestImpl::GetErrorLogs() { std::string DeathTestImpl::GetErrorLogs() { return GetCapturedStderr(); }
return GetCapturedStderr();
}
// Signals that the death test code which should have exited, didn't. // Signals that the death test code which should have exited, didn't.
// Should be called only in a death test child process. // Should be called only in a death test child process.
// Writes a status byte to the child's status file descriptor, then // Writes a status byte to the child's status file descriptor, then
// calls _exit(1). // calls _exit(1).
void DeathTestImpl::Abort(AbortReason reason) { void DeathTestImpl::Abort(AbortReason reason) {
// The parent process considers the death test to be a failure if // The parent process considers the death test to be a failure if
// it finds any data in our pipe. So, here we write a single flag byte // it finds any data in our pipe. So, here we write a single flag byte
// to the pipe, then exit. // to the pipe, then exit.
const char status_ch = const char status_ch = reason == TEST_DID_NOT_DIE ? kDeathTestLived
reason == TEST_DID_NOT_DIE ? kDeathTestLived : : reason == TEST_THREW_EXCEPTION ? kDeathTestThrew
reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; : kDeathTestReturned;
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
// We are leaking the descriptor here because on some platforms (i.e., // We are leaking the descriptor here because on some platforms (i.e.,
// when built as Windows DLL), destructors of global objects will still // when built as Windows DLL), destructors of global objects will still
// run after calling _exit(). On such systems, write_fd_ will be // run after calling _exit(). On such systems, write_fd_ will be
// indirectly closed from the destructor of UnitTestImpl, causing double // indirectly closed from the destructor of UnitTestImpl, causing double
// close if it is also closed here. On debug configurations, double close // close if it is also closed here. On debug configurations, double close
// may assert. As there are no in-process buffers to flush here, we are // may assert. As there are no in-process buffers to flush here, we are
// relying on the OS to close the descriptor after the process terminates // relying on the OS to close the descriptor after the process terminates
// when the destructors are not run. // when the destructors are not run.
_exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
} }
// Returns an indented copy of stderr output for a death test. // Returns an indented copy of stderr output for a death test.
// This makes distinguishing death test output lines from regular log lines // This makes distinguishing death test output lines from regular log lines
// much easier. // much easier.
static ::std::string FormatDeathTestOutput(const ::std::string& output) { static ::std::string FormatDeathTestOutput(const ::std::string& output) {
::std::string ret; ::std::string ret;
for (size_t at = 0; ; ) { for (size_t at = 0;;) {
const size_t line_end = output.find('\n', at); const size_t line_end = output.find('\n', at);
ret += "[ DEATH ] "; ret += "[ DEATH ] ";
if (line_end == ::std::string::npos) { if (line_end == ::std::string::npos) {
ret += output.substr(at); ret += output.substr(at);
break; break;
} }
ret += output.substr(at, line_end + 1 - at); ret += output.substr(at, line_end + 1 - at);
at = line_end + 1; at = line_end + 1;
} }
return ret; return ret;
skipping to change at line 571 skipping to change at line 571
// process. // process.
// //
// Argument: // Argument:
// status_ok: true if exit_status is acceptable in the context of // status_ok: true if exit_status is acceptable in the context of
// this particular death test, which fails if it is false // this particular death test, which fails if it is false
// //
// Returns true if and only if all of the above conditions are met. Otherwise, // Returns true if and only if all of the above conditions are met. Otherwise,
// the first failing condition, in the order given above, is the one that is // the first failing condition, in the order given above, is the one that is
// reported. Also sets the last death test message string. // reported. Also sets the last death test message string.
bool DeathTestImpl::Passed(bool status_ok) { bool DeathTestImpl::Passed(bool status_ok) {
if (!spawned()) if (!spawned()) return false;
return false;
const std::string error_message = GetErrorLogs(); const std::string error_message = GetErrorLogs();
bool success = false; bool success = false;
Message buffer; Message buffer;
buffer << "Death test: " << statement() << "\n"; buffer << "Death test: " << statement() << "\n";
switch (outcome()) { switch (outcome()) {
case LIVED: case LIVED:
buffer << " Result: failed to die.\n" buffer << " Result: failed to die.\n"
<< " Error msg:\n" << FormatDeathTestOutput(error_message); << " Error msg:\n"
<< FormatDeathTestOutput(error_message);
break; break;
case THREW: case THREW:
buffer << " Result: threw an exception.\n" buffer << " Result: threw an exception.\n"
<< " Error msg:\n" << FormatDeathTestOutput(error_message); << " Error msg:\n"
<< FormatDeathTestOutput(error_message);
break; break;
case RETURNED: case RETURNED:
buffer << " Result: illegal return in test statement.\n" buffer << " Result: illegal return in test statement.\n"
<< " Error msg:\n" << FormatDeathTestOutput(error_message); << " Error msg:\n"
<< FormatDeathTestOutput(error_message);
break; break;
case DIED: case DIED:
if (status_ok) { if (status_ok) {
if (matcher_.Matches(error_message)) { if (matcher_.Matches(error_message)) {
success = true; success = true;
} else { } else {
std::ostringstream stream; std::ostringstream stream;
matcher_.DescribeTo(&stream); matcher_.DescribeTo(&stream);
buffer << " Result: died but not with expected error.\n" buffer << " Result: died but not with expected error.\n"
<< " Expected: " << stream.str() << "\n" << " Expected: " << stream.str() << "\n"
<< "Actual msg:\n" << "Actual msg:\n"
<< FormatDeathTestOutput(error_message); << FormatDeathTestOutput(error_message);
} }
} else { } else {
buffer << " Result: died but not with expected exit code:\n" buffer << " Result: died but not with expected exit code:\n"
<< " " << ExitSummary(status()) << "\n" << " " << ExitSummary(status()) << "\n"
<< "Actual msg:\n" << FormatDeathTestOutput(error_message); << "Actual msg:\n"
<< FormatDeathTestOutput(error_message);
} }
break; break;
case IN_PROGRESS: case IN_PROGRESS:
default: default:
GTEST_LOG_(FATAL) GTEST_LOG_(FATAL)
<< "DeathTest::Passed somehow called before conclusion of test"; << "DeathTest::Passed somehow called before conclusion of test";
} }
DeathTest::set_last_death_test_message(buffer.GetString()); DeathTest::set_last_death_test_message(buffer.GetString());
return success; return success;
} }
# if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
// WindowsDeathTest implements death tests on Windows. Due to the // WindowsDeathTest implements death tests on Windows. Due to the
// specifics of starting new processes on Windows, death tests there are // specifics of starting new processes on Windows, death tests there are
// always threadsafe, and Google Test considers the // always threadsafe, and Google Test considers the
// --gtest_death_test_style=fast setting to be equivalent to // --gtest_death_test_style=fast setting to be equivalent to
// --gtest_death_test_style=threadsafe there. // --gtest_death_test_style=threadsafe there.
// //
// A few implementation notes: Like the Linux version, the Windows // A few implementation notes: Like the Linux version, the Windows
// implementation uses pipes for child-to-parent communication. But due to // implementation uses pipes for child-to-parent communication. But due to
// the specifics of pipes on Windows, some extra steps are required: // the specifics of pipes on Windows, some extra steps are required:
// //
skipping to change at line 682 skipping to change at line 685
// acquired the handle to the write end of the pipe. After seeing this // acquired the handle to the write end of the pipe. After seeing this
// event the parent can release its own handles to make sure its // event the parent can release its own handles to make sure its
// ReadFile() calls return when the child terminates. // ReadFile() calls return when the child terminates.
AutoHandle event_handle_; AutoHandle event_handle_;
}; };
// Waits for the child in a death test to exit, returning its exit // Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the // status, or 0 if no child process exists. As a side effect, sets the
// outcome data member. // outcome data member.
int WindowsDeathTest::Wait() { int WindowsDeathTest::Wait() {
if (!spawned()) if (!spawned()) return 0;
return 0;
// Wait until the child either signals that it has acquired the write end // Wait until the child either signals that it has acquired the write end
// of the pipe or it dies. // of the pipe or it dies.
const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; const HANDLE wait_handles[2] = {child_handle_.Get(), event_handle_.Get()};
switch (::WaitForMultipleObjects(2, switch (::WaitForMultipleObjects(2, wait_handles,
wait_handles,
FALSE, // Waits for any of the handles. FALSE, // Waits for any of the handles.
INFINITE)) { INFINITE)) {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
case WAIT_OBJECT_0 + 1: case WAIT_OBJECT_0 + 1:
break; break;
default: default:
GTEST_DEATH_TEST_CHECK_(false); // Should not get here. GTEST_DEATH_TEST_CHECK_(false); // Should not get here.
} }
// The child has acquired the write end of the pipe or exited. // The child has acquired the write end of the pipe or exited.
// We release the handle on our side and continue. // We release the handle on our side and continue.
write_handle_.Reset(); write_handle_.Reset();
event_handle_.Reset(); event_handle_.Reset();
ReadAndInterpretStatusByte(); ReadAndInterpretStatusByte();
// Waits for the child process to exit if it haven't already. This // Waits for the child process to exit if it haven't already. This
// returns immediately if the child has already exited, regardless of // returns immediately if the child has already exited, regardless of
// whether previous calls to WaitForMultipleObjects synchronized on this // whether previous calls to WaitForMultipleObjects synchronized on this
// handle or not. // handle or not.
GTEST_DEATH_TEST_CHECK_( GTEST_DEATH_TEST_CHECK_(WAIT_OBJECT_0 ==
WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), ::WaitForSingleObject(child_handle_.Get(), INFINITE));
INFINITE));
DWORD status_code; DWORD status_code;
GTEST_DEATH_TEST_CHECK_( GTEST_DEATH_TEST_CHECK_(
::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
child_handle_.Reset(); child_handle_.Reset();
set_status(static_cast<int>(status_code)); set_status(static_cast<int>(status_code));
return status(); return status();
} }
// The AssumeRole process for a Windows death test. It creates a child // The AssumeRole process for a Windows death test. It creates a child
// process with the same executable as the current process to run the // process with the same executable as the current process to run the
skipping to change at line 745 skipping to change at line 745
// processing. // processing.
set_write_fd(flag->write_fd()); set_write_fd(flag->write_fd());
return EXECUTE_TEST; return EXECUTE_TEST;
} }
// WindowsDeathTest uses an anonymous pipe to communicate results of // WindowsDeathTest uses an anonymous pipe to communicate results of
// a death test. // a death test.
SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES), SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
nullptr, TRUE}; nullptr, TRUE};
HANDLE read_handle, write_handle; HANDLE read_handle, write_handle;
GTEST_DEATH_TEST_CHECK_( GTEST_DEATH_TEST_CHECK_(::CreatePipe(&read_handle, &write_handle,
::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, &handles_are_inheritable,
0) // Default buffer size. 0) // Default buffer size.
!= FALSE); != FALSE);
set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle), set_read_fd(
O_RDONLY)); ::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle), O_RDONLY));
write_handle_.Reset(write_handle); write_handle_.Reset(write_handle);
event_handle_.Reset(::CreateEvent( event_handle_.Reset(::CreateEvent(
&handles_are_inheritable, &handles_are_inheritable,
TRUE, // The event will automatically reset to non-signaled state. TRUE, // The event will automatically reset to non-signaled state.
FALSE, // The initial state is non-signalled. FALSE, // The initial state is non-signalled.
nullptr)); // The even is unnamed. nullptr)); // The even is unnamed.
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr); GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
kFilterFlag + "=" + info->test_suite_name() + "filter=" + info->test_suite_name() + "." +
"." + info->name(); info->name();
const std::string internal_flag = const std::string internal_flag =
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + std::string("--") + GTEST_FLAG_PREFIX_ +
"=" + file_ + "|" + StreamableToString(line_) + "|" + "internal_run_death_test=" + file_ + "|" + StreamableToString(line_) +
StreamableToString(death_test_index) + "|" + "|" + StreamableToString(death_test_index) + "|" +
StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) + StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
// size_t has the same width as pointers on both 32-bit and 64-bit // size_t has the same width as pointers on both 32-bit and 64-bit
// Windows platforms. // Windows platforms.
// See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
"|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) + "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) + "|" +
"|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get())); StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
char executable_path[_MAX_PATH + 1]; // NOLINT char executable_path[_MAX_PATH + 1]; // NOLINT
GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr, GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
executable_path, executable_path,
_MAX_PATH)); _MAX_PATH));
std::string command_line = std::string command_line = std::string(::GetCommandLineA()) + " " +
std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + filter_flag + " \"" + internal_flag + "\"";
internal_flag + "\"";
DeathTest::set_last_death_test_message(""); DeathTest::set_last_death_test_message("");
CaptureStderr(); CaptureStderr();
// Flush the log buffers since the log streams are shared with the child. // Flush the log buffers since the log streams are shared with the child.
FlushInfoLog(); FlushInfoLog();
// The child process will share the standard handles with the parent. // The child process will share the standard handles with the parent.
STARTUPINFOA startup_info; STARTUPINFOA startup_info;
memset(&startup_info, 0, sizeof(STARTUPINFO)); memset(&startup_info, 0, sizeof(STARTUPINFO));
startup_info.dwFlags = STARTF_USESTDHANDLES; startup_info.dwFlags = STARTF_USESTDHANDLES;
startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
PROCESS_INFORMATION process_info; PROCESS_INFORMATION process_info;
GTEST_DEATH_TEST_CHECK_( GTEST_DEATH_TEST_CHECK_(
::CreateProcessA( ::CreateProcessA(
executable_path, const_cast<char*>(command_line.c_str()), executable_path, const_cast<char*>(command_line.c_str()),
nullptr, // Retuned process handle is not inheritable. nullptr, // Returned process handle is not inheritable.
nullptr, // Retuned thread handle is not inheritable. nullptr, // Returned thread handle is not inheritable.
TRUE, // Child inherits all inheritable handles (for write_handle_). TRUE, // Child inherits all inheritable handles (for write_handle_).
0x0, // Default creation flags. 0x0, // Default creation flags.
nullptr, // Inherit the parent's environment. nullptr, // Inherit the parent's environment.
UnitTest::GetInstance()->original_working_dir(), &startup_info, UnitTest::GetInstance()->original_working_dir(), &startup_info,
&process_info) != FALSE); &process_info) != FALSE);
child_handle_.Reset(process_info.hProcess); child_handle_.Reset(process_info.hProcess);
::CloseHandle(process_info.hThread); ::CloseHandle(process_info.hThread);
set_spawned(true); set_spawned(true);
return OVERSEE_TEST; return OVERSEE_TEST;
} }
# elif GTEST_OS_FUCHSIA #elif GTEST_OS_FUCHSIA
class FuchsiaDeathTest : public DeathTestImpl { class FuchsiaDeathTest : public DeathTestImpl {
public: public:
FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher, FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const char* file, int line) const char* file, int line)
: DeathTestImpl(a_statement, std::move(matcher)), : DeathTestImpl(a_statement, std::move(matcher)),
file_(file), file_(file),
line_(line) {} line_(line) {}
// All of these virtual functions are inherited from DeathTest. // All of these virtual functions are inherited from DeathTest.
skipping to change at line 858 skipping to change at line 857
free(*i); free(*i);
} }
} }
void AddArgument(const char* argument) { void AddArgument(const char* argument) {
args_.insert(args_.end() - 1, posix::StrDup(argument)); args_.insert(args_.end() - 1, posix::StrDup(argument));
} }
template <typename Str> template <typename Str>
void AddArguments(const ::std::vector<Str>& arguments) { void AddArguments(const ::std::vector<Str>& arguments) {
for (typename ::std::vector<Str>::const_iterator i = arguments.begin(); for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
i != arguments.end(); i != arguments.end(); ++i) {
++i) {
args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
} }
} }
char* const* Argv() { char* const* Argv() { return &args_[0]; }
return &args_[0];
}
int size() { int size() { return static_cast<int>(args_.size()) - 1; }
return static_cast<int>(args_.size()) - 1;
}
private: private:
std::vector<char*> args_; std::vector<char*> args_;
}; };
// Waits for the child in a death test to exit, returning its exit // Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the // status, or 0 if no child process exists. As a side effect, sets the
// outcome data member. // outcome data member.
int FuchsiaDeathTest::Wait() { int FuchsiaDeathTest::Wait() {
const int kProcessKey = 0; const int kProcessKey = 0;
const int kSocketKey = 1; const int kSocketKey = 1;
const int kExceptionKey = 2; const int kExceptionKey = 2;
if (!spawned()) if (!spawned()) return 0;
return 0;
// Create a port to wait for socket/task/exception events. // Create a port to wait for socket/task/exception events.
zx_status_t status_zx; zx_status_t status_zx;
zx::port port; zx::port port;
status_zx = zx::port::create(0, &port); status_zx = zx::port::create(0, &port);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
// Register to wait for the child process to terminate. // Register to wait for the child process to terminate.
status_zx = child_process_.wait_async( status_zx =
port, kProcessKey, ZX_PROCESS_TERMINATED, 0); child_process_.wait_async(port, kProcessKey, ZX_PROCESS_TERMINATED, 0);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
// Register to wait for the socket to be readable or closed. // Register to wait for the socket to be readable or closed.
status_zx = stderr_socket_.wait_async( status_zx = stderr_socket_.wait_async(
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0); port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
// Register to wait for an exception. // Register to wait for an exception.
status_zx = exception_channel_.wait_async( status_zx = exception_channel_.wait_async(port, kExceptionKey,
port, kExceptionKey, ZX_CHANNEL_READABLE, 0); ZX_CHANNEL_READABLE, 0);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
bool process_terminated = false; bool process_terminated = false;
bool socket_closed = false; bool socket_closed = false;
do { do {
zx_port_packet_t packet = {}; zx_port_packet_t packet = {};
status_zx = port.wait(zx::time::infinite(), &packet); status_zx = port.wait(zx::time::infinite(), &packet);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
if (packet.key == kExceptionKey) { if (packet.key == kExceptionKey) {
skipping to change at line 934 skipping to change at line 927
process_terminated = true; process_terminated = true;
} else if (packet.key == kSocketKey) { } else if (packet.key == kSocketKey) {
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type)); GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
if (packet.signal.observed & ZX_SOCKET_READABLE) { if (packet.signal.observed & ZX_SOCKET_READABLE) {
// Read data from the socket. // Read data from the socket.
constexpr size_t kBufferSize = 1024; constexpr size_t kBufferSize = 1024;
do { do {
size_t old_length = captured_stderr_.length(); size_t old_length = captured_stderr_.length();
size_t bytes_read = 0; size_t bytes_read = 0;
captured_stderr_.resize(old_length + kBufferSize); captured_stderr_.resize(old_length + kBufferSize);
status_zx = stderr_socket_.read( status_zx =
0, &captured_stderr_.front() + old_length, kBufferSize, stderr_socket_.read(0, &captured_stderr_.front() + old_length,
&bytes_read); kBufferSize, &bytes_read);
captured_stderr_.resize(old_length + bytes_read); captured_stderr_.resize(old_length + bytes_read);
} while (status_zx == ZX_OK); } while (status_zx == ZX_OK);
if (status_zx == ZX_ERR_PEER_CLOSED) { if (status_zx == ZX_ERR_PEER_CLOSED) {
socket_closed = true; socket_closed = true;
} else { } else {
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
status_zx = stderr_socket_.wait_async( status_zx = stderr_socket_.wait_async(
port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0); port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
} }
skipping to change at line 990 skipping to change at line 983
// processing. // processing.
set_write_fd(kFuchsiaReadPipeFd); set_write_fd(kFuchsiaReadPipeFd);
return EXECUTE_TEST; return EXECUTE_TEST;
} }
// Flush the log buffers since the log streams are shared with the child. // Flush the log buffers since the log streams are shared with the child.
FlushInfoLog(); FlushInfoLog();
// Build the child process command line. // Build the child process command line.
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
kFilterFlag + "=" + info->test_suite_name() + "filter=" + info->test_suite_name() + "." +
"." + info->name(); info->name();
const std::string internal_flag = const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" kInternalRunDeathTestFlag + "=" + file_ +
+ file_ + "|" "|" + StreamableToString(line_) + "|" +
+ StreamableToString(line_) + "|" StreamableToString(death_test_index);
+ StreamableToString(death_test_index);
Arguments args; Arguments args;
args.AddArguments(GetInjectableArgvs()); args.AddArguments(GetInjectableArgvs());
args.AddArgument(filter_flag.c_str()); args.AddArgument(filter_flag.c_str());
args.AddArgument(internal_flag.c_str()); args.AddArgument(internal_flag.c_str());
// Build the pipe for communication with the child. // Build the pipe for communication with the child.
zx_status_t status; zx_status_t status;
zx_handle_t child_pipe_handle; zx_handle_t child_pipe_handle;
int child_pipe_fd; int child_pipe_fd;
status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle); status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
skipping to change at line 1019 skipping to change at line 1011
// Set the pipe handle for the child. // Set the pipe handle for the child.
fdio_spawn_action_t spawn_actions[2] = {}; fdio_spawn_action_t spawn_actions[2] = {};
fdio_spawn_action_t* add_handle_action = &spawn_actions[0]; fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE; add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd); add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
add_handle_action->h.handle = child_pipe_handle; add_handle_action->h.handle = child_pipe_handle;
// Create a socket pair will be used to receive the child process' stderr. // Create a socket pair will be used to receive the child process' stderr.
zx::socket stderr_producer_socket; zx::socket stderr_producer_socket;
status = status = zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
GTEST_DEATH_TEST_CHECK_(status >= 0); GTEST_DEATH_TEST_CHECK_(status >= 0);
int stderr_producer_fd = -1; int stderr_producer_fd = -1;
status = status =
fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd); fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
GTEST_DEATH_TEST_CHECK_(status >= 0); GTEST_DEATH_TEST_CHECK_(status >= 0);
// Make the stderr socket nonblocking. // Make the stderr socket nonblocking.
GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0); GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
fdio_spawn_action_t* add_stderr_action = &spawn_actions[1]; fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD; add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
add_stderr_action->fd.local_fd = stderr_producer_fd; add_stderr_action->fd.local_fd = stderr_producer_fd;
add_stderr_action->fd.target_fd = STDERR_FILENO; add_stderr_action->fd.target_fd = STDERR_FILENO;
// Create a child job. // Create a child job.
zx_handle_t child_job = ZX_HANDLE_INVALID; zx_handle_t child_job = ZX_HANDLE_INVALID;
status = zx_job_create(zx_job_default(), 0, & child_job); status = zx_job_create(zx_job_default(), 0, &child_job);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK); GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
zx_policy_basic_t policy; zx_policy_basic_t policy;
policy.condition = ZX_POL_NEW_ANY; policy.condition = ZX_POL_NEW_ANY;
policy.policy = ZX_POL_ACTION_ALLOW; policy.policy = ZX_POL_ACTION_ALLOW;
status = zx_job_set_policy( status = zx_job_set_policy(child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC,
child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1); &policy, 1);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK); GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
// Create an exception channel attached to the |child_job|, to allow // Create an exception channel attached to the |child_job|, to allow
// us to suppress the system default exception handler from firing. // us to suppress the system default exception handler from firing.
status = status = zx_task_create_exception_channel(
zx_task_create_exception_channel( child_job, 0, exception_channel_.reset_and_get_address());
child_job, 0, exception_channel_.reset_and_get_address());
GTEST_DEATH_TEST_CHECK_(status == ZX_OK); GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
// Spawn the child process. // Spawn the child process.
status = fdio_spawn_etc( status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0],
child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr, args.Argv(), nullptr, 2, spawn_actions,
2, spawn_actions, child_process_.reset_and_get_address(), nullptr); child_process_.reset_and_get_address(), nullptr);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK); GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
set_spawned(true); set_spawned(true);
return OVERSEE_TEST; return OVERSEE_TEST;
} }
std::string FuchsiaDeathTest::GetErrorLogs() { std::string FuchsiaDeathTest::GetErrorLogs() { return captured_stderr_; }
return captured_stderr_;
}
#else // We are neither on Windows, nor on Fuchsia. #else // We are neither on Windows, nor on Fuchsia.
// ForkingDeathTest provides implementations for most of the abstract // ForkingDeathTest provides implementations for most of the abstract
// methods of the DeathTest interface. Only the AssumeRole method is // methods of the DeathTest interface. Only the AssumeRole method is
// left undefined. // left undefined.
class ForkingDeathTest : public DeathTestImpl { class ForkingDeathTest : public DeathTestImpl {
public: public:
ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher); ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher);
skipping to change at line 1096 skipping to change at line 1084
// Constructs a ForkingDeathTest. // Constructs a ForkingDeathTest.
ForkingDeathTest::ForkingDeathTest(const char* a_statement, ForkingDeathTest::ForkingDeathTest(const char* a_statement,
Matcher<const std::string&> matcher) Matcher<const std::string&> matcher)
: DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {} : DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
// Waits for the child in a death test to exit, returning its exit // Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the // status, or 0 if no child process exists. As a side effect, sets the
// outcome data member. // outcome data member.
int ForkingDeathTest::Wait() { int ForkingDeathTest::Wait() {
if (!spawned()) if (!spawned()) return 0;
return 0;
ReadAndInterpretStatusByte(); ReadAndInterpretStatusByte();
int status_value; int status_value;
GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
set_status(status_value); set_status(status_value);
return status_value; return status_value;
} }
// A concrete death test class that forks, then immediately runs the test // A concrete death test class that forks, then immediately runs the test
skipping to change at line 1176 skipping to change at line 1163
ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher, ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const char* file, int line) const char* file, int line)
: ForkingDeathTest(a_statement, std::move(matcher)), : ForkingDeathTest(a_statement, std::move(matcher)),
file_(file), file_(file),
line_(line) {} line_(line) {}
TestRole AssumeRole() override; TestRole AssumeRole() override;
private: private:
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() { static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
::std::vector<std::string> args = GetInjectableArgvs(); ::std::vector<std::string> args = GetInjectableArgvs();
# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) #if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
::std::vector<std::string> extra_args = ::std::vector<std::string> extra_args =
GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_(); GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
args.insert(args.end(), extra_args.begin(), extra_args.end()); args.insert(args.end(), extra_args.begin(), extra_args.end());
# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_) #endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
return args; return args;
} }
// The name of the file in which the death test is located. // The name of the file in which the death test is located.
const char* const file_; const char* const file_;
// The line number on which the death test is located. // The line number on which the death test is located.
const int line_; const int line_;
}; };
// Utility class for accumulating command-line arguments. // Utility class for accumulating command-line arguments.
class Arguments { class Arguments {
skipping to change at line 1207 skipping to change at line 1194
free(*i); free(*i);
} }
} }
void AddArgument(const char* argument) { void AddArgument(const char* argument) {
args_.insert(args_.end() - 1, posix::StrDup(argument)); args_.insert(args_.end() - 1, posix::StrDup(argument));
} }
template <typename Str> template <typename Str>
void AddArguments(const ::std::vector<Str>& arguments) { void AddArguments(const ::std::vector<Str>& arguments) {
for (typename ::std::vector<Str>::const_iterator i = arguments.begin(); for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
i != arguments.end(); i != arguments.end(); ++i) {
++i) {
args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
} }
} }
char* const* Argv() { char* const* Argv() { return &args_[0]; }
return &args_[0];
}
private: private:
std::vector<char*> args_; std::vector<char*> args_;
}; };
// A struct that encompasses the arguments to the child process of a // A struct that encompasses the arguments to the child process of a
// threadsafe-style death test process. // threadsafe-style death test process.
struct ExecDeathTestArgs { struct ExecDeathTestArgs {
char* const* argv; // Command-line arguments for the child's call to exec char* const* argv; // Command-line arguments for the child's call to exec
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_QNX #if GTEST_OS_QNX
extern "C" char** environ; extern "C" char** environ;
# else // GTEST_OS_QNX #else // 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.
static int ExecDeathTestChildMain(void* child_arg) { static int ExecDeathTestChildMain(void* child_arg) {
ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg); ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
// We need to execute the test program in the same environment where // We need to execute the test program in the same environment where
// it was originally invoked. Therefore we change to the original // it was originally invoked. Therefore we change to the original
// working directory first. // working directory first.
const char* const original_dir = const char* const original_dir =
UnitTest::GetInstance()->original_working_dir(); UnitTest::GetInstance()->original_working_dir();
// We can safely call chdir() as it's a direct system call. // We can safely call chdir() as it's a direct system call.
if (chdir(original_dir) != 0) { if (chdir(original_dir) != 0) {
DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + DeathTestAbort(std::string("chdir(\"") + original_dir +
GetLastErrnoDescription()); "\") failed: " + GetLastErrnoDescription());
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// We can safely call execv() as it's almost a direct system call. We // We can safely call execv() as it's almost a direct system call. We
// cannot use execvp() as it's a libc function and thus potentially // cannot use execvp() as it's a libc function and thus potentially
// unsafe. Since execv() doesn't search the PATH, the user must // unsafe. Since execv() 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.
execv(args->argv[0], args->argv); execv(args->argv[0], args->argv);
DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " + DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
original_dir + " failed: " + original_dir + " failed: " + GetLastErrnoDescription());
GetLastErrnoDescription());
return EXIT_FAILURE; return EXIT_FAILURE;
} }
# endif // GTEST_OS_QNX #endif // GTEST_OS_QNX
# if GTEST_HAS_CLONE #if GTEST_HAS_CLONE
// Two utility routines that together determine the direction the stack // Two utility routines that together determine the direction the stack
// grows. // grows.
// 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.
// //
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining // GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
// StackLowerThanAddress into StackGrowsDown, which then doesn't give // StackLowerThanAddress into StackGrowsDown, which then doesn't give
// correct answer. // correct answer.
static void StackLowerThanAddress(const void* ptr, static void StackLowerThanAddress(const void* ptr,
skipping to change at line 1296 skipping to change at line 1279
// Make sure AddressSanitizer does not tamper with the stack here. // Make sure AddressSanitizer does not tamper with the stack here.
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
static bool StackGrowsDown() { static bool StackGrowsDown() {
int dummy = 0; int dummy = 0;
bool result; bool result;
StackLowerThanAddress(&dummy, &result); StackLowerThanAddress(&dummy, &result);
return result; return result;
} }
# endif // GTEST_HAS_CLONE #endif // GTEST_HAS_CLONE
// Spawns a child process with the same executable as the current process in // Spawns a child process with the same executable as the current process in
// a thread-safe manner and instructs it to run the death test. The // a thread-safe manner and instructs it to run the death test. The
// implementation uses fork(2) + exec. On systems where clone(2) is // implementation uses fork(2) + exec. On systems where clone(2) is
// available, it is used instead, being slightly more thread-safe. On QNX, // available, it is used instead, being slightly more thread-safe. On QNX,
// fork supports only single-threaded environments, so this function uses // fork supports only single-threaded environments, so this function uses
// spawn(2) there instead. The function dies with an error message if // spawn(2) there instead. The function dies with an error message if
// anything goes wrong. // anything goes wrong.
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { 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_OS_QNX #if GTEST_OS_QNX
// Obtains the current directory and sets it to be closed in the child // Obtains the current directory and sets it to be closed in the child
// process. // process.
const int cwd_fd = open(".", O_RDONLY); const int cwd_fd = open(".", O_RDONLY);
GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
// We need to execute the test program in the same environment where // We need to execute the test program in the same environment where
// it was originally invoked. Therefore we change to the original // it was originally invoked. Therefore we change to the original
// working directory first. // working directory first.
const char* const original_dir = const char* const original_dir =
UnitTest::GetInstance()->original_working_dir(); UnitTest::GetInstance()->original_working_dir();
// We can safely call chdir() as it's a direct system call. // We can safely call chdir() as it's a direct system call.
if (chdir(original_dir) != 0) { if (chdir(original_dir) != 0) {
DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + DeathTestAbort(std::string("chdir(\"") + original_dir +
GetLastErrnoDescription()); "\") failed: " + GetLastErrnoDescription());
return EXIT_FAILURE; return EXIT_FAILURE;
} }
int fd_flags; int fd_flags;
// Set close_fd to be closed after spawn. // 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_(fd_flags = fcntl(close_fd, F_GETFD));
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, GTEST_DEATH_TEST_CHECK_SYSCALL_(
fd_flags | FD_CLOEXEC)); fcntl(close_fd, F_SETFD, fd_flags | FD_CLOEXEC));
struct inheritance inherit = {0}; struct inheritance inherit = {0};
// spawn is a system call. // spawn is a system call.
child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ); child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ);
// Restores the current working directory. // Restores the current working directory.
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
# else // GTEST_OS_QNX #else // GTEST_OS_QNX
# if GTEST_OS_LINUX #if GTEST_OS_LINUX
// When a SIGPROF signal is received while fork() or clone() are executing, // When a SIGPROF signal is received while fork() or clone() are executing,
// the process may hang. To avoid this, we ignore SIGPROF here and re-enable // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
// it after the call to fork()/clone() is complete. // it after the call to fork()/clone() is complete.
struct sigaction saved_sigprof_action; struct sigaction saved_sigprof_action;
struct sigaction ignore_sigprof_action; struct sigaction ignore_sigprof_action;
memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
sigemptyset(&ignore_sigprof_action.sa_mask); sigemptyset(&ignore_sigprof_action.sa_mask);
ignore_sigprof_action.sa_handler = SIG_IGN; ignore_sigprof_action.sa_handler = SIG_IGN;
GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( GTEST_DEATH_TEST_CHECK_SYSCALL_(
SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); sigaction(SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
# endif // GTEST_OS_LINUX #endif // GTEST_OS_LINUX
# if GTEST_HAS_CLONE #if GTEST_HAS_CLONE
const bool use_fork = GTEST_FLAG(death_test_use_fork); const bool use_fork = GTEST_FLAG_GET(death_test_use_fork);
if (!use_fork) { if (!use_fork) {
static const bool stack_grows_down = StackGrowsDown(); static const bool stack_grows_down = StackGrowsDown();
const auto stack_size = static_cast<size_t>(getpagesize() * 2); const auto stack_size = static_cast<size_t>(getpagesize() * 2);
// MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE, void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0); MAP_ANON | MAP_PRIVATE, -1, 0);
GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
// Maximum stack alignment in bytes: For a downward-growing stack, this // Maximum stack alignment in bytes: For a downward-growing stack, this
// amount is subtracted from size of the stack space to get an address // amount is subtracted from size of the stack space to get an address
// that is within the stack space and is aligned on all systems we care // that is within the stack space and is aligned on all systems we care
// about. As far as I know there is no ABI with stack alignment greater // about. As far as I know there is no ABI with stack alignment greater
// than 64. We assume stack and stack_size already have alignment of // than 64. We assume stack and stack_size already have alignment of
// kMaxStackAlignment. // kMaxStackAlignment.
const size_t kMaxStackAlignment = 64; const size_t kMaxStackAlignment = 64;
void* const stack_top = void* const stack_top =
static_cast<char*>(stack) + static_cast<char*>(stack) +
(stack_grows_down ? stack_size - kMaxStackAlignment : 0); (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
GTEST_DEATH_TEST_CHECK_( GTEST_DEATH_TEST_CHECK_(
static_cast<size_t>(stack_size) > kMaxStackAlignment && static_cast<size_t>(stack_size) > kMaxStackAlignment &&
reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0); reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
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 #endif // GTEST_OS_QNX
# if GTEST_OS_LINUX #if GTEST_OS_LINUX
GTEST_DEATH_TEST_CHECK_SYSCALL_( GTEST_DEATH_TEST_CHECK_SYSCALL_(
sigaction(SIGPROF, &saved_sigprof_action, nullptr)); sigaction(SIGPROF, &saved_sigprof_action, nullptr));
# endif // GTEST_OS_LINUX #endif // GTEST_OS_LINUX
GTEST_DEATH_TEST_CHECK_(child_pid != -1); GTEST_DEATH_TEST_CHECK_(child_pid != -1);
return child_pid; return child_pid;
} }
// The AssumeRole process for a fork-and-exec death test. It re-executes the // The AssumeRole process for a fork-and-exec death test. It re-executes the
// main program from the beginning, setting the --gtest_filter // main program from the beginning, setting the --gtest_filter
// and --gtest_internal_run_death_test flags to cause only the current // and --gtest_internal_run_death_test flags to cause only the current
// death test to be re-run. // death test to be re-run.
DeathTest::TestRole ExecDeathTest::AssumeRole() { DeathTest::TestRole ExecDeathTest::AssumeRole() {
skipping to change at line 1423 skipping to change at line 1406
return EXECUTE_TEST; return EXECUTE_TEST;
} }
int pipe_fd[2]; int pipe_fd[2];
GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
// Clear the close-on-exec flag on the write end of the pipe, lest // Clear the close-on-exec flag on the write end of the pipe, lest
// it be closed when the child process does an exec: // it be closed when the child process does an exec:
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
kFilterFlag + "=" + info->test_suite_name() + "filter=" + info->test_suite_name() + "." +
"." + info->name(); info->name();
const std::string internal_flag = const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" "internal_run_death_test=" + file_ + "|" +
+ file_ + "|" + StreamableToString(line_) + "|" StreamableToString(line_) + "|" +
+ StreamableToString(death_test_index) + "|" StreamableToString(death_test_index) + "|" +
+ StreamableToString(pipe_fd[1]); StreamableToString(pipe_fd[1]);
Arguments args; Arguments args;
args.AddArguments(GetArgvsForDeathTestChildProcess()); args.AddArguments(GetArgvsForDeathTestChildProcess());
args.AddArgument(filter_flag.c_str()); args.AddArgument(filter_flag.c_str());
args.AddArgument(internal_flag.c_str()); args.AddArgument(internal_flag.c_str());
DeathTest::set_last_death_test_message(""); DeathTest::set_last_death_test_message("");
CaptureStderr(); CaptureStderr();
// See the comment in NoExecDeathTest::AssumeRole for why the next line // See the comment in NoExecDeathTest::AssumeRole for why the next line
// is necessary. // is necessary.
FlushInfoLog(); FlushInfoLog();
const pid_t child_pid = ExecDeathTestSpawnChild(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]);
set_spawned(true); set_spawned(true);
return OVERSEE_TEST; return OVERSEE_TEST;
} }
# endif // !GTEST_OS_WINDOWS #endif // !GTEST_OS_WINDOWS
// Creates a concrete DeathTest-derived class that depends on the // Creates a concrete DeathTest-derived class that depends on the
// --gtest_death_test_style flag, and sets the pointer pointed to // --gtest_death_test_style flag, and sets the pointer pointed to
// by the "test" argument to its address. If the test should be // by the "test" argument to its address. If the test should be
// skipped, sets that pointer to NULL. Returns true, unless the // skipped, sets that pointer to NULL. Returns true, unless the
// flag is set to an invalid value. // flag is set to an invalid value.
bool DefaultDeathTestFactory::Create(const char* statement, bool DefaultDeathTestFactory::Create(const char* statement,
Matcher<const std::string&> matcher, Matcher<const std::string&> matcher,
const char* file, int line, const char* file, int line,
DeathTest** test) { DeathTest** test) {
UnitTestImpl* const impl = GetUnitTestImpl(); UnitTestImpl* const impl = GetUnitTestImpl();
const InternalRunDeathTestFlag* const flag = const InternalRunDeathTestFlag* const flag =
impl->internal_run_death_test_flag(); impl->internal_run_death_test_flag();
const int death_test_index = impl->current_test_info() const int death_test_index =
->increment_death_test_count(); impl->current_test_info()->increment_death_test_count();
if (flag != nullptr) { if (flag != nullptr) {
if (death_test_index > flag->index()) { if (death_test_index > flag->index()) {
DeathTest::set_last_death_test_message( DeathTest::set_last_death_test_message(
"Death test count (" + StreamableToString(death_test_index) "Death test count (" + StreamableToString(death_test_index) +
+ ") somehow exceeded expected maximum (" ") somehow exceeded expected maximum (" +
+ StreamableToString(flag->index()) + ")"); StreamableToString(flag->index()) + ")");
return false; return false;
} }
if (!(flag->file() == file && flag->line() == line && if (!(flag->file() == file && flag->line() == line &&
flag->index() == death_test_index)) { flag->index() == death_test_index)) {
*test = nullptr; *test = nullptr;
return true; return true;
} }
} }
# if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
if (GTEST_FLAG(death_test_style) == "threadsafe" || if (GTEST_FLAG_GET(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") { GTEST_FLAG_GET(death_test_style) == "fast") {
*test = new WindowsDeathTest(statement, std::move(matcher), file, line); *test = new WindowsDeathTest(statement, std::move(matcher), file, line);
} }
# elif GTEST_OS_FUCHSIA #elif GTEST_OS_FUCHSIA
if (GTEST_FLAG(death_test_style) == "threadsafe" || if (GTEST_FLAG_GET(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") { GTEST_FLAG_GET(death_test_style) == "fast") {
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line); *test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
} }
# else #else
if (GTEST_FLAG(death_test_style) == "threadsafe") { if (GTEST_FLAG_GET(death_test_style) == "threadsafe") {
*test = new ExecDeathTest(statement, std::move(matcher), file, line); *test = new ExecDeathTest(statement, std::move(matcher), file, line);
} else if (GTEST_FLAG(death_test_style) == "fast") { } else if (GTEST_FLAG_GET(death_test_style) == "fast") {
*test = new NoExecDeathTest(statement, std::move(matcher)); *test = new NoExecDeathTest(statement, std::move(matcher));
} }
# endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
else { // NOLINT - this is more readable than unbalanced brackets inside #if. else { // NOLINT - this is more readable than unbalanced brackets inside #if.
DeathTest::set_last_death_test_message( DeathTest::set_last_death_test_message("Unknown death test style \"" +
"Unknown death test style \"" + GTEST_FLAG(death_test_style) GTEST_FLAG_GET(death_test_style) +
+ "\" encountered"); "\" encountered");
return false; return false;
} }
return true; return true;
} }
# if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
// Recreates the pipe and event handles from the provided parameters, // Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe // signals the event, and returns a file descriptor wrapped around the pipe
// handle. This function is called in the child process only. // handle. This function is called in the child process only.
static int GetStatusFileDescriptor(unsigned int parent_process_id, static int GetStatusFileDescriptor(unsigned int parent_process_id,
size_t write_handle_as_size_t, size_t write_handle_as_size_t,
size_t event_handle_as_size_t) { size_t event_handle_as_size_t) {
AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
FALSE, // Non-inheritable. FALSE, // Non-inheritable.
parent_process_id)); parent_process_id));
if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
DeathTestAbort("Unable to open parent process " + DeathTestAbort("Unable to open parent process " +
StreamableToString(parent_process_id)); StreamableToString(parent_process_id));
} }
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
const HANDLE write_handle = const HANDLE write_handle = reinterpret_cast<HANDLE>(write_handle_as_size_t);
reinterpret_cast<HANDLE>(write_handle_as_size_t);
HANDLE dup_write_handle; HANDLE dup_write_handle;
// The newly initialized handle is accessible only in the parent // The newly initialized handle is accessible only in the parent
// process. To obtain one accessible within the child, we need to use // process. To obtain one accessible within the child, we need to use
// DuplicateHandle. // DuplicateHandle.
if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
::GetCurrentProcess(), &dup_write_handle, ::GetCurrentProcess(), &dup_write_handle,
0x0, // Requested privileges ignored since 0x0, // Requested privileges ignored since
// DUPLICATE_SAME_ACCESS is used. // DUPLICATE_SAME_ACCESS is used.
FALSE, // Request non-inheritable handler. FALSE, // Request non-inheritable handler.
skipping to change at line 1557 skipping to change at line 1539
DeathTestAbort("Unable to duplicate the pipe handle " + DeathTestAbort("Unable to duplicate the pipe handle " +
StreamableToString(write_handle_as_size_t) + StreamableToString(write_handle_as_size_t) +
" from the parent process " + " from the parent process " +
StreamableToString(parent_process_id)); StreamableToString(parent_process_id));
} }
const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t); const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
HANDLE dup_event_handle; HANDLE dup_event_handle;
if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
::GetCurrentProcess(), &dup_event_handle, ::GetCurrentProcess(), &dup_event_handle, 0x0, FALSE,
0x0,
FALSE,
DUPLICATE_SAME_ACCESS)) { DUPLICATE_SAME_ACCESS)) {
DeathTestAbort("Unable to duplicate the event handle " + DeathTestAbort("Unable to duplicate the event handle " +
StreamableToString(event_handle_as_size_t) + StreamableToString(event_handle_as_size_t) +
" from the parent process " + " from the parent process " +
StreamableToString(parent_process_id)); StreamableToString(parent_process_id));
} }
const int write_fd = const int write_fd =
::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND); ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
if (write_fd == -1) { if (write_fd == -1) {
skipping to change at line 1581 skipping to change at line 1561
StreamableToString(write_handle_as_size_t) + StreamableToString(write_handle_as_size_t) +
" to a file descriptor"); " to a file descriptor");
} }
// Signals the parent that the write end of the pipe has been acquired // Signals the parent that the write end of the pipe has been acquired
// so the parent can release its own write end. // so the parent can release its own write end.
::SetEvent(dup_event_handle); ::SetEvent(dup_event_handle);
return write_fd; return write_fd;
} }
# endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
// Returns a newly created InternalRunDeathTestFlag object with fields // Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if // initialized from the GTEST_FLAG(internal_run_death_test) flag if
// the flag is specified; otherwise returns NULL. // the flag is specified; otherwise returns NULL.
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
if (GTEST_FLAG(internal_run_death_test) == "") return nullptr; if (GTEST_FLAG_GET(internal_run_death_test) == "") return nullptr;
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
// can use it here. // can use it here.
int line = -1; int line = -1;
int index = -1; int index = -1;
::std::vector< ::std::string> fields; ::std::vector< ::std::string> fields;
SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); SplitString(GTEST_FLAG_GET(internal_run_death_test), '|', &fields);
int write_fd = -1; int write_fd = -1;
# if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
unsigned int parent_process_id = 0; unsigned int parent_process_id = 0;
size_t write_handle_as_size_t = 0; size_t write_handle_as_size_t = 0;
size_t event_handle_as_size_t = 0; size_t event_handle_as_size_t = 0;
if (fields.size() != 6 if (fields.size() != 6 || !ParseNaturalNumber(fields[1], &line) ||
|| !ParseNaturalNumber(fields[1], &line) !ParseNaturalNumber(fields[2], &index) ||
|| !ParseNaturalNumber(fields[2], &index) !ParseNaturalNumber(fields[3], &parent_process_id) ||
|| !ParseNaturalNumber(fields[3], &parent_process_id) !ParseNaturalNumber(fields[4], &write_handle_as_size_t) ||
|| !ParseNaturalNumber(fields[4], &write_handle_as_size_t) !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
|| !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
GTEST_FLAG(internal_run_death_test)); GTEST_FLAG_GET(internal_run_death_test));
} }
write_fd = GetStatusFileDescriptor(parent_process_id, write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t,
write_handle_as_size_t,
event_handle_as_size_t); event_handle_as_size_t);
# elif GTEST_OS_FUCHSIA #elif GTEST_OS_FUCHSIA
if (fields.size() != 3 if (fields.size() != 3 || !ParseNaturalNumber(fields[1], &line) ||
|| !ParseNaturalNumber(fields[1], &line) !ParseNaturalNumber(fields[2], &index)) {
|| !ParseNaturalNumber(fields[2], &index)) { DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " GTEST_FLAG_GET(internal_run_death_test));
+ GTEST_FLAG(internal_run_death_test));
} }
# else #else
if (fields.size() != 4 if (fields.size() != 4 || !ParseNaturalNumber(fields[1], &line) ||
|| !ParseNaturalNumber(fields[1], &line) !ParseNaturalNumber(fields[2], &index) ||
|| !ParseNaturalNumber(fields[2], &index) !ParseNaturalNumber(fields[3], &write_fd)) {
|| !ParseNaturalNumber(fields[3], &write_fd)) { DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " GTEST_FLAG_GET(internal_run_death_test));
+ GTEST_FLAG(internal_run_death_test));
} }
# endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
} }
} // namespace internal } // namespace internal
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
} // namespace testing } // namespace testing
 End of changes. 121 change blocks. 
272 lines changed or deleted 248 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)