Add tests for unordered nonintrusive and kv lists.
authorMike Krinkin <krinkin.m.u@gmail.com>
Sat, 28 Mar 2015 10:04:02 +0000 (13:04 +0300)
committerMike Krinkin <krinkin.m.u@gmail.com>
Sat, 28 Mar 2015 11:24:43 +0000 (14:24 +0300)
These tests just rewritten version of similar test for ordered
nonintrusive and key-value lists.

projects/source.test-hdr.mk
tests/test-hdr/unordered_list/hdr_lazy.h [new file with mode: 0644]
tests/test-hdr/unordered_list/hdr_lazy_kv.h [new file with mode: 0644]
tests/test-hdr/unordered_list/hdr_lazy_kv_nogc.cpp [new file with mode: 0644]
tests/test-hdr/unordered_list/hdr_lazy_nogc.cpp [new file with mode: 0644]

index 349bde712c0c50a08582005323d2b16929d0bfae..7f6a46b7c188cc8723a68039157e8cdfb76f59f6 100644 (file)
@@ -94,6 +94,10 @@ CDS_TESTHDR_ORDLIST := \
     tests/test-hdr/ordered_list/hdr_michael_kv_rcu_shb.cpp \
     tests/test-hdr/ordered_list/hdr_michael_kv_rcu_sht.cpp
 
+CDS_TESTHDR_UNORDLIST := \
+    tests/test-hdr/unordered_list/hdr_lazy_nogc.cpp \
+    tests/test-hdr/unordered_list/hdr_lazy_kv_nogc.cpp
+
 CDS_TESTHDR_PQUEUE := \
     tests/test-hdr/priority_queue/hdr_intrusive_mspqueue_dyn.cpp \
     tests/test-hdr/priority_queue/hdr_intrusive_mspqueue_static.cpp \
@@ -276,7 +280,8 @@ CDS_TESTHDR_SOURCES := \
     $(CDS_TESTHDR_MAP) \
     $(CDS_TESTHDR_DEQUE) \
     $(CDS_TESTHDR_ORDLIST) \
+    $(CDS_TESTHDR_UNORDLIST) \
     $(CDS_TESTHDR_SET) \
     $(CDS_TESTHDR_TREE) \
     $(CDS_TESTHDR_MISC)
