Makes gtest print enums as integers instead of hex dumps (by Zhanyong Wan); improves the hex dump format (by Zhanyong Wan); gets rid of class TestInfoImpl (by Zhanyong Wan); adds exception handling (by Vlad Losev).
This commit is contained in:
parent
7c598c4f1a
commit
5c4b472bbf
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
434
src/gtest.cc
434
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;
|
||||
}
|
||||
|
||||
#if GTEST_HAS_SEH
|
||||
|
||||
// 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
|
||||
__try {
|
||||
return (object->*method)();
|
||||
} __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
|
||||
GetExceptionCode())) {
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Runs the test and updates the test result.
|
||||
void Test::Run() {
|
||||
if (!HasSameFixtureClass()) return;
|
||||
|
||||
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
|
||||
#if GTEST_HAS_SEH
|
||||
// Catch SEH-style exceptions.
|
||||
impl->os_stack_trace_getter()->UponLeavingGTest();
|
||||
__try {
|
||||
SetUp();
|
||||
} __except(internal::UnitTestOptions::GTestShouldProcessSEH(
|
||||
GetExceptionCode())) {
|
||||
AddExceptionThrownFailure(GetExceptionCode(), "SetUp()");
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
// 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()");
|
||||
}
|
||||
|
||||
#else // We are on a compiler or platform that doesn't support SEH.
|
||||
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 {};
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
203
test/gtest_catch_exceptions_test.py
Executable file
203
test/gtest_catch_exceptions_test.py
Executable file
@ -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()
|
299
test/gtest_catch_exceptions_test_.cc
Normal file
299
test/gtest_catch_exceptions_test_.cc
Normal file
@ -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();
|
||||
}
|
@ -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.
|
||||
|
@ -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.*
|
||||
|
@ -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)");
|
||||
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(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");
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user