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