res wrote:
This is wrong. You can't dynamic_cast interfaces - CS doesn't even
support RTTI! The solution is to query the interface with scfQueryInterface.
I changed that in the new patch.
#including cssysdef.h before the cppunit headers in the generated
sources works, too. (Probably some earlier definition of new tripping up
gcc.)
Unfortunately, that only fixes compilation, but creates another crash at runtime. cssysdef.h has to be #included after the cppunit headers, otherwise we run into the infamous RtlFreeHeap-issue (memory being deallocated on a different heap than it was allocated on).

However, the new patch does fix the crash on exit. A minimal implementation of cppunit's automated test registration was added to the unit testing boilerplate code inside Jamrules, and unittest.jam was changed to accommodate the syntactic differences between cppunit's classes and their replacement. I also moved the CS_FORCEINLINE re-#definition to the boilerplate code so that it only affects unit testing.

Greetings,
Lukas E. (erluk)


Index: Jamrules
===================================================================
--- Jamrules    (revision 25359)
+++ Jamrules    (working copy)
@@ -25,14 +25,101 @@
 ApplicationIconDefault macosx : gui : appicon.icns :
   $(TOP) libs csutil macosx ;
 
+# Unit-testing helper classes/macro: replaces CPPUNIT_TEST_SUITE_REGISTRATION
+# with a version that lives on the CS side. This prevents a crash on exit due
+# to static variable destruction order.
+UNITTEST_HELPER_REGISTRY = "
+class csCppUnitTestFactoryRegistry
+{
+public:
+  CS_DECLARE_STATIC_CLASSVAR(registry, getRegistry, 
csCppUnitTestFactoryRegistry);
+    
+  void registerFactory( CppUnit::TestFactory *factory )
+  {
+    m_factories.insert (factory);
+  }
+  
+  void unregisterFactory( CppUnit::TestFactory *factory )
+  {
+    m_factories.erase (factory);
+  }
+  
+  void addTestToSuite( CppUnit::TestSuite *suite )
+  {
+    for ( Factories::iterator it = m_factories.begin(); 
+          it != m_factories.end(); 
+          ++it )
+    {
+      CppUnit::TestFactory *factory = *it;
+      suite->addTest( factory->makeTest() );
+    }
+  }
+  
+  virtual CppUnit::Test* makeTest ()
+  {
+    CppUnit::TestSuite *suite = new CppUnit::TestSuite( 
\"CS_CPPUNIT_TEST_SUITE\" );
+    addTestToSuite( suite );
+    return suite;
+  }
+  
+private:
+  typedef CppUnitSet<CppUnit::TestFactory *, std::less<CppUnit::TestFactory*> 
> Factories;
+  Factories m_factories;
+  
+  virtual ~csCppUnitTestFactoryRegistry ()
+  {
+  }
+};
+" ;
+
+UNITTEST_HELPER_AUTOREG = "
+template<class TestCaseType> class csAutoRegisterSuite
+{
+public:
+  csAutoRegisterSuite()
+      : m_registry( csCppUnitTestFactoryRegistry::getRegistry() )
+  {
+    m_registry->registerFactory( &m_factory );
+  }
+
+  ~csAutoRegisterSuite()
+  {
+    m_registry->unregisterFactory( &m_factory );
+  }
+
+private:
+  csCppUnitTestFactoryRegistry *m_registry;
+  CppUnit::TestSuiteFactory<TestCaseType> m_factory;
+};
+
+#ifdef CS_CPPUNIT
+#undef CPPUNIT_TEST_SUITE_REGISTRATION
+#define CPPUNIT_TEST_SUITE_REGISTRATION( ATestFixtureType )      \\
+  static csAutoRegisterSuite< ATestFixtureType >       \\
+             CPPUNIT_MAKE_UNIQUE_NAME(autoRegisterRegistry__ )
+#endif
+
+" ;
+  
 # Unit-testing boilerplate: The code we want inserted into each test case and
 # the main driver program.
 UNITTEST_BOILERPLATE_TEST_PRE = "
+#include <cppunit/extensions/TestSuiteFactory.h>
+#ifdef __GNUC__
+# if (__GNUC__ == 3) && (__GNUC_MINOR__ == 4)
+#  undef CS_FORCEINLINE
+#  define CS_FORCEINLINE inline
+# endif
+#endif
 #include \"cssysdef.h\"
 #include \"csutil/scf.h\"
-" ;
+
+#define CS_CPPUNIT
+" $(UNITTEST_HELPER_REGISTRY) $(UNITTEST_HELPER_AUTOREG) ;
+
 UNITTEST_BOILERPLATE_MAIN_PRE = $(UNITTEST_BOILERPLATE_TEST_PRE) "
 CS_IMPLEMENT_APPLICATION
+CS_IMPLEMENT_STATIC_CLASSVAR(csCppUnitTestFactoryRegistry, registry, 
getRegistry, csCppUnitTestFactoryRegistry,)
 " ;
 
 # Set up a property which clients can query to determine if the build directory
Index: libs/csutil/t/blockallocator.t
===================================================================
--- libs/csutil/t/blockallocator.t      (revision 25359)
+++ libs/csutil/t/blockallocator.t      (working copy)
@@ -46,7 +46,7 @@
     size_t get_granularity() const { return S::size; }
     size_t get_element_size() const { return S::elsize; }
     size_t get_block_size() const { return S::blocksize; }
-    size_t get_block_count() const { return S::blocks.GetSize(); }
+    size_t get_block_count() const { return S::blocks.b.GetSize(); }
     csBitArray get_allocation_map() const { return S::GetAllocationMap(); }
   };
 
