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.
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).#including cssysdef.h before the cppunit headers in the generated sources works, too. (Probably some earlier definition of new tripping up gcc.)
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]