Changes test creation functions to factories. By Vlad Losev.

This commit is contained in:
shiqian 2008-08-06 21:44:19 +00:00
parent 9b093c1779
commit d5f13d4a25
5 changed files with 61 additions and 32 deletions

View File

@ -24,4 +24,5 @@ Russ Rufer <russ@pentad.com>
Sean Mcafee <eefacm@gmail.com> Sean Mcafee <eefacm@gmail.com>
Sigurður Ásgeirsson <siggi@google.com> Sigurður Ásgeirsson <siggi@google.com>
Tracy Bialik <tracy@pentad.com> Tracy Bialik <tracy@pentad.com>
Vlad Losev <vladl@google.com>
Zhanyong Wan <wan@google.com> Zhanyong Wan <wan@google.com>

View File

@ -310,11 +310,6 @@ class Test {
}; };
// Defines the type of a function pointer that creates a Test object
// when invoked.
typedef Test* (*TestMaker)();
// A TestInfo object stores the following information about a test: // A TestInfo object stores the following information about a test:
// //
// Test case name // Test case name
@ -342,7 +337,9 @@ class TestInfo {
// fixture_class_id: ID of the test fixture class // fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case // set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case // tear_down_tc: pointer to the function that tears down the test case
// maker: pointer to the function that creates a test object // factory: Pointer to the factory that creates a test object.
// The newly created TestInfo instance will assume
// ownershi pof the factory object.
// //
// This is public only because it's needed by the TEST and TEST_F macros. // This is public only because it's needed by the TEST and TEST_F macros.
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
@ -352,7 +349,7 @@ class TestInfo {
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
Test::SetUpTestCaseFunc set_up_tc, Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc, Test::TearDownTestCaseFunc tear_down_tc,
TestMaker maker); internal::TestFactoryBase* factory);
// Returns the test case name. // Returns the test case name.
const char* test_case_name() const; const char* test_case_name() const;
@ -395,9 +392,11 @@ class TestInfo {
internal::TestInfoImpl* impl() { return impl_; } internal::TestInfoImpl* impl() { return impl_; }
const internal::TestInfoImpl* impl() const { return impl_; } const internal::TestInfoImpl* impl() const { return impl_; }
// Constructs a TestInfo object. // Constructs a TestInfo object. The newly constructed instance assumes
// ownership of the factory object.
TestInfo(const char* test_case_name, const char* name, TestInfo(const char* test_case_name, const char* name,
internal::TypeId fixture_class_id, TestMaker maker); internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory);
// An opaque implementation object. // An opaque implementation object.
internal::TestInfoImpl* impl_; internal::TestInfoImpl* impl_;

View File

@ -98,6 +98,7 @@ namespace testing {
// Forward declaration of classes. // Forward declaration of classes.
class Message; // Represents a failure message. class Message; // Represents a failure message.
class Test; // Represents a test.
class TestCase; // A collection of related tests. class TestCase; // A collection of related tests.
class TestPartResult; // Result of a test part. class TestPartResult; // Result of a test part.
class TestInfo; // Information about a test. class TestInfo; // Information about a test.
@ -484,6 +485,31 @@ inline TypeId GetTypeId() {
return &dummy; return &dummy;
} }
// Defines the abstract factory interface that creates instances
// of a Test object.
class TestFactoryBase {
public:
virtual ~TestFactoryBase() {}
// Creates a test instance to run. The instance is both created and destroyed
// within TestInfoImpl::Run()
virtual Test* CreateTest() = 0;
protected:
TestFactoryBase() {}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN(TestFactoryBase);
};
// This class provides implementation of TeastFactoryBase interface.
// It is used in TEST and TEST_F macros.
template <class TestClass>
class TestFactoryImpl : public TestFactoryBase {
public:
virtual Test* CreateTest() { return new TestClass; }
};
#ifdef GTEST_OS_WINDOWS #ifdef GTEST_OS_WINDOWS
// Predicate-formatters for implementing the HRESULT checking macros // Predicate-formatters for implementing the HRESULT checking macros
@ -523,9 +549,6 @@ AssertionResult IsHRESULTFailure(const char* expr, long hr); // NOLINT
class test_case_name##_##test_name##_Test : public parent_class {\ class test_case_name##_##test_name##_Test : public parent_class {\
public:\ public:\
test_case_name##_##test_name##_Test() {}\ test_case_name##_##test_name##_Test() {}\
static ::testing::Test* NewTest() {\
return new test_case_name##_##test_name##_Test;\
}\
private:\ private:\
virtual void TestBody();\ virtual void TestBody();\
static ::testing::TestInfo* const test_info_;\ static ::testing::TestInfo* const test_info_;\
@ -533,13 +556,14 @@ class test_case_name##_##test_name##_Test : public parent_class {\
};\ };\
\ \
::testing::TestInfo* const test_case_name##_##test_name##_Test::test_info_ =\ ::testing::TestInfo* const test_case_name##_##test_name##_Test::test_info_ =\
::testing::TestInfo::MakeAndRegisterInstance(\ ::testing::TestInfo::MakeAndRegisterInstance(\
#test_case_name, \ #test_case_name, \
#test_name, \ #test_name, \
::testing::internal::GetTypeId< parent_class >(), \ ::testing::internal::GetTypeId< parent_class >(), \
parent_class::SetUpTestCase, \ parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \ parent_class::TearDownTestCase, \
test_case_name##_##test_name##_Test::NewTest);\ new ::testing::internal::TestFactoryImpl<\
test_case_name##_##test_name##_Test>);\
void test_case_name##_##test_name##_Test::TestBody() void test_case_name##_##test_name##_Test::TestBody()

View File

@ -542,7 +542,7 @@ class TestInfoImpl {
public: public:
TestInfoImpl(TestInfo* parent, const char* test_case_name, TestInfoImpl(TestInfo* parent, const char* test_case_name,
const char* name, TypeId fixture_class_id, const char* name, TypeId fixture_class_id,
TestMaker maker); internal::TestFactoryBase* factory);
~TestInfoImpl(); ~TestInfoImpl();
// Returns true if this test should run. // Returns true if this test should run.
@ -595,7 +595,8 @@ class TestInfoImpl {
const TypeId fixture_class_id_; // ID of the test fixture class const TypeId fixture_class_id_; // ID of the test fixture class
bool should_run_; // True iff this test should run bool should_run_; // True iff this test should run
bool is_disabled_; // True iff this test is disabled bool is_disabled_; // True iff this test is disabled
const TestMaker maker_; // The function that creates the test object internal::TestFactoryBase* const factory_; // The factory that creates
// the test object
// This field is mutable and needs to be reset before running the // This field is mutable and needs to be reset before running the
// test for the second time. // test for the second time.

View File

@ -1882,13 +1882,14 @@ bool Test::HasFatalFailure() {
// class TestInfo // class TestInfo
// Constructs a TestInfo object. // Constructs a TestInfo object. It assumes ownership of the test factory
// object via impl_.
TestInfo::TestInfo(const char* test_case_name, TestInfo::TestInfo(const char* test_case_name,
const char* name, const char* name,
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
TestMaker maker) { internal::TestFactoryBase* factory) {
impl_ = new internal::TestInfoImpl(this, test_case_name, name, impl_ = new internal::TestInfoImpl(this, test_case_name, name,
fixture_class_id, maker); fixture_class_id, factory);
} }
// Destructs a TestInfo object. // Destructs a TestInfo object.
@ -1905,16 +1906,17 @@ TestInfo::~TestInfo() {
// name: name of the test // name: name of the test
// set_up_tc: pointer to the function that sets up the test case // set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case // tear_down_tc: pointer to the function that tears down the test case
// maker: pointer to the function that creates a test object // factory factory object that creates a test object. The new
// TestInfo instance assumes ownership of the factory object.
TestInfo* TestInfo::MakeAndRegisterInstance( TestInfo* TestInfo::MakeAndRegisterInstance(
const char* test_case_name, const char* test_case_name,
const char* name, const char* name,
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
Test::SetUpTestCaseFunc set_up_tc, Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc, Test::TearDownTestCaseFunc tear_down_tc,
TestMaker maker) { internal::TestFactoryBase* factory) {
TestInfo* const test_info = TestInfo* const test_info =
new TestInfo(test_case_name, name, fixture_class_id, maker); new TestInfo(test_case_name, name, fixture_class_id, factory);
internal::GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); internal::GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info; return test_info;
} }
@ -2007,7 +2009,7 @@ void TestInfoImpl::Run() {
__try { __try {
// Creates the test object. // Creates the test object.
test = (*maker_)(); test = factory_->CreateTest();
} __except(internal::UnitTestOptions::GTestShouldProcessSEH( } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
GetExceptionCode())) { GetExceptionCode())) {
AddExceptionThrownFailure(GetExceptionCode(), AddExceptionThrownFailure(GetExceptionCode(),
@ -2022,7 +2024,7 @@ void TestInfoImpl::Run() {
// exception-safe. // exception-safe.
// Creates the test object. // Creates the test object.
Test* test = (*maker_)(); Test* test = factory_->CreateTest();
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
// Runs the test only if the constructor of the test fixture didn't // Runs the test only if the constructor of the test fixture didn't
@ -3417,23 +3419,25 @@ internal::TestResult* UnitTestImpl::current_test_result() {
current_test_info_->impl()->result() : &ad_hoc_test_result_; current_test_info_->impl()->result() : &ad_hoc_test_result_;
} }
// TestInfoImpl constructor. // TestInfoImpl constructor. The new instance assumes ownership of the test
// factory opbject.
TestInfoImpl::TestInfoImpl(TestInfo* parent, TestInfoImpl::TestInfoImpl(TestInfo* parent,
const char* test_case_name, const char* test_case_name,
const char* name, const char* name,
TypeId fixture_class_id, TypeId fixture_class_id,
TestMaker maker) : internal::TestFactoryBase* factory) :
parent_(parent), parent_(parent),
test_case_name_(String(test_case_name)), test_case_name_(String(test_case_name)),
name_(String(name)), name_(String(name)),
fixture_class_id_(fixture_class_id), fixture_class_id_(fixture_class_id),
should_run_(false), should_run_(false),
is_disabled_(false), is_disabled_(false),
maker_(maker) { factory_(factory) {
} }
// TestInfoImpl destructor. // TestInfoImpl destructor.
TestInfoImpl::~TestInfoImpl() { TestInfoImpl::~TestInfoImpl() {
delete factory_;
} }
} // namespace internal } // namespace internal