using ordinary Show for popup windows as on MSW which activates it as well, I'll...
[wxWidgets.git] / tests / any / anytest.cpp
index 6912bd622fe22e7730fdfd5b12b703072e490b8e..29dd5170a9898bf09f017db13bcce152621d690c 100644 (file)
@@ -18,6 +18,7 @@
 #include "wx/any.h"
 #include "wx/datetime.h"
 #include "wx/object.h"
 #include "wx/any.h"
 #include "wx/datetime.h"
 #include "wx/object.h"
+#include "wx/vector.h"
 
 #include <math.h>
 
 
 #include <math.h>
 
@@ -32,20 +33,24 @@ public:
 
 private:
     CPPUNIT_TEST_SUITE( 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( Equality );
         CPPUNIT_TEST( As );
         CPPUNIT_TEST( GetAs );
         CPPUNIT_TEST( Null );
         CPPUNIT_TEST( wxVariantConversions );
         CPPUNIT_TEST( CustomTemplateSpecialization );
+        CPPUNIT_TEST( Misc );
     CPPUNIT_TEST_SUITE_END();
 
     CPPUNIT_TEST_SUITE_END();
 
+    void CheckType();
     void Equality();
     void As();
     void GetAs();
     void Null();
     void wxVariantConversions();
     void CustomTemplateSpecialization();
     void Equality();
     void As();
     void GetAs();
     void Null();
     void wxVariantConversions();
     void CustomTemplateSpecialization();
+    void Misc();
 
     wxDateTime m_testDateTime;
 
 
     wxDateTime m_testDateTime;
 
@@ -96,13 +101,14 @@ private:
 // register in the unnamed registry so that these tests are run by default
 CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase );
 
 // register in the unnamed registry so that these tests are run by default
 CPPUNIT_TEST_SUITE_REGISTRATION( wxAnyTestCase );
 
-// also include in it's own registry so that these tests can be run alone
+// 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.
 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 double TEST_FLOAT_CONST = 123.456;
+const float TEST_FLOAT_CONST = 123.456f;
+const double TEST_DOUBLE_CONST = 123.456;
 
 const double FEQ_DELTA = 0.001;
 
 
 const double FEQ_DELTA = 0.001;
 
@@ -131,8 +137,8 @@ wxAnyTestCase::wxAnyTestCase()
       m_anyCharString1("abc"),
       m_anyWcharString1(L"abc"),
       m_anyBool1(true),
       m_anyCharString1("abc"),
       m_anyWcharString1(L"abc"),
       m_anyBool1(true),
-      m_anyFloatDouble1((float)TEST_FLOAT_CONST),
-      m_anyDoubleDouble1((double)TEST_FLOAT_CONST),
+      m_anyFloatDouble1(TEST_FLOAT_CONST),
+      m_anyDoubleDouble1(TEST_DOUBLE_CONST),
       m_anyWxObjectPtr1(dummyWxObjectPointer),
       m_anyVoidPtr1(dummyVoidPointer),
       m_anyDateTime1(wxDateTime::Now())
       m_anyWxObjectPtr1(dummyWxObjectPointer),
       m_anyVoidPtr1(dummyVoidPointer),
       m_anyDateTime1(wxDateTime::Now())
@@ -156,14 +162,31 @@ wxAnyTestCase::wxAnyTestCase()
     m_anyCharString2 = "abc";
     m_anyWcharString2 = L"abc";
     m_anyBool2 = true;
     m_anyCharString2 = "abc";
     m_anyWcharString2 = L"abc";
     m_anyBool2 = true;
-    m_anyFloatDouble2 = (float)TEST_FLOAT_CONST;
-    m_anyDoubleDouble2 = (double)TEST_FLOAT_CONST;
+    m_anyFloatDouble2 = TEST_FLOAT_CONST;
+    m_anyDoubleDouble2 = TEST_DOUBLE_CONST;
     m_anyDateTime2 = m_testDateTime;
     m_anyUniChar1 = wxUniChar('A');
     m_anyWxObjectPtr2 = dummyWxObjectPointer;
     m_anyVoidPtr2 = dummyVoidPointer;
 }
 
     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()
 {
     //
 void wxAnyTestCase::Equality()
 {
     //
@@ -243,15 +266,24 @@ void wxAnyTestCase::As()
     wxString k = wxANY_AS(m_anyStringString1, wxString);
     CPPUNIT_ASSERT(k == "abc");
     wxString l = wxANY_AS(m_anyCharString1, wxString);
     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(l == "abc");
+    CPPUNIT_ASSERT(cptr);
     wxString m = wxANY_AS(m_anyWcharString1, wxString);
     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);
     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);
     float o = wxANY_AS(m_anyFloatDouble1, float);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(o, TEST_FLOAT_CONST, FEQ_DELTA);
+    CPPUNIT_ASSERT_EQUAL(o, TEST_FLOAT_CONST);
+
     double p = wxANY_AS(m_anyDoubleDouble1, double);
     double p = wxANY_AS(m_anyDoubleDouble1, double);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(p, TEST_FLOAT_CONST, FEQ_DELTA);
+    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);
     wxUniChar chr = wxANY_AS(m_anyUniChar1, wxUniChar);
     CPPUNIT_ASSERT(chr == 'A');
     wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime);
@@ -371,7 +403,7 @@ void wxAnyTestCase::GetAs()
     res = m_anyDoubleDouble1.GetAs(&s);
     CPPUNIT_ASSERT(res);
     double d2;
     res = m_anyDoubleDouble1.GetAs(&s);
     CPPUNIT_ASSERT(res);
     double d2;
