+// 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 )
+ {
+ 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<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 );
+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;
+