X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8899b155a1e4fa5f4b90e1f3bebe28088ea46bc9..0cdd04ad993f86710bc5c9d9c8c12ec25a34ac71:/tests/hashes/hashes.cpp?ds=sidebyside diff --git a/tests/hashes/hashes.cpp b/tests/hashes/hashes.cpp index 062822fedd..a277728591 100644 --- a/tests/hashes/hashes.cpp +++ b/tests/hashes/hashes.cpp @@ -1,10 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// // Name: tests/hashes/hashes.cpp -// Purpose: wxArray unit test +// Purpose: wxHashTable, wxHashMap, wxHashSet unit test // Author: Vadim Zeitlin, Mattia Barbon +// Modified: Mike Wetherell // Created: 2004-05-16 // RCS-ID: $Id$ -// Copyright: (c) 2004 Vadim Zeitlin, Mattia Barbon +// Copyright: (c) 2004 Vadim Zeitlin, Mattia Barbon, 2005 M. Wetherell /////////////////////////////////////////////////////////////////////////////// // ---------------------------------------------------------------------------- @@ -25,6 +26,11 @@ #include "wx/hashmap.h" #include "wx/hashset.h" +#if defined wxLongLong_t && !defined wxLongLongIsLong && \ + (!defined __VISUALC__ || __VISUALC__ > 1100) // doesn't work on VC5 + #define TEST_LONGLONG +#endif + // -------------------------------------------------------------------------- // helper class for typed/untyped wxHashTable // -------------------------------------------------------------------------- @@ -67,14 +73,36 @@ private: CPPUNIT_TEST( wxHashTableTest ); CPPUNIT_TEST( wxUntypedHashTableDeleteContents ); CPPUNIT_TEST( wxTypedHashTableTest ); - CPPUNIT_TEST( wxHashMapTest ); + CPPUNIT_TEST( StringHashMapTest ); + CPPUNIT_TEST( PtrHashMapTest ); + CPPUNIT_TEST( LongHashMapTest ); + CPPUNIT_TEST( ULongHashMapTest ); + CPPUNIT_TEST( UIntHashMapTest ); + CPPUNIT_TEST( IntHashMapTest ); + CPPUNIT_TEST( ShortHashMapTest ); + CPPUNIT_TEST( UShortHashMapTest ); +#ifdef TEST_LONGLONG + CPPUNIT_TEST( LLongHashMapTest ); + CPPUNIT_TEST( ULLongHashMapTest ); +#endif CPPUNIT_TEST( wxHashSetTest ); CPPUNIT_TEST_SUITE_END(); void wxHashTableTest(); void wxUntypedHashTableDeleteContents(); void wxTypedHashTableTest(); - void wxHashMapTest(); + void StringHashMapTest(); + void PtrHashMapTest(); + void LongHashMapTest(); + void ULongHashMapTest(); + void UIntHashMapTest(); + void IntHashMapTest(); + void ShortHashMapTest(); + void UShortHashMapTest(); +#ifdef TEST_LONGLONG + void LLongHashMapTest(); + void ULLongHashMapTest(); +#endif void wxHashSetTest(); DECLARE_NO_COPY_CLASS(HashesTestCase) @@ -244,7 +272,7 @@ WX_DECLARE_HASH(Foo, wxListFoos, wxHashFoos); #if WXWIN_COMPATIBILITY_2_4 #include "wx/listimpl.cpp" -WX_DEFINE_LIST(wxListFoos); +WX_DEFINE_LIST(wxListFoos) #endif void HashesTestCase::wxTypedHashTableTest() @@ -295,10 +323,242 @@ void HashesTestCase::wxTypedHashTableTest() CPPUNIT_ASSERT( Foo::count == 0 ); } -void HashesTestCase::wxHashMapTest() +// test compilation of basic map types +WX_DECLARE_HASH_MAP( int*, int*, wxPointerHash, wxPointerEqual, myPtrHashMap ); +WX_DECLARE_HASH_MAP( long, long, wxIntegerHash, wxIntegerEqual, myLongHashMap ); +WX_DECLARE_HASH_MAP( unsigned long, unsigned, wxIntegerHash, wxIntegerEqual, + myUnsignedHashMap ); +WX_DECLARE_HASH_MAP( unsigned int, unsigned, wxIntegerHash, wxIntegerEqual, + myTestHashMap1 ); +WX_DECLARE_HASH_MAP( int, unsigned, wxIntegerHash, wxIntegerEqual, + myTestHashMap2 ); +WX_DECLARE_HASH_MAP( short, unsigned, wxIntegerHash, wxIntegerEqual, + myTestHashMap3 ); +WX_DECLARE_HASH_MAP( unsigned short, unsigned, wxIntegerHash, wxIntegerEqual, + myTestHashMap4 ); + +// same as: +// WX_DECLARE_HASH_MAP( wxString, wxString, wxStringHash, wxStringEqual, +// myStringHashMap ); +WX_DECLARE_STRING_HASH_MAP(wxString, myStringHashMap); + +#ifdef TEST_LONGLONG + WX_DECLARE_HASH_MAP( wxLongLong_t, wxLongLong_t, + wxIntegerHash, wxIntegerEqual, myLLongHashMap ); + WX_DECLARE_HASH_MAP( wxULongLong_t, wxULongLong_t, + wxIntegerHash, wxIntegerEqual, myULLongHashMap ); +#endif + +// Helpers to generate a key value pair for item 'i', out of a total of 'count' +void MakeKeyValuePair(size_t i, size_t /*count*/, wxString& key, wxString& val) +{ + key.clear(); + key << i; + val = wxT("A") + key + wxT("C"); +} + +// for integral keys generate a range of keys that will use all the bits of +// the key type +template +IntT MakeKey(size_t i, size_t count) { + IntT max = 1; + max <<= sizeof(KeyT) * 8 - 2; + max -= count / 4 + 1; + + return max / count * 4 * i + i / 3; } +// make key/value pairs for integer types +template +void MakeKeyValuePair(size_t i, size_t count, KeyT& key, ValueT& value) +{ + key = MakeKey(i, count); + value = wx_truncate_cast(ValueT, key); +} + +// make key/values paris for pointer types +template +void MakeKeyValuePair(size_t i, size_t count, T*& key, ValueT& value) +{ + key = (T*)wxUIntToPtr(MakeKey(i, count)); + value = wx_truncate_cast(ValueT, key); +} + +// the test +template +void HashMapTest() +{ +#if wxUSE_STL && defined HAVE_STL_HASH_MAP + typedef typename HashMapT::value_type::second_type value_type; +#else + typedef typename HashMapT::value_type::t2 value_type; +#endif + typedef typename HashMapT::key_type key_type; + typedef typename HashMapT::iterator Itor; + + HashMapT sh(0); // as small as possible + key_type buf; + value_type value; + size_t i; + const size_t count = 10000; + + // init with some data + for( i = 0; i < count; ++i ) + { + MakeKeyValuePair(i, count, buf, value); + sh[buf] = value; + } + + // test that insertion worked + CPPUNIT_ASSERT( sh.size() == count ); + + for( i = 0; i < count; ++i ) + { + MakeKeyValuePair(i, count, buf, value); + CPPUNIT_ASSERT( sh[buf] == value ); + } + + // check that iterators work + Itor it; + for( i = 0, it = sh.begin(); it != sh.end(); ++it, ++i ) + { + CPPUNIT_ASSERT( i != count ); + CPPUNIT_ASSERT( it->second == sh[it->first] ); + } + + CPPUNIT_ASSERT( sh.size() == i ); + + // test copy ctor, assignment operator + HashMapT h1( sh ), h2( 0 ); + h2 = sh; + + for( i = 0, it = sh.begin(); it != sh.end(); ++it, ++i ) + { + CPPUNIT_ASSERT( h1[it->first] == it->second ); + CPPUNIT_ASSERT( h2[it->first] == it->second ); + } + + // other tests + for( i = 0; i < count; ++i ) + { + MakeKeyValuePair(i, count, buf, value); + size_t sz = sh.size(); + + // test find() and erase(it) + if( i < 100 ) + { + it = sh.find( buf ); + CPPUNIT_ASSERT( it != sh.end() ); + + sh.erase( it ); + + CPPUNIT_ASSERT( sh.find( buf ) == sh.end() ); + } + else + // test erase(key) + { + size_t c = sh.erase( buf ); + CPPUNIT_ASSERT( c == 1 ); + CPPUNIT_ASSERT( sh.find( buf ) == sh.end() ); + } + + // count should decrease + CPPUNIT_ASSERT( sh.size() == sz - 1 ); + } +} + +void HashesTestCase::StringHashMapTest() { HashMapTest(); } +void HashesTestCase::PtrHashMapTest() { HashMapTest(); } +void HashesTestCase::LongHashMapTest() { HashMapTest(); } +void HashesTestCase::ULongHashMapTest() { HashMapTest(); } +void HashesTestCase::UIntHashMapTest() { HashMapTest(); } +void HashesTestCase::IntHashMapTest() { HashMapTest(); } +void HashesTestCase::ShortHashMapTest() { HashMapTest(); } +void HashesTestCase::UShortHashMapTest() { HashMapTest(); } + +#ifdef TEST_LONGLONG +void HashesTestCase::LLongHashMapTest() { HashMapTest(); } +void HashesTestCase::ULLongHashMapTest() { HashMapTest(); } +#endif + +// test compilation of basic set types +WX_DECLARE_HASH_SET( int*, wxPointerHash, wxPointerEqual, myPtrHashSet ); +WX_DECLARE_HASH_SET( long, wxIntegerHash, wxIntegerEqual, myLongHashSet ); +WX_DECLARE_HASH_SET( unsigned long, wxIntegerHash, wxIntegerEqual, + myUnsignedHashSet ); +WX_DECLARE_HASH_SET( unsigned int, wxIntegerHash, wxIntegerEqual, + myTestHashSet1 ); +WX_DECLARE_HASH_SET( int, wxIntegerHash, wxIntegerEqual, + myTestHashSet2 ); +WX_DECLARE_HASH_SET( short, wxIntegerHash, wxIntegerEqual, + myTestHashSet3 ); +WX_DECLARE_HASH_SET( unsigned short, wxIntegerHash, wxIntegerEqual, + myTestHashSet4 ); +WX_DECLARE_HASH_SET( wxString, wxStringHash, wxStringEqual, + myTestHashSet5 ); + +struct MyStruct +{ + int* ptr; + wxString str; +}; + +class MyHash +{ +public: + unsigned long operator()(const MyStruct& s) const + { return m_dummy(s.ptr); } + MyHash& operator=(const MyHash&) { return *this; } +private: + wxPointerHash m_dummy; +}; + +class MyEqual +{ +public: + bool operator()(const MyStruct& s1, const MyStruct& s2) const + { return s1.ptr == s2.ptr; } + MyEqual& operator=(const MyEqual&) { return *this; } +}; + +WX_DECLARE_HASH_SET( MyStruct, MyHash, MyEqual, mySet ); + +typedef myTestHashSet5 wxStringHashSet; + void HashesTestCase::wxHashSetTest() { + wxStringHashSet set1; + + set1.insert( _T("abc") ); + + CPPUNIT_ASSERT( set1.size() == 1 ); + + set1.insert( _T("bbc") ); + set1.insert( _T("cbc") ); + + CPPUNIT_ASSERT( set1.size() == 3 ); + + set1.insert( _T("abc") ); + + CPPUNIT_ASSERT( set1.size() == 3 ); + + mySet set2; + int dummy; + MyStruct tmp; + + tmp.ptr = &dummy; tmp.str = _T("ABC"); + set2.insert( tmp ); + tmp.ptr = &dummy + 1; + set2.insert( tmp ); + tmp.ptr = &dummy; tmp.str = _T("CDE"); + set2.insert( tmp ); + + CPPUNIT_ASSERT( set2.size() == 2 ); + + mySet::iterator it = set2.find( tmp ); + + CPPUNIT_ASSERT( it != set2.end() ); + CPPUNIT_ASSERT( it->ptr == &dummy ); + CPPUNIT_ASSERT( it->str == _T("ABC") ); }