]>
Commit | Line | Data |
---|---|---|
cbca1e08 MB |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: tests/hashes/hashes.cpp | |
7d9cfc54 | 3 | // Purpose: wxHashTable, wxHashMap, wxHashSet unit test |
cbca1e08 | 4 | // Author: Vadim Zeitlin, Mattia Barbon |
d8b6309b | 5 | // Modified: Mike Wetherell |
cbca1e08 MB |
6 | // Created: 2004-05-16 |
7 | // RCS-ID: $Id$ | |
d8b6309b | 8 | // Copyright: (c) 2004 Vadim Zeitlin, Mattia Barbon, 2005 M. Wetherell |
cbca1e08 MB |
9 | /////////////////////////////////////////////////////////////////////////////// |
10 | ||
11 | // ---------------------------------------------------------------------------- | |
12 | // headers | |
13 | // ---------------------------------------------------------------------------- | |
14 | ||
8899b155 | 15 | #include "testprec.h" |
cbca1e08 MB |
16 | |
17 | #ifdef __BORLANDC__ | |
18 | #pragma hdrstop | |
19 | #endif | |
20 | ||
21 | #ifndef WX_PRECOMP | |
22 | #include "wx/wx.h" | |
23 | #endif // WX_PRECOMP | |
24 | ||
25 | #include "wx/hash.h" | |
26 | #include "wx/hashmap.h" | |
27 | #include "wx/hashset.h" | |
28 | ||
d8b6309b MW |
29 | #if defined wxLongLong_t && !defined wxLongLongIsLong && \ |
30 | (!defined __VISUALC__ || __VISUALC__ > 1100) // doesn't work on VC5 | |
31 | #define TEST_LONGLONG | |
32 | #endif | |
33 | ||
cbca1e08 MB |
34 | // -------------------------------------------------------------------------- |
35 | // helper class for typed/untyped wxHashTable | |
36 | // -------------------------------------------------------------------------- | |
37 | ||
38 | struct Foo | |
39 | { | |
40 | Foo(int n_) { n = n_; count++; } | |
41 | ~Foo() { count--; } | |
42 | ||
43 | int n; | |
44 | ||
45 | static size_t count; | |
46 | }; | |
47 | ||
48 | size_t Foo::count = 0; | |
49 | ||
50 | struct FooObject : public wxObject | |
51 | { | |
52 | FooObject(int n_) { n = n_; count++; } | |
53 | ~FooObject() { count--; } | |
54 | ||
55 | int n; | |
56 | ||
57 | static size_t count; | |
58 | }; | |
59 | ||
60 | size_t FooObject::count = 0; | |
61 | ||
62 | // -------------------------------------------------------------------------- | |
63 | // test class | |
64 | // -------------------------------------------------------------------------- | |
65 | ||
66 | class HashesTestCase : public CppUnit::TestCase | |
67 | { | |
68 | public: | |
69 | HashesTestCase() { } | |
70 | ||
71 | private: | |
72 | CPPUNIT_TEST_SUITE( HashesTestCase ); | |
73 | CPPUNIT_TEST( wxHashTableTest ); | |
74 | CPPUNIT_TEST( wxUntypedHashTableDeleteContents ); | |
75 | CPPUNIT_TEST( wxTypedHashTableTest ); | |
d8b6309b MW |
76 | CPPUNIT_TEST( StringHashMapTest ); |
77 | CPPUNIT_TEST( PtrHashMapTest ); | |
78 | CPPUNIT_TEST( LongHashMapTest ); | |
79 | CPPUNIT_TEST( ULongHashMapTest ); | |
80 | CPPUNIT_TEST( UIntHashMapTest ); | |
81 | CPPUNIT_TEST( IntHashMapTest ); | |
82 | CPPUNIT_TEST( ShortHashMapTest ); | |
83 | CPPUNIT_TEST( UShortHashMapTest ); | |
84 | #ifdef TEST_LONGLONG | |
85 | CPPUNIT_TEST( LLongHashMapTest ); | |
86 | CPPUNIT_TEST( ULLongHashMapTest ); | |
87 | #endif | |
cbca1e08 MB |
88 | CPPUNIT_TEST( wxHashSetTest ); |
89 | CPPUNIT_TEST_SUITE_END(); | |
90 | ||
91 | void wxHashTableTest(); | |
92 | void wxUntypedHashTableDeleteContents(); | |
93 | void wxTypedHashTableTest(); | |
d8b6309b MW |
94 | void StringHashMapTest(); |
95 | void PtrHashMapTest(); | |
96 | void LongHashMapTest(); | |
97 | void ULongHashMapTest(); | |
98 | void UIntHashMapTest(); | |
99 | void IntHashMapTest(); | |
100 | void ShortHashMapTest(); | |
101 | void UShortHashMapTest(); | |
102 | #ifdef TEST_LONGLONG | |
103 | void LLongHashMapTest(); | |
104 | void ULLongHashMapTest(); | |
105 | #endif | |
cbca1e08 MB |
106 | void wxHashSetTest(); |
107 | ||
108 | DECLARE_NO_COPY_CLASS(HashesTestCase) | |
109 | }; | |
110 | ||
111 | // register in the unnamed registry so that these tests are run by default | |
112 | CPPUNIT_TEST_SUITE_REGISTRATION( HashesTestCase ); | |
113 | ||
114 | // also include in it's own registry so that these tests can be run alone | |
115 | CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HashesTestCase, "HashesTestCase" ); | |
116 | ||
117 | void HashesTestCase::wxHashTableTest() | |
118 | { | |
119 | const int COUNT = 100; | |
120 | ||
121 | { | |
122 | wxHashTable hash(wxKEY_INTEGER, 10), hash2(wxKEY_STRING); | |
123 | wxObject o; | |
124 | int i; | |
125 | ||
126 | for ( i = 0; i < COUNT; ++i ) | |
127 | hash.Put(i, &o + i); | |
128 | ||
129 | hash.BeginFind(); | |
130 | wxHashTable::compatibility_iterator it = hash.Next(); | |
131 | i = 0; | |
132 | ||
133 | while (it) | |
134 | { | |
135 | ++i; | |
136 | it = hash.Next(); | |
137 | } | |
138 | ||
139 | CPPUNIT_ASSERT( i == COUNT ); | |
140 | ||
141 | for ( i = 99; i >= 0; --i ) | |
142 | CPPUNIT_ASSERT( hash.Get(i) == &o + i ); | |
143 | ||
144 | for ( i = 0; i < COUNT; ++i ) | |
145 | hash.Put(i, &o + i + 20); | |
146 | ||
147 | for ( i = 99; i >= 0; --i ) | |
148 | CPPUNIT_ASSERT( hash.Get(i) == &o + i); | |
149 | ||
150 | for ( i = 0; i < COUNT/2; ++i ) | |
151 | CPPUNIT_ASSERT( hash.Delete(i) == &o + i); | |
152 | ||
153 | for ( i = COUNT/2; i < COUNT; ++i ) | |
154 | CPPUNIT_ASSERT( hash.Get(i) == &o + i); | |
155 | ||
156 | for ( i = 0; i < COUNT/2; ++i ) | |
157 | CPPUNIT_ASSERT( hash.Get(i) == &o + i + 20); | |
158 | ||
159 | for ( i = 0; i < COUNT/2; ++i ) | |
160 | CPPUNIT_ASSERT( hash.Delete(i) == &o + i + 20); | |
161 | ||
162 | for ( i = 0; i < COUNT/2; ++i ) | |
163 | CPPUNIT_ASSERT( hash.Get(i) == NULL); | |
164 | ||
165 | hash2.Put(_T("foo"), &o + 1); | |
166 | hash2.Put(_T("bar"), &o + 2); | |
167 | hash2.Put(_T("baz"), &o + 3); | |
168 | ||
169 | CPPUNIT_ASSERT(hash2.Get(_T("moo")) == NULL); | |
170 | CPPUNIT_ASSERT(hash2.Get(_T("bar")) == &o + 2); | |
171 | ||
172 | hash2.Put(_T("bar"), &o + 0); | |
173 | ||
174 | CPPUNIT_ASSERT(hash2.Get(_T("bar")) == &o + 2); | |
175 | } | |
176 | ||
177 | // and now some corner-case testing; 3 and 13 hash to the same bucket | |
178 | { | |
179 | wxHashTable hash(wxKEY_INTEGER, 10); | |
180 | wxObject dummy; | |
181 | ||
182 | hash.Put(3, &dummy); | |
183 | hash.Delete(3); | |
184 | ||
185 | CPPUNIT_ASSERT(hash.Get(3) == NULL); | |
186 | ||
187 | hash.Put(3, &dummy); | |
188 | hash.Put(13, &dummy); | |
189 | hash.Delete(3); | |
190 | ||
191 | CPPUNIT_ASSERT(hash.Get(3) == NULL); | |
192 | ||
193 | hash.Delete(13); | |
194 | ||
195 | CPPUNIT_ASSERT(hash.Get(13) == NULL); | |
196 | ||
197 | hash.Put(3, &dummy); | |
198 | hash.Put(13, &dummy); | |
199 | hash.Delete(13); | |
200 | ||
201 | CPPUNIT_ASSERT(hash.Get(13) == NULL); | |
202 | ||
203 | hash.Delete(3); | |
204 | ||
205 | CPPUNIT_ASSERT(hash.Get(3) == NULL); | |
206 | } | |
207 | ||
208 | // test for key + value access (specifically that supplying either | |
209 | // wrong key or wrong value returns NULL) | |
210 | { | |
211 | wxHashTable hash(wxKEY_INTEGER, 10); | |
212 | wxObject dummy; | |
213 | ||
214 | hash.Put(3, 7, &dummy + 7); | |
215 | hash.Put(4, 8, &dummy + 8); | |
216 | ||
217 | CPPUNIT_ASSERT(hash.Get(7) == NULL); | |
218 | CPPUNIT_ASSERT(hash.Get(3, 7) == &dummy + 7); | |
219 | CPPUNIT_ASSERT(hash.Get(4) == NULL); | |
220 | CPPUNIT_ASSERT(hash.Get(3) == NULL); | |
221 | CPPUNIT_ASSERT(hash.Get(8) == NULL); | |
222 | CPPUNIT_ASSERT(hash.Get(8, 4) == NULL); | |
223 | ||
224 | CPPUNIT_ASSERT(hash.Delete(7) == NULL); | |
225 | CPPUNIT_ASSERT(hash.Delete(3) == NULL); | |
226 | CPPUNIT_ASSERT(hash.Delete(3, 7) == &dummy + 7); | |
227 | } | |
228 | ||
229 | } | |
230 | ||
231 | void HashesTestCase::wxUntypedHashTableDeleteContents() | |
232 | { | |
233 | // need a nested scope for destruction | |
234 | { | |
235 | wxHashTable hash; | |
236 | hash.DeleteContents(true); | |
237 | ||
238 | CPPUNIT_ASSERT( hash.GetCount() == 0 ); | |
239 | CPPUNIT_ASSERT( FooObject::count == 0 ); | |
240 | ||
241 | static const int hashTestData[] = | |
242 | { | |
243 | 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1, | |
244 | }; | |
245 | ||
246 | size_t n; | |
247 | for ( n = 0; n < WXSIZEOF(hashTestData); n++ ) | |
248 | { | |
249 | hash.Put(hashTestData[n], n, new FooObject(n)); | |
250 | } | |
251 | ||
252 | CPPUNIT_ASSERT( hash.GetCount() == WXSIZEOF(hashTestData) ); | |
253 | CPPUNIT_ASSERT( FooObject::count == WXSIZEOF(hashTestData) ); | |
254 | ||
255 | // delete from hash without deleting object | |
256 | FooObject* foo = (FooObject*)hash.Delete(0l); | |
257 | ||
258 | CPPUNIT_ASSERT( FooObject::count == WXSIZEOF(hashTestData) ); | |
259 | delete foo; | |
260 | CPPUNIT_ASSERT( FooObject::count == WXSIZEOF(hashTestData) - 1 ); | |
261 | } | |
262 | ||
263 | // hash destroyed | |
264 | CPPUNIT_ASSERT( FooObject::count == 0 ); | |
265 | } | |
266 | ||
cbca1e08 MB |
267 | WX_DECLARE_HASH(Foo, wxListFoos, wxHashFoos); |
268 | ||
cbca1e08 MB |
269 | void HashesTestCase::wxTypedHashTableTest() |
270 | { | |
271 | // need a nested scope for destruction | |
272 | { | |
273 | wxHashFoos hash; | |
274 | hash.DeleteContents(true); | |
275 | ||
276 | CPPUNIT_ASSERT( hash.GetCount() == 0 ); | |
277 | CPPUNIT_ASSERT( Foo::count == 0 ); | |
278 | ||
279 | static const int hashTestData[] = | |
280 | { | |
281 | 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1, | |
282 | }; | |
283 | ||
284 | size_t n; | |
285 | for ( n = 0; n < WXSIZEOF(hashTestData); n++ ) | |
286 | { | |
287 | hash.Put(hashTestData[n], n, new Foo(n)); | |
288 | } | |
289 | ||
290 | CPPUNIT_ASSERT( hash.GetCount() == WXSIZEOF(hashTestData) ); | |
291 | CPPUNIT_ASSERT( Foo::count == WXSIZEOF(hashTestData) ); | |
292 | ||
293 | for ( n = 0; n < WXSIZEOF(hashTestData); n++ ) | |
294 | { | |
295 | Foo *foo = hash.Get(hashTestData[n], n); | |
296 | ||
297 | CPPUNIT_ASSERT( foo != NULL ); | |
298 | CPPUNIT_ASSERT( foo->n == (int)n ); | |
299 | } | |
300 | ||
301 | // element not in hash | |
302 | CPPUNIT_ASSERT( hash.Get(1234) == NULL ); | |
303 | CPPUNIT_ASSERT( hash.Get(1, 0) == NULL ); | |
304 | ||
305 | // delete from hash without deleting object | |
306 | Foo* foo = hash.Delete(0); | |
307 | ||
308 | CPPUNIT_ASSERT( Foo::count == WXSIZEOF(hashTestData) ); | |
309 | delete foo; | |
310 | CPPUNIT_ASSERT( Foo::count == WXSIZEOF(hashTestData) - 1 ); | |
311 | } | |
312 | ||
313 | // hash destroyed | |
314 | CPPUNIT_ASSERT( Foo::count == 0 ); | |
315 | } | |
316 | ||
7d9cfc54 MB |
317 | // test compilation of basic map types |
318 | WX_DECLARE_HASH_MAP( int*, int*, wxPointerHash, wxPointerEqual, myPtrHashMap ); | |
319 | WX_DECLARE_HASH_MAP( long, long, wxIntegerHash, wxIntegerEqual, myLongHashMap ); | |
320 | WX_DECLARE_HASH_MAP( unsigned long, unsigned, wxIntegerHash, wxIntegerEqual, | |
321 | myUnsignedHashMap ); | |
322 | WX_DECLARE_HASH_MAP( unsigned int, unsigned, wxIntegerHash, wxIntegerEqual, | |
323 | myTestHashMap1 ); | |
324 | WX_DECLARE_HASH_MAP( int, unsigned, wxIntegerHash, wxIntegerEqual, | |
325 | myTestHashMap2 ); | |
326 | WX_DECLARE_HASH_MAP( short, unsigned, wxIntegerHash, wxIntegerEqual, | |
327 | myTestHashMap3 ); | |
328 | WX_DECLARE_HASH_MAP( unsigned short, unsigned, wxIntegerHash, wxIntegerEqual, | |
329 | myTestHashMap4 ); | |
330 | ||
331 | // same as: | |
332 | // WX_DECLARE_HASH_MAP( wxString, wxString, wxStringHash, wxStringEqual, | |
333 | // myStringHashMap ); | |
334 | WX_DECLARE_STRING_HASH_MAP(wxString, myStringHashMap); | |
335 | ||
d8b6309b MW |
336 | #ifdef TEST_LONGLONG |
337 | WX_DECLARE_HASH_MAP( wxLongLong_t, wxLongLong_t, | |
338 | wxIntegerHash, wxIntegerEqual, myLLongHashMap ); | |
339 | WX_DECLARE_HASH_MAP( wxULongLong_t, wxULongLong_t, | |
340 | wxIntegerHash, wxIntegerEqual, myULLongHashMap ); | |
341 | #endif | |
342 | ||
343 | // Helpers to generate a key value pair for item 'i', out of a total of 'count' | |
344 | void MakeKeyValuePair(size_t i, size_t /*count*/, wxString& key, wxString& val) | |
345 | { | |
346 | key.clear(); | |
347 | key << i; | |
348 | val = wxT("A") + key + wxT("C"); | |
349 | } | |
350 | ||
351 | // for integral keys generate a range of keys that will use all the bits of | |
352 | // the key type | |
353 | template <class IntT, class KeyT> | |
354 | IntT MakeKey(size_t i, size_t count) | |
355 | { | |
356 | IntT max = 1; | |
357 | max <<= sizeof(KeyT) * 8 - 2; | |
358 | max -= count / 4 + 1; | |
d7ad5a02 | 359 | |
d8b6309b MW |
360 | return max / count * 4 * i + i / 3; |
361 | } | |
7d9cfc54 | 362 | |
d8b6309b MW |
363 | // make key/value pairs for integer types |
364 | template <class KeyT, class ValueT> | |
365 | void MakeKeyValuePair(size_t i, size_t count, KeyT& key, ValueT& value) | |
cbca1e08 | 366 | { |
d8b6309b MW |
367 | key = MakeKey<KeyT, KeyT>(i, count); |
368 | value = wx_truncate_cast(ValueT, key); | |
369 | } | |
370 | ||
371 | // make key/values paris for pointer types | |
372 | template <class T, class ValueT> | |
373 | void MakeKeyValuePair(size_t i, size_t count, T*& key, ValueT& value) | |
374 | { | |
375 | key = (T*)wxUIntToPtr(MakeKey<wxUIntPtr, T*>(i, count)); | |
376 | value = wx_truncate_cast(ValueT, key); | |
377 | } | |
378 | ||
379 | // the test | |
380 | template <class HashMapT> | |
381 | void HashMapTest() | |
382 | { | |
d8b6309b | 383 | typedef typename HashMapT::value_type::second_type value_type; |
d8b6309b MW |
384 | typedef typename HashMapT::key_type key_type; |
385 | typedef typename HashMapT::iterator Itor; | |
386 | ||
387 | HashMapT sh(0); // as small as possible | |
388 | key_type buf; | |
389 | value_type value; | |
7d9cfc54 MB |
390 | size_t i; |
391 | const size_t count = 10000; | |
392 | ||
393 | // init with some data | |
394 | for( i = 0; i < count; ++i ) | |
395 | { | |
d8b6309b MW |
396 | MakeKeyValuePair(i, count, buf, value); |
397 | sh[buf] = value; | |
7d9cfc54 MB |
398 | } |
399 | ||
400 | // test that insertion worked | |
401 | CPPUNIT_ASSERT( sh.size() == count ); | |
402 | ||
403 | for( i = 0; i < count; ++i ) | |
404 | { | |
d8b6309b MW |
405 | MakeKeyValuePair(i, count, buf, value); |
406 | CPPUNIT_ASSERT( sh[buf] == value ); | |
7d9cfc54 MB |
407 | } |
408 | ||
409 | // check that iterators work | |
410 | Itor it; | |
411 | for( i = 0, it = sh.begin(); it != sh.end(); ++it, ++i ) | |
412 | { | |
413 | CPPUNIT_ASSERT( i != count ); | |
414 | CPPUNIT_ASSERT( it->second == sh[it->first] ); | |
415 | } | |
416 | ||
417 | CPPUNIT_ASSERT( sh.size() == i ); | |
418 | ||
419 | // test copy ctor, assignment operator | |
d8b6309b | 420 | HashMapT h1( sh ), h2( 0 ); |
7d9cfc54 MB |
421 | h2 = sh; |
422 | ||
423 | for( i = 0, it = sh.begin(); it != sh.end(); ++it, ++i ) | |
424 | { | |
425 | CPPUNIT_ASSERT( h1[it->first] == it->second ); | |
426 | CPPUNIT_ASSERT( h2[it->first] == it->second ); | |
427 | } | |
428 | ||
429 | // other tests | |
430 | for( i = 0; i < count; ++i ) | |
431 | { | |
d8b6309b | 432 | MakeKeyValuePair(i, count, buf, value); |
7d9cfc54 MB |
433 | size_t sz = sh.size(); |
434 | ||
435 | // test find() and erase(it) | |
436 | if( i < 100 ) | |
437 | { | |
438 | it = sh.find( buf ); | |
439 | CPPUNIT_ASSERT( it != sh.end() ); | |
440 | ||
441 | sh.erase( it ); | |
442 | ||
443 | CPPUNIT_ASSERT( sh.find( buf ) == sh.end() ); | |
444 | } | |
445 | else | |
446 | // test erase(key) | |
447 | { | |
448 | size_t c = sh.erase( buf ); | |
449 | CPPUNIT_ASSERT( c == 1 ); | |
450 | CPPUNIT_ASSERT( sh.find( buf ) == sh.end() ); | |
451 | } | |
452 | ||
453 | // count should decrease | |
454 | CPPUNIT_ASSERT( sh.size() == sz - 1 ); | |
455 | } | |
cbca1e08 MB |
456 | } |
457 | ||
d8b6309b MW |
458 | void HashesTestCase::StringHashMapTest() { HashMapTest<myStringHashMap>(); } |
459 | void HashesTestCase::PtrHashMapTest() { HashMapTest<myPtrHashMap>(); } | |
460 | void HashesTestCase::LongHashMapTest() { HashMapTest<myLongHashMap>(); } | |
461 | void HashesTestCase::ULongHashMapTest() { HashMapTest<myUnsignedHashMap>(); } | |
462 | void HashesTestCase::UIntHashMapTest() { HashMapTest<myTestHashMap1>(); } | |
463 | void HashesTestCase::IntHashMapTest() { HashMapTest<myTestHashMap2>(); } | |
464 | void HashesTestCase::ShortHashMapTest() { HashMapTest<myTestHashMap3>(); } | |
465 | void HashesTestCase::UShortHashMapTest() { HashMapTest<myTestHashMap4>(); } | |
466 | ||
467 | #ifdef TEST_LONGLONG | |
468 | void HashesTestCase::LLongHashMapTest() { HashMapTest<myLLongHashMap>(); } | |
469 | void HashesTestCase::ULLongHashMapTest() { HashMapTest<myULLongHashMap>(); } | |
470 | #endif | |
471 | ||
5098c258 VZ |
472 | #ifdef __VISUALC__ |
473 | #if __VISUALC__ <= 1200 | |
474 | #pragma warning(disable:4284) // operator->() returns a non-UDT | |
475 | #endif | |
476 | #endif // __VISUALC__ | |
477 | ||
7d9cfc54 MB |
478 | // test compilation of basic set types |
479 | WX_DECLARE_HASH_SET( int*, wxPointerHash, wxPointerEqual, myPtrHashSet ); | |
480 | WX_DECLARE_HASH_SET( long, wxIntegerHash, wxIntegerEqual, myLongHashSet ); | |
481 | WX_DECLARE_HASH_SET( unsigned long, wxIntegerHash, wxIntegerEqual, | |
482 | myUnsignedHashSet ); | |
483 | WX_DECLARE_HASH_SET( unsigned int, wxIntegerHash, wxIntegerEqual, | |
484 | myTestHashSet1 ); | |
485 | WX_DECLARE_HASH_SET( int, wxIntegerHash, wxIntegerEqual, | |
486 | myTestHashSet2 ); | |
487 | WX_DECLARE_HASH_SET( short, wxIntegerHash, wxIntegerEqual, | |
488 | myTestHashSet3 ); | |
489 | WX_DECLARE_HASH_SET( unsigned short, wxIntegerHash, wxIntegerEqual, | |
490 | myTestHashSet4 ); | |
491 | WX_DECLARE_HASH_SET( wxString, wxStringHash, wxStringEqual, | |
492 | myTestHashSet5 ); | |
493 | ||
494 | struct MyStruct | |
495 | { | |
496 | int* ptr; | |
497 | wxString str; | |
498 | }; | |
499 | ||
500 | class MyHash | |
501 | { | |
502 | public: | |
503 | unsigned long operator()(const MyStruct& s) const | |
504 | { return m_dummy(s.ptr); } | |
505 | MyHash& operator=(const MyHash&) { return *this; } | |
506 | private: | |
507 | wxPointerHash m_dummy; | |
508 | }; | |
509 | ||
510 | class MyEqual | |
511 | { | |
512 | public: | |
513 | bool operator()(const MyStruct& s1, const MyStruct& s2) const | |
514 | { return s1.ptr == s2.ptr; } | |
515 | MyEqual& operator=(const MyEqual&) { return *this; } | |
516 | }; | |
517 | ||
518 | WX_DECLARE_HASH_SET( MyStruct, MyHash, MyEqual, mySet ); | |
519 | ||
520 | typedef myTestHashSet5 wxStringHashSet; | |
521 | ||
cbca1e08 MB |
522 | void HashesTestCase::wxHashSetTest() |
523 | { | |
7d9cfc54 MB |
524 | wxStringHashSet set1; |
525 | ||
526 | set1.insert( _T("abc") ); | |
527 | ||
528 | CPPUNIT_ASSERT( set1.size() == 1 ); | |
529 | ||
530 | set1.insert( _T("bbc") ); | |
531 | set1.insert( _T("cbc") ); | |
532 | ||
533 | CPPUNIT_ASSERT( set1.size() == 3 ); | |
534 | ||
535 | set1.insert( _T("abc") ); | |
536 | ||
537 | CPPUNIT_ASSERT( set1.size() == 3 ); | |
538 | ||
539 | mySet set2; | |
540 | int dummy; | |
541 | MyStruct tmp; | |
542 | ||
543 | tmp.ptr = &dummy; tmp.str = _T("ABC"); | |
544 | set2.insert( tmp ); | |
545 | tmp.ptr = &dummy + 1; | |
546 | set2.insert( tmp ); | |
547 | tmp.ptr = &dummy; tmp.str = _T("CDE"); | |
548 | set2.insert( tmp ); | |
549 | ||
550 | CPPUNIT_ASSERT( set2.size() == 2 ); | |
551 | ||
552 | mySet::iterator it = set2.find( tmp ); | |
553 | ||
554 | CPPUNIT_ASSERT( it != set2.end() ); | |
555 | CPPUNIT_ASSERT( it->ptr == &dummy ); | |
556 | CPPUNIT_ASSERT( it->str == _T("ABC") ); | |
cbca1e08 | 557 | } |