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 #ifdef CDS_MOVE_SEMANTICS_SUPPORT
38 value_type( value_type&& v )
42 value_type( value_type const& v )
46 value_type& operator=( value_type const& v )
54 typedef std::pair<key_type const, value_type> pair_type;
58 bool operator ()(int v1, int v2 ) const
65 int operator ()(int v1, int v2 ) const
69 return v1 > v2 ? 1 : 0;
74 bool operator ()(int v1, int v2 ) const
81 size_t operator()( int i ) const
83 return co::v::hash<int>()( i );
87 struct simple_item_counter {
109 operator size_t() const
115 template <typename Map>
116 struct insert_functor
118 typedef typename Map::value_type pair_type;
121 void operator()( pair_type& item )
123 item.second.m_val = item.first * 3;
127 void operator()( bool bNew, pair_type& item )
130 item.second.m_val = item.first * 2;
132 item.second.m_val = item.first * 5;
139 check_value( int nExpected )
140 : m_nExpected( nExpected )
143 template <typename T>
144 void operator ()( T& pair )
146 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
148 template <typename T, typename Q>
149 void operator ()( T& pair, Q )
151 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
155 struct extract_functor
158 void operator()( pair_type const& val )
160 *m_pVal = val.second.m_val;
165 void test_int_with( Map& m )
167 std::pair<bool, bool> ensureResult;
170 CPPUNIT_ASSERT( m.empty() );
171 CPPUNIT_ASSERT( check_size( m, 0 ));
172 CPPUNIT_ASSERT( !m.find(25) );
173 CPPUNIT_ASSERT( m.insert( 25 ) ) ; // value = 0
174 CPPUNIT_ASSERT( m.find(25) );
175 CPPUNIT_ASSERT( !m.empty() );
176 CPPUNIT_ASSERT( check_size( m, 1 ));
177 CPPUNIT_ASSERT( m.find(25) );
179 CPPUNIT_ASSERT( !m.insert( 25 ) );
180 CPPUNIT_ASSERT( !m.empty() );
181 CPPUNIT_ASSERT( check_size( m, 1 ));
183 CPPUNIT_ASSERT( !m.find(10) );
184 CPPUNIT_ASSERT( m.insert( 10, 10 ) );
185 CPPUNIT_ASSERT( !m.empty() );
186 CPPUNIT_ASSERT( check_size( m, 2 ));
187 CPPUNIT_ASSERT( m.find(10) );
189 CPPUNIT_ASSERT( !m.insert( 10, 20 ) );
190 CPPUNIT_ASSERT( !m.empty() );
191 CPPUNIT_ASSERT( check_size( m, 2 ));
193 CPPUNIT_ASSERT( !m.find(30) );
194 CPPUNIT_ASSERT( m.insert_key( 30, insert_functor<Map>() ) ) ; // value = 90
195 CPPUNIT_ASSERT( !m.empty() );
196 CPPUNIT_ASSERT( check_size( m, 3 ));
197 CPPUNIT_ASSERT( m.find(30) );
199 CPPUNIT_ASSERT( !m.insert_key( 10, insert_functor<Map>() ) );
200 CPPUNIT_ASSERT( !m.insert_key( 25, insert_functor<Map>() ) );
201 CPPUNIT_ASSERT( !m.insert_key( 30, insert_functor<Map>() ) );
204 CPPUNIT_ASSERT( !m.find(27) );
205 ensureResult = m.ensure( 27, insert_functor<Map>() ) ; // value = 54
206 CPPUNIT_ASSERT( ensureResult.first );
207 CPPUNIT_ASSERT( ensureResult.second );
208 CPPUNIT_ASSERT( check_size( m, 4 ));
209 CPPUNIT_ASSERT( m.find(27) );
213 CPPUNIT_ASSERT( m.find( 10, cds::ref(chk) ));
215 CPPUNIT_ASSERT( m.find( 25, boost::ref(chk) ));
216 chk.m_nExpected = 90;
217 CPPUNIT_ASSERT( m.find( 30, boost::ref(chk) ));
218 chk.m_nExpected = 54;
219 CPPUNIT_ASSERT( m.find( 27, boost::ref(chk) ));
221 ensureResult = m.ensure( 10, insert_functor<Map>() ) ; // value = 50
222 CPPUNIT_ASSERT( ensureResult.first );
223 CPPUNIT_ASSERT( !ensureResult.second );
224 chk.m_nExpected = 50;
225 CPPUNIT_ASSERT( m.find( 10, boost::ref(chk) ));
228 CPPUNIT_ASSERT( !m.find(100) );
229 CPPUNIT_ASSERT( !m.erase( 100 )) ; // not found
231 CPPUNIT_ASSERT( m.find(25) );
232 CPPUNIT_ASSERT( check_size( m, 4 ));
233 CPPUNIT_ASSERT( m.erase( 25 ));
234 CPPUNIT_ASSERT( !m.empty() );
235 CPPUNIT_ASSERT( check_size( m, 3 ));
236 CPPUNIT_ASSERT( !m.find(25) );
237 CPPUNIT_ASSERT( !m.erase( 25 ));
239 CPPUNIT_ASSERT( !m.find(258) );
240 CPPUNIT_ASSERT( m.insert(258))
241 CPPUNIT_ASSERT( check_size( m, 4 ));
242 CPPUNIT_ASSERT( m.find(258) );
243 CPPUNIT_ASSERT( m.erase( 258 ));
244 CPPUNIT_ASSERT( !m.empty() );
245 CPPUNIT_ASSERT( check_size( m, 3 ));
246 CPPUNIT_ASSERT( !m.find(258) );
247 CPPUNIT_ASSERT( !m.erase( 258 ));
253 CPPUNIT_ASSERT( !m.find(29) );
254 CPPUNIT_ASSERT( m.insert(29, 290));
255 CPPUNIT_ASSERT( check_size( m, 4 ));
256 CPPUNIT_ASSERT( m.erase( 29, boost::ref(ext)));
257 CPPUNIT_ASSERT( !m.empty() );
258 CPPUNIT_ASSERT( check_size( m, 3 ));
259 CPPUNIT_ASSERT( nVal == 290 );
261 CPPUNIT_ASSERT( !m.erase( 29, boost::ref(ext)));
262 CPPUNIT_ASSERT( nVal == -1 );
264 CPPUNIT_ASSERT( m.erase( 30, boost::ref(ext)));
265 CPPUNIT_ASSERT( !m.empty() );
266 CPPUNIT_ASSERT( check_size( m, 2 ));
267 CPPUNIT_ASSERT( nVal == 90 );
269 CPPUNIT_ASSERT( !m.erase( 30, boost::ref(ext)));
270 CPPUNIT_ASSERT( nVal == -1 );
273 CPPUNIT_ASSERT( m.empty() );
274 CPPUNIT_ASSERT( check_size( m, 0 ));
276 # ifdef CDS_EMPLACE_SUPPORT
278 CPPUNIT_ASSERT( m.emplace(126) ) ; // key = 126, val = 0
279 CPPUNIT_ASSERT( m.emplace(137, 731)) ; // key = 137, val = 731
280 CPPUNIT_ASSERT( m.emplace( 149, value_type(941) )) ; // key = 149, val = 941
282 CPPUNIT_ASSERT( !m.empty() );
283 CPPUNIT_ASSERT( check_size( m, 3 ));
286 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
287 chk.m_nExpected = 731;
288 CPPUNIT_ASSERT( m.find( 137, cds::ref(chk) ));
289 chk.m_nExpected = 941;
290 CPPUNIT_ASSERT( m.find( 149, cds::ref(chk) ));
292 CPPUNIT_ASSERT( !m.emplace(126, 621)) ; // already in map
294 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
295 CPPUNIT_ASSERT( !m.empty() );
296 CPPUNIT_ASSERT( check_size( m, 3 ));
299 CPPUNIT_ASSERT( m.empty() );
300 CPPUNIT_ASSERT( check_size( m, 0 ));
306 void test_iter( Map& s)
308 typedef typename Map::iterator iterator;
309 typedef typename Map::const_iterator const_iterator;
311 const int nMaxCount = 500;
312 for ( int i = 0; i < nMaxCount; ++i ) {
313 CPPUNIT_ASSERT( s.insert( i, i * 2 ));
317 for ( iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) {
318 CPPUNIT_ASSERT( it->first * 2 == it->second.m_val );
319 CPPUNIT_ASSERT( (*it).first * 2 == (*it).second.m_val );
320 it->second.m_val = it->first;
323 CPPUNIT_ASSERT( nCount == nMaxCount );
325 Map const& refSet = s;
327 for ( const_iterator it = refSet.begin(), itEnd = refSet.end(); it != itEnd; ++it ) {
328 CPPUNIT_ASSERT( it->first == it->second.m_val );
329 CPPUNIT_ASSERT( (*it).first == (*it).second.m_val );
332 CPPUNIT_ASSERT( nCount == nMaxCount );
339 CPPUNIT_ASSERT( m.bucket_count() == 32 );
340 CPPUNIT_ASSERT( m.lock_count() == 32 );
342 test_striped_with(m);
346 void test_striped_with(Map& m)
348 cds::OS::Timer timer;
352 // Iterators is not yet supported
354 //CPPUNIT_ASSERT( m.empty() );
355 //CPPUNIT_ASSERT( check_size( m, 0 ));
359 CPPUNIT_ASSERT( m.empty() );
360 CPPUNIT_ASSERT( check_size( m, 0 ));
363 for ( int i = 0; i < 40000; i++ ) {
367 CPPUNIT_MSG( " Duration=" << timer.duration() );
370 //*******************************************
371 // If erase_with && find_with are supported
373 void test_int_with2( Map& m )
375 std::pair<bool, bool> ensureResult;
378 CPPUNIT_ASSERT( m.empty() );
379 CPPUNIT_ASSERT( check_size( m, 0 ));
380 CPPUNIT_ASSERT( !m.find(25) );
381 CPPUNIT_ASSERT( m.insert( 25 ) ) ; // value = 0
382 CPPUNIT_ASSERT( m.find(25) );
383 CPPUNIT_ASSERT( !m.empty() );
384 CPPUNIT_ASSERT( check_size( m, 1 ));
385 CPPUNIT_ASSERT( m.find(25) );
387 CPPUNIT_ASSERT( !m.insert( 25 ) );
388 CPPUNIT_ASSERT( !m.empty() );
389 CPPUNIT_ASSERT( check_size( m, 1 ));
391 CPPUNIT_ASSERT( !m.find_with(10, less()) );
392 CPPUNIT_ASSERT( m.insert( 10, 10 ) );
393 CPPUNIT_ASSERT( !m.empty() );
394 CPPUNIT_ASSERT( check_size( m, 2 ));
395 CPPUNIT_ASSERT( m.find_with(10, less()) );
397 CPPUNIT_ASSERT( !m.insert( 10, 20 ) );
398 CPPUNIT_ASSERT( !m.empty() );
399 CPPUNIT_ASSERT( check_size( m, 2 ));
401 CPPUNIT_ASSERT( !m.find(30) );
402 CPPUNIT_ASSERT( m.insert_key( 30, insert_functor<Map>() ) ) ; // value = 90
403 CPPUNIT_ASSERT( !m.empty() );
404 CPPUNIT_ASSERT( check_size( m, 3 ));
405 CPPUNIT_ASSERT( m.find(30) );
407 CPPUNIT_ASSERT( !m.insert_key( 10, insert_functor<Map>() ) );
408 CPPUNIT_ASSERT( !m.insert_key( 25, insert_functor<Map>() ) );
409 CPPUNIT_ASSERT( !m.insert_key( 30, insert_functor<Map>() ) );
412 CPPUNIT_ASSERT( !m.find(27) );
413 ensureResult = m.ensure( 27, insert_functor<Map>() ) ; // value = 54
414 CPPUNIT_ASSERT( ensureResult.first );
415 CPPUNIT_ASSERT( ensureResult.second );
416 CPPUNIT_ASSERT( m.find(27) );
420 CPPUNIT_ASSERT( m.find( 10, cds::ref(chk) ));
422 CPPUNIT_ASSERT( m.find_with( 25, less(), boost::ref(chk) ));
423 chk.m_nExpected = 90;
424 CPPUNIT_ASSERT( m.find( 30, boost::ref(chk) ));
425 chk.m_nExpected = 54;
426 CPPUNIT_ASSERT( m.find( 27, boost::ref(chk) ));
428 ensureResult = m.ensure( 10, insert_functor<Map>() ) ; // value = 50
429 CPPUNIT_ASSERT( ensureResult.first );
430 CPPUNIT_ASSERT( !ensureResult.second );
431 chk.m_nExpected = 50;
432 CPPUNIT_ASSERT( m.find( 10, boost::ref(chk) ));
435 CPPUNIT_ASSERT( !m.find(100) );
436 CPPUNIT_ASSERT( !m.erase( 100 )) ; // not found
438 CPPUNIT_ASSERT( m.find(25) );
439 CPPUNIT_ASSERT( check_size( m, 4 ));
440 CPPUNIT_ASSERT( m.erase( 25 ));
441 CPPUNIT_ASSERT( !m.empty() );
442 CPPUNIT_ASSERT( check_size( m, 3 ));
443 CPPUNIT_ASSERT( !m.find(25) );
444 CPPUNIT_ASSERT( !m.erase( 25 ));
446 CPPUNIT_ASSERT( !m.find(258) );
447 CPPUNIT_ASSERT( m.insert(258))
448 CPPUNIT_ASSERT( check_size( m, 4 ));
449 CPPUNIT_ASSERT( m.find_with(258, less()) );
450 CPPUNIT_ASSERT( m.erase_with( 258, less() ));
451 CPPUNIT_ASSERT( !m.empty() );
452 CPPUNIT_ASSERT( check_size( m, 3 ));
453 CPPUNIT_ASSERT( !m.find(258) );
454 CPPUNIT_ASSERT( !m.erase_with( 258, less() ));
460 CPPUNIT_ASSERT( !m.find(29) );
461 CPPUNIT_ASSERT( m.insert(29, 290))
462 CPPUNIT_ASSERT( m.erase_with( 29, less(), boost::ref(ext)));
463 CPPUNIT_ASSERT( !m.empty() );
464 CPPUNIT_ASSERT( check_size( m, 3 ));
465 CPPUNIT_ASSERT( nVal == 290 );
467 CPPUNIT_ASSERT( !m.erase_with( 29, less(), boost::ref(ext)));
468 CPPUNIT_ASSERT( nVal == -1 );
470 CPPUNIT_ASSERT( m.erase( 30, boost::ref(ext)));
471 CPPUNIT_ASSERT( !m.empty() );
472 CPPUNIT_ASSERT( check_size( m, 2 ));
473 CPPUNIT_ASSERT( nVal == 90 );
475 CPPUNIT_ASSERT( !m.erase( 30, boost::ref(ext)));
476 CPPUNIT_ASSERT( nVal == -1 );
479 CPPUNIT_ASSERT( m.empty() );
480 CPPUNIT_ASSERT( check_size( m, 0 ));
482 # ifdef CDS_EMPLACE_SUPPORT
484 CPPUNIT_ASSERT( m.emplace(126) ) ; // key = 126, val = 0
485 CPPUNIT_ASSERT( m.emplace(137, 731)) ; // key = 137, val = 731
486 CPPUNIT_ASSERT( m.emplace( 149, value_type(941) )) ; // key = 149, val = 941
488 CPPUNIT_ASSERT( !m.empty() );
489 CPPUNIT_ASSERT( check_size( m, 3 ));
492 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
493 chk.m_nExpected = 731;
494 CPPUNIT_ASSERT( m.find_with( 137, less(), cds::ref(chk) ));
495 chk.m_nExpected = 941;
496 CPPUNIT_ASSERT( m.find( 149, cds::ref(chk) ));
498 CPPUNIT_ASSERT( !m.emplace(126, 621)) ; // already in map
500 CPPUNIT_ASSERT( m.find( 126, cds::ref(chk) ));
501 CPPUNIT_ASSERT( !m.empty() );
502 CPPUNIT_ASSERT( check_size( m, 3 ));
505 CPPUNIT_ASSERT( m.empty() );
506 CPPUNIT_ASSERT( check_size( m, 0 ));
512 void test_striped_with2(Map& m)
514 cds::OS::Timer timer;
518 // Iterators is not yet supported
520 //CPPUNIT_ASSERT( m.empty() );
521 //CPPUNIT_ASSERT( check_size( m, 0 ));
525 CPPUNIT_ASSERT( m.empty() );
526 CPPUNIT_ASSERT( check_size( m, 0 ));
529 for ( int i = 0; i < 40000; i++ ) {
533 CPPUNIT_MSG( " Duration=" << timer.duration() );
536 #ifndef CDS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS_SUPPORT
547 CPPUNIT_ASSERT( m.bucket_count() == 32 );
548 CPPUNIT_ASSERT( m.lock_count() == 32 );
550 test_striped_with2(m);
554 void Striped_hashmap();
557 void Striped_slist();
558 void Striped_boost_list();
559 void Striped_boost_flat_map();
560 void Striped_boost_map();
561 void Striped_boost_unordered_map();
563 void Refinable_hashmap();
564 void Refinable_list();
565 void Refinable_map();
566 void Refinable_slist();
567 void Refinable_boost_list();
568 void Refinable_boost_flat_map();
569 void Refinable_boost_map();
570 void Refinable_boost_unordered_map();
572 CPPUNIT_TEST_SUITE(StripedMapHdrTest)
573 CPPUNIT_TEST(Striped_hashmap)
574 CPPUNIT_TEST(Striped_list)
575 CPPUNIT_TEST(Striped_map)
576 CPPUNIT_TEST(Striped_slist)
577 CPPUNIT_TEST(Striped_boost_list)
578 CPPUNIT_TEST(Striped_boost_flat_map)
579 CPPUNIT_TEST(Striped_boost_map)
580 CPPUNIT_TEST(Striped_boost_unordered_map)
582 CPPUNIT_TEST(Refinable_hashmap)
583 CPPUNIT_TEST(Refinable_list)
584 CPPUNIT_TEST(Refinable_map)
585 CPPUNIT_TEST(Refinable_slist)
586 CPPUNIT_TEST(Refinable_boost_list)
587 CPPUNIT_TEST(Refinable_boost_flat_map)
588 CPPUNIT_TEST(Refinable_boost_map)
589 CPPUNIT_TEST(Refinable_boost_unordered_map)
590 CPPUNIT_TEST_SUITE_END()
595 #endif // #ifndef __CDSTEST_HDR_STRIPED_MAP_H