summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt14
-rw-r--r--include/gtest/gtest-printers.h56
-rw-r--r--include/gtest/gtest.h90
-rw-r--r--src/gtest-internal-inl.h89
-rw-r--r--src/gtest-printers.cc7
-rw-r--r--src/gtest.cc426
-rw-r--r--test/gtest-death-test_test.cc11
-rw-r--r--test/gtest-printers_test.cc82
-rwxr-xr-xtest/gtest_catch_exceptions_test.py203
-rw-r--r--test/gtest_catch_exceptions_test_.cc299
-rw-r--r--test/gtest_output_test_.cc131
-rw-r--r--test/gtest_output_test_golden_win.txt49
-rw-r--r--test/gtest_unittest.cc62
13 files changed, 933 insertions, 586 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4a978a1..316d257 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -142,6 +142,8 @@ if (gtest_build_tests)
cxx_library(gtest_no_exception "${cxx_no_exception}"
src/gtest-all.cc)
+ cxx_library(gtest_main_no_exception "${cxx_no_exception}"
+ src/gtest-all.cc src/gtest_main.cc)
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
src/gtest-all.cc src/gtest_main.cc)
@@ -180,6 +182,18 @@ if (gtest_build_tests)
cxx_executable(gtest_break_on_failure_unittest_ test gtest)
py_test(gtest_break_on_failure_unittest)
+ cxx_executable_with_flags(
+ gtest_catch_exceptions_no_ex_test_
+ "${cxx_no_exception}"
+ gtest_main_no_exception
+ test/gtest_catch_exceptions_test_.cc)
+ cxx_executable_with_flags(
+ gtest_catch_exceptions_ex_test_
+ "${cxx_exception}"
+ gtest_main
+ test/gtest_catch_exceptions_test_.cc)
+ py_test(gtest_catch_exceptions_test)
+
cxx_executable(gtest_color_test_ test gtest)
py_test(gtest_color_test)
diff --git a/include/gtest/gtest-printers.h b/include/gtest/gtest-printers.h
index 0676269..68e7eb1 100644
--- a/include/gtest/gtest-printers.h
+++ b/include/gtest/gtest-printers.h
@@ -115,16 +115,23 @@ GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
size_t count,
::std::ostream* os);
-// TypeWithoutFormatter<T, kIsProto>::PrintValue(value, os) is called
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+ kProtobuf, // a protobuf type
+ kConvertibleToInteger, // a type implicitly convertible to BiggestInt
+ // (e.g. a named or unnamed enum type)
+ kOtherType, // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
// by the universal printer to print a value of type T when neither
-// operator<< nor PrintTo() is defined for type T. When T is
-// ProtocolMessage, proto2::Message, or a subclass of those, kIsProto
-// will be true and the short debug string of the protocol message
-// value will be printed; otherwise kIsProto will be false and the
-// bytes in the value will be printed.
-template <typename T, bool kIsProto>
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
class TypeWithoutFormatter {
public:
+ // This default version is called when kTypeKind is kOtherType.
static void PrintValue(const T& value, ::std::ostream* os) {
PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
sizeof(value), os);
@@ -137,22 +144,39 @@ class TypeWithoutFormatter {
const size_t kProtobufOneLinerMaxLength = 50;
template <typename T>
-class TypeWithoutFormatter<T, true> {
+class TypeWithoutFormatter<T, kProtobuf> {
public:
static void PrintValue(const T& value, ::std::ostream* os) {
const ::testing::internal::string short_str = value.ShortDebugString();
const ::testing::internal::string pretty_str =
short_str.length() <= kProtobufOneLinerMaxLength ?
short_str : ("\n" + value.DebugString());
- ::std::operator<<(*os, "<" + pretty_str + ">");
+ *os << ("<" + pretty_str + ">");
+ }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+ // Since T has no << operator or PrintTo() but can be implicitly
+ // converted to BiggestInt, we print it as a BiggestInt.
+ //
+ // Most likely T is an enum type (either named or unnamed), in which
+ // case printing it as an integer is the desired behavior. In case
+ // T is not an enum, printing it as an integer is the best we can do
+ // given that it has no user-defined printer.
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ const internal::BiggestInt kBigInt = value;
+ *os << kBigInt;
}
};
// Prints the given value to the given ostream. If the value is a
-// protocol message, its short debug string is printed; otherwise the
-// bytes in the value are printed. This is what
-// UniversalPrinter<T>::Print() does when it knows nothing about type
-// T and T has no << operator.
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed. This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
//
// A user can override this behavior for a class type Foo by defining
// a << operator in the namespace where Foo is defined.
@@ -174,8 +198,10 @@ class TypeWithoutFormatter<T, true> {
template <typename Char, typename CharTraits, typename T>
::std::basic_ostream<Char, CharTraits>& operator<<(
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
- TypeWithoutFormatter<T, ::testing::internal::IsAProtocolMessage<T>::value>::
- PrintValue(x, &os);
+ TypeWithoutFormatter<T,
+ (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+ internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+ kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
return os;
}
diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h
index af9d9e7..20028a1 100644
--- a/include/gtest/gtest.h
+++ b/include/gtest/gtest.h
@@ -148,7 +148,6 @@ class ExecDeathTest;
class NoExecDeathTest;
class FinalSuccessChecker;
class GTestFlagSaver;
-class TestInfoImpl;
class TestResultAccessor;
class TestEventListenersAccessor;
class TestEventRepeater;
@@ -341,7 +340,7 @@ GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
// Test is not copyable.
class GTEST_API_ Test {
public:
- friend class internal::TestInfoImpl;
+ friend class TestInfo;
// Defines types for pointers to functions that set up and tear down
// a test case.
@@ -418,6 +417,10 @@ class GTEST_API_ Test {
// Sets up, executes, and tears down the test.
void Run();
+ // Deletes self. We deliberately pick an unusual name for this
+ // internal method to avoid clashing with names used in user TESTs.
+ void DeleteSelf_() { delete this; }
+
// Uses a GTestFlagSaver to save and restore all Google Test flags.
const internal::GTestFlagSaver* const gtest_flag_saver_;
@@ -532,7 +535,6 @@ class GTEST_API_ TestResult {
friend class UnitTest;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::ExecDeathTest;
- friend class internal::TestInfoImpl;
friend class internal::TestResultAccessor;
friend class internal::UnitTestImpl;
friend class internal::WindowsDeathTest;
@@ -612,16 +614,16 @@ class GTEST_API_ TestInfo {
~TestInfo();
// Returns the test case name.
- const char* test_case_name() const;
+ const char* test_case_name() const { return test_case_name_.c_str(); }
// Returns the test name.
- const char* name() const;
+ const char* name() const { return name_.c_str(); }
// Returns the test case comment.
- const char* test_case_comment() const;
+ const char* test_case_comment() const { return test_case_comment_.c_str(); }
// Returns the test comment.
- const char* comment() const;
+ const char* comment() const { return comment_.c_str(); }
// Returns true if this test should run, that is if the test is not disabled
// (or it is disabled but the also_run_disabled_tests flag has been specified)
@@ -639,10 +641,10 @@ class GTEST_API_ TestInfo {
//
// For example, *A*:Foo.* is a filter that matches any string that
// contains the character 'A' or starts with "Foo.".
- bool should_run() const;
+ bool should_run() const { return should_run_; }
// Returns the result of the test.
- const TestResult* result() const;
+ const TestResult* result() const { return &result_; }
private:
#if GTEST_HAS_DEATH_TEST
@@ -650,7 +652,6 @@ class GTEST_API_ TestInfo {
#endif // GTEST_HAS_DEATH_TEST
friend class Test;
friend class TestCase;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
friend TestInfo* internal::MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
@@ -660,17 +661,6 @@ class GTEST_API_ TestInfo {
Test::TearDownTestCaseFunc tear_down_tc,
internal::TestFactoryBase* factory);
- // Returns true if this test matches the user-specified filter.
- bool matches_filter() const;
-
- // Increments the number of death tests encountered in this test so
- // far.
- int increment_death_test_count();
-
- // Accessors for the implementation object.
- internal::TestInfoImpl* impl() { return impl_; }
- const internal::TestInfoImpl* impl() const { return impl_; }
-
// Constructs a TestInfo object. The newly constructed instance assumes
// ownership of the factory object.
TestInfo(const char* test_case_name, const char* name,
@@ -678,8 +668,36 @@ class GTEST_API_ TestInfo {
internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory);
- // An opaque implementation object.
- internal::TestInfoImpl* impl_;
+ // Increments the number of death tests encountered in this test so
+ // far.
+ int increment_death_test_count() {
+ return result_.increment_death_test_count();
+ }
+
+ // Creates the test object, runs it, records its result, and then
+ // deletes it.
+ void Run();
+
+ static void ClearTestResult(TestInfo* test_info) {
+ test_info->result_.Clear();
+ }
+
+ // These fields are immutable properties of the test.
+ const std::string test_case_name_; // Test case name
+ const std::string name_; // Test name
+ const std::string test_case_comment_; // Test case comment
+ const std::string comment_; // Test comment
+ const internal::TypeId fixture_class_id_; // ID of the test fixture class
+ bool should_run_; // True iff this test should run
+ bool is_disabled_; // True iff this test is disabled
+ bool matches_filter_; // True if this test matches the
+ // user-specified filter.
+ internal::TestFactoryBase* const factory_; // The factory that creates
+ // the test object
+
+ // This field is mutable and needs to be reset before running the
+ // test for the second time.
+ TestResult result_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
};
@@ -777,17 +795,33 @@ class GTEST_API_ TestCase {
// Runs every test in this TestCase.
void Run();
+ // Runs SetUpTestCase() for this TestCase. This wrapper is needed
+ // for catching exceptions thrown from SetUpTestCase().
+ void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+ // Runs TearDownTestCase() for this TestCase. This wrapper is
+ // needed for catching exceptions thrown from TearDownTestCase().
+ void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
// Returns true iff test passed.
- static bool TestPassed(const TestInfo * test_info);
+ static bool TestPassed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Passed();
+ }
// Returns true iff test failed.
- static bool TestFailed(const TestInfo * test_info);
+ static bool TestFailed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Failed();
+ }
// Returns true iff test is disabled.
- static bool TestDisabled(const TestInfo * test_info);
+ static bool TestDisabled(const TestInfo* test_info) {
+ return test_info->is_disabled_;
+ }
// Returns true if the given test should run.
- static bool ShouldRunTest(const TestInfo *test_info);
+ static bool ShouldRunTest(const TestInfo* test_info) {
+ return test_info->should_run();
+ }
// Shuffles the tests in this test case.
void ShuffleTests(internal::Random* random);
@@ -962,10 +996,10 @@ class GTEST_API_ TestEventListeners {
private:
friend class TestCase;
+ friend class TestInfo;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::NoExecDeathTest;
friend class internal::TestEventListenersAccessor;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
// Returns repeater that broadcasts the TestEventListener events to all
diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h
index c5608c9..d1e0b59 100644
--- a/src/gtest-internal-inl.h
+++ b/src/gtest-internal-inl.h
@@ -340,85 +340,6 @@ class TestPropertyKeyIs {
String key_;
};
-class TestInfoImpl {
- public:
- TestInfoImpl(TestInfo* parent, const char* test_case_name,
- const char* name, const char* test_case_comment,
- const char* comment, TypeId fixture_class_id,
- internal::TestFactoryBase* factory);
- ~TestInfoImpl();
-
- // Returns true if this test should run.
- bool should_run() const { return should_run_; }
-
- // Sets the should_run member.
- void set_should_run(bool should) { should_run_ = should; }
-
- // Returns true if this test is disabled. Disabled tests are not run.
- bool is_disabled() const { return is_disabled_; }
-
- // Sets the is_disabled member.
- void set_is_disabled(bool is) { is_disabled_ = is; }
-
- // Returns true if this test matches the filter specified by the user.
- bool matches_filter() const { return matches_filter_; }
-
- // Sets the matches_filter member.
- void set_matches_filter(bool matches) { matches_filter_ = matches; }
-
- // Returns the test case name.
- const char* test_case_name() const { return test_case_name_.c_str(); }
-
- // Returns the test name.
- const char* name() const { return name_.c_str(); }
-
- // Returns the test case comment.
- const char* test_case_comment() const { return test_case_comment_.c_str(); }
-
- // Returns the test comment.
- const char* comment() const { return comment_.c_str(); }
-
- // Returns the ID of the test fixture class.
- TypeId fixture_class_id() const { return fixture_class_id_; }
-
- // Returns the test result.
- TestResult* result() { return &result_; }
- const TestResult* result() const { return &result_; }
-
- // Creates the test object, runs it, records its result, and then
- // deletes it.
- void Run();
-
- // Clears the test result.
- void ClearResult() { result_.Clear(); }
-
- // Clears the test result in the given TestInfo object.
- static void ClearTestResult(TestInfo * test_info) {
- test_info->impl()->ClearResult();
- }
-
- private:
- // These fields are immutable properties of the test.
- TestInfo* const parent_; // The owner of this object
- const String test_case_name_; // Test case name
- const String name_; // Test name
- const String test_case_comment_; // Test case comment
- const String comment_; // Test comment
- const TypeId fixture_class_id_; // ID of the test fixture class
- bool should_run_; // True iff this test should run
- bool is_disabled_; // True iff this test is disabled
- bool matches_filter_; // True if this test matches the
- // user-specified filter.
- internal::TestFactoryBase* const factory_; // The factory that creates
- // the test object
-
- // This field is mutable and needs to be reset before running the
- // test for the second time.
- TestResult result_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfoImpl);
-};
-
// Class UnitTestOptions.
//
// This class contains functions for processing options the user
@@ -747,12 +668,10 @@ class GTEST_API_ UnitTestImpl {
void RegisterParameterizedTests();
// Runs all tests in this UnitTest object, prints the result, and
- // returns 0 if all tests are successful, or 1 otherwise. If any
- // exception is thrown during a test on Windows, this test is
- // considered to be failed, but the rest of the tests will still be
- // run. (We disable exceptions on Linux and Mac OS X, so the issue
- // doesn't apply there.)
- int RunAllTests();
+ // returns true if all tests are successful. If any exception is
+ // thrown during a test, this test is considered to be failed, but
+ // the rest of the tests will still be run.
+ bool RunAllTests();
// Clears the results of all tests, except the ad hoc tests.
void ClearNonAdHocTestResult() {
diff --git a/src/gtest-printers.cc b/src/gtest-printers.cc
index 1d97b53..07a0d85 100644
--- a/src/gtest-printers.cc
+++ b/src/gtest-printers.cc
@@ -72,9 +72,10 @@ void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
if (i != 0) {
// Organizes the bytes into groups of 2 for easy parsing by
// human.
- if ((j % 2) == 0) {
- *os << " ";
- }
+ if ((j % 2) == 0)
+ *os << ' ';
+ else
+ *os << '-';
}
snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
*os << text;
diff --git a/src/gtest.cc b/src/gtest.cc
index 03799a2..f3768e3 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -495,13 +495,26 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
// 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
@@ -1922,22 +1935,6 @@ void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
} // namespace internal
-#if GTEST_OS_WINDOWS
-// We are on Windows.
-
-// 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_OS_WINDOWS
-
// 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
@@ -1948,15 +1945,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) {
@@ -2006,62 +2001,134 @@ 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
+
+// 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>
+static 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>
+static Result HandleExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+#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
+}
- // 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()");
- }
+// Runs the test and updates the test result.
+void Test::Run() {
+ if (!HasSameFixtureClass()) return;
-#else // We are on a compiler or platform that doesn't support SEH.
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
impl->os_stack_trace_getter()->UponLeavingGTest();
- SetUp();
-
+ HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
// We will run the test only if SetUp() was successful.
if (!HasFatalFailure()) {
impl->os_stack_trace_getter()->UponLeavingGTest();
- TestBody();
+ 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
+ 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();
@@ -2076,22 +2143,26 @@ bool Test::HasNonfatalFailure() {
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
-// object via impl_.
+// object.
TestInfo::TestInfo(const char* a_test_case_name,
const char* a_name,
const char* a_test_case_comment,
const char* a_comment,
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),
+ test_case_comment_(a_test_case_comment),
+ comment_(a_comment),
+ 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 {
@@ -2147,41 +2218,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.
-bool TestInfo::should_run() const { return impl_->should_run(); }
-
-// Returns true if this test matches the user-specified filter.
-bool TestInfo::matches_filter() const { return impl_->matches_filter(); }
-
-// Returns the result of the test.
-const TestResult* TestInfo::result() const { return impl_->result(); }
-
-// Increments the number of death tests encountered in this test so
-// far.
-int TestInfo::increment_death_test_count() {
- return impl_->result()->increment_death_test_count();
-}
-
namespace {
// A predicate that checks the test name of a TestInfo against a known
@@ -2225,70 +2261,54 @@ void UnitTestImpl::RegisterParameterizedTests() {
#endif
}
+} // namespace internal
+
// Creates the test object, runs it, records its result, and then
// deletes it.
-void TestInfoImpl::Run() {
+void TestInfo::Run() {
if (!should_run_) return;
// Tells UnitTest where to store test result.
- UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_info(parent_);
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_info(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
// Notifies the unit test event listeners that a test is about to start.
- repeater->OnTestStart(*parent_);
+ repeater->OnTestStart(*this);
- const TimeInMillis start = GetTimeInMillis();
+ const TimeInMillis start = internal::GetTimeInMillis();
impl->os_stack_trace_getter()->UponLeavingGTest();
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
- Test* test = NULL;
-
- __try {
- // Creates the test object.
- test = factory_->CreateTest();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(),
- "the test fixture's constructor");
- return;
- }
-#else // We are on a compiler or platform that doesn't support SEH.
-
- // TODO(wan): If test->Run() throws, test won't be deleted. This is
- // not a problem now as we don't use exceptions. If we were to
- // enable exceptions, we should revise the following to be
- // exception-safe.
// Creates the test object.
- Test* test = factory_->CreateTest();
-#endif // GTEST_HAS_SEH
+ Test* const test = HandleExceptionsInMethodIfSupported(
+ factory_, &internal::TestFactoryBase::CreateTest,
+ "the test fixture's constructor");
- // Runs the test only if the constructor of the test fixture didn't
+ // Runs the test only if the test object was created and its constructor didn't
// generate a fatal failure.
- if (!Test::HasFatalFailure()) {
+ if ((test != NULL) && !Test::HasFatalFailure()) {
+ // This doesn't throw as all user code that can throw are wrapped into
+ // exception handling code.
test->Run();
}
// Deletes the test object.
impl->os_stack_trace_getter()->UponLeavingGTest();
- delete test;
- test = NULL;
+ HandleExceptionsInMethodIfSupported(
+ test, &Test::DeleteSelf_, "the test fixture's destructor");
- result_.set_elapsed_time(GetTimeInMillis() - start);
+ result_.set_elapsed_time(internal::GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished.
- repeater->OnTestEnd(*parent_);
+ repeater->OnTestEnd(*this);
// Tells UnitTest to stop associating assertion results to this
// test.
impl->set_current_test_info(NULL);
}
-} // namespace internal
-
// class TestCase
// Gets the number of successful tests in this test case.
@@ -2371,45 +2391,26 @@ void TestCase::Run() {
repeater->OnTestCaseStart(*this);
impl->os_stack_trace_getter()->UponLeavingGTest();
- set_up_tc_();
+ HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
const internal::TimeInMillis start = internal::GetTimeInMillis();
for (int i = 0; i < total_test_count(); i++) {
- GetMutableTestInfo(i)->impl()->Run();
+ GetMutableTestInfo(i)->Run();
}
elapsed_time_ = internal::GetTimeInMillis() - start;
impl->os_stack_trace_getter()->UponLeavingGTest();
- tear_down_tc_();
+ HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
repeater->OnTestCaseEnd(*this);
impl->set_current_test_case(NULL);
}
// Clears the results of all tests in this test case.
void TestCase::ClearResult() {
- ForEach(test_info_list_, internal::TestInfoImpl::ClearTestResult);
-}
-
-// Returns true iff test passed.
-bool TestCase::TestPassed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Passed();
-}
-
-// Returns true iff test failed.
-bool TestCase::TestFailed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Failed();
-}
-
-// Returns true iff test is disabled.
-bool TestCase::TestDisabled(const TestInfo * test_info) {
- return test_info->impl()->is_disabled();
-}
-
-// Returns true if the given test should run.
-bool TestCase::ShouldRunTest(const TestInfo *test_info) {
- return test_info->impl()->should_run();
+ ForEach(test_info_list_, TestInfo::ClearTestResult);
}
// Shuffles the tests in this test case.
@@ -3505,19 +3506,6 @@ Environment* UnitTest::AddEnvironment(Environment* env) {
return env;
}
-#if GTEST_HAS_EXCEPTIONS
-// A failed Google Test assertion will throw an exception of this type
-// when 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
-
// Adds a TestPartResult to the current TestResult object. All Google Test
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
// this to report their results. The user code should use the
@@ -3640,20 +3628,12 @@ int UnitTest::Run() {
_WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
#endif
}
-
- __try {
- return impl_->RunAllTests();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- printf("Exception thrown with code 0x%x.\nFAIL\n", GetExceptionCode());
- fflush(stdout);
- return 1;
- }
-
-#else // We are on a compiler or platform that doesn't support SEH.
-
- return impl_->RunAllTests();
#endif // GTEST_HAS_SEH
+
+ return HandleExceptionsInMethodIfSupported(
+ impl_,
+ &internal::UnitTestImpl::RunAllTests,
+ "auxiliary test code (environments or event listeners)") ? 0 : 1;
}
// Returns the working directory when the first TEST() or TEST_F() was
@@ -3890,27 +3870,26 @@ static void SetUpEnvironment(Environment* env) { env->SetUp(); }
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
// Runs all tests in this UnitTest object, prints the result, and
-// returns 0 if all tests are successful, or 1 otherwise. If any
-// exception is thrown during a test on Windows, this test is
-// considered to be failed, but the rest of the tests will still be
-// run. (We disable exceptions on Linux and Mac OS X, so the issue
-// doesn't apply there.)
+// returns true if all tests are successful. If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
// When parameterized tests are enabled, it expands and registers
// parameterized tests first in RegisterParameterizedTests().
// All other functions called from RunAllTests() may safely assume that
// parameterized tests are ready to be counted and run.
-int UnitTestImpl::RunAllTests() {
+bool UnitTestImpl::RunAllTests() {
// Makes sure InitGoogleTest() was called.
if (!GTestIsInitialized()) {
printf("%s",
"\nThis test program did NOT call ::testing::InitGoogleTest "
"before calling RUN_ALL_TESTS(). Please fix it.\n");
- return 1;
+ return false;
}
// Do not run any test if the --help flag was specified.
if (g_help_flag)
- return 0;
+ return true;
// Repeats the call to the post-flag parsing initialization in case the
// user didn't call InitGoogleTest.
@@ -3942,7 +3921,7 @@ int UnitTestImpl::RunAllTests() {
if (GTEST_FLAG(list_tests)) {
// This must be called *after* FilterTests() has been called.
ListTestsMatchingFilter();
- return 0;
+ return true;
}
random_seed_ = GTEST_FLAG(shuffle) ?
@@ -4028,8 +4007,7 @@ int UnitTestImpl::RunAllTests() {
repeater->OnTestProgramEnd(*parent_);
- // Returns 0 if all tests passed, or 1 other wise.
- return failed ? 1 : 0;
+ return !failed;
}
// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
@@ -4159,12 +4137,12 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
kDisableTestFilter) ||
internal::UnitTestOptions::MatchesFilter(test_name,
kDisableTestFilter);
- test_info->impl()->set_is_disabled(is_disabled);
+ test_info->is_disabled_ = is_disabled;
const bool matches_filter =
internal::UnitTestOptions::FilterMatchesTest(test_case_name,
test_name);
- test_info->impl()->set_matches_filter(matches_filter);
+ test_info->matches_filter_ = matches_filter;
const bool is_runnable =
(GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
@@ -4178,7 +4156,7 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
num_runnable_tests += is_runnable;
num_selected_tests += is_selected;
- test_info->impl()->set_should_run(is_selected);
+ test_info->should_run_ = is_selected;
test_case->set_should_run(test_case->should_run() || is_selected);
}
}
@@ -4194,7 +4172,7 @@ void UnitTestImpl::ListTestsMatchingFilter() {
for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
const TestInfo* const test_info =
test_case->test_info_list()[j];
- if (test_info->matches_filter()) {
+ if (test_info->matches_filter_) {
if (!printed_test_case_name) {
printed_test_case_name = true;
printf("%s.\n", test_case->name());
@@ -4234,7 +4212,7 @@ OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
// the TestResult for the ad hoc test if no test is running.
TestResult* UnitTestImpl::current_test_result() {
return current_test_info_ ?
- current_test_info_->impl()->result() : &ad_hoc_test_result_;
+ &(current_test_info_->result_) : &ad_hoc_test_result_;
}
// Shuffles all test cases, and the tests within each test case,
@@ -4263,32 +4241,6 @@ void UnitTestImpl::UnshuffleTests() {
}
}
-// TestInfoImpl constructor. The new instance assumes ownership of the test
-// factory object.
-TestInfoImpl::TestInfoImpl(TestInfo* parent,
- const char* a_test_case_name,
- const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
- TypeId a_fixture_class_id,
- internal::TestFactoryBase* factory) :
- parent_(parent),
- test_case_name_(String(a_test_case_name)),
- name_(String(a_name)),
- test_case_comment_(String(a_test_case_comment)),
- comment_(String(a_comment)),
- fixture_class_id_(a_fixture_class_id),
- should_run_(false),
- is_disabled_(false),
- matches_filter_(false),
- factory_(factory) {
-}
-
-// TestInfoImpl destructor.
-TestInfoImpl::~TestInfoImpl() {
- delete factory_;
-}
-
// Returns the current OS stack trace as a String.
//
// The maximum number of stack frames to be included is specified by
@@ -4306,8 +4258,8 @@ String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
}
-// Used by the GTEST_HIDE_UNREACHABLE_CODE_ macro to suppress unreachable
-// code warnings.
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
namespace {
class ClassUniqueToAlwaysTrue {};
}
diff --git a/test/gtest-death-test_test.cc b/test/gtest-death-test_test.cc
index ed5b53b..d33cfeb 100644
--- a/test/gtest-death-test_test.cc
+++ b/test/gtest-death-test_test.cc
@@ -614,17 +614,6 @@ TEST(PopUpDeathTest, DoesNotShowPopUpOnAbort) {
abort();
}, "");
}
-
-TEST(PopUpDeathTest, 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
diff --git a/test/gtest-printers_test.cc b/test/gtest-printers_test.cc
index 11f6625..5dec871 100644
--- a/test/gtest-printers_test.cc
+++ b/test/gtest-printers_test.cc
@@ -60,6 +60,42 @@
// Some user-defined types for testing the universal value printer.
+// An anonymous enum type.
+enum AnonymousEnum {
+ kAE1 = -1,
+ kAE2 = 1
+};
+
+// An enum without a user-defined printer.
+enum EnumWithoutPrinter {
+ kEWP1 = -2,
+ kEWP2 = 42
+};
+
+// An enum with a << operator.
+enum EnumWithStreaming {
+ kEWS1 = 10,
+};
+
+std::ostream& operator<<(std::ostream& os, EnumWithStreaming e) {
+ return os << (e == kEWS1 ? "kEWS1" : "invalid");
+}
+
+// An enum with a PrintTo() function.
+enum EnumWithPrintTo {
+ kEWPT1 = 1,
+};
+
+void PrintTo(EnumWithPrintTo e, std::ostream* os) {
+ *os << (e == kEWPT1 ? "kEWPT1" : "invalid");
+}
+
+// A class implicitly convertible to BiggestInt.
+class BiggestIntConvertible {
+ public:
+ operator ::testing::internal::BiggestInt() const { return 42; }
+};
+
// A user-defined unprintable class template in the global namespace.
template <typename T>
class UnprintableTemplateInGlobal {
@@ -207,6 +243,34 @@ string PrintByRef(const T& value) {
return ss.str();
}
+// Tests printing various enum types.
+
+TEST(PrintEnumTest, AnonymousEnum) {
+ EXPECT_EQ("-1", Print(kAE1));
+ EXPECT_EQ("1", Print(kAE2));
+}
+
+TEST(PrintEnumTest, EnumWithoutPrinter) {
+ EXPECT_EQ("-2", Print(kEWP1));
+ EXPECT_EQ("42", Print(kEWP2));
+}
+
+TEST(PrintEnumTest, EnumWithStreaming) {
+ EXPECT_EQ("kEWS1", Print(kEWS1));
+ EXPECT_EQ("invalid", Print(static_cast<EnumWithStreaming>(0)));
+}
+
+TEST(PrintEnumTest, EnumWithPrintTo) {
+ EXPECT_EQ("kEWPT1", Print(kEWPT1));
+ EXPECT_EQ("invalid", Print(static_cast<EnumWithPrintTo>(0)));
+}
+
+// Tests printing a class implicitly convertible to BiggestInt.
+
+TEST(PrintClassTest, BiggestIntConvertible) {
+ EXPECT_EQ("42", Print(BiggestIntConvertible()));
+}
+
// Tests printing various char types.
// char.
@@ -913,7 +977,7 @@ TEST(PrintUnprintableTypeTest, InGlobalNamespace) {
// Unprintable types in a user namespace.
TEST(PrintUnprintableTypeTest, InUserNamespace) {
- EXPECT_EQ("16-byte object <EF12 0000 34AB 0000 0000 0000 0000 0000>",
+ EXPECT_EQ("16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
Print(::foo::UnprintableInFoo()));
}
@@ -925,13 +989,13 @@ struct Big {
};
TEST(PrintUnpritableTypeTest, BigObject) {
- EXPECT_EQ("257-byte object <0000 0000 0000 0000 0000 0000 "
- "0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
- "0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
- "0000 0000 0000 0000 0000 0000 ... 0000 0000 0000 "
- "0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
- "0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 "
- "0000 0000 0000 0000 0000 0000 0000 0000 00>",
+ EXPECT_EQ("257-byte object <00-00 00-00 00-00 00-00 00-00 00-00 "
+ "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+ "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+ "00-00 00-00 00-00 00-00 00-00 00-00 ... 00-00 00-00 00-00 "
+ "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+ "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+ "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00>",
Print(Big()));
}
@@ -1022,7 +1086,7 @@ TEST(PrintReferenceTest, PrintsAddressAndValue) {
const ::foo::UnprintableInFoo x;
EXPECT_EQ("@" + PrintPointer(&x) + " 16-byte object "
- "<EF12 0000 34AB 0000 0000 0000 0000 0000>",
+ "<EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
PrintByRef(x));
}
diff --git a/test/gtest_catch_exceptions_test.py b/test/gtest_catch_exceptions_test.py
new file mode 100755
index 0000000..c4d1756
--- /dev/null
+++ b/test/gtest_catch_exceptions_test.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests Google Test's exception catching behavior.
+
+This script invokes gtest_catch_exceptions_test_ and
+gtest_catch_exceptions_ex_test_ (programs written with
+Google Test) and verifies their output.
+"""
+
+__author__ = 'vladl@google.com (Vlad Losev)'
+
+import os
+
+import gtest_test_utils
+
+# Constants.
+LIST_TESTS_FLAG = '--gtest_list_tests'
+
+# Path to the gtest_catch_exceptions_ex_test_ binary, compiled with
+# exceptions enabled.
+EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+ 'gtest_catch_exceptions_ex_test_')
+
+# Path to the gtest_catch_exceptions_test_ binary, compiled with
+# exceptions disabled.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+ 'gtest_catch_exceptions_no_ex_test_')
+
+TEST_LIST = gtest_test_utils.Subprocess([EXE_PATH, LIST_TESTS_FLAG]).output
+
+SUPPORTS_SEH_EXCEPTIONS = 'ThrowsSehException' in TEST_LIST
+
+if SUPPORTS_SEH_EXCEPTIONS:
+ BINARY_OUTPUT = gtest_test_utils.Subprocess([EXE_PATH]).output
+
+EX_BINARY_OUTPUT = gtest_test_utils.Subprocess([EX_EXE_PATH]).output
+
+
+# The tests.
+if SUPPORTS_SEH_EXCEPTIONS:
+ # pylint:disable-msg=C6302
+ class CatchSehExceptionsTest(gtest_test_utils.TestCase):
+ """Tests exception-catching behavior."""
+
+
+ def TestSehExceptions(self, test_output):
+ self.assert_('SEH exception with code 0x2a thrown '
+ 'in the test fixture\'s constructor'
+ in test_output)
+ self.assert_('SEH exception with code 0x2a thrown '
+ 'in the test fixture\'s destructor'
+ in test_output)
+ self.assert_('SEH exception with code 0x2a thrown in SetUpTestCase()'
+ in test_output)
+ self.assert_('SEH exception with code 0x2a thrown in TearDownTestCase()'
+ in test_output)
+ self.assert_('SEH exception with code 0x2a thrown in SetUp()'
+ in test_output)
+ self.assert_('SEH exception with code 0x2a thrown in TearDown()'
+ in test_output)
+ self.assert_('SEH exception with code 0x2a thrown in the test body'
+ in test_output)
+
+ def testCatchesSehExceptionsWithCxxExceptionsEnabled(self):
+ self.TestSehExceptions(EX_BINARY_OUTPUT)
+
+ def testCatchesSehExceptionsWithCxxExceptionsDisabled(self):
+ self.TestSehExceptions(BINARY_OUTPUT)
+
+
+class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
+ """Tests C++ exception-catching behavior.
+
+ Tests in this test case verify that:
+ * C++ exceptions are caught and logged as C++ (not SEH) exceptions
+ * Exception thrown affect the remainder of the test work flow in the
+ expected manner.
+ """
+
+ def testCatchesCxxExceptionsInFixtureConstructor(self):
+ self.assert_('C++ exception with description '
+ '"Standard C++ exception" thrown '
+ 'in the test fixture\'s constructor'
+ in EX_BINARY_OUTPUT)
+ self.assert_('unexpected' not in EX_BINARY_OUTPUT,
+ 'This failure belongs in this test only if '
+ '"CxxExceptionInConstructorTest" (no quotes) '
+ 'appears on the same line as words "called unexpectedly"')
+
+ def testCatchesCxxExceptionsInFixtureDestructor(self):
+ self.assert_('C++ exception with description '
+ '"Standard C++ exception" thrown '
+ 'in the test fixture\'s destructor'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInDestructorTest::TearDownTestCase() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+
+ def testCatchesCxxExceptionsInSetUpTestCase(self):
+ self.assert_('C++ exception with description "Standard C++ exception"'
+ ' thrown in SetUpTestCase()'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInConstructorTest::TearDownTestCase() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTestCaseTest constructor '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTestCaseTest destructor '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTestCaseTest::SetUp() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTestCaseTest::TearDown() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTestCaseTest test body '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+
+ def testCatchesCxxExceptionsInTearDownTestCase(self):
+ self.assert_('C++ exception with description "Standard C++ exception"'
+ ' thrown in TearDownTestCase()'
+ in EX_BINARY_OUTPUT)
+
+ def testCatchesCxxExceptionsInSetUp(self):
+ self.assert_('C++ exception with description "Standard C++ exception"'
+ ' thrown in SetUp()'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTest::TearDownTestCase() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTest destructor '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInSetUpTest::TearDown() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('unexpected' not in EX_BINARY_OUTPUT,
+ 'This failure belongs in this test only if '
+ '"CxxExceptionInSetUpTest" (no quotes) '
+ 'appears on the same line as words "called unexpectedly"')
+
+ def testCatchesCxxExceptionsInTearDown(self):
+ self.assert_('C++ exception with description "Standard C++ exception"'
+ ' thrown in TearDown()'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInTearDownTest::TearDownTestCase() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInTearDownTest destructor '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+
+ def testCatchesCxxExceptionsInTestBody(self):
+ self.assert_('C++ exception with description "Standard C++ exception"'
+ ' thrown in the test body'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInTestBodyTest::TearDownTestCase() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInTestBodyTest destructor '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+ self.assert_('CxxExceptionInTestBodyTest::TearDown() '
+ 'called as expected.'
+ in EX_BINARY_OUTPUT)
+
+ def testCatchesNonStdCxxExceptions(self):
+ self.assert_('Unknown C++ exception thrown in the test body'
+ in EX_BINARY_OUTPUT)
+
+if __name__ == '__main__':
+ gtest_test_utils.Main()
diff --git a/test/gtest_catch_exceptions_test_.cc b/test/gtest_catch_exceptions_test_.cc
new file mode 100644
index 0000000..8673681
--- /dev/null
+++ b/test/gtest_catch_exceptions_test_.cc
@@ -0,0 +1,299 @@
+// Copyright 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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: vladl@google.com (Vlad Losev)
+//
+// Tests for Google Test itself. Tests in this file throw C++ or SEH
+// exceptions, and the output is verified by gtest_catch_exceptions_test.py.
+
+#include <gtest/gtest.h>
+
+#include <stdio.h> // NOLINT
+
+#if GTEST_HAS_SEH
+#include <windows.h>
+#endif
+
+#if GTEST_HAS_EXCEPTIONS
+#include <stdexcept>
+#endif
+
+using testing::Test;
+using testing::GTEST_FLAG(catch_exceptions);
+
+#if GTEST_HAS_SEH
+
+class SehExceptionInConstructorTest : public Test {
+ public:
+ SehExceptionInConstructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInConstructorTest, ThrowsExceptionInConstructor) {}
+
+class SehExceptionInDestructorTest : public Test {
+ public:
+ ~SehExceptionInDestructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
+
+class SehExceptionInSetUpTestCaseTest : public Test {
+ public:
+ static void SetUpTestCase() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTestCaseTest, ThrowsExceptionInSetUpTestCase) {}
+
+class SehExceptionInTearDownTestCaseTest : public Test {
+ public:
+ static void TearDownTestCase() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTestCaseTest, ThrowsExceptionInTearDownTestCase) {}
+
+class SehExceptionInSetUpTest : public Test {
+ protected:
+ virtual void SetUp() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTest, ThrowsExceptionInSetUp) {}
+
+class SehExceptionInTearDownTest : public Test {
+ protected:
+ virtual void TearDown() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+TEST(SehExceptionTest, ThrowsSehException) {
+ RaiseException(42, 0, 0, NULL);
+}
+
+#endif // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+class CxxExceptionInConstructorTest : public Test {
+ public:
+ CxxExceptionInConstructorTest() {
+ // Without this macro VC++ complains about unreachable code at the end of
+ // the constructor.
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+ throw std::runtime_error("Standard C++ exception"));
+ }
+
+ static void TearDownTestCase() {
+ printf("%s",
+ "CxxExceptionInConstructorTest::TearDownTestCase() "
+ "called as expected.\n");
+ }
+
+ protected:
+ ~CxxExceptionInConstructorTest() {
+ ADD_FAILURE() << "CxxExceptionInConstructorTest destructor "
+ << "called unexpectedly.";
+ }
+
+ virtual void SetUp() {
+ ADD_FAILURE() << "CxxExceptionInConstructorTest::SetUp() "
+ << "called unexpectedly.";
+ }
+
+ virtual void TearDown() {
+ ADD_FAILURE() << "CxxExceptionInConstructorTest::TearDown() "
+ << "called unexpectedly.";
+ }
+};
+
+TEST_F(CxxExceptionInConstructorTest, ThrowsExceptionInConstructor) {
+ ADD_FAILURE() << "CxxExceptionInConstructorTest test body "
+ << "called unexpectedly.";
+}
+
+class CxxExceptionInDestructorTest : public Test {
+ public:
+ static void TearDownTestCase() {
+ printf("%s",
+ "CxxExceptionInDestructorTest::TearDownTestCase() "
+ "called as expected.\n");
+ }
+
+ protected:
+ ~CxxExceptionInDestructorTest() {
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+ throw std::runtime_error("Standard C++ exception"));
+ }
+};
+
+TEST_F(CxxExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
+
+class CxxExceptionInSetUpTestCaseTest : public Test {
+ public:
+ CxxExceptionInSetUpTestCaseTest() {
+ printf("%s",
+ "CxxExceptionInSetUpTestCaseTest constructor "
+ "called as expected.\n");
+ }
+
+ static void SetUpTestCase() {
+ throw std::runtime_error("Standard C++ exception");
+ }
+
+ static void TearDownTestCase() {
+ printf("%s",
+ "CxxExceptionInSetUpTestCaseTest::TearDownTestCase() "
+ "called as expected.\n");
+ }
+
+ protected:
+ ~CxxExceptionInSetUpTestCaseTest() {
+ printf("%s",
+ "CxxExceptionInSetUpTestCaseTest destructor "
+ "called as expected.\n");
+ }
+
+ virtual void SetUp() {
+ printf("%s",
+ "CxxExceptionInSetUpTestCaseTest::SetUp() "
+ "called as expected.\n");
+ }
+
+ virtual void TearDown() {
+ printf("%s",
+ "CxxExceptionInSetUpTestCaseTest::TearDown() "
+ "called as expected.\n");
+ }
+};
+
+TEST_F(CxxExceptionInSetUpTestCaseTest, ThrowsExceptionInSetUpTestCase) {
+ printf("%s",
+ "CxxExceptionInSetUpTestCaseTest test body "
+ "called as expected.\n");
+}
+
+class CxxExceptionInTearDownTestCaseTest : public Test {
+ public:
+ static void TearDownTestCase() {
+ throw std::runtime_error("Standard C++ exception");
+ }
+};
+
+TEST_F(CxxExceptionInTearDownTestCaseTest, ThrowsExceptionInTearDownTestCase) {}
+
+class CxxExceptionInSetUpTest : public Test {
+ public:
+ static void TearDownTestCase() {
+ printf("%s",
+ "CxxExceptionInSetUpTest::TearDownTestCase() "
+ "called as expected.\n");
+ }
+
+ protected:
+ ~CxxExceptionInSetUpTest() {
+ printf("%s",
+ "CxxExceptionInSetUpTest destructor "
+ "called as expected.\n");
+ }
+
+ virtual void SetUp() { throw std::runtime_error("Standard C++ exception"); }
+
+ virtual void TearDown() {
+ printf("%s",
+ "CxxExceptionInSetUpTest::TearDown() "
+ "called as expected.\n");
+ }
+};
+
+TEST_F(CxxExceptionInSetUpTest, ThrowsExceptionInSetUp) {
+ ADD_FAILURE() << "CxxExceptionInSetUpTest test body "
+ << "called unexpectedly.";
+}
+
+class CxxExceptionInTearDownTest : public Test {
+ public:
+ static void TearDownTestCase() {
+ printf("%s",
+ "CxxExceptionInTearDownTest::TearDownTestCase() "
+ "called as expected.\n");
+ }
+
+ protected:
+ ~CxxExceptionInTearDownTest() {
+ printf("%s",
+ "CxxExceptionInTearDownTest destructor "
+ "called as expected.\n");
+ }
+
+ virtual void TearDown() {
+ throw std::runtime_error("Standard C++ exception");
+ }
+};
+
+TEST_F(CxxExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+class CxxExceptionInTestBodyTest : public Test {
+ public:
+ static void TearDownTestCase() {
+ printf("%s",
+ "CxxExceptionInTestBodyTest::TearDownTestCase() "
+ "called as expected.\n");
+ }
+
+ protected:
+ ~CxxExceptionInTestBodyTest() {
+ printf("%s",
+ "CxxExceptionInTestBodyTest destructor "
+ "called as expected.\n");
+ }
+
+ virtual void TearDown() {
+ printf("%s",
+ "CxxExceptionInTestBodyTest::TearDown() "
+ "called as expected.\n");
+ }
+};
+
+TEST_F(CxxExceptionInTestBodyTest, ThrowsStdCxxException) {
+ throw std::runtime_error("Standard C++ exception");
+}
+
+TEST(CxxExceptionTest, ThrowsNonStdCxxException) {
+ throw "C-string";
+}
+
+#endif // GTEST_HAS_EXCEPTIONS
+
+int main(int argc, char** argv) {
+#if GTEST_HAS_SEH
+ // Tells Google Test to catch SEH-style exceptions on Windows.
+ GTEST_FLAG(catch_exceptions) = true;
+#endif
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/gtest_output_test_.cc b/test/gtest_output_test_.cc
index 454e1ba..fc80fac 100644
--- a/test/gtest_output_test_.cc
+++ b/test/gtest_output_test_.cc
@@ -445,137 +445,6 @@ TEST(AddFailureAtTest, MessageContainsSpecifiedFileAndLineNumber) {
ADD_FAILURE_AT("foo.cc", 42) << "Expected failure in foo.cc";
}
-#if GTEST_OS_WINDOWS
-
-// This group of tests verifies that Google Test handles SEH and C++
-// exceptions correctly.
-
-// A function that throws an SEH exception.
-static void ThrowSEH() {
- int* p = NULL;
- *p = 0; // Raises an access violation.
-}
-
-// Tests exceptions thrown in the test fixture constructor.
-class ExceptionInFixtureCtorTest : public testing::Test {
- protected:
- ExceptionInFixtureCtorTest() {
- printf("(expecting a failure on thrown exception "
- "in the test fixture's constructor)\n");
-
- ThrowSEH();
- }
-
- virtual ~ExceptionInFixtureCtorTest() {
- Deinit();
- }
-
- virtual void SetUp() {
- FAIL() << "UNEXPECTED failure in SetUp(). "
- << "We should never get here, as the test fixture c'tor threw.";
- }
-
- virtual void TearDown() {
- FAIL() << "UNEXPECTED failure in TearDown(). "
- << "We should never get here, as the test fixture c'tor threw.";
- }
- private:
- void Deinit() {
- FAIL() << "UNEXPECTED failure in the d'tor. "
- << "We should never get here, as the test fixture c'tor threw.";
- }
-};
-
-TEST_F(ExceptionInFixtureCtorTest, ExceptionInFixtureCtor) {
- FAIL() << "UNEXPECTED failure in the test function. "
- << "We should never get here, as the test fixture c'tor threw.";
-}
-
-// Tests exceptions thrown in SetUp().
-class ExceptionInSetUpTest : public testing::Test {
- protected:
- virtual ~ExceptionInSetUpTest() {
- Deinit();
- }
-
- virtual void SetUp() {
- printf("(expecting 3 failures)\n");
-
- ThrowSEH();
- }
-
- virtual void TearDown() {
- FAIL() << "Expected failure #2, in TearDown().";
- }
- private:
- void Deinit() {
- FAIL() << "Expected failure #3, in the test fixture d'tor.";
- }
-};
-
-TEST_F(ExceptionInSetUpTest, ExceptionInSetUp) {
- FAIL() << "UNEXPECTED failure in the test function. "
- << "We should never get here, as SetUp() threw.";
-}
-
-// Tests that TearDown() and the test fixture d'tor are always called,
-// even when the test function throws an exception.
-class ExceptionInTestFunctionTest : public testing::Test {
- protected:
- virtual ~ExceptionInTestFunctionTest() {
- Deinit();
- }
-
- virtual void TearDown() {
- FAIL() << "Expected failure #2, in TearDown().";
- }
- private:
- void Deinit() {
- FAIL() << "Expected failure #3, in the test fixture d'tor.";
- }
-};
-
-// Tests that the test fixture d'tor is always called, even when the
-// test function throws an SEH exception.
-TEST_F(ExceptionInTestFunctionTest, SEH) {
- printf("(expecting 3 failures)\n");
-
- ThrowSEH();
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-// Tests that the test fixture d'tor is always called, even when the
-// test function throws a C++ exception. We do this only when
-// GTEST_HAS_EXCEPTIONS is non-zero, i.e. C++ exceptions are enabled.
-TEST_F(ExceptionInTestFunctionTest, CppException) {
- throw 1;
-}
-
-// Tests exceptions thrown in TearDown().
-class ExceptionInTearDownTest : public testing::Test {
- protected:
- virtual ~ExceptionInTearDownTest() {
- Deinit();
- }
-
- virtual void TearDown() {
- throw 1;
- }
- private:
- void Deinit() {
- FAIL() << "Expected failure #2, in the test fixture d'tor.";
- }
-};
-
-TEST_F(ExceptionInTearDownTest, ExceptionInTearDown) {
- printf("(expecting 2 failures)\n");
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-#endif // GTEST_OS_WINDOWS
-
#if GTEST_IS_THREADSAFE
// A unary function that may die.
diff --git a/test/gtest_output_test_golden_win.txt b/test/gtest_output_test_golden_win.txt
index 135f39e..8251c23 100644
--- a/test/gtest_output_test_golden_win.txt
+++ b/test/gtest_output_test_golden_win.txt
@@ -5,7 +5,7 @@ gtest_output_test_.cc:#: error: Value of: false
Expected: true
gtest_output_test_.cc:#: error: Value of: 3
Expected: 2
-[==========] Running 63 tests from 29 test cases.
+[==========] Running 58 tests from 25 test cases.
[----------] Global test environment set-up.
FooEnvironment::SetUp() called.
BarEnvironment::SetUp() called.
@@ -178,42 +178,6 @@ Expected failure #3, in the test fixture d'tor.
foo.cc(42): error: Failed
Expected failure in foo.cc
[ FAILED ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
-[----------] 1 test from ExceptionInFixtureCtorTest
-[ RUN ] ExceptionInFixtureCtorTest.ExceptionInFixtureCtor
-(expecting a failure on thrown exception in the test fixture's constructor)
-unknown file: error: Exception thrown with code 0xc0000005 in the test fixture's constructor.
-[----------] 1 test from ExceptionInSetUpTest
-[ RUN ] ExceptionInSetUpTest.ExceptionInSetUp
-(expecting 3 failures)
-unknown file: error: Exception thrown with code 0xc0000005 in SetUp().
-gtest_output_test_.cc:#: error: Failed
-Expected failure #2, in TearDown().
-gtest_output_test_.cc:#: error: Failed
-Expected failure #3, in the test fixture d'tor.
-[ FAILED ] ExceptionInSetUpTest.ExceptionInSetUp
-[----------] 2 tests from ExceptionInTestFunctionTest
-[ RUN ] ExceptionInTestFunctionTest.SEH
-(expecting 3 failures)
-unknown file: error: Exception thrown with code 0xc0000005 in the test body.
-gtest_output_test_.cc:#: error: Failed
-Expected failure #2, in TearDown().
-gtest_output_test_.cc:#: error: Failed
-Expected failure #3, in the test fixture d'tor.
-[ FAILED ] ExceptionInTestFunctionTest.SEH
-[ RUN ] ExceptionInTestFunctionTest.CppException
-unknown file: error: Exception thrown with code 0xe06d7363 in the test body.
-gtest_output_test_.cc:#: error: Failed
-Expected failure #2, in TearDown().
-gtest_output_test_.cc:#: error: Failed
-Expected failure #3, in the test fixture d'tor.
-[ FAILED ] ExceptionInTestFunctionTest.CppException
-[----------] 1 test from ExceptionInTearDownTest
-[ RUN ] ExceptionInTearDownTest.ExceptionInTearDown
-(expecting 2 failures)
-unknown file: error: Exception thrown with code 0xe06d7363 in TearDown().
-gtest_output_test_.cc:#: error: Failed
-Expected failure #2, in the test fixture d'tor.
-[ FAILED ] ExceptionInTearDownTest.ExceptionInTearDown
[----------] 4 tests from MixedUpTestCaseTest
[ RUN ] MixedUpTestCaseTest.FirstTestFromNamespaceFoo
[ OK ] MixedUpTestCaseTest.FirstTestFromNamespaceFoo
@@ -497,9 +461,9 @@ Expected non-fatal failure.
FooEnvironment::TearDown() called.
gtest_output_test_.cc:#: error: Failed
Expected fatal failure.
-[==========] 63 tests from 29 test cases ran.
+[==========] 58 tests from 25 test cases ran.
[ PASSED ] 21 tests.
-[ FAILED ] 42 tests, listed below:
+[ FAILED ] 37 tests, listed below:
[ FAILED ] FatalFailureTest.FatalFailureInSubroutine
[ FAILED ] FatalFailureTest.FatalFailureInNestedSubroutine
[ FAILED ] FatalFailureTest.NonfatalFailureInSubroutine
@@ -514,11 +478,6 @@ Expected fatal failure.
[ FAILED ] NonFatalFailureInSetUpTest.FailureInSetUp
[ FAILED ] FatalFailureInSetUpTest.FailureInSetUp
[ FAILED ] AddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
-[ FAILED ] ExceptionInFixtureCtorTest.ExceptionInFixtureCtor
-[ FAILED ] ExceptionInSetUpTest.ExceptionInSetUp
-[ FAILED ] ExceptionInTestFunctionTest.SEH
-[ FAILED ] ExceptionInTestFunctionTest.CppException
-[ FAILED ] ExceptionInTearDownTest.ExceptionInTearDown
[ FAILED ] MixedUpTestCaseTest.ThisShouldFail
[ FAILED ] MixedUpTestCaseTest.ThisShouldFailToo
[ FAILED ] MixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
@@ -543,7 +502,7 @@ Expected fatal failure.
[ FAILED ] ExpectFailureTest.ExpectNonFatalFailureOnAllThreads
[ FAILED ] PrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
-42 FAILED TESTS
+37 FAILED TESTS
YOU HAVE 1 DISABLED TEST
Note: Google Test filter = FatalFailureTest.*:LoggingTest.*
diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc
index 910d4e2..9b95b13 100644
--- a/test/gtest_unittest.cc
+++ b/test/gtest_unittest.cc
@@ -3767,6 +3767,17 @@ TEST(AssertionTest, ExpectWorksWithUncopyableObject) {
"Value of: y\n Actual: -1\nExpected: x\nWhich is: 5");
}
+enum NamedEnum {
+ kE1 = 0,
+ kE2 = 1,
+};
+
+TEST(AssertionTest, NamedEnum) {
+ EXPECT_EQ(kE1, kE1);
+ EXPECT_LT(kE1, kE2);
+ EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Which is: 0");
+ EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Actual: 1");
+}
// The version of gcc used in XCode 2.2 has a bug and doesn't allow
// anonymous enums in assertions. Therefore the following test is not
@@ -3776,7 +3787,7 @@ TEST(AssertionTest, ExpectWorksWithUncopyableObject) {
// Tests using assertions with anonymous enums.
enum {
- CASE_A = -1,
+ kCaseA = -1,
#if GTEST_OS_LINUX
// We want to test the case where the size of the anonymous enum is
// larger than sizeof(int), to make sure our implementation of the
@@ -3784,37 +3795,44 @@ enum {
// (incorrectly) doesn't allow an enum value to exceed the range of
// an int, so this has to be conditionally compiled.
//
- // On Linux, CASE_B and CASE_A have the same value when truncated to
+ // On Linux, kCaseB and kCaseA have the same value when truncated to
// int size. We want to test whether this will confuse the
// assertions.
- CASE_B = testing::internal::kMaxBiggestInt,
+ kCaseB = testing::internal::kMaxBiggestInt,
#else
- CASE_B = INT_MAX,
+ kCaseB = INT_MAX,
#endif // GTEST_OS_LINUX
+ kCaseC = 42,
};
TEST(AssertionTest, AnonymousEnum) {
#if GTEST_OS_LINUX
- EXPECT_EQ(static_cast<int>(CASE_A), static_cast<int>(CASE_B));
+ EXPECT_EQ(static_cast<int>(kCaseA), static_cast<int>(kCaseB));
#endif // GTEST_OS_LINUX
- EXPECT_EQ(CASE_A, CASE_A);
- EXPECT_NE(CASE_A, CASE_B);
- EXPECT_LT(CASE_A, CASE_B);
- EXPECT_LE(CASE_A, CASE_B);
- EXPECT_GT(CASE_B, CASE_A);
- EXPECT_GE(CASE_A, CASE_A);
- EXPECT_NONFATAL_FAILURE(EXPECT_GE(CASE_A, CASE_B),
- "(CASE_A) >= (CASE_B)");
-
- ASSERT_EQ(CASE_A, CASE_A);
- ASSERT_NE(CASE_A, CASE_B);
- ASSERT_LT(CASE_A, CASE_B);
- ASSERT_LE(CASE_A, CASE_B);
- ASSERT_GT(CASE_B, CASE_A);
- ASSERT_GE(CASE_A, CASE_A);
- EXPECT_FATAL_FAILURE(ASSERT_EQ(CASE_A, CASE_B),
- "Value of: CASE_B");
+ EXPECT_EQ(kCaseA, kCaseA);
+ EXPECT_NE(kCaseA, kCaseB);
+ EXPECT_LT(kCaseA, kCaseB);
+ EXPECT_LE(kCaseA, kCaseB);
+ EXPECT_GT(kCaseB, kCaseA);
+ EXPECT_GE(kCaseA, kCaseA);
+ EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseB),
+ "(kCaseA) >= (kCaseB)");
+ EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseC),
+ "-1 vs 42");
+
+ ASSERT_EQ(kCaseA, kCaseA);
+ ASSERT_NE(kCaseA, kCaseB);
+ ASSERT_LT(kCaseA, kCaseB);
+ ASSERT_LE(kCaseA, kCaseB);
+ ASSERT_GT(kCaseB, kCaseA);
+ ASSERT_GE(kCaseA, kCaseA);
+ EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseB),
+ "Value of: kCaseB");
+ EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
+ "Actual: 42");
+ EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
+ "Which is: -1");
}
#endif // !GTEST_OS_MAC && !defined(__SUNPRO_CC)