Splitted up map_find_string test to reduce compiling time and memory requirements
authorkhizmax <libcds.dev@gmail.com>
Tue, 24 Mar 2015 20:24:42 +0000 (23:24 +0300)
committerkhizmax <libcds.dev@gmail.com>
Tue, 24 Mar 2015 20:24:42 +0000 (23:24 +0300)
16 files changed:
projects/Win/vc12/unit-map-find.vcxproj
projects/source.unit.map.mk
tests/cppunit/cppunit_mini.h
tests/unit/map2/map_find_int.cpp
tests/unit/map2/map_find_int.h
tests/unit/map2/map_find_string.cpp
tests/unit/map2/map_find_string.h [new file with mode: 0644]
tests/unit/map2/map_find_string_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_split.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_std.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_striped.cpp [new file with mode: 0644]

index 5beceb54763045ba8129eb6f8596e7bbfabf42cb..4559070db1a1fc303e87955c120d713a1c71b737 100644 (file)
     <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_std.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_find_string.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_bronsonavltree.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_cuckoo.cpp" />\r
@@ -67,6 +76,7 @@
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\..\..\tests\unit\map2\map_find_int.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_find_string.h" />\r
     <ClInclude Include="..\..\..\tests\unit\map2\map_insfind_int.h" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
index f44c1a4702d14a2e125539be27cb857aba6d137f..22bac08fd4831357b988fca4afe609f188750aec 100644 (file)
@@ -11,6 +11,15 @@ CDSUNIT_MAP_SOURCES := \
     tests/unit/map2/map_find_int_refinable.cpp \
     tests/unit/map2/map_find_int_std.cpp \
     tests/unit/map2/map_find_string.cpp \    
+    tests/unit/map2/map_find_string_bronsonavltree.cpp \
+    tests/unit/map2/map_find_string_cuckoo.cpp \
+    tests/unit/map2/map_find_string_ellentree.cpp \
+    tests/unit/map2/map_find_string_michael.cpp \
+    tests/unit/map2/map_find_string_skip.cpp \
+    tests/unit/map2/map_find_string_split.cpp \
+    tests/unit/map2/map_find_string_striped.cpp \
+    tests/unit/map2/map_find_string_refinable.cpp \
+    tests/unit/map2/map_find_string_std.cpp \
     tests/unit/map2/map_insfind_int.cpp \
     tests/unit/map2/map_insfind_int_bronsonavltree.cpp \
     tests/unit/map2/map_insfind_int_cuckoo.cpp \
index 89ae6d0d3144dd75346c2ace47112510b734d4be..714b088391945273206652715506b15713468af5 100644 (file)
@@ -81,6 +81,10 @@ namespace CppUnitMini
       unsigned int getUInt( const char * pszParamName, unsigned int nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
       long getLong( const char * pszParamName, long nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
       unsigned long getULong( const char * pszParamName, unsigned long nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
+      size_t getSizeT( const char * pszParamName, size_t nDefVal = 0 ) const 
+      {
+          return static_cast<size_t>( getULong( pszParamName, static_cast<unsigned long>(nDefVal)));
+      }
 
       bool getBool( const char * pszParamName, bool bDefVal = false ) const
       {
@@ -96,8 +100,7 @@ namespace CppUnitMini
               std::cerr << "bad_lexical_cast encountered while getting parameter "
                   << strParamName << "=" << it->second
                   << ": " << ex.what()
-                  << std::endl
-;
+                  << std::endl;
           }
           return bDefVal;
       }
index c8bfe8543c78d335e6e2dd8433358b6c7f81ea5e..5b201ff826fa15dc837e544e994d98ba92d3d837 100644 (file)
@@ -50,11 +50,11 @@ namespace map2 {
 
     void Map_find_int::setUpParams( const CppUnitMini::TestCfg& cfg )
     {
-        c_nThreadCount = cfg.getULong("ThreadCount", static_cast<unsigned long>(c_nThreadCount)); // thread count
-        c_nMapSize = cfg.getULong("MapSize", static_cast<unsigned long>(c_nMapSize));  // map size (count of searching item)
-        c_nPercentExists = cfg.getULong("PercentExists", static_cast<unsigned long>(c_nPercentExists));  // percent of existing keys in searching sequence
-        c_nPassCount = cfg.getULong("PassCount", static_cast<unsigned long>(c_nPassCount));
-        c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast<unsigned long>(c_nMaxLoadFactor));
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize);
+        c_nPercentExists = cfg.getSizeT("PercentExists", c_nPercentExists);
+        c_nPassCount = cfg.getSizeT("PassCount", c_nPassCount);
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor);
         c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState );
     }
 
