From 86dc48a26cf0b2254ad3b424b6a25fc780c27776 Mon Sep 17 00:00:00 2001 From: khizmax Date: Sun, 14 Feb 2016 11:37:48 +0300 Subject: [PATCH] Moved list unit tests to gtest framework --- projects/Win/vc14/gtest-list.vcxproj | 6 + projects/Win/vc14/gtest-list.vcxproj.filters | 18 + test/unit/list/CMakeLists.txt | 4 + test/unit/list/lazy_dhp.cpp | 162 ++++++++ test/unit/list/lazy_hp.cpp | 163 ++++++++ test/unit/list/michael_dhp.cpp | 146 ++++++++ test/unit/list/michael_hp.cpp | 147 ++++++++ test/unit/list/test_list.h | 373 +++++++++++++++++++ test/unit/list/test_list_hp.h | 136 +++++++ 9 files changed, 1155 insertions(+) create mode 100644 test/unit/list/lazy_dhp.cpp create mode 100644 test/unit/list/lazy_hp.cpp create mode 100644 test/unit/list/michael_dhp.cpp create mode 100644 test/unit/list/michael_hp.cpp create mode 100644 test/unit/list/test_list.h create mode 100644 test/unit/list/test_list_hp.h diff --git a/projects/Win/vc14/gtest-list.vcxproj b/projects/Win/vc14/gtest-list.vcxproj index d576b13f..20ef3853 100644 --- a/projects/Win/vc14/gtest-list.vcxproj +++ b/projects/Win/vc14/gtest-list.vcxproj @@ -33,6 +33,8 @@ + + @@ -79,6 +81,10 @@ + + + + diff --git a/projects/Win/vc14/gtest-list.vcxproj.filters b/projects/Win/vc14/gtest-list.vcxproj.filters index c696fc37..59ab214e 100644 --- a/projects/Win/vc14/gtest-list.vcxproj.filters +++ b/projects/Win/vc14/gtest-list.vcxproj.filters @@ -33,6 +33,12 @@ Header Files + + Header Files + + + Header Files + @@ -86,5 +92,17 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/test/unit/list/CMakeLists.txt b/test/unit/list/CMakeLists.txt index 040bdb28..96f7f65f 100644 --- a/test/unit/list/CMakeLists.txt +++ b/test/unit/list/CMakeLists.txt @@ -18,6 +18,10 @@ set(CDSGTEST_LIST_SOURCES intrusive_michael_rcu_gpt.cpp intrusive_michael_rcu_shb.cpp intrusive_michael_rcu_sht.cpp + lazy_hp.cpp + lazy_dhp.cpp + michael_hp.cpp + michael_dhp.cpp ) include_directories( diff --git a/test/unit/list/lazy_dhp.cpp b/test/unit/list/lazy_dhp.cpp new file mode 100644 index 00000000..da84906f --- /dev/null +++ b/test/unit/list/lazy_dhp.cpp @@ -0,0 +1,162 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_list_hp.h" +#include + +namespace { + namespace cc = cds::container; + typedef cds::gc::DHP gc_type; + + class LazyList_DHP : public cds_test::list_hp + { + protected: + void SetUp() + { + typedef cc::LazyList< gc_type, item > list_type; + + cds::gc::dhp::GarbageCollector::Construct( 16, list_type::c_nHazardPtrCount ); + cds::threading::Manager::attachThread(); + } + + void TearDown() + { + cds::threading::Manager::detachThread(); + cds::gc::hp::GarbageCollector::Destruct(); + } + }; + + TEST_F( LazyList_DHP, less_ordered ) + { + typedef cc::LazyList< gc_type, item, + typename cc::lazy_list::make_traits< + cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_DHP, compare_ordered ) + { + typedef cc::LazyList< gc_type, item, + typename cc::lazy_list::make_traits< + cds::opt::compare< cmp > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_DHP, mix_ordered ) + { + typedef cc::LazyList< gc_type, item, + typename cc::lazy_list::make_traits< + cds::opt::compare< cmp > + ,cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_DHP, item_counting ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_DHP, backoff ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::backoff::empty back_off; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_DHP, seq_cst ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::sequential_consistent memory_model; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_DHP, mutex ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef std::mutex lock_type; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + +} // namespace diff --git a/test/unit/list/lazy_hp.cpp b/test/unit/list/lazy_hp.cpp new file mode 100644 index 00000000..9189906f --- /dev/null +++ b/test/unit/list/lazy_hp.cpp @@ -0,0 +1,163 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_list_hp.h" +#include + +namespace { + namespace cc = cds::container; + typedef cds::gc::HP gc_type; + + class LazyList_HP : public cds_test::list_hp + { + protected: + void SetUp() + { + typedef cc::LazyList< gc_type, item > list_type; + + // +1 - for guarded_ptr + cds::gc::hp::GarbageCollector::Construct( list_type::c_nHazardPtrCount + 1, 1, 16 ); + cds::threading::Manager::attachThread(); + } + + void TearDown() + { + cds::threading::Manager::detachThread(); + cds::gc::hp::GarbageCollector::Destruct( true ); + } + }; + + TEST_F( LazyList_HP, less_ordered ) + { + typedef cc::LazyList< gc_type, item, + typename cc::lazy_list::make_traits< + cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_HP, compare_ordered ) + { + typedef cc::LazyList< gc_type, item, + typename cc::lazy_list::make_traits< + cds::opt::compare< cmp > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_HP, mix_ordered ) + { + typedef cc::LazyList< gc_type, item, + typename cc::lazy_list::make_traits< + cds::opt::compare< cmp > + ,cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_HP, item_counting ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_HP, backoff ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::backoff::empty back_off; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_HP, seq_cst ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::sequential_consistent memory_model; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( LazyList_HP, mutex ) + { + struct traits : public cc::lazy_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef std::mutex lock_type; + }; + typedef cc::LazyList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + +} // namespace diff --git a/test/unit/list/michael_dhp.cpp b/test/unit/list/michael_dhp.cpp new file mode 100644 index 00000000..1ecabe2c --- /dev/null +++ b/test/unit/list/michael_dhp.cpp @@ -0,0 +1,146 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_list_hp.h" +#include + +namespace { + namespace cc = cds::container; + typedef cds::gc::DHP gc_type; + + class MichaelList_DHP : public cds_test::list_hp + { + protected: + void SetUp() + { + typedef cc::MichaelList< gc_type, item > list_type; + + cds::gc::dhp::GarbageCollector::Construct( 16, list_type::c_nHazardPtrCount ); + cds::threading::Manager::attachThread(); + } + + void TearDown() + { + cds::threading::Manager::detachThread(); + cds::gc::hp::GarbageCollector::Destruct(); + } + }; + + TEST_F( MichaelList_DHP, less_ordered ) + { + typedef cc::MichaelList< gc_type, item, + typename cc::michael_list::make_traits< + cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_DHP, compare_ordered ) + { + typedef cc::MichaelList< gc_type, item, + typename cc::michael_list::make_traits< + cds::opt::compare< cmp > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_DHP, mix_ordered ) + { + typedef cc::MichaelList< gc_type, item, + typename cc::michael_list::make_traits< + cds::opt::compare< cmp > + ,cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_DHP, item_counting ) + { + struct traits : public cc::michael_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_DHP, backoff ) + { + struct traits : public cc::michael_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::backoff::empty back_off; + }; + typedef cc::MichaelList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_DHP, seq_cst ) + { + struct traits : public cc::michael_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::sequential_consistent memory_model; + }; + typedef cc::MichaelList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + +} // namespace diff --git a/test/unit/list/michael_hp.cpp b/test/unit/list/michael_hp.cpp new file mode 100644 index 00000000..6a2261be --- /dev/null +++ b/test/unit/list/michael_hp.cpp @@ -0,0 +1,147 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "test_list_hp.h" +#include + +namespace { + namespace cc = cds::container; + typedef cds::gc::HP gc_type; + + class MichaelList_HP : public cds_test::list_hp + { + protected: + void SetUp() + { + typedef cc::MichaelList< gc_type, item > list_type; + + // +1 - for guarded_ptr + cds::gc::hp::GarbageCollector::Construct( list_type::c_nHazardPtrCount + 1, 1, 16 ); + cds::threading::Manager::attachThread(); + } + + void TearDown() + { + cds::threading::Manager::detachThread(); + cds::gc::hp::GarbageCollector::Destruct( true ); + } + }; + + TEST_F( MichaelList_HP, less_ordered ) + { + typedef cc::MichaelList< gc_type, item, + typename cc::michael_list::make_traits< + cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_HP, compare_ordered ) + { + typedef cc::MichaelList< gc_type, item, + typename cc::michael_list::make_traits< + cds::opt::compare< cmp > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_HP, mix_ordered ) + { + typedef cc::MichaelList< gc_type, item, + typename cc::michael_list::make_traits< + cds::opt::compare< cmp > + ,cds::opt::less< lt > + >::type + > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_HP, item_counting ) + { + struct traits : public cc::michael_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_HP, backoff ) + { + struct traits : public cc::michael_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::backoff::empty back_off; + }; + typedef cc::MichaelList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + + TEST_F( MichaelList_HP, seq_cst ) + { + struct traits : public cc::michael_list::traits + { + typedef lt less; + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::sequential_consistent memory_model; + }; + typedef cc::MichaelList list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + +} // namespace diff --git a/test/unit/list/test_list.h b/test/unit/list/test_list.h new file mode 100644 index 00000000..c3086a73 --- /dev/null +++ b/test/unit/list/test_list.h @@ -0,0 +1,373 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef CDSUNIT_LIST_TEST_LIST_H +#define CDSUNIT_LIST_TEST_LIST_H + +#include +#include + +namespace cds_test { + + class list_common : public fixture + { + public: + struct item { + int nKey; + int nVal; + + item() + {} + + item( int key ) + : nKey( key ) + , nVal( key * 2 ) + {} + + item( int key, int val ) + : nKey( key ) + , nVal( val ) + {} + + item( const item& v ) + : nKey( v.nKey ) + , nVal( v.nVal ) + {} + + int key() const + { + return nKey; + } + }; + + template + struct lt + { + 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; + } + }; + + struct other_item + { + int nKey; + + other_item() + {} + + other_item( int n ) + : nKey( n ) + {} + }; + + struct other_less + { + template + bool operator()( T1 const& t1, T2 const& t2 ) const + { + return t1.nKey < t2.nKey; + } + }; + + protected: + template + void test_common( List& l ) + { + // Precondition: list is empty + // Postcondition: list is empty + + static const size_t nSize = 20; + typedef typename List::value_type value_type; + value_type arr[nSize]; + + for ( size_t i = 0; i < nSize; ++i ) { + arr[i].nKey = static_cast(i); + arr[i].nVal = arr[i].nKey * 10; + } + shuffle( arr, arr + nSize ); + + ASSERT_TRUE( l.empty() ); + ASSERT_CONTAINER_SIZE( l, 0 ); + + // insert/find + for ( auto const& i : arr ) { + EXPECT_FALSE( l.contains( i )); + EXPECT_FALSE( l.contains( i.nKey )); + EXPECT_FALSE( l.contains( other_item( i.nKey ), other_less())); + EXPECT_FALSE( l.find( i, []( value_type&, value_type const&) {} )); + EXPECT_FALSE( l.find( i.nKey, []( value_type&, int ) {} )); + EXPECT_FALSE( l.find_with( other_item( i.nKey ), other_less(), []( value_type&, other_item const& ) {} )); + + switch ( i.nKey & 3 ) { + case 0: + EXPECT_TRUE( l.insert( i.nKey )); + EXPECT_TRUE( l.find( i.nKey, []( value_type& n, int key ) { + EXPECT_EQ( n.nVal, key * 2 ); + } )); + EXPECT_FALSE( l.insert( i.nKey )); + break; + case 1: + EXPECT_TRUE( l.insert( i, []( value_type& n ) { + n.nVal = n.nKey * 3; + })); + EXPECT_TRUE( l.find( i.nKey, []( value_type& n, int key ) { + EXPECT_EQ( n.nVal, key * 3 ); + } )); + EXPECT_FALSE( l.insert( i )); + break; + case 2: + EXPECT_TRUE( l.emplace( i.nKey, i.nKey * 100 )); + EXPECT_TRUE( l.find( i.nKey, []( value_type& n, int key ) { + EXPECT_EQ( n.nVal, key * 100 ); + } )); + EXPECT_FALSE( l.insert( i )); + break; + case 3: + { + auto pair = l.update( i.nKey, []( bool bNew, value_type& n, int key ) { + EXPECT_TRUE( bNew ); + EXPECT_EQ( key, n.nKey ); + n.nVal = n.nKey * 3; + }, false ); + EXPECT_FALSE( pair.first ); + EXPECT_FALSE( pair.second ); + + pair = l.update( i.nKey, []( bool bNew, value_type& n, int key ) { + EXPECT_TRUE( bNew ); + EXPECT_EQ( key, n.nKey ); + n.nVal = n.nKey * 3; + }); + EXPECT_TRUE( pair.first ); + EXPECT_TRUE( pair.second ); + + EXPECT_TRUE( l.find( i.nKey, []( value_type& n, int key ) { + EXPECT_EQ( n.nVal, key * 3 ); + } )); + EXPECT_FALSE( l.insert( i )); + } + break; + } + + EXPECT_TRUE( l.contains( i )); + EXPECT_TRUE( l.contains( i.nKey )); + EXPECT_TRUE( l.contains( other_item( i.nKey ), other_less())); + EXPECT_TRUE( l.find( i, []( value_type& n, value_type const& arg ) { + EXPECT_EQ( arg.nKey, n.nKey ); + n.nVal = n.nKey; + } )); + EXPECT_TRUE( l.find( i.nKey, []( value_type& n, int key ) { + EXPECT_EQ( key, n.nKey ); + EXPECT_EQ( n.nKey, n.nVal ); + n.nVal = n.nKey * 5; + } )); + EXPECT_TRUE( l.find_with( other_item( i.nKey ), other_less(), []( value_type& n, other_item const& key ) { + EXPECT_EQ( key.nKey, n.nKey ); + EXPECT_EQ( n.nKey * 5, n.nVal ); + } )); + + auto pair = l.update( i.nKey, []( bool bNew, value_type& n, int key ) { + EXPECT_FALSE( bNew ); + EXPECT_EQ( key, n.nKey ); + EXPECT_EQ( key * 5, n.nVal ); + n.nVal = n.nKey * 3; + }, false ); + EXPECT_TRUE( pair.first ); + EXPECT_FALSE( pair.second ); + + EXPECT_FALSE( l.empty() ); + } + + ASSERT_FALSE( l.empty() ); + EXPECT_CONTAINER_SIZE( l, nSize ); + + // erase + for ( auto const&i : arr ) { + switch ( i.nKey & 3 ) { + case 0: + EXPECT_TRUE( l.erase( i.nKey )); + break; + case 1: + EXPECT_TRUE( l.erase_with( other_item( i.nKey ), other_less())); + break; + case 2: + EXPECT_TRUE( l.erase( i, [ &i ]( value_type const& n ) { + EXPECT_EQ( n.nKey, i.nKey ); + EXPECT_EQ( n.nKey * 3, n.nVal ); + })); + break; + case 3: + EXPECT_TRUE( l.erase_with( other_item( i.nKey ), other_less(), [ &i ]( value_type const& n) { + EXPECT_EQ( n.nKey, i.nKey ); + EXPECT_EQ( n.nKey * 3, n.nVal ); + } )); + } + + EXPECT_FALSE( l.contains( i )); + EXPECT_FALSE( l.contains( i.nKey )); + EXPECT_FALSE( l.contains( other_item( i.nKey ), other_less())); + EXPECT_FALSE( l.find( i, []( value_type&, value_type const&) {} )); + EXPECT_FALSE( l.find( i.nKey, []( value_type&, int ) {} )); + EXPECT_FALSE( l.find_with( other_item( i.nKey ), other_less(), []( value_type&, other_item const& ) {} )); + } + + ASSERT_TRUE( l.empty() ); + EXPECT_CONTAINER_SIZE( l, 0 ); + + // clear test + for ( auto& i : arr ) + EXPECT_TRUE( l.insert( i )); + + ASSERT_FALSE( l.empty() ); + EXPECT_CONTAINER_SIZE( l, nSize ); + + l.clear(); + + ASSERT_TRUE( l.empty() ); + EXPECT_CONTAINER_SIZE( l, 0 ); + + // empty list iterator test + { + List const& cl = l; + EXPECT_TRUE( l.begin() == l.end()); + EXPECT_TRUE( l.cbegin() == l.cend()); + EXPECT_TRUE( cl.begin() == cl.end()); + EXPECT_TRUE( l.begin() == l.cend()); + EXPECT_TRUE( cl.begin() == l.end()); + } + } + + template + void test_ordered_iterator( List& l ) + { + // Precondition: list is empty + // Postcondition: list is empty + + static const size_t nSize = 20; + typedef typename List::value_type value_type; + value_type arr[nSize]; + + for ( size_t i = 0; i < nSize; ++i ) { + arr[i].nKey = static_cast(i); + arr[i].nVal = arr[i].nKey; + } + shuffle( arr, arr + nSize ); + + ASSERT_TRUE( l.empty() ); + ASSERT_CONTAINER_SIZE( l, 0 ); + + for ( auto& i : arr ) + EXPECT_TRUE( l.insert( i )); + + int key = 0; + for ( auto& it : l ) { + EXPECT_EQ( key, it.nKey ); + EXPECT_EQ( it.nVal, it.nKey ); + it.nVal = it.nKey * 10; + ++key; + } + EXPECT_EQ( static_cast(key), nSize ); + + key = 0; + for ( auto it = l.cbegin(); it != l.cend(); ++it ) { + EXPECT_EQ( key, it->nKey ); + EXPECT_EQ( key, (*it).nKey ); + EXPECT_EQ( it->nKey * 10, it->nVal ); + ++key; + } + EXPECT_EQ( static_cast(key), nSize ); + + key = 0; + for ( auto it = l.begin(); it != l.end(); ++it ) { + EXPECT_EQ( key, it->nKey ); + EXPECT_EQ( key, (*it).nKey ); + EXPECT_EQ( it->nKey * 10, it->nVal ); + it->nVal = it->nKey * 2; + ++key; + } + EXPECT_EQ( static_cast(key), nSize ); + + List const& cl = l; + key = 0; + for ( auto it = cl.begin(); it != cl.end(); ++it ) { + EXPECT_EQ( key, it->nKey ); + EXPECT_EQ( key, (*it).nKey ); + EXPECT_EQ( it->nKey * 2, it->nVal ); + ++key; + } + EXPECT_EQ( static_cast(key), nSize ); + + l.clear(); + ASSERT_TRUE( l.empty() ); + EXPECT_CONTAINER_SIZE( l, 0 ); + } + }; + +} // namespace cds_test + +#endif // CDSUNIT_LIST_TEST_LIST_H diff --git a/test/unit/list/test_list_hp.h b/test/unit/list/test_list_hp.h new file mode 100644 index 00000000..67cb38cb --- /dev/null +++ b/test/unit/list/test_list_hp.h @@ -0,0 +1,136 @@ +/* + This file is a part of libcds - Concurrent Data Structures library + + (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016 + + Source code repo: http://github.com/khizmax/libcds/ + Download: http://sourceforge.net/projects/libcds/files/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef CDSUNIT_LIST_TEST_LIST_HP_H +#define CDSUNIT_LIST_TEST_LIST_HP_H + +#include "test_list.h" + +namespace cds_test { + + class list_hp : public list_common + { + protected: + template + void test_hp( List& l ) + { + // Precondition: list is empty + // Postcondition: list is empty + + static const size_t nSize = 20; + typedef typename List::value_type value_type; + typedef typename List::guarded_ptr guarded_ptr; + value_type arr[nSize]; + + for ( size_t i = 0; i < nSize; ++i ) { + arr[i].nKey = static_cast(i); + arr[i].nVal = arr[i].nKey * 10; + } + shuffle( arr, arr + nSize ); + + ASSERT_TRUE( l.empty() ); + ASSERT_CONTAINER_SIZE( l, 0 ); + + guarded_ptr gp; + size_t nCount = 0; + + // get() test + for ( auto& i : arr ) { + gp = l.get( i.nKey ); + EXPECT_TRUE( !gp ); + gp = l.get_with( other_item( i.nKey ), other_less()); + EXPECT_TRUE( !gp ); + + EXPECT_TRUE( l.insert( i )); + + gp = l.get( i ); + ASSERT_FALSE( !gp ); + EXPECT_EQ( gp->nKey, i.nKey ); + EXPECT_EQ( gp->nVal, gp->nKey * 10 ); + gp->nVal = gp->nKey * 5; + + gp = l.get_with( other_item( i.nKey ), other_less()); + ASSERT_FALSE( !gp ); + EXPECT_EQ( gp->nKey, i.nKey ); + EXPECT_EQ( gp->nVal, gp->nKey * 5 ); + gp->nVal = gp->nKey * 10; + + ++nCount; + ASSERT_FALSE( l.empty() ); + ASSERT_CONTAINER_SIZE( l, nCount ); + } + + ASSERT_FALSE( l.empty() ); + ASSERT_CONTAINER_SIZE( l, nSize ); + + // extract() test + for ( auto const& i : arr ) { + ASSERT_FALSE( l.empty() ); + ASSERT_CONTAINER_SIZE( l, nCount ); + --nCount; + + gp = l.get( i ); + ASSERT_FALSE( !gp ); + EXPECT_EQ( gp->nKey, i.nKey ); + + switch ( i.nKey & 3 ) { + case 0: + gp = l.extract( i ); + break; + case 1: + gp = l.extract_with( other_item( i.nKey ), other_less()); + break; + default: + gp = l.extract( i.nKey ); + break; + } + ASSERT_FALSE( !gp ); + EXPECT_EQ( gp->nKey, i.nKey ); + EXPECT_EQ( gp->nVal, gp->nKey * 10 ); + + gp = l.get( i.nKey ); + EXPECT_FALSE( gp ); + + gp = l.extract( i ); + EXPECT_FALSE( gp ); + gp = l.extract_with( other_item( i.nKey ), other_less()); + EXPECT_FALSE( gp ); + gp = l.extract( i.nKey ); + EXPECT_FALSE( gp ); + } + + ASSERT_TRUE( l.empty() ); + ASSERT_CONTAINER_SIZE( l, 0 ); + } + }; + +} // namespace cds_list + +#endif // CDSUNIT_LIST_TEST_LIST_HP_H -- 2.34.1