From ddfca2261132a879f631cbaaf22e82feaa2460ef Mon Sep 17 00:00:00 2001 From: Baptiste Lepilleur Date: Tue, 2 Oct 2001 19:44:54 +0000 Subject: Include/cppunit/extensions/TestFactoryRegistry. include/cppunit/extensions/TestFactoryRegistry.h * src/cppunit/TestFactoryRegistry.cpp : fixed memory leaks that occured when a TestFactoryRegistry was registered into another TestFactoryRegistry. * include/cppunit/extensions/AutoRegisterSuite.h : updated doc. * include/cppunit/extensions/HelperMacros.h : added macro CPPUNIT_TEST_SUITE_NAMED_REGISTRATION to register a suite into a named suite. Updated doc. * examples/cppunittest/CoreSuite.h: * examples/cppunittest/ExtensionSuite.h: * examples/cppunittest/HelperSuite.h: added, declaration of suite for use with CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. * examples/cppunittest/makefile.am : added HelperSuite.h, CoreSuite.h, ExtensionSuite.h, CppUnitTestSuite.h and CppUnitTestSuite.cpp. * examples/cppunittest/CppUnitTestSuite.*: added. * examples/cppunittest/ExceptionTest.cpp: * examples/cppunittest/TestAssertTest.cpp: * examples/cppunittest/TestCaseTest.cpp: * examples/cppunittest/TestFailureTest.cpp: * examples/cppunittest/TestListenerTest.cpp: * examples/cppunittest/TestResultTest.cpp: * examples/cppunittest/TestSuiteTest.cpp: moved into named suite "Core" using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. * examples/cppunittest/OrthodoxTest.cpp: * examples/cppunittest/RepeatedTest.cpp: * examples/cppunittest/TestDecoratorTest.cpp: * examples/cppunittest/TestSetUpTest.cpp: moved into named suite "Extension" using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. * examples/cppunittest/HelperMacrosTest.cpp: * examples/cppunittest/TestCallerTest.cpp: moved into named suite "Helper" using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. * examples/cppunittest/CppUnitTest.dsp : * examples/msvc6/CppUnitTestApp/CppUnitTestApp.dsp : added Makefile.am, HelperSuite.h, CoreSuite.h, ExtensionSuite.h, CppUnitTestSuite.h and CppUnitTestSuite.cpp. --- src/cppunit/TestFactoryRegistry.cpp | 117 ++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 19 deletions(-) (limited to 'src/cppunit/TestFactoryRegistry.cpp') diff --git a/src/cppunit/TestFactoryRegistry.cpp b/src/cppunit/TestFactoryRegistry.cpp index 33bf0bf..5082736 100644 --- a/src/cppunit/TestFactoryRegistry.cpp +++ b/src/cppunit/TestFactoryRegistry.cpp @@ -1,5 +1,7 @@ #include #include +#include + #if CPPUNIT_USE_TYPEINFO_NAME # include "cppunit/extensions/TypeInfoHelper.h" @@ -8,17 +10,109 @@ namespace CppUnit { +/** This class manages all the TestFactoryRegistry. + * + * Responsible for the life-cycle of the TestFactoryRegistry. + * + * TestFactory registry must call wasDestroyed() to indicate that + * a given TestRegistry was destroyed, and needDestroy() to + * know if a given TestFactory need to be destroyed (was not already + * destroyed by another TestFactoryRegistry). + */ +class NamedRegistries +{ +public: + ~NamedRegistries(); + + static NamedRegistries &getInstance(); + + TestFactoryRegistry &getRegistry( std::string name ); + + void wasDestroyed( TestFactory *factory ); + + bool needDestroy( TestFactory *factory ); + +private: + typedef std::map Registries; + Registries m_registries; + + typedef std::set Factories; + Factories m_factoriesToDestroy; + Factories m_destroyedFactories; +}; + + +NamedRegistries::~NamedRegistries() +{ + Registries::iterator it = m_registries.begin(); + while ( it != m_registries.end() ) + { + TestFactoryRegistry *registry = (it++)->second; + if ( needDestroy( registry ) ) + delete registry; + } +} + + +NamedRegistries & +NamedRegistries::getInstance() +{ + static NamedRegistries namedRegistries; + return namedRegistries; +} + + +TestFactoryRegistry & +NamedRegistries::getRegistry( std::string name ) +{ + Registries::const_iterator foundIt = m_registries.find( name ); + if ( foundIt == m_registries.end() ) + { + TestFactoryRegistry *factory = new TestFactoryRegistry( name ); + m_registries.insert( std::make_pair( name, factory ) ); + m_factoriesToDestroy.insert( factory ); + return *factory; + } + return *foundIt->second; +} + + +void +NamedRegistries::wasDestroyed( TestFactory *factory ) +{ + m_factoriesToDestroy.erase( factory ); + m_destroyedFactories.insert( factory ); +} + + +bool +NamedRegistries::needDestroy( TestFactory *factory ) +{ + return m_destroyedFactories.count( factory ) == 0; +} + + + TestFactoryRegistry::TestFactoryRegistry( std::string name ) : m_name( name ) { } + TestFactoryRegistry::~TestFactoryRegistry() { + // The wasDestroyed() and needDestroy() is used to prevent + // a double destruction of a factory registry. + // registerFactory( "All Tests", getRegistry( "Unit Tests" ) ); + // => the TestFactoryRegistry "Unit Tests" is owned by both + // the "All Tests" registry and the NamedRegistries... + NamedRegistries::getInstance().wasDestroyed( this ); + for ( Factories::iterator it = m_factories.begin(); it != m_factories.end(); ++it ) { TestFactory *factory = it->second; - delete factory; + if ( NamedRegistries::getInstance().needDestroy( factory ) ) + delete factory; } } @@ -26,30 +120,14 @@ TestFactoryRegistry::~TestFactoryRegistry() TestFactoryRegistry & TestFactoryRegistry::getRegistry() { - static TestFactoryRegistry registry; - return registry; + return getRegistry( "All Tests" ); } TestFactoryRegistry & TestFactoryRegistry::getRegistry( const std::string &name ) { -// No clean-up at the current time => memory leaks. -// Need to find a way to solve the folowing issue: -// getRegistry().registryFactory( "Functionnal", -// getRegistry( "Functionnal" ) ); -// => the test factory registry "Functionnal" would be -// destroyed twice: once by the map below, once by the getRegistry() factory. - static NamedRegistries registries; - - NamedRegistries::const_iterator foundIt = registries.find( name ); - if ( foundIt == registries.end() ) - { - TestFactoryRegistry *factory = new TestFactoryRegistry( name ); - registries.insert( std::make_pair( name, factory ) ); - return *factory; - } - return *foundIt->second; + return NamedRegistries::getInstance().getRegistry( name ); } @@ -72,6 +150,7 @@ TestFactoryRegistry::registerFactory( TestFactory *factory ) registerFactory( ost.str(), factory ); } + Test * TestFactoryRegistry::makeTest() { -- cgit v1.2.1