diff options
Diffstat (limited to 'utils/unittest/googletest/gtest-death-test.cc')
-rw-r--r-- | utils/unittest/googletest/gtest-death-test.cc | 849 |
1 files changed, 623 insertions, 226 deletions
diff --git a/utils/unittest/googletest/gtest-death-test.cc b/utils/unittest/googletest/gtest-death-test.cc index 617e301..e4199de 100644 --- a/utils/unittest/googletest/gtest-death-test.cc +++ b/utils/unittest/googletest/gtest-death-test.cc @@ -27,17 +27,31 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Author: wan@google.com (Zhanyong Wan) +// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev) // // This file implements death tests. #include <gtest/gtest-death-test.h> #include <gtest/internal/gtest-port.h> -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST + +#if GTEST_OS_MAC +#include <crt_externs.h> +#endif // GTEST_OS_MAC + #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <stdarg.h> + +#if GTEST_OS_WINDOWS +#include <windows.h> +#else +#include <sys/mman.h> +#include <sys/wait.h> +#endif // GTEST_OS_WINDOWS + #endif // GTEST_HAS_DEATH_TEST #include <gtest/gtest-message.h> @@ -48,9 +62,9 @@ // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. -#define GTEST_IMPLEMENTATION +#define GTEST_IMPLEMENTATION_ 1 #include "gtest/internal/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION +#undef GTEST_IMPLEMENTATION_ namespace testing { @@ -68,6 +82,18 @@ GTEST_DEFINE_string_( "\"fast\" (child process runs the death test immediately " "after forking)."); +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + namespace internal { GTEST_DEFINE_string_( internal_run_death_test, "", @@ -79,7 +105,7 @@ GTEST_DEFINE_string_( "death test. FOR INTERNAL USE ONLY."); } // namespace internal -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST // ExitedWithCode constructor. ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { @@ -87,9 +113,14 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { // ExitedWithCode function-call operator. bool ExitedWithCode::operator()(int exit_status) const { +#if GTEST_OS_WINDOWS + return exit_status == exit_code_; +#else return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; +#endif // GTEST_OS_WINDOWS } +#if !GTEST_OS_WINDOWS // KilledBySignal constructor. KilledBySignal::KilledBySignal(int signum) : signum_(signum) { } @@ -98,6 +129,7 @@ KilledBySignal::KilledBySignal(int signum) : signum_(signum) { bool KilledBySignal::operator()(int exit_status) const { return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; } +#endif // !GTEST_OS_WINDOWS namespace internal { @@ -107,6 +139,9 @@ namespace internal { // specified by wait(2). static String ExitSummary(int exit_code) { Message m; +#if GTEST_OS_WINDOWS + m << "Exited with exit status " << exit_code; +#else if (WIFEXITED(exit_code)) { m << "Exited with exit status " << WEXITSTATUS(exit_code); } else if (WIFSIGNALED(exit_code)) { @@ -117,6 +152,7 @@ static String ExitSummary(int exit_code) { m << " (core dumped)"; } #endif +#endif // GTEST_OS_WINDOWS return m.GetString(); } @@ -126,6 +162,7 @@ bool ExitedUnsuccessfully(int exit_status) { return !ExitedWithCode(0)(exit_status); } +#if !GTEST_OS_WINDOWS // Generates a textual failure message when a death test finds more than // one thread running, or cannot determine the number of threads, prior // to executing the given statement. It is the responsibility of the @@ -133,17 +170,14 @@ bool ExitedUnsuccessfully(int exit_status) { static String DeathTestThreadWarning(size_t thread_count) { Message msg; 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) msg << "couldn't detect the number of threads."; else msg << "detected " << thread_count << " threads."; return msg.GetString(); } - -// Static string containing a description of the outcome of the -// last death test. -static String last_death_test_message; +#endif // !GTEST_OS_WINDOWS // Flag characters for reporting a death test that did not die. static const char kDeathTestLived = 'L'; @@ -159,29 +193,25 @@ static const char kDeathTestInternalError = 'I'; enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED }; // Routine for aborting the program which is safe to call from an -// exec-style death test child process, in which case the the error +// exec-style death test child process, in which case the error // message is propagated back to the parent process. Otherwise, the // message is simply printed to stderr. In either case, the program // then exits with status 1. -void DeathTestAbort(const char* format, ...) { - // This function may be called from a threadsafe-style death test - // child process, which operates on a very small stack. Use the - // heap for any additional non-miniscule memory requirements. +void DeathTestAbort(const String& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. const InternalRunDeathTestFlag* const flag = GetUnitTestImpl()->internal_run_death_test_flag(); - va_list args; - va_start(args, format); - if (flag != NULL) { - FILE* parent = fdopen(flag->status_fd, "w"); + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); fputc(kDeathTestInternalError, parent); - vfprintf(parent, format, args); - fclose(parent); - va_end(args); + fprintf(parent, "%s", message.c_str()); + fflush(parent); _exit(1); } else { - vfprintf(stderr, format, args); - va_end(args); + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); abort(); } } @@ -190,11 +220,12 @@ void DeathTestAbort(const char* format, ...) { // fails. #define GTEST_DEATH_TEST_CHECK_(expression) \ do { \ - if (!(expression)) { \ - DeathTestAbort("CHECK failed: File %s, line %d: %s", \ - __FILE__, __LINE__, #expression); \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s", \ + __FILE__, __LINE__, #expression)); \ } \ - } while (0) + } while (::testing::internal::AlwaysFalse()) // 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 @@ -205,15 +236,46 @@ void DeathTestAbort(const char* format, ...) { // something other than EINTR, DeathTestAbort is called. #define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ do { \ - int retval; \ + int gtest_retval; \ do { \ - retval = (expression); \ - } while (retval == -1 && errno == EINTR); \ - if (retval == -1) { \ - DeathTestAbort("CHECK failed: File %s, line %d: %s != -1", \ - __FILE__, __LINE__, #expression); \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s != -1", \ + __FILE__, __LINE__, #expression)); \ } \ - } while (0) + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +String GetLastErrnoDescription() { + return String(errno == 0 ? "" : posix::StrError(errno)); +} + +// 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 +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} // Death test constructor. Increments the running death test count // for the current test. @@ -234,143 +296,146 @@ bool DeathTest::Create(const char* statement, const RE* regex, } const char* DeathTest::LastMessage() { - return last_death_test_message.c_str(); + return last_death_test_message_.c_str(); } -// ForkingDeathTest provides implementations for most of the abstract -// methods of the DeathTest interface. Only the AssumeRole method is -// left undefined. -class ForkingDeathTest : public DeathTest { - public: - ForkingDeathTest(const char* statement, const RE* regex); +void DeathTest::set_last_death_test_message(const String& message) { + last_death_test_message_ = message; +} - // All of these virtual functions are inherited from DeathTest. - virtual int Wait(); - virtual bool Passed(bool status_ok); - virtual void Abort(AbortReason reason); +String DeathTest::last_death_test_message_; +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { protected: - void set_forked(bool forked) { forked_ = forked; } - void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } void set_write_fd(int fd) { write_fd_ = fd; } + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + private: - // The textual content of the code this object is testing. + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. const char* const statement_; - // The regular expression which test output must match. + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. const RE* const regex_; - // True if the death test successfully forked. - bool forked_; - // PID of child process during death test; 0 in the child process itself. - pid_t child_pid_; - // File descriptors for communicating the death test's status byte. - int read_fd_; // Always -1 in the child process. - int write_fd_; // Always -1 in the parent process. + // True if the death test child process has been successfully spawned. + bool spawned_; // The exit status of the child process. int status_; // How the death test concluded. DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; }; -// Constructs a ForkingDeathTest. -ForkingDeathTest::ForkingDeathTest(const char* statement, const RE* regex) - : DeathTest(), - statement_(statement), - regex_(regex), - forked_(false), - child_pid_(-1), - read_fd_(-1), - write_fd_(-1), - status_(-1), - outcome_(IN_PROGRESS) { -} - -// Reads an internal failure message from a file descriptor, then calls -// LOG(FATAL) with that message. Called from a death test parent process -// to read a failure message from the death test child process. -static void FailFromInternalError(int fd) { - Message error; - char buffer[256]; - ssize_t num_read; - - do { - while ((num_read = read(fd, buffer, 255)) > 0) { - buffer[num_read] = '\0'; - error << buffer; - } - } while (num_read == -1 && errno == EINTR); - - // TODO(smcafee): Maybe just FAIL the test instead? - if (num_read == 0) { - GTEST_LOG_(FATAL, error); - } else { - GTEST_LOG_(FATAL, - Message() << "Error while reading death test internal: " - << strerror(errno) << " [" << errno << "]"); - } -} - -// 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 -// outcome data member. -int ForkingDeathTest::Wait() { - if (!forked_) - return 0; +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; // The read() here blocks until data is available (signifying the // failure of the death test) or until the pipe is closed (signifying // its success), so it's okay to call this in the parent before // the child process has exited. - char flag; - ssize_t bytes_read; - do { - bytes_read = read(read_fd_, &flag, 1); + bytes_read = posix::Read(read_fd(), &flag, 1); } while (bytes_read == -1 && errno == EINTR); if (bytes_read == 0) { - outcome_ = DIED; + set_outcome(DIED); } else if (bytes_read == 1) { switch (flag) { case kDeathTestReturned: - outcome_ = RETURNED; + set_outcome(RETURNED); break; case kDeathTestLived: - outcome_ = LIVED; + set_outcome(LIVED); break; case kDeathTestInternalError: - FailFromInternalError(read_fd_); // Does not return. + FailFromInternalError(read_fd()); // Does not return. break; default: - GTEST_LOG_(FATAL, - Message() << "Death test child process reported unexpected " - << "status byte (" << static_cast<unsigned int>(flag) - << ")"); + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast<unsigned int>(flag) << ")"; } } else { - GTEST_LOG_(FATAL, - Message() << "Read from death test child process failed: " - << strerror(errno)); + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(read_fd_)); - GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_, 0)); - return status_; +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // 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 + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned; + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(write_fd())); + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) } // Assesses the success or failure of a death test, using both private // members which have previously been set, and one argument: // // Private data members: -// outcome: an enumeration describing how the death test +// outcome: An enumeration describing how the death test // concluded: DIED, LIVED, or RETURNED. The death test fails -// in the latter two cases -// status: the exit status of the child process, in the format -// specified by wait(2) -// regex: a regular expression object to be applied to +// in the latter two cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to // the test's captured standard error output; the death test -// fails if it does not match +// fails if it does not match. // // Argument: // status_ok: true if exit_status is acceptable in the context of @@ -378,22 +443,18 @@ int ForkingDeathTest::Wait() { // // Returns true iff all of the above conditions are met. Otherwise, the // first failing condition, in the order given above, is the one that is -// reported. Also sets the static variable last_death_test_message. -bool ForkingDeathTest::Passed(bool status_ok) { - if (!forked_) +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) return false; -#if GTEST_HAS_GLOBAL_STRING - const ::string error_message = GetCapturedStderr(); -#else - const ::std::string error_message = GetCapturedStderr(); -#endif // GTEST_HAS_GLOBAL_STRING + const String error_message = GetCapturedStderr(); bool success = false; Message buffer; - buffer << "Death test: " << statement_ << "\n"; - switch (outcome_) { + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { case LIVED: buffer << " Result: failed to die.\n" << " Error msg: " << error_message; @@ -404,49 +465,271 @@ bool ForkingDeathTest::Passed(bool status_ok) { break; case DIED: if (status_ok) { - if (RE::PartialMatch(error_message, *regex_)) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { success = true; } else { buffer << " Result: died but not with expected error.\n" - << " Expected: " << regex_->pattern() << "\n" + << " Expected: " << regex()->pattern() << "\n" << "Actual msg: " << error_message; } } else { buffer << " Result: died but not with expected exit code:\n" - << " " << ExitSummary(status_) << "\n"; + << " " << ExitSummary(status()) << "\n"; } break; case IN_PROGRESS: default: - GTEST_LOG_(FATAL, - "DeathTest::Passed somehow called before conclusion of test"); + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; } - last_death_test_message = buffer.GetString(); + DeathTest::set_last_death_test_message(buffer.GetString()); return success; } -// Signals that the death test code which should have exited, didn't. -// Should be called only in a death test child process. -// Writes a status byte to the child's status file desriptor, then -// calls _exit(1). -void ForkingDeathTest::Abort(AbortReason reason) { - // 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 - // to the pipe, then exit. - const char flag = - reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned; - GTEST_DEATH_TEST_CHECK_SYSCALL_(write(write_fd_, &flag, 1)); - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(write_fd_)); - _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +#if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* statement, + const RE* regex, + const char* file, + int line) + : DeathTestImpl(statement, regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // 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 + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// 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 +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status; + GTEST_DEATH_TEST_CHECK_(::GetExitCodeProcess(child_handle_.Get(), &status) + != FALSE); + child_handle_.Reset(); + set_status(static_cast<int>(status)); + return this->status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const String filter_flag = String::Format("--%s%s=%s.%s", + GTEST_FLAG_PREFIX_, kFilterFlag, + info->test_case_name(), + info->name()); + const String internal_flag = String::Format( + "--%s%s=%s|%d|%d|%u|%Iu|%Iu", + GTEST_FLAG_PREFIX_, + kInternalRunDeathTestFlag, + file_, line_, + death_test_index, + static_cast<unsigned int>(::GetCurrentProcessId()), + // size_t has the same with as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + reinterpret_cast<size_t>(write_handle), + reinterpret_cast<size_t>(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + String command_line = String::Format("%s %s \"%s\"", + ::GetCommandLineA(), + filter_flag.c_str(), + internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast<char*>(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +#else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// 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 +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; } // A concrete death test class that forks, then immediately runs the test // in the child process. class NoExecDeathTest : public ForkingDeathTest { public: - NoExecDeathTest(const char* statement, const RE* regex) : - ForkingDeathTest(statement, regex) { } + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } virtual TestRole AssumeRole(); }; @@ -455,13 +738,13 @@ class NoExecDeathTest : public ForkingDeathTest { DeathTest::TestRole NoExecDeathTest::AssumeRole() { const size_t thread_count = GetThreadCount(); if (thread_count != 1) { - GTEST_LOG_(WARNING, DeathTestThreadWarning(thread_count)); + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); } int pipe_fd[2]; GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); - last_death_test_message = ""; + DeathTest::set_last_death_test_message(""); CaptureStderr(); // When we fork the process below, the log file buffers are copied, but the // file descriptors are shared. We flush all log files here so that closing @@ -482,11 +765,14 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() { // concurrent writes to the log files. We capture stderr in the parent // process and append the child process' output to a log. LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); return EXECUTE_TEST; } else { GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); set_read_fd(pipe_fd[0]); - set_forked(true); + set_spawned(true); return OVERSEE_TEST; } } @@ -496,9 +782,9 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() { // only this specific death test to be run. class ExecDeathTest : public ForkingDeathTest { public: - ExecDeathTest(const char* statement, const RE* regex, + ExecDeathTest(const char* a_statement, const RE* a_regex, const char* file, int line) : - ForkingDeathTest(statement, regex), file_(file), line_(line) { } + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } virtual TestRole AssumeRole(); private: // The name of the file in which the death test is located. @@ -513,15 +799,15 @@ class Arguments { Arguments() { args_.push_back(NULL); } + ~Arguments() { - for (std::vector<char*>::iterator i = args_.begin(); - i + 1 != args_.end(); + for (std::vector<char*>::iterator i = args_.begin(); i != args_.end(); ++i) { free(*i); } } void AddArgument(const char* argument) { - args_.insert(args_.end() - 1, strdup(argument)); + args_.insert(args_.end() - 1, posix::StrDup(argument)); } template <typename Str> @@ -529,7 +815,7 @@ class Arguments { for (typename ::std::vector<Str>::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - args_.insert(args_.end() - 1, strdup(i->c_str())); + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); } } char* const* Argv() { @@ -546,6 +832,20 @@ struct ExecDeathTestArgs { int close_fd; // File descriptor to close; the read end of a pipe }; +#if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +#else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +#endif // GTEST_OS_MAC + // The main function for a threadsafe-style death test child process. // This function is called in a clone()-ed process and thus must avoid // any potentially unsafe operations like malloc or libc functions. @@ -560,8 +860,9 @@ static int ExecDeathTestChildMain(void* child_arg) { UnitTest::GetInstance()->original_working_dir(); // We can safely call chdir() as it's a direct system call. if (chdir(original_dir) != 0) { - DeathTestAbort("chdir(\"%s\") failed: %s", - original_dir, strerror(errno)); + DeathTestAbort(String::Format("chdir(\"%s\") failed: %s", + original_dir, + GetLastErrnoDescription().c_str())); return EXIT_FAILURE; } @@ -570,9 +871,11 @@ static int ExecDeathTestChildMain(void* child_arg) { // unsafe. Since execve() doesn't search the PATH, the user must // invoke the test program via a valid path that contains at least // one path separator. - execve(args->argv[0], args->argv, environ); - DeathTestAbort("execve(%s, ...) in %s failed: %s", - args->argv[0], original_dir, strerror(errno)); + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s", + args->argv[0], + original_dir, + GetLastErrnoDescription().c_str())); return EXIT_FAILURE; } @@ -581,12 +884,12 @@ static int ExecDeathTestChildMain(void* child_arg) { // This could be accomplished more elegantly by a single recursive // function, but we want to guard against the unlikely possibility of // a smart compiler optimizing the recursion away. -static bool StackLowerThanAddress(const void* ptr) { +bool StackLowerThanAddress(const void* ptr) { int dummy; return &dummy < ptr; } -static bool StackGrowsDown() { +bool StackGrowsDown() { int dummy; return StackLowerThanAddress(&dummy); } @@ -595,18 +898,36 @@ static bool StackGrowsDown() { // that uses clone(2). It dies with an error message if anything goes // wrong. static pid_t ExecDeathTestFork(char* const* argv, int close_fd) { - static const bool stack_grows_down = StackGrowsDown(); - const size_t stack_size = getpagesize(); - void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); - void* const stack_top = - static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0); ExecDeathTestArgs args = { argv, close_fd }; - const pid_t child_pid = clone(&ExecDeathTestChildMain, stack_top, - SIGCHLD, &args); + pid_t child_pid = -1; + +#if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + void* const stack_top = + static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +#else + const bool use_fork = true; +#endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } + GTEST_DEATH_TEST_CHECK_(child_pid != -1); - GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); return child_pid; } @@ -622,7 +943,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { const int death_test_index = info->result()->death_test_count(); if (flag != NULL) { - set_write_fd(flag->status_fd); + set_write_fd(flag->write_fd()); return EXECUTE_TEST; } @@ -634,19 +955,18 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { const String filter_flag = String::Format("--%s%s=%s.%s", - GTEST_FLAG_PREFIX, kFilterFlag, + GTEST_FLAG_PREFIX_, kFilterFlag, info->test_case_name(), info->name()); const String internal_flag = - String::Format("--%s%s=%s:%d:%d:%d", - GTEST_FLAG_PREFIX, kInternalRunDeathTestFlag, file_, line_, - death_test_index, pipe_fd[1]); + String::Format("--%s%s=%s|%d|%d|%d", + GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag, + file_, line_, death_test_index, pipe_fd[1]); Arguments args; args.AddArguments(GetArgvs()); - args.AddArgument("--logtostderr"); args.AddArgument(filter_flag.c_str()); args.AddArgument(internal_flag.c_str()); - last_death_test_message = ""; + DeathTest::set_last_death_test_message(""); CaptureStderr(); // See the comment in NoExecDeathTest::AssumeRole for why the next line @@ -657,10 +977,12 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); set_child_pid(child_pid); set_read_fd(pipe_fd[0]); - set_forked(true); + set_spawned(true); return OVERSEE_TEST; } +#endif // !GTEST_OS_WINDOWS + // Creates a concrete DeathTest-derived class that depends on the // --gtest_death_test_style flag, and sets the pointer pointed to // by the "test" argument to its address. If the test should be @@ -676,28 +998,36 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, ->increment_death_test_count(); if (flag != NULL) { - if (death_test_index > flag->index) { - last_death_test_message = String::Format( + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message(String::Format( "Death test count (%d) somehow exceeded expected maximum (%d)", - death_test_index, flag->index); + death_test_index, flag->index())); return false; } - if (!(flag->file == file && flag->line == line && - flag->index == death_test_index)) { + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { *test = NULL; return true; } } +#if GTEST_OS_WINDOWS + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } +#else if (GTEST_FLAG(death_test_style) == "threadsafe") { *test = new ExecDeathTest(statement, regex, file, line); } else if (GTEST_FLAG(death_test_style) == "fast") { *test = new NoExecDeathTest(statement, regex); - } else { - last_death_test_message = String::Format( + } +#endif // GTEST_OS_WINDOWS + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message(String::Format( "Unknown death test style \"%s\" encountered", - GTEST_FLAG(death_test_style).c_str()); + GTEST_FLAG(death_test_style).c_str())); return false; } @@ -711,7 +1041,7 @@ static void SplitString(const ::std::string& str, char delimiter, ::std::vector< ::std::string>* dest) { ::std::vector< ::std::string> parsed; ::std::string::size_type pos = 0; - while (true) { + while (::testing::internal::AlwaysTrue()) { const ::std::string::size_type colon = str.find(delimiter, pos); if (colon == ::std::string::npos) { parsed.push_back(str.substr(pos)); @@ -724,25 +1054,71 @@ static void SplitString(const ::std::string& str, char delimiter, dest->swap(parsed); } -// Attempts to parse a string into a positive integer. Returns true -// if that is possible. GTEST_HAS_DEATH_TEST implies that we have -// ::std::string, so we can use it here. -static bool ParsePositiveInt(const ::std::string& str, int* number) { - // Fail fast if the given string does not begin with a digit; - // this bypasses strtol's "optional leading whitespace and plus - // or minus sign" semantics, which are undesirable here. - if (str.empty() || !isdigit(str[0])) { - return false; +#if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort(String::Format("Unable to open parent process %u", + parent_process_id)); } - char* endptr; - const long parsed = strtol(str.c_str(), &endptr, 10); // NOLINT - if (*endptr == '\0' && parsed <= INT_MAX) { - *number = static_cast<int>(parsed); - return true; - } else { - return false; + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast<HANDLE>(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the pipe handle %Iu from the parent process %u", + write_handle_as_size_t, parent_process_id)); } + + const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the event handle %Iu from the parent process %u", + event_handle_as_size_t, parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort(String::Format( + "Unable to convert pipe handle %Iu to a file descriptor", + write_handle_as_size_t)); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; } +#endif // GTEST_OS_WINDOWS // Returns a newly created InternalRunDeathTestFlag object with fields // initialized from the GTEST_FLAG(internal_run_death_test) flag if @@ -750,22 +1126,43 @@ static bool ParsePositiveInt(const ::std::string& str, int* number) { InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { if (GTEST_FLAG(internal_run_death_test) == "") return NULL; - InternalRunDeathTestFlag* const internal_run_death_test_flag = - new InternalRunDeathTestFlag; // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we // can use it here. + int line = -1; + int index = -1; ::std::vector< ::std::string> fields; - SplitString(GTEST_FLAG(internal_run_death_test).c_str(), ':', &fields); + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +#if GTEST_OS_WINDOWS + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +#else if (fields.size() != 4 - || !ParsePositiveInt(fields[1], &internal_run_death_test_flag->line) - || !ParsePositiveInt(fields[2], &internal_run_death_test_flag->index) - || !ParsePositiveInt(fields[3], - &internal_run_death_test_flag->status_fd)) { - DeathTestAbort("Bad --gtest_internal_run_death_test flag: %s", - GTEST_FLAG(internal_run_death_test).c_str()); + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); } - internal_run_death_test_flag->file = fields[0].c_str(); - return internal_run_death_test_flag; +#endif // GTEST_OS_WINDOWS + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); } } // namespace internal |