From d5f13d4a257b6bfc43068f3a918989cf89af75ec Mon Sep 17 00:00:00 2001 From: shiqian Date: Wed, 6 Aug 2008 21:44:19 +0000 Subject: Changes test creation functions to factories. By Vlad Losev. --- CONTRIBUTORS | 1 + include/gtest/gtest.h | 17 ++++++------- include/gtest/internal/gtest-internal.h | 44 +++++++++++++++++++++++++-------- src/gtest-internal-inl.h | 5 ++-- src/gtest.cc | 26 ++++++++++--------- 5 files changed, 61 insertions(+), 32 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index d6fa9bd0..ffc23418 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -24,4 +24,5 @@ Russ Rufer Sean Mcafee Sigurður Ásgeirsson Tracy Bialik +Vlad Losev Zhanyong Wan diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h index 2464f725..1f5d7640 100644 --- a/include/gtest/gtest.h +++ b/include/gtest/gtest.h @@ -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: // // Test case name @@ -342,7 +337,9 @@ class TestInfo { // fixture_class_id: ID of the test fixture class // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case - // 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. // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. @@ -352,7 +349,7 @@ class TestInfo { internal::TypeId fixture_class_id, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc, - TestMaker maker); + internal::TestFactoryBase* factory); // Returns the test case name. const char* test_case_name() const; @@ -395,9 +392,11 @@ class TestInfo { internal::TestInfoImpl* impl() { 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, - internal::TypeId fixture_class_id, TestMaker maker); + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); // An opaque implementation object. internal::TestInfoImpl* impl_; diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h index 2eefc7bf..dc6154b6 100644 --- a/include/gtest/internal/gtest-internal.h +++ b/include/gtest/internal/gtest-internal.h @@ -98,6 +98,7 @@ namespace testing { // Forward declaration of classes. class Message; // Represents a failure message. +class Test; // Represents a test. class TestCase; // A collection of related tests. class TestPartResult; // Result of a test part. class TestInfo; // Information about a test. @@ -484,6 +485,31 @@ inline TypeId GetTypeId() { 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 TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + #ifdef GTEST_OS_WINDOWS // 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 {\ public:\ test_case_name##_##test_name##_Test() {}\ - static ::testing::Test* NewTest() {\ - return new test_case_name##_##test_name##_Test;\ - }\ private:\ virtual void TestBody();\ 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::MakeAndRegisterInstance(\ - #test_case_name, \ - #test_name, \ - ::testing::internal::GetTypeId< parent_class >(), \ - parent_class::SetUpTestCase, \ - parent_class::TearDownTestCase, \ - test_case_name##_##test_name##_Test::NewTest);\ + ::testing::TestInfo::MakeAndRegisterInstance(\ + #test_case_name, \ + #test_name, \ + ::testing::internal::GetTypeId< parent_class >(), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + test_case_name##_##test_name##_Test>);\ void test_case_name##_##test_name##_Test::TestBody() diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h index 5546a77a..77571918 100644 --- a/src/gtest-internal-inl.h +++ b/src/gtest-internal-inl.h @@ -542,7 +542,7 @@ class TestInfoImpl { public: TestInfoImpl(TestInfo* parent, const char* test_case_name, const char* name, TypeId fixture_class_id, - TestMaker maker); + internal::TestFactoryBase* factory); ~TestInfoImpl(); // Returns true if this test should run. @@ -595,7 +595,8 @@ class TestInfoImpl { 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 - 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 // test for the second time. diff --git a/src/gtest.cc b/src/gtest.cc index 720341b0..a0a05208 100644 --- a/src/gtest.cc +++ b/src/gtest.cc @@ -1882,13 +1882,14 @@ bool Test::HasFatalFailure() { // 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, const char* name, internal::TypeId fixture_class_id, - TestMaker maker) { + internal::TestFactoryBase* factory) { impl_ = new internal::TestInfoImpl(this, test_case_name, name, - fixture_class_id, maker); + fixture_class_id, factory); } // Destructs a TestInfo object. @@ -1905,16 +1906,17 @@ TestInfo::~TestInfo() { // name: name of the test // 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 -// 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( const char* test_case_name, const char* name, internal::TypeId fixture_class_id, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc, - TestMaker maker) { + internal::TestFactoryBase* factory) { 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); return test_info; } @@ -2007,7 +2009,7 @@ void TestInfoImpl::Run() { __try { // Creates the test object. - test = (*maker_)(); + test = factory_->CreateTest(); } __except(internal::UnitTestOptions::GTestShouldProcessSEH( GetExceptionCode())) { AddExceptionThrownFailure(GetExceptionCode(), @@ -2022,7 +2024,7 @@ void TestInfoImpl::Run() { // exception-safe. // Creates the test object. - Test* test = (*maker_)(); + Test* test = factory_->CreateTest(); #endif // GTEST_OS_WINDOWS // 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_; } -// TestInfoImpl constructor. +// TestInfoImpl constructor. The new instance assumes ownership of the test +// factory opbject. TestInfoImpl::TestInfoImpl(TestInfo* parent, const char* test_case_name, const char* name, TypeId fixture_class_id, - TestMaker maker) : + internal::TestFactoryBase* factory) : parent_(parent), test_case_name_(String(test_case_name)), name_(String(name)), fixture_class_id_(fixture_class_id), should_run_(false), is_disabled_(false), - maker_(maker) { + factory_(factory) { } // TestInfoImpl destructor. TestInfoImpl::~TestInfoImpl() { + delete factory_; } } // namespace internal -- cgit v1.2.3