Added new test for bounded queues
authorkhizmax <libcds.dev@gmail.com>
Sun, 22 Nov 2015 09:06:39 +0000 (12:06 +0300)
committerkhizmax <libcds.dev@gmail.com>
Sun, 22 Nov 2015 09:06:39 +0000 (12:06 +0300)
projects/Win/vc12/unit-queue.vcxproj
projects/Win/vc14/unit-queue.vcxproj
projects/source.unit.queue.mk
tests/data/test-debug.conf
tests/data/test-express.conf
tests/data/test.conf
tests/unit/queue/CMakeLists.txt
tests/unit/queue/bounded_queue_fulness.cpp [new file with mode: 0644]

index 103c41e9ee9a937f73d8a3a511eead83af7faad1..639c3c059a44e17b13da1bbab649a1aea2772c0c 100644 (file)
     </Link>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="..\..\..\tests\unit\queue\bounded_queue_fulness.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\queue\intrusive_queue_reader_writer.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\queue\queue_pop.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\queue\queue_push.cpp" />\r
index bf32217df1579bf8d482728626930ffa05c075eb..574d06ce7098806dccf69428f08649dcb19799f9 100644 (file)
     </Link>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="..\..\..\tests\unit\queue\bounded_queue_fulness.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\queue\intrusive_queue_reader_writer.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\queue\queue_pop.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\queue\queue_push.cpp" />\r
index 7c677e00c3a256865a54149db6b7d8d841c06048..0c80d48dec39549f6546c2505ca8ce7be5ce0454 100644 (file)
@@ -1,5 +1,6 @@
 
 CDSUNIT_QUEUE_SOURCES := \
+    tests/unit/queue/bounded_queue_fulness.cpp \
     tests/unit/queue/queue_pop.cpp \
     tests/unit/queue/queue_push.cpp \
     tests/unit/queue/queue_random.cpp \
index ce46294d1d0a748d5913d8aac1f7f92d4c9e60e2..6b9e4444db735938a744a4417121a0f0cb0cb768 100644 (file)
@@ -99,6 +99,11 @@ QueueSize=100000
 ThreadCount=4\r
 QueueSize=500000\r
 \r
+[BoundedQueue_Fullness]\r
+ThreadCount=4\r
+QueueSize=1024\r
+PassCount=100000\r
+\r
 [PQueue_Push]\r
 ThreadCount=4\r
 QueueSize=10000\r
index c58393c86d9d8faef2afa0d950e1a67e866b5ea6..6f9b2f558d92263cca2fc48f3463d65c94a1d9f9 100644 (file)
@@ -100,9 +100,10 @@ QueueSize=500000
 ThreadCount=8\r
 QueueSize=500000\r
 \r
-[Queue_bounded_empty_ST]\r
-PassCount=100\r
-QueueSize=256\r
+[BoundedQueue_Fullness]\r
+ThreadCount=4\r
+QueueSize=1024\r
+PassCount=100000\r
 \r
 [PQueue_Push]\r
 ThreadCount=8\r
index f0d175db9cbd25bf8a58487efeb6408a66844965..2d35bd012ced14f8d1f75b78109001b2ff16c019 100644 (file)
@@ -99,6 +99,11 @@ QueueSize=5000000
 ThreadCount=8\r
 QueueSize=5000000\r
 \r
+[BoundedQueue_Fullness]\r
+ThreadCount=8\r
+QueueSize=1024\r
+PassCount=1000000\r
+\r
 [PQueue_Push]\r
 ThreadCount=8\r
 QueueSize=10000000\r
