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