Use wxCLANG_WARNING_SUPPRESS() to avoid multiple warnings in CATCH headers as well as in some of our own tests.
		
			
				
	
	
		
			328 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			328 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| ///////////////////////////////////////////////////////////////////////////////
 | |
| // Name:        tests/weakref/weakref.cpp
 | |
| // Purpose:     wxWeakRef<T> unit test
 | |
| // Author:      Arne Steinarson
 | |
| // Created:     2008-01-10
 | |
| // Copyright:   (c) 2007 Arne Steinarson
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // headers
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| #include "testprec.h"
 | |
| 
 | |
| #ifdef __BORLANDC__
 | |
|     #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| #ifndef WX_PRECOMP
 | |
|     #include "wx/wx.h"
 | |
| #endif // WX_PRECOMP
 | |
| 
 | |
| #include "wx/event.h"
 | |
| #include "wx/weakref.h"
 | |
| 
 | |
| // A statically trackable derived wxObject
 | |
| class wxObjectTrackable : public wxObject, public wxTrackable
 | |
| {
 | |
| public:
 | |
|     // Test member access
 | |
|     void TestFunc(){ }
 | |
| 
 | |
|     // Make sure this does not clash with wxTrackableBase method
 | |
|     int GetFirst() { return 0; }
 | |
| };
 | |
| 
 | |
| // --------------------------------------------------------------------------
 | |
| // test class
 | |
| // --------------------------------------------------------------------------
 | |
| 
 | |
| class WeakRefTestCase : public CppUnit::TestCase
 | |
| {
 | |
| public:
 | |
|     WeakRefTestCase() {}
 | |
| 
 | |
| private:
 | |
|     CPPUNIT_TEST_SUITE( WeakRefTestCase );
 | |
|         CPPUNIT_TEST( DeclareTest );
 | |
|         CPPUNIT_TEST( AssignTest );
 | |
|         CPPUNIT_TEST( AssignWeakRefTest );
 | |
|         CPPUNIT_TEST( MultiAssignTest );
 | |
|         CPPUNIT_TEST( CleanupTest );
 | |
|         CPPUNIT_TEST( DeleteTest );
 | |
| #ifdef HAVE_DYNAMIC_CAST
 | |
|         CPPUNIT_TEST( DynamicRefTest );
 | |
| #endif
 | |
|     CPPUNIT_TEST_SUITE_END();
 | |
| 
 | |
|     void DeclareTest();
 | |
|     void AssignTest();
 | |
|     void AssignWeakRefTest();
 | |
|     void MultiAssignTest();
 | |
|     void CleanupTest();
 | |
|     void DeleteTest();
 | |
| #ifdef HAVE_DYNAMIC_CAST
 | |
|     void DynamicRefTest();
 | |
| #endif
 | |
| 
 | |
|     wxDECLARE_NO_COPY_CLASS(WeakRefTestCase);
 | |
| };
 | |
| 
 | |
| // register in the unnamed registry so that these tests are run by default
 | |
| CPPUNIT_TEST_SUITE_REGISTRATION( WeakRefTestCase );
 | |
| 
 | |
| // also include in its own registry so that these tests can be run alone
 | |
| CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( WeakRefTestCase, "WeakRefTestCase" );
 | |
| 
 | |
| 
 | |
| // Test weak reference to an incomplete type, this should work if the type is
 | |
| // fully defined before it is used (but currently doesn't, see #11916)
 | |
| struct ForwardDeclaredClass;
 | |
| wxWeakRef<ForwardDeclaredClass> g_incompleteWeakRef;
 | |
| 
 | |
| struct ForwardDeclaredClass : wxEvtHandler { };
 | |
| 
 | |
| // A incomplete class that would be defined in other compilation units
 | |
| struct IncompleteClass;
 | |
| 
 | |
| void WeakRefTestCase::DeclareTest()
 | |