-    
\ No newline at end of file
+    
diff --git a/tests/test-hdr/unordered_list/hdr_lazy.h b/tests/test-hdr/unordered_list/hdr_lazy.h
new file mode 100644 (file)
index 0000000..2c6ae89
--- /dev/null
@@ -0,0 +1,233 @@
+//$$CDS-header$$
+
+#ifndef CDSTEST_HDR_LAZY_H
+#define CDSTEST_HDR_LAZY_H
+
+#include "cppunit/cppunit_proxy.h"
+#include <cds/container/details/lazy_list_base.h>
+
+namespace unordlist {
+    namespace cc = cds::container;
+    namespace co = cds::container::opt;
+
+    class UnorderedLazyListTestHeader: public CppUnitMini::TestCase
+    {
+    public:
+        struct stat {
+            int nEnsureExistsCall;
+            int nEnsureNewCall;
+
+            stat()
+            {
+                nEnsureExistsCall
+                    = nEnsureNewCall
+                    = 0;
+            }
+        };
+
+        struct item {
+            int     nKey;
+            int     nVal;
+
+            stat    s;
+
+            item(int key)
+                : nKey( key )
+                , nVal( key * 2 )
+                , s()
+            {}
+
+            item(int key, int val)
+                : nKey( key )
+                , nVal(val)
+                , s()
+            {}
+
+            item( item const& v )
+                : nKey( v.nKey )
+                , nVal( v.nVal )
+                , s()
+            {}
+
+            int key() const
+            {
+                return nKey;
+            }
+        };
+
+        template <typename T>
+        struct lt
+        {
+            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 {
+            int operator ()(const T& v1, const T& v2 ) const
+            {
+                return v1.key() == v2.key();
+            }
+
+            template <typename Q>
+            int operator ()(const T& v1, const Q& v2 ) const
+            {
+                return v1.key() == v2;
+            }
+
+            template <typename Q>
+            int operator ()(const Q& v1, const T& v2 ) const
+            {
+                return v1 == v2.key();
+            }
+        };
+
+    protected:
+        template <class UnordList>
+        void nogc_test()
+        {
+            typedef UnordList list;
+            typedef typename list::value_type    value_type;
+            typedef std::pair<typename list::iterator, bool> ensure_result;
+
+            typename list::iterator it;
+
+            list l;
+            CPPUNIT_ASSERT( l.empty() );
+            CPPUNIT_ASSERT( l.insert(50) != l.end() );
+            CPPUNIT_ASSERT( !l.empty() );
+
+            ensure_result eres = l.ensure( item(100, 33) );
+            CPPUNIT_ASSERT( eres.second );
+            CPPUNIT_ASSERT( eres.first != l.end() );
+            CPPUNIT_ASSERT( l.insert( item(150) ) != l.end() );
+
+            CPPUNIT_ASSERT( l.insert(100) == l.end() );
+            eres = l.ensure( item(50, 33) );
+            CPPUNIT_ASSERT( !eres.second );
+            CPPUNIT_ASSERT( eres.first->nVal == eres.first->nKey * 2 );
+            eres.first->nVal = 63;
+
+            it = l.find( 33 );
+            CPPUNIT_ASSERT( it == l.end() );
+
+            it = l.find( 50 );
+            CPPUNIT_ASSERT( it != l.end() );
+            CPPUNIT_ASSERT( it->nKey == 50 );
+            CPPUNIT_ASSERT( it->nVal == 63 );
+
+            it = l.find( 100 );
+            CPPUNIT_ASSERT( it != l.end() );
+            CPPUNIT_ASSERT( it->nKey == 100 );
+            CPPUNIT_ASSERT( it->nVal == 33 );
+
+            CPPUNIT_ASSERT( !l.empty() );
+            l.clear();
+            CPPUNIT_ASSERT( l.empty() );
+
+            // insert test
+            CPPUNIT_ASSERT( l.emplace( 501 ) != l.end());
+            CPPUNIT_ASSERT( l.emplace( 251, 152 ) != l.end());
+            CPPUNIT_ASSERT( l.emplace( item( 1001 )) != l.end());
+
+            // insert failed - such key exists
+            CPPUNIT_ASSERT( l.emplace( 501, 2 ) == l.end());
+            CPPUNIT_ASSERT( l.emplace( 251, 10) == l.end());
+
+            it = l.find( 501 );
+            CPPUNIT_ASSERT( it != l.end() );
+            CPPUNIT_ASSERT( it->nKey == 501 );
+            CPPUNIT_ASSERT( it->nVal == 501 * 2 );
+
+            it = l.find( 1001 );
+            CPPUNIT_ASSERT( it != l.end() );
+            CPPUNIT_ASSERT( it->nKey == 1001 );
+            CPPUNIT_ASSERT( it->nVal == 1001 * 2 );
+
+            {
+                typename UnordList::iterator it( l.begin() );
+                typename UnordList::const_iterator cit( l.cbegin() );
+                CPPUNIT_CHECK( it == cit );
+                CPPUNIT_CHECK( it != l.end() );
+                CPPUNIT_CHECK( it != l.cend() );
+                CPPUNIT_CHECK( cit != l.end() );
+                CPPUNIT_CHECK( cit != l.cend() );
+                ++it;
+                CPPUNIT_CHECK( it != cit );
+                CPPUNIT_CHECK( it != l.end() );
+                CPPUNIT_CHECK( it != l.cend() );
+                CPPUNIT_CHECK( cit != l.end() );
+                CPPUNIT_CHECK( cit != l.cend() );
+                ++cit;
+                CPPUNIT_CHECK( it == cit );
+                CPPUNIT_CHECK( it != l.end() );
+                CPPUNIT_CHECK( it != l.cend() );
+                CPPUNIT_CHECK( cit != l.end() );
+                CPPUNIT_CHECK( cit != l.cend() );
+            }
+
+
+            l.clear();
+            CPPUNIT_ASSERT( l.empty() );
+        }
+
+        void NOGC_cmp();
+        void NOGC_less();
+        void NOGC_equal_to();
+        void NOGC_cmpmix();
+        void NOGC_equal_to_mix();
+        void NOGC_ic();
+
+        CPPUNIT_TEST_SUITE(UnorderedLazyListTestHeader)
+            CPPUNIT_TEST(NOGC_cmp)
+            CPPUNIT_TEST(NOGC_less)
+            CPPUNIT_TEST(NOGC_equal_to)
+            CPPUNIT_TEST(NOGC_cmpmix)
+            CPPUNIT_TEST(NOGC_equal_to_mix)
+            CPPUNIT_TEST(NOGC_ic)
+        CPPUNIT_TEST_SUITE_END()
+    };
+
+}   // namespace unordlist
+
+#endif // #ifndef CDSTEST_HDR_LAZY_H
diff --git a/tests/test-hdr/unordered_list/hdr_lazy_kv.h b/tests/test-hdr/unordered_list/hdr_lazy_kv.h
new file mode 100644 (file)
index 0000000..cf3c4d2
--- /dev/null
@@ -0,0 +1,263 @@
+//$$CDS-header$$
+
+#ifndef CDSTEST_HDR_LAZY_KV_H
+#define CDSTEST_HDR_LAZY_KV_H
+
+#include "cppunit/cppunit_proxy.h"
+#include <cds/container/details/lazy_list_base.h>
+
+namespace unordlist {
+    namespace cc = cds::container;
+    namespace co = cds::container::opt;
+
+    class UnorderedLazyKVListTestHeader: public CppUnitMini::TestCase
+    {
+    public:
+        typedef int key_type;
+        struct value_type {
+            int m_val;
+
+            value_type()
+                : m_val(0)
+            {}
+
+            value_type( int n )
+                : m_val( n )
+            {}
+        };
+
+        template <typename T>
+        struct lt
+        {
+            bool operator ()(const T& v1, const T& v2 ) const
+            {
+                return v1 < v2;
+            }
+        };
+
+        template <typename T>
+        struct cmp {
+            int operator ()(const T& v1, const T& v2 ) const
+            {
+                if ( v1 < v2 )
+                    return -1;
+                return v1 > v2 ? 1 : 0;
+            }
+        };
+
+        template <typename T>
+        struct eq {
+            bool operator ()(const T& v1, const T& v2 ) const
+            {
+                return v1 == v2;
+            }
+        };
+
+        struct insert_functor {
+            template <typename T>
+            void operator()( T& pair )
+            {
+                pair.second.m_val = pair.first * 10;
+            }
+        };
+
+    protected:
+        template <class UnordList>
+        void nogc_test()
+        {
+            typedef typename UnordList::value_type    value_type;
+            typedef typename UnordList::iterator      iterator;
+
+            {
+                UnordList l;
+                iterator it;
+
+                CPPUNIT_ASSERT( l.empty() );
+
+                // insert / find test
+                CPPUNIT_ASSERT( l.find( 100 ) == l.end() );
+                CPPUNIT_ASSERT( l.insert( 100 ) != l.end() );
+                CPPUNIT_ASSERT( !l.empty() );
+                it = l.find( 100 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 100 );
+                CPPUNIT_ASSERT( it.val().m_val == 0 );
+
+                CPPUNIT_ASSERT( l.insert( 50, 500 ) != l.end());
+                it = l.find( 50 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 50 );
+                CPPUNIT_ASSERT( it.val().m_val == 500 );
+
+                CPPUNIT_ASSERT( l.insert( 50, 5 ) == l.end() );
+                it = l.find( 50 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 50 );
+                CPPUNIT_ASSERT( it.val().m_val == 500 );
+                CPPUNIT_ASSERT( !l.empty() );
+
+                CPPUNIT_ASSERT( l.find( 150 ) == l.end() );
+                CPPUNIT_ASSERT( l.insert_with( 150, insert_functor() ) != l.end() );
+                it = l.find( 150 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 150 );
+                CPPUNIT_ASSERT( it.val().m_val == 1500 );
+                it = l.find( 100 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 100 );
+                CPPUNIT_ASSERT( it.val().m_val == 0 );
+                it = l.find( 50 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 50 );
+                CPPUNIT_ASSERT( it.val().m_val == 500 );
+                it.val().m_val = 25;
+                it = l.find( 50 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 50 );
+                CPPUNIT_ASSERT( it.val().m_val == 25 );
+                CPPUNIT_ASSERT( !l.empty() );
+
+                // ensure existing item
+                std::pair<iterator, bool> ensureResult;
+                ensureResult = l.ensure( 100 );
+                CPPUNIT_ASSERT( !ensureResult.second );
+                CPPUNIT_ASSERT( ensureResult.first.key() == 100 );
+                CPPUNIT_ASSERT( ensureResult.first.val().m_val == 0   );
+                ensureResult.first.val().m_val = 5;
+                it = l.find( 100 );
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 100 );
+                CPPUNIT_ASSERT( it.val().m_val == 5 );
+
+                CPPUNIT_ASSERT( !l.empty() );
+
+                // ensure new item
+                ensureResult = l.ensure( 1000 );
+                CPPUNIT_ASSERT( ensureResult.second );
+                CPPUNIT_ASSERT( ensureResult.first.key() == 1000 );
+                CPPUNIT_ASSERT( ensureResult.first.val().m_val == 0   );
+                ensureResult.first.val().m_val = 33;
+                ensureResult = l.ensure( 1000 );
+                CPPUNIT_ASSERT( !ensureResult.second );
+                CPPUNIT_ASSERT( ensureResult.first.key() == 1000 );
+                CPPUNIT_ASSERT( ensureResult.first.val().m_val == 33   );
+
+                // clear test
+                l.clear();
+                CPPUNIT_ASSERT( l.empty() );
+
+                // insert test
+                CPPUNIT_ASSERT( l.emplace( 501 ) != l.end());
+                CPPUNIT_ASSERT( l.emplace( 251, 152 ) != l.end());
+
+                // insert failed - such key exists
+                CPPUNIT_ASSERT( l.emplace( 501, 2 ) == l.end());
+                CPPUNIT_ASSERT( l.emplace( 251, 10) == l.end());
+
+                it = l.find(501);
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 501 );
+                CPPUNIT_ASSERT( it.val().m_val == 0 );
+
+                it = l.find(251);
+                CPPUNIT_ASSERT( it != l.end() );
+                CPPUNIT_ASSERT( it.key() == 251 );
+                CPPUNIT_ASSERT( it.val().m_val == 152 );
+
+                l.clear();
+                CPPUNIT_ASSERT( l.empty() );
+
+                // Iterator test
+                {
+                    int nCount = 100;
+                    for ( int i = 0; i < nCount; ++i )
+                        CPPUNIT_ASSERT( l.insert(i, i * 2 ) != l.end() );
+
+                    {
+                        typename UnordList::iterator it( l.begin() );
+                        typename UnordList::const_iterator cit( l.cbegin() );
+                        CPPUNIT_CHECK( it == cit );
+                        CPPUNIT_CHECK( it != l.end() );
+                        CPPUNIT_CHECK( it != l.cend() );
+                        CPPUNIT_CHECK( cit != l.end() );
+                        CPPUNIT_CHECK( cit != l.cend() );
+                        ++it;
+                        CPPUNIT_CHECK( it != cit );
+                        CPPUNIT_CHECK( it != l.end() );
+                        CPPUNIT_CHECK( it != l.cend() );
+                        CPPUNIT_CHECK( cit != l.end() );
+                        CPPUNIT_CHECK( cit != l.cend() );
+                        ++cit;
+                        CPPUNIT_CHECK( it == cit );
+                        CPPUNIT_CHECK( it != l.end() );
+                        CPPUNIT_CHECK( it != l.cend() );
+                        CPPUNIT_CHECK( cit != l.end() );
+                        CPPUNIT_CHECK( cit != l.cend() );
+                    }
+
+                    int i = 0;
+                    for ( typename UnordList::iterator iter = l.begin(), itEnd = l.end(); iter != itEnd; ++iter, ++i ) {
+                        CPPUNIT_ASSERT( iter.key() == i );
+                        CPPUNIT_ASSERT( iter->first == i );
+                        CPPUNIT_ASSERT( (*iter).first == i );
+
+                        CPPUNIT_ASSERT( iter.val().m_val == i * 2 );
+                        CPPUNIT_ASSERT( iter->second.m_val == i * 2 );
+                        CPPUNIT_ASSERT( (*iter).second.m_val == i * 2 );
+
+                        iter.val().m_val = i * 3;
+                    }
+
+                    // Check that we have visited all items
+                    for ( int i = 0; i < nCount; ++i ) {
+                        it = l.find( i );
+                        CPPUNIT_ASSERT( it != l.end() );
+                        CPPUNIT_ASSERT( it.key() == i );
+                        CPPUNIT_ASSERT( it.val().m_val == i * 3 );
+                    }
+
+                    l.clear();
+                    CPPUNIT_ASSERT( l.empty() );
+
+                    // Const iterator
+                    for ( int i = 0; i < nCount; ++i )
+                        CPPUNIT_ASSERT( l.insert(i, i * 7) != l.end() );
+
+                    i = 0;
+                    const UnordList& rl = l;
+                    for ( typename UnordList::const_iterator iter = rl.begin(), itEnd = rl.end(); iter != itEnd; ++iter, ++i ) {
+                        CPPUNIT_ASSERT( iter.key() == i );
+                        CPPUNIT_ASSERT( iter->first == i );
+                        CPPUNIT_ASSERT( (*iter).first == i );
+
+                        CPPUNIT_ASSERT( iter.val().m_val == i * 7 );
+                        CPPUNIT_ASSERT( iter->second.m_val == i * 7 );
+                        CPPUNIT_ASSERT( (*iter).second.m_val == i * 7 );
+                        // it.val().m_val = i * 3    ; // error: const-iterator
+                    }
+
+                    l.clear();
+                    CPPUNIT_ASSERT( l.empty() );
+                }
+
+            }
+        }
+
+        void NOGC_cmp();
+        void NOGC_less();
+        void NOGC_equal_to();
+        void NOGC_cmpmix();
+        void NOGC_ic();
+
+        CPPUNIT_TEST_SUITE(UnorderedLazyKVListTestHeader)
+            CPPUNIT_TEST(NOGC_cmp)
+            CPPUNIT_TEST(NOGC_less)
+            CPPUNIT_TEST(NOGC_equal_to)
+            CPPUNIT_TEST(NOGC_cmpmix)
+            CPPUNIT_TEST(NOGC_ic)
+        CPPUNIT_TEST_SUITE_END()
+    };
+
+}   // namespace unordlist
+
+#endif // #ifndef CDSTEST_HDR_LAZY_KV_H
diff --git a/tests/test-hdr/unordered_list/hdr_lazy_kv_nogc.cpp b/tests/test-hdr/unordered_list/hdr_lazy_kv_nogc.cpp
new file mode 100644 (file)
index 0000000..66e0179
--- /dev/null
@@ -0,0 +1,132 @@
+//$$CDS-header$$
+
+#include "unordered_list/hdr_lazy_kv.h"
+#include <cds/container/lazy_kvlist_nogc.h>
+
+namespace unordlist {
+    namespace {
+        struct NOGC_cmp_traits: public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyKVListTestHeader::cmp<UnorderedLazyKVListTestHeader::key_type>   compare;
+            static const bool sort = false;
+        };
+
+    }
+    void UnorderedLazyKVListTestHeader::NOGC_cmp()
+    {
+        // traits-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type, NOGC_cmp_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyKVList< cds::gc::nogc,
+            key_type,
+            value_type,
+            cc::lazy_list::make_traits<
+                cc::opt::compare< cmp<key_type> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_less_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyKVListTestHeader::lt<UnorderedLazyKVListTestHeader::key_type>   less;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyKVListTestHeader::NOGC_less()
+    {
+        // traits-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type, NOGC_less_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type,
+            cc::lazy_list::make_traits<
+                cc::opt::less< lt<key_type> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_equal_to_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyKVListTestHeader::eq<UnorderedLazyKVListTestHeader::key_type>   equal_to;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyKVListTestHeader::NOGC_equal_to()
+    {
+        // traits-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type, NOGC_equal_to_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type,
+            cc::lazy_list::make_traits<
+                cc::opt::equal_to< eq<key_type> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_cmpmix_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyKVListTestHeader::cmp<UnorderedLazyKVListTestHeader::key_type>   compare;
+            typedef UnorderedLazyKVListTestHeader::lt<UnorderedLazyKVListTestHeader::key_type>  less;
+            typedef UnorderedLazyKVListTestHeader::eq<UnorderedLazyKVListTestHeader::key_type>   equal_to;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyKVListTestHeader::NOGC_cmpmix()
+    {
+        // traits-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type, NOGC_cmpmix_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type,
+            cc::lazy_list::make_traits<
+                cc::opt::compare< cmp<key_type> >
+                ,cc::opt::less< lt<key_type> >
+                ,cc::opt::equal_to< eq<key_type> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_ic_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyKVListTestHeader::eq<UnorderedLazyKVListTestHeader::key_type>   equal_to;
+            typedef cds::atomicity::item_counter item_counter;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyKVListTestHeader::NOGC_ic()
+    {
+        // traits-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type, NOGC_ic_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyKVList< cds::gc::nogc, key_type, value_type,
+            cc::lazy_list::make_traits<
+                cc::opt::equal_to< eq<key_type> >
+                ,cc::opt::item_counter< cds::atomicity::item_counter >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+}   // namespace unordlist
+CPPUNIT_TEST_SUITE_REGISTRATION(unordlist::UnorderedLazyKVListTestHeader);
diff --git a/tests/test-hdr/unordered_list/hdr_lazy_nogc.cpp b/tests/test-hdr/unordered_list/hdr_lazy_nogc.cpp
new file mode 100644 (file)
index 0000000..c1538ab
--- /dev/null
@@ -0,0 +1,153 @@
+//$$CDS-header$$
+
+#include "unordered_list/hdr_lazy.h"
+#include <cds/container/lazy_list_nogc.h>
+
+namespace unordlist {
+    namespace {
+        struct NOGC_cmp_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyListTestHeader::cmp<UnorderedLazyListTestHeader::item>   compare;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyListTestHeader::NOGC_cmp()
+    {
+        // traits-based version
+        typedef cc::LazyList< cds::gc::nogc, item, NOGC_cmp_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyList< cds::gc::nogc, item,
+            cc::lazy_list::make_traits<
+                cc::opt::compare< cmp<item> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_less_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyListTestHeader::lt<UnorderedLazyListTestHeader::item>   less;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyListTestHeader::NOGC_less()
+    {
+        // traits-based version
+        typedef cc::LazyList< cds::gc::nogc, item, NOGC_less_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyList< cds::gc::nogc, item,
+            cc::lazy_list::make_traits<
+                cc::opt::less< lt<item> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_equal_to_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyListTestHeader::equal_to<UnorderedLazyListTestHeader::item> equal_to;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyListTestHeader::NOGC_equal_to()
+    {
+        // traits-based version
+        typedef cc::LazyList< cds::gc::nogc, item, NOGC_equal_to_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyList< cds::gc::nogc, item,
+            cc::lazy_list::make_traits<
+                cc::opt::equal_to< equal_to<item> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_cmpmix_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyListTestHeader::cmp<UnorderedLazyListTestHeader::item>   compare;
+            typedef UnorderedLazyListTestHeader::lt<UnorderedLazyListTestHeader::item>  less;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyListTestHeader::NOGC_cmpmix()
+    {
+        // traits-based version
+        typedef cc::LazyList< cds::gc::nogc, item, NOGC_cmpmix_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyList< cds::gc::nogc, item,
+            cc::lazy_list::make_traits<
+                cc::opt::compare< cmp<item> >
+                ,cc::opt::less< lt<item> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+    namespace {
+        struct NOGC_equal_to_mix_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyListTestHeader::cmp<UnorderedLazyListTestHeader::item> compare;
+            typedef UnorderedLazyListTestHeader::lt<UnorderedLazyListTestHeader::item> less;
+            typedef UnorderedLazyListTestHeader::equal_to<UnorderedLazyListTestHeader::item> equal_to;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyListTestHeader::NOGC_equal_to_mix()
+    {
+        // traits-based version
+        typedef cc::LazyList< cds::gc::nogc, item, NOGC_equal_to_mix_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyList< cds::gc::nogc, item,
+            cc::lazy_list::make_traits<
+                cc::opt::compare< cmp<item> >
+                ,cc::opt::less< lt<item> >
+                ,cc::opt::equal_to< equal_to<item> >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+    namespace {
+        struct NOGC_ic_traits : public cc::lazy_list::traits
+        {
+            typedef UnorderedLazyListTestHeader::equal_to<UnorderedLazyListTestHeader::item> equal_to;
+            typedef cds::atomicity::item_counter item_counter;
+            static const bool sort = false;
+        };
+    }
+    void UnorderedLazyListTestHeader::NOGC_ic()
+    {
+        // traits-based version
+        typedef cc::LazyList< cds::gc::nogc, item, NOGC_ic_traits > list;
+        nogc_test< list >();
+
+        // option-based version
+        typedef cc::LazyList< cds::gc::nogc, item,
+            cc::lazy_list::make_traits<
+                cc::opt::equal_to< equal_to<item> >
+                ,cc::opt::item_counter< cds::atomicity::item_counter >
+                ,cc::opt::sort<false>
+            >::type
+        > opt_list;
+        nogc_test< opt_list >();
+    }
+
+}   // namespace unordlist
+CPPUNIT_TEST_SUITE_REGISTRATION(unordlist::UnorderedLazyListTestHeader);