anytest.cpp 23 KB

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