3 #ifndef CDSTEST_HDR_INTRUSIVE_MULTILEVEL_HASHSET_H
4 #define CDSTEST_HDR_INTRUSIVE_MULTILEVEL_HASHSET_H
6 #include "cppunit/cppunit_proxy.h"
10 namespace intrusive {}
15 namespace ci = cds::intrusive;
16 namespace co = cds::opt;
18 class IntrusiveMultiLevelHashSetHdrTest: public CppUnitMini::TestCase
20 template <typename Hash>
23 unsigned int nDisposeCount ; // count of disposer calling
25 unsigned int nInsertCall;
26 unsigned int nFindCall;
27 unsigned int nEraseCall;
37 template <typename Hash>
40 Hash const& operator()( Item<Hash> const& i ) const
46 struct item_disposer {
47 template <typename Hash>
48 void operator()( Item<Hash> * p )
54 template <typename Set>
57 typedef typename Set::hash_type hash_type;
58 typedef typename Set::value_type value_type;
60 std::hash<hash_type> hasher;
62 size_t const arrCapacity = 1000;
63 std::vector< value_type > arrValue;
64 arrValue.reserve( arrCapacity );
65 for ( size_t i = 0; i < arrCapacity; ++i ) {
66 arrValue.emplace_back( value_type() );
67 arrValue.back().hash = hasher( i );
69 CPPUNIT_ASSERT( arrValue.size() == arrCapacity );
72 CPPUNIT_ASSERT(s.head_size() == 16 );
73 CPPUNIT_ASSERT(s.array_node_size() == 4 );
76 CPPUNIT_ASSERT(s.size() == 0 );
77 CPPUNIT_ASSERT(s.empty() );
78 for ( auto& el : arrValue ) {
79 CPPUNIT_ASSERT( s.insert( el ));
80 CPPUNIT_ASSERT(s.contains( el.hash ));
82 CPPUNIT_ASSERT(s.size() == arrCapacity );
83 for ( auto& el : arrValue ) {
84 CPPUNIT_ASSERT(s.contains( el.hash ));
85 CPPUNIT_ASSERT( !s.insert( el ) );
87 CPPUNIT_ASSERT(s.size() == arrCapacity );
88 CPPUNIT_ASSERT( !s.empty() );
90 // update() exists test
91 for ( auto& el : arrValue ) {
93 std::tie(bOp, bInsert) = s.update( el, false );
94 CPPUNIT_ASSERT( bOp );
95 CPPUNIT_ASSERT( !bInsert );
96 CPPUNIT_ASSERT( el.nFindCall == 0 );
97 CPPUNIT_ASSERT(s.find(el.hash, [](value_type& v) { v.nFindCall++; } ));
98 CPPUNIT_ASSERT( el.nFindCall == 1 );
102 CPPUNIT_ASSERT(s.size() == arrCapacity );
103 for ( auto const& el : arrValue ) {
104 CPPUNIT_ASSERT(s.unlink( el ));
105 CPPUNIT_ASSERT(!s.contains( el.hash ));
107 CPPUNIT_ASSERT(s.size() == 0 );
108 Set::gc::force_dispose();
109 for ( auto const& el : arrValue ) {
110 CPPUNIT_ASSERT( el.nDisposeCount == 1 );
114 for ( auto& el : arrValue )
115 el.hash = hasher( el.hash );
118 CPPUNIT_ASSERT(s.size() == 0 );
119 for ( auto& el : arrValue ) {
120 CPPUNIT_ASSERT( s.insert( el, []( value_type& v ) { ++v.nInsertCall; } ));
121 CPPUNIT_ASSERT(s.contains( el.hash ));
122 CPPUNIT_ASSERT( el.nInsertCall == 1 );
124 CPPUNIT_ASSERT(s.size() == arrCapacity );
125 for ( auto& el : arrValue ) {
126 CPPUNIT_ASSERT(s.contains( el.hash ));
127 CPPUNIT_ASSERT( !s.insert( el ) );
129 CPPUNIT_ASSERT(s.size() == arrCapacity );
130 CPPUNIT_ASSERT( !s.empty() );
132 for ( auto& el : arrValue )
133 el.nDisposeCount = 0;
136 CPPUNIT_ASSERT(s.size() == 0 );
137 Set::gc::force_dispose();
138 for ( auto const& el : arrValue ) {
139 CPPUNIT_ASSERT( el.nDisposeCount == 1 );
143 for ( auto& el : arrValue )
144 el.hash = hasher( el.hash );
147 for ( auto& el : arrValue ) {
149 std::tie(bOp, bInsert) = s.update( el, false );
150 CPPUNIT_ASSERT( !bOp );
151 CPPUNIT_ASSERT( !bInsert );
152 CPPUNIT_ASSERT( !s.contains( el.hash ));
154 std::tie(bOp, bInsert) = s.update( el, true );
155 CPPUNIT_ASSERT( bOp );
156 CPPUNIT_ASSERT( bInsert );
157 CPPUNIT_ASSERT( s.contains( el.hash ));
159 CPPUNIT_ASSERT(s.size() == arrCapacity );
162 for ( auto& el : arrValue ) {
163 el.nDisposeCount = 0;
164 CPPUNIT_ASSERT( s.contains( el.hash ));
165 CPPUNIT_ASSERT(s.erase( el.hash ));
166 CPPUNIT_ASSERT( !s.contains( el.hash ));
167 CPPUNIT_ASSERT( !s.erase( el.hash ));
169 CPPUNIT_ASSERT(s.size() == 0 );
170 Set::gc::force_dispose();
171 for ( auto& el : arrValue ) {
172 CPPUNIT_ASSERT( el.nDisposeCount == 1 );
173 CPPUNIT_ASSERT(s.insert( el ));
176 // erase with functor, get() test
177 for ( auto& el : arrValue ) {
178 el.nDisposeCount = 0;
179 CPPUNIT_ASSERT( s.contains( el.hash ) );
181 typename Set::guarded_ptr gp{ s.get( el.hash ) };
182 CPPUNIT_ASSERT( gp );
183 CPPUNIT_ASSERT( gp->nEraseCall == 0);
184 CPPUNIT_ASSERT(s.erase( gp->hash, []( value_type& i ) { ++i.nEraseCall; } ));
185 CPPUNIT_ASSERT( gp->nEraseCall == 1);
186 Set::gc::force_dispose();
187 CPPUNIT_ASSERT( gp->nDisposeCount == 0 );
189 CPPUNIT_ASSERT( !s.contains( el.hash ));
190 CPPUNIT_ASSERT( !s.erase( el.hash ));
191 CPPUNIT_ASSERT( el.nEraseCall == 1 );
192 Set::gc::force_dispose();
193 CPPUNIT_ASSERT( el.nDisposeCount == 1 );
195 CPPUNIT_ASSERT(s.size() == 0 );
198 for ( auto& el : arrValue ) {
199 el.hash = hasher( el.hash );
200 el.nDisposeCount = 0;
202 std::tie(bOp, bInsert) = s.update( el );
203 CPPUNIT_ASSERT( bOp );
204 CPPUNIT_ASSERT( bInsert );
206 CPPUNIT_ASSERT(s.size() == arrCapacity );
209 for ( auto& el : arrValue ) {
210 CPPUNIT_ASSERT( s.contains( el.hash ) );
211 typename Set::guarded_ptr gp = s.extract( el.hash );
212 CPPUNIT_ASSERT( gp );
213 Set::gc::force_dispose();
214 CPPUNIT_ASSERT( el.nDisposeCount == 0 );
215 CPPUNIT_ASSERT( gp->nDisposeCount == 0 );
216 gp = s.get( el.hash );
217 CPPUNIT_ASSERT( !gp );
218 Set::gc::force_dispose();
219 CPPUNIT_ASSERT( el.nDisposeCount == 1 );
220 CPPUNIT_ASSERT( !s.contains( el.hash ) );
222 CPPUNIT_ASSERT(s.size() == 0 );
223 CPPUNIT_ASSERT(s.empty() );
225 CPPUNIT_MSG( s.statistics() );
229 void hp_stdhash_stat();
231 CPPUNIT_TEST_SUITE(IntrusiveMultiLevelHashSetHdrTest)
232 CPPUNIT_TEST(hp_stdhash)
233 CPPUNIT_TEST(hp_stdhash_stat)
234 CPPUNIT_TEST_SUITE_END()
238 #endif // #ifndef CDSTEST_HDR_INTRUSIVE_MULTILEVEL_HASHSET_H