Commit 4984c934 authored by zhanyong.wan's avatar zhanyong.wan
Browse files

Implements death tests on Windows (by Vlad Losev); enables POSIX regex on Mac...

Implements death tests on Windows (by Vlad Losev); enables POSIX regex on Mac and Cygwin; fixes build issue on some Linux versions due to PATH_MAX.
parent 0af0709b
......@@ -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,
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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(
......
......@@ -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
......
......@@ -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
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment