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 // ----------------------------------------------------------------------------
14 #include "wx/wxprec.h"
25 #include "wx/hashmap.h"
26 #include "wx/hashset.h"
28 #include "wx/cppunit.h"
30 // --------------------------------------------------------------------------
31 // helper class for typed/untyped wxHashTable
32 // --------------------------------------------------------------------------
36 Foo(int n_
) { n
= n_
; count
++; }
44 size_t Foo::count
= 0;
46 struct FooObject
: public wxObject
48 FooObject(int n_
) { n
= n_
; count
++; }
49 ~FooObject() { count
--; }
56 size_t FooObject::count
= 0;
58 // --------------------------------------------------------------------------
60 // --------------------------------------------------------------------------
62 class HashesTestCase
: public CppUnit::TestCase
68 CPPUNIT_TEST_SUITE( HashesTestCase
);
69 CPPUNIT_TEST( wxHashTableTest
);
70 CPPUNIT_TEST( wxUntypedHashTableDeleteContents
);
71 CPPUNIT_TEST( wxTypedHashTableTest
);
72 CPPUNIT_TEST( wxHashMapTest
);
73 CPPUNIT_TEST( wxHashSetTest
);
74 CPPUNIT_TEST_SUITE_END();
76 void wxHashTableTest();
77 void wxUntypedHashTableDeleteContents();
78 void wxTypedHashTableTest();
82 DECLARE_NO_COPY_CLASS(HashesTestCase
)
85 // register in the unnamed registry so that these tests are run by default
86 CPPUNIT_TEST_SUITE_REGISTRATION( HashesTestCase
);
88 // also include in it's own registry so that these tests can be run alone
89 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HashesTestCase
, "HashesTestCase" );
91 void HashesTestCase::wxHashTableTest()
93 const int COUNT
= 100;
96 wxHashTable
hash(wxKEY_INTEGER
, 10), hash2(wxKEY_STRING
);
100 for ( i
= 0; i
< COUNT
; ++i
)
104 wxHashTable::compatibility_iterator it
= hash
.Next();
113 CPPUNIT_ASSERT( i
== COUNT
);
115 for ( i
= 99; i
>= 0; --i
)
116 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
);
118 for ( i
= 0; i
< COUNT
; ++i
)
119 hash
.Put(i
, &o
+ i
+ 20);
121 for ( i
= 99; i
>= 0; --i
)
122 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
);
124 for ( i
= 0; i
< COUNT
/2; ++i
)
125 CPPUNIT_ASSERT( hash
.Delete(i
) == &o
+ i
);
127 for ( i
= COUNT
/2; i
< COUNT
; ++i
)
128 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
);
130 for ( i
= 0; i
< COUNT
/2; ++i
)
131 CPPUNIT_ASSERT( hash
.Get(i
) == &o
+ i
+ 20);
133 for ( i
= 0; i
< COUNT
/2; ++i
)
134 CPPUNIT_ASSERT( hash
.Delete(i
) == &o
+ i
+ 20);
136 for ( i
= 0; i
< COUNT
/2; ++i
)
137 CPPUNIT_ASSERT( hash
.Get(i
) == NULL
);
139 hash2
.Put(_T("foo"), &o
+ 1);
140 hash2
.Put(_T("bar"), &o
+ 2);
141 hash2
.Put(_T("baz"), &o
+ 3);
143 CPPUNIT_ASSERT(hash2
.Get(_T("moo")) == NULL
);
144 CPPUNIT_ASSERT(hash2
.Get(_T("bar")) == &o
+ 2);
146 hash2
.Put(_T("bar"), &o
+ 0);
148 CPPUNIT_ASSERT(hash2
.Get(_T("bar")) == &o
+ 2);
151 // and now some corner-case testing; 3 and 13 hash to the same bucket
153 wxHashTable
hash(wxKEY_INTEGER
, 10);
159 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
162 hash
.Put(13, &dummy
);
165 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
169 CPPUNIT_ASSERT(hash
.Get(13) == NULL
);
172 hash
.Put(13, &dummy
);
175 CPPUNIT_ASSERT(hash
.Get(13) == NULL
);
179 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
182 // test for key + value access (specifically that supplying either
183 // wrong key or wrong value returns NULL)
185 wxHashTable
hash(wxKEY_INTEGER
, 10);
188 hash
.Put(3, 7, &dummy
+ 7);
189 hash
.Put(4, 8, &dummy
+ 8);
191 CPPUNIT_ASSERT(hash
.Get(7) == NULL
);
192 CPPUNIT_ASSERT(hash
.Get(3, 7) == &dummy
+ 7);
193 CPPUNIT_ASSERT(hash
.Get(4) == NULL
);
194 CPPUNIT_ASSERT(hash
.Get(3) == NULL
);
195 CPPUNIT_ASSERT(hash
.Get(8) == NULL
);
196 CPPUNIT_ASSERT(hash
.Get(8, 4) == NULL
);
198 CPPUNIT_ASSERT(hash
.Delete(7) == NULL
);
199 CPPUNIT_ASSERT(hash
.Delete(3) == NULL
);
200 CPPUNIT_ASSERT(hash
.Delete(3, 7) == &dummy
+ 7);
205 void HashesTestCase::wxUntypedHashTableDeleteContents()
207 // need a nested scope for destruction
210 hash
.DeleteContents(true);
212 CPPUNIT_ASSERT( hash
.GetCount() == 0 );
213 CPPUNIT_ASSERT( FooObject::count
== 0 );
215 static const int hashTestData
[] =
217 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
221 for ( n
= 0; n
< WXSIZEOF(hashTestData
); n
++ )
223 hash
.Put(hashTestData
[n
], n
, new FooObject(n
));
226 CPPUNIT_ASSERT( hash
.GetCount() == WXSIZEOF(hashTestData
) );
227 CPPUNIT_ASSERT( FooObject::count
== WXSIZEOF(hashTestData
) );
229 // delete from hash without deleting object
230 FooObject
* foo
= (FooObject
*)hash
.Delete(0l);
232 CPPUNIT_ASSERT( FooObject::count
== WXSIZEOF(hashTestData
) );
234 CPPUNIT_ASSERT( FooObject::count
== WXSIZEOF(hashTestData
) - 1 );
238 CPPUNIT_ASSERT( FooObject::count
== 0 );
241 #if WXWIN_COMPATIBILITY_2_4
242 WX_DECLARE_LIST(Foo
, wxListFoos
);
245 WX_DECLARE_HASH(Foo
, wxListFoos
, wxHashFoos
);
247 #if WXWIN_COMPATIBILITY_2_4
248 #include "wx/listimpl.cpp"
249 WX_DEFINE_LIST(wxListFoos
);
252 void HashesTestCase::wxTypedHashTableTest()
254 // need a nested scope for destruction
257 hash
.DeleteContents(true);
259 CPPUNIT_ASSERT( hash
.GetCount() == 0 );
260 CPPUNIT_ASSERT( Foo::count
== 0 );
262 static const int hashTestData
[] =
264 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
268 for ( n
= 0; n
< WXSIZEOF(hashTestData
); n
++ )
270 hash
.Put(hashTestData
[n
], n
, new Foo(n
));
273 CPPUNIT_ASSERT( hash
.GetCount() == WXSIZEOF(hashTestData
) );
274 CPPUNIT_ASSERT( Foo::count
== WXSIZEOF(hashTestData
) );
276 for ( n
= 0; n
< WXSIZEOF(hashTestData
); n
++ )
278 Foo
*foo
= hash
.Get(hashTestData
[n
], n
);
280 CPPUNIT_ASSERT( foo
!= NULL
);
281 CPPUNIT_ASSERT( foo
->n
== (int)n
);
284 // element not in hash
285 CPPUNIT_ASSERT( hash
.Get(1234) == NULL
);
286 CPPUNIT_ASSERT( hash
.Get(1, 0) == NULL
);
288 // delete from hash without deleting object
289 Foo
* foo
= hash
.Delete(0);
291 CPPUNIT_ASSERT( Foo::count
== WXSIZEOF(hashTestData
) );
293 CPPUNIT_ASSERT( Foo::count
== WXSIZEOF(hashTestData
) - 1 );
297 CPPUNIT_ASSERT( Foo::count
== 0 );
300 void HashesTestCase::wxHashMapTest()
304 void HashesTestCase::wxHashSetTest()