aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/gtest/gtest-death-test.h2
-rw-r--r--include/gtest/internal/gtest-death-test-internal.h51
-rw-r--r--include/gtest/internal/gtest-port.h30
-rw-r--r--scons/SConscript72
-rw-r--r--src/gtest-death-test.cc742
-rw-r--r--src/gtest-filepath.cc1
-rw-r--r--src/gtest-internal-inl.h80
-rw-r--r--src/gtest-port.cc66
-rw-r--r--src/gtest.cc38
-rw-r--r--test/gtest-death-test_test.cc268
-rw-r--r--test/gtest-port_test.cc38
-rw-r--r--test/gtest_output_test_.cc11
-rw-r--r--test/gtest_output_test_golden_win.txt21
13 files changed, 1219 insertions, 201 deletions
diff --git a/include/gtest/gtest-death-test.h b/include/gtest/gtest-death-test.h
index bb306f28..dcb2b66e 100644
--- a/include/gtest/gtest-death-test.h
+++ b/include/gtest/gtest-death-test.h
@@ -184,6 +184,7 @@ class ExitedWithCode {
const int exit_code_;
};
+#if !GTEST_OS_WINDOWS
// Tests that an exit code describes an exit due to termination by a
// given signal.
class KilledBySignal {
@@ -193,6 +194,7 @@ class KilledBySignal {
private:
const int signum_;
};
+#endif // !GTEST_OS_WINDOWS
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
// The death testing framework causes this to have interesting semantics,
diff --git a/include/gtest/internal/gtest-death-test-internal.h b/include/gtest/internal/gtest-death-test-internal.h
index 815a3b53..ff2e490e 100644
--- a/include/gtest/internal/gtest-death-test-internal.h
+++ b/include/gtest/internal/gtest-death-test-internal.h
@@ -39,6 +39,10 @@
#include <gtest/internal/gtest-internal.h>
+#if GTEST_HAS_DEATH_TEST && GTEST_OS_WINDOWS
+#include <io.h>
+#endif // GTEST_HAS_DEATH_TEST && GTEST_OS_WINDOWS
+
namespace testing {
namespace internal {
@@ -121,7 +125,12 @@ class DeathTest {
// the last death test.
static const char* LastMessage();
+ static void set_last_death_test_message(const String& message);
+
private:
+ // A string containing a description of the outcome of the last death test.
+ static String last_death_test_message_;
+
GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
};
@@ -167,7 +176,7 @@ bool ExitedUnsuccessfully(int exit_status);
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel \
gtest_sentinel(gtest_dt); \
- { statement; } \
+ GTEST_HIDE_UNREACHABLE_CODE_(statement); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
@@ -179,14 +188,42 @@ bool ExitedUnsuccessfully(int exit_status);
// The symbol "fail" here expands to something into which a message
// can be streamed.
-// A struct representing the parsed contents of the
+// A class representing the parsed contents of the
// --gtest_internal_run_death_test flag, as it existed when
// RUN_ALL_TESTS was called.
-struct InternalRunDeathTestFlag {
- String file;
- int line;
- int index;
- int status_fd;
+class InternalRunDeathTestFlag {
+ public:
+ InternalRunDeathTestFlag(const String& file,
+ int line,
+ int index,
+ int status_fd)
+ : file_(file), line_(line), index_(index), status_fd_(status_fd) {}
+
+ ~InternalRunDeathTestFlag() {
+ if (status_fd_ >= 0)
+// Suppress MSVC complaints about POSIX functions.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4996)
+#endif // _MSC_VER
+ close(status_fd_);
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+ }
+
+ String file() const { return file_; }
+ int line() const { return line_; }
+ int index() const { return index_; }
+ int status_fd() const { return status_fd_; }
+
+ private:
+ String file_;
+ int line_;
+ int index_;
+ int status_fd_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
};
// Returns a newly created InternalRunDeathTestFlag object with fields
diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h
index 8f75e9ac..c93ebd8a 100644
--- a/include/gtest/internal/gtest-port.h
+++ b/include/gtest/internal/gtest-port.h
@@ -183,7 +183,7 @@
#define GTEST_OS_SOLARIS 1
#endif // _MSC_VER
-#if GTEST_OS_LINUX
+#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC
// On some platforms, <regex.h> needs someone to define size_t, and
// won't compile otherwise. We can #include it here as we already
@@ -194,8 +194,8 @@
#else
-// We are not on Linux, so <regex.h> may not be available. Use our
-// own simple regex implementation instead.
+// <regex.h> may not be available on this platform. Use our own
+// simple regex implementation instead.
#define GTEST_USES_SIMPLE_RE 1
#endif // GTEST_OS_LINUX
@@ -367,12 +367,19 @@
#endif // GTEST_HAS_CLONE
// Determines whether to support death tests.
-#if GTEST_HAS_STD_STRING && GTEST_HAS_CLONE
+// Google Test does not support death tests for VC 7.1 and earlier for
+// these reasons:
+// 1. std::vector does not build in VC 7.1 when exceptions are disabled.
+// 2. std::string does not build in VC 7.1 when exceptions are disabled
+// (this is covered by GTEST_HAS_STD_STRING guard).
+// 3. abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if GTEST_HAS_STD_STRING && (GTEST_HAS_CLONE || \
+ GTEST_OS_WINDOWS && _MSC_VER >= 1400)
#define GTEST_HAS_DEATH_TEST 1
#include <vector>
-#include <fcntl.h>
-#include <sys/mman.h>
-#endif // GTEST_HAS_STD_STRING && GTEST_HAS_CLONE
+#endif // GTEST_HAS_STD_STRING && (GTEST_HAS_CLONE ||
+ // GTEST_OS_WINDOWS && _MSC_VER >= 1400)
// Determines whether to support value-parameterized tests.
@@ -595,14 +602,17 @@ inline void FlushInfoLog() { fflush(NULL); }
// CaptureStderr - starts capturing stderr.
// GetCapturedStderr - stops capturing stderr and returns the captured string.
+#if GTEST_HAS_STD_STRING
+void CaptureStderr();
+::std::string GetCapturedStderr();
+#endif // GTEST_HAS_STD_STRING
+
#if GTEST_HAS_DEATH_TEST
// A copy of all command line arguments. Set by InitGoogleTest().
extern ::std::vector<String> g_argvs;
-void CaptureStderr();
// GTEST_HAS_DEATH_TEST implies we have ::std::string.
-::std::string GetCapturedStderr();
const ::std::vector<String>& GetArgvs();
#endif // GTEST_HAS_DEATH_TEST
@@ -692,7 +702,7 @@ struct is_pointer<T*> : public true_type {};
#if GTEST_OS_WINDOWS
typedef __int64 BiggestInt;
#else
-typedef long long BiggestInt; // NOLINT
+typedef long long BiggestInt; // NOLINT
#endif // GTEST_OS_WINDOWS
// The maximum number a BiggestInt can represent. This definition
diff --git a/scons/SConscript b/scons/SConscript
index 17f9dcdc..b7dafc76 100644
--- a/scons/SConscript
+++ b/scons/SConscript
@@ -102,38 +102,65 @@ env = env.Clone()
env.Prepend(CPPPATH = ['..',
'../include'])
-# Sources shared by base library and library that includes main.
-gtest_sources = ['../src/gtest-all.cc']
+# Sources used by base library and library that includes main.
+gtest_source = '../src/gtest-all.cc'
+gtest_main_source = '../src/gtest_main.cc'
# gtest.lib to be used by most apps (if you have your own main
# function)
gtest = env.StaticLibrary(target='gtest',
- source=gtest_sources)
+ source=[gtest_source])
# gtest_main.lib can be used if you just want a basic main function;
# it is also used by the tests for Google Test itself.
gtest_main = env.StaticLibrary(target='gtest_main',
- source=gtest_sources + ['../src/gtest_main.cc'])
+ source=[gtest_source, gtest_main_source])
+
+env_with_exceptions = env.Clone()
+platform = env_with_exceptions['PLATFORM']
+if platform == 'win32':
+ env_with_exceptions.Append(CCFLAGS = ['/EHsc'])
+ env_with_exceptions.Append(CPPDEFINES = '_HAS_EXCEPTIONS=1')
+
+gtest_ex_obj = env_with_exceptions.Object(target='gtest_ex',
+ source=gtest_source)
+gtest_main_ex_obj = env_with_exceptions.Object(target='gtest_main_ex',
+ source=gtest_main_source)
+
+gtest_ex_main = env_with_exceptions.StaticLibrary(
+ target='gtest_ex_main',
+ source=gtest_ex_obj + gtest_main_ex_obj)
# Install the libraries if needed.
if 'LIB_OUTPUT' in env.Dictionary():
- env.Install('$LIB_OUTPUT', source=[gtest, gtest_main])
+ env.Install('$LIB_OUTPUT', source=[gtest, gtest_main, gtest_ex_main])
-def GtestBinary(env, target, dir_prefix, gtest_lib, additional_sources=None):
- """Helper to create gtest binaries: tests, samples, etc.
+def ConstructSourceList(target, dir_prefix, additional_sources=None):
+ """Helper to create source file list for gtest binaries.
Args:
- env: The SCons construction environment to use to build.
- target: The basename of the target's main source file, also used as target
- name.
+ target: The basename of the target's main source file.
dir_prefix: The path to prefix the main source file.
gtest_lib: The gtest lib to use.
+ additional_sources: A list of additional source files in the target.
"""
source = [env.File('%s.cc' % target, env.Dir(dir_prefix))]
if additional_sources:
source += additional_sources
- unit_test = env.Program(target=target, source=source, LIBS=[gtest_lib])
+ return source
+
+def GtestBinary(env, target, gtest_lib, sources):
+ """Helper to create gtest binaries: tests, samples, etc.
+
+ Args:
+ env: The SCons construction environment to use to build.
+ target: The basename of the target's main source file, also used as target
+ name.
+ gtest_lib: The gtest lib to use.
+ sources: A list of source files in the target.
+ """
+ unit_test = env.Program(target=target, source=sources, LIBS=[gtest_lib])
if 'EXE_OUTPUT' in env.Dictionary():
env.Install('$EXE_OUTPUT', source=[unit_test])
@@ -144,8 +171,13 @@ def GtestUnitTest(env, target, gtest_lib, additional_sources=None):
env: The SCons construction environment to use to build.
target: The basename of the target unit test .cc file.
gtest_lib: The gtest lib to use.
+ additional_sources: A list of additional source files in the target.
"""
- GtestBinary(env, target, "../test", gtest_lib, additional_sources)
+ GtestBinary(env,
+ target,
+ gtest_lib,
+ ConstructSourceList(target, "../test",
+ additional_sources=additional_sources))
GtestUnitTest(env, 'gtest-filepath_test', gtest_main)
GtestUnitTest(env, 'gtest-message_test', gtest_main)
@@ -168,6 +200,15 @@ GtestUnitTest(env, 'gtest_output_test_', gtest)
GtestUnitTest(env, 'gtest_color_test_', gtest)
GtestUnitTest(env, 'gtest-linked_ptr_test', gtest_main)
GtestUnitTest(env, 'gtest-port_test', gtest_main)
+GtestUnitTest(env, 'gtest-death-test_test', gtest_main)
+
+gtest_unittest_ex_obj = env_with_exceptions.Object(
+ target='gtest_unittest_ex',
+ source='../test/gtest_unittest.cc')
+GtestBinary(env_with_exceptions,
+ 'gtest_ex_unittest',
+ gtest_ex_main,
+ gtest_unittest_ex_obj)
# TODO(wan@google.com) Add these unit tests:
# - gtest_break_on_failure_unittest_
@@ -195,8 +236,13 @@ def GtestSample(env, target, gtest_lib, additional_sources=None):
env: The SCons construction environment to use to build.
target: The basename of the target unit test .cc file.
gtest_lib: The gtest lib to use.
+ additional_sources: A list of additional source files in the target.
"""
- GtestBinary(env, target, "../samples", gtest_lib, additional_sources)
+ GtestBinary(env,
+ target,
+ gtest_lib,
+ ConstructSourceList(target, "../samples",
+ additional_sources=additional_sources))
# Use the GTEST_BUILD_SAMPLES build variable to control building of samples.
# In your SConstruct file, add
diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc
index 7bb36490..71b749b9 100644
--- a/src/gtest-death-test.cc
+++ b/src/gtest-death-test.cc
@@ -27,7 +27,7 @@
// (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@losev.com (Vlad Losev)
//
// This file implements death tests.
@@ -36,8 +36,16 @@
#if GTEST_HAS_DEATH_TEST
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
+
+#if GTEST_OS_WINDOWS
+#include <windows.h>
+#else
+#include <sys/mman.h>
+#endif // GTEST_OS_WINDOWS
+
#endif // GTEST_HAS_DEATH_TEST
#include <gtest/gtest-message.h>
@@ -98,9 +106,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) {
}
@@ -109,6 +122,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 {
@@ -118,6 +132,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)) {
@@ -128,6 +145,7 @@ static String ExitSummary(int exit_code) {
m << " (core dumped)";
}
#endif
+#endif // GTEST_OS_WINDOWS
return m.GetString();
}
@@ -137,6 +155,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
@@ -151,10 +170,7 @@ static String DeathTestThreadWarning(size_t thread_count) {
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';
@@ -170,29 +186,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();
}
}
@@ -202,8 +222,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)
@@ -216,16 +237,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() {
@@ -245,61 +309,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];
@@ -312,21 +708,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
@@ -341,14 +740,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.
@@ -360,28 +759,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
@@ -389,9 +794,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) {
+ if (!spawned())
return false;
#if GTEST_HAS_GLOBAL_STRING
@@ -403,8 +808,8 @@ bool ForkingDeathTest::Passed(bool status_ok) {
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;
@@ -415,16 +820,16 @@ bool ForkingDeathTest::Passed(bool status_ok) {
break;
case DIED:
if (status_ok) {
- if (RE::PartialMatch(error_message, *regex_)) {
+ if (RE::PartialMatch(error_message, *regex())) {
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:
@@ -433,13 +838,14 @@ bool ForkingDeathTest::Passed(bool status_ok) {
"DeathTest::Passed somehow called before conclusion of test");
}
- last_death_test_message = buffer.GetString();
+ DeathTest::set_last_death_test_message(buffer.GetString());
return success;
}
+#if !GTEST_OS_WINDOWS
// 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
+// Writes a status byte to the child's status file descriptor, then
// calls _exit(1).
void ForkingDeathTest::Abort(AbortReason reason) {
// The parent process considers the death test to be a failure if
@@ -472,7 +878,7 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
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
@@ -497,7 +903,7 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
} 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;
}
}
@@ -524,9 +930,9 @@ 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);
}
@@ -571,8 +977,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,
+ GetLastSystemErrorMessage().c_str()));
return EXIT_FAILURE;
}
@@ -582,8 +989,10 @@ static int ExecDeathTestChildMain(void* child_arg) {
// 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));
+ DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s",
+ args->argv[0],
+ original_dir,
+ GetLastSystemErrorMessage().c_str()));
return EXIT_FAILURE;
}
@@ -643,7 +1052,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->status_fd());
return EXECUTE_TEST;
}
@@ -658,16 +1067,15 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
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
@@ -678,10 +1086,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
@@ -697,28 +1107,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;
}
@@ -728,6 +1146,8 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
// Splits a given string on a given delimiter, populating a given
// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
// ::std::string, so we can use it here.
+// TODO(vladl@google.com): Get rid of std::vector to be able to build on
+// Visual C++ 7.1 with exceptions disabled.
static void SplitString(const ::std::string& str, char delimiter,
::std::vector< ::std::string>* dest) {
::std::vector< ::std::string> parsed;
@@ -745,25 +1165,72 @@ 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 status_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 status_handle =
+ reinterpret_cast<HANDLE>(status_handle_as_size_t);
+ HANDLE dup_status_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(), status_handle,
+ ::GetCurrentProcess(), &dup_status_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",
+ status_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 status_fd =
+ ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_status_handle),
+ O_APPEND | O_TEXT);
+ if (status_fd == -1) {
+ DeathTestAbort(String::Format(
+ "Unable to convert pipe handle %Iu to a file descriptor",
+ status_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 status_fd;
}
+#endif // GTEST_OS_WINDOWS
// Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
@@ -771,22 +1238,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 status_fd = -1;
+
+#if GTEST_OS_WINDOWS
+ unsigned int parent_process_id = 0;
+ size_t status_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], &status_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()));
+ }
+ status_fd = GetStatusFileDescriptor(parent_process_id,
+ status_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());
- }
- internal_run_death_test_flag->file = fields[0].c_str();
- return internal_run_death_test_flag;
+ || !ParseNaturalNumber(fields[1], &line)
+ || !ParseNaturalNumber(fields[2], &index)
+ || !ParseNaturalNumber(fields[3], &status_fd)) {
+ DeathTestAbort(String::Format(
+ "Bad --gtest_internal_run_death_test flag: %s",
+ GTEST_FLAG(internal_run_death_test).c_str()));
+ }
+#endif // GTEST_OS_WINDOWS
+ return new InternalRunDeathTestFlag(fields[0], line, index, status_fd);
}
} // namespace internal
diff --git a/src/gtest-filepath.cc b/src/gtest-filepath.cc
index e5908012..32fd3bcb 100644
--- a/src/gtest-filepath.cc
+++ b/src/gtest-filepath.cc
@@ -48,6 +48,7 @@
#include <limits.h>
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
+#include <climits> // Some Linux distributions define PATH_MAX here.
#endif // _WIN32_WCE or _WIN32
#if GTEST_OS_WINDOWS
diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h
index b1a5dbb1..eadcf95e 100644
--- a/src/gtest-internal-inl.h
+++ b/src/gtest-internal-inl.h
@@ -45,17 +45,20 @@
#error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_
+#include <errno.h>
#include <stddef.h>
-
-#include <gtest/internal/gtest-port.h>
+#include <stdlib.h> // For strtoll/_strtoul64.
#if GTEST_OS_WINDOWS
-#include <windows.h> // NOLINT
+#include <windows.h> // For DWORD.
#endif // GTEST_OS_WINDOWS
+#include <gtest/internal/gtest-port.h>
#include <gtest/gtest.h>
#include <gtest/gtest-spi.h>
+#include <string>
+
namespace testing {
// Declares the flags.
@@ -1313,6 +1316,77 @@ bool MatchRegexAnywhere(const char* regex, const char* str);
void ParseGoogleTestFlagsOnly(int* argc, char** argv);
void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+String GetLastSystemErrorMessage();
+
+#if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+ AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+ explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+ ~AutoHandle() { Reset(); }
+
+ HANDLE Get() const { return handle_; }
+ void Reset() { Reset(INVALID_HANDLE_VALUE); }
+ void Reset(HANDLE handle) {
+ if (handle != handle_) {
+ if (handle_ != INVALID_HANDLE_VALUE)
+ ::CloseHandle(handle_);
+ handle_ = handle;
+ }
+ }
+
+ private:
+ HANDLE handle_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+#endif // GTEST_OS_WINDOWS
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter. Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+ // Fail fast if the given string does not begin with a digit;
+ // this bypasses strtoXXX's "optional leading whitespace and plus
+ // or minus sign" semantics, which are undesirable here.
+ if (str.empty() || !isdigit(str[0])) {
+ return false;
+ }
+ errno = 0;
+
+ char* end;
+ // BiggestConvertible is the largest integer type that system-provided
+ // string-to-number conversion routines can return.
+#if GTEST_OS_WINDOWS
+ typedef unsigned __int64 BiggestConvertible;
+ const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+#else
+ typedef unsigned long long BiggestConvertible; // NOLINT
+ const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+#endif // GTEST_OS_WINDOWS
+ const bool parse_success = *end == '\0' && errno == 0;
+
+ // TODO(vladl@google.com): Convert this to compile time assertion when it is
+ // available.
+ GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+ const Integer result = static_cast<Integer>(parsed);
+ if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+ *number = result;
+ return true;
+ }
+ return false;
+}
+#endif // GTEST_HAS_DEATH_TEST
+
} // namespace internal
} // namespace testing
diff --git a/src/gtest-port.cc b/src/gtest-port.cc
index 59a22308..aacb5e72 100644
--- a/src/gtest-port.cc
+++ b/src/gtest-port.cc
@@ -35,9 +35,9 @@
#include <stdlib.h>
#include <stdio.h>
-#if GTEST_HAS_DEATH_TEST
-#include <regex.h>
-#endif // GTEST_HAS_DEATH_TEST
+#if !GTEST_OS_WINDOWS
+#include <unistd.h>
+#endif // GTEST_OS_WINDOWS
#if GTEST_USES_SIMPLE_RE
#include <string.h>
@@ -63,6 +63,13 @@
namespace testing {
namespace internal {
+#if GTEST_OS_WINDOWS
+// Microsoft does not provide a definition of STDERR_FILENO.
+const int kStdErrFileno = 2;
+#else
+const int kStdErrFileno = STDERR_FILENO;
+#endif // GTEST_OS_WINDOWS
+
#if GTEST_USES_POSIX_RE
// Implements RE. Currently only needed for death tests.
@@ -105,7 +112,13 @@ void RE::Init(const char* regex) {
// previous expression returns false. Otherwise partial_regex_ may
// not be properly initialized can may cause trouble when it's
// freed.
- is_valid_ = (regcomp(&partial_regex_, regex, REG_EXTENDED) == 0) && is_valid_;
+ //
+ // Some implementation of POSIX regex (e.g. on at least some
+ // versions of Cygwin) doesn't accept the empty string as a valid
+ // regex. We change it to an equivalent form "()" to be safe.
+ const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+ is_valid_ = (regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0)
+ && is_valid_;
EXPECT_TRUE(is_valid_)
<< "Regular expression \"" << regex
<< "\" is not a valid POSIX Extended regular expression.";
@@ -379,11 +392,19 @@ void GTestLog(GTestLogSeverity severity, const char* file,
severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
fprintf(stderr, "\n%s %s:%d: %s\n", marker, file, line, msg);
if (severity == GTEST_FATAL) {
+ fflush(NULL); // abort() is not guaranteed to flush open file streams.
abort();
}
}
-#if GTEST_HAS_DEATH_TEST
+#if GTEST_HAS_STD_STRING
+
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4996)
+#endif // _MSC_VER
// Defines the stderr capturer.
@@ -391,16 +412,26 @@ class CapturedStderr {
public:
// The ctor redirects stderr to a temporary file.
CapturedStderr() {
- uncaptured_fd_ = dup(STDERR_FILENO);
+ uncaptured_fd_ = dup(kStdErrFileno);
+
+#if GTEST_OS_WINDOWS
+ char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
+ char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
+ ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+ ::GetTempFileNameA(temp_dir_path, "gtest_redir", 0, temp_file_path);
+ const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+ filename_ = temp_file_path;
+#else
// There's no guarantee that a test has write access to the
// current directory, so we create the temporary file in the /tmp
// directory instead.
char name_template[] = "/tmp/captured_stderr.XXXXXX";
const int captured_fd = mkstemp(name_template);
filename_ = name_template;
+#endif // GTEST_OS_WINDOWS
fflush(NULL);
- dup2(captured_fd, STDERR_FILENO);
+ dup2(captured_fd, kStdErrFileno);
close(captured_fd);
}
@@ -412,7 +443,7 @@ class CapturedStderr {
void StopCapture() {
// Restores the original stream.
fflush(NULL);
- dup2(uncaptured_fd_, STDERR_FILENO);
+ dup2(uncaptured_fd_, kStdErrFileno);
close(uncaptured_fd_);
uncaptured_fd_ = -1;
}
@@ -427,6 +458,10 @@ class CapturedStderr {
::std::string filename_;
};
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
static CapturedStderr* g_captured_stderr = NULL;
// Returns the size (in bytes) of a file.
@@ -436,8 +471,6 @@ static size_t GetFileSize(FILE * file) {
}
// Reads the entire content of a file as a string.
-// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
-// use it here.
static ::std::string ReadEntireFile(FILE * file) {
const size_t file_size = GetFileSize(file);
char* const buffer = new char[file_size];
@@ -473,9 +506,18 @@ void CaptureStderr() {
// use it here.
::std::string GetCapturedStderr() {
g_captured_stderr->StopCapture();
+
+// Disables Microsoft deprecation warning for fopen and fclose.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4996)
+#endif // _MSC_VER
FILE* const file = fopen(g_captured_stderr->filename().c_str(), "r");
const ::std::string content = ReadEntireFile(file);
fclose(file);
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
delete g_captured_stderr;
g_captured_stderr = NULL;
@@ -483,6 +525,10 @@ void CaptureStderr() {
return content;
}
+#endif // GTEST_HAS_STD_STRING
+
+#if GTEST_HAS_DEATH_TEST
+
// A copy of all command line arguments. Set by InitGoogleTest().
::std::vector<String> g_argvs;
diff --git a/src/gtest.cc b/src/gtest.cc
index e4f9d0f3..f86a2a35 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -3300,17 +3300,43 @@ void UnitTest::RecordPropertyForCurrentTest(const char* key,
int UnitTest::Run() {
#if GTEST_OS_WINDOWS
+ const bool in_death_test_child_process =
+ internal::GTEST_FLAG(internal_run_death_test).GetLength() > 0;
+
+ // Either the user wants Google Test to catch exceptions thrown by the
+ // tests or this is executing in the context of death test child
+ // process. In either case the user does not want to see pop-up dialogs
+ // about crashes - they are expected..
+ if (GTEST_FLAG(catch_exceptions) || in_death_test_child_process) {
#if !defined(_WIN32_WCE)
- // SetErrorMode doesn't exist on CE.
- if (GTEST_FLAG(catch_exceptions)) {
- // The user wants Google Test to catch exceptions thrown by the tests.
-
- // This lets fatal errors be handled by us, instead of causing pop-ups.
+ // SetErrorMode doesn't exist on CE.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
- }
#endif // _WIN32_WCE
+ // Death test children can be terminated with _abort(). On Windows,
+ // _abort() can show a dialog with a warning message. This forces the
+ // abort message to go to stderr instead.
+ _set_error_mode(_OUT_TO_STDERR);
+
+ // In the debug version, Visual Studio pops up a separate dialog
+ // offering a choice to debug the aborted program. We need to suppress
+ // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+ // executed. Google Test will notify the user of any unexpected
+ // failure via stderr.
+#if _MSC_VER >= 1400
+ // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+ // Users of prior VC versions shall suffer the agony and pain of
+ // clicking through the countless debug dialogs.
+ // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+ // debug mode when compiled with VC 7.1 or lower.
+ if (!GTEST_FLAG(break_on_failure))
+ _set_abort_behavior(
+ 0x0, // Clear the following flags:
+ _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
+#endif // _MSC_VER >= 1400
+ }
+
__try {
return impl_->RunAllTests();
} __except(internal::UnitTestOptions::GTestShouldProcessSEH(
diff --git a/test/gtest-death-test_test.cc b/test/gtest-death-test_test.cc
index 6d8a3f89..4151ef0e 100644
--- a/test/gtest-death-test_test.cc
+++ b/test/gtest-death-test_test.cc
@@ -36,8 +36,16 @@
#if GTEST_HAS_DEATH_TEST
-#include <stdio.h>
+#if GTEST_OS_WINDOWS
+#include <direct.h> // For chdir().
+#else
#include <unistd.h>
+#include <limits> // For std::numeric_limits.
+#endif // GTEST_OS_WINDOWS
+
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
#include <gtest/gtest-spi.h>
// Indicates that this translation unit is part of Google Test's
@@ -49,8 +57,13 @@
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
+using testing::Message;
+
using testing::internal::DeathTest;
using testing::internal::DeathTestFactory;
+using testing::internal::GetLastSystemErrorMessage;
+using testing::internal::ParseNaturalNumber;
+using testing::internal::String;
namespace testing {
namespace internal {
@@ -88,6 +101,7 @@ class TestForDeathTest : public testing::Test {
// A static member function that's expected to die.
static void StaticMemberFunction() {
fprintf(stderr, "%s", "death inside StaticMemberFunction().");
+ fflush(stderr);
// We call _exit() instead of exit(), as the former is a direct
// system call and thus safer in the presence of threads. exit()
// will invoke user-defined exit-hooks, which may do dangerous
@@ -99,6 +113,7 @@ class TestForDeathTest : public testing::Test {
void MemberFunction() {
if (should_die_) {
fprintf(stderr, "%s", "death inside MemberFunction().");
+ fflush(stderr);
_exit(1);
}
}
@@ -165,6 +180,21 @@ int DieInDebugElse12(int* sideeffect) {
return 12;
}
+#if GTEST_OS_WINDOWS
+
+// Tests the ExitedWithCode predicate.
+TEST(ExitStatusPredicateTest, ExitedWithCode) {
+ // On Windows, the process's exit code is the same as its exit status,
+ // so the predicate just compares the its input with its parameter.
+ EXPECT_TRUE(testing::ExitedWithCode(0)(0));
+ EXPECT_TRUE(testing::ExitedWithCode(1)(1));
+ EXPECT_TRUE(testing::ExitedWithCode(42)(42));
+ EXPECT_FALSE(testing::ExitedWithCode(0)(1));
+ EXPECT_FALSE(testing::ExitedWithCode(1)(0));
+}
+
+#else
+
// Returns the exit status of a process that calls _exit(2) with a
// given exit code. This is a helper function for the
// ExitStatusPredicateTest test suite.
@@ -222,6 +252,8 @@ TEST(ExitStatusPredicateTest, KilledBySignal) {
EXPECT_FALSE(pred_kill(status_segv));
}
+#endif // GTEST_OS_WINDOWS
+
// Tests that the death test macros expand to code which may or may not
// be followed by operator<<, and that in either case the complete text
// comprises only a single C++ statement.
@@ -248,6 +280,7 @@ TEST_F(TestForDeathTest, SingleStatement) {
void DieWithEmbeddedNul() {
fprintf(stderr, "Hello%cworld.\n", '\0');
+ fflush(stderr);
_exit(1);
}
@@ -263,6 +296,13 @@ TEST_F(TestForDeathTest, DISABLED_EmbeddedNulInMessage) {
// Tests that death test macros expand to code which interacts well with switch
// statements.
TEST_F(TestForDeathTest, SwitchStatement) {
+// Microsoft compiler usually complains about switch statements without
+// case labels. We suppress that warning for this test.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4065)
+#endif // _MSC_VER
+
switch (0)
default:
ASSERT_DEATH(_exit(1), "") << "exit in default switch handler";
@@ -270,6 +310,10 @@ TEST_F(TestForDeathTest, SwitchStatement) {
switch (0)
case 0:
EXPECT_DEATH(_exit(1), "") << "exit in switch case";
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
}
// Tests that a static member function can be used in a "fast" style
@@ -287,15 +331,23 @@ TEST_F(TestForDeathTest, MemberFunctionFastStyle) {
EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
}
+void ChangeToRootDir() {
+#if GTEST_OS_WINDOWS
+ _chdir("\\");
+#else
+ chdir("/");
+#endif // GTEST_OS_WINDOWS
+}
+
// Tests that death tests work even if the current directory has been
// changed.
TEST_F(TestForDeathTest, FastDeathTestInChangedDir) {
testing::GTEST_FLAG(death_test_style) = "fast";
- chdir("/");
+ ChangeToRootDir();
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
- chdir("/");
+ ChangeToRootDir();
ASSERT_DEATH(_exit(1), "");
}
@@ -322,10 +374,10 @@ TEST_F(TestForDeathTest, ThreadsafeDeathTestInLoop) {
TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) {
testing::GTEST_FLAG(death_test_style) = "threadsafe";
- chdir("/");
+ ChangeToRootDir();
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
- chdir("/");
+ ChangeToRootDir();
ASSERT_DEATH(_exit(1), "");
}
@@ -346,6 +398,8 @@ void SetPthreadFlag() {
} // namespace
+#if !GTEST_OS_WINDOWS
+
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
if (!testing::GTEST_FLAG(death_test_use_fork)) {
testing::GTEST_FLAG(death_test_style) = "threadsafe";
@@ -356,6 +410,8 @@ TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
}
}
+#endif // !GTEST_OS_WINDOWS
+
// Tests that a method of another class can be used in a death test.
TEST_F(TestForDeathTest, MethodOfAnotherClass) {
const MayDie x(true);
@@ -537,6 +593,30 @@ void ExpectDebugDeathHelper(bool* aborted) {
*aborted = false;
}
+#if GTEST_OS_WINDOWS
+TEST(TestForPopUps, DoesNotShowPopUpOnAbort) {
+ printf("This test should be considered failing if it shows "
+ "any pop-up dialogs.\n");
+ fflush(stdout);
+
+ EXPECT_DEATH({
+ testing::GTEST_FLAG(catch_exceptions) = false;
+ abort();
+ }, "");
+}
+
+TEST(TestForPopUps, DoesNotShowPopUpOnThrow) {
+ printf("This test should be considered failing if it shows "
+ "any pop-up dialogs.\n");
+ fflush(stdout);
+
+ EXPECT_DEATH({
+ testing::GTEST_FLAG(catch_exceptions) = false;
+ throw 1;
+ }, "");
+}
+#endif // GTEST_OS_WINDOWS
+
// Tests that EXPECT_DEBUG_DEATH in debug mode does not abort
// the function.
TEST_F(TestForDeathTest, ExpectDebugDeathDoesNotAbort) {
@@ -566,18 +646,38 @@ TEST_F(TestForDeathTest, AssertDebugDeathAborts) {
static void TestExitMacros() {
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
- EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
- ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar";
+
+#if GTEST_OS_WINDOWS
+ EXPECT_EXIT({
+ testing::GTEST_FLAG(catch_exceptions) = false;
+ *static_cast<int*>(NULL) = 1;
+ }, testing::ExitedWithCode(0xC0000005), "") << "foo";
EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
- << "This failure is expected.";
+ EXPECT_EXIT({
+ testing::GTEST_FLAG(catch_exceptions) = false;
+ *static_cast<int*>(NULL) = 1;
+ }, testing::ExitedWithCode(0), "") << "This failure is expected.";
}, "This failure is expected.");
+ // Of all signals effects on the process exit code, only those of SIGABRT
+ // are documented on Windows.
+ // See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx.
+ EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "");
+#else
+ EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
+ ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar";
+
EXPECT_FATAL_FAILURE({ // NOLINT
ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "")
<< "This failure is expected, too.";
}, "This failure is expected, too.");
+#endif // GTEST_OS_WINDOWS
+
+ EXPECT_NONFATAL_FAILURE({ // NOLINT
+ EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
+ << "This failure is expected.";
+ }, "This failure is expected.");
}
TEST_F(TestForDeathTest, ExitMacros) {
@@ -873,6 +973,156 @@ TEST(StreamingAssertionsDeathTest, DeathTest) {
}, "expected failure");
}
+// Tests that GetLastSystemErrorMessage returns an empty string when the
+// last error is 0 and non-empty string when it is non-zero.
+TEST(GetLastSystemErrorMessageTest, GetLastSystemErrorMessageWorks) {
+#if GTEST_OS_WINDOWS
+ ::SetLastError(ERROR_FILE_NOT_FOUND);
+ EXPECT_STRNE("", GetLastSystemErrorMessage().c_str());
+ ::SetLastError(0);
+ EXPECT_STREQ("", GetLastSystemErrorMessage().c_str());
+#else
+ errno = ENOENT;
+ EXPECT_STRNE("", GetLastSystemErrorMessage().c_str());
+ errno = 0;
+ EXPECT_STREQ("", GetLastSystemErrorMessage().c_str());
+#endif
+}
+
+#if GTEST_OS_WINDOWS
+TEST(AutoHandleTest, AutoHandleWorks) {
+ HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+
+ // Tests that the AutoHandle is correctly initialized with a handle.
+ testing::internal::AutoHandle auto_handle(handle);
+ EXPECT_EQ(handle, auto_handle.Get());
+
+ // Tests that Reset assigns INVALID_HANDLE_VALUE.
+ // Note that this cannot verify whether the original handle is closed.
+ auto_handle.Reset();
+ EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle.Get());
+
+ // Tests that Reset assigns the new handle.
+ // Note that this cannot verify whether the original handle is closed.
+ handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+ auto_handle.Reset(handle);
+ EXPECT_EQ(handle, auto_handle.Get());
+
+ // Tests that AutoHandle contains INVALID_HANDLE_VALUE by default.
+ testing::internal::AutoHandle auto_handle2;
+ EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get());
+}
+#endif // GTEST_OS_WINDOWS
+
+#if GTEST_OS_WINDOWS
+typedef unsigned __int64 BiggestParsable;
+typedef signed __int64 BiggestSignedParsable;
+const BiggestParsable kBiggestParsableMax = ULLONG_MAX;
+const BiggestParsable kBiggestSignedParsableMax = LLONG_MAX;
+#else
+typedef unsigned long long BiggestParsable;
+typedef signed long long BiggestSignedParsable;
+const BiggestParsable kBiggestParsableMax =
+ ::std::numeric_limits<BiggestParsable>::max();
+const BiggestSignedParsable kBiggestSignedParsableMax =
+ ::std::numeric_limits<BiggestSignedParsable>::max();
+#endif // GTEST_OS_WINDOWS
+
+TEST(ParseNaturalNumberTest, RejectsInvalidFormat) {
+ BiggestParsable result = 0;
+
+ // Rejects non-numbers.
+ EXPECT_FALSE(ParseNaturalNumber(String("non-number string"), &result));
+
+ // Rejects numbers with whitespace prefix.
+ EXPECT_FALSE(ParseNaturalNumber(String(" 123"), &result));
+
+ // Rejects negative numbers.
+ EXPECT_FALSE(ParseNaturalNumber(String("-123"), &result));
+
+ // Rejects numbers starting with a plus sign.
+ EXPECT_FALSE(ParseNaturalNumber(String("+123"), &result));
+ errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, RejectsOverflownNumbers) {
+ BiggestParsable result = 0;
+
+ EXPECT_FALSE(ParseNaturalNumber(String("99999999999999999999999"), &result));
+
+ signed char char_result = 0;
+ EXPECT_FALSE(ParseNaturalNumber(String("200"), &char_result));
+ errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, AcceptsValidNumbers) {
+ BiggestParsable result = 0;
+
+ result = 0;
+ ASSERT_TRUE(ParseNaturalNumber(String("123"), &result));
+ EXPECT_EQ(123, result);
+
+ // Check 0 as an edge case.
+ result = 1;
+ ASSERT_TRUE(ParseNaturalNumber(String("0"), &result));
+ EXPECT_EQ(0, result);
+
+ result = 1;
+ ASSERT_TRUE(ParseNaturalNumber(String("00000"), &result));
+ EXPECT_EQ(0, result);
+}
+
+TEST(ParseNaturalNumberTest, AcceptsTypeLimits) {
+ Message msg;
+ msg << kBiggestParsableMax;
+
+ BiggestParsable result = 0;
+ EXPECT_TRUE(ParseNaturalNumber(msg.GetString(), &result));
+ EXPECT_EQ(kBiggestParsableMax, result);
+
+ Message msg2;
+ msg2 << kBiggestSignedParsableMax;
+
+ BiggestSignedParsable signed_result = 0;
+ EXPECT_TRUE(ParseNaturalNumber(msg2.GetString(), &signed_result));
+ EXPECT_EQ(kBiggestSignedParsableMax, signed_result);
+
+ Message msg3;
+ msg3 << INT_MAX;
+
+ int int_result = 0;
+ EXPECT_TRUE(ParseNaturalNumber(msg3.GetString(), &int_result));
+ EXPECT_EQ(INT_MAX, int_result);
+
+ Message msg4;
+ msg4 << UINT_MAX;
+
+ unsigned int uint_result = 0;
+ EXPECT_TRUE(ParseNaturalNumber(msg4.GetString(), &uint_result));
+ EXPECT_EQ(UINT_MAX, uint_result);
+}
+
+TEST(ParseNaturalNumberTest, WorksForShorterIntegers) {
+ short short_result = 0;
+ ASSERT_TRUE(ParseNaturalNumber(String("123"), &short_result));
+ EXPECT_EQ(123, short_result);
+
+ signed char char_result = 0;
+ ASSERT_TRUE(ParseNaturalNumber(String("123"), &char_result));
+ EXPECT_EQ(123, char_result);
+}
+
+#if GTEST_OS_WINDOWS
+TEST(EnvironmentTest, HandleFitsIntoSizeT) {
+ // TODO(vladl@google.com): Remove this test after this condition is verified
+ // in a static assertion in gtest-death-test.cc in the function
+ // GetStatusFileDescriptor.
+ ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t));
+}
+#endif // GTEST_OS_WINDOWS
+
#endif // GTEST_HAS_DEATH_TEST
// Tests that a test case whose name ends with "DeathTest" works fine
diff --git a/test/gtest-port_test.cc b/test/gtest-port_test.cc
index 40d36bd1..0bda6f5e 100644
--- a/test/gtest-port_test.cc
+++ b/test/gtest-port_test.cc
@@ -80,13 +80,15 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
const bool a_false_condition = false;
- EXPECT_DEATH(GTEST_CHECK_(a_false_condition) << "Extra info",
+ const char regex[] =
#ifdef _MSC_VER
- "gtest-port_test\\.cc\\([0-9]+\\):"
+ "gtest-port_test\\.cc\\(\\d+\\):"
#else
- "gtest-port_test\\.cc:[0-9]+"
+ "gtest-port_test\\.cc:[0-9]+"
#endif // _MSC_VER
- ".*a_false_condition.*Extra info.*");
+ ".*a_false_condition.*Extra info.*";
+
+ EXPECT_DEATH(GTEST_CHECK_(a_false_condition) << "Extra info", regex);
}
TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
@@ -575,25 +577,25 @@ TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) {
// Tests RE's implicit constructors.
TEST(RETest, ImplicitConstructorWorks) {
- const RE empty = "";
+ const RE empty("");
EXPECT_STREQ("", empty.pattern());
- const RE simple = "hello";
+ const RE simple("hello");
EXPECT_STREQ("hello", simple.pattern());
}
// Tests that RE's constructors reject invalid regular expressions.
TEST(RETest, RejectsInvalidRegex) {
EXPECT_NONFATAL_FAILURE({
- const RE normal = NULL;
+ const RE normal(NULL);
}, "NULL is not a valid simple regular expression");
EXPECT_NONFATAL_FAILURE({
- const RE normal = ".*(\\w+";
+ const RE normal(".*(\\w+");
}, "'(' is unsupported");
EXPECT_NONFATAL_FAILURE({
- const RE invalid = "^?";
+ const RE invalid("^?");
}, "'?' can only follow a repeatable token");
}
@@ -603,10 +605,10 @@ TEST(RETest, FullMatchWorks) {
EXPECT_TRUE(RE::FullMatch("", empty));
EXPECT_FALSE(RE::FullMatch("a", empty));
- const RE re1 = "a";
+ const RE re1("a");
EXPECT_TRUE(RE::FullMatch("a", re1));
- const RE re = "a.*z";
+ const RE re("a.*z");
EXPECT_TRUE(RE::FullMatch("az", re));
EXPECT_TRUE(RE::FullMatch("axyz", re));
EXPECT_FALSE(RE::FullMatch("baz", re));
@@ -615,11 +617,11 @@ TEST(RETest, FullMatchWorks) {
// Tests RE::PartialMatch().
TEST(RETest, PartialMatchWorks) {
- const RE empty = "";
+ const RE empty("");
EXPECT_TRUE(RE::PartialMatch("", empty));
EXPECT_TRUE(RE::PartialMatch("a", empty));
- const RE re = "a.*z";
+ const RE re("a.*z");
EXPECT_TRUE(RE::PartialMatch("az", re));
EXPECT_TRUE(RE::PartialMatch("axyz", re));
EXPECT_TRUE(RE::PartialMatch("baz", re));
@@ -629,5 +631,15 @@ TEST(RETest, PartialMatchWorks) {
#endif // GTEST_USES_POSIX_RE
+#if GTEST_HAS_STD_STRING
+
+TEST(CaptureStderrTest, CapturesStdErr) {
+ CaptureStderr();
+ fprintf(stderr, "abc");
+ ASSERT_EQ("abc", GetCapturedStderr());
+}
+
+#endif // GTEST_HAS_STD_STRING
+
} // namespace internal
} // namespace testing
diff --git a/test/gtest_output_test_.cc b/test/gtest_output_test_.cc
index a8ffa412..90d89b94 100644
--- a/test/gtest_output_test_.cc
+++ b/test/gtest_output_test_.cc
@@ -988,7 +988,18 @@ int main(int argc, char **argv) {
if (testing::internal::GTEST_FLAG(internal_run_death_test) != "") {
// Skip the usual output capturing if we're running as the child
// process of an threadsafe-style death test.
+#if GTEST_OS_WINDOWS
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4996)
+#endif // _MSC_VER
+ freopen("nul:", "w", stdout);
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+#else
freopen("/dev/null", "w", stdout);
+#endif // GTEST_OS_WINDOWS
return RUN_ALL_TESTS();
}
#endif // GTEST_HAS_DEATH_TEST
diff --git a/test/gtest_output_test_golden_win.txt b/test/gtest_output_test_golden_win.txt
index 77903ba1..d8bb622b 100644
--- a/test/gtest_output_test_golden_win.txt
+++ b/test/gtest_output_test_golden_win.txt
@@ -5,10 +5,25 @@ gtest_output_test_.cc:#: error: Value of: false
Expected: true
gtest_output_test_.cc:#: error: Value of: 3
Expected: 2
-[==========] Running 52 tests from 21 test cases.
+[==========] Running 57 tests from 26 test cases.
[----------] Global test environment set-up.
FooEnvironment::SetUp() called.
BarEnvironment::SetUp() called.
+[----------] 1 test from ADeathTest
+[ RUN ] ADeathTest.ShouldRunFirst
+[ OK ] ADeathTest.ShouldRunFirst
+[----------] 1 test from ATypedDeathTest/0, where TypeParam = int
+[ RUN ] ATypedDeathTest/0.ShouldRunFirst
+[ OK ] ATypedDeathTest/0.ShouldRunFirst
+[----------] 1 test from ATypedDeathTest/1, where TypeParam = double
+[ RUN ] ATypedDeathTest/1.ShouldRunFirst
+[ OK ] ATypedDeathTest/1.ShouldRunFirst
+[----------] 1 test from My/ATypeParamDeathTest/0, where TypeParam = int
+[ RUN ] My/ATypeParamDeathTest/0.ShouldRunFirst
+[ OK ] My/ATypeParamDeathTest/0.ShouldRunFirst
+[----------] 1 test from My/ATypeParamDeathTest/1, where TypeParam = double
+[ RUN ] My/ATypeParamDeathTest/1.ShouldRunFirst
+[ OK ] My/ATypeParamDeathTest/1.ShouldRunFirst
[----------] 2 tests from PassingTest
[ RUN ] PassingTest.PassingTest1
[ OK ] PassingTest.PassingTest1
@@ -445,8 +460,8 @@ Expected non-fatal failure.
FooEnvironment::TearDown() called.
gtest_output_test_.cc:#: error: Failed
Expected fatal failure.
-[==========] 52 tests from 21 test cases ran.
-[ PASSED ] 16 tests.
+[==========] 57 tests from 26 test cases ran.
+[ PASSED ] 21 tests.
[ FAILED ] 36 tests, listed below:
[ FAILED ] FatalFailureTest.FatalFailureInSubroutine
[ FAILED ] FatalFailureTest.FatalFailureInNestedSubroutine