index 0408d4c38d53abaeb573b310bd679b7fa9658b8b..cc4c12eed9512d544dd04aa964306c4acb41b9ff 100644 (file)
@@ -247,22 +247,5 @@ namespace map2 {
         CDSUNIT_DECLARE_RefinableMap
         CDSUNIT_DECLARE_CuckooMap
         CDSUNIT_DECLARE_StdMap
-
-        /*
-        CPPUNIT_TEST_SUITE( Map_find_int )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_MichaelMap_nogc
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SplitList_nogc
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_SkipListMap_nogc
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-        */
     };
 } // namespace map
index e1398b9c394bce4e038e9c4499b486870bc6305a..c0629f434e929034987c2ce9e8bf67c9d67ccc8c 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
+#include "map2/map_find_string.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_find_string );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
-
-    namespace {
-        static size_t  c_nThreadCount = 8      ;  // thread count
-        static size_t  c_nMapSize = 20000000   ;  // map size (count of searching item)
-        static size_t  c_nPercentExists = 50   ;  // percent of existing keys in searching sequence
-        static size_t  c_nPassCount = 2;
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
-    }
+    size_t Map_find_string::c_nThreadCount = 8      ;  // thread count
+    size_t Map_find_string::c_nMapSize = 20000000   ;  // map size (count of searching item)
+    size_t Map_find_string::c_nPercentExists = 50   ;  // percent of existing keys in searching sequence
+    size_t Map_find_string::c_nPassCount = 2;
+    size_t Map_find_string::c_nMaxLoadFactor = 8    ;  // maximum load factor
+    bool   Map_find_string::c_bPrintGCState = true;
 
