Set svn properties correctly for the newly added files.
[wxWidgets.git] / tests / any / anytest.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/any/anytest.cpp
3 // Purpose: Test the wxAny classes
4 // Author: Jaakko Salli
5 // RCS-ID: $Id$
6 // Copyright: (c) the wxWidgets team
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #include "testprec.h"
11
12 #ifdef __BORLANDC__
13 # pragma hdrstop
14 #endif
15
16 #if wxUSE_ANY
17
18 #include "wx/any.h"
19 #include "wx/datetime.h"
20
21 #include <math.h>
22
23 // ----------------------------------------------------------------------------
24 // test class
25 // ----------------------------------------------------------------------------
26
27 class wxAnyTestCase : public CppUnit::TestCase
28 {
29 public:
30 wxAnyTestCase();
31
32 private:
33 CPPUNIT_TEST_SUITE( wxAnyTestCase );
34 CPPUNIT_TEST( Equality );
35 CPPUNIT_TEST( As );
36 CPPUNIT_TEST( GetAs );
37 CPPUNIT_TEST( Null );
38 CPPUNIT_TEST( CustomTemplateSpecialization );
39 CPPUNIT_TEST_SUITE_END();
40
41 void Equality();
42 void As();
43 void GetAs();
44 void Null();
45 void CustomTemplateSpecialization();
46
47 wxDateTime m_testDateTime;
48
49 wxAny m_anySignedChar1;
50 wxAny m_anySignedShort1;
51 wxAny m_anySignedInt1;
52 wxAny m_anySignedLong1;
53 wxAny m_anySignedLongLong1;
54 wxAny m_anyUnsignedChar1;
55 wxAny m_anyUnsignedShort1;
56 wxAny m_anyUnsignedInt1;
57 wxAny m_anyUnsignedLong1;
58 wxAny m_anyUnsignedLongLong1;
59 wxAny m_anyStringString1;
60 wxAny m_anyCharString1;
61 wxAny m_anyWcharString1;
62 wxAny m_anyBool1;
63 wxAny m_anyFloatDouble1;
64 wxAny m_anyDoubleDouble1;
65 wxAny m_anyWxObjectPtr1;
66 wxAny m_anyVoidPtr1;
67 wxAny m_anyDateTime1;
68
69 wxAny m_anySignedChar2;
70 wxAny m_anySignedShort2;
71 wxAny m_anySignedInt2;
72 wxAny m_anySignedLong2;
73 wxAny m_anySignedLongLong2;
74 wxAny m_anyUnsignedChar2;
75 wxAny m_anyUnsignedShort2;
76 wxAny m_anyUnsignedInt2;
77 wxAny m_anyUnsignedLong2;
78 wxAny m_anyUnsignedLongLong2;
79 wxAny m_anyStringString2;
80 wxAny m_anyCharString2;
81 wxAny m_anyWcharString2;
82 wxAny m_anyBool2;
83 wxAny m_anyFloatDouble2;
84 wxAny m_anyDoubleDouble2;
85 wxAny m_anyWxObjectPtr2;
86 wxAny m_anyVoidPtr2;
87 wxAny m_anyDateTime2;
88
89 DECLARE_NO_COPY_CLASS(wxAnyTestCase)
90 };
91
92 // register in the unnamed registry so that these tests are run by default
93 CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase );
94
95 // also include in it's own registry so that these tests can be run alone
96 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( wxAnyTestCase, "wxAnyTestCase" );
97
98 // Let's use a number with first digit after decimal dot less than 5,
99 // so that we don't have to worry about whether conversion from float
100 // to int truncates or rounds.
101 const double TEST_FLOAT_CONST = 123.456;
102
103 const double FEQ_DELTA = 0.001;
104
105 wxObject* dummyWxObjectPointer = reinterpret_cast<wxObject*>(1234);
106 void* dummyVoidPointer = reinterpret_cast<void*>(1234);
107
108
109 //
110 // Test both 'creation' methods
111 wxAnyTestCase::wxAnyTestCase()
112 : m_anySignedChar1((signed char)15),
113 m_anySignedShort1((signed short)15),
114 m_anySignedInt1((signed int)15),
115 m_anySignedLong1((signed long)15),
116 #ifdef wxLongLong_t
117 m_anySignedLongLong1((wxLongLong_t)15),
118 #endif
119 m_anyUnsignedChar1((unsigned char)15),
120 m_anyUnsignedShort1((unsigned short)15),
121 m_anyUnsignedInt1((unsigned int)15),
122 m_anyUnsignedLong1((unsigned long)15),
123 #ifdef wxLongLong_t
124 m_anyUnsignedLongLong1((wxULongLong_t)15),
125 #endif
126 m_anyStringString1(wxString("abc")),
127 m_anyCharString1("abc"),
128 m_anyWcharString1(L"abc"),
129 m_anyBool1(true),
130 m_anyFloatDouble1((float)TEST_FLOAT_CONST),
131 m_anyDoubleDouble1((double)TEST_FLOAT_CONST),
132 m_anyWxObjectPtr1(dummyWxObjectPointer),
133 m_anyVoidPtr1(dummyVoidPointer),
134 m_anyDateTime1(wxDateTime::Now())
135 {
136 m_testDateTime = wxDateTime::Now();
137 m_anySignedChar2 = (signed char)15;
138 m_anySignedShort2 = (signed short)15;
139 m_anySignedInt2 = (signed int)15;
140 m_anySignedLong2 = (signed long)15;
141 #ifdef wxLongLong_t
142 m_anySignedLongLong2 = (wxLongLong_t)15;
143 #endif
144 m_anyUnsignedChar2 = (unsigned char)15;
145 m_anyUnsignedShort2 = (unsigned short)15;
146 m_anyUnsignedInt2 = (unsigned int)15;
147 m_anyUnsignedLong2 = (unsigned long)15;
148 #ifdef wxLongLong_t
149 m_anyUnsignedLongLong2 = (wxULongLong_t)15;
150 #endif
151 m_anyStringString2 = wxString("abc");
152 m_anyCharString2 = "abc";
153 m_anyWcharString2 = L"abc";
154 m_anyBool2 = true;
155 m_anyFloatDouble2 = (float)TEST_FLOAT_CONST;
156 m_anyDoubleDouble2 = (double)TEST_FLOAT_CONST;
157 m_anyDateTime2 = m_testDateTime;
158 m_anyWxObjectPtr2 = dummyWxObjectPointer;
159 m_anyVoidPtr2 = dummyVoidPointer;
160 }
161
162 void wxAnyTestCase::Equality()
163 {
164 //
165 // Currently this should work
166 CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15L);
167 CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30L);
168 CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15UL);
169 CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30UL);
170 CPPUNIT_ASSERT(m_anyStringString1 == wxString("abc"));
171 CPPUNIT_ASSERT(m_anyStringString1 != wxString("ABC"));
172 CPPUNIT_ASSERT(m_anyStringString1 == "abc");
173 CPPUNIT_ASSERT(m_anyStringString1 != "ABC");
174 CPPUNIT_ASSERT(m_anyStringString1 == L"abc");
175 CPPUNIT_ASSERT(m_anyStringString1 != L"ABC");
176 CPPUNIT_ASSERT(m_anyBool1 == true);
177 CPPUNIT_ASSERT(m_anyBool1 != false);
178 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),
179 wxANY_AS(m_anyDoubleDouble1, double),
180 FEQ_DELTA);
181 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),
182 TEST_FLOAT_CONST,
183 FEQ_DELTA);
184 CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr1, wxObject*)
185 == dummyWxObjectPointer);
186 CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr1, void*) == dummyVoidPointer);
187
188 CPPUNIT_ASSERT(m_anySignedLong2 == 15);
189 CPPUNIT_ASSERT(m_anyStringString2 == wxString("abc"));
190 CPPUNIT_ASSERT(m_anyStringString2 == "abc");
191 CPPUNIT_ASSERT(m_anyStringString2 == L"abc");
192 CPPUNIT_ASSERT(m_anyBool2 == true);
193 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),
194 wxANY_AS(m_anyDoubleDouble2, double),
195 FEQ_DELTA);
196 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),
197 TEST_FLOAT_CONST,
198 FEQ_DELTA);
199 CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr2, wxObject*)
200 == dummyWxObjectPointer);
201 CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr2, void*) == dummyVoidPointer);
202 }
203
204 void wxAnyTestCase::As()
205 {
206 //
207 // Test getting C++ data from wxAny without dynamic conversion
208 signed char a = wxANY_AS(m_anySignedChar1, signed char);
209 CPPUNIT_ASSERT(a == (signed int)15);
210 signed short b = wxANY_AS(m_anySignedShort1, signed short);
211 CPPUNIT_ASSERT(b == (signed int)15);
212 signed int c = wxANY_AS(m_anySignedInt1, signed int);
213 CPPUNIT_ASSERT(c == (signed int)15);
214 signed long d = wxANY_AS(m_anySignedLong1, signed long);
215 CPPUNIT_ASSERT(d == (signed int)15);
216 #ifdef wxLongLong_t
217 wxLongLong_t e = wxANY_AS(m_anySignedLongLong1, wxLongLong_t);
218 CPPUNIT_ASSERT(e == (signed int)15);
219 #endif
220 unsigned char f = wxANY_AS(m_anyUnsignedChar1, unsigned char);
221 CPPUNIT_ASSERT(f == (unsigned int)15);
222 unsigned short g = wxANY_AS(m_anyUnsignedShort1, unsigned short);
223 CPPUNIT_ASSERT(g == (unsigned int)15);
224 unsigned int h = wxANY_AS(m_anyUnsignedInt1, unsigned int);
225 CPPUNIT_ASSERT(h == (unsigned int)15);
226 unsigned long i = wxANY_AS(m_anyUnsignedLong1, unsigned long);
227 CPPUNIT_ASSERT(i == (unsigned int)15);
228 #ifdef wxLongLong_t
229 wxULongLong_t j = wxANY_AS(m_anyUnsignedLongLong1, wxULongLong_t);
230 CPPUNIT_ASSERT(j == (unsigned int)15);
231 #endif
232 wxString k = wxANY_AS(m_anyStringString1, wxString);
233 CPPUNIT_ASSERT(k == "abc");
234 wxString l = wxANY_AS(m_anyCharString1, wxString);
235 CPPUNIT_ASSERT(l == "abc");
236 wxString m = wxANY_AS(m_anyWcharString1, wxString);
237 CPPUNIT_ASSERT(m == "abc");
238 bool n = wxANY_AS(m_anyBool1, bool);
239 CPPUNIT_ASSERT(n);
240 float o = wxANY_AS(m_anyFloatDouble1, float);
241 CPPUNIT_ASSERT_DOUBLES_EQUAL(o, TEST_FLOAT_CONST, FEQ_DELTA);
242 double p = wxANY_AS(m_anyDoubleDouble1, double);
243 CPPUNIT_ASSERT_DOUBLES_EQUAL(p, TEST_FLOAT_CONST, FEQ_DELTA);
244 wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime);
245 CPPUNIT_ASSERT(q == m_testDateTime);
246 wxObject* r = wxANY_AS(m_anyWxObjectPtr1, wxObject*);
247 CPPUNIT_ASSERT(r == dummyWxObjectPointer);
248 void* s = wxANY_AS(m_anyVoidPtr1, void*);
249 CPPUNIT_ASSERT(s == dummyVoidPointer);
250 }
251
252 void wxAnyTestCase::Null()
253 {
254 wxAny a;
255 CPPUNIT_ASSERT(a.IsNull());
256 a = -127;
257 CPPUNIT_ASSERT(a == -127);
258 a.MakeNull();
259 CPPUNIT_ASSERT(a.IsNull());
260 }
261
262 void wxAnyTestCase::GetAs()
263 {
264 //
265 // Test dynamic conversion
266 bool res;
267 long l = 0;
268 unsigned long ul = 0;
269 wxString s;
270 // Let's test against float instead of double, since the former
271 // is not the native underlying type the code converts to, but
272 // should still work, all the same.
273 float f = 0.0;
274 bool b = false;
275
276 // Conversions from signed long type
277 res = m_anySignedLong1.GetAs(&ul);
278 CPPUNIT_ASSERT(res);
279 CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(15));
280 res = m_anySignedLong1.GetAs(&s);
281 CPPUNIT_ASSERT(res);
282 CPPUNIT_ASSERT(s == "15");
283 res = m_anySignedLong1.GetAs(&f);
284 CPPUNIT_ASSERT(res);
285 CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
286 res = m_anySignedLong1.GetAs(&b);
287 CPPUNIT_ASSERT(res);
288 CPPUNIT_ASSERT(b == true);
289
290 // Conversions from unsigned long type
291 res = m_anyUnsignedLong1.GetAs(&l);
292 CPPUNIT_ASSERT(res);
293 CPPUNIT_ASSERT(l == static_cast<signed long>(15));
294 res = m_anyUnsignedLong1.GetAs(&s);
295 CPPUNIT_ASSERT(res);
296 CPPUNIT_ASSERT(s == "15");
297 res = m_anyUnsignedLong1.GetAs(&f);
298 CPPUNIT_ASSERT(res);
299 CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
300 res = m_anyUnsignedLong1.GetAs(&b);
301 CPPUNIT_ASSERT(res);
302 CPPUNIT_ASSERT(b == true);
303
304 // Conversions from default "abc" string to other types
305 // should not work.
306 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&l));
307 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&ul));
308 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&f));
309 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&b));
310
311 // Let's test some other conversions from string that should work.
312 wxAny anyString;
313
314 anyString = "15";
315 res = anyString.GetAs(&l);
316 CPPUNIT_ASSERT(res);
317 CPPUNIT_ASSERT(l == static_cast<signed long>(15));
318 res = anyString.GetAs(&ul);
319 CPPUNIT_ASSERT(res);
320 CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(15));
321 res = anyString.GetAs(&f);
322 CPPUNIT_ASSERT(res);
323 CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
324 anyString = "TRUE";
325 res = anyString.GetAs(&b);
326 CPPUNIT_ASSERT(res);
327 CPPUNIT_ASSERT(b == true);
328 anyString = "0";
329 res = anyString.GetAs(&b);
330 CPPUNIT_ASSERT(res);
331 CPPUNIT_ASSERT(b == false);
332
333 // Conversions from bool type
334 res = m_anyBool1.GetAs(&l);
335 CPPUNIT_ASSERT(res);
336 CPPUNIT_ASSERT(l == static_cast<signed long>(1));
337 res = m_anyBool1.GetAs(&ul);
338 CPPUNIT_ASSERT(res);
339 CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(1));
340 res = m_anyBool1.GetAs(&s);
341 CPPUNIT_ASSERT(res);
342 CPPUNIT_ASSERT(s == "true");
343 CPPUNIT_ASSERT(!m_anyBool1.GetAs(&f));
344
345 // Conversions from floating point type
346 res = m_anyDoubleDouble1.GetAs(&l);
347 CPPUNIT_ASSERT(res);
348 CPPUNIT_ASSERT(l == static_cast<signed long>(123));
349 res = m_anyDoubleDouble1.GetAs(&ul);
350 CPPUNIT_ASSERT(res);
351 CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(123));
352 res = m_anyDoubleDouble1.GetAs(&s);
353 CPPUNIT_ASSERT(res);
354 double d2;
355 res = s.ToDouble(&d2);
356 CPPUNIT_ASSERT(res);
357 CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA);
358 }
359
360 //
361 // Test user data type specialization of wxAnyValueTypeImpl
362 //
363
364 class MyClass
365 {
366 public:
367 MyClass( int someValue = 32768 )
368 {
369 m_someValue = someValue;
370 }
371
372 wxString ToString()
373 {
374 return wxString::Format("%i", m_someValue);
375 }
376
377 private:
378 int m_someValue;
379 };
380
381
382 template<>
383 class wxAnyValueTypeImpl<MyClass> :
384 public wxAnyValueTypeImplBase<MyClass>
385 {
386 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)
387 public:
388 wxAnyValueTypeImpl() :
389 wxAnyValueTypeImplBase<MyClass>() { }
390 virtual ~wxAnyValueTypeImpl() { }
391
392 virtual bool ConvertValue(const wxAnyValueBuffer& src,
393 wxAnyValueType* dstType,
394 wxAnyValueBuffer& dst) const
395 {
396 MyClass value = GetValue(src);
397
398 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
399 {
400 wxString s = value.ToString();
401 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
402 }
403 else
404 return false;
405
406 return true;
407 }
408 };
409
410 //
411 // Following must be placed somewhere in your source code
412 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)
413
414 void wxAnyTestCase::CustomTemplateSpecialization()
415 {
416 // Do only a minimal CheckType() test, as dynamic type conversion already
417 // uses it a lot.
418 bool res;
419 MyClass myObject;
420 wxAny any = myObject;
421
422 CPPUNIT_ASSERT( wxANY_CHECK_TYPE(any, MyClass) );
423 MyClass myObject2 = wxANY_AS(any, MyClass);
424 wxUnusedVar(myObject2);
425
426 wxString str;
427 res = any.GetAs(&str);
428 CPPUNIT_ASSERT(res);
429 CPPUNIT_ASSERT_EQUAL(str, myObject.ToString());
430 }
431
432 #endif // wxUSE_ANY
433