// Name: tests/hashes/hashes.cpp
// 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
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
#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
// --------------------------------------------------------------------------
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)
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( HashesTestCase );
-// 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( HashesTestCase, "HashesTestCase" );
void HashesTestCase::wxHashTableTest()
for ( i = 0; i < COUNT/2; ++i )
CPPUNIT_ASSERT( hash.Get(i) == NULL);
- hash2.Put(_T("foo"), &o + 1);
- hash2.Put(_T("bar"), &o + 2);
- hash2.Put(_T("baz"), &o + 3);
+ hash2.Put(wxT("foo"), &o + 1);
+ hash2.Put(wxT("bar"), &o + 2);
+ hash2.Put(wxT("baz"), &o + 3);
- CPPUNIT_ASSERT(hash2.Get(_T("moo")) == NULL);
- CPPUNIT_ASSERT(hash2.Get(_T("bar")) == &o + 2);
+ CPPUNIT_ASSERT(hash2.Get(wxT("moo")) == NULL);
+ CPPUNIT_ASSERT(hash2.Get(wxT("bar")) == &o + 2);
- hash2.Put(_T("bar"), &o + 0);
+ hash2.Put(wxT("bar"), &o + 0);
- CPPUNIT_ASSERT(hash2.Get(_T("bar")) == &o + 2);
+ CPPUNIT_ASSERT(hash2.Get(wxT("bar")) == &o + 2);
}
// and now some corner-case testing; 3 and 13 hash to the same bucket
CPPUNIT_ASSERT( FooObject::count == 0 );
}
-#if WXWIN_COMPATIBILITY_2_4
-WX_DECLARE_LIST(Foo, wxListFoos);
-#endif
-
WX_DECLARE_HASH(Foo, wxListFoos, wxHashFoos);
-#if WXWIN_COMPATIBILITY_2_4
-#include "wx/listimpl.cpp"
-WX_DEFINE_LIST(wxListFoos);
-#endif
-
void HashesTestCase::wxTypedHashTableTest()
{
// need a nested scope for destruction
// myStringHashMap );
WX_DECLARE_STRING_HASH_MAP(wxString, myStringHashMap);
-typedef myStringHashMap::iterator Itor;
+#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 <class IntT, class KeyT>
+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;
+}
-void HashesTestCase::wxHashMapTest()
+// make key/value pairs for integer types
+template <class KeyT, class ValueT>
+void MakeKeyValuePair(size_t i, size_t count, KeyT& key, ValueT& value)
{
- myStringHashMap sh(0); // as small as possible
- wxString buf;
+ key = MakeKey<KeyT, KeyT>(i, count);
+ value = wx_truncate_cast(ValueT, key);
+}
+
+// make key/values paris for pointer types
+template <class T, class ValueT>
+void MakeKeyValuePair(size_t i, size_t count, T*& key, ValueT& value)
+{
+ key = (T*)wxUIntToPtr(MakeKey<wxUIntPtr, T*>(i, count));
+ value = wx_truncate_cast(ValueT, key);
+}
+
+// the test
+template <class HashMapT>
+void HashMapTest()
+{
+ typedef typename HashMapT::value_type::second_type value_type;
+ 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 )
{
- buf.Printf(wxT("%d"), i );
- sh[buf] = wxT("A") + buf + wxT("C");
+ MakeKeyValuePair(i, count, buf, value);
+ sh[buf] = value;
}
// test that insertion worked
for( i = 0; i < count; ++i )
{
- buf.Printf(wxT("%d"), i );
- CPPUNIT_ASSERT( sh[buf] == wxT("A") + buf + wxT("C") );
+ MakeKeyValuePair(i, count, buf, value);
+ CPPUNIT_ASSERT( sh[buf] == value );
}
// check that iterators work
CPPUNIT_ASSERT( sh.size() == i );
// test copy ctor, assignment operator
- myStringHashMap h1( sh ), h2( 0 );
+ HashMapT h1( sh ), h2( 0 );
h2 = sh;
for( i = 0, it = sh.begin(); it != sh.end(); ++it, ++i )
// other tests
for( i = 0; i < count; ++i )
{
- buf.Printf(wxT("%d"), i );
+ MakeKeyValuePair(i, count, buf, value);
size_t sz = sh.size();
// test find() and erase(it)
}
}
+void HashesTestCase::StringHashMapTest() { HashMapTest<myStringHashMap>(); }
+void HashesTestCase::PtrHashMapTest() { HashMapTest<myPtrHashMap>(); }
+void HashesTestCase::LongHashMapTest() { HashMapTest<myLongHashMap>(); }
+void HashesTestCase::ULongHashMapTest() { HashMapTest<myUnsignedHashMap>(); }
+void HashesTestCase::UIntHashMapTest() { HashMapTest<myTestHashMap1>(); }
+void HashesTestCase::IntHashMapTest() { HashMapTest<myTestHashMap2>(); }
+void HashesTestCase::ShortHashMapTest() { HashMapTest<myTestHashMap3>(); }
+void HashesTestCase::UShortHashMapTest() { HashMapTest<myTestHashMap4>(); }
+
+#ifdef TEST_LONGLONG
+void HashesTestCase::LLongHashMapTest() { HashMapTest<myLLongHashMap>(); }
+void HashesTestCase::ULLongHashMapTest() { HashMapTest<myULLongHashMap>(); }
+#endif
+
+#ifdef __VISUALC__
+ #if __VISUALC__ <= 1200
+ #pragma warning(disable:4284) // operator->() returns a non-UDT
+ #endif
+#endif // __VISUALC__
+
// test compilation of basic set types
WX_DECLARE_HASH_SET( int*, wxPointerHash, wxPointerEqual, myPtrHashSet );
WX_DECLARE_HASH_SET( long, wxIntegerHash, wxIntegerEqual, myLongHashSet );
{
wxStringHashSet set1;
- set1.insert( _T("abc") );
+ set1.insert( wxT("abc") );
CPPUNIT_ASSERT( set1.size() == 1 );
- set1.insert( _T("bbc") );
- set1.insert( _T("cbc") );
+ set1.insert( wxT("bbc") );
+ set1.insert( wxT("cbc") );
CPPUNIT_ASSERT( set1.size() == 3 );
- set1.insert( _T("abc") );
+ set1.insert( wxT("abc") );
CPPUNIT_ASSERT( set1.size() == 3 );
int dummy;
MyStruct tmp;
- tmp.ptr = &dummy; tmp.str = _T("ABC");
+ tmp.ptr = &dummy; tmp.str = wxT("ABC");
set2.insert( tmp );
tmp.ptr = &dummy + 1;
set2.insert( tmp );
- tmp.ptr = &dummy; tmp.str = _T("CDE");
+ tmp.ptr = &dummy; tmp.str = wxT("CDE");
set2.insert( tmp );
CPPUNIT_ASSERT( set2.size() == 2 );
CPPUNIT_ASSERT( it != set2.end() );
CPPUNIT_ASSERT( it->ptr == &dummy );
- CPPUNIT_ASSERT( it->str == _T("ABC") );
+ CPPUNIT_ASSERT( it->str == wxT("ABC") );
}