81462dd4e13b8a3f836a939a8f7fa5fd16ac77c1
[libcds.git] / tests / test-hdr / map / hdr_map.h
1 //$$CDS-header$$
2
3 #ifndef __CDSTEST_HDR_MAP_H
4 #define __CDSTEST_HDR_MAP_H
5 #include "size_check.h"
6
7 #include "cppunit/cppunit_proxy.h"
8 #include <cds/os/timer.h>
9 #include <cds/opt/hash.h>
10 #include <functional>   // ref
11 #include <algorithm>    // random_shuffle
12
13 namespace cds { namespace container {}}
14
15 namespace map {
16     using misc::check_size;
17
18     namespace cc = cds::container;
19     namespace co = cds::opt;
20
21     // MichaelHashSet based on MichaelList
22     class HashMapHdrTest: public CppUnitMini::TestCase
23     {
24     public:
25         typedef int key_type;
26
27         struct value_type {
28             int m_val;
29
30             value_type()
31                 : m_val(0)
32             {}
33
34             value_type( int n )
35                 : m_val( n )
36             {}
37
38             value_type( value_type&& v )
39                 : m_val( v.m_val )
40             {}
41
42             value_type( value_type const& v )
43                 : m_val( v.m_val )
44             {}
45
46             value_type& operator=( value_type const& v )
47             {
48                 m_val = v.m_val;
49                 return *this;
50             }
51         };
52
53         typedef std::pair<key_type const, value_type> pair_type;
54
55         struct less
56         {
57             bool operator ()(int v1, int v2 ) const
58             {
59                 return v1 < v2;
60             }
61         };
62
63         struct cmp {
64             int operator ()(int v1, int v2 ) const
65             {
66                 if ( v1 < v2 )
67                     return -1;
68                 return v1 > v2 ? 1 : 0;
69             }
70         };
71
72         struct equal {
73             bool operator ()(int v1, int v2 ) const
74             {
75                 return v1 == v2;
76             }
77         };
78
79         struct hash_int {
80             size_t operator()( int i ) const
81             {
82                 return co::v::hash<int>()( i );
83             }
84
85             template <typename T>
86             size_t operator()( T const& i ) const
87             {
88                 return co::v::hash<int>()( i.nKey );
89             }
90         };
91
92         struct simple_item_counter {
93             size_t  m_nCount;
94
95             simple_item_counter()
96                 : m_nCount(0)
97             {}
98
99             size_t operator ++()
100             {
101                 return ++m_nCount;
102             }
103
104             size_t operator --()
105             {
106                 return --m_nCount;
107             }
108
109             void reset()
110             {
111                 m_nCount = 0;
112             }
113
114             operator size_t() const
115             {
116                 return m_nCount;
117             }
118         };
119
120         template <typename Map>
121         struct insert_functor
122         {
123             typedef typename Map::value_type pair_type;
124
125             // insert ftor
126             void operator()( pair_type& item )
127             {
128                 item.second.m_val = item.first * 3;
129             }
130
131             // ensure ftor
132             void operator()( bool bNew, pair_type& item )
133             {
134                 if ( bNew )
135                     item.second.m_val = item.first * 2;
136                 else
137                     item.second.m_val = item.first * 5;
138             }
139         };
140
141         struct check_value {
142             int     m_nExpected;
143
144             check_value( int nExpected )
145                 : m_nExpected( nExpected )
146             {}
147
148             template <typename T>
149             void operator ()( T& pair )
150             {
151                 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
152             }
153             template <typename T, typename Q>
154             void operator ()( T& pair, Q )
155             {
156                 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
157             }
158         };
159
160         struct extract_functor
161         {
162             int *   m_pVal;
163             void operator()( pair_type const& val )
164             {
165                 *m_pVal = val.second.m_val;
166             }
167         };
168
169         struct other_item {
170             int nKey;
171
172             other_item( int key )
173                 : nKey(key)
174             {}
175         };
176
177         struct other_less
178         {
179             bool operator ()(int v1, other_item const& v2 ) const
180             {
181                 return v1 < v2.nKey;
182             }
183             bool operator ()(other_item const& v1, int v2 ) const
184             {
185                 return v1.nKey < v2;
186             }
187         };
188
189
190         template <class Map>
191         void test_int()
192         {
193             Map m( 100, 4 );
194
195             test_int_with(m);
196
197             // extract/get test
198             CPPUNIT_ASSERT( m.empty() );
199             {
200                 const int nLimit = 100;
201                 typename Map::guarded_ptr gp;
202                 int arrRandom[nLimit];
203                 for ( int i = 0; i < nLimit; ++i )
204                     arrRandom[i] = i;
205                 std::random_shuffle( arrRandom, arrRandom + nLimit );
206
207                 for ( int i = 0; i < nLimit; ++i )
208                     CPPUNIT_ASSERT( m.insert( arrRandom[i], arrRandom[i] ));
209
210                 for ( int i = 0; i < nLimit; ++i ) {
211                     int nKey = arrRandom[i];
212                     gp = m.get( nKey );
213                     CPPUNIT_ASSERT( gp );
214                     CPPUNIT_ASSERT( !gp.empty());
215                     CPPUNIT_CHECK( gp->first == nKey );
216                     CPPUNIT_CHECK( gp->second.m_val == nKey );
217
218                     gp = m.extract( nKey );
219                     CPPUNIT_ASSERT( gp );
220                     CPPUNIT_ASSERT( !gp.empty());
221                     CPPUNIT_CHECK( gp->first == nKey );
222                     CPPUNIT_CHECK( gp->second.m_val == nKey );
223                     gp = m.get( nKey );
224                     CPPUNIT_CHECK( !gp );
225
226                     CPPUNIT_CHECK( !m.extract(nKey));
227                     CPPUNIT_CHECK( gp.empty());
228                 }
229                 CPPUNIT_ASSERT( m.empty() );
230
231                 for ( int i = 0; i < nLimit; ++i )
232                     CPPUNIT_ASSERT( m.insert( arrRandom[i], arrRandom[i] ));
233
234                 for ( int i = 0; i < nLimit; ++i ) {
235                     int nKey = arrRandom[i];
236                     gp = m.get_with( other_item( nKey ), other_less() );
237                     CPPUNIT_ASSERT( gp );
238                     CPPUNIT_ASSERT( !gp.empty());
239                     CPPUNIT_CHECK( gp->first == nKey );
240                     CPPUNIT_CHECK( gp->second.m_val == nKey );
241
242                     gp = m.extract_with( other_item( nKey ), other_less() );
243                     CPPUNIT_ASSERT( gp );
244                     CPPUNIT_ASSERT( !gp.empty());
245                     CPPUNIT_CHECK( gp->first == nKey );
246                     CPPUNIT_CHECK( gp->second.m_val == nKey );
247                     gp = m.get_with( other_item( nKey ), other_less() );
248                     CPPUNIT_CHECK( !gp );
249
250                     CPPUNIT_CHECK( !m.extract_with(other_item(nKey), other_less() ));
251                     CPPUNIT_CHECK( gp.empty());
252                 }
253                 CPPUNIT_ASSERT( m.empty() );
254             }
255
256             // iterator test
257             test_iter<Map>();
258         }
259
260         template <class Map>
261         void test_rcu()
262         {
263             Map m( 52, 4 );
264
265             test_int_with(m);
266
267             // extract/get test
268             {
269                 typedef typename Map::gc    rcu;
270                 typedef typename Map::rcu_lock rcu_lock;
271                 typedef typename Map::value_type value_type;
272                 typename Map::exempt_ptr ep;
273
274                 static size_t const nLimit = 100;
275                 int arr[nLimit];
276                 for ( size_t i = 0; i < nLimit; ++i )
277                     arr[i] = (int) i;
278                 std::random_shuffle( arr, arr + nLimit );
279
280                 for ( size_t i = 0; i < nLimit; ++i )
281                     CPPUNIT_ASSERT( m.insert( arr[i], arr[i] ));
282
283                 for ( size_t i = 0; i < nLimit; i += 2 ) {
284                     value_type * pVal;
285                     int nKey = arr[i];
286                     {
287                         rcu_lock l;
288                         pVal = m.get( nKey );
289                         CPPUNIT_ASSERT( pVal != nullptr );
290                         CPPUNIT_CHECK( pVal->first == nKey );
291                         CPPUNIT_CHECK( pVal->second.m_val == nKey );
292
293                         ep = m.extract( nKey );
294                         CPPUNIT_ASSERT( ep );
295                         CPPUNIT_ASSERT( !ep.empty() );
296                         CPPUNIT_CHECK( pVal->first == ep->first );
297                         CPPUNIT_CHECK( pVal->second.m_val == ep->second.m_val );
298                     }
299                     ep.release();
300                     {
301                         rcu_lock l;
302                         CPPUNIT_CHECK( m.get( nKey ) == nullptr );
303                         ep = m.extract( nKey );
304                         CPPUNIT_CHECK( !ep );
305                         CPPUNIT_CHECK( ep.empty() );
306
307                         nKey = arr[i+1];
308                         pVal = m.get_with( other_item(nKey), other_less() );
309                         CPPUNIT_ASSERT( pVal != nullptr );
310                         CPPUNIT_CHECK( pVal->first == nKey );
311                         CPPUNIT_CHECK( pVal->second.m_val == nKey );
312
313                         ep = m.extract_with( other_item( nKey ), other_less() );
314                         CPPUNIT_ASSERT( ep );
315                         CPPUNIT_ASSERT( !ep.empty() );
316                         CPPUNIT_CHECK( pVal->first == ep->first );
317                         CPPUNIT_CHECK( pVal->second.m_val == (*ep).second.m_val );
318                     }
319                     ep.release();
320                     {
321                         rcu_lock l;
322                         CPPUNIT_CHECK( m.get_with( other_item(nKey), other_less() ) == nullptr );
323                         CPPUNIT_CHECK( !m.extract_with( other_item(nKey), other_less() ));
324                         CPPUNIT_CHECK( ep.empty() );
325                     }
326                 }
327                 CPPUNIT_CHECK( m.empty() );
328                 CPPUNIT_CHECK( check_size( m, 0 ));
329                 {
330                     rcu_lock l;
331                     CPPUNIT_CHECK( m.get( int(nLimit / 2) ) == nullptr );
332                     ep = m.extract( int( nLimit / 2 ) );
333                     CPPUNIT_CHECK( !ep );
334                     CPPUNIT_CHECK( ep.empty() );
335                 }
336             }
337
338             // iterator test
339             test_iter<Map>();
340         }
341
342         template <class Map>
343         void test_int_with( Map& m )
344         {
345             std::pair<bool, bool> ensureResult;
346
347             // insert
348             CPPUNIT_ASSERT( m.empty() );
349             CPPUNIT_ASSERT( check_size( m, 0 ));
350             CPPUNIT_ASSERT( !m.find(25) );
351             CPPUNIT_ASSERT( m.insert( 25 ) )    ;   // value = 0
352             CPPUNIT_ASSERT( m.find(25) );
353             CPPUNIT_ASSERT( !m.empty() );
354             CPPUNIT_ASSERT( check_size( m, 1 ));
355             CPPUNIT_ASSERT( m.find(25) );
356
357             CPPUNIT_ASSERT( !m.insert( 25 ) );
358             CPPUNIT_ASSERT( !m.empty() );
359             CPPUNIT_ASSERT( check_size( m, 1 ));
360
361             CPPUNIT_ASSERT( !m.find_with(10, less()) );
362             CPPUNIT_ASSERT( m.insert( 10, 10 ) );
363             CPPUNIT_ASSERT( !m.empty() );
364             CPPUNIT_ASSERT( check_size( m, 2 ));
365             CPPUNIT_ASSERT( m.find_with(10, less()) );
366
367             CPPUNIT_ASSERT( !m.insert( 10, 20 ) );
368             CPPUNIT_ASSERT( !m.empty() );
369             CPPUNIT_ASSERT( check_size( m, 2 ));
370
371             CPPUNIT_ASSERT( !m.find(30) );
372             CPPUNIT_ASSERT( m.insert_key( 30, insert_functor<Map>() ) )    ; // value = 90
373             CPPUNIT_ASSERT( !m.empty() );
374             CPPUNIT_ASSERT( check_size( m, 3 ));
375             CPPUNIT_ASSERT( m.find(30) );
376
377             CPPUNIT_ASSERT( !m.insert_key( 10, insert_functor<Map>() ) );
378             CPPUNIT_ASSERT( !m.insert_key( 25, insert_functor<Map>() ) );
379             CPPUNIT_ASSERT( !m.insert_key( 30, insert_functor<Map>() ) );
380
381             // ensure (new key)
382             CPPUNIT_ASSERT( !m.find(27) );
383             ensureResult = m.ensure( 27, insert_functor<Map>() ) ;   // value = 54
384             CPPUNIT_ASSERT( ensureResult.first );
385             CPPUNIT_ASSERT( ensureResult.second );
386             CPPUNIT_ASSERT( m.find(27) );
387
388             // find test
389             check_value chk(10);
390             CPPUNIT_ASSERT( m.find( 10, std::ref(chk) ));
391             chk.m_nExpected = 0;
392             CPPUNIT_ASSERT( m.find_with( 25, less(), std::ref( chk ) ) );
393             chk.m_nExpected = 90;
394             CPPUNIT_ASSERT( m.find( 30, std::ref( chk ) ) );
395             chk.m_nExpected = 54;
396             CPPUNIT_ASSERT( m.find( 27, std::ref( chk ) ) );
397
398             ensureResult = m.ensure( 10, insert_functor<Map>() ) ;   // value = 50
399             CPPUNIT_ASSERT( ensureResult.first );
400             CPPUNIT_ASSERT( !ensureResult.second );
401             chk.m_nExpected = 50;
402             CPPUNIT_ASSERT( m.find( 10, std::ref( chk ) ) );
403
404             // erase test
405             CPPUNIT_ASSERT( !m.find(100) );
406             CPPUNIT_ASSERT( !m.erase( 100 )) ;  // not found
407
408             CPPUNIT_ASSERT( m.find(25) );
409             CPPUNIT_ASSERT( check_size( m, 4 ));
410             CPPUNIT_ASSERT( m.erase( 25 ));
411             CPPUNIT_ASSERT( !m.empty() );
412             CPPUNIT_ASSERT( check_size( m, 3 ));
413             CPPUNIT_ASSERT( !m.find(25) );
414             CPPUNIT_ASSERT( !m.erase( 25 ));
415
416             CPPUNIT_ASSERT( !m.find(258) );
417             CPPUNIT_ASSERT( m.insert(258))
418             CPPUNIT_ASSERT( check_size( m, 4 ));
419             CPPUNIT_ASSERT( m.find_with(258, less()) );
420             CPPUNIT_ASSERT( m.erase_with( 258, less() ));
421             CPPUNIT_ASSERT( !m.empty() );
422             CPPUNIT_ASSERT( check_size( m, 3 ));
423             CPPUNIT_ASSERT( !m.find(258) );
424             CPPUNIT_ASSERT( !m.erase_with( 258, less() ));
425
426             int nVal;
427             extract_functor ext;
428             ext.m_pVal = &nVal;
429
430             CPPUNIT_ASSERT( !m.find(29) );
431             CPPUNIT_ASSERT( m.insert(29, 290));
432             CPPUNIT_ASSERT( check_size( m, 4 ));
433             CPPUNIT_ASSERT( m.erase_with( 29, less(), std::ref( ext ) ) );
434             CPPUNIT_ASSERT( !m.empty() );
435             CPPUNIT_ASSERT( check_size( m, 3 ));
436             CPPUNIT_ASSERT( nVal == 290 );
437             nVal = -1;
438             CPPUNIT_ASSERT( !m.erase_with( 29, less(), std::ref( ext ) ) );
439             CPPUNIT_ASSERT( nVal == -1 );
440
441             CPPUNIT_ASSERT( m.erase( 30, std::ref( ext ) ) );
442             CPPUNIT_ASSERT( !m.empty() );
443             CPPUNIT_ASSERT( check_size( m, 2 ));
444             CPPUNIT_ASSERT( nVal == 90 );
445             nVal = -1;
446             CPPUNIT_ASSERT( !m.erase( 30, std::ref( ext ) ) );
447             CPPUNIT_ASSERT( nVal == -1 );
448
449             m.clear();
450             CPPUNIT_ASSERT( m.empty() );
451             CPPUNIT_ASSERT( check_size( m, 0 ));
452
453             // emplace test
454             CPPUNIT_ASSERT( m.emplace(126) ) ; // key = 126, val = 0
455             CPPUNIT_ASSERT( m.emplace(137, 731))    ;   // key = 137, val = 731
456             CPPUNIT_ASSERT( m.emplace( 149, value_type(941) ))   ;   // key = 149, val = 941
457
458             CPPUNIT_ASSERT( !m.empty() );
459             CPPUNIT_ASSERT( check_size( m, 3 ));
460
461             chk.m_nExpected = 0;
462             CPPUNIT_ASSERT( m.find( 126, std::ref(chk) ));
463             chk.m_nExpected = 731;
464             CPPUNIT_ASSERT( m.find_with( 137, less(), std::ref(chk) ));
465             chk.m_nExpected = 941;
466             CPPUNIT_ASSERT( m.find( 149, std::ref(chk) ));
467
468             CPPUNIT_ASSERT( !m.emplace(126, 621)) ; // already in map
469             chk.m_nExpected = 0;
470             CPPUNIT_ASSERT( m.find( 126, std::ref(chk) ));
471             CPPUNIT_ASSERT( !m.empty() );
472             CPPUNIT_ASSERT( check_size( m, 3 ));
473
474             m.clear();
475             CPPUNIT_ASSERT( m.empty() );
476             CPPUNIT_ASSERT( check_size( m, 0 ));
477         }
478
479
480         template <class Map>
481         void test_int_nogc()
482         {
483             typedef typename Map::iterator          iterator;
484             typedef typename Map::const_iterator    const_iterator;
485
486             {
487                 Map m( 52, 4 );
488
489                 CPPUNIT_ASSERT( m.empty() );
490                 CPPUNIT_ASSERT( check_size( m, 0 ));
491
492                 CPPUNIT_ASSERT( m.find(10) == m.end() );
493                 iterator it = m.insert( 10 );
494                 CPPUNIT_ASSERT( it != m.end() );
495                 CPPUNIT_ASSERT( !m.empty() );
496                 CPPUNIT_ASSERT( check_size( m, 1 ));
497                 CPPUNIT_ASSERT( m.find(10) == it );
498                 CPPUNIT_ASSERT( it->first == 10 );
499                 CPPUNIT_ASSERT( it->second.m_val == 0 );
500
501                 CPPUNIT_ASSERT( m.find(100) == m.end() );
502                 it = m.insert( 100, 200 );
503                 CPPUNIT_ASSERT( it != m.end() );
504                 CPPUNIT_ASSERT( !m.empty() );
505                 CPPUNIT_ASSERT( check_size( m, 2 ));
506                 CPPUNIT_ASSERT( m.find_with(100, less()) == it );
507                 CPPUNIT_ASSERT( it->first == 100 );
508                 CPPUNIT_ASSERT( it->second.m_val == 200 );
509
510                 CPPUNIT_ASSERT( m.find(55) == m.end() );
511                 it = m.insert_key( 55, insert_functor<Map>() );
512                 CPPUNIT_ASSERT( it != m.end() );
513                 CPPUNIT_ASSERT( !m.empty() );
514                 CPPUNIT_ASSERT( check_size( m, 3 ));
515                 CPPUNIT_ASSERT( m.find(55) == it );
516                 CPPUNIT_ASSERT( it->first == 55 );
517                 CPPUNIT_ASSERT( it->second.m_val == 55 * 3 );
518
519                 CPPUNIT_ASSERT( m.insert( 55 ) == m.end() );
520                 CPPUNIT_ASSERT( m.insert( 55, 10 ) == m.end() );
521                 CPPUNIT_ASSERT( m.insert_key( 55, insert_functor<Map>()) == m.end() );
522
523                 CPPUNIT_ASSERT( m.find(10) != m.end() );
524                 std::pair<iterator, bool> ensureResult = m.ensure( 10 );
525                 CPPUNIT_ASSERT( ensureResult.first != m.end() );
526                 CPPUNIT_ASSERT( !ensureResult.second  );
527                 CPPUNIT_ASSERT( !m.empty() );
528                 ensureResult.first->second.m_val = ensureResult.first->first * 5;
529                 CPPUNIT_ASSERT( check_size( m, 3 ));
530                 CPPUNIT_ASSERT( m.find(10) == ensureResult.first );
531                 it = m.find(10);
532                 CPPUNIT_ASSERT( it != m.end() );
533                 CPPUNIT_ASSERT( it->second.m_val == 50 );
534
535                 CPPUNIT_ASSERT( m.find(120) == m.end() );
536                 ensureResult = m.ensure( 120 );
537                 CPPUNIT_ASSERT( ensureResult.first != m.end() );
538                 CPPUNIT_ASSERT( ensureResult.second  );
539                 CPPUNIT_ASSERT( !m.empty() );
540                 CPPUNIT_ASSERT( check_size( m, 4 ));
541                 ensureResult.first->second.m_val = ensureResult.first->first * 5;
542                 CPPUNIT_ASSERT( m.find_with(120, less()) == ensureResult.first );
543                 it = m.find_with(120, less());
544                 CPPUNIT_ASSERT( it != m.end() );
545                 CPPUNIT_ASSERT( it->second.m_val == 120 * 5 );
546                 CPPUNIT_ASSERT( m.find_with(120, less()) == m.find(120) );
547
548                 // emplace test
549                 it = m.emplace( 151 ) ;  // key = 151,  val = 0
550                 CPPUNIT_ASSERT( it != m.end() );
551                 CPPUNIT_ASSERT( it->first == 151 );
552                 CPPUNIT_ASSERT( it->second.m_val == 0 );
553
554                 it = m.emplace( 174, 471 ) ; // key == 174, val = 471
555                 CPPUNIT_ASSERT( it != m.end() );
556                 CPPUNIT_ASSERT( it->first == 174 );
557                 CPPUNIT_ASSERT( it->second.m_val == 471 );
558
559                 it = m.emplace( 190, value_type(91)) ; // key == 190, val = 19
560                 CPPUNIT_ASSERT( it != m.end() );
561                 CPPUNIT_ASSERT( it->first == 190 );
562                 CPPUNIT_ASSERT( it->second.m_val == 91 );
563
564                 it = m.emplace( 151, 1051 );
565                 CPPUNIT_ASSERT( it == m.end());
566
567                 it = m.find( 174 );
568                 CPPUNIT_ASSERT( it != m.end() );
569                 CPPUNIT_ASSERT( it->first == 174 );
570                 CPPUNIT_ASSERT( it->second.m_val == 471 );
571
572                 it = m.find( 190 );
573                 CPPUNIT_ASSERT( it != m.end() );
574                 CPPUNIT_ASSERT( it->first == 190 );
575                 CPPUNIT_ASSERT( it->second.m_val == 91 );
576
577                 it = m.find( 151 );
578                 CPPUNIT_ASSERT( it != m.end() );
579                 CPPUNIT_ASSERT( it->first == 151 );
580                 CPPUNIT_ASSERT( it->second.m_val == 0 );
581             }
582
583             // iterator test
584
585             {
586                 Map m( 52, 4 );
587
588                 for ( int i = 0; i < 500; ++i ) {
589                     CPPUNIT_ASSERT( m.insert( i, i * 2 ) != m.end() );
590                 }
591                 CPPUNIT_ASSERT( check_size( m, 500 ));
592
593                 {
594                     typename Map::iterator it( m.begin() );
595                     typename Map::const_iterator cit( m.cbegin() );
596                     CPPUNIT_CHECK( it == cit );
597                     CPPUNIT_CHECK( it != m.end() );
598                     CPPUNIT_CHECK( it != m.cend() );
599                     CPPUNIT_CHECK( cit != m.end() );
600                     CPPUNIT_CHECK( cit != m.cend() );
601                     ++it;
602                     CPPUNIT_CHECK( it != cit );
603                     CPPUNIT_CHECK( it != m.end() );
604                     CPPUNIT_CHECK( it != m.cend() );
605                     CPPUNIT_CHECK( cit != m.end() );
606                     CPPUNIT_CHECK( cit != m.cend() );
607                     ++cit;
608                     CPPUNIT_CHECK( it == cit );
609                     CPPUNIT_CHECK( it != m.end() );
610                     CPPUNIT_CHECK( it != m.cend() );
611                     CPPUNIT_CHECK( cit != m.end() );
612                     CPPUNIT_CHECK( cit != m.cend() );
613                 }
614
615
616                 for ( iterator it = m.begin(), itEnd = m.end(); it != itEnd; ++it ) {
617                     iterator it2 = it;
618                     CPPUNIT_CHECK( it2 == it );
619                     CPPUNIT_CHECK( it2 != itEnd );
620                     CPPUNIT_ASSERT( it->first * 2 == (*it).second.m_val );
621                     it->second = it->first;
622                 }
623
624                 Map const& refMap = m;
625                 for ( const_iterator it = refMap.begin(), itEnd = refMap.end(); it != itEnd; ++it ) {
626                     CPPUNIT_ASSERT( it->first == it->second.m_val );
627                     CPPUNIT_ASSERT( (*it).first == (*it).second.m_val );
628                 }
629             }
630         }
631
632         template <class Map>
633         void test_iter()
634         {
635             typedef typename Map::iterator          iterator;
636             typedef typename Map::const_iterator    const_iterator;
637
638             Map s( 100, 4 );
639
640             const int nMaxCount = 500;
641             for ( int i = 0; i < nMaxCount; ++i ) {
642                 CPPUNIT_ASSERT( s.insert( i, i * 2 ));
643             }
644
645             {
646                 typename Map::iterator it( s.begin() );
647                 typename Map::const_iterator cit( s.cbegin() );
648                 CPPUNIT_CHECK( it == cit );
649                 CPPUNIT_CHECK( it != s.end() );
650                 CPPUNIT_CHECK( it != s.cend() );
651                 CPPUNIT_CHECK( cit != s.end() );
652                 CPPUNIT_CHECK( cit != s.cend() );
653                 ++it;
654                 CPPUNIT_CHECK( it != cit );
655                 CPPUNIT_CHECK( it != s.end() );
656                 CPPUNIT_CHECK( it != s.cend() );
657                 CPPUNIT_CHECK( cit != s.end() );
658                 CPPUNIT_CHECK( cit != s.cend() );
659                 ++cit;
660                 CPPUNIT_CHECK( it == cit );
661                 CPPUNIT_CHECK( it != s.end() );
662                 CPPUNIT_CHECK( it != s.cend() );
663                 CPPUNIT_CHECK( cit != s.end() );
664                 CPPUNIT_CHECK( cit != s.cend() );
665             }
666
667             int nCount = 0;
668             for ( iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) {
669                 CPPUNIT_ASSERT( it->first * 2 == it->second.m_val );
670                 CPPUNIT_ASSERT( (*it).first * 2 == (*it).second.m_val );
671                 it->second.m_val = it->first;
672                 ++nCount;
673             }
674             CPPUNIT_ASSERT( nCount == nMaxCount );
675
676             Map const& refSet = s;
677             nCount = 0;
678             for ( const_iterator it = refSet.begin(), itEnd = refSet.end(); it != itEnd; ++it ) {
679                 CPPUNIT_ASSERT( it->first == it->second.m_val );
680                 CPPUNIT_ASSERT( (*it).first == (*it).second.m_val );
681                 ++nCount;
682             }
683             CPPUNIT_ASSERT( nCount == nMaxCount );
684         }
685
686
687         void Michael_HP_cmp();
688         void Michael_HP_less();
689         void Michael_HP_cmpmix();
690
691         void Michael_DHP_cmp();
692         void Michael_DHP_less();
693         void Michael_DHP_cmpmix();
694
695         void Michael_RCU_GPI_cmp();
696         void Michael_RCU_GPI_less();
697         void Michael_RCU_GPI_cmpmix();
698
699         void Michael_RCU_GPB_cmp();
700         void Michael_RCU_GPB_less();
701         void Michael_RCU_GPB_cmpmix();
702
703         void Michael_RCU_GPT_cmp();
704         void Michael_RCU_GPT_less();
705         void Michael_RCU_GPT_cmpmix();
706
707         void Michael_RCU_SHB_cmp();
708         void Michael_RCU_SHB_less();
709         void Michael_RCU_SHB_cmpmix();
710
711         void Michael_RCU_SHT_cmp();
712         void Michael_RCU_SHT_less();
713         void Michael_RCU_SHT_cmpmix();
714
715         void Michael_nogc_cmp();
716         void Michael_nogc_less();
717         void Michael_nogc_cmpmix();
718
719         void Lazy_HP_cmp();
720         void Lazy_HP_less();
721         void Lazy_HP_cmpmix();
722
723         void Lazy_DHP_cmp();
724         void Lazy_DHP_less();
725         void Lazy_DHP_cmpmix();
726
727         void Lazy_RCU_GPI_cmp();
728         void Lazy_RCU_GPI_less();
729         void Lazy_RCU_GPI_cmpmix();
730
731         void Lazy_RCU_GPB_cmp();
732         void Lazy_RCU_GPB_less();
733         void Lazy_RCU_GPB_cmpmix();
734
735         void Lazy_RCU_GPT_cmp();
736         void Lazy_RCU_GPT_less();
737         void Lazy_RCU_GPT_cmpmix();
738
739         void Lazy_RCU_SHB_cmp();
740         void Lazy_RCU_SHB_less();
741         void Lazy_RCU_SHB_cmpmix();
742
743         void Lazy_RCU_SHT_cmp();
744         void Lazy_RCU_SHT_less();
745         void Lazy_RCU_SHT_cmpmix();
746
747         void Lazy_nogc_cmp();
748         void Lazy_nogc_less();
749         void Lazy_nogc_cmpmix();
750
751         void Split_HP_cmp();
752         void Split_HP_less();
753         void Split_HP_cmpmix();
754         void Split_HP_cmpmix_stat();
755
756         void Split_DHP_cmp();
757         void Split_DHP_less();
758         void Split_DHP_cmpmix();
759         void Split_DHP_cmpmix_stat();
760
761         void Split_RCU_GPI_cmp();
762         void Split_RCU_GPI_less();
763         void Split_RCU_GPI_cmpmix();
764         void Split_RCU_GPI_cmpmix_stat();
765
766         void Split_RCU_GPB_cmp();
767         void Split_RCU_GPB_less();
768         void Split_RCU_GPB_cmpmix();
769         void Split_RCU_GPB_cmpmix_stat();
770
771         void Split_RCU_GPT_cmp();
772         void Split_RCU_GPT_less();
773         void Split_RCU_GPT_cmpmix();
774         void Split_RCU_GPT_cmpmix_stat();
775
776         void Split_RCU_SHB_cmp();
777         void Split_RCU_SHB_less();
778         void Split_RCU_SHB_cmpmix();
779         void Split_RCU_SHB_cmpmix_stat();
780
781         void Split_RCU_SHT_cmp();
782         void Split_RCU_SHT_less();
783         void Split_RCU_SHT_cmpmix();
784         void Split_RCU_SHT_cmpmix_stat();
785
786         void Split_nogc_cmp();
787         void Split_nogc_less();
788         void Split_nogc_cmpmix();
789         void Split_nogc_cmpmix_stat();
790
791         void Split_Lazy_HP_cmp();
792         void Split_Lazy_HP_less();
793         void Split_Lazy_HP_cmpmix();
794         void Split_Lazy_HP_cmpmix_stat();
795
796         void Split_Lazy_DHP_cmp();
797         void Split_Lazy_DHP_less();
798         void Split_Lazy_DHP_cmpmix();
799         void Split_Lazy_DHP_cmpmix_stat();
800
801         void Split_Lazy_RCU_GPI_cmp();
802         void Split_Lazy_RCU_GPI_less();
803         void Split_Lazy_RCU_GPI_cmpmix();
804         void Split_Lazy_RCU_GPI_cmpmix_stat();
805
806         void Split_Lazy_RCU_GPB_cmp();
807         void Split_Lazy_RCU_GPB_less();
808         void Split_Lazy_RCU_GPB_cmpmix();
809         void Split_Lazy_RCU_GPB_cmpmix_stat();
810
811         void Split_Lazy_RCU_GPT_cmp();
812         void Split_Lazy_RCU_GPT_less();
813         void Split_Lazy_RCU_GPT_cmpmix();
814         void Split_Lazy_RCU_GPT_cmpmix_stat();
815
816         void Split_Lazy_RCU_SHB_cmp();
817         void Split_Lazy_RCU_SHB_less();
818         void Split_Lazy_RCU_SHB_cmpmix();
819         void Split_Lazy_RCU_SHB_cmpmix_stat();
820
821         void Split_Lazy_RCU_SHT_cmp();
822         void Split_Lazy_RCU_SHT_less();
823         void Split_Lazy_RCU_SHT_cmpmix();
824         void Split_Lazy_RCU_SHT_cmpmix_stat();
825
826         void Split_Lazy_nogc_cmp();
827         void Split_Lazy_nogc_less();
828         void Split_Lazy_nogc_cmpmix();
829         void Split_Lazy_nogc_cmpmix_stat();
830
831         CPPUNIT_TEST_SUITE(HashMapHdrTest)
832             CPPUNIT_TEST(Michael_HP_cmp)
833             CPPUNIT_TEST(Michael_HP_less)
834             CPPUNIT_TEST(Michael_HP_cmpmix)
835
836             CPPUNIT_TEST(Michael_DHP_cmp)
837             CPPUNIT_TEST(Michael_DHP_less)
838             CPPUNIT_TEST(Michael_DHP_cmpmix)
839
840             CPPUNIT_TEST(Michael_RCU_GPI_cmp)
841             CPPUNIT_TEST(Michael_RCU_GPI_less)
842             CPPUNIT_TEST(Michael_RCU_GPI_cmpmix)
843
844             CPPUNIT_TEST(Michael_RCU_GPB_cmp)
845             CPPUNIT_TEST(Michael_RCU_GPB_less)
846             CPPUNIT_TEST(Michael_RCU_GPB_cmpmix)
847
848             CPPUNIT_TEST(Michael_RCU_SHT_cmp)
849             CPPUNIT_TEST(Michael_RCU_SHT_less)
850             CPPUNIT_TEST(Michael_RCU_SHT_cmpmix)
851
852             CPPUNIT_TEST(Michael_RCU_SHB_cmp)
853             CPPUNIT_TEST(Michael_RCU_SHB_less)
854             CPPUNIT_TEST(Michael_RCU_SHB_cmpmix)
855
856             CPPUNIT_TEST(Michael_RCU_GPT_cmp)
857             CPPUNIT_TEST(Michael_RCU_GPT_less)
858             CPPUNIT_TEST(Michael_RCU_GPT_cmpmix)
859
860             CPPUNIT_TEST(Michael_nogc_cmp)
861             CPPUNIT_TEST(Michael_nogc_less)
862             CPPUNIT_TEST(Michael_nogc_cmpmix)
863
864             CPPUNIT_TEST(Lazy_HP_cmp)
865             CPPUNIT_TEST(Lazy_HP_less)
866             CPPUNIT_TEST(Lazy_HP_cmpmix)
867
868             CPPUNIT_TEST(Lazy_DHP_cmp)
869             CPPUNIT_TEST(Lazy_DHP_less)
870             CPPUNIT_TEST(Lazy_DHP_cmpmix)
871
872             CPPUNIT_TEST(Lazy_RCU_GPI_cmp)
873             CPPUNIT_TEST(Lazy_RCU_GPI_less)
874             CPPUNIT_TEST(Lazy_RCU_GPI_cmpmix)
875
876             CPPUNIT_TEST(Lazy_RCU_GPB_cmp)
877             CPPUNIT_TEST(Lazy_RCU_GPB_less)
878             CPPUNIT_TEST(Lazy_RCU_GPB_cmpmix)
879
880             CPPUNIT_TEST(Lazy_RCU_GPT_cmp)
881             CPPUNIT_TEST(Lazy_RCU_GPT_less)
882             CPPUNIT_TEST(Lazy_RCU_GPT_cmpmix)
883
884             CPPUNIT_TEST(Lazy_RCU_SHB_cmp)
885             CPPUNIT_TEST(Lazy_RCU_SHB_less)
886             CPPUNIT_TEST(Lazy_RCU_SHB_cmpmix)
887
888             CPPUNIT_TEST(Lazy_RCU_SHT_cmp)
889             CPPUNIT_TEST(Lazy_RCU_SHT_less)
890             CPPUNIT_TEST(Lazy_RCU_SHT_cmpmix)
891
892             CPPUNIT_TEST(Lazy_nogc_cmp)
893             CPPUNIT_TEST(Lazy_nogc_less)
894             CPPUNIT_TEST(Lazy_nogc_cmpmix)
895
896             CPPUNIT_TEST(Split_HP_cmp)
897             CPPUNIT_TEST(Split_HP_less)
898             CPPUNIT_TEST(Split_HP_cmpmix)
899             CPPUNIT_TEST( Split_HP_cmpmix_stat )
900
901             CPPUNIT_TEST(Split_DHP_cmp)
902             CPPUNIT_TEST(Split_DHP_less)
903             CPPUNIT_TEST(Split_DHP_cmpmix)
904             CPPUNIT_TEST( Split_DHP_cmpmix_stat )
905
906             CPPUNIT_TEST(Split_RCU_GPI_cmp)
907             CPPUNIT_TEST(Split_RCU_GPI_less)
908             CPPUNIT_TEST(Split_RCU_GPI_cmpmix)
909             CPPUNIT_TEST( Split_RCU_GPI_cmpmix_stat )
910
911             CPPUNIT_TEST(Split_RCU_GPB_cmp)
912             CPPUNIT_TEST(Split_RCU_GPB_less)
913             CPPUNIT_TEST(Split_RCU_GPB_cmpmix)
914             CPPUNIT_TEST( Split_RCU_GPB_cmpmix_stat )
915
916             CPPUNIT_TEST(Split_RCU_GPT_cmp)
917             CPPUNIT_TEST(Split_RCU_GPT_less)
918             CPPUNIT_TEST(Split_RCU_GPT_cmpmix)
919             CPPUNIT_TEST( Split_RCU_GPT_cmpmix_stat )
920
921             CPPUNIT_TEST(Split_RCU_SHB_cmp)
922             CPPUNIT_TEST(Split_RCU_SHB_less)
923             CPPUNIT_TEST(Split_RCU_SHB_cmpmix)
924             CPPUNIT_TEST( Split_RCU_SHB_cmpmix_stat )
925
926             CPPUNIT_TEST(Split_RCU_SHT_cmp)
927             CPPUNIT_TEST(Split_RCU_SHT_less)
928             CPPUNIT_TEST(Split_RCU_SHT_cmpmix)
929             CPPUNIT_TEST( Split_RCU_SHT_cmpmix_stat )
930
931             CPPUNIT_TEST(Split_nogc_cmp)
932             CPPUNIT_TEST(Split_nogc_less)
933             CPPUNIT_TEST(Split_nogc_cmpmix)
934             CPPUNIT_TEST( Split_nogc_cmpmix_stat )
935
936             CPPUNIT_TEST(Split_Lazy_HP_cmp)
937             CPPUNIT_TEST(Split_Lazy_HP_less)
938             CPPUNIT_TEST(Split_Lazy_HP_cmpmix)
939             CPPUNIT_TEST( Split_Lazy_HP_cmpmix_stat )
940
941             CPPUNIT_TEST(Split_Lazy_DHP_cmp)
942             CPPUNIT_TEST(Split_Lazy_DHP_less)
943             CPPUNIT_TEST(Split_Lazy_DHP_cmpmix)
944             CPPUNIT_TEST( Split_Lazy_DHP_cmpmix_stat )
945
946             CPPUNIT_TEST(Split_Lazy_RCU_GPI_cmp)
947             CPPUNIT_TEST(Split_Lazy_RCU_GPI_less)
948             CPPUNIT_TEST(Split_Lazy_RCU_GPI_cmpmix)
949             CPPUNIT_TEST( Split_Lazy_RCU_GPI_cmpmix_stat )
950
951             CPPUNIT_TEST(Split_Lazy_RCU_GPB_cmp)
952             CPPUNIT_TEST(Split_Lazy_RCU_GPB_less)
953             CPPUNIT_TEST(Split_Lazy_RCU_GPB_cmpmix)
954             CPPUNIT_TEST( Split_Lazy_RCU_GPB_cmpmix_stat )
955
956             CPPUNIT_TEST(Split_Lazy_RCU_GPT_cmp)
957             CPPUNIT_TEST(Split_Lazy_RCU_GPT_less)
958             CPPUNIT_TEST(Split_Lazy_RCU_GPT_cmpmix)
959             CPPUNIT_TEST( Split_Lazy_RCU_GPT_cmpmix_stat )
960
961             CPPUNIT_TEST(Split_Lazy_RCU_SHB_cmp)
962             CPPUNIT_TEST(Split_Lazy_RCU_SHB_less)
963             CPPUNIT_TEST(Split_Lazy_RCU_SHB_cmpmix)
964             CPPUNIT_TEST( Split_Lazy_RCU_SHB_cmpmix_stat )
965
966             CPPUNIT_TEST(Split_Lazy_RCU_SHT_cmp)
967             CPPUNIT_TEST(Split_Lazy_RCU_SHT_less)
968             CPPUNIT_TEST(Split_Lazy_RCU_SHT_cmpmix)
969             CPPUNIT_TEST( Split_Lazy_RCU_SHT_cmpmix_stat )
970
971             CPPUNIT_TEST(Split_Lazy_nogc_cmp)
972             CPPUNIT_TEST(Split_Lazy_nogc_less)
973             CPPUNIT_TEST(Split_Lazy_nogc_cmpmix)
974             CPPUNIT_TEST( Split_Lazy_nogc_cmpmix_stat )
975             CPPUNIT_TEST_SUITE_END()
976
977     };
978 }   // namespace map
979
980 #endif // #ifndef __CDSTEST_HDR_MAP_H