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