3 #include "cppunit/cppunit_proxy.h"
4 #include <cds/container/details/michael_list_base.h>
7 namespace cc = cds::container;
8 namespace co = cds::container::opt;
10 class MichaelKVListTestHeader: public CppUnitMini::TestCase
29 bool operator ()(const T& v1, const T& v2 ) const
37 int operator ()(const T& v1, const T& v2 ) const
41 return v1 > v2 ? 1 : 0;
48 check_value( int nExpected )
49 : m_nExpected( nExpected )
53 void operator ()( T& pair )
55 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
59 struct insert_functor {
61 void operator()( T& pair )
63 pair.second.m_val = pair.first * 10;
67 struct ensure_functor {
69 void operator()( bool /*bNew*/, T& pair )
71 pair.second.m_val = pair.first * 50;
75 struct erase_functor {
85 void operator()( T& i )
88 nVal = i.second.m_val;
92 typedef float other_key;
94 bool operator()( float f, int i ) const
98 bool operator()( int i, float f ) const
105 template <class OrdList>
106 void test_with( OrdList& l)
108 typedef typename OrdList::value_type value_type;
110 typename OrdList::iterator itTest;
111 typename OrdList::const_iterator citTest;
113 CPPUNIT_ASSERT( l.empty() );
115 // insert / find test
116 CPPUNIT_ASSERT( !l.find( 100 ));
117 CPPUNIT_ASSERT( l.insert( 100 ));
118 CPPUNIT_ASSERT( !l.empty() );
119 CPPUNIT_ASSERT( l.find( 100 ));
122 CPPUNIT_ASSERT( l.find( 100, std::ref( chk ) ) );
124 CPPUNIT_ASSERT( !l.find_with( 50, lt<key_type>() ));
125 CPPUNIT_ASSERT( l.insert( 50, 500 ));
126 CPPUNIT_ASSERT( l.find_with( 50, lt<key_type>() ));
127 CPPUNIT_ASSERT( !l.insert( 50, 5 ));
128 chk.m_nExpected = 500;
129 CPPUNIT_ASSERT( l.find_with( 50, lt<key_type>(), std::ref( chk ) ) );
131 CPPUNIT_ASSERT( l.find_with( 100, lt<key_type>(), std::ref( chk ) ) );
132 CPPUNIT_ASSERT( !l.empty() );
134 CPPUNIT_ASSERT( !l.find( 150 ));
135 CPPUNIT_ASSERT( l.insert_with( 150, insert_functor() ));
136 CPPUNIT_ASSERT( l.find( 150 ));
137 chk.m_nExpected = 1500;
138 CPPUNIT_ASSERT( l.find( 150, std::ref( chk ) ) );
140 CPPUNIT_ASSERT( l.find( 100, std::ref( chk ) ) );
141 chk.m_nExpected = 500;
142 CPPUNIT_ASSERT( l.find( 50, std::ref( chk ) ) );
143 CPPUNIT_ASSERT( !l.empty() );
147 CPPUNIT_ASSERT( !l.erase( 500 ));
148 CPPUNIT_ASSERT( !l.empty() );
150 CPPUNIT_ASSERT( l.find( 50 ));
153 l.erase( 50, std::ref( ef ) );
154 CPPUNIT_ASSERT( ef.nKey == 50 );
155 CPPUNIT_ASSERT( ef.nVal == 500 );
157 CPPUNIT_ASSERT( !l.find( 50 ));
160 std::pair<bool, bool> bEnsureResult;
161 bEnsureResult = l.ensure( 100, ensure_functor() );
162 CPPUNIT_ASSERT( bEnsureResult.first );
163 CPPUNIT_ASSERT( !bEnsureResult.second );
164 chk.m_nExpected = 5000;
165 CPPUNIT_ASSERT( l.find( 100, std::ref( chk ) ) );
169 bEnsureResult = l.ensure( 50, std::ref( ef ) );
171 CPPUNIT_ASSERT( bEnsureResult.first );
172 CPPUNIT_ASSERT( bEnsureResult.second );
173 chk.m_nExpected = 2500;
174 CPPUNIT_ASSERT( l.find( 50, std::ref( chk ) ) );
177 CPPUNIT_ASSERT( !l.empty() );
178 CPPUNIT_ASSERT( l.insert_with( 200, insert_functor() ));
179 CPPUNIT_ASSERT( l.insert( 25 ));
180 CPPUNIT_ASSERT( l.erase( 100 ));
181 CPPUNIT_ASSERT( l.erase( 150 ));
184 CPPUNIT_ASSERT( l.erase_with( 200, lt<key_type>(), std::ref(ef)) );
185 CPPUNIT_ASSERT( ef.nKey == 200 );
186 CPPUNIT_ASSERT( ef.nVal == 2000 );
188 CPPUNIT_ASSERT( l.erase_with( 25, lt<key_type>()))
189 CPPUNIT_ASSERT( l.erase( 50 ));
190 CPPUNIT_ASSERT( l.empty() );
194 CPPUNIT_ASSERT( l.empty() );
197 CPPUNIT_ASSERT( l.emplace( 501 ) );
198 CPPUNIT_ASSERT( l.emplace( 251, 152 ));
200 // insert failed - such key exists
201 CPPUNIT_ASSERT( !l.emplace( 501, 2 ) );
202 CPPUNIT_ASSERT( !l.emplace( 251, 10) );
205 CPPUNIT_ASSERT( l.find( 501, std::ref(cv) ));
206 cv.m_nExpected = 152;
207 CPPUNIT_ASSERT( l.find( 251, std::ref(cv) ));
210 CPPUNIT_ASSERT( l.empty() );
215 for ( int i = 0; i < nCount; ++i )
216 CPPUNIT_ASSERT( l.insert(i, i * 2 ) );
219 typename OrdList::iterator it( l.begin() );
220 typename OrdList::const_iterator cit( l.cbegin() );
221 CPPUNIT_CHECK( it == cit );
222 CPPUNIT_CHECK( it != l.end() );
223 CPPUNIT_CHECK( it != l.cend() );
224 CPPUNIT_CHECK( cit != l.end() );
225 CPPUNIT_CHECK( cit != l.cend() );
227 CPPUNIT_CHECK( it != cit );
228 CPPUNIT_CHECK( it != l.end() );
229 CPPUNIT_CHECK( it != l.cend() );
230 CPPUNIT_CHECK( cit != l.end() );
231 CPPUNIT_CHECK( cit != l.cend() );
233 CPPUNIT_CHECK( it == cit );
234 CPPUNIT_CHECK( it != l.end() );
235 CPPUNIT_CHECK( it != l.cend() );
236 CPPUNIT_CHECK( cit != l.end() );
237 CPPUNIT_CHECK( cit != l.cend() );
241 for ( typename OrdList::iterator it = l.begin(), itEnd = l.end(); it != itEnd; ++it, ++i ) {
242 CPPUNIT_ASSERT( it.key() == i );
243 CPPUNIT_ASSERT( it->first == i );
244 CPPUNIT_ASSERT( (*it).first == i );
246 CPPUNIT_ASSERT( it.val().m_val == i * 2 );
247 CPPUNIT_ASSERT( it->second.m_val == i * 2 );
248 CPPUNIT_ASSERT( (*it).second.m_val == i * 2 );
249 it.val().m_val = i * 3;
252 // Check that we have visited all items
253 for ( int i = 0; i < nCount; ++i ) {
254 chk.m_nExpected = i * 3;
255 CPPUNIT_ASSERT( l.find( i, std::ref( chk ) ) );
259 CPPUNIT_ASSERT( l.empty() );
262 for ( int i = 0; i < nCount; ++i )
263 CPPUNIT_ASSERT( l.insert(i, i * 7) );
266 const OrdList& rl = l;
267 for ( typename OrdList::const_iterator it = rl.begin(), itEnd = rl.end(); it != itEnd; ++it, ++i ) {
268 CPPUNIT_ASSERT( it.key() == i );
269 CPPUNIT_ASSERT( it->first == i );
270 CPPUNIT_ASSERT( (*it).first == i );
272 CPPUNIT_ASSERT( it.val().m_val == i * 7 );
273 CPPUNIT_ASSERT( it->second.m_val == i * 7 );
274 CPPUNIT_ASSERT( (*it).second.m_val == i * 7 );
277 // Check that we have visited all items
278 for ( int i = 0; i < nCount; ++i ) {
279 chk.m_nExpected = i * 7;
280 CPPUNIT_ASSERT( l.find_with( i, lt<key_type>(), std::ref( chk ) ) );
284 CPPUNIT_ASSERT( l.empty() );
288 template <class OrdList>
294 typedef typename OrdList::guarded_ptr guarded_ptr;
296 static int const nLimit = 20;
298 for ( int i = 0; i < nLimit; i++ )
300 std::random_shuffle( arr, arr + nLimit );
303 for ( int i = 0; i < nLimit; ++i )
304 l.insert( arr[i], arr[i] * 2 );
307 for ( int i = 0; i < nLimit; ++i ) {
311 CPPUNIT_ASSERT( gp );
312 CPPUNIT_ASSERT( !gp.empty());
313 CPPUNIT_CHECK( gp->first == nKey );
314 CPPUNIT_CHECK( gp->second.m_val == nKey * 2 );
316 CPPUNIT_CHECK( gp.empty() );
318 gp = l.extract( nKey );
319 CPPUNIT_ASSERT( gp );
320 CPPUNIT_ASSERT( !gp.empty());
321 CPPUNIT_CHECK( gp->first == nKey );
322 CPPUNIT_CHECK( gp->second.m_val == nKey*2 );
326 CPPUNIT_CHECK( !gp );
327 CPPUNIT_CHECK( gp.empty());
328 CPPUNIT_CHECK( !l.extract( nKey));
329 CPPUNIT_CHECK( gp.empty());
331 CPPUNIT_ASSERT( l.empty());
332 CPPUNIT_CHECK( !l.get(arr[0]));
333 CPPUNIT_CHECK( gp.empty());
334 CPPUNIT_CHECK( !l.extract( arr[0]));
335 CPPUNIT_CHECK( gp.empty());
338 // extract_with/get_with
339 for ( int i = 0; i < nLimit; ++i )
340 l.insert( arr[i], arr[i] * 2 );
343 for ( int i = 0; i < nLimit; ++i ) {
345 other_key key = float(nKey + 0.3);
347 gp = l.get_with( key, other_less() );
348 CPPUNIT_ASSERT( gp );
349 CPPUNIT_ASSERT( !gp.empty());
350 CPPUNIT_CHECK( gp->first == nKey );
351 CPPUNIT_CHECK( gp->second.m_val == nKey * 2 );
354 gp = l.extract_with( key, other_less() );
355 CPPUNIT_ASSERT( gp );
356 CPPUNIT_ASSERT( !gp.empty());
357 CPPUNIT_CHECK( gp->first == nKey );
358 CPPUNIT_CHECK( gp->second.m_val == nKey*2 );
361 gp = l.get_with( key, other_less() );
362 CPPUNIT_CHECK( !gp );
363 CPPUNIT_CHECK( gp.empty());
364 CPPUNIT_CHECK( !l.extract_with( key, other_less()));
365 CPPUNIT_CHECK( gp.empty());
367 CPPUNIT_ASSERT( l.empty());
368 CPPUNIT_CHECK( !l.get_with( 3.4f, other_less()));
369 CPPUNIT_CHECK( gp.empty());
370 CPPUNIT_CHECK( !l.extract_with( 3.4f, other_less()));
371 CPPUNIT_CHECK( gp.empty());
375 template <class OrdList>
381 static int const nLimit = 20;
383 typedef typename OrdList::rcu_lock rcu_lock;
384 typedef typename OrdList::value_type value_type;
385 typedef typename OrdList::gc rcu_type;
389 for (int i = 0; i < nLimit; ++i)
391 std::random_shuffle( a, a + nLimit );
394 for ( int i = 0; i < nLimit; ++i )
395 CPPUNIT_ASSERT( l.insert( a[i], a[i]*2 ) );
397 typename OrdList::exempt_ptr ep;
399 for ( int i = 0; i < nLimit; ++i ) {
402 value_type * pGet = l.get( a[i] );
403 CPPUNIT_ASSERT( pGet != nullptr );
404 CPPUNIT_CHECK( pGet->first == a[i] );
405 CPPUNIT_CHECK( pGet->second.m_val == a[i] * 2 );
407 ep = l.extract( a[i] );
408 CPPUNIT_ASSERT( ep );
409 CPPUNIT_ASSERT( !ep.empty() );
410 CPPUNIT_CHECK( ep->first == a[i] );
411 CPPUNIT_CHECK( (*ep).second.m_val == a[i] * 2 );
416 CPPUNIT_CHECK( l.get( a[i] ) == nullptr );
417 ep = l.extract( a[i] );
418 CPPUNIT_CHECK( !ep );
419 CPPUNIT_CHECK( ep.empty() );
422 CPPUNIT_ASSERT( l.empty() );
426 CPPUNIT_CHECK( l.get( a[0] ) == nullptr );
427 CPPUNIT_CHECK( !l.extract( a[0] ) );
428 CPPUNIT_CHECK( ep.empty() );
431 // extract_with/get_with
432 for ( int i = 0; i < nLimit; ++i ) {
433 CPPUNIT_ASSERT( l.insert( a[i], a[i]*2 ) );
436 for ( int i = 0; i < nLimit; ++i ) {
437 float itm = a[i] + 0.3f;
440 value_type * pGet = l.get_with( itm, other_less() );
441 CPPUNIT_ASSERT( pGet != nullptr );
442 CPPUNIT_CHECK( pGet->first == a[i] );
443 CPPUNIT_CHECK( pGet->second.m_val == a[i] * 2 );
445 ep = l.extract_with( itm, other_less() );
446 CPPUNIT_ASSERT( ep );
447 CPPUNIT_ASSERT( !ep.empty() );
448 CPPUNIT_CHECK( ep->first == a[i] );
449 CPPUNIT_CHECK( ep->second.m_val == a[i] * 2 );
454 CPPUNIT_CHECK( l.get_with( itm, other_less() ) == nullptr );
455 ep = l.extract_with( itm, other_less() );
456 CPPUNIT_CHECK( !ep );
457 CPPUNIT_CHECK( ep.empty() );
460 CPPUNIT_ASSERT( l.empty() );
464 CPPUNIT_CHECK( l.get_with( 3.14f, other_less() ) == nullptr );
465 CPPUNIT_CHECK( !l.extract_with( 3.14f, other_less() ));
466 CPPUNIT_CHECK( ep.empty() );
472 template <class OrdList>
475 typedef typename OrdList::value_type value_type;
476 typedef typename OrdList::iterator iterator;
482 CPPUNIT_ASSERT( l.empty() );
484 // insert / find test
485 CPPUNIT_ASSERT( l.find( 100 ) == l.end() );
486 CPPUNIT_ASSERT( l.insert( 100 ) != l.end() );
487 CPPUNIT_ASSERT( !l.empty() );
488 it = l.find_with( 100, lt<key_type>() );
489 CPPUNIT_ASSERT( it != l.end() );
490 CPPUNIT_ASSERT( it.key() == 100 );
491 CPPUNIT_ASSERT( it.val().m_val == 0 );
493 CPPUNIT_ASSERT( l.find_with( 50, lt<key_type>() ) == l.end() );
494 CPPUNIT_ASSERT( l.insert( 50, 500 ) != l.end());
496 CPPUNIT_ASSERT( it != l.end() );
497 CPPUNIT_ASSERT( it.key() == 50 );
498 CPPUNIT_ASSERT( it.val().m_val == 500 );
500 CPPUNIT_ASSERT( l.insert( 50, 5 ) == l.end() );
502 CPPUNIT_ASSERT( it != l.end() );
503 CPPUNIT_ASSERT( it.key() == 50 );
504 CPPUNIT_ASSERT( it.val().m_val == 500 );
505 CPPUNIT_ASSERT( !l.empty() );
507 CPPUNIT_ASSERT( l.find( 150 ) == l.end() );
508 CPPUNIT_ASSERT( l.insert_with( 150, insert_functor() ) != l.end() );
510 CPPUNIT_ASSERT( it != l.end() );
511 CPPUNIT_ASSERT( it.key() == 150 );
512 CPPUNIT_ASSERT( it.val().m_val == 1500 );
514 CPPUNIT_ASSERT( it != l.end() );
515 CPPUNIT_ASSERT( it.key() == 100 );
516 CPPUNIT_ASSERT( it.val().m_val == 0 );
518 CPPUNIT_ASSERT( it != l.end() );
519 CPPUNIT_ASSERT( it.key() == 50 );
520 CPPUNIT_ASSERT( it.val().m_val == 500 );
523 CPPUNIT_ASSERT( it != l.end() );
524 CPPUNIT_ASSERT( it.key() == 50 );
525 CPPUNIT_ASSERT( it.val().m_val == 25 );
526 CPPUNIT_ASSERT( !l.empty() );
528 // ensure existing item
529 std::pair<iterator, bool> ensureResult;
530 ensureResult = l.ensure( 100 );
531 CPPUNIT_ASSERT( !ensureResult.second );
532 CPPUNIT_ASSERT( ensureResult.first.key() == 100 );
533 CPPUNIT_ASSERT( ensureResult.first.val().m_val == 0 );
534 ensureResult.first.val().m_val = 5;
536 CPPUNIT_ASSERT( it != l.end() );
537 CPPUNIT_ASSERT( it.key() == 100 );
538 CPPUNIT_ASSERT( it.val().m_val == 5 );
540 CPPUNIT_ASSERT( !l.empty() );
543 ensureResult = l.ensure( 1000 );
544 CPPUNIT_ASSERT( ensureResult.second );
545 CPPUNIT_ASSERT( ensureResult.first.key() == 1000 );
546 CPPUNIT_ASSERT( ensureResult.first.val().m_val == 0 );
547 ensureResult.first.val().m_val = 33;
548 ensureResult = l.ensure( 1000 );
549 CPPUNIT_ASSERT( !ensureResult.second );
550 CPPUNIT_ASSERT( ensureResult.first.key() == 1000 );
551 CPPUNIT_ASSERT( ensureResult.first.val().m_val == 33 );
555 CPPUNIT_ASSERT( l.empty() );
558 CPPUNIT_ASSERT( l.emplace( 501 ) != l.end());
559 CPPUNIT_ASSERT( l.emplace( 251, 152 ) != l.end());
561 // insert failed - such key exists
562 CPPUNIT_ASSERT( l.emplace( 501, 2 ) == l.end());
563 CPPUNIT_ASSERT( l.emplace( 251, 10) == l.end());
566 CPPUNIT_ASSERT( it != l.end());
567 CPPUNIT_ASSERT( it.key() == 501 );
568 CPPUNIT_ASSERT( it.val().m_val == 0 );
571 CPPUNIT_ASSERT( it != l.end());
572 CPPUNIT_ASSERT( it.key() == 251 );
573 CPPUNIT_ASSERT( it.val().m_val == 152 );
576 CPPUNIT_ASSERT( l.empty() );
581 for ( int i = 0; i < nCount; ++i )
582 CPPUNIT_ASSERT( l.insert(i, i * 2 ) != l.end() );
585 typename OrdList::iterator it( l.begin() );
586 typename OrdList::const_iterator cit( l.cbegin() );
587 CPPUNIT_CHECK( it == cit );
588 CPPUNIT_CHECK( it != l.end() );
589 CPPUNIT_CHECK( it != l.cend() );
590 CPPUNIT_CHECK( cit != l.end() );
591 CPPUNIT_CHECK( cit != l.cend() );
593 CPPUNIT_CHECK( it != cit );
594 CPPUNIT_CHECK( it != l.end() );
595 CPPUNIT_CHECK( it != l.cend() );
596 CPPUNIT_CHECK( cit != l.end() );
597 CPPUNIT_CHECK( cit != l.cend() );
599 CPPUNIT_CHECK( it == cit );
600 CPPUNIT_CHECK( it != l.end() );
601 CPPUNIT_CHECK( it != l.cend() );
602 CPPUNIT_CHECK( cit != l.end() );
603 CPPUNIT_CHECK( cit != l.cend() );
607 for ( typename OrdList::iterator iter = l.begin(), itEnd = l.end(); iter != itEnd; ++iter, ++i ) {
608 CPPUNIT_ASSERT( iter.key() == i );
609 CPPUNIT_ASSERT( iter->first == i );
610 CPPUNIT_ASSERT( (*iter).first == i );
612 CPPUNIT_ASSERT( iter.val().m_val == i * 2 );
613 CPPUNIT_ASSERT( iter->second.m_val == i * 2 );
614 CPPUNIT_ASSERT( (*iter).second.m_val == i * 2 );
616 iter.val().m_val = i * 3;
619 // Check that we have visited all items
620 for ( int i = 0; i < nCount; ++i ) {
622 CPPUNIT_ASSERT( it != l.end() );
623 CPPUNIT_ASSERT( it.key() == i );
624 CPPUNIT_ASSERT( it.val().m_val == i * 3 );
628 CPPUNIT_ASSERT( l.empty() );
631 for ( int i = 0; i < nCount; ++i )
632 CPPUNIT_ASSERT( l.insert(i, i * 7) != l.end() );
635 const OrdList& rl = l;
636 for ( typename OrdList::const_iterator iter = rl.begin(), itEnd = rl.end(); iter != itEnd; ++iter, ++i ) {
637 CPPUNIT_ASSERT( iter.key() == i );
638 CPPUNIT_ASSERT( iter->first == i );
639 CPPUNIT_ASSERT( (*iter).first == i );
641 CPPUNIT_ASSERT( iter.val().m_val == i * 7 );
642 CPPUNIT_ASSERT( iter->second.m_val == i * 7 );
643 CPPUNIT_ASSERT( (*iter).second.m_val == i * 7 );
645 // it.val().m_val = i * 3 ; // error: const-iterator
649 CPPUNIT_ASSERT( l.empty() );
667 void RCU_GPI_cmpmix();
672 void RCU_GPB_cmpmix();
677 void RCU_GPT_cmpmix();
682 void RCU_SHB_cmpmix();
687 void RCU_SHT_cmpmix();
695 CPPUNIT_TEST_SUITE(MichaelKVListTestHeader)
697 CPPUNIT_TEST(HP_less)
698 CPPUNIT_TEST(HP_cmpmix)
701 CPPUNIT_TEST(DHP_cmp)
702 CPPUNIT_TEST(DHP_less)
703 CPPUNIT_TEST(DHP_cmpmix)
706 CPPUNIT_TEST(RCU_GPI_cmp)
707 CPPUNIT_TEST(RCU_GPI_less)
708 CPPUNIT_TEST(RCU_GPI_cmpmix)
709 CPPUNIT_TEST(RCU_GPI_ic)
711 CPPUNIT_TEST(RCU_GPB_cmp)
712 CPPUNIT_TEST(RCU_GPB_less)
713 CPPUNIT_TEST(RCU_GPB_cmpmix)
714 CPPUNIT_TEST(RCU_GPB_ic)
716 CPPUNIT_TEST(RCU_GPT_cmp)
717 CPPUNIT_TEST(RCU_GPT_less)
718 CPPUNIT_TEST(RCU_GPT_cmpmix)
719 CPPUNIT_TEST(RCU_GPT_ic)
721 CPPUNIT_TEST(RCU_SHB_cmp)
722 CPPUNIT_TEST(RCU_SHB_less)
723 CPPUNIT_TEST(RCU_SHB_cmpmix)
724 CPPUNIT_TEST(RCU_SHB_ic)
726 CPPUNIT_TEST(RCU_SHT_cmp)
727 CPPUNIT_TEST(RCU_SHT_less)
728 CPPUNIT_TEST(RCU_SHT_cmpmix)
729 CPPUNIT_TEST(RCU_SHT_ic)
731 CPPUNIT_TEST(NOGC_cmp)
732 CPPUNIT_TEST(NOGC_less)
733 CPPUNIT_TEST(NOGC_cmpmix)
734 CPPUNIT_TEST(NOGC_ic)
735 CPPUNIT_TEST_SUITE_END()
738 } // namespace ordlist