Adds check for sequential map test case
[libcds.git] / test / stress / sequential / sequential-map / insdelfind / map_insdelfind.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "map_type.h"
32
33 namespace map {
34
35
36     class Map_InsDelFind: public cds_test::stress_fixture
37     {
38     public:
39         static size_t s_nMapSize;           // initial map size
40
41         static size_t s_nPassCount;
42         static size_t s_nBronsonAVLTreeMapPassCount;
43         static size_t s_nEllenBinTreeMapPassCount;
44         static size_t s_nFeldmanPassCount;
45         static size_t s_nMichaelMapPassCount;
46         static size_t s_nSkipListMapPassCount;
47         static size_t s_nSplitListMapPassCount;
48
49         static size_t s_nThreadCount;       // thread count
50         static size_t s_nMaxLoadFactor;     // maximum load factor
51         static unsigned int s_nInsertPercentage;
52         static unsigned int s_nDeletePercentage;
53         static unsigned int s_nDuration;    // test duration, seconds
54
55         static size_t s_nCuckooInitialSize;         // initial size for CuckooMap
56         static size_t s_nCuckooProbesetSize;        // CuckooMap probeset size (only for list-based probeset)
57         static size_t s_nCuckooProbesetThreshold;   // CuckooMap probeset threshold (o - use default)
58
59         static size_t s_nFeldmanMap_HeadBits;
60         static size_t s_nFeldmanMap_ArrayBits;
61
62         static size_t  s_nLoadFactor;  // current load factor
63
64         static void SetUpTestCase();
65         //static void TearDownTestCase();
66
67     public:
68         enum actions
69         {
70             do_find,
71             do_insert,
72             do_delete
73         };
74         static const unsigned int c_nShuffleSize = 100;
75         static actions s_arrShuffle[c_nShuffleSize];
76
77     protected:
78         typedef size_t  key_type;
79         typedef size_t  value_type;
80
81         template <class Map>
82         class Worker: public cds_test::thread
83         {
84             typedef cds_test::thread base_class;
85             Map&     m_Map;
86
87         public:
88             size_t  m_nInsertSuccess = 0;
89             size_t  m_nInsertFailed = 0;
90             size_t  m_nDeleteSuccess = 0;
91             size_t  m_nDeleteFailed = 0;
92             size_t  m_nFindSuccess = 0;
93             size_t  m_nFindFailed = 0;
94
95         public:
96             Worker( cds_test::thread_pool& pool, Map& map )
97                 : base_class( pool )
98                 , m_Map( map )
99             {}
100
101             Worker( Worker& src )
102                 : base_class( src )
103                 , m_Map( src.m_Map )
104             {}
105
106             virtual thread * clone()
107             {
108                 return new Worker( *this );
109             }
110
111             typedef std::pair< key_type const, value_type > map_value_type;
112
113             struct update_functor {
114                 template <typename Q>
115                 void operator()( bool /*bNew*/, map_value_type& /*cur*/, Q const& /*val*/ ) const
116                 {}
117
118                 // FeldmanHashMap
119                 void operator()( map_value_type& /*cur*/, map_value_type* /*old*/) const
120                 {}
121
122                 // MichaelMap
123                 void operator()( bool /*bNew*/, map_value_type& /*cur*/ ) const
124                 {}
125
126                 // BronsonAVLTreeMap
127                 void operator()( bool /*bNew*/, key_type /*key*/, value_type& /*val*/ ) const
128                 {}
129             };
130
131             virtual void test()
132             {
133                 Map& rMap = m_Map;
134                 size_t pass_count = Map_InsDelFind::s_nPassCount;
135
136                 size_t nInsertedNum = 0;
137                 size_t nUninsertedNum = 0;
138                 for (size_t count = 0; count < pass_count; count++) {
139                   bool shouldUpdate = true;
140                   for (size_t i = 0; i < s_nMapSize; ++i) {
141                     // The number to operate on the map.
142                     size_t n = i;
143                     // Insert
144                     if (i % s_nInsertPercentage == 1) {
145                       nInsertedNum++;
146                       if (!shouldUpdate) {
147                         if (rMap.insert(n, n))
148                           ++m_nInsertSuccess;
149                         else
150                           ++m_nInsertFailed;
151                         shouldUpdate = true;
152                       } else {
153                         if (rMap.update(n, update_functor(), true).first)
154                           ++m_nInsertSuccess;
155                         else
156                           ++m_nInsertFailed;
157                         shouldUpdate = false;
158                       }
159                     } else {
160                       nUninsertedNum++;
161                     }
162                     // Find
163                     if (rMap.contains(n))
164                       ++m_nFindSuccess;
165                     else
166                       ++m_nFindFailed;
167                     // Delete
168                     if (i % s_nInsertPercentage == 1) {
169
170                       if (rMap.erase(n))
171                         ++m_nDeleteSuccess;
172                       else
173                         ++m_nDeleteFailed;
174                       break;
175                     }
176                   }
177                 }
178                 EXPECT_EQ(nInsertedNum, m_nFindSuccess);
179                 EXPECT_EQ(nUninsertedNum, m_nFindFailed);
180                 EXPECT_EQ(m_nDeleteSuccess, nInsertedNum);
181                 EXPECT_EQ(m_nDeleteFailed, 0);
182             }
183         };
184
185     protected:
186         template <class Map>
187         void do_test( Map& testMap )
188         {
189             typedef Worker<Map> worker;
190             cds_test::thread_pool& pool = get_pool();
191             std::unique_ptr<worker> worker_thrd(new worker(pool, testMap));
192             worker_thrd->test();
193
194             testMap.clear();
195             EXPECT_TRUE( testMap.empty());
196             additional_cleanup( testMap );
197         }
198
199         template <class Map>
200         void run_test()
201         {
202             Map testMap( *this );
203             do_test( testMap );
204         }
205
206         template <class Map>
207         void run_bronson_avl_tree() {
208           Map_InsDelFind::s_nPassCount =
209               Map_InsDelFind::s_nBronsonAVLTreeMapPassCount;
210           run_test<Map>();
211         }
212
213         template <class Map>
214         void run_ellen_bin_tree() {
215           Map_InsDelFind::s_nPassCount =
216               Map_InsDelFind::s_nEllenBinTreeMapPassCount;
217           run_test<Map>();
218         }
219
220         template <class Map>
221         void run_skip_list() {
222           Map_InsDelFind::s_nPassCount =
223               Map_InsDelFind::s_nSkipListMapPassCount;
224           run_test<Map>();
225         }
226
227         template <class Map>
228         void run_feldman() {
229           Map_InsDelFind::s_nPassCount =
230               Map_InsDelFind::s_nFeldmanPassCount;
231           run_test<Map>();
232         }
233     };
234
235     class Map_InsDelFind_LF: public Map_InsDelFind
236         , public ::testing::WithParamInterface<size_t>
237     {
238     public:
239         template <class Map>
240         void run_test()
241         {
242             s_nLoadFactor = GetParam();
243             propout() << std::make_pair( "load_factor", s_nLoadFactor );
244             Map_InsDelFind::run_test<Map>();
245         }
246
247                                 template <class Map>
248         void run_michael() {
249           Map_InsDelFind::s_nPassCount =
250               Map_InsDelFind::s_nMichaelMapPassCount;
251           Map_InsDelFind_LF::run_test<Map>();
252         }
253
254         template <class Map>
255         void run_split_list() {
256           Map_InsDelFind::s_nPassCount =
257               Map_InsDelFind::s_nSplitListMapPassCount;
258           Map_InsDelFind_LF::run_test<Map>();
259         }
260
261         static std::vector<size_t> get_load_factors();
262     };
263
264 } // namespace map