diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2010-06-02 22:01:25 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2010-06-02 22:01:25 +0000 |
commit | e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0 (patch) | |
tree | 1656513dd240b9ed4690589b9934d0e5371694fb /utils/unittest/googletest | |
parent | 18f30e6f5e80787808fe1455742452a5210afe07 (diff) |
Merge gtest-1.3.0.
OSX users: make sure that CrashReporter is disabled when running unit tests.
Death tests are enabled now so you'll get a ton of message boxes.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105352 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/unittest/googletest')
20 files changed, 2089 insertions, 468 deletions
diff --git a/utils/unittest/googletest/gtest-death-test.cc b/utils/unittest/googletest/gtest-death-test.cc index 617e3010f2..149b8a6c59 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,33 @@ 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"); +// Suppress MSVC complaints about POSIX functions. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4996) +#endif // _MSC_VER + FILE* parent = fdopen(flag->status_fd(), "w"); +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER 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(); } } @@ -191,8 +229,9 @@ void DeathTestAbort(const char* format, ...) { #define GTEST_DEATH_TEST_CHECK_(expression) \ do { \ if (!(expression)) { \ - DeathTestAbort("CHECK failed: File %s, line %d: %s", \ - __FILE__, __LINE__, #expression); \ + DeathTestAbort(::testing::internal::String::Format(\ + "CHECK failed: File %s, line %d: %s", \ + __FILE__, __LINE__, #expression)); \ } \ } while (0) @@ -205,16 +244,59 @@ 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) +// Returns the message describing the last system error, regardless of the +// platform. +String GetLastSystemErrorMessage() { +#if GTEST_OS_WINDOWS + const DWORD error_num = ::GetLastError(); + + if (error_num == NULL) + return String(""); + + char* message_ptr; + + ::FormatMessageA( + // The caller does not provide a buffer. The function will allocate one. + FORMAT_MESSAGE_ALLOCATE_BUFFER | + // The function must look up an error message in its system error + // message table. + FORMAT_MESSAGE_FROM_SYSTEM | + // Do not expand insert sequences in the message definition. + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, // Message source. Ignored in this call. + error_num, + 0x0, // Use system-default language. + reinterpret_cast<LPSTR>(&message_ptr), + 0, // Buffer size. Ignored in this call. + NULL); // Message arguments. Ignored in this call. + + const String message = message_ptr; + ::LocalFree(message_ptr); + return message; +#else + return errno == 0 ? String("") : String(strerror(errno)); +#endif // GTEST_OS_WINDOWS +} + +// TODO(vladl@google.com): Move the definition of FailFromInternalError +// here. +#if GTEST_OS_WINDOWS +static void FailFromInternalError(HANDLE handle); +#else +static void FailFromInternalError(int fd); +#endif // GTEST_OS_WINDOWS + // Death test constructor. Increments the running death test count // for the current test. DeathTest::DeathTest() { @@ -234,61 +316,393 @@ 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(); } +void DeathTest::set_last_death_test_message(const String& message) { + last_death_test_message_ = message; +} + +String DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +// TODO(vladl@google.com): Merge this class with DeathTest in +// gtest-death-test-internal.h. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* statement, const RE* regex) + : statement_(statement), + regex_(regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS) {} + + 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 spawned) { spawned_ = spawned; } + int status() const { return status_; } + void set_status(int status) { status_ = status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome outcome) { outcome_ = outcome; } + + private: + // 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. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // 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_; +}; + +// TODO(vladl@google.com): Move definition of DeathTestImpl::Passed() here. + +#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 void Abort(AbortReason reason); + 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 read end of the pipe to the child process. + // The child keeps its write end of the pipe in the status_handle_ + // field of its InternalRunDeathTestFlag class. + AutoHandle read_handle_; + // 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. +// TODO(vladl@google.com): Outcome classification logic is common with +// ForkingDeathTes::Wait(). Refactor it into a +// common function. +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(); + + // ReadFile() 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 or + // after the child process has exited. + char flag; + DWORD bytes_read; + GTEST_DEATH_TEST_CHECK_(::ReadFile(read_handle_.Get(), + &flag, + 1, + &bytes_read, + NULL) || + ::GetLastError() == ERROR_BROKEN_PIPE); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_handle_.Get()); // Does not return. + break; + default: + GTEST_LOG_(FATAL, + Message() << "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: " + << GetLastSystemErrorMessage()); + } + read_handle_.Reset(); // Done with reading. + + // 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)); + child_handle_.Reset(); + set_status(static_cast<int>(status)); + return this->status(); +} + +// TODO(vladl@google.com): define a cross-platform way to write to +// status_fd to be used both here and in ForkingDeathTest::Abort(). +// +// Signals that the death test did not die as expected. This is called +// from the child process only. +void WindowsDeathTest::Abort(AbortReason reason) { + const InternalRunDeathTestFlag* const internal_flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + // 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; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4996) +#endif // _MSC_VER + GTEST_DEATH_TEST_CHECK_SYSCALL_(write(internal_flag->status_fd(), + &status_ch, 1)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + + // The write handle will be closed when the child terminates in _exit(). + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// 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. + 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. + read_handle_.Reset(read_handle); + 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)); + 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 DeathTest { +class ForkingDeathTest : public DeathTestImpl { public: ForkingDeathTest(const char* statement, const RE* regex); // All of these virtual functions are inherited from DeathTest. virtual int Wait(); - virtual bool Passed(bool status_ok); virtual void Abort(AbortReason reason); protected: - void set_forked(bool forked) { forked_ = forked; } void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } void set_read_fd(int fd) { read_fd_ = fd; } void set_write_fd(int fd) { write_fd_ = fd; } private: - // The textual content of the code this object is testing. - const char* const statement_; - // The regular expression which test output must match. - 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. - // The exit status of the child process. - int status_; - // How the death test concluded. - DeathTestOutcome outcome_; }; // Constructs a ForkingDeathTest. ForkingDeathTest::ForkingDeathTest(const char* statement, const RE* regex) - : DeathTest(), - statement_(statement), - regex_(regex), - forked_(false), + : DeathTestImpl(statement, regex), child_pid_(-1), read_fd_(-1), - write_fd_(-1), - status_(-1), - outcome_(IN_PROGRESS) { + write_fd_(-1) { } +#endif // GTEST_OS_WINDOWS + +// 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. +// TODO(vladl@google.com): Re-factor the code to merge common parts after +// the reading code is abstracted. +#if GTEST_OS_WINDOWS +static void FailFromInternalError(HANDLE handle) { + Message error; + char buffer[256]; -// 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. + bool read_succeeded = true; + DWORD bytes_read; + do { + // ERROR_BROKEN_PIPE arises when the other end of the pipe has been + // closed. This is a normal condition for us. + bytes_read = 0; + read_succeeded = ::ReadFile(handle, + buffer, + sizeof(buffer) - 1, + &bytes_read, + NULL) || ::GetLastError() == ERROR_BROKEN_PIPE; + buffer[bytes_read] = 0; + error << buffer; + } while (read_succeeded && bytes_read > 0); + + if (read_succeeded) { + GTEST_LOG_(FATAL, error); + } else { + const DWORD last_error = ::GetLastError(); + const String message = GetLastSystemErrorMessage(); + GTEST_LOG_(FATAL, + Message() << "Error while reading death test internal: " + << message << " [" << last_error << "]"); + } +} +#else static void FailFromInternalError(int fd) { Message error; char buffer[256]; @@ -301,21 +715,24 @@ static void FailFromInternalError(int fd) { } } while (num_read == -1 && errno == EINTR); - // TODO(smcafee): Maybe just FAIL the test instead? if (num_read == 0) { GTEST_LOG_(FATAL, error); } else { + const int last_error = errno; + const String message = GetLastSystemErrorMessage(); GTEST_LOG_(FATAL, Message() << "Error while reading death test internal: " - << strerror(errno) << " [" << errno << "]"); + << message << " [" << last_error << "]"); } } +#endif // GTEST_OS_WINDOWS +#if !GTEST_OS_WINDOWS // 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_) + if (!spawned()) return 0; // The read() here blocks until data is available (signifying the @@ -330,14 +747,14 @@ int ForkingDeathTest::Wait() { } 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. @@ -349,28 +766,34 @@ int ForkingDeathTest::Wait() { << ")"); } } else { + const String error_message = GetLastSystemErrorMessage(); GTEST_LOG_(FATAL, Message() << "Read from death test child process failed: " - << strerror(errno)); + << error_message); } GTEST_DEATH_TEST_CHECK_SYSCALL_(close(read_fd_)); - GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_, 0)); - return status_; + int status; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status, 0)); + set_status(status); + return status; } +#endif // !GTEST_OS_WINDOWS // 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,9 +801,9 @@ 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) { |