aboutsummaryrefslogtreecommitdiff
path: root/utils/unittest/googletest/gtest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'utils/unittest/googletest/gtest.cc')
-rw-r--r--utils/unittest/googletest/gtest.cc1132
1 files changed, 661 insertions, 471 deletions
diff --git a/utils/unittest/googletest/gtest.cc b/utils/unittest/googletest/gtest.cc
index 9aa5441149..7624497411 100644
--- a/utils/unittest/googletest/gtest.cc
+++ b/utils/unittest/googletest/gtest.cc
@@ -31,8 +31,8 @@
//
// The Google C++ Testing Framework (Google Test)
-#include <gtest/gtest.h>
-#include <gtest/gtest-spi.h>
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
#include <ctype.h>
#include <math.h>
@@ -43,7 +43,7 @@
#include <wctype.h>
#include <algorithm>
-#include <ostream>
+#include <ostream> // NOLINT
#include <sstream>
#include <vector>
@@ -51,72 +51,76 @@
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <fcntl.h>
-#include <limits.h>
-#include <sched.h>
+# include <fcntl.h> // NOLINT
+# include <limits.h> // NOLINT
+# include <sched.h> // NOLINT
// Declares vsnprintf(). This header is not available on Windows.
-#include <strings.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <string>
-#include <vector>
+# include <strings.h> // NOLINT
+# include <sys/mman.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
+# include <string>
#elif GTEST_OS_SYMBIAN
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
#elif GTEST_OS_ZOS
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
// On z/OS we additionally need strings.h for strcasecmp.
-#include <strings.h> // NOLINT
+# include <strings.h> // NOLINT
#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#elif GTEST_OS_WINDOWS // We are on Windows proper.
-#include <io.h> // NOLINT
-#include <sys/timeb.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <sys/stat.h> // NOLINT
+# include <io.h> // NOLINT
+# include <sys/timeb.h> // NOLINT
+# include <sys/types.h> // NOLINT
+# include <sys/stat.h> // NOLINT
-#if GTEST_OS_WINDOWS_MINGW
+# if GTEST_OS_WINDOWS_MINGW
// MinGW has gettimeofday() but not _ftime64().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
// TODO(kenton@google.com): There are other ways to get the time on
// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW
// supports these. consider using them instead.
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
-#endif // GTEST_OS_WINDOWS_MINGW
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
+# endif // GTEST_OS_WINDOWS_MINGW
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#else
// Assume other platforms have gettimeofday().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <sys/time.h> // NOLINT
-#include <unistd.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
#endif // GTEST_OS_LINUX
#if GTEST_HAS_EXCEPTIONS
-#include <stdexcept>
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h> // NOLINT
+# include <netdb.h> // NOLINT
#endif
// Indicates that this translation unit is part of Google Test's
@@ -129,7 +133,7 @@
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_WINDOWS
-#define vsnprintf _vsnprintf
+# define vsnprintf _vsnprintf
#endif // GTEST_OS_WINDOWS
namespace testing {
@@ -187,7 +191,7 @@ GTEST_DEFINE_bool_(
GTEST_DEFINE_bool_(
catch_exceptions,
- internal::BoolFromGTestEnv("catch_exceptions", false),
+ internal::BoolFromGTestEnv("catch_exceptions", true),
"True iff " GTEST_NAME_
" should catch exceptions and treat them as test failures.");
@@ -258,6 +262,13 @@ GTEST_DEFINE_int32_(
"The maximum number of stack frames to print when an "
"assertion fails. The valid range is 0 through 100, inclusive.");
+GTEST_DEFINE_string_(
+ stream_result_to,
+ internal::StringFromGTestEnv("stream_result_to", ""),
+ "This flag specifies the host name and the port number on which to stream "
+ "test results. Example: \"localhost:555\". The flag is effective only on "
+ "Linux.");
+
GTEST_DEFINE_bool_(
throw_on_failure,
internal::BoolFromGTestEnv("throw_on_failure", false),
@@ -490,20 +501,33 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
!MatchesFilter(full_name, negative.c_str()));
}
-#if GTEST_OS_WINDOWS
+#if GTEST_HAS_SEH
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
// This function is useful as an __except condition.
int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
- // Google Test should handle an exception if:
+ // Google Test should handle a SEH exception if:
// 1. the user wants it to, AND
- // 2. this is not a breakpoint exception.
- return (GTEST_FLAG(catch_exceptions) &&
- exception_code != EXCEPTION_BREAKPOINT) ?
- EXCEPTION_EXECUTE_HANDLER :
- EXCEPTION_CONTINUE_SEARCH;
+ // 2. this is not a breakpoint exception, AND
+ // 3. this is not a C++ exception (VC++ implements them via SEH,
+ // apparently).
+ //
+ // SEH exception code for C++ exceptions.
+ // (see http://support.microsoft.com/kb/185294 for more information).
+ const DWORD kCxxExceptionCode = 0xe06d7363;
+
+ bool should_handle = true;
+
+ if (!GTEST_FLAG(catch_exceptions))
+ should_handle = false;
+ else if (exception_code == EXCEPTION_BREAKPOINT)
+ should_handle = false;
+ else if (exception_code == kCxxExceptionCode)
+ should_handle = false;
+
+ return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
-#endif // GTEST_OS_WINDOWS
+#endif // GTEST_HAS_SEH
} // namespace internal
@@ -583,7 +607,7 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
const char* /* substr_expr */,
const TestPartResultArray& results,
TestPartResult::Type type,
- const char* substr) {
+ const string& substr) {
const String expected(type == TestPartResult::kFatalFailure ?
"1 fatal failure" :
"1 non-fatal failure");
@@ -594,23 +618,21 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
for (int i = 0; i < results.size(); i++) {
msg << "\n" << results.GetTestPartResult(i);
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
const TestPartResult& r = results.GetTestPartResult(0);
if (r.type() != type) {
- msg << "Expected: " << expected << "\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: " << expected << "\n"
+ << " Actual:\n"
+ << r;
}
- if (strstr(r.message(), substr) == NULL) {
- msg << "Expected: " << expected << " containing \""
- << substr << "\"\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ if (strstr(r.message(), substr.c_str()) == NULL) {
+ return AssertionFailure() << "Expected: " << expected << " containing \""
+ << substr << "\"\n"
+ << " Actual:\n"
+ << r;
}
return AssertionSuccess();
@@ -622,7 +644,7 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
SingleFailureChecker:: SingleFailureChecker(
const TestPartResultArray* results,
TestPartResult::Type type,
- const char* substr)
+ const string& substr)
: results_(results),
type_(type),
substr_(substr) {}
@@ -632,7 +654,7 @@ SingleFailureChecker:: SingleFailureChecker(
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
SingleFailureChecker::~SingleFailureChecker() {
- EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_.c_str());
+ EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
}
DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
@@ -764,25 +786,30 @@ TimeInMillis GetTimeInMillis() {
return 0;
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
__timeb64 now;
-#ifdef _MSC_VER
+
+# ifdef _MSC_VER
+
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
// (deprecated function) there.
// TODO(kenton@google.com): Use GetTickCount()? Or use
// SystemTimeToFileTime()
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
_ftime64(&now);
-#pragma warning(pop) // Restores the warning state.
-#else
+# pragma warning(pop) // Restores the warning state.
+# else
+
_ftime64(&now);
-#endif // _MSC_VER
+
+# endif // _MSC_VER
+
return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
#elif GTEST_HAS_GETTIMEOFDAY_
struct timeval now;
gettimeofday(&now, NULL);
return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
#else
-#error "Don't know how to get the current time on your system."
+# error "Don't know how to get the current time on your system."
#endif
}
@@ -918,55 +945,13 @@ Message& Message::operator <<(const ::wstring& wstr) {
}
#endif // GTEST_HAS_GLOBAL_WSTRING
-namespace internal {
-
-// Formats a value to be used in a failure message.
-
-// For a char value, we print it as a C++ char literal and as an
-// unsigned integer (both in decimal and in hexadecimal).
-String FormatForFailureMessage(char ch) {
- const unsigned int ch_as_uint = ch;
- // A String object cannot contain '\0', so we print "\\0" when ch is
- // '\0'.
- return String::Format("'%s' (%u, 0x%X)",
- ch ? String::Format("%c", ch).c_str() : "\\0",
- ch_as_uint, ch_as_uint);
-}
-
-// For a wchar_t value, we print it as a C++ wchar_t literal and as an
-// unsigned integer (both in decimal and in hexidecimal).
-String FormatForFailureMessage(wchar_t wchar) {
- // The C++ standard doesn't specify the exact size of the wchar_t
- // type. It just says that it shall have the same size as another
- // integral type, called its underlying type.
- //
- // Therefore, in order to print a wchar_t value in the numeric form,
- // we first convert it to the largest integral type (UInt64) and
- // then print the converted value.
- //
- // We use streaming to print the value as "%llu" doesn't work
- // correctly with MSVC 7.1.
- const UInt64 wchar_as_uint64 = wchar;
- Message msg;
- // A String object cannot contain '\0', so we print "\\0" when wchar is
- // L'\0'.
- char buffer[32]; // CodePointToUtf8 requires a buffer that big.
- msg << "L'"
- << (wchar ? CodePointToUtf8(static_cast<UInt32>(wchar), buffer) : "\\0")
- << "' (" << wchar_as_uint64 << ", 0x" << ::std::setbase(16)
- << wchar_as_uint64 << ")";
- return msg.GetString();
-}
-
-} // namespace internal
-
// AssertionResult constructors.
// Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult::AssertionResult(const AssertionResult& other)
: success_(other.success_),
message_(other.message_.get() != NULL ?
- new internal::String(*other.message_) :
- static_cast<internal::String*>(NULL)) {
+ new ::std::string(*other.message_) :
+ static_cast< ::std::string*>(NULL)) {
}
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
@@ -1029,7 +1014,7 @@ AssertionResult EqFailure(const char* expected_expression,
msg << "\nWhich is: " << expected_value;
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
@@ -1059,13 +1044,12 @@ AssertionResult DoubleNearPredFormat(const char* expr1,
// TODO(wan): do not print the value of an expression if it's
// already a literal.
- Message msg;
- msg << "The difference between " << expr1 << " and " << expr2
+ return AssertionFailure()
+ << "The difference between " << expr1 << " and " << expr2
<< " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
<< expr1 << " evaluates to " << val1 << ",\n"
<< expr2 << " evaluates to " << val2 << ", and\n"
<< abs_error_expr << " evaluates to " << abs_error << ".";
- return AssertionFailure(msg);
}
@@ -1090,20 +1074,18 @@ AssertionResult FloatingPointLE(const char* expr1,
// val2 is NaN, as the IEEE floating-point standard requires that
// any predicate involving a NaN must return false.
- StrStream val1_ss;
+ ::std::stringstream val1_ss;
val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val1;
- StrStream val2_ss;
+ ::std::stringstream val2_ss;
val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val2;
- Message msg;
- msg << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
- << " Actual: " << StrStreamToString(&val1_ss) << " vs "
- << StrStreamToString(&val2_ss);
-
- return AssertionFailure(msg);
+ return AssertionFailure()
+ << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+ << " Actual: " << StringStreamToString(&val1_ss) << " vs "
+ << StringStreamToString(&val2_ss);
}
} // namespace internal
@@ -1150,11 +1132,10 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
- Message msg;\
- msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
- return AssertionFailure(msg);\
}\
}
@@ -1216,11 +1197,9 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
if (!String::CStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: \""
- << s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
}
}
@@ -1232,11 +1211,10 @@ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
+ return AssertionFailure()
+ << "Expected: (" << s1_expression << ") != ("
<< s2_expression << ") (ignoring case), actual: \""
<< s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
}
}
@@ -1285,13 +1263,12 @@ AssertionResult IsSubstringImpl(
const bool is_wide_string = sizeof(needle[0]) > 1;
const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
- return AssertionFailure(
- Message()
+ return AssertionFailure()
<< "Value of: " << needle_expr << "\n"
<< " Actual: " << begin_string_quote << needle << "\"\n"
<< "Expected: " << (expected_to_be_substring ? "" : "not ")
<< "a substring of " << haystack_expr << "\n"
- << "Which is: " << begin_string_quote << haystack << "\"");
+ << "Which is: " << begin_string_quote << haystack << "\"";
}
} // namespace
@@ -1360,10 +1337,13 @@ namespace {
AssertionResult HRESULTFailureHelper(const char* expr,
const char* expected,
long hr) { // NOLINT
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
+
// Windows CE doesn't support FormatMessage.
const char error_text[] = "";
-#else
+
+# else
+
// Looks up the human-readable system message for the HRESULT code
// and since we're not passing any params to FormatMessage, we don't
// want inserts expanded.
@@ -1380,18 +1360,17 @@ AssertionResult HRESULTFailureHelper(const char* expr,
kBufSize, // buf size
NULL); // no arguments for inserts
// Trims tailing white space (FormatMessage leaves a trailing cr-lf)
- for (; message_length && isspace(error_text[message_length - 1]);
+ for (; message_length && IsSpace(error_text[message_length - 1]);
--message_length) {
error_text[message_length - 1] = '\0';
}
-#endif // GTEST_OS_WINDOWS_MOBILE
+
+# endif // GTEST_OS_WINDOWS_MOBILE
const String error_hex(String::Format("0x%08X ", hr));
- Message msg;
- msg << "Expected: " << expr << " " << expected << ".\n"
+ return ::testing::AssertionFailure()
+ << "Expected: " << expr << " " << expected << ".\n"
<< " Actual: " << error_hex << error_text << "\n";
-
- return ::testing::AssertionFailure(msg);
}
} // namespace
@@ -1526,7 +1505,7 @@ String WideStringToUtf8(const wchar_t* str, int num_chars) {
if (num_chars == -1)
num_chars = static_cast<int>(wcslen(str));
- StrStream stream;
+ ::std::stringstream stream;
for (int i = 0; i < num_chars; ++i) {
UInt32 unicode_code_point;
@@ -1543,7 +1522,7 @@ String WideStringToUtf8(const wchar_t* str, int num_chars) {
char buffer[32]; // CodePointToUtf8 requires a buffer this big.
stream << CodePointToUtf8(unicode_code_point, buffer);
}
- return StrStreamToString(&stream);
+ return StringStreamToString(&stream);
}
// Converts a wide C string to a String using the UTF-8 encoding.
@@ -1602,12 +1581,10 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
return AssertionSuccess();
}
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: "
- << String::ShowWideCStringQuoted(s1)
- << " vs " << String::ShowWideCStringQuoted(s2);
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: "
+ << String::ShowWideCStringQuoted(s1)
+ << " vs " << String::ShowWideCStringQuoted(s2);
}
// Compares two C strings, ignoring case. Returns true iff they have
@@ -1638,17 +1615,17 @@ bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
// current locale.
bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
const wchar_t* rhs) {
- if ( lhs == NULL ) return rhs == NULL;
+ if (lhs == NULL) return rhs == NULL;
- if ( rhs == NULL ) return false;
+ if (rhs == NULL) return false;
#if GTEST_OS_WINDOWS
return _wcsicmp(lhs, rhs) == 0;
-#elif GTEST_OS_LINUX
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
return wcscasecmp(lhs, rhs) == 0;
#else
- // Mac OS X and Cygwin don't define wcscasecmp. Other unknown OSes
- // may not define it either.
+ // Android, Mac OS X and Cygwin don't define wcscasecmp.
+ // Other unknown OSes may not define it either.
wint_t left, right;
do {
left = towlower(*lhs++);
@@ -1730,10 +1707,12 @@ String String::Format(const char * format, ...) {
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
// 4996 (deprecated function) there.
#ifdef _MSC_VER // We are using MSVC.
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
+
const int size = vsnprintf(buffer, kBufferSize, format, args);
-#pragma warning(pop) // Restores the warning state.
+
+# pragma warning(pop) // Restores the warning state.
#else // We are not using MSVC.
const int size = vsnprintf(buffer, kBufferSize, format, args);
#endif // _MSC_VER
@@ -1751,16 +1730,16 @@ String String::Format(const char * format, ...) {
}
}
-// Converts the buffer in a StrStream to a String, converting NUL
+// Converts the buffer in a stringstream to a String, converting NUL
// bytes to "\\0" along the way.
-String StrStreamToString(StrStream* ss) {
+String StringStreamToString(::std::stringstream* ss) {
const ::std::string& str = ss->str();
const char* const start = str.c_str();
const char* const end = start + str.length();
- // We need to use a helper StrStream to do this transformation
+ // We need to use a helper stringstream to do this transformation
// because String doesn't support push_back().
- StrStream helper;
+ ::std::stringstream helper;
for (const char* ch = start; ch != end; ++ch) {
if (*ch == '\0') {
helper << "\\0"; // Replaces NUL with "\\0";
@@ -1964,22 +1943,6 @@ void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
} // namespace internal
-#if GTEST_HAS_SEH
-// We are on Windows with SEH.
-
-// Adds an "exception thrown" fatal failure to the current test.
-static void AddExceptionThrownFailure(DWORD exception_code,
- const char* location) {
- Message message;
- message << "Exception thrown with code 0x" << std::setbase(16) <<
- exception_code << std::setbase(10) << " in " << location << ".";
-
- internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
- message.GetString());
-}
-
-#endif // GTEST_HAS_SEH
-
// Google Test requires all tests in the same test case to use the same test
// fixture class. This function checks if the current test has the
// same fixture class as the first test in the current test case. If
@@ -1990,15 +1953,13 @@ bool Test::HasSameFixtureClass() {
const TestCase* const test_case = impl->current_test_case();
// Info about the first test in the current test case.
- const internal::TestInfoImpl* const first_test_info =
- test_case->test_info_list()[0]->impl();
- const internal::TypeId first_fixture_id = first_test_info->fixture_class_id();
+ const TestInfo* const first_test_info = test_case->test_info_list()[0];
+ const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
const char* const first_test_name = first_test_info->name();
// Info about the current test.
- const internal::TestInfoImpl* const this_test_info =
- impl->current_test_info()->impl();
- const internal::TypeId this_fixture_id = this_test_info->fixture_class_id();
+ const TestInfo* const this_test_info = impl->current_test_info();
+ const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
const char* const this_test_name = this_test_info->name();
if (this_fixture_id != first_fixture_id) {
@@ -2048,62 +2009,167 @@ bool Test::HasSameFixtureClass() {
return true;
}
-// Runs the test and updates the test result.
-void Test::Run() {
- if (!HasSameFixtureClass()) return;
+#if GTEST_HAS_SEH
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+// Adds an "exception thrown" fatal failure to the current test. This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static internal::String* FormatSehExceptionMessage(DWORD exception_code,
+ const char* location) {
+ Message message;
+ message << "SEH exception with code 0x" << std::setbase(16) <<
+ exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+ return new internal::String(message.GetString());
+}
+
+#endif // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static internal::String FormatCxxExceptionMessage(const char* description,
+ const char* location) {
+ Message message;
+ if (description != NULL) {
+ message << "C++ exception with description \"" << description << "\"";
+ } else {
+ message << "Unknown C++ exception";
+ }
+ message << " thrown in " << location << ".";
+
+ return message.GetString();
+}
+
+static internal::String PrintTestPartResultToString(
+ const TestPartResult& test_part_result);
+
+// A failed Google Test assertion will throw an exception of this type when
+// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled). We
+// derive it from std::runtime_error, which is for errors presumably
+// detectable only at run time. Since std::runtime_error inherits from
+// std::exception, many testing frameworks know how to extract and print the
+// message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+ explicit GoogleTestFailureException(const TestPartResult& failure)
+ : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception. (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function. Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
- impl->os_stack_trace_getter()->UponLeavingGTest();
__try {
- SetUp();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
+ return (object->*method)();
+ } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "SetUp()");
+ // We create the exception message on the heap because VC++ prohibits
+ // creation of objects with destructors on stack in functions using __try
+ // (see error C2712).
+ internal::String* exception_message = FormatSehExceptionMessage(
+ GetExceptionCode(), location);
+ internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+ *exception_message);
+ delete exception_message;
+ return static_cast<Result>(0);
}
+#else
+ (void)location;
+ return (object->*method)();
+#endif // GTEST_HAS_SEH
+}
- // We will run the test only if SetUp() had no fatal failure.
- if (!HasFatalFailure()) {
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TestBody();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "the test body");
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+ // NOTE: The user code can affect the way in which Google Test handles
+ // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+ // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+ // after the exception is caught and either report or re-throw the
+ // exception based on the flag's value:
+ //
+ // try {
+ // // Perform the test method.
+ // } catch (...) {
+ // if (GTEST_FLAG(catch_exceptions))
+ // // Report the exception as failure.
+ // else
+ // throw; // Re-throws the original exception.
+ // }
+ //
+ // However, the purpose of this flag is to allow the program to drop into
+ // the debugger when the exception is thrown. On most platforms, once the
+ // control enters the catch block, the exception origin information is
+ // lost and the debugger will stop the program at the point of the
+ // re-throw in this function -- instead of at the point of the original
+ // throw statement in the code under test. For this reason, we perform
+ // the check early, sacrificing the ability to affect Google Test's
+ // exception handling in the method where the exception is thrown.
+ if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+ try {
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+ } catch (const GoogleTestFailureException&) { // NOLINT
+ // This exception doesn't originate in code under test. It makes no
+ // sense to report it as a test failure.
+ throw;
+ } catch (const std::exception& e) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(e.what(), location));
+ } catch (...) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(NULL, location));
}
+ return static_cast<Result>(0);
+#else
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif // GTEST_HAS_EXCEPTIONS
+ } else {
+ return (object->*method)();
}
+}
- // However, we want to clean up as much as possible. Hence we will
- // always call TearDown(), even if SetUp() or the test body has
- // failed.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TearDown();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "TearDown()");
- }
+} // namespace internal
-#else // We are on a compiler or platform that doesn't support SEH.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- SetUp();
+// Runs the test and updates the test result.
+void Test::Run() {
+ if (!HasSameFixtureClass()) return;
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
// We will run the test only if SetUp() was successful.
if (!HasFatalFailure()) {
impl->os_stack_trace_getter()->UponLeavingGTest();
- TestBody();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TestBody, "the test body");
}
// However, we want to clean up as much as possible. Hence we will
// always call TearDown(), even if SetUp() or the test body has
// failed.
impl->os_stack_trace_getter()->UponLeavingGTest();
- TearDown();
-#endif // GTEST_HAS_SEH
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TearDown, "TearDown()");
}
-
// Returns true iff the current test has a fatal failure.
bool Test::HasFatalFailure() {
return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
@@ -2118,22 +2184,28 @@ bool Test::HasNonfatalFailure() {
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
-// object via impl_.
+// object.
+// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s
+// to signify they cannot be NULLs.
TestInfo::TestInfo(const char* a_test_case_name,
const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
+ const char* a_type_param,
+ const char* a_value_param,
internal::TypeId fixture_class_id,
- internal::TestFactoryBase* factory) {
- impl_ = new internal::TestInfoImpl(this, a_test_case_name, a_name,
- a_test_case_comment, a_comment,
- fixture_class_id, factory);
-}
+ internal::TestFactoryBase* factory)
+ : test_case_name_(a_test_case_name),
+ name_(a_name),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+ value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+ fixture_class_id_(fixture_class_id),
+ should_run_(false),
+ is_disabled_(false),
+ matches_filter_(false),
+ factory_(factory),
+ result_() {}
// Destructs a TestInfo object.
-TestInfo::~TestInfo() {
- delete impl_;
-}
+TestInfo::~TestInfo() { delete factory_; }
namespace internal {
@@ -2144,10 +2216,10 @@ namespace internal {
//
// test_case_name: name of the test case
// name: name of the test
-// test_case_comment: a comment on the test case that will be included in
-// the test output
-// comment: a comment on the test that will be included in the
-// test output
+// type_param: the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param: text representation of the test's value parameter,
+// or NULL if this is not a value-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
@@ -2156,13 +2228,14 @@ namespace internal {
// ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
TestFactoryBase* factory) {
TestInfo* const test_info =
- new TestInfo(test_case_name, name, test_case_comment, comment,
+ new TestInfo(test_case_name, name, type_param, value_param,
fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info;
@@ -2189,41 +2262,6 @@ void ReportInvalidTestCaseType(const char* test_case_name,
} // namespace internal
-// Returns the test case name.
-const char* TestInfo::test_case_name() const {
- return impl_->test_case_name();
-}
-
-// Returns the test name.
-const char* TestInfo::name() const {
- return impl_->name();
-}
-
-// Returns the test case comment.
-const char* TestInfo::test_case_comment() const {
- return impl_->test_case_comment();
-}
-
-// Returns the test comment.
-const char* TestInfo::comment() const {
- return impl_->comment();
-}
-
-// Returns true if this test should run.