-///////////////////////////////////////////////////////////////////////////////\r
-// Name: tests/any/anytest.cpp\r
-// Purpose: Test the wxAny classes\r
-// Author: Jaakko Salli\r
-// RCS-ID: $Id$\r
-// Copyright: (c) the wxWidgets team\r
-// Licence: wxWindows licence\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#include "testprec.h"\r
-\r
-#ifdef __BORLANDC__\r
-# pragma hdrstop\r
-#endif\r
-\r
-#if wxUSE_ANY\r
-\r
-#include "wx/any.h"\r
-#include "wx/datetime.h"\r
-\r
-#include <math.h>\r
-\r
-// ----------------------------------------------------------------------------\r
-// test class\r
-// ----------------------------------------------------------------------------\r
-\r
-class wxAnyTestCase : public CppUnit::TestCase\r
-{\r
-public:\r
- wxAnyTestCase();\r
-\r
-private:\r
- CPPUNIT_TEST_SUITE( wxAnyTestCase );\r
- CPPUNIT_TEST( Equality );\r
- CPPUNIT_TEST( As );\r
- CPPUNIT_TEST( GetAs );\r
- CPPUNIT_TEST( Null );\r
- CPPUNIT_TEST( CustomTemplateSpecialization );\r
- CPPUNIT_TEST_SUITE_END();\r
-\r
- void Equality();\r
- void As();\r
- void GetAs();\r
- void Null();\r
- void CustomTemplateSpecialization();\r
-\r
- wxDateTime m_testDateTime;\r
-\r
- wxAny m_anySignedChar1;\r
- wxAny m_anySignedShort1;\r
- wxAny m_anySignedInt1;\r
- wxAny m_anySignedLong1;\r
- wxAny m_anySignedLongLong1;\r
- wxAny m_anyUnsignedChar1;\r
- wxAny m_anyUnsignedShort1;\r
- wxAny m_anyUnsignedInt1;\r
- wxAny m_anyUnsignedLong1;\r
- wxAny m_anyUnsignedLongLong1;\r
- wxAny m_anyStringString1;\r
- wxAny m_anyCharString1;\r
- wxAny m_anyWcharString1;\r
- wxAny m_anyBool1;\r
- wxAny m_anyFloatDouble1;\r
- wxAny m_anyDoubleDouble1;\r
- wxAny m_anyWxObjectPtr1;\r
- wxAny m_anyVoidPtr1;\r
- wxAny m_anyDateTime1;\r
-\r
- wxAny m_anySignedChar2;\r
- wxAny m_anySignedShort2;\r
- wxAny m_anySignedInt2;\r
- wxAny m_anySignedLong2;\r
- wxAny m_anySignedLongLong2;\r
- wxAny m_anyUnsignedChar2;\r
- wxAny m_anyUnsignedShort2;\r
- wxAny m_anyUnsignedInt2;\r
- wxAny m_anyUnsignedLong2;\r
- wxAny m_anyUnsignedLongLong2;\r
- wxAny m_anyStringString2;\r
- wxAny m_anyCharString2;\r
- wxAny m_anyWcharString2;\r
- wxAny m_anyBool2;\r
- wxAny m_anyFloatDouble2;\r
- wxAny m_anyDoubleDouble2;\r
- wxAny m_anyWxObjectPtr2;\r
- wxAny m_anyVoidPtr2;\r
- wxAny m_anyDateTime2;\r
-\r
- DECLARE_NO_COPY_CLASS(wxAnyTestCase)\r
-};\r
-\r
-// register in the unnamed registry so that these tests are run by default\r
-CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase );\r
-\r
-// also include in it's own registry so that these tests can be run alone\r
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( wxAnyTestCase, "wxAnyTestCase" );\r
-\r
-// Let's use a number with first digit after decimal dot less than 5,\r
-// so that we don't have to worry about whether conversion from float\r
-// to int truncates or rounds.\r
-const double TEST_FLOAT_CONST = 123.456;\r
-\r
-const double FEQ_DELTA = 0.001;\r
-\r
-wxObject* dummyWxObjectPointer = reinterpret_cast<wxObject*>(1234);\r
-void* dummyVoidPointer = reinterpret_cast<void*>(1234);\r
-\r
-\r
-//\r
-// Test both 'creation' methods\r
-wxAnyTestCase::wxAnyTestCase()\r
- : m_anySignedChar1((signed char)15),\r
- m_anySignedShort1((signed short)15),\r
- m_anySignedInt1((signed int)15),\r
- m_anySignedLong1((signed long)15),\r
-#ifdef wxLongLong_t\r
- m_anySignedLongLong1((wxLongLong_t)15),\r
-#endif\r
- m_anyUnsignedChar1((unsigned char)15),\r
- m_anyUnsignedShort1((unsigned short)15),\r
- m_anyUnsignedInt1((unsigned int)15),\r
- m_anyUnsignedLong1((unsigned long)15),\r
-#ifdef wxLongLong_t\r
- m_anyUnsignedLongLong1((wxULongLong_t)15),\r
-#endif\r
- m_anyStringString1(wxString("abc")),\r
- m_anyCharString1("abc"),\r
- m_anyWcharString1(L"abc"),\r
- m_anyBool1(true),\r
- m_anyFloatDouble1((float)TEST_FLOAT_CONST),\r
- m_anyDoubleDouble1((double)TEST_FLOAT_CONST),\r
- m_anyWxObjectPtr1(dummyWxObjectPointer),\r
- m_anyVoidPtr1(dummyVoidPointer),\r
- m_anyDateTime1(wxDateTime::Now())\r
-{\r
- m_testDateTime = wxDateTime::Now();\r
- m_anySignedChar2 = (signed char)15;\r
- m_anySignedShort2 = (signed short)15;\r
- m_anySignedInt2 = (signed int)15;\r
- m_anySignedLong2 = (signed long)15;\r
-#ifdef wxLongLong_t\r
- m_anySignedLongLong2 = (wxLongLong_t)15;\r
-#endif\r
- m_anyUnsignedChar2 = (unsigned char)15;\r
- m_anyUnsignedShort2 = (unsigned short)15;\r
- m_anyUnsignedInt2 = (unsigned int)15;\r
- m_anyUnsignedLong2 = (unsigned long)15;\r
-#ifdef wxLongLong_t\r
- m_anyUnsignedLongLong2 = (wxULongLong_t)15;\r
-#endif\r
- m_anyStringString2 = wxString("abc");\r
- m_anyCharString2 = "abc";\r
- m_anyWcharString2 = L"abc";\r
- m_anyBool2 = true;\r
- m_anyFloatDouble2 = (float)TEST_FLOAT_CONST;\r
- m_anyDoubleDouble2 = (double)TEST_FLOAT_CONST;\r
- m_anyDateTime2 = m_testDateTime;\r
- m_anyWxObjectPtr2 = dummyWxObjectPointer;\r
- m_anyVoidPtr2 = dummyVoidPointer;\r
-}\r
-\r
-void wxAnyTestCase::Equality()\r
-{\r
- //\r
- // Currently this should work\r
- CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15L);\r
- CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30L);\r
- CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15UL);\r
- CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30UL);\r
- CPPUNIT_ASSERT(m_anyStringString1 == wxString("abc"));\r
- CPPUNIT_ASSERT(m_anyStringString1 != wxString("ABC"));\r
- CPPUNIT_ASSERT(m_anyStringString1 == "abc");\r
- CPPUNIT_ASSERT(m_anyStringString1 != "ABC");\r
- CPPUNIT_ASSERT(m_anyStringString1 == L"abc");\r
- CPPUNIT_ASSERT(m_anyStringString1 != L"ABC");\r
- CPPUNIT_ASSERT(m_anyBool1 == true);\r
- CPPUNIT_ASSERT(m_anyBool1 != false);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),\r
- wxANY_AS(m_anyDoubleDouble1, double),\r
- FEQ_DELTA);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),\r
- TEST_FLOAT_CONST,\r
- FEQ_DELTA);\r
- CPPUNIT_ASSERT(m_anyWxObjectPtr1.As<wxObject*>() == dummyWxObjectPointer);\r
- CPPUNIT_ASSERT(m_anyVoidPtr1.As<void*>() == dummyVoidPointer);\r
-\r
- CPPUNIT_ASSERT(m_anySignedLong2 == 15);\r
- CPPUNIT_ASSERT(m_anyStringString2 == wxString("abc"));\r
- CPPUNIT_ASSERT(m_anyStringString2 == "abc");\r
- CPPUNIT_ASSERT(m_anyStringString2 == L"abc");\r
- CPPUNIT_ASSERT(m_anyBool2 == true);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),\r
- wxANY_AS(m_anyDoubleDouble2, double),\r
- FEQ_DELTA);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),\r
- TEST_FLOAT_CONST,\r
- FEQ_DELTA);\r
- CPPUNIT_ASSERT(m_anyWxObjectPtr2.As<wxObject*>() == dummyWxObjectPointer);\r
- CPPUNIT_ASSERT(m_anyVoidPtr2.As<void*>() == dummyVoidPointer);\r
-}\r
-\r
-void wxAnyTestCase::As()\r
-{\r
- //\r
- // Test getting C++ data from wxAny without dynamic conversion\r
- signed char a = wxANY_AS(m_anySignedChar1, signed char);\r
- CPPUNIT_ASSERT(a == (signed int)15);\r
- signed short b = wxANY_AS(m_anySignedShort1, signed short);\r
- CPPUNIT_ASSERT(b == (signed int)15);\r
- signed int c = wxANY_AS(m_anySignedInt1, signed int);\r
- CPPUNIT_ASSERT(c == (signed int)15);\r
- signed long d = wxANY_AS(m_anySignedLong1, signed long);\r
- CPPUNIT_ASSERT(d == (signed int)15);\r
-#ifdef wxLongLong_t\r
- wxLongLong_t e = wxANY_AS(m_anySignedLongLong1, wxLongLong_t);\r
- CPPUNIT_ASSERT(e == (signed int)15);\r
-#endif\r
- unsigned char f = wxANY_AS(m_anyUnsignedChar1, unsigned char);\r
- CPPUNIT_ASSERT(f == (unsigned int)15);\r
- unsigned short g = wxANY_AS(m_anyUnsignedShort1, unsigned short);\r
- CPPUNIT_ASSERT(g == (unsigned int)15);\r
- unsigned int h = wxANY_AS(m_anyUnsignedInt1, unsigned int);\r
- CPPUNIT_ASSERT(h == (unsigned int)15);\r
- unsigned long i = wxANY_AS(m_anyUnsignedLong1, unsigned long);\r
- CPPUNIT_ASSERT(i == (unsigned int)15);\r
-#ifdef wxLongLong_t\r
- wxULongLong_t j = wxANY_AS(m_anyUnsignedLongLong1, wxULongLong_t);\r
- CPPUNIT_ASSERT(j == (unsigned int)15);\r
-#endif\r
- wxString k = wxANY_AS(m_anyStringString1, wxString);\r
- CPPUNIT_ASSERT(k == "abc");\r
- wxString l = wxANY_AS(m_anyCharString1, wxString);\r
- CPPUNIT_ASSERT(l == "abc");\r
- wxString m = wxANY_AS(m_anyWcharString1, wxString);\r
- CPPUNIT_ASSERT(m == "abc");\r
- bool n = wxANY_AS(m_anyBool1, bool);\r
- CPPUNIT_ASSERT(n);\r
- float o = wxANY_AS(m_anyFloatDouble1, float);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(o, TEST_FLOAT_CONST, FEQ_DELTA);\r
- double p = wxANY_AS(m_anyDoubleDouble1, double);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(p, TEST_FLOAT_CONST, FEQ_DELTA);\r
- wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime);\r
- CPPUNIT_ASSERT(q == m_testDateTime);\r
- wxObject* r = wxANY_AS(m_anyWxObjectPtr1, wxObject*);\r
- CPPUNIT_ASSERT(r == dummyWxObjectPointer);\r
- void* s = wxANY_AS(m_anyVoidPtr1, void*);\r
- CPPUNIT_ASSERT(s == dummyVoidPointer);\r
-}\r
-\r
-void wxAnyTestCase::Null()\r
-{\r
- wxAny a;\r
- CPPUNIT_ASSERT(a.IsNull());\r
- a = -127;\r
- CPPUNIT_ASSERT(a == -127);\r
- a.MakeNull();\r
- CPPUNIT_ASSERT(a.IsNull());\r
-}\r
-\r
-void wxAnyTestCase::GetAs()\r
-{\r
- //\r
- // Test dynamic conversion\r
- bool res;\r
- long l = 0;\r
- unsigned long ul = 0;\r
- wxString s;\r
- // Let's test against float instead of double, since the former\r
- // is not the native underlying type the code converts to, but\r
- // should still work, all the same.\r
- float f = 0.0;\r
- bool b = false;\r
-\r
- // Conversions from signed long type\r
- res = m_anySignedLong1.GetAs(&ul);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(15));\r
- res = m_anySignedLong1.GetAs(&s);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(s == "15");\r
- res = m_anySignedLong1.GetAs(&f);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);\r
- res = m_anySignedLong1.GetAs(&b);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(b == true);\r
-\r
- // Conversions from unsigned long type\r
- res = m_anyUnsignedLong1.GetAs(&l);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(l == static_cast<signed long>(15));\r
- res = m_anyUnsignedLong1.GetAs(&s);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(s == "15");\r
- res = m_anyUnsignedLong1.GetAs(&f);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);\r
- res = m_anyUnsignedLong1.GetAs(&b);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(b == true);\r
-\r
- // Conversions from default "abc" string to other types\r
- // should not work.\r
- CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&l));\r
- CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&ul));\r
- CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&f));\r
- CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&b));\r
-\r
- // Let's test some other conversions from string that should work.\r
- wxAny anyString;\r
-\r
- anyString = "15";\r
- res = anyString.GetAs(&l);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(l == static_cast<signed long>(15));\r
- res = anyString.GetAs(&ul);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(15));\r
- res = anyString.GetAs(&f);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);\r
- anyString = "TRUE";\r
- res = anyString.GetAs(&b);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(b == true);\r
- anyString = "0";\r
- res = anyString.GetAs(&b);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(b == false);\r
-\r
- // Conversions from bool type\r
- res = m_anyBool1.GetAs(&l);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(l == static_cast<signed long>(1));\r
- res = m_anyBool1.GetAs(&ul);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(1));\r
- res = m_anyBool1.GetAs(&s);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(s == "true");\r
- CPPUNIT_ASSERT(!m_anyBool1.GetAs(&f));\r
-\r
- // Conversions from floating point type\r
- res = m_anyDoubleDouble1.GetAs(&l);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT(l == static_cast<signed long>(123));\r
- res = m_anyDoubleDouble1.GetAs(&ul);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(123));\r
- res = m_anyDoubleDouble1.GetAs(&s);\r
- CPPUNIT_ASSERT(res);\r
- double d2;\r
- res = s.ToDouble(&d2);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA);\r
-}\r
-\r
-//\r
-// Test user data type specialization of wxAnyValueTypeImpl\r
-//\r
-\r
-class MyClass\r
-{\r
-public:\r
- MyClass( int someValue = 32768 )\r
- {\r
- m_someValue = someValue;\r
- }\r
-\r
- wxString ToString()\r
- {\r
- return wxString::Format("%i", m_someValue);\r
- }\r
-\r
-private:\r
- int m_someValue;\r
-};\r
-\r
-\r
-template<>\r
-class wxAnyValueTypeImpl<MyClass> :\r
- public wxAnyValueTypeImplBase<MyClass>\r
-{\r
- WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)\r
-public:\r
- wxAnyValueTypeImpl() :\r
- wxAnyValueTypeImplBase<MyClass>() { }\r
- virtual ~wxAnyValueTypeImpl() { }\r
-\r
- virtual bool ConvertValue(const wxAnyValueBuffer& src,\r
- wxAnyValueType* dstType,\r
- wxAnyValueBuffer& dst) const\r
- {\r
- MyClass value = GetValue(src);\r
-\r
- if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )\r
- {\r
- wxString s = value.ToString();\r
- wxAnyValueTypeImpl<wxString>::SetValue(s, dst);\r
- }\r
- else\r
- return false;\r
-\r
- return true;\r
- }\r
-};\r
-\r
-//\r
-// Following must be placed somewhere in your source code\r
-WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)\r
-\r
-void wxAnyTestCase::CustomTemplateSpecialization()\r
-{\r
- // Do only a minimal CheckType() test, as dynamic type conversion already\r
- // uses it a lot.\r
- bool res;\r
- MyClass myObject;\r
- wxAny any = myObject;\r
-\r
- CPPUNIT_ASSERT( wxANY_CHECK_TYPE(any, MyClass) );\r
- MyClass myObject2 = wxANY_AS(any, MyClass);\r
- wxUnusedVar(myObject2);\r
-\r
- wxString str;\r
- res = any.GetAs(&str);\r
- CPPUNIT_ASSERT(res);\r
- CPPUNIT_ASSERT_EQUAL(str, myObject.ToString());\r
-}\r
-\r
-#endif // wxUSE_ANY\r
-\r
+///////////////////////////////////////////////////////////////////////////////
+// Name: tests/any/anytest.cpp
+// Purpose: Test the wxAny classes
+// Author: Jaakko Salli
+// RCS-ID: $Id$
+// Copyright: (c) the wxWidgets team
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#include "testprec.h"
+
+#ifdef __BORLANDC__
+# pragma hdrstop
+#endif
+
+#if wxUSE_ANY
+
+#include "wx/any.h"
+#include "wx/datetime.h"
+#include "wx/object.h"
+#include "wx/vector.h"
+
+#include <math.h>
+
+// ----------------------------------------------------------------------------
+// test class
+// ----------------------------------------------------------------------------
+
+class wxAnyTestCase : public CppUnit::TestCase
+{
+public:
+ wxAnyTestCase();
+
+private:
+ CPPUNIT_TEST_SUITE( wxAnyTestCase );
+ CPPUNIT_TEST( CheckType );
+ CPPUNIT_TEST( Equality );
+ CPPUNIT_TEST( As );
+ CPPUNIT_TEST( GetAs );
+ CPPUNIT_TEST( Null );
+ CPPUNIT_TEST( wxVariantConversions );
+ CPPUNIT_TEST( CustomTemplateSpecialization );
+ CPPUNIT_TEST( Misc );
+ CPPUNIT_TEST_SUITE_END();
+
+ void CheckType();
+ void Equality();
+ void As();
+ void GetAs();
+ void Null();
+ void wxVariantConversions();
+ void CustomTemplateSpecialization();
+ void Misc();
+
+ wxDateTime m_testDateTime;
+
+ wxAny m_anySignedChar1;
+ wxAny m_anySignedShort1;
+ wxAny m_anySignedInt1;
+ wxAny m_anySignedLong1;
+ wxAny m_anySignedLongLong1;
+ wxAny m_anyUnsignedChar1;
+ wxAny m_anyUnsignedShort1;
+ wxAny m_anyUnsignedInt1;
+ wxAny m_anyUnsignedLong1;
+ wxAny m_anyUnsignedLongLong1;
+ wxAny m_anyStringString1;
+ wxAny m_anyCharString1;
+ wxAny m_anyWcharString1;
+ wxAny m_anyBool1;
+ wxAny m_anyFloatDouble1;
+ wxAny m_anyDoubleDouble1;
+ wxAny m_anyWxObjectPtr1;
+ wxAny m_anyVoidPtr1;
+ wxAny m_anyDateTime1;
+ wxAny m_anyUniChar1;
+
+ wxAny m_anySignedChar2;
+ wxAny m_anySignedShort2;
+ wxAny m_anySignedInt2;
+ wxAny m_anySignedLong2;
+ wxAny m_anySignedLongLong2;
+ wxAny m_anyUnsignedChar2;
+ wxAny m_anyUnsignedShort2;
+ wxAny m_anyUnsignedInt2;
+ wxAny m_anyUnsignedLong2;
+ wxAny m_anyUnsignedLongLong2;
+ wxAny m_anyStringString2;
+ wxAny m_anyCharString2;
+ wxAny m_anyWcharString2;
+ wxAny m_anyBool2;
+ wxAny m_anyFloatDouble2;
+ wxAny m_anyDoubleDouble2;
+ wxAny m_anyWxObjectPtr2;
+ wxAny m_anyVoidPtr2;
+ wxAny m_anyDateTime2;
+
+ DECLARE_NO_COPY_CLASS(wxAnyTestCase)
+};
+
+// register in the unnamed registry so that these tests are run by default
+CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase );
+
+// also include in its own registry so that these tests can be run alone
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( wxAnyTestCase, "wxAnyTestCase" );
+
+// Let's use a number with first digit after decimal dot less than 5,
+// so that we don't have to worry about whether conversion from float
+// to int truncates or rounds.
+const float TEST_FLOAT_CONST = 123.456f;
+const double TEST_DOUBLE_CONST = 123.456;
+
+const double FEQ_DELTA = 0.001;
+
+wxObject* dummyWxObjectPointer = reinterpret_cast<wxObject*>(1234);
+void* dummyVoidPointer = reinterpret_cast<void*>(1234);
+
+
+//
+// Test both 'creation' methods
+wxAnyTestCase::wxAnyTestCase()
+ : m_anySignedChar1((signed char)15),
+ m_anySignedShort1((signed short)15),
+ m_anySignedInt1((signed int)15),
+ m_anySignedLong1((signed long)15),
+#ifdef wxLongLong_t
+ m_anySignedLongLong1((wxLongLong_t)15),
+#endif
+ m_anyUnsignedChar1((unsigned char)15),
+ m_anyUnsignedShort1((unsigned short)15),
+ m_anyUnsignedInt1((unsigned int)15),
+ m_anyUnsignedLong1((unsigned long)15),
+#ifdef wxLongLong_t
+ m_anyUnsignedLongLong1((wxULongLong_t)15),
+#endif
+ m_anyStringString1(wxString("abc")),
+ m_anyCharString1("abc"),
+ m_anyWcharString1(L"abc"),
+ m_anyBool1(true),
+ m_anyFloatDouble1(TEST_FLOAT_CONST),
+ m_anyDoubleDouble1(TEST_DOUBLE_CONST),
+ m_anyWxObjectPtr1(dummyWxObjectPointer),
+ m_anyVoidPtr1(dummyVoidPointer),
+ m_anyDateTime1(wxDateTime::Now())
+{
+ m_testDateTime = wxDateTime::Now();
+ m_anySignedChar2 = (signed char)15;
+ m_anySignedShort2 = (signed short)15;
+ m_anySignedInt2 = (signed int)15;
+ m_anySignedLong2 = (signed long)15;
+#ifdef wxLongLong_t
+ m_anySignedLongLong2 = (wxLongLong_t)15;
+#endif
+ m_anyUnsignedChar2 = (unsigned char)15;
+ m_anyUnsignedShort2 = (unsigned short)15;
+ m_anyUnsignedInt2 = (unsigned int)15;
+ m_anyUnsignedLong2 = (unsigned long)15;
+#ifdef wxLongLong_t
+ m_anyUnsignedLongLong2 = (wxULongLong_t)15;
+#endif
+ m_anyStringString2 = wxString("abc");
+ m_anyCharString2 = "abc";
+ m_anyWcharString2 = L"abc";
+ m_anyBool2 = true;
+ m_anyFloatDouble2 = TEST_FLOAT_CONST;
+ m_anyDoubleDouble2 = TEST_DOUBLE_CONST;
+ m_anyDateTime2 = m_testDateTime;
+ m_anyUniChar1 = wxUniChar('A');
+ m_anyWxObjectPtr2 = dummyWxObjectPointer;
+ m_anyVoidPtr2 = dummyVoidPointer;
+}
+
+void wxAnyTestCase::CheckType()
+{
+ wxAny nullAny;
+ CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(nullAny, wxString));
+
+ CPPUNIT_ASSERT(wxANY_CHECK_TYPE(m_anyCharString2, const char*));
+ CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyCharString2, wxString));
+ CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyCharString2, const wchar_t*));
+ CPPUNIT_ASSERT(wxANY_CHECK_TYPE(m_anyWcharString2, const wchar_t*));
+ CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyWcharString2, wxString));
+ CPPUNIT_ASSERT(!wxANY_CHECK_TYPE(m_anyWcharString2, const char*));
+
+ // HasSameType()
+ CPPUNIT_ASSERT( m_anyWcharString1.HasSameType(m_anyWcharString2) );
+ CPPUNIT_ASSERT( !m_anyWcharString1.HasSameType(m_anyBool1) );
+}
+
+void wxAnyTestCase::Equality()
+{
+ //
+ // Currently this should work
+ CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15L);
+ CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30L);
+ CPPUNIT_ASSERT(m_anyUnsignedLong1 == 15UL);
+ CPPUNIT_ASSERT(m_anyUnsignedLong1 != 30UL);
+ CPPUNIT_ASSERT(m_anyStringString1 == wxString("abc"));
+ CPPUNIT_ASSERT(m_anyStringString1 != wxString("ABC"));
+ CPPUNIT_ASSERT(m_anyStringString1 == "abc");
+ CPPUNIT_ASSERT(m_anyStringString1 != "ABC");
+ CPPUNIT_ASSERT(m_anyStringString1 == L"abc");
+ CPPUNIT_ASSERT(m_anyStringString1 != L"ABC");
+ CPPUNIT_ASSERT(m_anyBool1 == true);
+ CPPUNIT_ASSERT(m_anyBool1 != false);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),
+ wxANY_AS(m_anyDoubleDouble1, double),
+ FEQ_DELTA);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble1, double),
+ TEST_FLOAT_CONST,
+ FEQ_DELTA);
+ CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr1, wxObject*)
+ == dummyWxObjectPointer);
+ CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr1, void*) == dummyVoidPointer);
+
+ CPPUNIT_ASSERT(m_anySignedLong2 == 15);
+ CPPUNIT_ASSERT(m_anyStringString2 == wxString("abc"));
+ CPPUNIT_ASSERT(m_anyStringString2 == "abc");
+ CPPUNIT_ASSERT(m_anyStringString2 == L"abc");
+ CPPUNIT_ASSERT(m_anyBool2 == true);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),
+ wxANY_AS(m_anyDoubleDouble2, double),
+ FEQ_DELTA);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(wxANY_AS(m_anyFloatDouble2, double),
+ TEST_FLOAT_CONST,
+ FEQ_DELTA);
+ CPPUNIT_ASSERT(wxANY_AS(m_anyWxObjectPtr2, wxObject*)
+ == dummyWxObjectPointer);
+ CPPUNIT_ASSERT(wxANY_AS(m_anyVoidPtr2, void*) == dummyVoidPointer);
+
+ // Test sub-type system type compatibility
+ CPPUNIT_ASSERT(m_anySignedShort1.GetType()->
+ IsSameType(m_anySignedLongLong1.GetType()));
+ CPPUNIT_ASSERT(m_anyUnsignedShort1.GetType()->
+ IsSameType(m_anyUnsignedLongLong1.GetType()));
+}
+
+void wxAnyTestCase::As()
+{
+ //
+ // Test getting C++ data from wxAny without dynamic conversion
+ signed char a = wxANY_AS(m_anySignedChar1, signed char);
+ CPPUNIT_ASSERT(a == (signed int)15);
+ signed short b = wxANY_AS(m_anySignedShort1, signed short);
+ CPPUNIT_ASSERT(b == (signed int)15);
+ signed int c = wxANY_AS(m_anySignedInt1, signed int);
+ CPPUNIT_ASSERT(c == (signed int)15);
+ signed long d = wxANY_AS(m_anySignedLong1, signed long);
+ CPPUNIT_ASSERT(d == (signed int)15);
+#ifdef wxLongLong_t
+ wxLongLong_t e = wxANY_AS(m_anySignedLongLong1, wxLongLong_t);
+ CPPUNIT_ASSERT(e == (signed int)15);
+#endif
+ unsigned char f = wxANY_AS(m_anyUnsignedChar1, unsigned char);
+ CPPUNIT_ASSERT(f == (unsigned int)15);
+ unsigned short g = wxANY_AS(m_anyUnsignedShort1, unsigned short);
+ CPPUNIT_ASSERT(g == (unsigned int)15);
+ unsigned int h = wxANY_AS(m_anyUnsignedInt1, unsigned int);
+ CPPUNIT_ASSERT(h == (unsigned int)15);
+ unsigned long i = wxANY_AS(m_anyUnsignedLong1, unsigned long);
+ CPPUNIT_ASSERT(i == (unsigned int)15);
+#ifdef wxLongLong_t
+ wxULongLong_t j = wxANY_AS(m_anyUnsignedLongLong1, wxULongLong_t);
+ CPPUNIT_ASSERT(j == (unsigned int)15);
+#endif
+ wxString k = wxANY_AS(m_anyStringString1, wxString);
+ CPPUNIT_ASSERT(k == "abc");
+ wxString l = wxANY_AS(m_anyCharString1, wxString);
+ const char* cptr = wxANY_AS(m_anyCharString1, const char*);
+ CPPUNIT_ASSERT(l == "abc");
+ CPPUNIT_ASSERT(cptr);
+ wxString m = wxANY_AS(m_anyWcharString1, wxString);
+ const wchar_t* wcptr = wxANY_AS(m_anyWcharString1, const wchar_t*);
+ CPPUNIT_ASSERT(wcptr);
+ CPPUNIT_ASSERT(m == "abc");
+ bool n = wxANY_AS(m_anyBool1, bool);
+ CPPUNIT_ASSERT(n);
+
+ // Make sure the stored float that comes back is -identical-.
+ // So do not use delta comparison here.
+ float o = wxANY_AS(m_anyFloatDouble1, float);
+ CPPUNIT_ASSERT_EQUAL(o, TEST_FLOAT_CONST);
+
+ double p = wxANY_AS(m_anyDoubleDouble1, double);
+ CPPUNIT_ASSERT_EQUAL(p, TEST_DOUBLE_CONST);
+
+ wxUniChar chr = wxANY_AS(m_anyUniChar1, wxUniChar);
+ CPPUNIT_ASSERT(chr == 'A');
+ wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime);
+ CPPUNIT_ASSERT(q == m_testDateTime);
+ wxObject* r = wxANY_AS(m_anyWxObjectPtr1, wxObject*);
+ CPPUNIT_ASSERT(r == dummyWxObjectPointer);
+ void* s = wxANY_AS(m_anyVoidPtr1, void*);
+ CPPUNIT_ASSERT(s == dummyVoidPointer);
+}
+
+void wxAnyTestCase::Null()
+{
+ wxAny a;
+ CPPUNIT_ASSERT(a.IsNull());
+ a = -127;
+ CPPUNIT_ASSERT(a == -127);
+ a.MakeNull();
+ CPPUNIT_ASSERT(a.IsNull());
+}
+
+void wxAnyTestCase::GetAs()
+{
+ //
+ // Test dynamic conversion
+ bool res;
+ long l = 0;
+ short int si = 0;
+ unsigned long ul = 0;
+ wxString s;
+ // Let's test against float instead of double, since the former
+ // is not the native underlying type the code converts to, but
+ // should still work, all the same.
+ float f = 0.0;
+ bool b = false;
+
+ // Conversions from signed long type
+ // The first check should be enough to make sure that the sub-type system
+ // has not failed.
+ res = m_anySignedLong1.GetAs(&si);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_EQUAL(si, 15);
+ res = m_anySignedLong1.GetAs(&ul);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_EQUAL(ul, 15UL);
+ res = m_anySignedLong1.GetAs(&s);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(s == "15");
+ res = m_anySignedLong1.GetAs(&f);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
+ res = m_anySignedLong1.GetAs(&b);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(b == true);
+
+ // Conversions from unsigned long type
+ res = m_anyUnsignedLong1.GetAs(&l);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(l == static_cast<signed long>(15));
+ res = m_anyUnsignedLong1.GetAs(&s);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(s == "15");
+ res = m_anyUnsignedLong1.GetAs(&f);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
+ res = m_anyUnsignedLong1.GetAs(&b);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(b == true);
+
+ // Conversions from default "abc" string to other types
+ // should not work.
+ CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&l));
+ CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&ul));
+ CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&f));
+ CPPUNIT_ASSERT(!m_anyStringString1.GetAs(&b));
+
+ // Let's test some other conversions from string that should work.
+ wxAny anyString;
+
+ anyString = "15";
+ res = anyString.GetAs(&l);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(l == static_cast<signed long>(15));
+ res = anyString.GetAs(&ul);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(15));
+ res = anyString.GetAs(&f);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(f, 15.0, FEQ_DELTA);
+ anyString = "TRUE";
+ res = anyString.GetAs(&b);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(b == true);
+ anyString = "0";
+ res = anyString.GetAs(&b);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(b == false);
+
+ // Conversions from bool type
+ res = m_anyBool1.GetAs(&l);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(l == static_cast<signed long>(1));
+ res = m_anyBool1.GetAs(&ul);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(1));
+ res = m_anyBool1.GetAs(&s);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(s == "true");
+ CPPUNIT_ASSERT(!m_anyBool1.GetAs(&f));
+
+ // Conversions from floating point type
+ res = m_anyDoubleDouble1.GetAs(&l);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(l == static_cast<signed long>(123));
+ res = m_anyDoubleDouble1.GetAs(&ul);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_EQUAL(ul, static_cast<unsigned long>(123));
+ res = m_anyDoubleDouble1.GetAs(&s);
+ CPPUNIT_ASSERT(res);
+ double d2;
+ res = s.ToDouble(&d2);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA);
+}
+
+
+//
+// Test user data type for wxAnyValueTypeImpl specialization
+// any hand-built wxVariantData. Also for inplace allocation
+// sanity checks.
+//
+
+class MyClass;
+
+static wxVector<MyClass*> gs_myClassInstances;
+
+class MyClass
+{
+public:
+ MyClass( int someValue = 32768 )
+ {
+ Init();
+ m_someValue = someValue;
+ }
+ MyClass( const MyClass& other )
+ {
+ Init();
+ m_someValue = other.m_someValue;
+ }
+ virtual ~MyClass()
+ {
+ for ( size_t i=0; i<gs_myClassInstances.size(); i++ )
+ {
+ if ( gs_myClassInstances[i] == this )
+ {
+ gs_myClassInstances.erase(gs_myClassInstances.begin()+i);
+ }
+ }
+ }
+
+ int GetValue() const
+ {
+ return m_someValue;
+ }
+
+ wxString ToString()
+ {
+ return wxString::Format("%i", m_someValue);
+ }
+
+private:
+ void Init()
+ {
+ // We use this for some sanity checking
+ gs_myClassInstances.push_back(this);
+ }
+
+ int m_someValue;
+};
+
+
+#if wxUSE_VARIANT
+
+// For testing purposes, create dummy variant data implementation
+// that does not have wxAny conversion code
+class wxMyVariantData : public wxVariantData
+{
+public:
+ wxMyVariantData(const MyClass& value)
+ {
+ m_value = value;
+ }
+
+ virtual bool Eq(wxVariantData& WXUNUSED(data)) const
+ {
+ return false;
+ }
+
+ // What type is it? Return a string name.
+ virtual wxString GetType() const { return "MyClass"; }
+
+ virtual wxVariantData* Clone() const
+ {
+ return new wxMyVariantData(m_value);
+ }
+
+protected:
+ MyClass m_value;
+};
+
+#endif // wxUSE_VARIANT
+
+
+void wxAnyTestCase::wxVariantConversions()
+{
+#if wxUSE_VARIANT
+ //
+ // Test various conversions to and from wxVariant
+ //
+ bool res;
+
+ // Prepare wxVariants
+ wxVariant vLong(123L);
+ wxVariant vString("ABC");
+ wxVariant vDouble(TEST_FLOAT_CONST);
+ wxVariant vBool((bool)true);
+ wxVariant vChar('A');
+#ifdef wxLongLong_t
+ wxVariant vLongLong(wxLongLong(wxLL(0xAABBBBCCCC)));
+ wxVariant vULongLong(wxULongLong(wxULL(123456)));
+#endif
+ wxArrayString arrstr;
+ arrstr.push_back("test string");
+ wxVariant vArrayString(arrstr);
+ wxVariant vDateTime(m_testDateTime);
+ wxVariant vVoidPtr(dummyVoidPointer);
+ wxVariant vCustomType(new wxMyVariantData(MyClass(101)));
+ wxVariant vList;
+
+ vList.NullList();
+ vList.Append(15);
+ vList.Append("abc");
+
+ // Convert to wxAnys, and then back to wxVariants
+ wxVariant variant;
+
+ wxAny any(vLong);
+ CPPUNIT_ASSERT(any == 123L);
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant == 123L);
+
+ // Make sure integer variant has correct type information
+ CPPUNIT_ASSERT(variant.GetLong() == 123);
+ CPPUNIT_ASSERT(variant.GetType() == "long");
+
+ // Unsigned long wxAny should convert to "ulonglong" wxVariant
+ any = 1000UL;
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetType() == "ulonglong");
+ CPPUNIT_ASSERT(variant.GetLong() == 1000);
+
+ any = vString;
+ CPPUNIT_ASSERT(any == "ABC");
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetString() == "ABC");
+
+ // Must be able to build string wxVariant from wxAny built from
+ // string literal
+ any = "ABC";
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetType() == "string");
+ CPPUNIT_ASSERT(variant.GetString() == "ABC");
+ any = L"ABC";
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetType() == "string");
+#if wxUSE_UNICODE
+ CPPUNIT_ASSERT(variant.GetString() == L"ABC");
+#endif
+
+ any = vDouble;
+ double d = wxANY_AS(any, double);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(d, TEST_FLOAT_CONST, FEQ_DELTA);
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(variant.GetDouble(),
+ TEST_FLOAT_CONST,
+ FEQ_DELTA);
+
+ any = vBool;
+ CPPUNIT_ASSERT(wxANY_AS(any, bool) == true);
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetBool() == true);
+
+ any = wxAny(vChar);
+ //CPPUNIT_ASSERT(wxANY_AS(any, wxUniChar) == 'A');
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetChar() == 'A');
+
+#ifdef wxLongLong_t
+ any = wxAny(vLongLong);
+ CPPUNIT_ASSERT(any == wxLL(0xAABBBBCCCC));
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetType() == "longlong");
+ CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xAABBBBCCCC)));
+
+#if LONG_MAX == wxINT64_MAX
+ // As a sanity check, test that wxVariant of type 'long' converts
+ // seamlessly to 'longlong' (on some 64-bit systems)
+ any = 0xAABBBBCCCCL;
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xAABBBBCCCC)));
+#endif
+
+ any = wxAny(vULongLong);
+ CPPUNIT_ASSERT(any == wxLL(123456));
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetType() == "ulonglong");
+ CPPUNIT_ASSERT(variant.GetULongLong() == wxULongLong(wxULL(123456)));
+#endif
+
+ // Cannot test equality for the rest, just test that they convert
+ // back correctly.
+ any = wxAny(vArrayString);
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ wxArrayString arrstr2 = variant.GetArrayString();
+ CPPUNIT_ASSERT(arrstr2 == arrstr);
+
+ any = m_testDateTime;
+ CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
+ any = wxAny(vDateTime);
+ CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant == m_testDateTime);
+
+ any = wxAny(vVoidPtr);
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetVoidPtr() == dummyVoidPointer);
+
+ any = wxAny(vList);
+ CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxAnyList));
+ wxAnyList anyList = wxANY_AS(any, wxAnyList);
+ CPPUNIT_ASSERT(anyList.GetCount() == 2);
+ CPPUNIT_ASSERT(wxANY_AS((*anyList[0]), int) == 15);
+ CPPUNIT_ASSERT(wxANY_AS((*anyList[1]), wxString) == "abc");
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetType() == "list");
+ CPPUNIT_ASSERT(variant.GetCount() == 2);
+ CPPUNIT_ASSERT(variant[0].GetLong() == 15);
+ CPPUNIT_ASSERT(variant[1].GetString() == "abc");
+
+ any = wxAny(vCustomType);
+ CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxVariantData*));
+ res = any.GetAs(&variant);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT(variant.GetType() == "MyClass");
+
+#endif // wxUSE_VARIANT
+}
+
+template<>
+class wxAnyValueTypeImpl<MyClass> :
+ public wxAnyValueTypeImplBase<MyClass>
+{
+ WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)
+public:
+ wxAnyValueTypeImpl() :
+ wxAnyValueTypeImplBase<MyClass>() { }
+ virtual ~wxAnyValueTypeImpl() { }
+
+ virtual bool ConvertValue(const wxAnyValueBuffer& src,
+ wxAnyValueType* dstType,
+ wxAnyValueBuffer& dst) const
+ {
+ MyClass value = GetValue(src);
+
+ if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
+ {
+ wxString s = value.ToString();
+ wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
+ }
+ else
+ return false;
+
+ return true;
+ }
+};
+
+//
+// Following must be placed somewhere in your source code
+WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>)
+
+void wxAnyTestCase::CustomTemplateSpecialization()
+{
+ // Do only a minimal CheckType() test, as dynamic type conversion already
+ // uses it a lot.
+ bool res;
+ MyClass myObject;
+ wxAny any = myObject;
+
+ CPPUNIT_ASSERT( wxANY_CHECK_TYPE(any, MyClass) );
+ MyClass myObject2 = wxANY_AS(any, MyClass);
+ wxUnusedVar(myObject2);
+
+ wxString str;
+ res = any.GetAs(&str);
+ CPPUNIT_ASSERT(res);
+ CPPUNIT_ASSERT_EQUAL(str, myObject.ToString());
+}
+
+void wxAnyTestCase::Misc()
+{
+ // Do some (inplace) allocation sanity checks
+ {
+
+ // Do it inside a scope so we can easily test instance count
+ // afterwards
+ MyClass myObject(15);
+ wxAny any = myObject;
+
+ // There must be two instances - first in myObject,
+ // and second copied in any.
+ CPPUNIT_ASSERT_EQUAL(gs_myClassInstances.size(), 2);
+
+ // Check that it is allocated in-place, as supposed
+ if ( sizeof(MyClass) <= WX_ANY_VALUE_BUFFER_SIZE )
+ {
+ // Memory block of the instance second must be inside the any
+ size_t anyBegin = reinterpret_cast<size_t>(&any);
+ size_t anyEnd = anyBegin + sizeof(wxAny);
+ size_t pos = reinterpret_cast<size_t>(gs_myClassInstances[1]);
+ CPPUNIT_ASSERT( pos >= anyBegin );
+ CPPUNIT_ASSERT( pos < anyEnd );
+ }
+
+ wxAny any2 = any;
+ CPPUNIT_ASSERT( wxANY_AS(any2, MyClass).GetValue() == 15 );
+ }
+
+ // Make sure allocations and deallocations match
+ CPPUNIT_ASSERT_EQUAL(gs_myClassInstances.size(), 0);
+}
+
+#endif // wxUSE_ANY
+