Added wxAny::HasSameType()
[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 #include "wx/object.h"
21
22 #include <math.h>
23
24 // ----------------------------------------------------------------------------
25 // test class
26 // ----------------------------------------------------------------------------
27
28 class wxAnyTestCase : public CppUnit::TestCase
29 {
30 public:
31 wxAnyTestCase();
32
33 private:
34 CPPUNIT_TEST_SUITE( wxAnyTestCase );
35 CPPUNIT_TEST( CheckType );
36 CPPUNIT_TEST( Equality );
37 CPPUNIT_TEST( As );
38 CPPUNIT_TEST( GetAs );
39 CPPUNIT_TEST( Null );
40 CPPUNIT_TEST( wxVariantConversions );
41 CPPUNIT_TEST( CustomTemplateSpecialization );
42 CPPUNIT_TEST_SUITE_END();
43
44 void CheckType();
45 void Equality();
46 void As();
47 void GetAs();
48 void Null();
49 void wxVariantConversions();
50 void CustomTemplateSpecialization();
51
52 wxDateTime m_testDateTime;
53
54 wxAny m_anySignedChar1;
55 wxAny m_anySignedShort1;
56 wxAny m_anySignedInt1;
57 wxAny m_anySignedLong1;
58 wxAny m_anySignedLongLong1;
59 wxAny m_anyUnsignedChar1;
60 wxAny m_anyUnsignedShort1;
61 wxAny m_anyUnsignedInt1;
62 wxAny m_anyUnsignedLong1;
63 wxAny m_anyUnsignedLongLong1;
64 wxAny m_anyStringString1;
65 wxAny m_anyCharString1;
66 wxAny m_anyWcharString1;
67 wxAny m_anyBool1;
68 wxAny m_anyFloatDouble1;
69 wxAny m_anyDoubleDouble1;
70 wxAny m_anyWxObjectPtr1;
71 wxAny m_anyVoidPtr1;
72 wxAny m_anyDateTime1;
73 wxAny m_anyUniChar1;
74
75 wxAny m_anySignedChar2;
76 wxAny m_anySignedShort2;
77 wxAny m_anySignedInt2;
78 wxAny m_anySignedLong2;
79 wxAny m_anySignedLongLong2;
80 wxAny m_anyUnsignedChar2;
81 wxAny m_anyUnsignedShort2;
82 wxAny m_anyUnsignedInt2;
83 wxAny m_anyUnsignedLong2;
84 wxAny m_anyUnsignedLongLong2;
85 wxAny m_anyStringString2;
86 wxAny m_anyCharString2;
87 wxAny m_anyWcharString2;
88 wxAny m_anyBool2;
89 wxAny m_anyFloatDouble2;
90 wxAny m_anyDoubleDouble2;
91 wxAny m_anyWxObjectPtr2;
92 wxAny m_anyVoidPtr2;
93 wxAny m_anyDateTime2;
94
95 DECLARE_NO_COPY_CLASS(wxAnyTestCase)
96 };
97
98 // register in the unnamed registry so that these tests are run by default
99 CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase );
100
101 // also include in it's own registry so that these tests can be run alone
102 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( wxAnyTestCase, "wxAnyTestCase" );
103
104 // Let's use a number with first digit after decimal dot less than 5,
105 // so that we don't have to worry about whether conversion from float
106 // to int truncates or rounds.
107 const float TEST_FLOAT_CONST = 123.456f;
108 const double TEST_DOUBLE_CONST = 123.456;
109
110 const double FEQ_DELTA = 0.001;
111
112 wxObject* dummyWxObjectPointer = reinterpret_cast<wxObject*>(1234);
113 void* dummyVoidPointer = reinterpret_cast<void*>(1234);
114
115
116 //
117 // Test both 'creation' methods
118 wxAnyTestCase::wxAnyTestCase()
119 : m_anySignedChar1((signed char)15),
120 m_anySignedShort1((signed short)15),
121 m_anySignedInt1((signed int)15),
122 m_anySignedLong1((signed long)15),
123 #ifdef wxLongLong_t
124 m_anySignedLongLong1((wxLongLong_t)15),
125 #endif
126 m_anyUnsignedChar1((unsigned char)15),
127 m_anyUnsignedShort1((unsigned short)15),
128 m_anyUnsignedInt1((unsigned int)15),
129 m_anyUnsignedLong1((unsigned long)15),
130 #ifdef wxLongLong_t
131 m_anyUnsignedLongLong1((wxULongLong_t)15),
132 #endif
133 m_anyStringString1(wxString("abc")),
134 m_anyCharString1("abc"),
135 m_anyWcharString1(L"abc"),
136 m_anyBool1(true),
137 m_anyFloatDouble1(TEST_FLOAT_CONST),
138 m_anyDoubleDouble1(TEST_DOUBLE_CONST),
139 m_anyWxObjectPtr1(dummyWxObjectPointer),
140 m_anyVoidPtr1(dummyVoidPointer),
141 m_anyDateTime1(wxDateTime::Now())
142 {
143 m_testDateTime = wxDateTime::Now();
144 m_anySignedChar2 = (signed char)15;
145 m_anySignedShort2 = (signed short)15;
146 m_anySignedInt2 = (signed int)15;
147 m_anySignedLong2 = (signed long)15;
148 #ifdef wxLongLong_t
149 m_anySignedLongLong2 = (wxLongLong_t)15;
150 #endif
151 m_anyUnsignedChar2 = (unsigned char)15;
152 m_anyUnsignedShort2 = (unsigned short)15;
153 m_anyUnsignedInt2 = (unsigned int)15;
154 m_anyUnsignedLong2 = (unsigned long)15;
155 #ifdef wxLongLong_t
156 m_anyUnsignedLongLong2 = (wxULongLong_t)15;
157 #endif
158 m_anyStringString2 = wxString("abc");
159 m_anyCharString2 = "abc";
160 m_anyWcharString2 = L"abc";
161 m_anyBool2 = true;
162 m_anyFloatDouble2 = TEST_FLOAT_CONST;
163 m_anyDoubleDouble2 = TEST_DOUBLE_CONST;
164 m_anyDateTime2 = m_testDateTime;
165 m_anyUniChar1 = wxUniChar('A');
166 m_anyWxObjectPtr2 = dummyWxObjectPointer;
167 m_anyVoidPtr2 = dummyVoidPointer;
168 }
169
170 void wxAnyTestCase::CheckType()
171 {
172 wxAny nullAny;
173 CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(nullAny, wxString));
174
175 CPPUNIT_ASSERT(wxANY_CHECK_TYPE(m_anyCharString2, const char*));
176 CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyCharString2, wxString));
177 CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyCharString2, const wchar_t*));
178 CPPUNIT_ASSERT(wxANY_CHECK_TYPE(m_anyWcharString2, const wchar_t*));
179 CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyWcharString2, wxString));
180 CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyWcharString2, const char*));
181
182 // HasSameType()
183 CPPUNIT_ASSERT( m_anyWcharString1.HasSameType(m_anyWcharString2) );
184 CPPUNIT_ASSERT( !m_anyWcharString1.HasSameType(m_anyBool1) );
185 }
186
187 void wxAnyTestCase::Equality()
188 {
189 //
190 // Currently this should work
191 CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15L);
192 CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30L);
193 CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15UL);
194 CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30UL);
195 CPPUNIT_ASSERT(m_anyStringString1 == wxString("abc"));
196 CPPUNIT_ASSERT(m_anyStringString1 != wxString("ABC"));
197 CPPUNIT_ASSERT(m_anyStringString1 == "abc");
198 CPPUNIT_ASSERT(m_anyStringString1 != "ABC");
199 CPPUNIT_ASSERT(m_anyStringString1 == L"abc");
200 CPPUNIT_ASSERT(m_anyStringString1 != L"ABC");
201 CPPUNIT_ASSERT(m_anyBool1 == true);
202 CPPUNIT_ASSERT(m_anyBool1 != false);
203 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),
204 wxANY_AS(m_anyDoubleDouble1, double),
205 FEQ_DELTA);
206 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),
207 TEST_FLOAT_CONST,
208 FEQ_DELTA);
209 CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr1, wxObject*)
210 == dummyWxObjectPointer);
211 CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr1, void*) == dummyVoidPointer);
212
213 CPPUNIT_ASSERT(m_anySignedLong2 == 15);
214 CPPUNIT_ASSERT(m_anyStringString2 == wxString("abc"));
215 CPPUNIT_ASSERT(m_anyStringString2 == "abc");
216 CPPUNIT_ASSERT(m_anyStringString2 == L"abc");
217 CPPUNIT_ASSERT(m_anyBool2 == true);
218 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),
219 wxANY_AS(m_anyDoubleDouble2, double),
220 FEQ_DELTA);
221 CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),
222 TEST_FLOAT_CONST,
223 FEQ_DELTA);
224 CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr2, wxObject*)
225 == dummyWxObjectPointer);
226 CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr2, void*) == dummyVoidPointer);
227
228 // Test sub-type system type compatibility
229 CPPUNIT_ASSERT(m_anySignedShort1.GetType()->
230 IsSameType(m_anySignedLongLong1.GetType()));
231 CPPUNIT_ASSERT(m_anyUnsignedShort1.GetType()->
232 IsSameType(m_anyUnsignedLongLong1.GetType()));
233 }
234
235 void wxAnyTestCase::As()
236 {
237 //
238 // Test getting C++ data from wxAny without dynamic conversion
239 signed char a = wxANY_AS(m_anySignedChar1, signed char);
240 CPPUNIT_ASSERT(a == (signed int)15);
241 signed short b = wxANY_AS(m_anySignedShort1, signed short);
242 CPPUNIT_ASSERT(b == (signed int)15);
243 signed int c = wxANY_AS(m_anySignedInt1, signed int);
244 CPPUNIT_ASSERT(c == (signed int)15);
245 signed long d = wxANY_AS(m_anySignedLong1, signed long);
246 CPPUNIT_ASSERT(d == (signed int)15);
247 #ifdef wxLongLong_t
248 wxLongLong_t e = wxANY_AS(m_anySignedLongLong1, wxLongLong_t);
249 CPPUNIT_ASSERT(e == (signed int)15);
250 #endif
251 unsigned char f = wxANY_AS(m_anyUnsignedChar1, unsigned char);
252 CPPUNIT_ASSERT(f == (unsigned int)15);
253 unsigned short g = wxANY_AS(m_anyUnsignedShort1, unsigned short);
254 CPPUNIT_ASSERT(g == (unsigned int)15);
255 unsigned int h = wxANY_AS(m_anyUnsignedInt1, unsigned int);
256 CPPUNIT_ASSERT(h == (unsigned int)15);
257 unsigned long i = wxANY_AS(m_anyUnsignedLong1, unsigned long);
258 CPPUNIT_ASSERT(i == (unsigned int)15);
259 #ifdef wxLongLong_t
260 wxULongLong_t j = wxANY_AS(m_anyUnsignedLongLong1, wxULongLong_t);
261 CPPUNIT_ASSERT(j == (unsigned int)15);
262 #endif
263 wxString k = wxANY_AS(m_anyStringString1, wxString);
264 CPPUNIT_ASSERT(k == "abc");
265 wxString l = wxANY_AS(m_anyCharString1, wxString);
266 const char* cptr = wxANY_AS(m_anyCharString1, const char*);
267 CPPUNIT_ASSERT(l == "abc");
268 CPPUNIT_ASSERT(cptr);
269 wxString m = wxANY_AS(m_anyWcharString1, wxString);
270 const wchar_t* wcptr = wxANY_AS(m_anyWcharString1, const wchar_t*);
271 CPPUNIT_ASSERT(wcptr);
272 CPPUNIT_ASSERT(m == "abc");
273 bool n = wxANY_AS(m_anyBool1, bool);
274 CPPUNIT_ASSERT(n);
275
276 // Make sure the stored float that comes back is -identical-.
277 // So do not use delta comparison here.
278 float o = wxANY_AS(m_anyFloatDouble1, float);
279 CPPUNIT_ASSERT_EQUAL(o, TEST_FLOAT_CONST);
280
281 double p = wxANY_AS(m_anyDoubleDouble1, double);
282 CPPUNIT_ASSERT_EQUAL(p, TEST_DOUBLE_CONST);
283
284 wxUniChar chr = wxANY_AS(m_anyUniChar1, wxUniChar);
285 CPPUNIT_ASSERT(chr == 'A');
286 wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime);
287 CPPUNIT_ASSERT(q == m_testDateTime);
288 wxObject* r = wxANY_AS(m_anyWxObjectPtr1, wxObject*);
289 CPPUNIT_ASSERT(r == dummyWxObjectPointer);
290 void* s = wxANY_AS(m_anyVoidPtr1, void*);
291 CPPUNIT_ASSERT(s == dummyVoidPointer);
292 }
293
294 void wxAnyTestCase::Null()
295 {
296 wxAny a;
297 CPPUNIT_ASSERT(a.IsNull());
298 a = -127;
299 CPPUNIT_ASSERT(a == -127);
300 a.MakeNull();
301 CPPUNIT_ASSERT(a.IsNull());
302 }
303
304 void wxAnyTestCase::GetAs()
305 {
306 //
307 // Test dynamic conversion
308 bool res;
309 long l = 0;
310 short int si = 0;
311 unsigned long ul = 0;
312 wxString s;
313 // Let's test against float instead of double, since the former
314 // is not the native underlying type the code converts to, but
315 // should still work, all the same.
316 float f = 0.0;
317 bool b = false;
318
319 // Conversions from signed long type
320 // The first check should be enough to make sure that the sub-type system
321 // has not failed.
322 res = m_anySignedLong1.GetAs(&si);
323 CPPUNIT_ASSERT(res);
324 CPPUNIT_ASSERT_EQUAL(si, 15);
325 res = m_anySignedLong1.GetAs(&ul);
326 CPPUNIT_ASSERT(res);
327 CPPUNIT_ASSERT_EQUAL(ul, 15UL);
328 res = m_anySignedLong1.GetAs(&s);
329 CPPUNIT_ASSERT(res);
330 CPPUNIT_ASSERT(s == "15");
331 res = m_anySignedLong1.GetAs(&f);
332 CPPUNIT_ASSERT(res);
333 CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
334 res = m_anySignedLong1.GetAs(&b);
335 CPPUNIT_ASSERT(res);
336 CPPUNIT_ASSERT(b == true);
337
338 // Conversions from unsigned long type
339 res = m_anyUnsignedLong1.GetAs(&l);
340 CPPUNIT_ASSERT(res);
341 CPPUNIT_ASSERT(l == static_cast<signed long>(15));
342 res = m_anyUnsignedLong1.GetAs(&s);
343 CPPUNIT_ASSERT(res);
344 CPPUNIT_ASSERT(s == "15");
345 res = m_anyUnsignedLong1.GetAs(&f);
346 CPPUNIT_ASSERT(res);
347 CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
348 res = m_anyUnsignedLong1.GetAs(&b);
349 CPPUNIT_ASSERT(res);
350 CPPUNIT_ASSERT(b == true);
351
352 // Conversions from default "abc" string to other types
353 // should not work.
354 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&l));
355 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&ul));
356 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&f));
357 CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&b));
358
359 // Let's test some other conversions from string that should work.
360 wxAny anyString;
361
362 anyString = "15";
363 res = anyString.GetAs(&l);
364 CPPUNIT_ASSERT(res);
365 CPPUNIT_ASSERT(l == static_cast<signed long>(15));
366 res = anyString.GetAs(&ul);
367 CPPUNIT_ASSERT(res);
368 CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(15));
369 res = anyString.GetAs(&f);
370 CPPUNIT_ASSERT(res);
371 CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
372 anyString = "TRUE";
373 res = anyString.GetAs(&b);
374 CPPUNIT_ASSERT(res);
375 CPPUNIT_ASSERT(b == true);
376 anyString = "0";
377 res = anyString.GetAs(&b);
378 CPPUNIT_ASSERT(res);
379 CPPUNIT_ASSERT(b == false);
380
381 // Conversions from bool type
382 res = m_anyBool1.GetAs(&l);
383 CPPUNIT_ASSERT(res);
384 CPPUNIT_ASSERT(l == static_cast<signed long>(1));
385 res = m_anyBool1.GetAs(&ul);
386 CPPUNIT_ASSERT(res);
387 CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(1));
388 res = m_anyBool1.GetAs(&s);
389 CPPUNIT_ASSERT(res);
390 CPPUNIT_ASSERT(s == "true");
391 CPPUNIT_ASSERT(!m_anyBool1.GetAs(&f));
392
393 // Conversions from floating point type
394 res = m_anyDoubleDouble1.GetAs(&l);
395 CPPUNIT_ASSERT(res);
396 CPPUNIT_ASSERT(l == static_cast<signed long>(123));
397 res = m_anyDoubleDouble1.GetAs(&ul);
398 CPPUNIT_ASSERT(res);
399 CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(123));
400 res = m_anyDoubleDouble1.GetAs(&s);
401 CPPUNIT_ASSERT(res);
402 double d2;
403 res = s.ToDouble(&d2);
404 CPPUNIT_ASSERT(res);
405 CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA);
406 }
407
408
409 //
410 // Test user data type for wxAnyValueTypeImpl specialization
411 // any hand-built wxVariantData
412 //
413
414 class MyClass
415 {
416 public:
417 MyClass( int someValue = 32768 )
418 {
419 m_someValue = someValue;
420 }
421
422 wxString ToString()
423 {
424 return wxString::Format("%i", m_someValue);
425 }
426
427 private:
428 int m_someValue;
429 };
430
431
432 #if wxUSE_VARIANT
433
434 // For testing purposes, create dummy variant data implementation
435 // that does not have wxAny conversion code
436 class wxMyVariantData : public wxVariantData
437 {
438 public:
439 wxMyVariantData(const MyClass& value)
440 {
441 m_value = value;
442 }
443
444 virtual bool Eq(wxVariantData& WXUNUSED(data)) const
445 {
446 return false;
447 }
448
449 // What type is it? Return a string name.
450 virtual wxString GetType() const { return "MyClass"; }
451
452 virtual wxVariantData* Clone() const
453 {
454 return new wxMyVariantData(m_value);
455 }
456
457 protected:
458 MyClass m_value;
459 };
460
461 #endif // wxUSE_VARIANT
462
463
464 void wxAnyTestCase::wxVariantConversions()
465 {
466 #if wxUSE_VARIANT
467 //
468 // Test various conversions to and from wxVariant
469 //
470 bool res;
471
472 // Prepare wxVariants
473 wxVariant vLong(123L);
474 wxVariant vString("ABC");
475 wxVariant vDouble(TEST_FLOAT_CONST);
476 wxVariant vBool((bool)true);
477 wxVariant vChar('A');
478 #ifdef wxLongLong_t
479 wxVariant vLongLong(wxLongLong(wxLL(0xAABBBBCCCC)));
480 wxVariant vULongLong(wxULongLong(wxULL(123456)));
481 #endif
482 wxArrayString arrstr;
483 arrstr.push_back("test string");
484 wxVariant vArrayString(arrstr);
485 wxVariant vDateTime(m_testDateTime);
486 wxVariant vVoidPtr(dummyVoidPointer);
487 wxVariant vCustomType(new wxMyVariantData(MyClass(101)));
488 wxVariant vList;
489
490 vList.NullList();
491 vList.Append(15);
492 vList.Append("abc");
493
494 // Convert to wxAnys, and then back to wxVariants
495 wxVariant variant;
496
497 wxAny any(vLong);
498 CPPUNIT_ASSERT(any == 123L);
499 res = any.GetAs(&variant);
500 CPPUNIT_ASSERT(res);
501 CPPUNIT_ASSERT(variant == 123L);
502
503 // Make sure integer variant has correct type information
504 CPPUNIT_ASSERT(variant.GetLong() == 123);
505 CPPUNIT_ASSERT(variant.GetType() == "long");
506
507 // Unsigned long wxAny should convert to "ulonglong" wxVariant
508 any = 1000UL;
509 res = any.GetAs(&variant);
510 CPPUNIT_ASSERT(res);
511 CPPUNIT_ASSERT(variant.GetType() == "ulonglong");
512 CPPUNIT_ASSERT(variant.GetLong() == 1000);
513
514 any = vString;
515 CPPUNIT_ASSERT(any == "ABC");
516 res = any.GetAs(&variant);
517 CPPUNIT_ASSERT(res);
518 CPPUNIT_ASSERT(variant.GetString() == "ABC");
519
520 // Must be able to build string wxVariant from wxAny built from
521 // string literal
522 any = "ABC";
523 res = any.GetAs(&variant);
524 CPPUNIT_ASSERT(res);
525 CPPUNIT_ASSERT(variant.GetType() == "string");
526 CPPUNIT_ASSERT(variant.GetString() == "ABC");
527 any = L"ABC";
528 res = any.GetAs(&variant);
529 CPPUNIT_ASSERT(res);
530 CPPUNIT_ASSERT(variant.GetType() == "string");
531 CPPUNIT_ASSERT(variant.GetString() == L"ABC");
532
533 any = vDouble;
534 double d = wxANY_AS(any, double);
535 CPPUNIT_ASSERT_DOUBLES_EQUAL(d, TEST_FLOAT_CONST, FEQ_DELTA);
536 res = any.GetAs(&variant);
537 CPPUNIT_ASSERT(res);
538 CPPUNIT_ASSERT_DOUBLES_EQUAL(variant.GetDouble(),
539 TEST_FLOAT_CONST,
540 FEQ_DELTA);
541
542 any = vBool;
543 CPPUNIT_ASSERT(wxANY_AS(any, bool) == true);
544 res = any.GetAs(&variant);
545 CPPUNIT_ASSERT(res);
546 CPPUNIT_ASSERT(variant.GetBool() == true);
547
548 any = wxAny(vChar);
549 //CPPUNIT_ASSERT(wxANY_AS(any, wxUniChar) == 'A');
550 res = any.GetAs(&variant);
551 CPPUNIT_ASSERT(res);
552 CPPUNIT_ASSERT(variant.GetChar() == 'A');
553
554 #ifdef wxLongLong_t
555 any = wxAny(vLongLong);
556 CPPUNIT_ASSERT(any == wxLL(0xAABBBBCCCC));
557 res = any.GetAs(&variant);
558 CPPUNIT_ASSERT(res);
559 CPPUNIT_ASSERT(variant.GetType() == "longlong");
560 CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xAABBBBCCCC)));
561
562 #if LONG_MAX == wxINT64_MAX
563 // As a sanity check, test that wxVariant of type 'long' converts
564 // seamlessly to 'longlong' (on some 64-bit systems)
565 any = 0xAABBBBCCCCL;
566 res = any.GetAs(&variant);
567 CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xAABBBBCCCC)));
568 #endif
569
570 any = wxAny(vULongLong);
571 CPPUNIT_ASSERT(any == wxLL(123456));
572 res = any.GetAs(&variant);
573 CPPUNIT_ASSERT(res);
574 CPPUNIT_ASSERT(variant.GetType() == "ulonglong");
575 CPPUNIT_ASSERT(variant.GetULongLong() == wxULongLong(wxULL(123456)));
576 #endif
577
578 // Cannot test equality for the rest, just test that they convert
579 // back correctly.
580 any = wxAny(vArrayString);
581 res = any.GetAs(&variant);
582 CPPUNIT_ASSERT(res);
583 wxArrayString arrstr2 = variant.GetArrayString();
584 CPPUNIT_ASSERT(arrstr2 == arrstr);
585
586 any = m_testDateTime;
587 CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
588 any = wxAny(vDateTime);
589 CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
590 res = any.GetAs(&variant);
591 CPPUNIT_ASSERT(res);
592 CPPUNIT_ASSERT(variant == m_testDateTime);
593
594 any = wxAny(vVoidPtr);
595 res = any.GetAs(&variant);
596 CPPUNIT_ASSERT(res);
597 CPPUNIT_ASSERT(variant.GetVoidPtr() == dummyVoidPointer);
598
599 any = wxAny(vList);
600 CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxAnyList));
601 wxAnyList anyList = wxANY_AS(any, wxAnyList);
602 CPPUNIT_ASSERT(anyList.GetCount() == 2);
603 CPPUNIT_ASSERT(wxANY_AS((*anyList[0]), int) == 15);
604 CPPUNIT_ASSERT(wxANY_AS((*anyList[1]), wxString) == "abc");
605 res = any.GetAs(&variant);
606 CPPUNIT_ASSERT(res);
607 CPPUNIT_ASSERT(variant.GetType() == "list");
608 CPPUNIT_ASSERT(variant.GetCount() == 2);
609 CPPUNIT_ASSERT(variant[0].GetLong() == 15);
610 CPPUNIT_ASSERT(variant[1].GetString() == "abc");
611
612 any = wxAny(vCustomType);
613 CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxVariantData*));
614 res = any.GetAs(&variant);
615 CPPUNIT_ASSERT(res);
616 CPPUNIT_ASSERT(variant.GetType() == "MyClass");
617
618 #endif // wxUSE_VARIANT
619 }
620
621 template<>
622 class wxAnyValueTypeImpl<MyClass> :
623 public wxAnyValueTypeImplBase<MyClass>
624 {
625 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)
626 public:
627 wxAnyValueTypeImpl() :
628 wxAnyValueTypeImplBase<MyClass>() { }
629 virtual ~wxAnyValueTypeImpl() { }
630
631 virtual bool ConvertValue(const wxAnyValueBuffer& src,
632 wxAnyValueType* dstType,
633 wxAnyValueBuffer& dst) const
634 {
635 MyClass value = GetValue(src);
636
637 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
638 {
639 wxString s = value.ToString();
640 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
641 }
642 else
643 return false;
644
645 return true;
646 }
647 };
648
649 //
650 // Following must be placed somewhere in your source code
651 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)
652
653 void wxAnyTestCase::CustomTemplateSpecialization()
654 {
655 // Do only a minimal CheckType() test, as dynamic type conversion already
656 // uses it a lot.
657 bool res;
658 MyClass myObject;
659 wxAny any = myObject;
660
661 CPPUNIT_ASSERT( wxANY_CHECK_TYPE(any, MyClass) );
662 MyClass myObject2 = wxANY_AS(any, MyClass);
663 wxUnusedVar(myObject2);
664
665 wxString str;
666 res = any.GetAs(&str);
667 CPPUNIT_ASSERT(res);
668 CPPUNIT_ASSERT_EQUAL(str, myObject.ToString());
669 }
670
671 #endif // wxUSE_ANY
672