Add header tests for unordered intrusive list.
authorMike Krinkin <krinkin.m.u@gmail.com>
Sat, 28 Mar 2015 09:59:09 +0000 (12:59 +0300)
committerMike Krinkin <krinkin.m.u@gmail.com>
Sat, 28 Mar 2015 11:24:28 +0000 (14:24 +0300)
This tests just a fixed version of header tests for ordered lazy
list.

projects/source.test-hdr.offsetof.mk
tests/test-hdr/unordered_list/hdr_intrusive_lazy.h [new file with mode: 0644]
tests/test-hdr/unordered_list/hdr_intrusive_lazy_nogc.cpp [new file with mode: 0644]

index 887527e20af41d2d5f7bf446a0e61f647bf89aef..cca42544a53f31eee02b64bff8d2949a29b4a89e 100644 (file)
@@ -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 (file)
index 0000000..f3702e4
--- /dev/null
@@ -0,0 +1,347 @@
+//$$CDS-header$$
+
+#ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H
+#define CDSTEST_HDR_INTRUSIVE_LAZY_H
+
+#include "cppunit/cppunit_proxy.h"
+#include <cds/intrusive/details/lazy_list_base.h>
+
+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 <typename GC>
+    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 <typename GC>
+    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 <typename T>
+    struct less
+    {
+        bool operator ()(const T& v1, const T& v2 ) const
+        {
+            return v1.key() < v2.key();
+        }
+
+        template <typename Q>
+        bool operator ()(const T& v1, const Q& v2 ) const
+        {
+            return v1.key() < v2;
+        }
+
+        template <typename Q>
+        bool operator ()(const Q& v1, const T& v2 ) const
+        {
+            return v1 < v2.key();
+        }
+    };
+
+    template <typename T>
+    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 <typename Q>
+        int operator ()(const T& v1, const Q& v2 ) const
+        {
+            if ( v1.key() < v2 )
+                return -1;
+            return v1.key() > v2 ? 1 : 0;
+        }
+
+        template <typename Q>
+        int operator ()(const Q& v1, const T& v2 ) const
+        {
+            if ( v1 < v2.key() )
+                return -1;
+            return v1 > v2.key() ? 1 : 0;
+        }
+    };
+
+    template <typename T>
+    struct equal_to {
+        bool operator()( T const& l, T const& r ) const
+        {
+            return l.key() == r.key();
+        }
+
+        template <typename Q>
+        bool operator()( Q const& l, T const& r ) const
+        {
+            return l == r.key();
+        }
+
+        template <typename Q>
+        bool operator()( T const& l, Q const& r ) const
+        {
+            return l.key() == r;
+        }
+    };
+
+    struct faked_disposer
+    {
+        template <typename T>
+        void operator ()( T * p )
+        {
+            ++p->s.nDisposeCount;
+        }
+    };
+
+    struct ensure_functor
+    {
+        template <typename T>
+        void operator ()(bool bNew, T& item, T& /*val*/ )
+        {
+            if ( bNew )
+                ++item.s.nEnsureNewCall;
+            else
+                ++item.s.nEnsureExistsCall;
+        }
+    };
+
+    struct find_functor
+    {
+        template <typename T, typename Q>
+        void operator ()( T& item, Q& /*val*/ )
+        {
+            ++item.s.nFindCall;
+        }
+    };
+
+    class UnorderedIntrusiveLazyListHeaderTest: public CppUnitMini::TestCase
+    {
+    public:
+        template <class UnordList>
+        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<bool, bool> 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 (file)
index 0000000..d519e60
--- /dev/null
@@ -0,0 +1,168 @@
+//$$CDS-header$$
+
+#include "unordered_list/hdr_intrusive_lazy.h"
+#include <cds/intrusive/lazy_list_nogc.h>
+
+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<cds::gc::nogc> > hook;
+            typedef unordlist::cmp<base_item> 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<cds::gc::nogc> > hook;
+            typedef unordlist::less<base_item> 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<cds::gc::nogc> > hook;
+            typedef unordlist::equal_to<base_item> 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<cds::gc::nogc> > >
+            ,co::less< less<base_item> >
+            ,co::compare< cmp<base_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::compare< cmp<base_item> >
+            ,co::equal_to< equal_to<base_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::equal_to< equal_to<base_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::compare< cmp<member_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::less< less<member_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::equal_to< equal_to<member_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::less< less<member_item> >
+            ,co::compare< cmp<member_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::compare< cmp<member_item> >
+            ,co::equal_to< equal_to<member_item> >
+            ,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<cds::gc::nogc> > >
+            ,co::equal_to< equal_to<member_item> >
+            ,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<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_base_less()
+    {
+        typedef ci::LazyList< cds::gc::nogc, base_item, less_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_base_equal_to()
+    {
+        typedef ci::LazyList< cds::gc::nogc, base_item, equal_to_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_base_cmpmix()
+    {
+        typedef ci::LazyList< cds::gc::nogc, base_item, cmpmix_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_base_equal_to_mix()
+    {
+        typedef ci::LazyList< cds::gc::nogc, base_item, equal_to_mix_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_base_ic()
+    {
+        typedef ci::LazyList< cds::gc::nogc, base_item, ic_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_member_cmp()
+    {
+        typedef ci::LazyList< cds::gc::nogc, member_item, member_cmp_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_member_less()
+    {
+        typedef ci::LazyList< cds::gc::nogc, member_item, member_less_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_member_equal_to()
+    {
+        typedef ci::LazyList< cds::gc::nogc, member_item, member_equal_to_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_member_cmpmix()
+    {
+        typedef ci::LazyList< cds::gc::nogc, member_item, member_cmpmix_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_member_equal_to_mix()
+    {
+        typedef ci::LazyList< cds::gc::nogc, member_item, member_equal_to_mix_traits > list;
+        test_nogc_int<list>();
+    }
+    void UnorderedIntrusiveLazyListHeaderTest::nogc_member_ic()
+    {
+        typedef ci::LazyList< cds::gc::nogc, member_item, member_ic_traits > list;
+        test_nogc_int<list>();
+    }
+
+} // namespace unordlist
+
+CPPUNIT_TEST_SUITE_REGISTRATION(unordlist::UnorderedIntrusiveLazyListHeaderTest);