]> git.saurik.com Git - wxWidgets.git/blobdiff - tests/weakref/weakref.cpp
improvements to wxWeakRef and related classes
[wxWidgets.git] / tests / weakref / weakref.cpp
diff --git a/tests/weakref/weakref.cpp b/tests/weakref/weakref.cpp
new file mode 100644 (file)
index 0000000..f2a9c79
--- /dev/null
@@ -0,0 +1,281 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        tests/weakref/weakref.cpp
+// Purpose:     wxWeakRef<T> unit test
+// Author:      Arne Steinarson
+// Created:     2008-01-10
+// RCS-ID:      $Id$
+// 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
+
+    DECLARE_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 it's own registry so that these tests can be run alone
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( WeakRefTestCase, "WeakRefTestCase" );
+
+void WeakRefTestCase::DeclareTest()
+{
+    {
+        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 );
+    }
+}
+
+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 );
+}
+
+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);
+
+    // test size of references (see that it has selected right base class)
+#ifdef HAVE_PARTIAL_SPECIALIZATION
+    CPPUNIT_ASSERT_EQUAL( sizeof(void*)*3, sizeof(wre) );
+    CPPUNIT_ASSERT_EQUAL( sizeof(void*)*4, sizeof(wro) );
+#else
+    CPPUNIT_ASSERT_EQUAL( sizeof(void*)*3, sizeof(wre) );
+    CPPUNIT_ASSERT_EQUAL( sizeof(void*)*3, sizeof(wro) );
+#endif
+
+    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