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:
zhanyong.wan
2010-08-09 18:19:15 +00:00
parent 7c598c4f1a
commit 5c4b472bbf
13 changed files with 936 additions and 589 deletions

View File

@@ -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;
}

View File

@@ -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