-    class Map_find_string: public CppUnitMini::TestCase
+    void Map_find_string::generateSequence()
     {
-        typedef std::string  key_type;
-        struct value_type {
-            std::string const * pKey;
-            bool        bExists ;   // true - key in map, false - key not in map
-        };
-
-        typedef std::vector<value_type> ValueVector;
-        ValueVector             m_Arr;
-        size_t                  m_nRealMapSize;
-        bool                    m_bSeqInit;
-
-        template <typename Iterator, typename Map>
-        static bool check_result( Iterator const& it, Map const& map )
-        {
-            return it != map.end();
-        }
-        template <typename Map>
-        static bool check_result( bool b, Map const& )
-        {
-            return b;
-        }
-
-        template <class MAP>
-        class TestThread: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual TestThread *    clone()
-            {
-                return new TestThread( *this );
-            }
-        public:
-            struct Stat {
-                size_t      nSuccess;
-                size_t      nFailed;
-
-                Stat()
-                    : nSuccess(0)
-                    , nFailed(0)
-                {}
-            };
-
-            Stat    m_KeyExists;
-            Stat    m_KeyNotExists;
-
-        public:
-            TestThread( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            TestThread( TestThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_find_string&  getTest()
-            {
-                return reinterpret_cast<Map_find_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                ValueVector& arr = getTest().m_Arr;
-                //size_t nSize = arr.size();
-
-                MAP& rMap = m_Map;
-                for ( size_t nPass = 0; nPass < c_nPassCount; ++nPass ) {
-                    if ( m_nThreadNo & 1 ) {
-                        ValueVector::const_iterator itEnd = arr.end();
-                        for ( ValueVector::const_iterator it = arr.begin(); it != itEnd; ++it ) {
-                            auto bFound = rMap.find( *(it->pKey) );
-                            if ( it->bExists ) {
-                                if ( check_result(bFound, rMap))
-                                    ++m_KeyExists.nSuccess;
-                                else
-                                    ++m_KeyExists.nFailed;
-                            }
-                            else {
-                                if ( check_result(bFound, rMap))
-                                    ++m_KeyNotExists.nFailed;
-                                else
-                                    ++m_KeyNotExists.nSuccess;
-                            }
-                        }
-                    }
-                    else {
-                        ValueVector::const_reverse_iterator itEnd = arr.rend();
-                        for ( ValueVector::const_reverse_iterator it = arr.rbegin(); it != itEnd; ++it ) {
-                            auto bFound = rMap.find( *(it->pKey) );
-                            if ( it->bExists ) {
-                                if ( check_result(bFound, rMap))
-                                    ++m_KeyExists.nSuccess;
-                                else
-                                    ++m_KeyExists.nFailed;
-                            }
-                            else {
-                                if ( check_result( bFound, rMap ))
-                                    ++m_KeyNotExists.nFailed;
-                                else
-                                    ++m_KeyNotExists.nSuccess;
-                            }
-                        }
-                    }
-                }
-            }
-        };
-
-    public:
-        Map_find_string()
-            : m_bSeqInit( false )
-        {}
-
-    protected:
-
-        void generateSequence()
-        {
-            size_t nPercent = c_nPercentExists;
-
-            if ( nPercent > 100 )
-                nPercent = 100;
-            else if ( nPercent < 1 )
-                nPercent = 1;
-
-            m_nRealMapSize = 0;
-
-            std::vector<std::string> const & arrString = CppUnitMini::TestCase::getTestStrings();
-            size_t nSize = arrString.size();
-            if ( nSize > c_nMapSize )
-                nSize = c_nMapSize;
-            m_Arr.resize( nSize );
-            for ( size_t i = 0; i < nSize; ++i ) {
-                m_Arr[i].pKey = &( arrString[i] );
-                m_Arr[i].bExists = CppUnitMini::Rand( 100 ) <= nPercent;
-                if ( m_Arr[i].bExists )
-                    ++m_nRealMapSize;
-            }
+        size_t nPercent = c_nPercentExists;
+
+        if ( nPercent > 100 )
+            nPercent = 100;
+        else if ( nPercent < 1 )
+            nPercent = 1;
+
+        m_nRealMapSize = 0;
+
+        std::vector<std::string> const & arrString = CppUnitMini::TestCase::getTestStrings();
+        size_t nSize = arrString.size();
+        if ( nSize > c_nMapSize )
+            nSize = c_nMapSize;
+        m_Arr.resize( nSize );
+        for ( size_t i = 0; i < nSize; ++i ) {
+            m_Arr[i].pKey = &( arrString[i] );
+            m_Arr[i].bExists = CppUnitMini::Rand( 100 ) <= nPercent;
+            if ( m_Arr[i].bExists )
+                ++m_nRealMapSize;
         }
+    }
 
+    void Map_find_string::initTestSequence()
+    {
+        if ( !m_bSeqInit ) {
+            m_bSeqInit = true;
 
-        template <class MAP>
-        void find_string_test( MAP& testMap )
-        {
-            typedef TestThread<MAP>     Thread;
+            CPPUNIT_MSG( "Generating test data...");
             cds::OS::Timer    timer;
-
-            // Fill the map
-            CPPUNIT_MSG( "  Fill map...");
-            timer.reset();
-            for ( size_t i = 0; i < m_Arr.size(); ++i ) {
-                // All keys in arrData are unique, insert() must be successful
-                if ( m_Arr[i].bExists )
-                    CPPUNIT_ASSERT( check_result( testMap.insert( *(m_Arr[i].pKey), m_Arr[i] ), testMap ));
-            }
+            generateSequence();
             CPPUNIT_MSG( "   Duration=" << timer.duration() );
-
-            CPPUNIT_MSG( "  Searching...");
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new Thread( pool, testMap ), c_nThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            // Postcondition: the number of success searching == the number of map item
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                Thread * pThread = static_cast<Thread *>( *it );
-                CPPUNIT_CHECK( pThread->m_KeyExists.nSuccess == m_nRealMapSize * c_nPassCount );
-                CPPUNIT_CHECK( pThread->m_KeyExists.nFailed == 0 );
-                CPPUNIT_CHECK( pThread->m_KeyNotExists.nSuccess == (m_Arr.size() - m_nRealMapSize) * c_nPassCount );
-                CPPUNIT_CHECK( pThread->m_KeyNotExists.nFailed == 0 );
-            }
-
-            check_before_cleanup( testMap );
-
-            testMap.clear();
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        void initTestSequence()
-        {
-            if ( !m_bSeqInit ) {
-                m_bSeqInit = true;
-
-                CPPUNIT_MSG( "Generating test data...");
-                cds::OS::Timer    timer;
-                generateSequence();
-                CPPUNIT_MSG( "   Duration=" << timer.duration() );
-                CPPUNIT_MSG( "Map size=" << m_nRealMapSize << " find key loop=" << m_Arr.size() << " (" << c_nPercentExists << "% success)" );
-                CPPUNIT_MSG( "Thread count=" << c_nThreadCount << " Pass count=" << c_nPassCount );
-            }
-        }
-
-        template <class MAP>
-        void test()
-        {
-            initTestSequence();
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                MAP  testMap( m_Arr.size(), nLoadFactor );
-                find_string_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class MAP>
-        void test_nolf()
-        {
-            initTestSequence();
-
-            MAP testMap;
-            find_string_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nThreadCount = cfg.getULong("ThreadCount", 8 )        ; // thread count
-            c_nMapSize = cfg.getULong("MapSize", 20000000 )         ;  // map size (count of searching item)
-            c_nPercentExists = cfg.getULong("PercentExists", 50 )   ;  // percent of existing keys in searching sequence
-            c_nPassCount = cfg.getULong("PassCount", 2 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
+            CPPUNIT_MSG( "Map size=" << m_nRealMapSize << " find key loop=" << m_Arr.size() << " (" << c_nPercentExists << "% success)" );
+            CPPUNIT_MSG( "Thread count=" << c_nThreadCount << " Pass count=" << c_nPassCount );
         }
+    }
 
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_MichaelMap_nogc
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SplitList_nogc
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_SkipListMap_nogc
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_find_string )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_MichaelMap_nogc
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SplitList_nogc
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_SkipListMap_nogc
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-
-    };
+    void Map_find_string::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize );
+        c_nPercentExists = cfg.getSizeT("PercentExists", c_nPercentExists );
+        c_nPassCount = cfg.getSizeT("PassCount", c_nPassCount );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
+    }
 
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_find_string );
+    void Map_find_string::myRun(const char *in_name, bool invert /*= false*/)
+    {
+        setUpParams( m_Cfg.get( "Map_find_string" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+        run_StdMap(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace map2
diff --git a/tests/unit/map2/map_find_string.h b/tests/unit/map2/map_find_string.h
new file mode 100644 (file)
index 0000000..8796698
--- /dev/null
@@ -0,0 +1,239 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_find_string: public CppUnitMini::TestCase
+    {
+        static size_t  c_nThreadCount;      // thread count
+        static size_t  c_nMapSize;          // map size (count of searching item)
+        static size_t  c_nPercentExists;    // percent of existing keys in searching sequence
+        static size_t  c_nPassCount;
+        static size_t  c_nMaxLoadFactor;    // maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef std::string  key_type;
+        struct value_type {
+            std::string const * pKey;
+            bool        bExists ;   // true - key in map, false - key not in map
+        };
+
+        typedef std::vector<value_type> ValueVector;
+        ValueVector             m_Arr;
+        size_t                  m_nRealMapSize;
+        bool                    m_bSeqInit;
+
+        template <typename Iterator, typename Map>
+        static bool check_result( Iterator const& it, Map const& map )
+        {
+            return it != map.end();
+        }
+        template <typename Map>
+        static bool check_result( bool b, Map const& )
+        {
+            return b;
+        }
+
+        template <class MAP>
+        class TestThread: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual TestThread *    clone()
+            {
+                return new TestThread( *this );
+            }
+        public:
+            struct Stat {
+                size_t      nSuccess;
+                size_t      nFailed;
+
+                Stat()
+                    : nSuccess(0)
+                    , nFailed(0)
+                {}
+            };
+
+            Stat    m_KeyExists;
+            Stat    m_KeyNotExists;
+
+        public:
+            TestThread( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            TestThread( TestThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_find_string&  getTest()
+            {
+                return reinterpret_cast<Map_find_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                ValueVector& arr = getTest().m_Arr;
+                //size_t nSize = arr.size();
+
+                MAP& rMap = m_Map;
+                for ( size_t nPass = 0; nPass < c_nPassCount; ++nPass ) {
+                    if ( m_nThreadNo & 1 ) {
+                        ValueVector::const_iterator itEnd = arr.end();
+                        for ( ValueVector::const_iterator it = arr.begin(); it != itEnd; ++it ) {
+                            auto bFound = rMap.find( *(it->pKey) );
+                            if ( it->bExists ) {
+                                if ( check_result(bFound, rMap))
+                                    ++m_KeyExists.nSuccess;
+                                else
+                                    ++m_KeyExists.nFailed;
+                            }
+                            else {
+                                if ( check_result(bFound, rMap))
+                                    ++m_KeyNotExists.nFailed;
+                                else
+                                    ++m_KeyNotExists.nSuccess;
+                            }
+                        }
+                    }
+                    else {
+                        ValueVector::const_reverse_iterator itEnd = arr.rend();
+                        for ( ValueVector::const_reverse_iterator it = arr.rbegin(); it != itEnd; ++it ) {
+                            auto bFound = rMap.find( *(it->pKey) );
+                            if ( it->bExists ) {
+                                if ( check_result(bFound, rMap))
+                                    ++m_KeyExists.nSuccess;
+                                else
+                                    ++m_KeyExists.nFailed;
+                            }
+                            else {
+                                if ( check_result( bFound, rMap ))
+                                    ++m_KeyNotExists.nFailed;
+                                else
+                                    ++m_KeyNotExists.nSuccess;
+                            }
+                        }
+                    }
+                }
+            }
+        };
+
+    public:
+        Map_find_string()
+            : m_bSeqInit( false )
+        {}
+
+    protected:
+
+        void generateSequence();
+
+        template <class MAP>
+        void find_string_test( MAP& testMap )
+        {
+            typedef TestThread<MAP>     Thread;
+            cds::OS::Timer    timer;
+
+            // Fill the map
+            CPPUNIT_MSG( "  Fill map...");
+            timer.reset();
+            for ( size_t i = 0; i < m_Arr.size(); ++i ) {
+                // All keys in arrData are unique, insert() must be successful
+                if ( m_Arr[i].bExists )
+                    CPPUNIT_ASSERT( check_result( testMap.insert( *(m_Arr[i].pKey), m_Arr[i] ), testMap ));
+            }
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+
+            CPPUNIT_MSG( "  Searching...");
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new Thread( pool, testMap ), c_nThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            // Postcondition: the number of success searching == the number of map item
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                Thread * pThread = static_cast<Thread *>( *it );
+                CPPUNIT_CHECK( pThread->m_KeyExists.nSuccess == m_nRealMapSize * c_nPassCount );
+                CPPUNIT_CHECK( pThread->m_KeyExists.nFailed == 0 );
+                CPPUNIT_CHECK( pThread->m_KeyNotExists.nSuccess == (m_Arr.size() - m_nRealMapSize) * c_nPassCount );
+                CPPUNIT_CHECK( pThread->m_KeyNotExists.nFailed == 0 );
+            }
+
+            check_before_cleanup( testMap );
+
+            testMap.clear();
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        void initTestSequence();
+
+        template <class MAP>
+        void test()
+        {
+            initTestSequence();
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                MAP  testMap( m_Arr.size(), nLoadFactor );
+                find_string_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class MAP>
+        void test_nolf()
+        {
+            initTestSequence();
+
+            MAP testMap;
+            find_string_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+        void run_StdMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_MichaelMap_nogc
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SplitList_nogc
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_SkipListMap_nogc
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_bronsonavltree.cpp b/tests/unit/map2/map_find_string_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..b74d017
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_cuckoo.cpp b/tests/unit/map2/map_find_string_cuckoo.cpp
new file mode 100644 (file)
index 0000000..c508512
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_ellentree.cpp b/tests/unit/map2/map_find_string_ellentree.cpp
new file mode 100644 (file)
index 0000000..9539c7d
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_michael.cpp b/tests/unit/map2/map_find_string_michael.cpp
new file mode 100644 (file)
index 0000000..5e9f61b
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+        CDSUNIT_TEST_MichaelMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_refinable.cpp b/tests/unit/map2/map_find_string_refinable.cpp
new file mode 100644 (file)
index 0000000..dd9a91f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_skip.cpp b/tests/unit/map2/map_find_string_skip.cpp
new file mode 100644 (file)
index 0000000..47671c1
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+        CDSUNIT_TEST_SkipListMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_split.cpp b/tests/unit/map2/map_find_string_split.cpp
new file mode 100644 (file)
index 0000000..d2095b1
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_SplitList )
+        CDSUNIT_TEST_SplitList
+        CDSUNIT_TEST_SplitList_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_std.cpp b/tests/unit/map2/map_find_string_std.cpp
new file mode 100644 (file)
index 0000000..d268977
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_StdMap )
+        CDSUNIT_TEST_StdMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_striped.cpp b/tests/unit/map2/map_find_string_striped.cpp
new file mode 100644 (file)
index 0000000..1d8280b
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2