index 82eafd2a54a4a8cf1085080b3087e7d0f8a2c749..b32e7123fc7d743405e0b3132728b8e92cb78bf8 100644 (file)
@@ -1,6 +1,7 @@
 set(PACKAGE_NAME cdsu-queue)
 
 set(CDSUNIT_QUEUE_SOURCES
+    bounded_queue_fulness.cpp
     queue_pop.cpp
     queue_push.cpp
     queue_random.cpp
diff --git a/tests/unit/queue/bounded_queue_fulness.cpp b/tests/unit/queue/bounded_queue_fulness.cpp
new file mode 100644 (file)
index 0000000..9222aaf
--- /dev/null
@@ -0,0 +1,193 @@
+//$$CDS-header$$
+
+#include "cppunit/thread.h"
+#include "queue/queue_type.h"
+#include "queue/queue_defs.h"
+
+
+/*
+    Bounded queue test.
+    The test checks the behaviour of bounded queue when it is almost full.
+    Many algorithms says the queue is full when it is not, and vice versa.
+*/
+namespace queue {
+
+#define TEST_BOUNDED( Q, V )    void Q() { test< Types<V>::Q >(); }
+
+    namespace ns_BoundedQueue_Fullness {
+        static size_t s_nThreadCount = 8;
+        static size_t s_nQueueSize = 1024;
+        static size_t s_nPassCount = 1000000;
+    }
+    using namespace ns_BoundedQueue_Fullness;
+
+    class BoundedQueue_Fullness: public CppUnitMini::TestCase
+    {
+        template <class Queue>
+        class Thread: public CppUnitMini::TestThread
+        {
+            virtual TestThread *    clone()
+            {
+                return new Thread( *this );
+            }
+        public:
+            Queue&              m_Queue;
+            double              m_fTime;
+            size_t              m_nPushError;
+            size_t              m_nPopError;
+
+        public:
+            Thread( CppUnitMini::ThreadPool& pool, Queue& q )
+                : CppUnitMini::TestThread( pool )
+                , m_Queue( q )
+            {}
+            Thread( Thread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Queue( src.m_Queue )
+            {}
+
+            BoundedQueue_Fullness&  getTest()
+            {
+                return reinterpret_cast<BoundedQueue_Fullness&>( m_Pool.m_Test );
+            }
+
+            virtual void init()
+            {
+                cds::threading::Manager::attachThread();
+            }
+            virtual void fini()
+            {
+                cds::threading::Manager::detachThread();
+            }
+
+            virtual void test()
+            {
+                m_fTime = m_Timer.duration();
+
+                m_nPushError = 0;
+                m_nPopError = 0;
+                for ( size_t i = 0; i < s_nPassCount; ++i ) {
+                    if ( !m_Queue.push( i ))
+                        ++m_nPushError;
+                    size_t item;
+                    if ( !m_Queue.pop( item ))
+                        ++m_nPopError;
+                }
+                m_fTime = m_Timer.duration() - m_fTime;
+            }
+        };
+
+    protected:
+        template <class Queue>
+        void analyze( CppUnitMini::ThreadPool& pool, Queue& testQueue  )
+        {
+            double fTime = 0;
+            size_t nPushError = 0;
+            size_t nPopError = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                Thread<Queue> * pThread = reinterpret_cast<Thread<Queue> *>(*it);
+                fTime += pThread->m_fTime;
+                nPushError += pThread->m_nPushError;
+                nPopError  += pThread->m_nPopError;
+            }
+            CPPUNIT_MSG( "     Duration=" << (fTime / s_nThreadCount) );
+            CPPUNIT_MSG( "     Errors: push=" << nPushError << ", pop=" << nPopError );
+            CPPUNIT_CHECK( !testQueue.empty());
+            CPPUNIT_CHECK( nPushError == 0 );
+            CPPUNIT_CHECK( nPopError == 0 );
+        }
+
+        template <class Queue>
+        void test()
+        {
+            Queue testQueue;
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
+
+            size_t nSize = testQueue.capacity() - s_nThreadCount;
+            for ( size_t i = 0; i < nSize; ++i )
+                testQueue.push( i );
+
+            CPPUNIT_MSG( "   Thread count=" << s_nThreadCount << " ...");
+            pool.run();
+
+            analyze( pool, testQueue );
+
+            CPPUNIT_MSG( testQueue.statistics() );
+        }
+
+        template <class Queue>
+        void test_bounded()
+        {
+            size_t nStart = 0;
+            size_t nThreadItemCount = s_nQueueSize / s_nThreadCount;
+
+            Queue testQueue( s_nQueueSize );
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
+
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                Thread<Queue> * pThread = reinterpret_cast<Thread<Queue> *>(*it);
+                pThread->m_nStartItem = nStart;
+                nStart += nThreadItemCount;
+                pThread->m_nEndItem = nStart;
+            }
+
+            CPPUNIT_MSG( "   Push test, thread count=" << s_nThreadCount << " ...");
+            pool.run();
+
+            analyze( pool, testQueue );
+
+            CPPUNIT_MSG( testQueue.statistics() );
+        }
+
+        template <class Queue>
+        void test_segmented()
+        {
+            CPPUNIT_MSG( "   Push test, thread count=" << s_nThreadCount << " ...");
+            for ( size_t nSegmentSize = 4; nSegmentSize <= 256; nSegmentSize *= 4 ) {
+                CPPUNIT_MSG( "Segment size: " << nSegmentSize );
+
+                Queue testQueue( nSegmentSize );
+
+                CppUnitMini::ThreadPool pool( *this );
+                pool.add( new Thread<Queue>( pool, testQueue ), s_nThreadCount );
+
+                size_t nStart = 0;
+                size_t nThreadItemCount = s_nQueueSize / s_nThreadCount;
+                for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                    Thread<Queue> * pThread = reinterpret_cast<Thread<Queue> *>(*it);
+                    pThread->m_nStartItem = nStart;
+                    nStart += nThreadItemCount;
+                    pThread->m_nEndItem = nStart;
+                }
+
+                pool.run();
+
+                analyze( pool, testQueue );
+
+                CPPUNIT_MSG( testQueue.statistics() );
+            }
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
+            s_nThreadCount = cfg.getULong("ThreadCount", 8 );
+            s_nQueueSize = cfg.getULong("QueueSize", 1024 );
+            s_nPassCount = cfg.getULong( "PassCount", 1000000 );
+        }
+
+    protected:
+        CDSUNIT_DECLARE_TsigasCycleQueue( size_t )
+        CDSUNIT_DECLARE_VyukovMPMCCycleQueue( size_t )
+
+        CPPUNIT_TEST_SUITE( BoundedQueue_Fullness )
+            CDSUNIT_TEST_TsigasCycleQueue
+            CDSUNIT_TEST_VyukovMPMCCycleQueue
+        CPPUNIT_TEST_SUITE_END();
+    };
+
+} // namespace queue
+
+CPPUNIT_TEST_SUITE_REGISTRATION(queue::BoundedQueue_Fullness );