2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H
32 #define CDSTEST_HDR_INTRUSIVE_LAZY_H
34 #include "cppunit/cppunit_proxy.h"
35 #include <cds/intrusive/details/lazy_list_base.h>
38 namespace ci = cds::intrusive;
39 namespace co = cds::opt;
41 class IntrusiveLazyListHeaderTest: public CppUnitMini::TestCase
47 int nUpdateExistsCall;
54 , nUpdateExistsCall(0)
65 stat& operator =(const stat& s)
67 memcpy( this, &s, sizeof(s));
72 template <typename GC>
73 struct base_int_item: public ci::lazy_list::node< GC >
83 base_int_item(int key, int val)
89 base_int_item(const base_int_item& v )
95 const int& key() const
101 template <typename GC>
102 struct member_int_item
107 ci::lazy_list::node< GC > hMember;
114 member_int_item(int key, int val)
120 member_int_item(const member_int_item& v )
126 const int& key() const
132 template <typename T>
135 bool operator ()(const T& v1, const T& v2 ) const
137 return v1.key() < v2.key();
140 template <typename Q>
141 bool operator ()(const T& v1, const Q& v2 ) const
143 return v1.key() < v2;
146 template <typename Q>
147 bool operator ()(const Q& v1, const T& v2 ) const
149 return v1 < v2.key();
153 template <typename T>
155 int operator ()(const T& v1, const T& v2 ) const
157 if ( v1.key() < v2.key() )
159 return v1.key() > v2.key() ? 1 : 0;
162 template <typename Q>
163 int operator ()(const T& v1, const Q& v2 ) const
167 return v1.key() > v2 ? 1 : 0;
170 template <typename Q>
171 int operator ()(const Q& v1, const T& v2 ) const
175 return v1 > v2.key() ? 1 : 0;
179 template <typename T>
181 bool operator ()(const T& v1, const T& v2 ) const
183 return v1.key() == v2.key();
186 template <typename Q>
187 bool operator ()(const T& v1, const Q& v2 ) const
189 return v1.key() == v2;
192 template <typename Q>
193 bool operator ()(const Q& v1, const T& v2 ) const
195 return v1 == v2.key();
208 template <typename T, typename Q>
209 bool operator()( T const& i1, Q const& i2) const
211 return i1.nKey < i2.nKey;
216 template <typename T, typename Q>
217 bool operator()( T const& i1, Q const& i2) const
219 return i1.nKey == i2.nKey;
223 struct faked_disposer
225 template <typename T>
226 void operator ()( T * p )
228 ++p->s.nDisposeCount;
232 struct update_functor
234 template <typename T>
235 void operator ()(bool bNew, T& item, T& /*val*/ )
238 ++item.s.nUpdateNewCall;
240 ++item.s.nUpdateExistsCall;
246 template <typename T, typename Q>
247 void operator ()( T& item, Q& /*val*/ )
255 template <typename T>
256 void operator()( T const& item )
262 template <class OrdList>
263 void test_int_common()
265 typedef typename OrdList::value_type value_type;
267 value_type v1( 10, 50 );
268 value_type v2( 5, 25 );
269 value_type v3( 20, 100 );
272 CPPUNIT_ASSERT( l.empty() );
274 CPPUNIT_ASSERT( l.insert( v1 )) ; // true
275 CPPUNIT_ASSERT( l.contains( v1.key() ));
277 CPPUNIT_ASSERT( v1.s.nFindCall == 0 );
278 CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
279 CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
281 CPPUNIT_ASSERT( !l.contains( v2.key(), less<value_type>() ));
282 CPPUNIT_ASSERT( !l.find( v3.key(), find_functor() ));
283 CPPUNIT_ASSERT( !l.empty() );
285 //CPPUNIT_ASSERT( !l.insert( v1 )) ; // assertion "is_empty" is raised
289 CPPUNIT_ASSERT( !l.insert( v )) ; // false
292 std::pair<bool, bool> ret = l.update( v2, update_functor() );
293 CPPUNIT_ASSERT( ret.first );
294 CPPUNIT_ASSERT( ret.second );
295 CPPUNIT_ASSERT( v2.s.nUpdateNewCall == 1 );
296 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == 0 );
298 //CPPUNIT_ASSERT( !l.insert( v2 )) ; // assertion "is_empty"
300 CPPUNIT_ASSERT( l.contains( v1.key() )) ; // true
302 CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
303 CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
304 CPPUNIT_ASSERT( v1.s.nFindCall == 2 );
306 CPPUNIT_ASSERT( l.contains( v2.key() ));
308 CPPUNIT_ASSERT( v2.s.nFindCall == 0 );
309 CPPUNIT_ASSERT( l.find_with( v2.key(), less<value_type>(), find_functor() ));
310 CPPUNIT_ASSERT( v2.s.nFindCall == 1 );
312 CPPUNIT_ASSERT( !l.contains( v3.key() ));
315 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == 0 );
316 CPPUNIT_ASSERT( v2.s.nUpdateNewCall == 1 );
319 ret = l.update( v, update_functor() );
321 CPPUNIT_ASSERT( ret.first );
322 CPPUNIT_ASSERT( !ret.second );
323 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == 1 );
324 CPPUNIT_ASSERT( v2.s.nUpdateNewCall == 1 );
325 CPPUNIT_ASSERT( v.s.nUpdateExistsCall == 0 );
326 CPPUNIT_ASSERT( v.s.nUpdateNewCall == 0 );
329 CPPUNIT_ASSERT( !l.empty() );
331 CPPUNIT_ASSERT( l.insert( v3 )) ; // true
332 CPPUNIT_ASSERT( l.contains( v3.key() ));
334 CPPUNIT_ASSERT( v3.s.nFindCall == 0 );
335 CPPUNIT_ASSERT( l.find( v3.key(), find_functor() ));
336 CPPUNIT_ASSERT( v3.s.nFindCall == 1 );
338 CPPUNIT_ASSERT( l.unlink( v2 ) );
339 CPPUNIT_ASSERT( l.contains( v1.key() )) ; // true
340 CPPUNIT_ASSERT( !l.contains( v2.key() )) ; // true
341 CPPUNIT_ASSERT( l.contains( v3.key() )) ; // true
342 CPPUNIT_ASSERT( !l.empty() );
343 CPPUNIT_ASSERT( !l.unlink( v2 ) );
346 // v1 key is in the list but v NODE is not in the list
348 CPPUNIT_ASSERT( !l.unlink( v ) );
351 CPPUNIT_ASSERT( l.unlink( v1 ) );
352 CPPUNIT_ASSERT( !l.unlink( v1 ) );
353 CPPUNIT_ASSERT( !l.contains( v1.key() ));
354 CPPUNIT_ASSERT( !l.contains( v2.key() ));
355 CPPUNIT_ASSERT( l.contains( v3.key() ));
356 CPPUNIT_ASSERT( !l.empty() );
357 CPPUNIT_ASSERT( !l.unlink( v1 ) );
358 CPPUNIT_ASSERT( !l.unlink( v2 ) );
360 CPPUNIT_ASSERT( l.unlink( v3 ) );
361 CPPUNIT_ASSERT( !l.contains( v1.key() ));
362 CPPUNIT_ASSERT( !l.contains( v2.key(), less<value_type>() ));
363 CPPUNIT_ASSERT( !l.contains( v3.key() ));
364 CPPUNIT_ASSERT( l.empty() );
365 CPPUNIT_ASSERT( !l.unlink( v1 ) );
366 CPPUNIT_ASSERT( !l.unlink( v2 ) );
367 CPPUNIT_ASSERT( !l.unlink( v3 ) );
369 // Apply retired pointer to clean links
370 OrdList::gc::force_dispose();
373 ret = l.update( v3, update_functor() );
374 CPPUNIT_ASSERT( ret.first );
375 CPPUNIT_ASSERT( ret.second );
376 CPPUNIT_ASSERT( v3.s.nUpdateNewCall == s.nUpdateNewCall + 1);
377 CPPUNIT_ASSERT( v3.s.nUpdateExistsCall == s.nUpdateExistsCall );
378 CPPUNIT_ASSERT( !l.empty() );
381 ret = l.update( v2, update_functor() );
382 CPPUNIT_ASSERT( ret.first );
383 CPPUNIT_ASSERT( ret.second );
384 CPPUNIT_ASSERT( v2.s.nUpdateNewCall == s.nUpdateNewCall + 1);
385 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == s.nUpdateExistsCall );
386 CPPUNIT_ASSERT( !l.empty() );
389 ret = l.update( v1, update_functor() );
390 CPPUNIT_ASSERT( ret.first );
391 CPPUNIT_ASSERT( ret.second );
392 CPPUNIT_ASSERT( v1.s.nUpdateNewCall == s.nUpdateNewCall + 1);
393 CPPUNIT_ASSERT( v1.s.nUpdateExistsCall == s.nUpdateExistsCall );
394 CPPUNIT_ASSERT( !l.empty() );
397 CPPUNIT_ASSERT( l.erase( v1.key()) );
398 //CPPUNIT_ASSERT( v1.s.nDisposeCount == 0 );
399 CPPUNIT_ASSERT( !l.empty() );
401 CPPUNIT_ASSERT( v2.s.nEraseCall == 0 );
402 CPPUNIT_ASSERT( l.erase_with( v2.key(), less<value_type>(), erase_functor()) );
403 CPPUNIT_ASSERT( v2.s.nEraseCall == 1 );
404 CPPUNIT_ASSERT( !l.erase_with( v2.key(), less<value_type>()));
405 CPPUNIT_ASSERT( v2.s.nEraseCall == 1 );
406 //CPPUNIT_ASSERT( v2.s.nDisposeCount == 0 );
407 CPPUNIT_ASSERT( !l.empty() );
409 CPPUNIT_ASSERT( !l.erase( v2 ));
410 CPPUNIT_ASSERT( !l.erase( v1 ));
411 //CPPUNIT_ASSERT( v2.s.nDisposeCount == 0 );
412 CPPUNIT_ASSERT( !l.empty() );
414 CPPUNIT_ASSERT( v3.s.nEraseCall == 0 );
415 CPPUNIT_ASSERT( l.erase( v3, erase_functor() ));
416 CPPUNIT_ASSERT( v3.s.nEraseCall == 1 );
417 //CPPUNIT_ASSERT( v3.s.nDisposeCount == 0 );
418 CPPUNIT_ASSERT( l.empty() );
420 // Apply retired pointer to clean links
421 OrdList::gc::force_dispose();
424 CPPUNIT_ASSERT( l.insert( v1 ));
425 CPPUNIT_ASSERT( l.insert( v3 ));
426 CPPUNIT_ASSERT( !l.empty() );
427 CPPUNIT_ASSERT( !l.unlink( v2 ));
428 CPPUNIT_ASSERT( l.unlink( v1 ));
429 CPPUNIT_ASSERT( !l.unlink( v1 ));
430 CPPUNIT_ASSERT( l.unlink( v3 ));
431 CPPUNIT_ASSERT( !l.unlink( v3 ));
432 CPPUNIT_ASSERT( l.empty() );
434 // Apply retired pointer
435 OrdList::gc::force_dispose();
436 CPPUNIT_ASSERT( v1.s.nDisposeCount == 3 );
437 CPPUNIT_ASSERT( v2.s.nDisposeCount == 2 );
438 CPPUNIT_ASSERT( v3.s.nDisposeCount == 3 );
440 // Destructor test (call disposer)
441 CPPUNIT_ASSERT( l.insert( v1 ));
442 CPPUNIT_ASSERT( l.insert( v3 ));
443 CPPUNIT_ASSERT( l.insert( v2 ));
447 typename OrdList::iterator it = l.begin();
448 typename OrdList::const_iterator cit = l.cbegin();
449 CPPUNIT_ASSERT( it != l.end() );
450 CPPUNIT_ASSERT( it != l.cend() );
451 CPPUNIT_ASSERT( cit != l.end() );
452 CPPUNIT_ASSERT( cit != l.cend() );
453 CPPUNIT_ASSERT( cit == it );
455 CPPUNIT_ASSERT( it->nKey == v2.nKey );
456 CPPUNIT_ASSERT( it->nVal == v2.nVal );
457 CPPUNIT_ASSERT( ++it != l.end() );
458 CPPUNIT_ASSERT( it->nKey == v1.nKey );
459 CPPUNIT_ASSERT( it->nVal == v1.nVal );
460 CPPUNIT_ASSERT( ++it != l.end() );
461 CPPUNIT_ASSERT( it->nKey == v3.nKey );
462 CPPUNIT_ASSERT( it->nVal == v3.nVal );
463 CPPUNIT_ASSERT( ++it == l.end() );
467 OrdList const & lref = l;
468 typename OrdList::const_iterator it = lref.begin();
469 CPPUNIT_ASSERT( it != l.end() );
470 CPPUNIT_ASSERT( it->nKey == v2.nKey );
471 CPPUNIT_ASSERT( it->nVal == v2.nVal );
472 CPPUNIT_ASSERT( ++it != lref.end() );
473 CPPUNIT_ASSERT( it->nKey == v1.nKey );
474 CPPUNIT_ASSERT( it->nVal == v1.nVal );
475 CPPUNIT_ASSERT( ++it != l.end() );
476 CPPUNIT_ASSERT( it->nKey == v3.nKey );
477 CPPUNIT_ASSERT( it->nVal == v3.nVal );
478 CPPUNIT_ASSERT( ++it == l.end() );
482 // Apply retired pointer
483 OrdList::gc::force_dispose();
485 CPPUNIT_ASSERT( v1.s.nDisposeCount == 4 );
486 CPPUNIT_ASSERT( v2.s.nDisposeCount == 3 );
487 CPPUNIT_ASSERT( v3.s.nDisposeCount == 4 );
490 template <class OrdList>
493 test_int_common<OrdList>();
496 typename OrdList::guarded_ptr gp;
498 static int const nLimit = 20;
499 typename OrdList::value_type arrItem[nLimit];
503 for (int i = 0; i < nLimit; ++i)
505 shuffle( a, a + nLimit );
507 for (int i = 0; i < nLimit; ++i) {
508 arrItem[i].nKey = a[i];
509 arrItem[i].nVal = a[i] * 2;
513 for ( int i = 0; i < nLimit; ++i )
514 CPPUNIT_ASSERT( l.insert( arrItem[i] ) );
516 for ( int i=0; i < nLimit; ++i ) {
517 gp = l.get( arrItem[i].nKey );
518 CPPUNIT_ASSERT( gp );
519 CPPUNIT_ASSERT( !gp.empty());
520 CPPUNIT_ASSERT( gp->nKey == arrItem[i].nKey );
521 CPPUNIT_ASSERT( gp->nVal == arrItem[i].nVal );
523 gp = l.extract( arrItem[i].nKey );
524 CPPUNIT_ASSERT( gp );
525 CPPUNIT_ASSERT( !gp.empty());
526 CPPUNIT_ASSERT( gp->nKey == arrItem[i].nKey );
527 CPPUNIT_ASSERT( gp->nVal == arrItem[i].nVal );
529 gp = l.get( arrItem[i].nKey );
530 CPPUNIT_ASSERT( !gp );
531 CPPUNIT_ASSERT( gp.empty());
532 CPPUNIT_ASSERT( !l.extract( arrItem[i].nKey ));
533 CPPUNIT_ASSERT( gp.empty());
535 CPPUNIT_ASSERT( l.empty() );
536 CPPUNIT_ASSERT( !l.get( nLimit/2 ));
537 CPPUNIT_ASSERT( !l.extract( nLimit/2 ));
539 // Apply retired pointer
540 OrdList::gc::force_dispose();
542 // extract_with/get_with
543 for ( int i = 0; i < nLimit; ++i )
544 CPPUNIT_ASSERT( l.insert( arrItem[i] ) );
546 for ( int i=0; i < nLimit; ++i ) {
547 other_item itm( arrItem[i].nKey );
548 gp = l.get_with( itm, other_less() );
549 CPPUNIT_ASSERT( gp );
550 CPPUNIT_ASSERT( !gp.empty());
551 CPPUNIT_ASSERT( gp->nKey == arrItem[i].nKey );
552 CPPUNIT_ASSERT( gp->nVal == arrItem[i].nVal );
554 gp = l.extract_with( itm, other_less() );
555 CPPUNIT_ASSERT( gp );
556 CPPUNIT_ASSERT( !gp.empty());
557 CPPUNIT_ASSERT( gp->nKey == arrItem[i].nKey );
558 CPPUNIT_ASSERT( gp->nVal == arrItem[i].nVal );
560 gp = l.get_with( itm, other_less() );
561 CPPUNIT_ASSERT( !gp );
562 CPPUNIT_ASSERT( gp.empty());
563 CPPUNIT_ASSERT( !l.extract_with( itm, other_less() ));
564 CPPUNIT_ASSERT( gp.empty());
566 CPPUNIT_ASSERT( l.empty() );
567 CPPUNIT_ASSERT( !l.get_with( other_item(nLimit/2), other_less() ));
568 CPPUNIT_ASSERT( gp.empty());
569 CPPUNIT_ASSERT( !l.extract_with( other_item(nLimit/2), other_less() ));
570 CPPUNIT_ASSERT( gp.empty());
572 // Apply retired pointer
573 OrdList::gc::force_dispose();
575 for ( int i=0; i < nLimit; i++ ) {
576 CPPUNIT_ASSERT( arrItem[i].s.nDisposeCount == 2 );
581 template <class OrdList>
584 test_int_common<OrdList>();
587 static int const nLimit = 20;
588 typename OrdList::value_type arrItem[nLimit];
590 typedef typename OrdList::rcu_lock rcu_lock;
591 typedef typename OrdList::value_type value_type;
592 typedef typename OrdList::gc rcu_type;
596 for (int i = 0; i < nLimit; ++i)
598 shuffle( a, a + nLimit );
600 for (int i = 0; i < nLimit; ++i) {
601 arrItem[i].nKey = a[i];
602 arrItem[i].nVal = a[i] * 2;
605 typename OrdList::exempt_ptr ep;
608 for ( int i = 0; i < nLimit; ++i )
609 CPPUNIT_ASSERT( l.insert( arrItem[i] ) );
611 for ( int i = 0; i < nLimit; ++i ) {
614 value_type * pGet = l.get( a[i] );
615 CPPUNIT_ASSERT( pGet != nullptr );
616 CPPUNIT_CHECK( pGet->nKey == a[i] );
617 CPPUNIT_CHECK( pGet->nVal == a[i] * 2 );
619 ep = l.extract( a[i] );
620 CPPUNIT_ASSERT( ep );
621 CPPUNIT_ASSERT( !ep.empty() );
622 CPPUNIT_CHECK( ep->nKey == a[i] );
623 CPPUNIT_CHECK( (*ep).nVal == a[i] * 2 );
628 CPPUNIT_CHECK( l.get( a[i] ) == nullptr );
629 CPPUNIT_CHECK( !l.extract( a[i] ) );
630 CPPUNIT_CHECK( ep.empty() );
633 CPPUNIT_ASSERT( l.empty() );
637 CPPUNIT_CHECK( l.get( a[0] ) == nullptr );
638 ep = l.extract( a[0] );
639 CPPUNIT_CHECK( !ep );
640 CPPUNIT_CHECK( ep.empty() );
642 // Apply retired pointer
643 OrdList::gc::force_dispose();
645 // extract_with/get_with
646 for ( int i = 0; i < nLimit; ++i ) {
647 CPPUNIT_ASSERT( l.insert( arrItem[i] ) );
650 for ( int i = 0; i < nLimit; ++i ) {
651 other_item itm( a[i] );
654 value_type * pGet = l.get_with( itm, other_less() );
655 CPPUNIT_ASSERT( pGet != nullptr );
656 CPPUNIT_CHECK( pGet->nKey == a[i] );
657 CPPUNIT_CHECK( pGet->nVal == a[i] * 2 );
659 ep = l.extract_with( itm, other_less() );
660 CPPUNIT_ASSERT( ep );
661 CPPUNIT_ASSERT( !ep.empty() );
662 CPPUNIT_CHECK( ep->nKey == a[i] );
663 CPPUNIT_CHECK( ep->nVal == a[i] * 2 );
668 CPPUNIT_CHECK( l.get_with( itm, other_less() ) == nullptr );
669 ep = l.extract_with( itm, other_less() );
670 CPPUNIT_CHECK( !ep );
671 CPPUNIT_CHECK( ep.empty() );
674 CPPUNIT_ASSERT( l.empty() );
678 CPPUNIT_CHECK( l.get_with( other_item( 0 ), other_less() ) == nullptr );
679 CPPUNIT_CHECK( !l.extract_with( other_item(0), other_less() ));
680 CPPUNIT_CHECK( ep.empty() );
682 // Apply retired pointer
683 OrdList::gc::force_dispose();
687 template <class OrdList>
690 typedef typename OrdList::value_type value_type;
693 value_type v1( 10, 50 );
694 value_type v2( 5, 25 );
695 value_type v3( 20, 100 );
698 CPPUNIT_ASSERT( l.empty() );
700 CPPUNIT_ASSERT( l.insert( v1 )) ; // true
701 CPPUNIT_ASSERT( l.contains( v1.key() ) == &v1 );
703 CPPUNIT_ASSERT( v1.s.nFindCall == 0 );
704 CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
705 CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
707 CPPUNIT_ASSERT( l.contains( v2.key(), less<value_type>() ) == nullptr );
708 CPPUNIT_ASSERT( l.contains( v3.key() ) == nullptr );
709 CPPUNIT_ASSERT( !l.empty() );
711 //CPPUNIT_ASSERT( !l.insert( v1 )) ; // assertion "is_empty" is raised
715 CPPUNIT_ASSERT( !l.insert( v )) ; // false
718 std::pair<bool, bool> ret = l.update( v2, update_functor() );
719 CPPUNIT_ASSERT( ret.first );
720 CPPUNIT_ASSERT( ret.second );
721 CPPUNIT_ASSERT( v2.s.nUpdateNewCall == 1 );
722 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == 0 );
724 //CPPUNIT_ASSERT( !l.insert( v2 )) ; // assertion "is_empty"
726 CPPUNIT_ASSERT( l.contains( v1.key() ) == &v1 ) ; // true
728 CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
729 CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
730 CPPUNIT_ASSERT( v1.s.nFindCall == 2 );
732 CPPUNIT_ASSERT( l.contains( v2.key(), less<value_type>() ) == &v2 );
734 CPPUNIT_ASSERT( v2.s.nFindCall == 0 );
735 CPPUNIT_ASSERT( l.find_with( v2.key(), less<value_type>(), find_functor() ));
736 CPPUNIT_ASSERT( v2.s.nFindCall == 1 );
738 CPPUNIT_ASSERT( !l.contains( v3.key() ));
742 ret = l.update( v, update_functor() );
744 CPPUNIT_ASSERT( ret.first );
745 CPPUNIT_ASSERT( !ret.second );
746 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == 1 );
747 CPPUNIT_ASSERT( v.s.nUpdateExistsCall == 0 && v.s.nUpdateNewCall == 0 );
750 CPPUNIT_ASSERT( !l.empty() );
752 CPPUNIT_ASSERT( l.insert( v3 )) ; // true
753 CPPUNIT_ASSERT( l.contains( v3.key() ) == &v3 );
755 CPPUNIT_ASSERT( v3.s.nFindCall == 0 );
756 CPPUNIT_ASSERT( l.find( v3.key(), find_functor() ));
757 CPPUNIT_ASSERT( v3.s.nFindCall == 1 );
760 typename OrdList::iterator it = l.begin();
761 typename OrdList::const_iterator cit = l.cbegin();
762 CPPUNIT_ASSERT( it != l.end() );
763 CPPUNIT_ASSERT( it != l.cend() );
764 CPPUNIT_ASSERT( cit != l.end() );
765 CPPUNIT_ASSERT( cit != l.cend() );
766 CPPUNIT_ASSERT( cit == it );
768 CPPUNIT_ASSERT( it->nKey == v2.nKey );
769 CPPUNIT_ASSERT( it->nVal == v2.nVal );
770 CPPUNIT_ASSERT( ++it != l.end() );
771 CPPUNIT_ASSERT( it->nKey == v1.nKey );
772 CPPUNIT_ASSERT( it->nVal == v1.nVal );
773 CPPUNIT_ASSERT( it++ != l.end() );
774 CPPUNIT_ASSERT( it->nKey == v3.nKey );
775 CPPUNIT_ASSERT( it->nVal == v3.nVal );
776 CPPUNIT_ASSERT( it++ != l.end() );
777 CPPUNIT_ASSERT( it == l.end() );
781 OrdList const & lref = l;
782 typename OrdList::const_iterator it = lref.begin();
783 CPPUNIT_ASSERT( it != l.end() );
784 CPPUNIT_ASSERT( it->nKey == v2.nKey );
785 CPPUNIT_ASSERT( it->nVal == v2.nVal );
786 CPPUNIT_ASSERT( ++it != lref.end() );
787 CPPUNIT_ASSERT( it->nKey == v1.nKey );
788 CPPUNIT_ASSERT( it->nVal == v1.nVal );
789 CPPUNIT_ASSERT( it++ != l.end() );
790 CPPUNIT_ASSERT( it->nKey == v3.nKey );
791 CPPUNIT_ASSERT( it->nVal == v3.nVal );
792 CPPUNIT_ASSERT( it++ != lref.end() );
793 CPPUNIT_ASSERT( it == l.end() );
797 // Disposer called on list destruction
798 CPPUNIT_ASSERT( v1.s.nDisposeCount == 1 );
799 CPPUNIT_ASSERT( v2.s.nDisposeCount == 1 );
800 CPPUNIT_ASSERT( v3.s.nDisposeCount == 1 );
804 template <class UnordList>
805 void test_nogc_int_unordered()
807 typedef typename UnordList::value_type value_type;
809 value_type v1( 10, 50 );
810 value_type v2( 5, 25 );
811 value_type v3( 20, 100 );
814 CPPUNIT_ASSERT( l.empty() );
816 CPPUNIT_ASSERT( l.insert( v1 )); // true
817 CPPUNIT_ASSERT( l.contains( v1.key() ) == &v1 );
819 CPPUNIT_ASSERT( v1.s.nFindCall == 0 );
820 CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
821 CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
823 CPPUNIT_ASSERT( l.contains( v2.key(), equal_to<value_type>() ) == nullptr );
824 CPPUNIT_ASSERT( l.contains( v3.key() ) == nullptr );
825 CPPUNIT_ASSERT( !l.empty() );
827 //CPPUNIT_ASSERT( !l.insert( v1 )) ; // assertion "is_empty" is raised
831 CPPUNIT_ASSERT( !l.insert( v )) ; // false
834 std::pair<bool, bool> ret = l.update( v2, update_functor() );
835 CPPUNIT_ASSERT( ret.first );
836 CPPUNIT_ASSERT( ret.second );
837 CPPUNIT_ASSERT( v2.s.nUpdateNewCall == 1 );
838 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == 0 );
840 //CPPUNIT_ASSERT( !l.insert( v2 )) ; // assertion "is_empty"
842 CPPUNIT_ASSERT( l.contains( v1.key() ) == &v1 ) ; // true
844 CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
845 CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
846 CPPUNIT_ASSERT( v1.s.nFindCall == 2 );
848 CPPUNIT_ASSERT( l.contains( v2.key(), equal_to<value_type>() ) == &v2 );
850 CPPUNIT_ASSERT( v2.s.nFindCall == 0 );
851 CPPUNIT_ASSERT( l.find_with( v2.key(), equal_to<value_type>(), find_functor() ));
852 CPPUNIT_ASSERT( v2.s.nFindCall == 1 );
854 CPPUNIT_ASSERT( !l.contains( v3.key() ));
858 ret = l.update( v, update_functor() );
860 CPPUNIT_ASSERT( ret.first );
861 CPPUNIT_ASSERT( !ret.second );
862 CPPUNIT_ASSERT( v2.s.nUpdateExistsCall == 1 );
863 CPPUNIT_ASSERT( v.s.nUpdateExistsCall == 0 && v.s.nUpdateNewCall == 0 );
866 CPPUNIT_ASSERT( !l.empty() );
868 CPPUNIT_ASSERT( l.insert( v3 )) ; // true
869 CPPUNIT_ASSERT( l.contains( v3.key() ) == &v3 );
871 CPPUNIT_ASSERT( v3.s.nFindCall == 0 );
872 CPPUNIT_ASSERT( l.find( v3.key(), find_functor() ));
873 CPPUNIT_ASSERT( v3.s.nFindCall == 1 );
876 typename UnordList::iterator it = l.begin();
877 typename UnordList::const_iterator cit = l.cbegin();
878 CPPUNIT_ASSERT( it != l.end() );
879 CPPUNIT_ASSERT( it != l.cend() );
880 CPPUNIT_ASSERT( cit != l.end() );
881 CPPUNIT_ASSERT( cit != l.cend() );
882 CPPUNIT_ASSERT( cit == it );
884 CPPUNIT_ASSERT( it->nKey == v1.nKey );
885 CPPUNIT_ASSERT( it->nVal == v1.nVal );
886 CPPUNIT_ASSERT( ++it != l.end() );
887 CPPUNIT_ASSERT( it->nKey == v2.nKey );
888 CPPUNIT_ASSERT( it->nVal == v2.nVal );
889 CPPUNIT_ASSERT( it++ != l.end() );
890 CPPUNIT_ASSERT( it->nKey == v3.nKey );
891 CPPUNIT_ASSERT( it->nVal == v3.nVal );
892 CPPUNIT_ASSERT( it++ != l.end() );
893 CPPUNIT_ASSERT( it == l.end() );
897 UnordList const & lref = l;
898 typename UnordList::const_iterator it = lref.begin();
899 CPPUNIT_ASSERT( it != l.end() );
900 CPPUNIT_ASSERT( it->nKey == v1.nKey );
901 CPPUNIT_ASSERT( it->nVal == v1.nVal );
902 CPPUNIT_ASSERT( ++it != lref.end() );
903 CPPUNIT_ASSERT( it->nKey == v2.nKey );
904 CPPUNIT_ASSERT( it->nVal == v2.nVal );
905 CPPUNIT_ASSERT( it++ != l.end() );
906 CPPUNIT_ASSERT( it->nKey == v3.nKey );
907 CPPUNIT_ASSERT( it->nVal == v3.nVal );
908 CPPUNIT_ASSERT( it++ != lref.end() );
909 CPPUNIT_ASSERT( it == l.end() );
913 // Disposer called on list destruction
914 CPPUNIT_ASSERT( v1.s.nDisposeCount == 1 );
915 CPPUNIT_ASSERT( v2.s.nDisposeCount == 1 );
916 CPPUNIT_ASSERT( v3.s.nDisposeCount == 1 );
923 void HP_base_cmpmix();
925 void HP_member_cmp();
926 void HP_member_less();
927 void HP_member_cmpmix();
931 void DHP_base_less();
932 void DHP_base_cmpmix();
934 void DHP_member_cmp();
935 void DHP_member_less();
936 void DHP_member_cmpmix();
937 void DHP_member_ic();
939 void RCU_GPI_base_cmp();
940 void RCU_GPI_base_less();
941 void RCU_GPI_base_cmpmix();
942 void RCU_GPI_base_ic();
943 void RCU_GPI_member_cmp();
944 void RCU_GPI_member_less();
945 void RCU_GPI_member_cmpmix();
946 void RCU_GPI_member_ic();
948 void RCU_GPB_base_cmp();
949 void RCU_GPB_base_less();
950 void RCU_GPB_base_cmpmix();
951 void RCU_GPB_base_ic();
952 void RCU_GPB_member_cmp();
953 void RCU_GPB_member_less();
954 void RCU_GPB_member_cmpmix();
955 void RCU_GPB_member_ic();
957 void RCU_GPT_base_cmp();
958 void RCU_GPT_base_less();
959 void RCU_GPT_base_cmpmix();
960 void RCU_GPT_base_ic();
961 void RCU_GPT_member_cmp();
962 void RCU_GPT_member_less();
963 void RCU_GPT_member_cmpmix();
964 void RCU_GPT_member_ic();
966 void RCU_SHB_base_cmp();
967 void RCU_SHB_base_less();
968 void RCU_SHB_base_cmpmix();
969 void RCU_SHB_base_ic();
970 void RCU_SHB_member_cmp();
971 void RCU_SHB_member_less();
972 void RCU_SHB_member_cmpmix();
973 void RCU_SHB_member_ic();
975 void RCU_SHT_base_cmp();
976 void RCU_SHT_base_less();
977 void RCU_SHT_base_cmpmix();
978 void RCU_SHT_base_ic();
979 void RCU_SHT_member_cmp();
980 void RCU_SHT_member_less();
981 void RCU_SHT_member_cmpmix();
982 void RCU_SHT_member_ic();
984 void nogc_base_cmp();
985 void nogc_base_less();
986 void nogc_base_cmpmix();
988 void nogc_member_cmp();
989 void nogc_member_less();
990 void nogc_member_cmpmix();
991 void nogc_member_ic();
993 void nogc_base_cmp_unord();
994 void nogc_base_less_unord();
995 void nogc_base_equal_to_unord();
996 void nogc_base_cmpmix_unord();
997 void nogc_base_equal_to_mix_unord();
998 void nogc_base_ic_unord();
999 void nogc_member_cmp_unord();
1000 void nogc_member_less_unord();
1001 void nogc_member_equal_to_unord();
1002 void nogc_member_cmpmix_unord();
1003 void nogc_member_equal_to_mix_unord();
1004 void nogc_member_ic_unord();
1006 CPPUNIT_TEST_SUITE(IntrusiveLazyListHeaderTest)
1007 CPPUNIT_TEST(HP_base_cmp)
1008 CPPUNIT_TEST(HP_base_less)
1009 CPPUNIT_TEST(HP_base_cmpmix)
1010 CPPUNIT_TEST(HP_base_ic)
1011 CPPUNIT_TEST(HP_member_cmp)
1012 CPPUNIT_TEST(HP_member_less)
1013 CPPUNIT_TEST(HP_member_cmpmix)
1014 CPPUNIT_TEST(HP_member_ic)
1016 CPPUNIT_TEST(DHP_base_cmp)
1017 CPPUNIT_TEST(DHP_base_less)
1018 CPPUNIT_TEST(DHP_base_cmpmix)
1019 CPPUNIT_TEST(DHP_base_ic)
1020 CPPUNIT_TEST(DHP_member_cmp)
1021 CPPUNIT_TEST(DHP_member_less)
1022 CPPUNIT_TEST(DHP_member_cmpmix)
1023 CPPUNIT_TEST(DHP_member_ic)
1025 CPPUNIT_TEST(RCU_GPI_base_cmp)
1026 CPPUNIT_TEST(RCU_GPI_base_less)
1027 CPPUNIT_TEST(RCU_GPI_base_cmpmix)
1028 CPPUNIT_TEST(RCU_GPI_base_ic)
1029 CPPUNIT_TEST(RCU_GPI_member_cmp)
1030 CPPUNIT_TEST(RCU_GPI_member_less)
1031 CPPUNIT_TEST(RCU_GPI_member_cmpmix)
1032 CPPUNIT_TEST(RCU_GPI_member_ic)
1034 CPPUNIT_TEST(RCU_GPB_base_cmp)
1035 CPPUNIT_TEST(RCU_GPB_base_less)
1036 CPPUNIT_TEST(RCU_GPB_base_cmpmix)
1037 CPPUNIT_TEST(RCU_GPB_base_ic)
1038 CPPUNIT_TEST(RCU_GPB_member_cmp)
1039 CPPUNIT_TEST(RCU_GPB_member_less)
1040 CPPUNIT_TEST(RCU_GPB_member_cmpmix)
1041 CPPUNIT_TEST(RCU_GPB_member_ic)
1043 CPPUNIT_TEST(RCU_GPT_base_cmp)
1044 CPPUNIT_TEST(RCU_GPT_base_less)
1045 CPPUNIT_TEST(RCU_GPT_base_cmpmix)
1046 CPPUNIT_TEST(RCU_GPT_base_ic)
1047 CPPUNIT_TEST(RCU_GPT_member_cmp)
1048 CPPUNIT_TEST(RCU_GPT_member_less)
1049 CPPUNIT_TEST(RCU_GPT_member_cmpmix)
1050 CPPUNIT_TEST(RCU_GPT_member_ic)
1052 CPPUNIT_TEST(RCU_SHB_base_cmp)
1053 CPPUNIT_TEST(RCU_SHB_base_less)
1054 CPPUNIT_TEST(RCU_SHB_base_cmpmix)
1055 CPPUNIT_TEST(RCU_SHB_base_ic)
1056 CPPUNIT_TEST(RCU_SHB_member_cmp)
1057 CPPUNIT_TEST(RCU_SHB_member_less)
1058 CPPUNIT_TEST(RCU_SHB_member_cmpmix)
1059 CPPUNIT_TEST(RCU_SHB_member_ic)
1061 CPPUNIT_TEST(RCU_SHT_base_cmp)
1062 CPPUNIT_TEST(RCU_SHT_base_less)
1063 CPPUNIT_TEST(RCU_SHT_base_cmpmix)
1064 CPPUNIT_TEST(RCU_SHT_base_ic)
1065 CPPUNIT_TEST(RCU_SHT_member_cmp)
1066 CPPUNIT_TEST(RCU_SHT_member_less)
1067 CPPUNIT_TEST(RCU_SHT_member_cmpmix)
1068 CPPUNIT_TEST(RCU_SHT_member_ic)
1070 CPPUNIT_TEST(nogc_base_cmp)
1071 CPPUNIT_TEST(nogc_base_less)
1072 CPPUNIT_TEST(nogc_base_cmpmix)
1073 CPPUNIT_TEST(nogc_base_ic)
1074 CPPUNIT_TEST(nogc_member_cmp)
1075 CPPUNIT_TEST(nogc_member_less)
1076 CPPUNIT_TEST(nogc_member_cmpmix)
1077 CPPUNIT_TEST(nogc_member_ic)
1079 CPPUNIT_TEST(nogc_base_cmp_unord)
1080 CPPUNIT_TEST(nogc_base_less_unord)
1081 CPPUNIT_TEST(nogc_base_equal_to_unord)
1082 CPPUNIT_TEST(nogc_base_cmpmix_unord)
1083 CPPUNIT_TEST(nogc_base_equal_to_mix_unord)
1084 CPPUNIT_TEST(nogc_base_ic_unord)
1085 CPPUNIT_TEST(nogc_member_cmp_unord)
1086 CPPUNIT_TEST(nogc_member_less_unord)
1087 CPPUNIT_TEST(nogc_member_equal_to_unord)
1088 CPPUNIT_TEST(nogc_member_cmpmix_unord)
1089 CPPUNIT_TEST(nogc_member_equal_to_mix_unord)
1090 CPPUNIT_TEST(nogc_member_ic_unord)
1092 CPPUNIT_TEST_SUITE_END()
1094 } // namespace ordlist
1096 #endif // #ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H