| {
 | |
|     {
 | |
|         // Not initializing or initializing with NULL should work too
 | |
|         wxWeakRef<wxEvtHandler> wroDef;
 | |
|         wxWeakRef<wxEvtHandler> wro0(NULL);
 | |
| 
 | |
|         wxObject o; // Should not work
 | |
|         wxEvtHandler eh;
 | |
|         wxObjectTrackable ot;
 | |
| 
 | |
|         // Test declare when T is wxObject
 | |
|         // wxWeakRef<wxObject> wro1(&o);    // Gives compile time failure
 | |
|         wxWeakRef<wxEvtHandler> wro2(&eh);
 | |
|         wxWeakRef<wxObjectTrackable> wro3(&ot);
 | |
| 
 | |
|         CPPUNIT_ASSERT( wro2.get() == &eh );
 | |
|         CPPUNIT_ASSERT( wro3.get() == &ot );
 | |
| 
 | |
|         // Test accessing wxObject members
 | |
|         CPPUNIT_ASSERT( !wro2->GetRefData() );
 | |
|         CPPUNIT_ASSERT( !wro3->GetRefData() );
 | |
| 
 | |
| 
 | |
|         wxWeakRef<wxEvtHandler> wreh(&eh);
 | |
|         wxWeakRef<wxObjectTrackable> wrot(&ot);
 | |
| 
 | |
|         CPPUNIT_ASSERT( wreh.get() == &eh );
 | |
|         CPPUNIT_ASSERT( wrot.get() == &ot );
 | |
|     }
 | |
| 
 | |
|     // This test requires a working dynamic_cast<>
 | |
| #ifndef wxNO_RTTI
 | |
|     {
 | |
|         ForwardDeclaredClass fdc;
 | |
|         g_incompleteWeakRef = &fdc;
 | |
|         CPPUNIT_ASSERT( g_incompleteWeakRef );
 | |
|     }
 | |
| 
 | |
|     CPPUNIT_ASSERT( !g_incompleteWeakRef );
 | |
| #endif // RTTI enabled
 | |
| 
 | |
|     {
 | |
|         // Construction of a wxWeakRef to an incomplete class should be fine
 | |
|         wxWeakRef<IncompleteClass> p;
 | |
| 
 | |
|         // Copying should be also OK
 | |
|         wxCLANG_WARNING_SUPPRESS(self-assign-overloaded)
 | |
|         p = p;
 | |
|         wxCLANG_WARNING_RESTORE(self-assign-overloaded)
 | |
| 
 | |
|         // Assigning a raw pointer should cause compile error
 | |
| #ifdef TEST_INVALID_INCOMPLETE_WEAKREF
 | |
|         p = static_cast<IncompleteClass*>(0);
 | |
| #endif
 | |
| 
 | |
|         // Releasing should be OK
 | |
|     }
 | |
| }
 | |
| 
 | |
| void WeakRefTestCase::AssignTest()
 | |
| {
 | |
|     wxWeakRef<wxEvtHandler> wro1;
 | |
|     wxWeakRef<wxObjectTrackable> wro2;
 | |
| 
 | |
|     {   // Scope for object destruction
 | |
|         wxEvtHandler eh;
 | |
|         wxObjectTrackable ot;
 | |
| 
 | |
|         wro1 = &eh;
 | |
|         wro2 = &ot;
 | |
| 
 | |
|         CPPUNIT_ASSERT( wro1.get() == &eh );
 | |
|         CPPUNIT_ASSERT( wro2.get() == &ot );
 | |
|     }
 | |
| 
 | |
|     // Should be reset now
 | |
|     CPPUNIT_ASSERT( !wro1 );
 | |
|     CPPUNIT_ASSERT( !wro2 );
 | |
| 
 | |
|     // Explicitly resetting should work too
 | |
|     wxEvtHandler eh;
 | |
|     wxObjectTrackable ot;
 | |
| 
 | |
|     wro1 = &eh;
 | |
|     wro2 = &ot;
 | |
| 
 | |
|     wro1 = NULL;
 | |
|     wro2 = NULL;
 | |
| 
 | |
|     CPPUNIT_ASSERT( !wro1 );
 | |
|     CPPUNIT_ASSERT( !wro2 );
 | |
| }
 | |
| 
 | |
| void WeakRefTestCase::AssignWeakRefTest()
 | |
| {
 | |
|     // Test declare when T is wxObject
 | |
|     wxWeakRef<wxEvtHandler> wro1;
 | |
|     wxWeakRef<wxObjectTrackable> wro2;
 | |
| 
 | |
|     {   // Scope for object destruction
 | |
|         wxEvtHandler eh;
 | |
|         wxObjectTrackable ot;
 | |
|         wxWeakRef<wxEvtHandler> wro3;
 | |
|         wxWeakRef<wxObjectTrackable> wro4;
 | |
| 
 | |
|         wro1 = &eh;
 | |
|         wro2 = &ot;
 | |
|         wro3 = wro1;
 | |
|         wro4 = wro2;
 | |
| 
 | |
|         CPPUNIT_ASSERT( wro1.get() == &eh );
 | |
|         CPPUNIT_ASSERT( wro2.get() == &ot );
 | |
|         CPPUNIT_ASSERT( wro3.get() == &eh );
 | |
|         CPPUNIT_ASSERT( wro4.get() == &ot );
 | |
| 
 | |
|         wro4.Release();
 | |
|         CPPUNIT_ASSERT( !wro4.get() );
 | |
|     }
 | |
| 
 | |
|     // Should be reset now
 | |
|     CPPUNIT_ASSERT( !wro1 );
 | |
|     CPPUNIT_ASSERT( !wro2 );
 | |
| }
 | |
| 
 | |
| void WeakRefTestCase::MultiAssignTest()
 | |
