// 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 "wx/any.h"
#include "wx/datetime.h"
#include "wx/object.h"
+#include "wx/vector.h"
#include <math.h>
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;
// 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.
-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;
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_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;
}
+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()
{
//
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_DOUBLES_EQUAL(o, TEST_FLOAT_CONST, FEQ_DELTA);
+ CPPUNIT_ASSERT_EQUAL(o, TEST_FLOAT_CONST);
+
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);
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);
}
//
// 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 )
{
+ 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()
{
}
private:
+ void Init()
+ {
+ // We use this for some sanity checking
+ gs_myClassInstances.push_back(this);
+ }
+
int m_someValue;
};
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;
CPPUNIT_ASSERT(variant.GetType() == "ulonglong");
CPPUNIT_ASSERT(variant.GetLong() == 1000);
- // FIXME-VC6: for VC6, any = variant needs to be any = wxAny(variant).
- // Note that 'wxAny any = variant' does work, probably because
- // ctor is used in that case instead of assignment operator.
- any = wxAny(vString);
+ any = vString;
CPPUNIT_ASSERT(any == "ABC");
res = any.GetAs(&variant);
CPPUNIT_ASSERT(res);
CPPUNIT_ASSERT(variant.GetString() == "ABC");
- any = wxAny(vDouble);
+ // 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);
TEST_FLOAT_CONST,
FEQ_DELTA);
- any = wxAny(vBool);
+ any = vBool;
CPPUNIT_ASSERT(wxANY_AS(any, bool) == true);
res = any.GetAs(&variant);
CPPUNIT_ASSERT(res);
#ifdef wxLongLong_t
any = wxAny(vLongLong);
- CPPUNIT_ASSERT(any == wxLL(0xFFFFFFFFFF));
+ CPPUNIT_ASSERT(any == wxLL(0xAABBBBCCCC));
res = any.GetAs(&variant);
CPPUNIT_ASSERT(res);
- CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xFFFFFFFFFF)));
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
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