Index: libs/csutil/t/eventqueue.t
===================================================================
--- libs/csutil/t/eventqueue.t  (revision 25359)
+++ libs/csutil/t/eventqueue.t  (working copy)
@@ -181,7 +181,7 @@
 
   csEventTree *frameEvent = queue->EventTree->FindNode(csevFrame (objreg), 
queue);
 
-  frameEvent->fatRecord->SubscriberGraph->Dump (objreg);
+  //frameEvent->fatRecord->SubscriberGraph->Dump (objreg);
 
   CPPUNIT_ASSERT_MESSAGE ("List is empty", !handlers->IsEmpty());
 
Index: libs/csutil/t/objreg.t
===================================================================
--- libs/csutil/t/objreg.t      (revision 25359)
+++ libs/csutil/t/objreg.t      (working copy)
@@ -178,11 +178,11 @@
   CPPUNIT_ASSERT(if2.IsValid());
 
   csRef<iString> cmp1, cmp2;
-  cmp1.AttachNew(static_cast<iString*> (objreg->Get(
+  cmp1.AttachNew(scfQueryInterface<iString> (objreg->Get(
     "Test Object Registry one",
     scfInterfaceTraits<iString>::GetID(),
     scfInterfaceTraits<iString>::GetVersion())));
-  cmp2.AttachNew(static_cast<iString*> (objreg->Get(
+  cmp2.AttachNew(scfQueryInterface<iString> (objreg->Get(
     "Test Object Registry two",
     scfInterfaceTraits<iString>::GetID(),
     scfInterfaceTraits<iString>::GetVersion())));
Index: mk/jam/unittest.jam
===================================================================
--- mk/jam/unittest.jam (revision 25359)
+++ mk/jam/unittest.jam (working copy)
@@ -504,6 +504,13 @@
 #   uses CppUnit's automated test class discovery protocol to discover classes
 #   containing tests, therefore it is entirely generic and can be used by any
 #   number of driver programs.
+#
+#   CrystalSpace has its own memory allocator, though, so the automated test
+#   registration has to happen on CS's side. Therefore, the boilerplate code
+#   from CS's Jamrules contains our own implementation of 
+#   CPPUNIT_TEST_SUITE_REGISTRATION and its companion classes. It also #defines
+#   the "CS_CPPUNIT" symbol to distinguish between our macro and the generic
+#   CppUnit variant.
 actions UnitTestMain
 {
   cat <<EOF > $(<)
@@ -530,12 +537,16 @@
   }
 
   CppUnit::TextUi::TestRunner runner;
-  CppUnit::TestFactoryRegistry& registry =
-    CppUnit::TestFactoryRegistry::getRegistry();
   CppUnit::BriefTestProgressListener listener;
   if (verbose)
     runner.eventManager().addListener(&listener);
+#ifdef CS_CPPUNIT
+  runner.addTest (csCppUnitTestFactoryRegistry::getRegistry()->makeTest());
+#else
+  CppUnit::TestFactoryRegistry& registry =
+    CppUnit::TestFactoryRegistry::getRegistry();
   runner.addTest(registry.makeTest());
+#endif
   return runner.run("", false, true, !verbose) ? 0 : -1;
 }
 $(UNITTEST_BOILERPLATE_MAIN_POST)
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Crystal-main mailing list
Crystal-main@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/crystal-main
Unsubscribe: mailto:[EMAIL PROTECTED]

Reply via email to