1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/hashes/hashes.cpp
3 // Purpose: wxArray unit test
4 // Author: Vadim Zeitlin, Mattia Barbon
7 // Copyright: (c) 2004 Vadim Zeitlin, Mattia Barbon
8 ///////////////////////////////////////////////////////////////////////////////
10 // ----------------------------------------------------------------------------
12 // ----------------------------------------------------------------------------
25 #include "wx/hashmap.h"
26 #include "wx/hashset.h"
28 // --------------------------------------------------------------------------
29 // helper class for typed/untyped wxHashTable
30 // --------------------------------------------------------------------------
34 Foo(int n_
) { n
= n_
; count
++; }
42 size_t Foo::count
= 0;
44 struct FooObject
: public wxObject
46 FooObject(int n_
) { n
= n_
; count
++; }
47 ~FooObject() { count
--; }
54 size_t FooObject::count
= 0;
56 // --------------------------------------------------------------------------
58 // --------------------------------------------------------------------------
60 class HashesTestCase
: public CppUnit::TestCase
66 CPPUNIT_TEST_SUITE( HashesTestCase
);
67 CPPUNIT_TEST( wxHashTableTest
);
68 CPPUNIT_TEST( wxUntypedHashTableDeleteContents
);
69 CPPUNIT_TEST( wxTypedHashTableTest
);
70 CPPUNIT_TEST( wxHashMapTest
);
71 CPPUNIT_TEST( wxHashSetTest
);
72 CPPUNIT_TEST_SUITE_END();
74 void wxHashTableTest();
75 void wxUntypedHashTableDeleteContents();
76 void wxTypedHashTableTest();
80 DECLARE_NO_COPY_CLASS(HashesTestCase
)
83 // register in the unnamed registry so that these tests are run by default
84 CPPUNIT_TEST_SUITE_REGISTRATION( HashesTestCase
);
86 // also include in it's own registry so that these tests can be run alone
87 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HashesTestCase
, "HashesTestCase" );
89 void HashesTestCase::wxHashTableTest()
91 const int COUNT
= 100;
94 wxHashTable
hash(wxKEY_INTEGER
, 10), hash2(wxKEY_STRING
);
98 for ( i
= 0; i
< COUNT
; ++i
)
102 wxHashTable::compatibility_iterator it
= hash
.Next();
111 CPPUNIT_ASSERT( i
== COUNT
);
113 for ( i
= 99; i
>= 0; --i
)
114 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
);
116 for ( i
= 0; i
< COUNT
; ++i
)
117 hash
.Put(i
, &o
+ i
+ 20);
119 for ( i
= 99; i
>= 0; --i
)
120 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
);
122 for ( i
= 0; i
< COUNT
/2; ++i
)
123 CPPUNIT_ASSERT( hash
.Delete(i
) == &o
+ i
);
125 for ( i
= COUNT
/2; i
< COUNT
; ++i
)
126 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
);
128 for ( i
= 0; i
< COUNT
/2; ++i
)
129 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
+ 20);
131 for ( i
= 0; i
< COUNT
/2; ++i
)
132 CPPUNIT_ASSERT( hash
.Delete(i
) == &o
+ i
+ 20);
134 for ( i
= 0; i
< COUNT
/2; ++i
)
135 CPPUNIT_ASSERT( hash
.Get(i
) == NULL
);
137 hash2
.Put(_T("foo"), &o
+ 1);
138 hash2
.Put(_T("bar"), &o
+ 2);
139 hash2
.Put(_T("baz"), &o
+ 3);
141 CPPUNIT_ASSERT(hash2
.Get(_T("moo")) == NULL
);
142 CPPUNIT_ASSERT(hash2
.Get(_T("bar")) == &o
+ 2);
144 hash2
.Put(_T("bar"), &o
+ 0);
146 CPPUNIT_ASSERT(hash2
.Get(_T("bar")) == &o
+ 2);
149 // and now some corner-case testing; 3 and 13 hash to the same bucket
151 wxHashTable
hash(wxKEY_INTEGER
, 10);
157 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
160 hash
.Put(13, &dummy
);
163 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
167 CPPUNIT_ASSERT(hash
.Get(13) == NULL
);
170 hash
.Put(13, &dummy
);
173 CPPUNIT_ASSERT(hash
.Get(13) == NULL
);
177 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
180 // test for key + value access (specifically that supplying either
181 // wrong key or wrong value returns NULL)
183 wxHashTable
hash(wxKEY_INTEGER
, 10);
186 hash
.Put(3, 7, &dummy
+ 7);
187 hash
.Put(4, 8, &dummy
+ 8);
189 CPPUNIT_ASSERT(hash
.Get(7) == NULL
);
190 CPPUNIT_ASSERT(hash
.Get(3, 7) == &dummy
+ 7);
191 CPPUNIT_ASSERT(hash
.Get(4) == NULL
);
192 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
193 CPPUNIT_ASSERT(hash
.Get(8) == NULL
);
194 CPPUNIT_ASSERT(hash
.Get(8, 4) == NULL
);
196 CPPUNIT_ASSERT(hash
.Delete(7) == NULL
);
197 CPPUNIT_ASSERT(hash
.Delete(3) == NULL
);
198 CPPUNIT_ASSERT(hash
.Delete(3, 7) == &dummy
+ 7);
203 void HashesTestCase::wxUntypedHashTableDeleteContents()
205 // need a nested scope for destruction
208 hash
.DeleteContents(true);
210 CPPUNIT_ASSERT( hash
.GetCount() == 0 );
211 CPPUNIT_ASSERT( FooObject::count
== 0 );
213 static const int hashTestData
[] =
215 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
219 for ( n
= 0; n
< WXSIZEOF(hashTestData
); n
++ )
221 hash
.Put(hashTestData
[n
], n
, new FooObject(n
));
224 CPPUNIT_ASSERT( hash
.GetCount() == WXSIZEOF(hashTestData
) );
225 CPPUNIT_ASSERT( FooObject::count
== WXSIZEOF(hashTestData
) );
227 // delete from hash without deleting object
228 FooObject
* foo
= (FooObject
*)hash
.Delete(0l);
230 CPPUNIT_ASSERT( FooObject::count
== WXSIZEOF(hashTestData
) );
232 CPPUNIT_ASSERT( FooObject::count
== WXSIZEOF(hashTestData
) - 1 );
236 CPPUNIT_ASSERT( FooObject::count
== 0 );
239 #if WXWIN_COMPATIBILITY_2_4
240 WX_DECLARE_LIST(Foo
, wxListFoos
);
243 WX_DECLARE_HASH(Foo
, wxListFoos
, wxHashFoos
);
245 #if WXWIN_COMPATIBILITY_2_4
246 #include "wx/listimpl.cpp"
247 WX_DEFINE_LIST(wxListFoos
);
250 void HashesTestCase::wxTypedHashTableTest()
252 // need a nested scope for destruction
255 hash
.DeleteContents(true);
257 CPPUNIT_ASSERT( hash
.GetCount() == 0 );
258 CPPUNIT_ASSERT( Foo::count
== 0 );
260 static const int hashTestData
[] =
262 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
266 for ( n
= 0; n
< WXSIZEOF(hashTestData
); n
++ )
268 hash
.Put(hashTestData
[n
], n
, new Foo(n
));
271 CPPUNIT_ASSERT( hash
.GetCount() == WXSIZEOF(hashTestData
) );
272 CPPUNIT_ASSERT( Foo::count
== WXSIZEOF(hashTestData
) );
274 for ( n
= 0; n
< WXSIZEOF(hashTestData
); n
++ )
276 Foo
*foo
= hash
.Get(hashTestData
[n
], n
);
278 CPPUNIT_ASSERT( foo
!= NULL
);
279 CPPUNIT_ASSERT( foo
->n
== (int)n
);
282 // element not in hash
283 CPPUNIT_ASSERT( hash
.Get(1234) == NULL
);
284 CPPUNIT_ASSERT( hash
.Get(1, 0) == NULL
);
286 // delete from hash without deleting object
287 Foo
* foo
= hash
.Delete(0);
289 CPPUNIT_ASSERT( Foo::count
== WXSIZEOF(hashTestData
) );
291 CPPUNIT_ASSERT( Foo::count
== WXSIZEOF(hashTestData
) - 1 );
295 CPPUNIT_ASSERT( Foo::count
== 0 );
298 void HashesTestCase::wxHashMapTest()
302 void HashesTestCase::wxHashSetTest()