Commit 4984c934 by zhanyong.wan

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 { ...@@ -184,6 +184,7 @@ class ExitedWithCode {
const int exit_code_; const int exit_code_;
}; };
#if !GTEST_OS_WINDOWS
// Tests that an exit code describes an exit due to termination by a // Tests that an exit code describes an exit due to termination by a
// given signal. // given signal.
class KilledBySignal { class KilledBySignal {
...@@ -193,6 +194,7 @@ class KilledBySignal { ...@@ -193,6 +194,7 @@ class KilledBySignal {
private: private:
const int signum_; const int signum_;
}; };
#endif // !GTEST_OS_WINDOWS
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. // EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
// The death testing framework causes this to have interesting semantics, // The death testing framework causes this to have interesting semantics,
......
...@@ -39,6 +39,10 @@ ...@@ -39,6 +39,10 @@
#include <gtest/internal/gtest-internal.h> #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 testing {
namespace internal { namespace internal {
...@@ -121,7 +125,12 @@ class DeathTest { ...@@ -121,7 +125,12 @@ class DeathTest {
// the last death test. // the last death test.
static const char* LastMessage(); static const char* LastMessage();
static void set_last_death_test_message(const String& message);
private: 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); GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
}; };
...@@ -167,7 +176,7 @@ bool ExitedUnsuccessfully(int exit_status); ...@@ -167,7 +176,7 @@ bool ExitedUnsuccessfully(int exit_status);
case ::testing::internal::DeathTest::EXECUTE_TEST: { \ case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel \ ::testing::internal::DeathTest::ReturnSentinel \
gtest_sentinel(gtest_dt); \ gtest_sentinel(gtest_dt); \
{ statement; } \ GTEST_HIDE_UNREACHABLE_CODE_(statement); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \ break; \
} \ } \
...@@ -179,14 +188,42 @@ bool ExitedUnsuccessfully(int exit_status); ...@@ -179,14 +188,42 @@ bool ExitedUnsuccessfully(int exit_status);
// The symbol "fail" here expands to something into which a message // The symbol "fail" here expands to something into which a message
// can be streamed. // 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 // --gtest_internal_run_death_test flag, as it existed when
// RUN_ALL_TESTS was called. // RUN_ALL_TESTS was called.
struct InternalRunDeathTestFlag { class InternalRunDeathTestFlag {
String file; public:
int line; InternalRunDeathTestFlag(const String& file,
int index; int line,
int status_fd; 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 // Returns a newly created InternalRunDeathTestFlag object with fields
......
...@@ -183,7 +183,7 @@ ...@@ -183,7 +183,7 @@
#define GTEST_OS_SOLARIS 1 #define GTEST_OS_SOLARIS 1
#endif // _MSC_VER #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 // On some platforms, <regex.h> needs someone to define size_t, and
// won't compile otherwise. We can #include it here as we already // won't compile otherwise. We can #include it here as we already
...@@ -194,8 +194,8 @@ ...@@ -194,8 +194,8 @@
#else #else
// We are not on Linux, so <regex.h> may not be available. Use our // <regex.h> may not be available on this platform. Use our own
// own simple regex implementation instead. // simple regex implementation instead.
#define GTEST_USES_SIMPLE_RE 1 #define GTEST_USES_SIMPLE_RE 1
#endif // GTEST_OS_LINUX #endif // GTEST_OS_LINUX
...@@ -367,12 +367,19 @@ ...@@ -367,12 +367,19 @@
#endif // GTEST_HAS_CLONE #endif // GTEST_HAS_CLONE
// Determines whether to support death tests. // 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 #define GTEST_HAS_DEATH_TEST 1
#include <vector> #include <vector>
#include <fcntl.h> #endif // GTEST_HAS_STD_STRING && (GTEST_HAS_CLONE ||
#include <sys/mman.h> // GTEST_OS_WINDOWS && _MSC_VER >= 1400)
#endif // GTEST_HAS_STD_STRING && GTEST_HAS_CLONE
// Determines whether to support value-parameterized tests. // Determines whether to support value-parameterized tests.
...@@ -595,14 +602,17 @@ inline void FlushInfoLog() { fflush(NULL); } ...@@ -595,14 +602,17 @@ inline void FlushInfoLog() { fflush(NULL); }
// CaptureStderr - starts capturing stderr. // CaptureStderr - starts capturing stderr.
// GetCapturedStderr - stops capturing stderr and returns the captured string. // 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 #if GTEST_HAS_DEATH_TEST
// A copy of all command line arguments. Set by InitGoogleTest(). // A copy of all command line arguments. Set by InitGoogleTest().
extern ::std::vector<String> g_argvs; extern ::std::vector<String> g_argvs;
void CaptureStderr();
// GTEST_HAS_DEATH_TEST implies we have ::std::string. // GTEST_HAS_DEATH_TEST implies we have ::std::string.
::std::string GetCapturedStderr();
const ::std::vector<String>& GetArgvs(); const ::std::vector<String>& GetArgvs();
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
...@@ -692,7 +702,7 @@ struct is_pointer<T*> : public true_type {}; ...@@ -692,7 +702,7 @@ struct is_pointer<T*> : public true_type {};
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
typedef __int64 BiggestInt; typedef __int64 BiggestInt;
#else #else
typedef long long BiggestInt; // NOLINT typedef long long BiggestInt; // NOLINT
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
// The maximum number a BiggestInt can represent. This definition // The maximum number a BiggestInt can represent. This definition
......
...@@ -102,38 +102,65 @@ env = env.Clone() ...@@ -102,38 +102,65 @@ env = env.Clone()
env.Prepend(CPPPATH = ['..', env.Prepend(CPPPATH = ['..',
'../include']) '../include'])
# Sources shared by base library and library that includes main. # Sources used by base library and library that includes main.
gtest_sources = ['../src/gtest-all.cc'] 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 # gtest.lib to be used by most apps (if you have your own main
# function) # function)
gtest = env.StaticLibrary(target='gtest', 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; # 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. # it is also used by the tests for Google Test itself.
gtest_main = env.StaticLibrary(target='gtest_main', 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. # Install the libraries if needed.
if 'LIB_OUTPUT' in env.Dictionary(): 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): def ConstructSourceList(target, dir_prefix, additional_sources=None):
"""Helper to create gtest binaries: tests, samples, etc. """Helper to create source file list for gtest binaries.
Args: Args:
env: The SCons construction environment to use to build. target: The basename of the target's main source file.
target: The basename of the target's main source file, also used as target
name.
dir_prefix: The path to prefix the main source file. dir_prefix: The path to prefix the main source file.
gtest_lib: The gtest lib to use. 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))] source = [env.File('%s.cc' % target, env.Dir(dir_prefix))]
if additional_sources: if additional_sources:
source += 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(): if 'EXE_OUTPUT' in env.Dictionary():
env.Install('$EXE_OUTPUT', source=[unit_test]) env.Install('$EXE_OUTPUT', source=[unit_test])
...@@ -144,8 +171,13 @@ def GtestUnitTest(env, target, gtest_lib, additional_sources=None): ...@@ -144,8 +171,13 @@ def GtestUnitTest(env, target, gtest_lib, additional_sources=None):
env: The SCons construction environment to use to build. env: The SCons construction environment to use to build.
target: The basename of the target unit test .cc file. target: The basename of the target unit test .cc file.
gtest_lib: The gtest lib to use. 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-filepath_test', gtest_main)
GtestUnitTest(env, 'gtest-message_test', gtest_main) GtestUnitTest(env, 'gtest-message_test', gtest_main)
...@@ -168,6 +200,15 @@ GtestUnitTest(env, 'gtest_output_test_', gtest) ...@@ -168,6 +200,15 @@ GtestUnitTest(env, 'gtest_output_test_', gtest)
GtestUnitTest(env, 'gtest_color_test_', gtest) GtestUnitTest(env, 'gtest_color_test_', gtest)
GtestUnitTest(env, 'gtest-linked_ptr_test', gtest_main) GtestUnitTest(env, 'gtest-linked_ptr_test', gtest_main)
GtestUnitTest(env, 'gtest-port_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: # TODO(wan@google.com) Add these unit tests:
# - gtest_break_on_failure_unittest_ # - gtest_break_on_failure_unittest_
...@@ -195,8 +236,13 @@ def GtestSample(env, target, gtest_lib, additional_sources=None): ...@@ -195,8 +236,13 @@ def GtestSample(env, target, gtest_lib, additional_sources=None):
env: The SCons construction environment to use to build. env: The SCons construction environment to use to build.
target: The basename of the target unit test .cc file. target: The basename of the target unit test .cc file.
gtest_lib: The gtest lib to use. 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. # Use the GTEST_BUILD_SAMPLES build variable to control building of samples.
# In your SConstruct file, add # In your SConstruct file, add
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <limits.h> #include <limits.h>
#include <sys/stat.h> // NOLINT #include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT #include <unistd.h> // NOLINT
#include <climits> // Some Linux distributions define PATH_MAX here.
#endif // _WIN32_WCE or _WIN32 #endif // _WIN32_WCE or _WIN32
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
......
...@@ -45,17 +45,20 @@ ...@@ -45,17 +45,20 @@
#error "It must not be included except by Google Test itself." #error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_ #endif // GTEST_IMPLEMENTATION_
#include <errno.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> // For strtoll/_strtoul64.
#include <gtest/internal/gtest-port.h>
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
#include <windows.h> // NOLINT #include <windows.h> // For DWORD.
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#include <gtest/internal/gtest-port.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <gtest/gtest-spi.h> #include <gtest/gtest-spi.h>
#include <string>
namespace testing { namespace testing {
// Declares the flags. // Declares the flags.
...@@ -1313,6 +1316,77 @@ bool MatchRegexAnywhere(const char* regex, const char* str); ...@@ -1313,6 +1316,77 @@ bool MatchRegexAnywhere(const char* regex, const char* str);
void ParseGoogleTestFlagsOnly(int* argc, char** argv); void ParseGoogleTestFlagsOnly(int* argc, char** argv);
void ParseGoogleTestFlagsOnly(int* argc, wchar_t** 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 internal
} // namespace testing } // namespace testing
......
...@@ -35,9 +35,9 @@ ...@@ -35,9 +35,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#if GTEST_HAS_DEATH_TEST #if !GTEST_OS_WINDOWS
#include <regex.h> #include <unistd.h>
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_OS_WINDOWS
#if GTEST_USES_SIMPLE_RE #if GTEST_USES_SIMPLE_RE
#include <string.h> #include <string.h>
...@@ -63,6 +63,13 @@ ...@@ -63,6 +63,13 @@
namespace testing { namespace testing {
namespace internal { 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 #if GTEST_USES_POSIX_RE
// Implements RE. Currently only needed for death tests. // Implements RE. Currently only needed for death tests.
...@@ -105,7 +112,13 @@ void RE::Init(const char* regex) { ...@@ -105,7 +112,13 @@ void RE::Init(const char* regex) {
// previous expression returns false. Otherwise partial_regex_ may // previous expression returns false. Otherwise partial_regex_ may
// not be properly initialized can may cause trouble when it's // not be properly initialized can may cause trouble when it's
// freed. // 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_) EXPECT_TRUE(is_valid_)
<< "Regular expression \"" << regex << "Regular expression \"" << regex
<< "\" is not a valid POSIX Extended regular expression."; << "\" is not a valid POSIX Extended regular expression.";
...@@ -379,11 +392,19 @@ void GTestLog(GTestLogSeverity severity, const char* file, ...@@ -379,11 +392,19 @@ void GTestLog(GTestLogSeverity severity, const char* file,
severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
fprintf(stderr, "\n%s %s:%d: %s\n", marker, file, line, msg); fprintf(stderr, "\n%s %s:%d: %s\n", marker, file, line, msg);
if (severity == GTEST_FATAL) { if (severity == GTEST_FATAL) {
fflush(NULL); // abort() is not guaranteed to flush open file streams.
abort(); 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. // Defines the stderr capturer.
...@@ -391,16 +412,26 @@ class CapturedStderr { ...@@ -391,16 +412,26 @@ class CapturedStderr {
public: public:
// The ctor redirects stderr to a temporary file. // The ctor redirects stderr to a temporary file.
CapturedStderr() { 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 // There's no guarantee that a test has write access to the
// current directory, so we create the temporary file in the /tmp // current directory, so we create the temporary file in the /tmp
// directory instead. // directory instead.
char name_template[] = "/tmp/captured_stderr.XXXXXX"; char name_template[] = "/tmp/captured_stderr.XXXXXX";
const int captured_fd = mkstemp(name_template); const int captured_fd = mkstemp(name_template);
filename_ = name_template; filename_ = name_template;
#endif // GTEST_OS_WINDOWS
fflush(NULL); fflush(NULL);
dup2(captured_fd, STDERR_FILENO); dup2(captured_fd, kStdErrFileno);
close(captured_fd); close(captured_fd);
} }
...@@ -412,7 +443,7 @@ class CapturedStderr { ...@@ -412,7 +443,7 @@ class CapturedStderr {
void StopCapture() { void StopCapture() {
// Restores the original stream. // Restores the original stream.
fflush(NULL); fflush(NULL);
dup2(uncaptured_fd_, STDERR_FILENO); dup2(uncaptured_fd_, kStdErrFileno);
close(uncaptured_fd_); close(uncaptured_fd_);
uncaptured_fd_ = -1; uncaptured_fd_ = -1;
} }
...@@ -427,6 +458,10 @@ class CapturedStderr { ...@@ -427,6 +458,10 @@ class CapturedStderr {
::std::string filename_; ::std::string filename_;
}; };
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
static CapturedStderr* g_captured_stderr = NULL; static CapturedStderr* g_captured_stderr = NULL;
// Returns the size (in bytes) of a file. // Returns the size (in bytes) of a file.
...@@ -436,8 +471,6 @@ static size_t GetFileSize(FILE * file) { ...@@ -436,8 +471,6 @@ static size_t GetFileSize(FILE * file) {
} }
// Reads the entire content of a file as a string. // 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) { static ::std::string ReadEntireFile(FILE * file) {
const size_t file_size = GetFileSize(file); const size_t file_size = GetFileSize(file);
char* const buffer = new char[file_size]; char* const buffer = new char[file_size];
...@@ -473,9 +506,18 @@ void CaptureStderr() { ...@@ -473,9 +506,18 @@ void CaptureStderr() {
// use it here. // use it here.
::std::string GetCapturedStderr() { ::std::string GetCapturedStderr() {
g_captured_stderr->StopCapture(); 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"); FILE* const file = fopen(g_captured_stderr->filename().c_str(), "r");
const ::std::string content = ReadEntireFile(file); const ::std::string content = ReadEntireFile(file);
fclose(file); fclose(file);
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
delete g_captured_stderr; delete g_captured_stderr;
g_captured_stderr = NULL; g_captured_stderr = NULL;
...@@ -483,6 +525,10 @@ void CaptureStderr() { ...@@ -483,6 +525,10 @@ void CaptureStderr() {
return content; return content;
} }
#endif // GTEST_HAS_STD_STRING
#if GTEST_HAS_DEATH_TEST
// A copy of all command line arguments. Set by InitGoogleTest(). // A copy of all command line arguments. Set by InitGoogleTest().
::std::vector<String> g_argvs; ::std::vector<String> g_argvs;
......
...@@ -3300,17 +3300,43 @@ void UnitTest::RecordPropertyForCurrentTest(const char* key, ...@@ -3300,17 +3300,43 @@ void UnitTest::RecordPropertyForCurrentTest(const char* key,
int UnitTest::Run() { int UnitTest::Run() {
#if GTEST_OS_WINDOWS #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) #if !defined(_WIN32_WCE)
// SetErrorMode doesn't exist on CE. // 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(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
}
#endif // _WIN32_WCE #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 { __try {
return impl_->RunAllTests(); return impl_->RunAllTests();
} __except(internal::UnitTestOptions::GTestShouldProcessSEH( } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
......
...@@ -80,13 +80,15 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) { ...@@ -80,13 +80,15 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) { TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
const bool a_false_condition = false; const bool a_false_condition = false;
EXPECT_DEATH(GTEST_CHECK_(a_false_condition) << "Extra info", const char regex[] =
#ifdef _MSC_VER #ifdef _MSC_VER
"gtest-port_test\\.cc\\([0-9]+\\):" "gtest-port_test\\.cc\\(\\d+\\):"
#else #else
"gtest-port_test\\.cc:[0-9]+" "gtest-port_test\\.cc:[0-9]+"
#endif // _MSC_VER #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) { TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
...@@ -575,25 +577,25 @@ TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) { ...@@ -575,25 +577,25 @@ TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) {
// Tests RE's implicit constructors. // Tests RE's implicit constructors.
TEST(RETest, ImplicitConstructorWorks) { TEST(RETest, ImplicitConstructorWorks) {
const RE empty = ""; const RE empty("");
EXPECT_STREQ("", empty.pattern()); EXPECT_STREQ("", empty.pattern());
const RE simple = "hello"; const RE simple("hello");
EXPECT_STREQ("hello", simple.pattern()); EXPECT_STREQ("hello", simple.pattern());
} }
// Tests that RE's constructors reject invalid regular expressions. // Tests that RE's constructors reject invalid regular expressions.
TEST(RETest, RejectsInvalidRegex) { TEST(RETest, RejectsInvalidRegex) {
EXPECT_NONFATAL_FAILURE({ EXPECT_NONFATAL_FAILURE({
const RE normal = NULL; const RE normal(NULL);
}, "NULL is not a valid simple regular expression"); }, "NULL is not a valid simple regular expression");
EXPECT_NONFATAL_FAILURE({ EXPECT_NONFATAL_FAILURE({
const RE normal = ".*(\\w+"; const RE normal(".*(\\w+");
}, "'(' is unsupported"); }, "'(' is unsupported");
EXPECT_NONFATAL_FAILURE({ EXPECT_NONFATAL_FAILURE({
const RE invalid = "^?"; const RE invalid("^?");
}, "'?' can only follow a repeatable token"); }, "'?' can only follow a repeatable token");
} }
...@@ -603,10 +605,10 @@ TEST(RETest, FullMatchWorks) { ...@@ -603,10 +605,10 @@ TEST(RETest, FullMatchWorks) {
EXPECT_TRUE(RE::FullMatch("", empty)); EXPECT_TRUE(RE::FullMatch("", empty));
EXPECT_FALSE(RE::FullMatch("a", empty)); EXPECT_FALSE(RE::FullMatch("a", empty));
const RE re1 = "a"; const RE re1("a");
EXPECT_TRUE(RE::FullMatch("a", re1)); 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("az", re));
EXPECT_TRUE(RE::FullMatch("axyz", re)); EXPECT_TRUE(RE::FullMatch("axyz", re));
EXPECT_FALSE(RE::FullMatch("baz", re)); EXPECT_FALSE(RE::FullMatch("baz", re));
...@@ -615,11 +617,11 @@ TEST(RETest, FullMatchWorks) { ...@@ -615,11 +617,11 @@ TEST(RETest, FullMatchWorks) {
// Tests RE::PartialMatch(). // Tests RE::PartialMatch().
TEST(RETest, PartialMatchWorks) { TEST(RETest, PartialMatchWorks) {
const RE empty = ""; const RE empty("");
EXPECT_TRUE(RE::PartialMatch("", empty)); EXPECT_TRUE(RE::PartialMatch("", empty));
EXPECT_TRUE(RE::PartialMatch("a", 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("az", re));
EXPECT_TRUE(RE::PartialMatch("axyz", re)); EXPECT_TRUE(RE::PartialMatch("axyz", re));
EXPECT_TRUE(RE::PartialMatch("baz", re)); EXPECT_TRUE(RE::PartialMatch("baz", re));
...@@ -629,5 +631,15 @@ TEST(RETest, PartialMatchWorks) { ...@@ -629,5 +631,15 @@ TEST(RETest, PartialMatchWorks) {
#endif // GTEST_USES_POSIX_RE #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 internal
} // namespace testing } // namespace testing
...@@ -988,7 +988,18 @@ int main(int argc, char **argv) { ...@@ -988,7 +988,18 @@ int main(int argc, char **argv) {
if (testing::internal::GTEST_FLAG(internal_run_death_test) != "") { if (testing::internal::GTEST_FLAG(internal_run_death_test) != "") {
// Skip the usual output capturing if we're running as the child // Skip the usual output capturing if we're running as the child
// process of an threadsafe-style death test. // 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); freopen("/dev/null", "w", stdout);
#endif // GTEST_OS_WINDOWS
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
......
...@@ -5,10 +5,25 @@ gtest_output_test_.cc:#: error: Value of: false ...@@ -5,10 +5,25 @@ gtest_output_test_.cc:#: error: Value of: false
Expected: true Expected: true
gtest_output_test_.cc:#: error: Value of: 3 gtest_output_test_.cc:#: error: Value of: 3
Expected: 2 Expected: 2
[==========] Running 52 tests from 21 test cases. [==========] Running 57 tests from 26 test cases.
[----------] Global test environment set-up. [----------] Global test environment set-up.
FooEnvironment::SetUp() called. FooEnvironment::SetUp() called.
BarEnvironment::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 [----------] 2 tests from PassingTest
[ RUN ] PassingTest.PassingTest1 [ RUN ] PassingTest.PassingTest1
[ OK ] PassingTest.PassingTest1 [ OK ] PassingTest.PassingTest1
...@@ -445,8 +460,8 @@ Expected non-fatal failure. ...@@ -445,8 +460,8 @@ Expected non-fatal failure.
FooEnvironment::TearDown() called. FooEnvironment::TearDown() called.
gtest_output_test_.cc:#: error: Failed gtest_output_test_.cc:#: error: Failed
Expected fatal failure. Expected fatal failure.
[==========] 52 tests from 21 test cases ran. [==========] 57 tests from 26 test cases ran.
[ PASSED ] 16 tests. [ PASSED ] 21 tests.
[ FAILED ] 36 tests, listed below: [ FAILED ] 36 tests, listed below:
[ FAILED ] FatalFailureTest.FatalFailureInSubroutine [ FAILED ] FatalFailureTest.FatalFailureInSubroutine
[ FAILED ] FatalFailureTest.FatalFailureInNestedSubroutine [ 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