| {
 | |
|     // Object is tracked by several refs
 | |
|     wxEvtHandler *peh = new wxEvtHandler;
 | |
| 
 | |
|     // Test declare when T is wxObject
 | |
|     wxWeakRef<wxEvtHandler> wro1(peh);
 | |
|     wxWeakRef<wxEvtHandler> wro2(peh);
 | |
| 
 | |
|     wxObjectTrackable *pot = new wxObjectTrackable;
 | |
|     wxWeakRef<wxObjectTrackable> wro3 = pot;
 | |
|     wxWeakRef<wxObjectTrackable> wro4 = pot;
 | |
| 
 | |
|     CPPUNIT_ASSERT( wro1.get() == peh );
 | |
|     CPPUNIT_ASSERT( wro2.get() == peh );
 | |
|     CPPUNIT_ASSERT( wro3.get() == pot );
 | |
|     CPPUNIT_ASSERT( wro4.get() == pot );
 | |
| 
 | |
|     delete peh;
 | |
|     delete pot;
 | |
| 
 | |
|     // Should be reset now
 | |
|     CPPUNIT_ASSERT( !wro1 );
 | |
|     CPPUNIT_ASSERT( !wro2 );
 | |
|     CPPUNIT_ASSERT( !wro3 );
 | |
|     CPPUNIT_ASSERT( !wro4 );
 | |
| }
 | |
| 
 | |
| void WeakRefTestCase::CleanupTest()
 | |
| {
 | |
|     // Make sure that trackable objects have no left over tracker nodes after use.
 | |
|     // This time the references goes out of scope before the objects.
 | |
|     wxEvtHandler eh;
 | |
|     wxObjectTrackable ots;
 | |
|     wxObjectTrackable otd;
 | |
| 
 | |
|     {   // Scope for object destruction
 | |
|         wxWeakRef<wxEvtHandler> wro1;
 | |
|         wxWeakRef<wxEvtHandler> wro2;
 | |
|         wxWeakRef<wxObjectTrackable> wro3;
 | |
|         wxWeakRef<wxObjectTrackable> wro4;
 | |
| 
 | |
|         wro1 = &eh;
 | |
|         wro2 = &eh; // Has two tracker nodes now
 | |
|         wro3 = &ots;
 | |
|         wro4 = &otd;
 | |
| 
 | |
|         // Access members of reffed object
 | |
|         wro3->TestFunc();
 | |
| 
 | |
|         CPPUNIT_ASSERT( eh.GetFirst()==&wro2 );
 | |
|         CPPUNIT_ASSERT( ots.wxTrackable::GetFirst()==&wro3 );
 | |
|         CPPUNIT_ASSERT( otd.wxTrackable::GetFirst()==&wro4 );
 | |
|     }
 | |
| 
 | |
|     // Should be reset now
 | |
|     CPPUNIT_ASSERT( !eh.GetFirst() );
 | |
|     CPPUNIT_ASSERT( !ots.wxTrackable::GetFirst() );
 | |
|     CPPUNIT_ASSERT( !otd.wxTrackable::GetFirst() );
 | |
| }
 | |
| 
 | |
| void WeakRefTestCase::DeleteTest()
 | |
| {
 | |
|     // Object is tracked by several refs
 | |
|     wxEvtHandler *peh = new wxEvtHandler;
 | |
| 
 | |
|     // Declared derived type of object and test deleting it
 | |
|     wxEvtHandlerRef wre(peh);
 | |
|     wxWeakRef<wxEvtHandler> wro(peh);
 | |
| 
 | |
|     CPPUNIT_ASSERT( wre.get() == peh );
 | |
|     CPPUNIT_ASSERT( wro.get() == peh );
 | |
| 
 | |
|     delete wre.get();
 | |
| 
 | |
|     CPPUNIT_ASSERT( !wre );
 | |
|     CPPUNIT_ASSERT( !wro );
 | |
| }
 | |
| 
 | |
| #ifdef HAVE_DYNAMIC_CAST
 | |
| 
 | |
| void WeakRefTestCase::DynamicRefTest()
 | |
| {
 | |
|     wxWeakRefDynamic<wxEvtHandler> wro1;
 | |
|     wxWeakRefDynamic<wxObjectTrackable> wro2;
 | |
|     wxWeakRefDynamic<wxObjectTrackable> wro3;
 | |
| 
 | |
|     {   // Scope for object destruction
 | |
|         {
 | |
|             wxEvtHandler eh;
 | |
|             wro1 = &eh;
 | |
|         }
 | |
| 
 | |
|         CPPUNIT_ASSERT( !wro1 );
 | |
| 
 | |
|         wxObjectTrackable otd1;
 | |
|         wxObjectTrackable otd2;
 | |
|         wro2 = &otd1;
 | |
|         wro3 = &otd2;
 | |
| 
 | |
|         CPPUNIT_ASSERT( wro2.get() == &otd1 );
 | |
|         CPPUNIT_ASSERT( wro3.get() == &otd2 );
 | |
| 
 | |
|         wro3 = wro2;
 | |
|         CPPUNIT_ASSERT( wro2.get() == &otd1 );
 | |
|         CPPUNIT_ASSERT( wro3.get() == &otd1 );
 | |
|     }
 | |
| 
 | |
|     // Should be reset now
 | |
|     CPPUNIT_ASSERT( !wro2 );
 | |
|     CPPUNIT_ASSERT( !wro3 );
 | |
| }
 | |
| 
 | |
| #endif // HAVE_DYNAMIC_CAST
 |