weakref.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: tests/weakref/weakref.cpp
  3. // Purpose: wxWeakRef<T> unit test
  4. // Author: Arne Steinarson
  5. // Created: 2008-01-10
  6. // Copyright: (c) 2007 Arne Steinarson
  7. ///////////////////////////////////////////////////////////////////////////////
  8. // ----------------------------------------------------------------------------
  9. // headers
  10. // ----------------------------------------------------------------------------
  11. #include "testprec.h"
  12. #ifdef __BORLANDC__
  13. #pragma hdrstop
  14. #endif
  15. #ifndef WX_PRECOMP
  16. #include "wx/wx.h"
  17. #endif // WX_PRECOMP
  18. #include "wx/event.h"
  19. #include "wx/weakref.h"
  20. // A statically trackable derived wxObject
  21. class wxObjectTrackable : public wxObject, public wxTrackable
  22. {
  23. public:
  24. // Test member access
  25. void TestFunc(){ }
  26. // Make sure this does not clash with wxTrackableBase method
  27. int GetFirst() { return 0; }
  28. };
  29. // --------------------------------------------------------------------------
  30. // test class
  31. // --------------------------------------------------------------------------
  32. class WeakRefTestCase : public CppUnit::TestCase
  33. {
  34. public:
  35. WeakRefTestCase() {}
  36. private:
  37. CPPUNIT_TEST_SUITE( WeakRefTestCase );
  38. CPPUNIT_TEST( DeclareTest );
  39. CPPUNIT_TEST( AssignTest );
  40. CPPUNIT_TEST( AssignWeakRefTest );
  41. CPPUNIT_TEST( MultiAssignTest );
  42. CPPUNIT_TEST( CleanupTest );
  43. CPPUNIT_TEST( DeleteTest );
  44. #ifdef HAVE_DYNAMIC_CAST
  45. CPPUNIT_TEST( DynamicRefTest );
  46. #endif
  47. CPPUNIT_TEST_SUITE_END();
  48. void DeclareTest();
  49. void AssignTest();
  50. void AssignWeakRefTest();
  51. void MultiAssignTest();
  52. void CleanupTest();
  53. void DeleteTest();
  54. #ifdef HAVE_DYNAMIC_CAST
  55. void DynamicRefTest();
  56. #endif
  57. DECLARE_NO_COPY_CLASS(WeakRefTestCase)
  58. };
  59. // register in the unnamed registry so that these tests are run by default
  60. CPPUNIT_TEST_SUITE_REGISTRATION( WeakRefTestCase );
  61. // also include in its own registry so that these tests can be run alone
  62. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( WeakRefTestCase, "WeakRefTestCase" );
  63. // Test weak reference to an incomplete type, this should work if the type is
  64. // fully defined before it is used (but currently doesn't, see #11916)
  65. struct ForwardDeclaredClass;
  66. wxWeakRef<ForwardDeclaredClass> g_incompleteWeakRef;
  67. struct ForwardDeclaredClass : wxEvtHandler { };
  68. void WeakRefTestCase::DeclareTest()
  69. {
  70. {
  71. // Not initializing or initializing with NULL should work too
  72. //
  73. // FIXME-VC6: but it doesn't with VC6, see comment in wx/weakref.h
  74. #ifndef __VISUALC6__
  75. wxWeakRef<wxEvtHandler> wroDef;
  76. wxWeakRef<wxEvtHandler> wro0(NULL);
  77. #endif // __VISUALC6__
  78. wxObject o; // Should not work
  79. wxEvtHandler eh;
  80. wxObjectTrackable ot;
  81. // Test declare when T is wxObject
  82. // wxWeakRef<wxObject> wro1(&o); // Gives compile time failure
  83. wxWeakRef<wxEvtHandler> wro2(&eh);
  84. wxWeakRef<wxObjectTrackable> wro3(&ot);
  85. CPPUNIT_ASSERT( wro2.get() == &eh );
  86. CPPUNIT_ASSERT( wro3.get() == &ot );
  87. // Test accessing wxObject members
  88. CPPUNIT_ASSERT( !wro2->GetRefData() );
  89. CPPUNIT_ASSERT( !wro3->GetRefData() );
  90. wxWeakRef<wxEvtHandler> wreh(&eh);
  91. wxWeakRef<wxObjectTrackable> wrot(&ot);
  92. CPPUNIT_ASSERT( wreh.get() == &eh );
  93. CPPUNIT_ASSERT( wrot.get() == &ot );
  94. }
  95. // This test requires a working dynamic_cast<>
  96. #ifndef wxNO_RTTI
  97. {
  98. ForwardDeclaredClass fdc;
  99. g_incompleteWeakRef = &fdc;
  100. CPPUNIT_ASSERT( g_incompleteWeakRef );
  101. }
  102. CPPUNIT_ASSERT( !g_incompleteWeakRef );
  103. #endif // RTTI enabled
  104. }
  105. void WeakRefTestCase::AssignTest()
  106. {
  107. wxWeakRef<wxEvtHandler> wro1;
  108. wxWeakRef<wxObjectTrackable> wro2;
  109. { // Scope for object destruction
  110. wxEvtHandler eh;
  111. wxObjectTrackable ot;
  112. wro1 = &eh;
  113. wro2 = &ot;
  114. CPPUNIT_ASSERT( wro1.get() == &eh );
  115. CPPUNIT_ASSERT( wro2.get() == &ot );
  116. }
  117. // Should be reset now
  118. CPPUNIT_ASSERT( !wro1 );
  119. CPPUNIT_ASSERT( !wro2 );
  120. // Explicitly resetting should work too
  121. //
  122. // FIXME-VC6: as above, it doesn't work with VC6, see wx/weakref.h
  123. #ifndef __VISUALC6__
  124. wxEvtHandler eh;
  125. wxObjectTrackable ot;
  126. wro1 = &eh;
  127. wro2 = &ot;
  128. wro1 = NULL;
  129. wro2 = NULL;
  130. CPPUNIT_ASSERT( !wro1 );
  131. CPPUNIT_ASSERT( !wro2 );
  132. #endif // __VISUALC6__
  133. }
  134. void WeakRefTestCase::AssignWeakRefTest()
  135. {
  136. // Test declare when T is wxObject
  137. wxWeakRef<wxEvtHandler> wro1;
  138. wxWeakRef<wxObjectTrackable> wro2;
  139. { // Scope for object destruction
  140. wxEvtHandler eh;
  141. wxObjectTrackable ot;
  142. wxWeakRef<wxEvtHandler> wro3;
  143. wxWeakRef<wxObjectTrackable> wro4;
  144. wro1 = &eh;
  145. wro2 = &ot;
  146. wro3 = wro1;
  147. wro4 = wro2;
  148. CPPUNIT_ASSERT( wro1.get() == &eh );
  149. CPPUNIT_ASSERT( wro2.get() == &ot );
  150. CPPUNIT_ASSERT( wro3.get() == &eh );
  151. CPPUNIT_ASSERT( wro4.get() == &ot );
  152. wro4.Release();
  153. CPPUNIT_ASSERT( !wro4.get() );
  154. }
  155. // Should be reset now
  156. CPPUNIT_ASSERT( !wro1 );
  157. CPPUNIT_ASSERT( !wro2 );
  158. }
  159. void WeakRefTestCase::MultiAssignTest()
  160. {
  161. // Object is tracked by several refs
  162. wxEvtHandler *peh = new wxEvtHandler;
  163. // Test declare when T is wxObject
  164. wxWeakRef<wxEvtHandler> wro1(peh);
  165. wxWeakRef<wxEvtHandler> wro2(peh);
  166. wxObjectTrackable *pot = new wxObjectTrackable;
  167. wxWeakRef<wxObjectTrackable> wro3 = pot;
  168. wxWeakRef<wxObjectTrackable> wro4 = pot;
  169. CPPUNIT_ASSERT( wro1.get() == peh );
  170. CPPUNIT_ASSERT( wro2.get() == peh );
  171. CPPUNIT_ASSERT( wro3.get() == pot );
  172. CPPUNIT_ASSERT( wro4.get() == pot );
  173. delete peh;
  174. delete pot;
  175. // Should be reset now
  176. CPPUNIT_ASSERT( !wro1 );
  177. CPPUNIT_ASSERT( !wro2 );
  178. CPPUNIT_ASSERT( !wro3 );
  179. CPPUNIT_ASSERT( !wro4 );
  180. }
  181. void WeakRefTestCase::CleanupTest()
  182. {
  183. // Make sure that trackable objects have no left over tracker nodes after use.
  184. // This time the references goes out of scope before the objects.
  185. wxEvtHandler eh;
  186. wxObjectTrackable ots;
  187. wxObjectTrackable otd;
  188. { // Scope for object destruction
  189. wxWeakRef<wxEvtHandler> wro1;
  190. wxWeakRef<wxEvtHandler> wro2;
  191. wxWeakRef<wxObjectTrackable> wro3;
  192. wxWeakRef<wxObjectTrackable> wro4;
  193. wro1 = &eh;
  194. wro2 = &eh; // Has two tracker nodes now
  195. wro3 = &ots;
  196. wro4 = &otd;
  197. // Access members of reffed object
  198. wro3->TestFunc();
  199. CPPUNIT_ASSERT( eh.GetFirst()==&wro2 );
  200. CPPUNIT_ASSERT( ots.wxTrackable::GetFirst()==&wro3 );
  201. CPPUNIT_ASSERT( otd.wxTrackable::GetFirst()==&wro4 );
  202. }
  203. // Should be reset now
  204. CPPUNIT_ASSERT( !eh.GetFirst() );
  205. CPPUNIT_ASSERT( !ots.wxTrackable::GetFirst() );
  206. CPPUNIT_ASSERT( !otd.wxTrackable::GetFirst() );
  207. }
  208. void WeakRefTestCase::DeleteTest()
  209. {
  210. // Object is tracked by several refs
  211. wxEvtHandler *peh = new wxEvtHandler;
  212. // Declared derived type of object and test deleting it
  213. wxEvtHandlerRef wre(peh);
  214. wxWeakRef<wxEvtHandler> wro(peh);
  215. CPPUNIT_ASSERT( wre.get() == peh );
  216. CPPUNIT_ASSERT( wro.get() == peh );
  217. delete wre.get();
  218. CPPUNIT_ASSERT( !wre );
  219. CPPUNIT_ASSERT( !wro );
  220. }
  221. #ifdef HAVE_DYNAMIC_CAST
  222. void WeakRefTestCase::DynamicRefTest()
  223. {
  224. wxWeakRefDynamic<wxEvtHandler> wro1;
  225. wxWeakRefDynamic<wxObjectTrackable> wro2;
  226. wxWeakRefDynamic<wxObjectTrackable> wro3;
  227. { // Scope for object destruction
  228. {
  229. wxEvtHandler eh;
  230. wro1 = &eh;
  231. }
  232. CPPUNIT_ASSERT( !wro1 );
  233. wxObjectTrackable otd1;
  234. wxObjectTrackable otd2;
  235. wro2 = &otd1;
  236. wro3 = &otd2;
  237. CPPUNIT_ASSERT( wro2.get() == &otd1 );
  238. CPPUNIT_ASSERT( wro3.get() == &otd2 );
  239. wro3 = wro2;
  240. CPPUNIT_ASSERT( wro2.get() == &otd1 );
  241. CPPUNIT_ASSERT( wro3.get() == &otd1 );
  242. }
  243. // Should be reset now
  244. CPPUNIT_ASSERT( !wro2 );
  245. CPPUNIT_ASSERT( !wro3 );
  246. }
  247. #endif // HAVE_DYNAMIC_CAST