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