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