Converted hash tests to CppUnit.
[wxWidgets.git] / tests / hashes / hashes.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/hashes/hashes.cpp
3 // Purpose: wxArray unit test
4 // Author: Vadim Zeitlin, Mattia Barbon
5 // Created: 2004-05-16
6 // RCS-ID: $Id$
7 // Copyright: (c) 2004 Vadim Zeitlin, Mattia Barbon
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #ifndef WX_PRECOMP
21 #include "wx/wx.h"
22 #endif // WX_PRECOMP
23
24 #include "wx/hash.h"
25 #include "wx/hashmap.h"
26 #include "wx/hashset.h"
27
28 #include "wx/cppunit.h"
29
30 // --------------------------------------------------------------------------
31 // helper class for typed/untyped wxHashTable
32 // --------------------------------------------------------------------------
33
34 struct Foo
35 {
36 Foo(int n_) { n = n_; count++; }
37 ~Foo() { count--; }
38
39 int n;
40
41 static size_t count;
42 };
43
44 size_t Foo::count = 0;
45
46 struct FooObject : public wxObject
47 {
48 FooObject(int n_) { n = n_; count++; }
49 ~FooObject() { count--; }
50
51 int n;
52
53 static size_t count;
54 };
55
56 size_t FooObject::count = 0;
57
58 // --------------------------------------------------------------------------
59 // test class
60 // --------------------------------------------------------------------------
61
62 class HashesTestCase : public CppUnit::TestCase
63 {
64 public:
65 HashesTestCase() { }
66
67 private:
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();
75
76 void wxHashTableTest();
77 void wxUntypedHashTableDeleteContents();
78 void wxTypedHashTableTest();
79 void wxHashMapTest();
80 void wxHashSetTest();
81
82 DECLARE_NO_COPY_CLASS(HashesTestCase)
83 };
84
85 // register in the unnamed registry so that these tests are run by default
86 CPPUNIT_TEST_SUITE_REGISTRATION( HashesTestCase );
87
88 // also include in it's own registry so that these tests can be run alone
89 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HashesTestCase, "HashesTestCase" );
90
91 void HashesTestCase::wxHashTableTest()
92 {
93 const int COUNT = 100;
94
95 {
96 wxHashTable hash(wxKEY_INTEGER, 10), hash2(wxKEY_STRING);
97 wxObject o;
98 int i;
99
100 for ( i = 0; i < COUNT; ++i )
101 hash.Put(i, &o + i);
102
103 hash.BeginFind();
104 wxHashTable::compatibility_iterator it = hash.Next();
105 i = 0;
106
107 while (it)
108 {
109 ++i;
110 it = hash.Next();
111 }
112
113 CPPUNIT_ASSERT( i == COUNT );
114
115 for ( i = 99; i >= 0; --i )
116 CPPUNIT_ASSERT( hash.Get(i) == &o + i );
117
118 for ( i = 0; i < COUNT; ++i )
119 hash.Put(i, &o + i + 20);
120
121 for ( i = 99; i >= 0; --i )
122 CPPUNIT_ASSERT( hash.Get(i) == &o + i);
123
124 for ( i = 0; i < COUNT/2; ++i )
125 CPPUNIT_ASSERT( hash.Delete(i) == &o + i);
126
127 for ( i = COUNT/2; i < COUNT; ++i )
128 CPPUNIT_ASSERT( hash.Get(i) == &o + i);
129
130 for ( i = 0; i < COUNT/2; ++i )
131 CPPUNIT_ASSERT( hash.Get(i) == &o + i + 20);
132
133 for ( i = 0; i < COUNT/2; ++i )
134 CPPUNIT_ASSERT( hash.Delete(i) == &o + i + 20);
135
136 for ( i = 0; i < COUNT/2; ++i )
137 CPPUNIT_ASSERT( hash.Get(i) == NULL);
138
139 hash2.Put(_T("foo"), &o + 1);
140 hash2.Put(_T("bar"), &o + 2);
141 hash2.Put(_T("baz"), &o + 3);
142
143 CPPUNIT_ASSERT(hash2.Get(_T("moo")) == NULL);
144 CPPUNIT_ASSERT(hash2.Get(_T("bar")) == &o + 2);
145
146 hash2.Put(_T("bar"), &o + 0);
147
148 CPPUNIT_ASSERT(hash2.Get(_T("bar")) == &o + 2);
149 }
150
151 // and now some corner-case testing; 3 and 13 hash to the same bucket
152 {
153 wxHashTable hash(wxKEY_INTEGER, 10);
154 wxObject dummy;
155
156 hash.Put(3, &dummy);
157 hash.Delete(3);
158
159 CPPUNIT_ASSERT(hash.Get(3) == NULL);
160
161 hash.Put(3, &dummy);
162 hash.Put(13, &dummy);
163 hash.Delete(3);
164
165 CPPUNIT_ASSERT(hash.Get(3) == NULL);
166
167 hash.Delete(13);
168
169 CPPUNIT_ASSERT(hash.Get(13) == NULL);
170
171 hash.Put(3, &dummy);
172 hash.Put(13, &dummy);
173 hash.Delete(13);
174
175 CPPUNIT_ASSERT(hash.Get(13) == NULL);
176
177 hash.Delete(3);
178
179 CPPUNIT_ASSERT(hash.Get(3) == NULL);
180 }
181
182 // test for key + value access (specifically that supplying either
183 // wrong key or wrong value returns NULL)
184 {
185 wxHashTable hash(wxKEY_INTEGER, 10);
186 wxObject dummy;
187
188 hash.Put(3, 7, &dummy + 7);
189 hash.Put(4, 8, &dummy + 8);
190
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);
197
198 CPPUNIT_ASSERT(hash.Delete(7) == NULL);
199 CPPUNIT_ASSERT(hash.Delete(3) == NULL);
200 CPPUNIT_ASSERT(hash.Delete(3, 7) == &dummy + 7);
201 }
202
203 }
204
205 void HashesTestCase::wxUntypedHashTableDeleteContents()
206 {
207 // need a nested scope for destruction
208 {
209 wxHashTable hash;
210 hash.DeleteContents(true);
211
212 CPPUNIT_ASSERT( hash.GetCount() == 0 );
213 CPPUNIT_ASSERT( FooObject::count == 0 );
214
215 static const int hashTestData[] =
216 {
217 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
218 };
219
220 size_t n;
221 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
222 {
223 hash.Put(hashTestData[n], n, new FooObject(n));
224 }
225
226 CPPUNIT_ASSERT( hash.GetCount() == WXSIZEOF(hashTestData) );
227 CPPUNIT_ASSERT( FooObject::count == WXSIZEOF(hashTestData) );
228
229 // delete from hash without deleting object
230 FooObject* foo = (FooObject*)hash.Delete(0l);
231
232 CPPUNIT_ASSERT( FooObject::count == WXSIZEOF(hashTestData) );
233 delete foo;
234 CPPUNIT_ASSERT( FooObject::count == WXSIZEOF(hashTestData) - 1 );
235 }
236
237 // hash destroyed
238 CPPUNIT_ASSERT( FooObject::count == 0 );
239 }
240
241 #if WXWIN_COMPATIBILITY_2_4
242 WX_DECLARE_LIST(Foo, wxListFoos);
243 #endif
244
245 WX_DECLARE_HASH(Foo, wxListFoos, wxHashFoos);
246
247 #if WXWIN_COMPATIBILITY_2_4
248 #include "wx/listimpl.cpp"
249 WX_DEFINE_LIST(wxListFoos);
250 #endif
251
252 void HashesTestCase::wxTypedHashTableTest()
253 {
254 // need a nested scope for destruction
255 {
256 wxHashFoos hash;
257 hash.DeleteContents(true);
258
259 CPPUNIT_ASSERT( hash.GetCount() == 0 );
260 CPPUNIT_ASSERT( Foo::count == 0 );
261
262 static const int hashTestData[] =
263 {
264 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
265 };
266
267 size_t n;
268 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
269 {
270 hash.Put(hashTestData[n], n, new Foo(n));
271 }
272
273 CPPUNIT_ASSERT( hash.GetCount() == WXSIZEOF(hashTestData) );
274 CPPUNIT_ASSERT( Foo::count == WXSIZEOF(hashTestData) );
275
276 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
277 {
278 Foo *foo = hash.Get(hashTestData[n], n);
279
280 CPPUNIT_ASSERT( foo != NULL );
281 CPPUNIT_ASSERT( foo->n == (int)n );
282 }
283
284 // element not in hash
285 CPPUNIT_ASSERT( hash.Get(1234) == NULL );
286 CPPUNIT_ASSERT( hash.Get(1, 0) == NULL );
287
288 // delete from hash without deleting object
289 Foo* foo = hash.Delete(0);
290
291 CPPUNIT_ASSERT( Foo::count == WXSIZEOF(hashTestData) );
292 delete foo;
293 CPPUNIT_ASSERT( Foo::count == WXSIZEOF(hashTestData) - 1 );
294 }
295
296 // hash destroyed
297 CPPUNIT_ASSERT( Foo::count == 0 );
298 }
299
300 void HashesTestCase::wxHashMapTest()
301 {
302 }
303
304 void HashesTestCase::wxHashSetTest()
305 {
306 }