-    res = s.ToDouble(&d2);
+    res = s.ToCDouble(&d2);
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA);
 }
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA);
 }
@@ -379,16 +411,42 @@ void wxAnyTestCase::GetAs()
 
 //
 // Test user data type for wxAnyValueTypeImpl specialization
 
 //
 // Test user data type for wxAnyValueTypeImpl specialization
-// any hand-built wxVariantData
+// any hand-built wxVariantData. Also for inplace allocation
+// sanity checks.
 //
 
 //
 
+class MyClass;
+
+static wxVector<MyClass*> gs_myClassInstances;
+
 class MyClass
 {
 public:
     MyClass( int someValue = 32768 )
     {
 class MyClass
 {
 public:
     MyClass( int someValue = 32768 )
     {
+        Init();
         m_someValue = someValue;
     }
         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()
     {
 
     wxString ToString()
     {
@@ -396,6 +454,12 @@ public:
     }
 
 private:
     }
 
 private:
+    void Init()
+    {
+        // We use this for some sanity checking
+        gs_myClassInstances.push_back(this);
+    }
+
     int     m_someValue;
 };
 
     int     m_someValue;
 };
 
@@ -447,7 +511,7 @@ void wxAnyTestCase::wxVariantConversions()
     wxVariant vBool((bool)true);
     wxVariant vChar('A');
 #ifdef wxLongLong_t
     wxVariant vBool((bool)true);
     wxVariant vChar('A');
 #ifdef wxLongLong_t
-    wxVariant vLongLong(wxLongLong(wxLL(0xFFFFFFFFFF)));
+    wxVariant vLongLong(wxLongLong(wxLL(0xAABBBBCCCC)));
     wxVariant vULongLong(wxULongLong(wxULL(123456)));
 #endif
     wxArrayString arrstr;
     wxVariant vULongLong(wxULongLong(wxULL(123456)));
 #endif
     wxArrayString arrstr;
@@ -488,6 +552,21 @@ void wxAnyTestCase::wxVariantConversions()
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant.GetString() == "ABC");
 
     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);
     any = vDouble;
     double d = wxANY_AS(any, double);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(d, TEST_FLOAT_CONST, FEQ_DELTA);
@@ -503,30 +582,39 @@ void wxAnyTestCase::wxVariantConversions()
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant.GetBool() == true);
 
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant.GetBool() == true);
 
-    any = vChar;
+    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
     //CPPUNIT_ASSERT(wxANY_AS(any, wxUniChar) == 'A');
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant.GetChar() == 'A');
 
 #ifdef wxLongLong_t
-    any = vLongLong;
-    CPPUNIT_ASSERT(any == wxLL(0xFFFFFFFFFF));
+    any = wxAny(vLongLong);
+    CPPUNIT_ASSERT(any == wxLL(0xAABBBBCCCC));
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
-    CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xFFFFFFFFFF)));
     CPPUNIT_ASSERT(variant.GetType() == "longlong");
     CPPUNIT_ASSERT(variant.GetType() == "longlong");
+    CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xAABBBBCCCC)));
 
 
-    any = vULongLong;
+#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(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.
     CPPUNIT_ASSERT(variant.GetULongLong() == wxULongLong(wxULL(123456)));
 #endif
 
     // Cannot test equality for the rest, just test that they convert
     // back correctly.
-    any = vArrayString;
+    any = wxAny(vArrayString);
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     wxArrayString arrstr2 = variant.GetArrayString();
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     wxArrayString arrstr2 = variant.GetArrayString();
@@ -534,18 +622,18 @@ void wxAnyTestCase::wxVariantConversions()
 
     any = m_testDateTime;
     CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
 
     any = m_testDateTime;
     CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
-    any = vDateTime;
+    any = wxAny(vDateTime);
     CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant == m_testDateTime);
 
     CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant == m_testDateTime);
 
-    any = vVoidPtr;
+    any = wxAny(vVoidPtr);
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant.GetVoidPtr() == dummyVoidPointer);
 
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(variant.GetVoidPtr() == dummyVoidPointer);
 
-    any = vList;
+    any = wxAny(vList);
     CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxAnyList));
     wxAnyList anyList = wxANY_AS(any, wxAnyList);
     CPPUNIT_ASSERT(anyList.GetCount() == 2);
     CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxAnyList));
     wxAnyList anyList = wxANY_AS(any, wxAnyList);
     CPPUNIT_ASSERT(anyList.GetCount() == 2);
@@ -558,7 +646,7 @@ void wxAnyTestCase::wxVariantConversions()
     CPPUNIT_ASSERT(variant[0].GetLong() == 15);
     CPPUNIT_ASSERT(variant[1].GetString() == "abc");
 
     CPPUNIT_ASSERT(variant[0].GetLong() == 15);
     CPPUNIT_ASSERT(variant[1].GetString() == "abc");
 
-    any = vCustomType;
+    any = wxAny(vCustomType);
     CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxVariantData*));
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
     CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxVariantData*));
     res = any.GetAs(&variant);
     CPPUNIT_ASSERT(res);
@@ -617,5 +705,38 @@ void wxAnyTestCase::CustomTemplateSpecialization()
     CPPUNIT_ASSERT_EQUAL(str, myObject.ToString());
 }
 
     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
 
 #endif // wxUSE_ANY