3 #ifndef __CDSTEST_HDR_STRIPED_MAP_H
4 #define __CDSTEST_HDR_STRIPED_MAP_H
5 #include "size_check.h"
7 #include "cppunit/cppunit_proxy.h"
8 #include <cds/os/timer.h>
9 #include <cds/opt/hash.h>
11 #include <algorithm> // random_shuffle
13 namespace cds { namespace container {}}
16 using misc::check_size;
18 namespace cc = cds::container;
19 namespace co = cds::opt;
21 class StripedMapHdrTest: public CppUnitMini::TestCase
37 value_type( value_type&& v )
41 value_type( value_type const& v )
45 value_type& operator=( value_type const& v )
52 typedef std::pair<key_type const, value_type> pair_type;
56 bool operator ()(int v1, int v2 ) const
63 int operator ()(int v1, int v2 ) const
67 return v1 > v2 ? 1 : 0;
72 bool operator ()(int v1, int v2 ) const
79 size_t operator()( int i ) const
81 return co::v::hash<int>()( i );
85 struct simple_item_counter {
107 operator size_t() const
113 template <typename Map>
114 struct insert_functor
116 typedef typename Map::value_type pair_type;
119 void operator()( pair_type& item )
121 item.second.m_val = item.first * 3;
125 void operator()( bool bNew, pair_type& item )
128 item.second.m_val = item.first * 2;
130 item.second.m_val = item.first * 5;
137 check_value( int nExpected )
138 : m_nExpected( nExpected )
141 template <typename T>
142 void operator ()( T& pair )
144 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
146 template <typename T, typename Q>
147 void operator ()( T& pair, Q )
149 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
153 struct extract_functor
156 void operator()( pair_type const& val )
158 *m_pVal = val.second.m_val;
163 void test_int_with( Map& m )
165 std::pair<bool, bool> ensureResult;
168 CPPUNIT_ASSERT( m.empty() );
169 CPPUNIT_ASSERT( check_size( m, 0 ));
170 CPPUNIT_ASSERT( !m.find(25) );
171 CPPUNIT_ASSERT( m.insert( 25 ) ) ; // value = 0
172 CPPUNIT_ASSERT( m.find(25) );
173 CPPUNIT_ASSERT( !m.empty() );
174 CPPUNIT_ASSERT( check_size( m, 1 ));
175 CPPUNIT_ASSERT( m.find(25) );
177 CPPUNIT_ASSERT( !m.insert( 25 ) );
178 CPPUNIT_ASSERT( !m.empty() );
179 CPPUNIT_ASSERT( check_size( m, 1 ));
181 CPPUNIT_ASSERT( !m.find(10) );
182 CPPUNIT_ASSERT( m.insert( 10, 10 ) );
183 CPPUNIT_ASSERT( !m.empty() );
184 CPPUNIT_ASSERT( check_size( m, 2 ));
185 CPPUNIT_ASSERT( m.find(10) );
187 CPPUNIT_ASSERT( !m.insert( 10, 20 ) );
188 CPPUNIT_ASSERT( !m.empty() );
189 CPPUNIT_ASSERT( check_size( m, 2 ));
191 CPPUNIT_ASSERT( !m.find(30) );
192 CPPUNIT_ASSERT( m.insert_key( 30, insert_functor<Map>() ) ) ; // value = 90
193 CPPUNIT_ASSERT( !m.empty() );
194 CPPUNIT_ASSERT( check_size( m, 3 ));
195 CPPUNIT_ASSERT( m.find(30) );
197 CPPUNIT_ASSERT( !m.insert_key( 10, insert_functor<Map>() ) );
198 CPPUNIT_ASSERT( !m.insert_key( 25, insert_functor<Map>() ) );
199 CPPUNIT_ASSERT( !m.insert_key( 30, insert_functor<Map>() ) );
202 CPPUNIT_ASSERT( !m.find(27) );
203 ensureResult = m.ensure( 27, insert_functor<Map>() ) ; // value = 54
204 CPPUNIT_ASSERT( ensureResult.first );
205 CPPUNIT_ASSERT( ensureResult.second );
206 CPPUNIT_ASSERT( check_size( m, 4 ));
207 CPPUNIT_ASSERT( m.find(27) );
211 CPPUNIT_ASSERT( m.find( 10, cds::ref(chk) ));
213 CPPUNIT_ASSERT( m.find( 25, boost::ref(chk) ));
214 chk.m_nExpected = 90;
215 CPPUNIT_ASSERT( m.find( 30, boost::ref(chk) ));
216 chk.m_nExpected = 54;
217 CPPUNIT_ASSERT( m.find( 27, boost::ref(chk) ));
219 ensureResult = m.ensure( 10, insert_functor<Map>() ) ; // value = 50
220 CPPUNIT_ASSERT( ensureResult.first );
221 CPPUNIT_ASSERT( !ensureResult.second );
222 chk.m_nExpected = 50;
223 CPPUNIT_ASSERT( m.find( 10, boost::ref(chk) ));
226 CPPUNIT_ASSERT( !m.find(100) );
227 CPPUNIT_ASSERT( !m.erase( 100 )) ; // not found
229 CPPUNIT_ASSERT( m.find(25) );
230 CPPUNIT_ASSERT( check_size( m, 4 ));
231 CPPUNIT_ASSERT( m.erase( 25 ));
232 CPPUNIT_ASSERT( !m.empty() );
233 CPPUNIT_ASSERT( check_size( m, 3 ));
234 CPPUNIT_ASSERT( !m.find(25) );
235 CPPUNIT_ASSERT( !m.erase( 25 ));
237 CPPUNIT_ASSERT( !m.find(258) );
238 CPPUNIT_ASSERT( m.insert(258))
239 CPPUNIT_ASSERT( check_size( m, 4 ));
240 CPPUNIT_ASSERT( m.find(258) );
241 CPPUNIT_ASSERT( m.erase( 258 ));
242 CPPUNIT_ASSERT( !m.empty() );
243 CPPUNIT_ASSERT( check_size( m, 3 ));
244 CPPUNIT_ASSERT( !m.find(258) );
245 CPPUNIT_ASSERT( !m.erase( 258 ));
251 CPPUNIT_ASSERT( !m.find(29) );
252 CPPUNIT_ASSERT( m.insert(29, 290));
253 CPPUNIT_ASSERT( check_size( m, 4 ));
254 CPPUNIT_ASSERT( m.erase( 29, boost::ref(ext)));
255 CPPUNIT_ASSERT( !m.empty() );
256 CPPUNIT_ASSERT( check_size( m, 3 ));
257 CPPUNIT_ASSERT( nVal == 290 );
259 CPPUNIT_ASSERT( !m.erase( 29, boost::ref(ext)));
260 CPPUNIT_ASSERT( nVal == -1 );
262 CPPUNIT_ASSERT( m.erase( 30, boost::ref(ext)));
263 CPPUNIT_ASSERT( !m.empty() );
264 CPPUNIT_ASSERT( check_size( m, 2 ));
265 CPPUNIT_ASSERT( nVal == 90 );
267 CPPUNIT_ASSERT( !m.erase( 30, boost::ref(ext)));
268 CPPUNIT_ASSERT( nVal == -1 );
271 CPPUNIT_ASSERT( m.empty() );
272 CPPUNIT_ASSERT( check_size( m, 0 ));
274 # ifdef CDS_EMPLACE_SUPPORT
276 CPPUNIT_ASSERT( m.emplace(126) ) ; // key = 126, val = 0
277 CPPUNIT_ASSERT( m.emplace(137, 731)) ; // key = 137, val = 731
278 CPPUNIT_ASSERT( m.emplace( 149, value_type(941) )) ; // key = 149, val = 941
280 CPPUNIT_ASSERT( !m.empty() );
281 CPPUNIT_ASSERT( check_size( m, 3 ));
284 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
285 chk.m_nExpected = 731;
286 CPPUNIT_ASSERT( m.find( 137, cds::ref(chk) ));
287 chk.m_nExpected = 941;
288 CPPUNIT_ASSERT( m.find( 149, cds::ref(chk) ));
290 CPPUNIT_ASSERT( !m.emplace(126, 621)) ; // already in map
292 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
293 CPPUNIT_ASSERT( !m.empty() );
294 CPPUNIT_ASSERT( check_size( m, 3 ));
297 CPPUNIT_ASSERT( m.empty() );
298 CPPUNIT_ASSERT( check_size( m, 0 ));
304 void test_iter( Map& s)
306 typedef typename Map::iterator iterator;
307 typedef typename Map::const_iterator const_iterator;
309 const int nMaxCount = 500;
310 for ( int i = 0; i < nMaxCount; ++i ) {
311 CPPUNIT_ASSERT( s.insert( i, i * 2 ));
315 for ( iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) {
316 CPPUNIT_ASSERT( it->first * 2 == it->second.m_val );
317 CPPUNIT_ASSERT( (*it).first * 2 == (*it).second.m_val );
318 it->second.m_val = it->first;
321 CPPUNIT_ASSERT( nCount == nMaxCount );
323 Map const& refSet = s;
325 for ( const_iterator it = refSet.begin(), itEnd = refSet.end(); it != itEnd; ++it ) {
326 CPPUNIT_ASSERT( it->first == it->second.m_val );
327 CPPUNIT_ASSERT( (*it).first == (*it).second.m_val );
330 CPPUNIT_ASSERT( nCount == nMaxCount );
337 CPPUNIT_ASSERT( m.bucket_count() == 32 );
338 CPPUNIT_ASSERT( m.lock_count() == 32 );
340 test_striped_with(m);
344 void test_striped_with(Map& m)
346 cds::OS::Timer timer;
350 // Iterators is not yet supported
352 //CPPUNIT_ASSERT( m.empty() );
353 //CPPUNIT_ASSERT( check_size( m, 0 ));
357 CPPUNIT_ASSERT( m.empty() );
358 CPPUNIT_ASSERT( check_size( m, 0 ));
361 for ( int i = 0; i < 40000; i++ ) {
365 CPPUNIT_MSG( " Duration=" << timer.duration() );
368 //*******************************************
369 // If erase_with && find_with are supported
371 void test_int_with2( Map& m )
373 std::pair<bool, bool> ensureResult;
376 CPPUNIT_ASSERT( m.empty() );
377 CPPUNIT_ASSERT( check_size( m, 0 ));
378 CPPUNIT_ASSERT( !m.find(25) );
379 CPPUNIT_ASSERT( m.insert( 25 ) ) ; // value = 0
380 CPPUNIT_ASSERT( m.find(25) );
381 CPPUNIT_ASSERT( !m.empty() );
382 CPPUNIT_ASSERT( check_size( m, 1 ));
383 CPPUNIT_ASSERT( m.find(25) );
385 CPPUNIT_ASSERT( !m.insert( 25 ) );
386 CPPUNIT_ASSERT( !m.empty() );
387 CPPUNIT_ASSERT( check_size( m, 1 ));
389 CPPUNIT_ASSERT( !m.find_with(10, less()) );
390 CPPUNIT_ASSERT( m.insert( 10, 10 ) );
391 CPPUNIT_ASSERT( !m.empty() );
392 CPPUNIT_ASSERT( check_size( m, 2 ));
393 CPPUNIT_ASSERT( m.find_with(10, less()) );
395 CPPUNIT_ASSERT( !m.insert( 10, 20 ) );
396 CPPUNIT_ASSERT( !m.empty() );
397 CPPUNIT_ASSERT( check_size( m, 2 ));
399 CPPUNIT_ASSERT( !m.find(30) );
400 CPPUNIT_ASSERT( m.insert_key( 30, insert_functor<Map>() ) ) ; // value = 90
401 CPPUNIT_ASSERT( !m.empty() );
402 CPPUNIT_ASSERT( check_size( m, 3 ));
403 CPPUNIT_ASSERT( m.find(30) );
405 CPPUNIT_ASSERT( !m.insert_key( 10, insert_functor<Map>() ) );
406 CPPUNIT_ASSERT( !m.insert_key( 25, insert_functor<Map>() ) );
407 CPPUNIT_ASSERT( !m.insert_key( 30, insert_functor<Map>() ) );
410 CPPUNIT_ASSERT( !m.find(27) );
411 ensureResult = m.ensure( 27, insert_functor<Map>() ) ; // value = 54
412 CPPUNIT_ASSERT( ensureResult.first );
413 CPPUNIT_ASSERT( ensureResult.second );
414 CPPUNIT_ASSERT( m.find(27) );
418 CPPUNIT_ASSERT( m.find( 10, cds::ref(chk) ));
420 CPPUNIT_ASSERT( m.find_with( 25, less(), boost::ref(chk) ));
421 chk.m_nExpected = 90;
422 CPPUNIT_ASSERT( m.find( 30, boost::ref(chk) ));
423 chk.m_nExpected = 54;
424 CPPUNIT_ASSERT( m.find( 27, boost::ref(chk) ));
426 ensureResult = m.ensure( 10, insert_functor<Map>() ) ; // value = 50
427 CPPUNIT_ASSERT( ensureResult.first );
428 CPPUNIT_ASSERT( !ensureResult.second );
429 chk.m_nExpected = 50;
430 CPPUNIT_ASSERT( m.find( 10, boost::ref(chk) ));
433 CPPUNIT_ASSERT( !m.find(100) );
434 CPPUNIT_ASSERT( !m.erase( 100 )) ; // not found
436 CPPUNIT_ASSERT( m.find(25) );
437 CPPUNIT_ASSERT( check_size( m, 4 ));
438 CPPUNIT_ASSERT( m.erase( 25 ));
439 CPPUNIT_ASSERT( !m.empty() );
440 CPPUNIT_ASSERT( check_size( m, 3 ));
441 CPPUNIT_ASSERT( !m.find(25) );
442 CPPUNIT_ASSERT( !m.erase( 25 ));
444 CPPUNIT_ASSERT( !m.find(258) );
445 CPPUNIT_ASSERT( m.insert(258))
446 CPPUNIT_ASSERT( check_size( m, 4 ));
447 CPPUNIT_ASSERT( m.find_with(258, less()) );
448 CPPUNIT_ASSERT( m.erase_with( 258, less() ));
449 CPPUNIT_ASSERT( !m.empty() );
450 CPPUNIT_ASSERT( check_size( m, 3 ));
451 CPPUNIT_ASSERT( !m.find(258) );
452 CPPUNIT_ASSERT( !m.erase_with( 258, less() ));
458 CPPUNIT_ASSERT( !m.find(29) );
459 CPPUNIT_ASSERT( m.insert(29, 290))
460 CPPUNIT_ASSERT( m.erase_with( 29, less(), boost::ref(ext)));
461 CPPUNIT_ASSERT( !m.empty() );
462 CPPUNIT_ASSERT( check_size( m, 3 ));
463 CPPUNIT_ASSERT( nVal == 290 );
465 CPPUNIT_ASSERT( !m.erase_with( 29, less(), boost::ref(ext)));
466 CPPUNIT_ASSERT( nVal == -1 );
468 CPPUNIT_ASSERT( m.erase( 30, boost::ref(ext)));
469 CPPUNIT_ASSERT( !m.empty() );
470 CPPUNIT_ASSERT( check_size( m, 2 ));
471 CPPUNIT_ASSERT( nVal == 90 );
473 CPPUNIT_ASSERT( !m.erase( 30, boost::ref(ext)));
474 CPPUNIT_ASSERT( nVal == -1 );
477 CPPUNIT_ASSERT( m.empty() );
478 CPPUNIT_ASSERT( check_size( m, 0 ));
480 # ifdef CDS_EMPLACE_SUPPORT
482 CPPUNIT_ASSERT( m.emplace(126) ) ; // key = 126, val = 0
483 CPPUNIT_ASSERT( m.emplace(137, 731)) ; // key = 137, val = 731
484 CPPUNIT_ASSERT( m.emplace( 149, value_type(941) )) ; // key = 149, val = 941
486 CPPUNIT_ASSERT( !m.empty() );
487 CPPUNIT_ASSERT( check_size( m, 3 ));
490 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
491 chk.m_nExpected = 731;
492 CPPUNIT_ASSERT( m.find_with( 137, less(), cds::ref(chk) ));
493 chk.m_nExpected = 941;
494 CPPUNIT_ASSERT( m.find( 149, cds::ref(chk) ));
496 CPPUNIT_ASSERT( !m.emplace(126, 621)) ; // already in map
498 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
499 CPPUNIT_ASSERT( !m.empty() );
500 CPPUNIT_ASSERT( check_size( m, 3 ));
503 CPPUNIT_ASSERT( m.empty() );
504 CPPUNIT_ASSERT( check_size( m, 0 ));
510 void test_striped_with2(Map& m)
512 cds::OS::Timer timer;
516 // Iterators is not yet supported
518 //CPPUNIT_ASSERT( m.empty() );
519 //CPPUNIT_ASSERT( check_size( m, 0 ));
523 CPPUNIT_ASSERT( m.empty() );
524 CPPUNIT_ASSERT( check_size( m, 0 ));
527 for ( int i = 0; i < 40000; i++ ) {
531 CPPUNIT_MSG( " Duration=" << timer.duration() );
538 CPPUNIT_ASSERT( m.bucket_count() == 32 );
539 CPPUNIT_ASSERT( m.lock_count() == 32 );
541 test_striped_with2(m);
544 void Striped_hashmap();
547 void Striped_slist();
548 void Striped_boost_list();
549 void Striped_boost_flat_map();
550 void Striped_boost_map();
551 void Striped_boost_unordered_map();
553 void Refinable_hashmap();
554 void Refinable_list();
555 void Refinable_map();
556 void Refinable_slist();
557 void Refinable_boost_list();
558 void Refinable_boost_flat_map();
559 void Refinable_boost_map();
560 void Refinable_boost_unordered_map();
562 CPPUNIT_TEST_SUITE(StripedMapHdrTest)
563 CPPUNIT_TEST(Striped_hashmap)
564 CPPUNIT_TEST(Striped_list)
565 CPPUNIT_TEST(Striped_map)
566 CPPUNIT_TEST(Striped_slist)
567 CPPUNIT_TEST(Striped_boost_list)
568 CPPUNIT_TEST(Striped_boost_flat_map)
569 CPPUNIT_TEST(Striped_boost_map)
570 CPPUNIT_TEST(Striped_boost_unordered_map)
572 CPPUNIT_TEST(Refinable_hashmap)
573 CPPUNIT_TEST(Refinable_list)
574 CPPUNIT_TEST(Refinable_map)
575 CPPUNIT_TEST(Refinable_slist)
576 CPPUNIT_TEST(Refinable_boost_list)
577 CPPUNIT_TEST(Refinable_boost_flat_map)
578 CPPUNIT_TEST(Refinable_boost_map)
579 CPPUNIT_TEST(Refinable_boost_unordered_map)
580 CPPUNIT_TEST_SUITE_END()
585 #endif // #ifndef __CDSTEST_HDR_STRIPED_MAP_H