1#include <cppunit/extensions/TestFactoryRegistry.h>
2#include <cppunit/TestSuite.h>
3#include <set>
4#include <string>
5
6
7#if CPPUNIT_USE_TYPEINFO_NAME
8#  include "cppunit/extensions/TypeInfoHelper.h"
9#endif
10
11
12using std::map;
13using std::set;
14using std::string;
15
16namespace CppUnit {
17
18/** (Implementation) This class manages all the TestFactoryRegistry.
19 *
20 * Responsible for the life-cycle of the TestFactoryRegistry.
21 *
22 * TestFactory registry must call wasDestroyed() to indicate that
23 * a given TestRegistry was destroyed, and needDestroy() to
24 * know if a given TestFactory need to be destroyed (was not already
25 * destroyed by another TestFactoryRegistry).
26 */
27class NamedRegistries
28{
29public:
30  ~NamedRegistries();
31
32  static NamedRegistries &getInstance();
33
34  TestFactoryRegistry &getRegistry( string name );
35
36  void wasDestroyed( TestFactory *factory );
37
38  bool needDestroy( TestFactory *factory );
39
40private:
41  typedef map<string, TestFactoryRegistry *> Registries;
42  Registries m_registries;
43
44  typedef set<TestFactory *> Factories;
45  Factories m_factoriesToDestroy;
46  Factories m_destroyedFactories;
47};
48
49
50NamedRegistries::~NamedRegistries()
51{
52  Registries::iterator it = m_registries.begin();
53  while ( it != m_registries.end() )
54  {
55    TestFactoryRegistry *registry = (it++)->second;
56    if ( needDestroy( registry ) )
57      delete registry;
58  }
59}
60
61
62NamedRegistries &
63NamedRegistries::getInstance()
64{
65  static NamedRegistries namedRegistries;
66  return namedRegistries;
67}
68
69
70TestFactoryRegistry &
71NamedRegistries::getRegistry( string name )
72{
73  Registries::const_iterator foundIt = m_registries.find( name );
74  if ( foundIt == m_registries.end() )
75  {
76    TestFactoryRegistry *factory = new TestFactoryRegistry( name );
77#if defined(__POWERPC__) && (defined(__BEOS__) || defined(__HAIKU__))
78    m_registries.insert(
79    	pair<
80  			const basic_string< char, char_traits< char>, allocator<char> >,
81  			CppUnit::TestFactoryRegistry*
82    	>(
83    		name, factory
84    	)
85    );
86#else
87    m_registries.insert( std::make_pair( name, factory ) );
88#endif
89    m_factoriesToDestroy.insert( factory );
90    return *factory;
91  }
92  return *foundIt->second;
93}
94
95
96void
97NamedRegistries::wasDestroyed( TestFactory *factory )
98{
99  m_factoriesToDestroy.erase( factory );
100  m_destroyedFactories.insert( factory );
101}
102
103
104bool
105NamedRegistries::needDestroy( TestFactory *factory )
106{
107  return m_destroyedFactories.count( factory ) == 0;
108}
109
110
111
112TestFactoryRegistry::TestFactoryRegistry( string name ) :
113    m_name( name )
114{
115}
116
117
118TestFactoryRegistry::~TestFactoryRegistry()
119{
120  // The wasDestroyed() and needDestroy() is used to prevent
121  // a double destruction of a factory registry.
122  // registerFactory( "All Tests", getRegistry( "Unit Tests" ) );
123  // => the TestFactoryRegistry "Unit Tests" is owned by both
124  // the "All Tests" registry and the NamedRegistries...
125  NamedRegistries::getInstance().wasDestroyed( this );
126
127  for ( Factories::iterator it = m_factories.begin(); it != m_factories.end(); ++it )
128  {
129    TestFactory *factory = it->second;
130    if ( NamedRegistries::getInstance().needDestroy( factory ) )
131      delete factory;
132  }
133}
134
135
136TestFactoryRegistry &
137TestFactoryRegistry::getRegistry()
138{
139  return getRegistry( "All Tests" );
140}
141
142
143TestFactoryRegistry &
144TestFactoryRegistry::getRegistry( const string &name )
145{
146  return NamedRegistries::getInstance().getRegistry( name );
147}
148
149
150void
151TestFactoryRegistry::registerFactory( const string &name,
152                                      TestFactory *factory )
153{
154  m_factories[name] = factory;
155}
156
157
158void
159TestFactoryRegistry::registerFactory( TestFactory *factory )
160{
161    static int serialNumber = 1;
162
163    OStringStream ost;
164    ost << "@Dummy@" << serialNumber++;
165
166    registerFactory( ost.str(), factory );
167}
168
169
170Test *
171TestFactoryRegistry::makeTest()
172{
173  TestSuite *suite = new TestSuite( m_name );
174  addTestToSuite( suite );
175  return suite;
176}
177
178
179void
180TestFactoryRegistry::addTestToSuite( TestSuite *suite )
181{
182  for ( Factories::iterator it = m_factories.begin();
183        it != m_factories.end();
184        ++it )
185  {
186    TestFactory *factory = (*it).second;
187    suite->addTest( factory->makeTest() );
188  }
189}
190
191
192}  // namespace CppUnit
193