3 #ifndef CDSTEST_HDR_CUCKOO_MAP_H
4 #define CDSTEST_HDR_CUCKOO_MAP_H
5 #include "size_check.h"
7 #include "cppunit/cppunit_proxy.h"
8 #include <cds/os/timer.h>
9 #include <cds/opt/hash.h>
10 #include <functional> // ref
12 namespace cds { namespace container {}}
15 using misc::check_size;
17 namespace cc = cds::container;
18 namespace co = cds::opt;
20 class CuckooMapHdrTest: public CppUnitMini::TestCase
36 value_type( value_type&& v )
40 value_type( value_type const& v )
44 value_type& operator=( value_type const& v )
51 typedef std::pair<key_type const, value_type> pair_type;
55 bool operator ()(int v1, int v2 ) const
62 int operator ()(int v1, int v2 ) const
66 return v1 > v2 ? 1 : 0;
71 bool operator ()(int v1, int v2 ) const
78 size_t operator()( int i ) const
80 return co::v::hash<int>()( i );
84 struct simple_item_counter {
106 operator size_t() const
112 template <typename Map>
113 struct insert_functor
115 typedef typename Map::value_type pair_type;
118 void operator()( pair_type& item )
120 item.second.m_val = item.first * 3;
124 void operator()( bool bNew, pair_type& item )
127 item.second.m_val = item.first * 2;
129 item.second.m_val = item.first * 5;
136 check_value( int nExpected )
137 : m_nExpected( nExpected )
140 template <typename T>
141 void operator ()( T& pair )
143 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
145 template <typename T, typename Q>
146 void operator ()( T& pair, Q )
148 CPPUNIT_ASSERT_CURRENT( pair.second.m_val == m_nExpected );
152 struct extract_functor
155 void operator()( pair_type const& val )
157 *m_pVal = val.second.m_val;
163 void test_iter( Map& s)
165 typedef typename Map::iterator iterator;
166 typedef typename Map::const_iterator const_iterator;
168 const int nMaxCount = 500;
169 for ( int i = 0; i < nMaxCount; ++i ) {
170 CPPUNIT_ASSERT( s.insert( i, i * 2 ));
174 for ( iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) {
175 CPPUNIT_ASSERT( it->first * 2 == it->second.m_val );
176 CPPUNIT_ASSERT( (*it).first * 2 == (*it).second.m_val );
177 it->second.m_val = it->first;
180 CPPUNIT_ASSERT( nCount == nMaxCount );
182 Map const& refSet = s;
184 for ( const_iterator it = refSet.begin(), itEnd = refSet.end(); it != itEnd; ++it ) {
185 CPPUNIT_ASSERT( it->first == it->second.m_val );
186 CPPUNIT_ASSERT( (*it).first == (*it).second.m_val );
189 CPPUNIT_ASSERT( nCount == nMaxCount );
198 CPPUNIT_ASSERT( m.bucket_count() == 32 );
199 CPPUNIT_ASSERT( m.lock_count() == 32 );
201 test_cuckoo_with( m );
203 // Iterators is not yet supported for CuckooMap
205 //CPPUNIT_ASSERT( m.empty() );
206 //CPPUNIT_ASSERT( check_size( m, 0 ));
210 //*******************************************
211 // If erase_with && find_with are supported
213 void test_int_with( Map& m )
215 std::pair<bool, bool> updateResult;
216 typedef typename std::conditional< Map::c_isSorted, less, equal >::type predicate;
219 CPPUNIT_ASSERT( m.empty() );
220 CPPUNIT_ASSERT( check_size( m, 0 ));
221 CPPUNIT_ASSERT( !m.contains(25) );
222 CPPUNIT_ASSERT( m.insert( 25 ) ) ; // value = 0
223 CPPUNIT_ASSERT( m.contains(25) );
224 CPPUNIT_ASSERT( !m.empty() );
225 CPPUNIT_ASSERT( check_size( m, 1 ));
226 CPPUNIT_ASSERT( m.contains(25) );
228 CPPUNIT_ASSERT( !m.insert( 25 ) );
229 CPPUNIT_ASSERT( !m.empty() );
230 CPPUNIT_ASSERT( check_size( m, 1 ));
232 CPPUNIT_ASSERT( !m.contains(10, predicate()) );
233 CPPUNIT_ASSERT( m.insert( 10, 10 ) );
234 CPPUNIT_ASSERT( !m.empty() );
235 CPPUNIT_ASSERT( check_size( m, 2 ));
236 CPPUNIT_ASSERT( m.contains(10, predicate()) );
238 CPPUNIT_ASSERT( !m.insert( 10, 20 ) );
239 CPPUNIT_ASSERT( !m.empty() );
240 CPPUNIT_ASSERT( check_size( m, 2 ));
242 CPPUNIT_ASSERT( !m.contains(30) );
243 CPPUNIT_ASSERT( m.insert_with( 30, insert_functor<Map>() ) ) ; // value = 90
244 CPPUNIT_ASSERT( !m.empty() );
245 CPPUNIT_ASSERT( check_size( m, 3 ));
246 CPPUNIT_ASSERT( m.contains(30) );
248 CPPUNIT_ASSERT( !m.insert_with( 10, insert_functor<Map>() ) );
249 CPPUNIT_ASSERT( !m.insert_with( 25, insert_functor<Map>() ) );
250 CPPUNIT_ASSERT( !m.insert_with( 30, insert_functor<Map>() ) );
253 CPPUNIT_ASSERT( !m.contains(27) );
254 updateResult = m.update(27, insert_functor<Map>(), false);
255 CPPUNIT_ASSERT(!updateResult.first);
256 CPPUNIT_ASSERT(!updateResult.second);
257 CPPUNIT_ASSERT(!m.contains(27));
258 updateResult = m.update( 27, insert_functor<Map>() ) ; // value = 54
259 CPPUNIT_ASSERT( updateResult.first );
260 CPPUNIT_ASSERT( updateResult.second );
261 CPPUNIT_ASSERT( m.contains(27) );
265 CPPUNIT_ASSERT( m.find( 10, std::ref(chk) ));
267 CPPUNIT_ASSERT( m.find_with( 25, predicate(), std::ref(chk) ));
268 chk.m_nExpected = 90;
269 CPPUNIT_ASSERT( m.find( 30, std::ref(chk) ));
270 chk.m_nExpected = 54;
271 CPPUNIT_ASSERT( m.find( 27, std::ref(chk) ));
273 updateResult = m.update( 10, insert_functor<Map>() ) ; // value = 50
274 CPPUNIT_ASSERT( updateResult.first );
275 CPPUNIT_ASSERT( !updateResult.second );
276 chk.m_nExpected = 50;
277 CPPUNIT_ASSERT( m.find( 10, std::ref(chk) ));
280 CPPUNIT_ASSERT( !m.contains(100) );
281 CPPUNIT_ASSERT( !m.erase( 100 )) ; // not found
283 CPPUNIT_ASSERT( m.contains(25) );
284 CPPUNIT_ASSERT( check_size( m, 4 ));
285 CPPUNIT_ASSERT( m.erase( 25 ));
286 CPPUNIT_ASSERT( !m.empty() );
287 CPPUNIT_ASSERT( check_size( m, 3 ));
288 CPPUNIT_ASSERT( !m.contains(25) );
289 CPPUNIT_ASSERT( !m.erase( 25 ));
291 CPPUNIT_ASSERT( !m.contains(258) );
292 CPPUNIT_ASSERT( m.insert(258))
293 CPPUNIT_ASSERT( check_size( m, 4 ));
294 CPPUNIT_ASSERT( m.contains(258, predicate()) );
295 CPPUNIT_ASSERT( m.erase_with( 258, predicate() ));
296 CPPUNIT_ASSERT( !m.empty() );
297 CPPUNIT_ASSERT( check_size( m, 3 ));
298 CPPUNIT_ASSERT( !m.contains(258) );
299 CPPUNIT_ASSERT( !m.erase_with( 258, predicate() ));
305 CPPUNIT_ASSERT( !m.contains(29) );
306 CPPUNIT_ASSERT( m.insert(29, 290))
307 CPPUNIT_ASSERT( m.erase_with( 29, predicate(), std::ref(ext)));
308 CPPUNIT_ASSERT( !m.empty() );
309 CPPUNIT_ASSERT( check_size( m, 3 ));
310 CPPUNIT_ASSERT( nVal == 290 );
312 CPPUNIT_ASSERT( !m.erase_with( 29, predicate(), std::ref( ext ) ) );
313 CPPUNIT_ASSERT( nVal == -1 );
315 CPPUNIT_ASSERT( m.erase( 30, std::ref( ext ) ) );
316 CPPUNIT_ASSERT( !m.empty() );
317 CPPUNIT_ASSERT( check_size( m, 2 ));
318 CPPUNIT_ASSERT( nVal == 90 );
320 CPPUNIT_ASSERT( !m.erase( 30, std::ref( ext ) ) );
321 CPPUNIT_ASSERT( nVal == -1 );
324 CPPUNIT_ASSERT( m.empty() );
325 CPPUNIT_ASSERT( check_size( m, 0 ));
328 CPPUNIT_ASSERT( m.emplace(126) ) ; // key = 126, val = 0
329 CPPUNIT_ASSERT( m.emplace(137, 731)) ; // key = 137, val = 731
330 CPPUNIT_ASSERT( m.emplace( 149, value_type(941) )) ; // key = 149, val = 941
332 CPPUNIT_ASSERT( !m.empty() );
333 CPPUNIT_ASSERT( check_size( m, 3 ));
336 CPPUNIT_ASSERT( m.find( 126, std::ref(chk) ));
337 chk.m_nExpected = 731;
338 CPPUNIT_ASSERT( m.find_with( 137, predicate(), std::ref(chk) ));
339 chk.m_nExpected = 941;
340 CPPUNIT_ASSERT( m.find( 149, std::ref(chk) ));
342 CPPUNIT_ASSERT( !m.emplace(126, 621)) ; // already in map
344 CPPUNIT_ASSERT( m.find( 126, std::ref(chk) ));
345 CPPUNIT_ASSERT( !m.empty() );
346 CPPUNIT_ASSERT( check_size( m, 3 ));
349 CPPUNIT_ASSERT( m.empty() );
350 CPPUNIT_ASSERT( check_size( m, 0 ));
354 void test_cuckoo_with(Map& m)
356 cds::OS::Timer timer;
360 // Iterators is not yet supported
362 //CPPUNIT_ASSERT( m.empty() );
363 //CPPUNIT_ASSERT( check_size( m, 0 ));
367 CPPUNIT_ASSERT( m.empty() );
368 CPPUNIT_ASSERT( check_size( m, 0 ));
371 for ( int i = 0; i < 40000; i++ ) {
375 CPPUNIT_MSG( " Duration=" << timer.duration() );
378 void Cuckoo_striped_list();
379 void Cuckoo_striped_vector();
380 void Cuckoo_refinable_list();
381 void Cuckoo_refinable_vector();
383 CPPUNIT_TEST_SUITE(CuckooMapHdrTest)
384 CPPUNIT_TEST(Cuckoo_striped_list)
385 CPPUNIT_TEST(Cuckoo_striped_vector)
386 CPPUNIT_TEST(Cuckoo_refinable_list)
387 CPPUNIT_TEST(Cuckoo_refinable_vector)
388 CPPUNIT_TEST_SUITE_END()
393 #endif // #ifndef CDSTEST_HDR_CUCKOO_MAP_H