From ffb25fcc0fbd38cd4dbe6581c2559fc2b6fa9839 Mon Sep 17 00:00:00 2001 From: Mike Krinkin Date: Sat, 28 Mar 2015 12:59:09 +0300 Subject: [PATCH] Add header tests for unordered intrusive list. This tests just a fixed version of header tests for ordered lazy list. --- projects/source.test-hdr.offsetof.mk | 6 +- .../unordered_list/hdr_intrusive_lazy.h | 347 ++++++++++++++++++ .../hdr_intrusive_lazy_nogc.cpp | 168 +++++++++ 3 files changed, 520 insertions(+), 1 deletion(-) create mode 100644 tests/test-hdr/unordered_list/hdr_intrusive_lazy.h create mode 100644 tests/test-hdr/unordered_list/hdr_intrusive_lazy_nogc.cpp diff --git a/projects/source.test-hdr.offsetof.mk b/projects/source.test-hdr.offsetof.mk index 887527e2..cca42544 100644 --- a/projects/source.test-hdr.offsetof.mk +++ b/projects/source.test-hdr.offsetof.mk @@ -66,6 +66,9 @@ CDS_TESTHDR_OFFSETOF_ORDLIST := \ tests/test-hdr/ordered_list/hdr_intrusive_michael_list_rcu_shb.cpp \ tests/test-hdr/ordered_list/hdr_intrusive_michael_list_rcu_sht.cpp +CDS_TESTHDR_OFFSETOF_UNORDLIST := \ + tests/test-hdr/unordered_list/hdr_intrusive_lazy_nogc.cpp + CDS_TESTHDR_OFFSETOF_QUEUE := \ tests/test-hdr/queue/hdr_intrusive_basketqueue_hp.cpp \ tests/test-hdr/queue/hdr_intrusive_basketqueue_dhp.cpp \ @@ -98,4 +101,5 @@ CDS_TESTHDR_OFFSETOF_SOURCES := \ $(CDS_TESTHDR_OFFSETOF_MAP) \ $(CDS_TESTHDR_OFFSETOF_SET) \ $(CDS_TESTHDR_OFFSETOF_ORDLIST) \ - $(CDS_TESTHDR_OFFSETOF_TREE) \ No newline at end of file + $(CDS_TESTHDR_OFFSETOF_UNORDLIST) \ + $(CDS_TESTHDR_OFFSETOF_TREE) diff --git a/tests/test-hdr/unordered_list/hdr_intrusive_lazy.h b/tests/test-hdr/unordered_list/hdr_intrusive_lazy.h new file mode 100644 index 00000000..f3702e4a --- /dev/null +++ b/tests/test-hdr/unordered_list/hdr_intrusive_lazy.h @@ -0,0 +1,347 @@ +//$$CDS-header$$ + +#ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H +#define CDSTEST_HDR_INTRUSIVE_LAZY_H + +#include "cppunit/cppunit_proxy.h" +#include + +namespace unordlist { + namespace ci = cds::intrusive; + namespace co = cds::opt; + + struct stat { + int nDisposeCount; + int nEnsureExistsCall; + int nEnsureNewCall; + int nFindCall; + int nEraseCall; + + stat() + : nDisposeCount(0) + , nEnsureExistsCall(0) + , nEnsureNewCall(0) + , nFindCall(0) + , nEraseCall(0) + {} + + stat( const stat& s ) + { + *this = s; + } + + stat& operator =(const stat& s) + { + memcpy( this, &s, sizeof(s)); + return *this; + } + }; + + template + struct base_int_item: public ci::lazy_list::node< GC > + { + int nKey; + int nVal; + + mutable stat s; + + base_int_item() + {} + + base_int_item(int key, int val) + : nKey( key ) + , nVal(val) + , s() + {} + + base_int_item(const base_int_item& v ) + : nKey( v.nKey ) + , nVal( v.nVal ) + , s() + {} + + const int& key() const + { + return nKey; + } + + operator int() const + { return nKey; } + }; + + template + struct member_int_item + { + int nKey; + int nVal; + + ci::lazy_list::node< GC > hMember; + + mutable stat s; + + member_int_item() + {} + + member_int_item(int key, int val) + : nKey( key ) + , nVal(val) + , s() + {} + + member_int_item(const member_int_item& v ) + : nKey( v.nKey ) + , nVal( v.nVal ) + , s() + {} + + const int& key() const + { + return nKey; + } + + operator int() const + { return nKey; } + }; + + template + struct less + { + bool operator ()(const T& v1, const T& v2 ) const + { + return v1.key() < v2.key(); + } + + template + bool operator ()(const T& v1, const Q& v2 ) const + { + return v1.key() < v2; + } + + template + bool operator ()(const Q& v1, const T& v2 ) const + { + return v1 < v2.key(); + } + }; + + template + struct cmp { + int operator ()(const T& v1, const T& v2 ) const + { + if ( v1.key() < v2.key() ) + return -1; + return v1.key() > v2.key() ? 1 : 0; + } + + template + int operator ()(const T& v1, const Q& v2 ) const + { + if ( v1.key() < v2 ) + return -1; + return v1.key() > v2 ? 1 : 0; + } + + template + int operator ()(const Q& v1, const T& v2 ) const + { + if ( v1 < v2.key() ) + return -1; + return v1 > v2.key() ? 1 : 0; + } + }; + + template + struct equal_to { + bool operator()( T const& l, T const& r ) const + { + return l.key() == r.key(); + } + + template + bool operator()( Q const& l, T const& r ) const + { + return l == r.key(); + } + + template + bool operator()( T const& l, Q const& r ) const + { + return l.key() == r; + } + }; + + struct faked_disposer + { + template + void operator ()( T * p ) + { + ++p->s.nDisposeCount; + } + }; + + struct ensure_functor + { + template + void operator ()(bool bNew, T& item, T& /*val*/ ) + { + if ( bNew ) + ++item.s.nEnsureNewCall; + else + ++item.s.nEnsureExistsCall; + } + }; + + struct find_functor + { + template + void operator ()( T& item, Q& /*val*/ ) + { + ++item.s.nFindCall; + } + }; + + class UnorderedIntrusiveLazyListHeaderTest: public CppUnitMini::TestCase + { + public: + template + void test_nogc_int() + { + typedef typename UnordList::value_type value_type; + { + value_type v1( 10, 50 ); + value_type v2( 5, 25 ); + value_type v3( 20, 100 ); + { + UnordList l; + CPPUNIT_ASSERT( l.empty() ); + + CPPUNIT_ASSERT( l.insert( v1 )); // true + CPPUNIT_ASSERT( l.find( v1.key() ) == &v1 ); + + CPPUNIT_ASSERT( v1.s.nFindCall == 0 ); + CPPUNIT_ASSERT( l.find( v1.key(), find_functor() )); + CPPUNIT_ASSERT( v1.s.nFindCall == 1 ); + + CPPUNIT_ASSERT( l.find( v3.key() ) == nullptr ); + CPPUNIT_ASSERT( !l.empty() ); + + //CPPUNIT_ASSERT( !l.insert( v1 )) ; // assertion "is_empty" is raised + + { + value_type v( v1 ); + CPPUNIT_ASSERT( !l.insert( v )) ; // false + } + + std::pair ret = l.ensure( v2, ensure_functor() ); + CPPUNIT_ASSERT( ret.first ); + CPPUNIT_ASSERT( ret.second ); + CPPUNIT_ASSERT( v2.s.nEnsureNewCall == 1 ); + CPPUNIT_ASSERT( v2.s.nEnsureExistsCall == 0 ); + + //CPPUNIT_ASSERT( !l.insert( v2 )) ; // assertion "is_empty" + + CPPUNIT_ASSERT( l.find( v1.key() ) == &v1 ) ; // true + + CPPUNIT_ASSERT( v1.s.nFindCall == 1 ); + CPPUNIT_ASSERT( l.find( v1.key(), find_functor() )); + CPPUNIT_ASSERT( v1.s.nFindCall == 2 ); + + CPPUNIT_ASSERT( !l.find( v3.key() )); + + { + value_type v( v2 ); + ret = l.ensure( v, ensure_functor() ); + + CPPUNIT_ASSERT( ret.first ); + CPPUNIT_ASSERT( !ret.second ); + CPPUNIT_ASSERT( v2.s.nEnsureExistsCall == 1 ); + CPPUNIT_ASSERT( v.s.nEnsureExistsCall == 0 && v.s.nEnsureNewCall == 0 ); + } + + CPPUNIT_ASSERT( !l.empty() ); + + CPPUNIT_ASSERT( l.insert( v3 )) ; // true + CPPUNIT_ASSERT( l.find( v3.key() ) == &v3 ); + + CPPUNIT_ASSERT( v3.s.nFindCall == 0 ); + CPPUNIT_ASSERT( l.find( v3.key(), find_functor() )); + CPPUNIT_ASSERT( v3.s.nFindCall == 1 ); + + { + typename UnordList::iterator it = l.begin(); + typename UnordList::const_iterator cit = l.cbegin(); + CPPUNIT_ASSERT( it != l.end() ); + CPPUNIT_ASSERT( it != l.cend() ); + CPPUNIT_ASSERT( cit != l.end() ); + CPPUNIT_ASSERT( cit != l.cend() ); + CPPUNIT_ASSERT( cit == it ); + + CPPUNIT_ASSERT( it->nKey == v1.nKey ); + CPPUNIT_ASSERT( it->nVal == v1.nVal ); + CPPUNIT_ASSERT( ++it != l.end() ); + CPPUNIT_ASSERT( it->nKey == v2.nKey ); + CPPUNIT_ASSERT( it->nVal == v2.nVal ); + CPPUNIT_ASSERT( it++ != l.end() ); + CPPUNIT_ASSERT( it->nKey == v3.nKey ); + CPPUNIT_ASSERT( it->nVal == v3.nVal ); + CPPUNIT_ASSERT( it++ != l.end() ); + CPPUNIT_ASSERT( it == l.end() ); + } + + { + UnordList const & lref = l; + typename UnordList::const_iterator it = lref.begin(); + CPPUNIT_ASSERT( it != l.end() ); + CPPUNIT_ASSERT( it->nKey == v1.nKey ); + CPPUNIT_ASSERT( it->nVal == v1.nVal ); + CPPUNIT_ASSERT( ++it != lref.end() ); + CPPUNIT_ASSERT( it->nKey == v2.nKey ); + CPPUNIT_ASSERT( it->nVal == v2.nVal ); + CPPUNIT_ASSERT( it++ != l.end() ); + CPPUNIT_ASSERT( it->nKey == v3.nKey ); + CPPUNIT_ASSERT( it->nVal == v3.nVal ); + CPPUNIT_ASSERT( it++ != lref.end() ); + CPPUNIT_ASSERT( it == l.end() ); + } + } + + // Disposer called on list destruction + CPPUNIT_ASSERT( v1.s.nDisposeCount == 1 ); + CPPUNIT_ASSERT( v2.s.nDisposeCount == 1 ); + CPPUNIT_ASSERT( v3.s.nDisposeCount == 1 ); + } + } + + void nogc_base_cmp(); + void nogc_base_less(); + void nogc_base_equal_to(); + void nogc_base_cmpmix(); + void nogc_base_equal_to_mix(); + void nogc_base_ic(); + void nogc_member_cmp(); + void nogc_member_less(); + void nogc_member_equal_to(); + void nogc_member_cmpmix(); + void nogc_member_equal_to_mix(); + void nogc_member_ic(); + + CPPUNIT_TEST_SUITE(UnorderedIntrusiveLazyListHeaderTest) + + CPPUNIT_TEST(nogc_base_cmp) + CPPUNIT_TEST(nogc_base_less) + CPPUNIT_TEST(nogc_base_equal_to) + CPPUNIT_TEST(nogc_base_cmpmix) + CPPUNIT_TEST(nogc_base_equal_to_mix) + CPPUNIT_TEST(nogc_base_ic) + CPPUNIT_TEST(nogc_member_cmp) + CPPUNIT_TEST(nogc_member_less) + CPPUNIT_TEST(nogc_member_equal_to) + CPPUNIT_TEST(nogc_member_cmpmix) + CPPUNIT_TEST(nogc_member_equal_to_mix) + CPPUNIT_TEST(nogc_member_ic) + + CPPUNIT_TEST_SUITE_END() + }; +} // namespace unordlist + +#endif // #ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H diff --git a/tests/test-hdr/unordered_list/hdr_intrusive_lazy_nogc.cpp b/tests/test-hdr/unordered_list/hdr_intrusive_lazy_nogc.cpp new file mode 100644 index 00000000..d519e602 --- /dev/null +++ b/tests/test-hdr/unordered_list/hdr_intrusive_lazy_nogc.cpp @@ -0,0 +1,168 @@ +//$$CDS-header$$ + +#include "unordered_list/hdr_intrusive_lazy.h" +#include + +namespace unordlist { + namespace { + typedef base_int_item< cds::gc::nogc > base_item; + typedef member_int_item< cds::gc::nogc > member_item; + + struct cmp_traits : public ci::lazy_list::traits { + typedef ci::lazy_list::base_hook< co::gc > hook; + typedef unordlist::cmp compare; + typedef faked_disposer disposer; + static const bool sort = false; + }; + + struct less_traits: public ci::lazy_list::traits { + typedef ci::lazy_list::base_hook< co::gc > hook; + typedef unordlist::less less; + typedef faked_disposer disposer; + static const bool sort = false; + }; + + struct equal_to_traits: public ci::lazy_list::traits { + typedef ci::lazy_list::base_hook< co::gc > hook; + typedef unordlist::equal_to equal_to; + typedef faked_disposer disposer; + static const bool sort = false; + }; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::base_hook< co::gc > > + ,co::less< less > + ,co::compare< cmp > + ,ci::opt::disposer< faked_disposer > + ,co::sort< false > >::type cmpmix_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::base_hook< co::gc > > + ,co::compare< cmp > + ,co::equal_to< equal_to > + ,ci::opt::disposer< faked_disposer > + ,co::sort< false > >::type equal_to_mix_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::base_hook< co::gc > > + ,co::equal_to< equal_to > + ,ci::opt::disposer< faked_disposer > + ,co::item_counter< cds::atomicity::item_counter > + ,co::sort< false > >::type ic_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::member_hook< + offsetof( member_item, hMember ) + ,co::gc > > + ,co::compare< cmp > + ,ci::opt::disposer< faked_disposer > + ,co::sort< false > >::type member_cmp_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::member_hook< + offsetof( member_item, hMember ) + ,co::gc > > + ,co::less< less > + ,ci::opt::disposer< faked_disposer > + ,co::sort< false > >::type member_less_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::member_hook< + offsetof( member_item, hMember ) + ,co::gc > > + ,co::equal_to< equal_to > + ,ci::opt::disposer< faked_disposer > + ,co::sort< false > >::type member_equal_to_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::member_hook< + offsetof( member_item, hMember ) + ,co::gc > > + ,co::less< less > + ,co::compare< cmp > + ,ci::opt::disposer< faked_disposer > + ,co::sort< false > >::type member_cmpmix_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::member_hook< + offsetof( member_item, hMember ) + ,co::gc > > + ,co::compare< cmp > + ,co::equal_to< equal_to > + ,ci::opt::disposer< faked_disposer > + ,co::sort< false > >::type member_equal_to_mix_traits; + + typedef typename ci::lazy_list::make_traits< + ci::opt::hook< ci::lazy_list::member_hook< + offsetof( member_item, hMember ), + co::gc > > + ,co::equal_to< equal_to > + ,ci::opt::disposer< faked_disposer > + ,co::item_counter< cds::atomicity::item_counter > + ,co::sort< false > >::type member_ic_traits; + + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_base_cmp() + { + typedef ci::LazyList< cds::gc::nogc, base_item, cmp_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_base_less() + { + typedef ci::LazyList< cds::gc::nogc, base_item, less_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_base_equal_to() + { + typedef ci::LazyList< cds::gc::nogc, base_item, equal_to_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_base_cmpmix() + { + typedef ci::LazyList< cds::gc::nogc, base_item, cmpmix_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_base_equal_to_mix() + { + typedef ci::LazyList< cds::gc::nogc, base_item, equal_to_mix_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_base_ic() + { + typedef ci::LazyList< cds::gc::nogc, base_item, ic_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_member_cmp() + { + typedef ci::LazyList< cds::gc::nogc, member_item, member_cmp_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_member_less() + { + typedef ci::LazyList< cds::gc::nogc, member_item, member_less_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_member_equal_to() + { + typedef ci::LazyList< cds::gc::nogc, member_item, member_equal_to_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_member_cmpmix() + { + typedef ci::LazyList< cds::gc::nogc, member_item, member_cmpmix_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_member_equal_to_mix() + { + typedef ci::LazyList< cds::gc::nogc, member_item, member_equal_to_mix_traits > list; + test_nogc_int(); + } + void UnorderedIntrusiveLazyListHeaderTest::nogc_member_ic() + { + typedef ci::LazyList< cds::gc::nogc, member_item, member_ic_traits > list; + test_nogc_int(); + } + +} // namespace unordlist + +CPPUNIT_TEST_SUITE_REGISTRATION(unordlist::UnorderedIntrusiveLazyListHeaderTest); -- 2.34.1