From: khizmax Date: Sat, 23 Jan 2016 14:34:34 +0000 (+0300) Subject: Moved queue unit test to gtest framework X-Git-Tag: v2.2.0~417 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=4afbf58f50636d756de4a15b74447e0ad99278df;p=libcds.git Moved queue unit test to gtest framework --- diff --git a/projects/Win/vc14/gtest-deque.vcxproj b/projects/Win/vc14/gtest-deque.vcxproj index 7861f82b..a3824281 100644 --- a/projects/Win/vc14/gtest-deque.vcxproj +++ b/projects/Win/vc14/gtest-deque.vcxproj @@ -135,8 +135,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -151,8 +150,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -167,8 +165,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -183,8 +180,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -200,8 +196,7 @@ Level3 - - + NotUsing MaxSpeed true true @@ -220,8 +215,7 @@ Level3 - - + NotUsing MaxSpeed true true diff --git a/projects/Win/vc14/gtest-pqueue.vcxproj b/projects/Win/vc14/gtest-pqueue.vcxproj index cb3ddb69..ffc22f8d 100644 --- a/projects/Win/vc14/gtest-pqueue.vcxproj +++ b/projects/Win/vc14/gtest-pqueue.vcxproj @@ -143,8 +143,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -159,8 +158,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -175,8 +173,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -191,8 +188,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -208,8 +204,7 @@ Level3 - - + NotUsing MaxSpeed true true @@ -228,8 +223,7 @@ Level3 - - + NotUsing MaxSpeed true true diff --git a/projects/Win/vc14/gtest-queue.vcxproj b/projects/Win/vc14/gtest-queue.vcxproj index f4d2a7f5..edb20c69 100644 --- a/projects/Win/vc14/gtest-queue.vcxproj +++ b/projects/Win/vc14/gtest-queue.vcxproj @@ -38,9 +38,17 @@ + + false + + + + + + {9EB8FAB6-78E8-48B6-9589-85985CE8D33D} @@ -147,8 +155,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -163,8 +170,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -179,8 +185,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -195,8 +200,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -212,8 +216,7 @@ Level3 - - + NotUsing MaxSpeed true true @@ -232,8 +235,7 @@ Level3 - - + NotUsing MaxSpeed true true diff --git a/projects/Win/vc14/gtest-queue.vcxproj.filters b/projects/Win/vc14/gtest-queue.vcxproj.filters index b766f092..2158a14d 100644 --- a/projects/Win/vc14/gtest-queue.vcxproj.filters +++ b/projects/Win/vc14/gtest-queue.vcxproj.filters @@ -48,10 +48,28 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/projects/Win/vc14/gtest-stack.vcxproj b/projects/Win/vc14/gtest-stack.vcxproj index 39cd7ea8..4680d2e4 100644 --- a/projects/Win/vc14/gtest-stack.vcxproj +++ b/projects/Win/vc14/gtest-stack.vcxproj @@ -144,8 +144,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -160,8 +159,7 @@ - - + NotUsing Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -176,8 +174,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -192,8 +189,7 @@ - - + NotUsing Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -209,8 +205,7 @@ Level3 - - + NotUsing MaxSpeed true true @@ -229,8 +224,7 @@ Level3 - - + NotUsing MaxSpeed true true diff --git a/test/unit/queue/CMakeLists.txt b/test/unit/queue/CMakeLists.txt index 947edc37..163a1082 100644 --- a/test/unit/queue/CMakeLists.txt +++ b/test/unit/queue/CMakeLists.txt @@ -12,6 +12,10 @@ set(CDSGTEST_QUEUE_SOURCES optimistic_queue_hp.cpp optimistic_queue_dhp.cpp rwqueue.cpp + segmented_queue_hp.cpp + segmented_queue_dhp.cpp + tsigas_queue.cpp + vyukov_mpmc_queue.cpp ) include_directories( diff --git a/test/unit/queue/segmented_queue_dhp.cpp b/test/unit/queue/segmented_queue_dhp.cpp new file mode 100644 index 00000000..fff7e296 --- /dev/null +++ b/test/unit/queue/segmented_queue_dhp.cpp @@ -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. +*/ + +#include "test_segmented_queue.h" + +#include +#include + +namespace { + namespace cc = cds::container; + typedef cds::gc::DHP gc_type; + + + class SegmentedQueue_DHP : public cds_test::segmented_queue + { + protected: + static const size_t c_QuasiFactor = 15; + void SetUp() + { + typedef cc::SegmentedQueue< gc_type, int > queue_type; + + cds::gc::dhp::GarbageCollector::Construct( 16, queue_type::c_nHazardPtrCount ); + cds::threading::Manager::attachThread(); + } + + void TearDown() + { + cds::threading::Manager::detachThread(); + cds::gc::hp::GarbageCollector::Destruct(); + } + }; + + TEST_F( SegmentedQueue_DHP, defaulted ) + { + typedef cds::container::SegmentedQueue< gc_type, int > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor )); + test(q); + } + + TEST_F( SegmentedQueue_DHP, mutex ) + { + struct traits : public cds::container::segmented_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::random_shuffle_permutation<> permutation_generator; + }; + typedef cds::container::SegmentedQueue< gc_type, int, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test( q ); + } + + TEST_F( SegmentedQueue_DHP, shuffle ) + { + struct traits : public cds::container::segmented_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::random_shuffle_permutation<> permutation_generator; + }; + typedef cds::container::SegmentedQueue< gc_type, int, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test( q ); + } + + TEST_F( SegmentedQueue_DHP, stat ) + { + struct traits : public + cds::container::segmented_queue::make_traits < + cds::opt::item_counter< cds::atomicity::item_counter > + , cds::opt::permutation_generator< cds::opt::v::random_permutation<> > + , cds::opt::stat < cds::container::segmented_queue::stat<> > + > ::type + {}; + typedef cds::container::SegmentedQueue< gc_type, int, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test( q ); + } + + TEST_F( SegmentedQueue_DHP, move ) + { + typedef cds::container::SegmentedQueue< gc_type, std::string > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test_string( q ); + } + + TEST_F( SegmentedQueue_DHP, move_item_counting ) + { + struct traits : public cds::container::segmented_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::SegmentedQueue< gc_type, std::string, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test_string( q ); + } + +} // namespace + diff --git a/test/unit/queue/segmented_queue_hp.cpp b/test/unit/queue/segmented_queue_hp.cpp new file mode 100644 index 00000000..1af21f46 --- /dev/null +++ b/test/unit/queue/segmented_queue_hp.cpp @@ -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. +*/ + +#include "test_segmented_queue.h" + +#include +#include + +namespace { + namespace cc = cds::container; + typedef cds::gc::HP gc_type; + + + class SegmentedQueue_HP : public cds_test::segmented_queue + { + protected: + static const size_t c_QuasiFactor = 15; + void SetUp() + { + typedef cc::SegmentedQueue< gc_type, int > queue_type; + + cds::gc::hp::GarbageCollector::Construct( queue_type::c_nHazardPtrCount, 1, 16 ); + cds::threading::Manager::attachThread(); + } + + void TearDown() + { + cds::threading::Manager::detachThread(); + cds::gc::hp::GarbageCollector::Destruct( true ); + } + }; + + TEST_F( SegmentedQueue_HP, defaulted ) + { + typedef cds::container::SegmentedQueue< gc_type, int > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor )); + test(q); + } + + TEST_F( SegmentedQueue_HP, mutex ) + { + struct traits : public cds::container::segmented_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::random_shuffle_permutation<> permutation_generator; + }; + typedef cds::container::SegmentedQueue< cds::gc::HP, int, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test( q ); + } + + TEST_F( SegmentedQueue_HP, shuffle ) + { + struct traits : public cds::container::segmented_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + typedef cds::opt::v::random_shuffle_permutation<> permutation_generator; + }; + typedef cds::container::SegmentedQueue< cds::gc::HP, int, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test( q ); + } + + TEST_F( SegmentedQueue_HP, stat ) + { + struct traits : public + cds::container::segmented_queue::make_traits < + cds::opt::item_counter< cds::atomicity::item_counter > + , cds::opt::permutation_generator< cds::opt::v::random_permutation<> > + , cds::opt::stat < cds::container::segmented_queue::stat<> > + > ::type + {}; + typedef cds::container::SegmentedQueue< cds::gc::HP, int, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test( q ); + } + + TEST_F( SegmentedQueue_HP, move ) + { + typedef cds::container::SegmentedQueue< gc_type, std::string > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test_string( q ); + } + + TEST_F( SegmentedQueue_HP, move_item_counting ) + { + struct traits : public cds::container::segmented_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::SegmentedQueue< gc_type, std::string, traits > test_queue; + + test_queue q( c_QuasiFactor ); + ASSERT_EQ( q.quasi_factor(), cds::beans::ceil2( c_QuasiFactor ) ); + test_string( q ); + } + +} // namespace + diff --git a/test/unit/queue/test_bounded_queue.h b/test/unit/queue/test_bounded_queue.h new file mode 100644 index 00000000..49de2bbf --- /dev/null +++ b/test/unit/queue/test_bounded_queue.h @@ -0,0 +1,215 @@ +/* + 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_QUEUE_TEST_BOUNDED_QUEUE_H +#define CDSUNIT_QUEUE_TEST_BOUNDED_QUEUE_H + +#include + +namespace cds_test { + + class bounded_queue : public ::testing::Test + { + protected: + template + void test( Queue& q ) + { + typedef typename Queue::value_type value_type; + value_type it; + + const size_t nSize = q.capacity(); + + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // enqueue/dequeue + for ( size_t i = 0; i < nSize; ++i ) { + it = static_cast(i); + ASSERT_TRUE( q.enqueue( it )); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + for ( size_t i = 0; i < nSize; ++i ) { + it = -1; + ASSERT_TRUE( q.dequeue( it ) ); + ASSERT_EQ( it, i ); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // push/pop + for ( size_t i = 0; i < nSize; ++i ) { + it = static_cast(i); + ASSERT_TRUE( q.push( it )); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + for ( size_t i = 0; i < nSize; ++i ) { + it = -1; + ASSERT_TRUE( q.pop( it ) ); + ASSERT_EQ( it, i ); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // push/pop with lambda + for ( size_t i = 0; i < nSize; ++i ) { + it = static_cast(i); + ASSERT_NE( it, -1 ); + auto f = [&it]( value_type& dest ) { dest = it; it = -1; }; + if ( i & 1 ) + ASSERT_TRUE( q.enqueue_with( f )); + else + ASSERT_TRUE( q.push_with( f )); + ASSERT_EQ( it, -1 ); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + for ( size_t i = 0; i < nSize; ++i ) { + it = -1; + auto f = [&it]( value_type& src ) { it = src; src = -1; }; + if ( i & 1 ) + ASSERT_TRUE( q.pop_with( f )); + else + ASSERT_TRUE( q.dequeue_with( f )); + ASSERT_EQ( it, i ); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + for ( size_t i = 0; i < nSize; ++i ) { + ASSERT_TRUE( q.push( static_cast(i) ) ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + // push in full queue + ASSERT_FALSE( q.push( static_cast(nSize * 2 ))); + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + it = static_cast( nSize * 2 ); + ASSERT_FALSE( q.enqueue( it )); + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + // clear + q.clear(); + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // pop from empty queue + it = static_cast(nSize * 2); + ASSERT_FALSE( q.pop( it ) ); + ASSERT_EQ( it, nSize * 2 ); + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + ASSERT_FALSE( q.dequeue( it ) ); + ASSERT_EQ( it, nSize * 2 ); + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + } + + template + void test_string( Queue& q ) + { + std::string str[3]; + str[0] = "one"; + str[1] = "two"; + str[2] = "three"; + const size_t nSize = sizeof( str ) / sizeof( str[0] ); + + // emplace + for ( size_t i = 0; i < nSize; ++i ) { + ASSERT_TRUE( q.emplace( str[i].c_str())); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + { + std::string s; + auto f = [&s]( std::string& src ) { + ASSERT_FALSE( src.empty() ); + s = std::move( src ); + ASSERT_NE( s, src ); + }; + for ( size_t i = 0; i < nSize; ++i ) { + if ( i & 1 ) + ASSERT_TRUE( q.pop_with( f )); + else + ASSERT_TRUE( q.dequeue_with( f )); + + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + ASSERT_EQ( s, str[i] ); + } + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + + // move push + for ( size_t i = 0; i < nSize; ++i ) { + std::string s = str[i]; + ASSERT_FALSE( s.empty()); + if ( i & 1 ) + ASSERT_TRUE( q.enqueue( std::move( s ))); + else + ASSERT_TRUE( q.push( std::move( s ))); + ASSERT_TRUE( s.empty() ); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + for ( size_t i = 0; i < nSize; ++i ) { + std::string s; + ASSERT_TRUE( q.pop( s ) ); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + ASSERT_EQ( s, str[i] ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + } + + }; + +} // namespace cds_test + +#endif // CDSUNIT_QUEUE_TEST_BOUNDED_QUEUE_H diff --git a/test/unit/queue/test_generic_queue.h b/test/unit/queue/test_generic_queue.h index 28554f06..5efc72cb 100644 --- a/test/unit/queue/test_generic_queue.h +++ b/test/unit/queue/test_generic_queue.h @@ -32,15 +32,15 @@ #define CDSUNIT_QUEUE_TEST_GENERIC_QUEUE_H #include - -namespace cds_test { - - class generic_queue : public ::testing::Test - { - protected: - template - void test( Queue& q ) - { + +namespace cds_test { + + class generic_queue : public ::testing::Test + { + protected: + template + void test( Queue& q ) + { typedef typename Queue::value_type value_type; value_type it; @@ -135,8 +135,8 @@ namespace cds_test { ASSERT_EQ( it, nSize * 2 ); ASSERT_TRUE( q.empty() ); ASSERT_CONTAINER_SIZE( q, 0 ); - } - + } + template void test_string( Queue& q ) { @@ -159,7 +159,7 @@ namespace cds_test { auto f = [&s]( std::string& src ) { ASSERT_FALSE( src.empty() ); s = std::move( src ); - ASSERT_TRUE( src.empty() ); + ASSERT_NE( s, src ); }; for ( size_t i = 0; i < nSize; ++i ) { if ( i & 1 ) @@ -198,9 +198,9 @@ namespace cds_test { ASSERT_TRUE( q.empty() ); ASSERT_CONTAINER_SIZE( q, 0 ); } - - }; - -} // namespace cds_test - -#endif // CDSUNIT_QUEUE_TEST_GENERIC_QUEUE_H + + }; + +} // namespace cds_test + +#endif // CDSUNIT_QUEUE_TEST_GENERIC_QUEUE_H diff --git a/test/unit/queue/test_segmented_queue.h b/test/unit/queue/test_segmented_queue.h new file mode 100644 index 00000000..0ad17b55 --- /dev/null +++ b/test/unit/queue/test_segmented_queue.h @@ -0,0 +1,231 @@ +/* + 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_QUEUE_TEST_SEGMENTED_QUEUE_H +#define CDSUNIT_QUEUE_TEST_SEGMENTED_QUEUE_H + +#include + +namespace cds_test { + + class segmented_queue : public ::testing::Test + { + protected: + template + void test( Queue& q ) + { + typedef typename Queue::value_type value_type; + value_type it; + + const size_t nSize = 100; + + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // enqueue/dequeue + for ( size_t i = 0; i < nSize; ++i ) { + it = static_cast(i); + ASSERT_TRUE( q.enqueue( it )); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + for ( size_t i = 0; i < nSize; ++i ) { + it = -1; + ASSERT_TRUE( q.dequeue( it ) ); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + + int nSegment = int( i / q.quasi_factor() ); + int nMin = nSegment * int( q.quasi_factor() ); + int nMax = nMin + int( q.quasi_factor() ) - 1; + EXPECT_LE( nMin, it ); + EXPECT_LE( it, nMax ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // push/pop + for ( size_t i = 0; i < nSize; ++i ) { + it = static_cast(i); + ASSERT_TRUE( q.push( it )); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + size_t nPushed = nSize; + size_t nStartSegment = nPushed / q.quasi_factor(); + size_t nOffset = nPushed % q.quasi_factor(); + for ( size_t i = 0; i < nSize; ++i ) { + it = -1; + ASSERT_TRUE( q.pop( it ) ); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + + int nSegment = static_cast((i + nPushed) / q.quasi_factor() - nStartSegment ); + int nMin = nSegment * static_cast( q.quasi_factor()); + if ( nSegment ) + nMin -= static_cast( nOffset ); + int nMax = nMin + static_cast( q.quasi_factor()) - 1; + EXPECT_LE( nMin, it ); + EXPECT_LE( it, nMax ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // push/pop with lambda + for ( size_t i = 0; i < nSize; ++i ) { + it = static_cast(i); + EXPECT_NE( it, -1 ); + auto f = [&it]( value_type& dest ) { dest = it; it = -1; }; + if ( i & 1 ) + ASSERT_TRUE( q.enqueue_with( f )); + else + ASSERT_TRUE( q.push_with( f )); + ASSERT_EQ( it, -1 ); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + nPushed += nSize; + nStartSegment = nPushed / q.quasi_factor(); + nOffset = nPushed % q.quasi_factor(); + for ( size_t i = 0; i < nSize; ++i ) { + it = -1; + auto f = [&it]( value_type& src ) { it = src; src = -1; }; + if ( i & 1 ) + ASSERT_TRUE( q.pop_with( f )); + else + ASSERT_TRUE( q.dequeue_with( f )); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + + int nSegment = static_cast((i + nPushed) / q.quasi_factor() - nStartSegment); + int nMin = nSegment * static_cast(q.quasi_factor()); + if ( nSegment ) + nMin -= static_cast(nOffset); + int nMax = nMin + static_cast(q.quasi_factor()) - 1; + EXPECT_LE( nMin, it ); + EXPECT_LE( it, nMax ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // clear + for ( size_t i = 0; i < nSize; ++i ) { + ASSERT_TRUE( q.push( static_cast(i) ) ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + q.clear(); + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + // pop from empty queue + it = nSize * 2; + ASSERT_FALSE( q.pop( it ) ); + ASSERT_EQ( it, nSize * 2 ); + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + ASSERT_FALSE( q.dequeue( it ) ); + ASSERT_EQ( it, nSize * 2 ); + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + } + + template + void test_string( Queue& q ) + { + std::string str[3]; + str[0] = "one"; + str[1] = "two"; + str[2] = "three"; + const size_t nSize = sizeof( str ) / sizeof( str[0] ); + + // emplace + for ( size_t i = 0; i < nSize; ++i ) { + ASSERT_TRUE( q.emplace( str[i].c_str())); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + { + std::string s; + auto f = [&s]( std::string& src ) { + ASSERT_FALSE( src.empty() ); + s = std::move( src ); + ASSERT_NE( s, src ); + }; + for ( size_t i = 0; i < nSize; ++i ) { + if ( i & 1 ) + ASSERT_TRUE( q.pop_with( f )); + else + ASSERT_TRUE( q.dequeue_with( f )); + + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + ASSERT_TRUE( s == str[0] || s == str[1] || s == str[2] ); + } + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + + + // move push + for ( size_t i = 0; i < nSize; ++i ) { + std::string s = str[i]; + ASSERT_FALSE( s.empty() ); + if ( i & 1 ) + ASSERT_TRUE( q.enqueue( std::move( s ))); + else + ASSERT_TRUE( q.push( std::move( s ))); + ASSERT_TRUE( s.empty() ); + ASSERT_CONTAINER_SIZE( q, i + 1 ); + } + ASSERT_FALSE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, nSize ); + + for ( size_t i = 0; i < nSize; ++i ) { + std::string s; + ASSERT_TRUE( q.pop( s ) ); + ASSERT_CONTAINER_SIZE( q, nSize - i - 1 ); + ASSERT_TRUE( s == str[0] || s == str[1] || s == str[2] ); + } + ASSERT_TRUE( q.empty() ); + ASSERT_CONTAINER_SIZE( q, 0 ); + } + + }; + +} // namespace cds_test + +#endif // CDSUNIT_QUEUE_TEST_SEGMENTED_QUEUE_H diff --git a/test/unit/queue/tsigas_queue.cpp b/test/unit/queue/tsigas_queue.cpp new file mode 100644 index 00000000..f82e2d5c --- /dev/null +++ b/test/unit/queue/tsigas_queue.cpp @@ -0,0 +1,134 @@ +/* + 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_bounded_queue.h" + +#include + +namespace { + namespace cc = cds::container; + + class TsigasCycleQueue: public cds_test::bounded_queue + {}; + + TEST_F( TsigasCycleQueue, defaulted ) + { + typedef cds::container::TsigasCycleQueue< int > test_queue; + + test_queue q( 128 ); + test(q); + } + + TEST_F( TsigasCycleQueue, stat ) + { + struct traits: public cds::container::tsigas_queue::traits + { + typedef cds::opt::v::static_buffer buffer; + }; + typedef cds::container::TsigasCycleQueue< int, traits > test_queue; + + test_queue q; + test( q ); + } + + TEST_F( TsigasCycleQueue, stat_item_counting ) + { + + typedef cds::container::TsigasCycleQueue< int, + cds::container::tsigas_queue::make_traits< + cds::opt::buffer< cds::opt::v::static_buffer> + , cds::opt::item_counter< cds::atomicity::item_counter> + >::type + > test_queue; + + test_queue q; + test( q ); + } + + TEST_F( TsigasCycleQueue, dynamic ) + { + struct traits : public cds::container::tsigas_queue::traits + { + typedef cds::opt::v::dynamic_buffer buffer; + }; + typedef cds::container::TsigasCycleQueue< int, traits > test_queue; + + test_queue q( 128 ); + test( q ); + } + + TEST_F( TsigasCycleQueue, dynamic_item_counting ) + { + typedef cds::container::TsigasCycleQueue< int, + cds::container::tsigas_queue::make_traits< + cds::opt::buffer< cds::opt::v::dynamic_buffer> + , cds::opt::item_counter< cds::atomicity::item_counter> + >::type + > test_queue; + + test_queue q( 128 ); + test( q ); + } + + TEST_F( TsigasCycleQueue, dynamic_padding ) + { + struct traits : public cds::container::tsigas_queue::traits + { + typedef cds::opt::v::dynamic_buffer buffer; + enum { alignment = 16 }; + }; + typedef cds::container::TsigasCycleQueue< int, traits > test_queue; + + test_queue q( 128 ); + test( q ); + } + + TEST_F( TsigasCycleQueue, move ) + { + typedef cds::container::TsigasCycleQueue< std::string > test_queue; + + test_queue q( 128 ); + test_string( q ); + } + + TEST_F( TsigasCycleQueue, move_item_counting ) + { + struct traits : public cds::container::tsigas_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::TsigasCycleQueue< std::string, traits > test_queue; + + test_queue q( 128 ); + test_string( q ); + } + +} // namespace + diff --git a/test/unit/queue/vyukov_mpmc_queue.cpp b/test/unit/queue/vyukov_mpmc_queue.cpp new file mode 100644 index 00000000..c9aa9c17 --- /dev/null +++ b/test/unit/queue/vyukov_mpmc_queue.cpp @@ -0,0 +1,134 @@ +/* + 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_bounded_queue.h" + +#include + +namespace { + namespace cc = cds::container; + + class VyukovMPMCCycleQueue: public cds_test::bounded_queue + {}; + + TEST_F( VyukovMPMCCycleQueue, defaulted ) + { + typedef cds::container::VyukovMPMCCycleQueue< int > test_queue; + + test_queue q( 128 ); + test(q); + } + + TEST_F( VyukovMPMCCycleQueue, stat ) + { + struct traits: public cds::container::vyukov_queue::traits + { + typedef cds::opt::v::static_buffer buffer; + }; + typedef cds::container::VyukovMPMCCycleQueue< int, traits > test_queue; + + test_queue q; + test( q ); + } + + TEST_F( VyukovMPMCCycleQueue, stat_item_counting ) + { + + typedef cds::container::VyukovMPMCCycleQueue< int, + cds::container::vyukov_queue::make_traits< + cds::opt::buffer< cds::opt::v::static_buffer> + , cds::opt::item_counter< cds::atomicity::item_counter> + >::type + > test_queue; + + test_queue q; + test( q ); + } + + TEST_F( VyukovMPMCCycleQueue, dynamic ) + { + struct traits : public cds::container::vyukov_queue::traits + { + typedef cds::opt::v::dynamic_buffer buffer; + }; + typedef cds::container::VyukovMPMCCycleQueue< int, traits > test_queue; + + test_queue q( 128 ); + test( q ); + } + + TEST_F( VyukovMPMCCycleQueue, dynamic_item_counting ) + { + typedef cds::container::VyukovMPMCCycleQueue< int, + cds::container::vyukov_queue::make_traits< + cds::opt::buffer< cds::opt::v::dynamic_buffer> + , cds::opt::item_counter< cds::atomicity::item_counter> + >::type + > test_queue; + + test_queue q( 128 ); + test( q ); + } + + TEST_F( VyukovMPMCCycleQueue, dynamic_padding ) + { + struct traits : public cds::container::vyukov_queue::traits + { + typedef cds::opt::v::dynamic_buffer buffer; + enum { padding = 64 }; + }; + typedef cds::container::VyukovMPMCCycleQueue< int, traits > test_queue; + + test_queue q( 128 ); + test( q ); + } + + TEST_F( VyukovMPMCCycleQueue, move ) + { + typedef cds::container::VyukovMPMCCycleQueue< std::string > test_queue; + + test_queue q( 128 ); + test_string( q ); + } + + TEST_F( VyukovMPMCCycleQueue, move_item_counting ) + { + struct traits : public cds::container::vyukov_queue::traits + { + typedef cds::atomicity::item_counter item_counter; + }; + typedef cds::container::VyukovMPMCCycleQueue< std::string, traits > test_queue; + + test_queue q( 128 ); + test_string( q ); + } + +} // namespace +