Add header tests for unordered intrusive list.
[libcds.git] / tests / test-hdr / unordered_list / hdr_intrusive_lazy.h
1 //$$CDS-header$$
2
3 #ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H
4 #define CDSTEST_HDR_INTRUSIVE_LAZY_H
5
6 #include "cppunit/cppunit_proxy.h"
7 #include <cds/intrusive/details/lazy_list_base.h>
8
9 namespace unordlist {
10     namespace ci = cds::intrusive;
11     namespace co = cds::opt;
12
13     struct stat {
14         int nDisposeCount;
15         int nEnsureExistsCall;
16         int nEnsureNewCall;
17         int nFindCall;
18         int nEraseCall;
19
20         stat()
21             : nDisposeCount(0)
22             , nEnsureExistsCall(0)
23             , nEnsureNewCall(0)
24             , nFindCall(0)
25             , nEraseCall(0)
26         {}
27
28         stat( const stat& s )
29         {
30             *this = s;
31         }
32
33         stat& operator =(const stat& s)
34         {
35             memcpy( this, &s, sizeof(s));
36             return *this;
37         }
38     };
39
40     template <typename GC>
41     struct base_int_item: public ci::lazy_list::node< GC >
42     {
43         int nKey;
44         int nVal;
45
46         mutable stat    s;
47
48         base_int_item()
49         {}
50
51         base_int_item(int key, int val)
52             : nKey( key )
53             , nVal(val)
54             , s()
55         {}
56
57         base_int_item(const base_int_item& v )
58             : nKey( v.nKey )
59             , nVal( v.nVal )
60             , s()
61         {}
62
63         const int& key() const
64         {
65             return nKey;
66         }
67
68         operator int() const
69         { return nKey; }
70     };
71
72     template <typename GC>
73     struct member_int_item
74     {
75         int nKey;
76         int nVal;
77
78         ci::lazy_list::node< GC > hMember;
79
80         mutable stat s;
81
82         member_int_item()
83         {}
84
85         member_int_item(int key, int val)
86             : nKey( key )
87             , nVal(val)
88             , s()
89         {}
90
91         member_int_item(const member_int_item& v )
92             : nKey( v.nKey )
93             , nVal( v.nVal )
94             , s()
95         {}
96
97         const int& key() const
98         {
99             return nKey;
100         }
101
102         operator int() const
103         { return nKey; }
104     };
105
106     template <typename T>
107     struct less
108     {
109         bool operator ()(const T& v1, const T& v2 ) const
110         {
111             return v1.key() < v2.key();
112         }
113
114         template <typename Q>
115         bool operator ()(const T& v1, const Q& v2 ) const
116         {
117             return v1.key() < v2;
118         }
119
120         template <typename Q>
121         bool operator ()(const Q& v1, const T& v2 ) const
122         {
123             return v1 < v2.key();
124         }
125     };
126
127     template <typename T>
128     struct cmp {
129         int operator ()(const T& v1, const T& v2 ) const
130         {
131             if ( v1.key() < v2.key() )
132                 return -1;
133             return v1.key() > v2.key() ? 1 : 0;
134         }
135
136         template <typename Q>
137         int operator ()(const T& v1, const Q& v2 ) const
138         {
139             if ( v1.key() < v2 )
140                 return -1;
141             return v1.key() > v2 ? 1 : 0;
142         }
143
144         template <typename Q>
145         int operator ()(const Q& v1, const T& v2 ) const
146         {
147             if ( v1 < v2.key() )
148                 return -1;
149             return v1 > v2.key() ? 1 : 0;
150         }
151     };
152
153     template <typename T>
154     struct equal_to {
155         bool operator()( T const& l, T const& r ) const
156         {
157             return l.key() == r.key();
158         }
159
160         template <typename Q>
161         bool operator()( Q const& l, T const& r ) const
162         {
163             return l == r.key();
164         }
165
166         template <typename Q>
167         bool operator()( T const& l, Q const& r ) const
168         {
169             return l.key() == r;
170         }
171     };
172
173     struct faked_disposer
174     {
175         template <typename T>
176         void operator ()( T * p )
177         {
178             ++p->s.nDisposeCount;
179         }
180     };
181
182     struct ensure_functor
183     {
184         template <typename T>
185         void operator ()(bool bNew, T& item, T& /*val*/ )
186         {
187             if ( bNew )
188                 ++item.s.nEnsureNewCall;
189             else
190                 ++item.s.nEnsureExistsCall;
191         }
192     };
193
194     struct find_functor
195     {
196         template <typename T, typename Q>
197         void operator ()( T& item, Q& /*val*/ )
198         {
199             ++item.s.nFindCall;
200         }
201     };
202
203     class UnorderedIntrusiveLazyListHeaderTest: public CppUnitMini::TestCase
204     {
205     public:
206         template <class UnordList>
207         void test_nogc_int()
208         {
209             typedef typename UnordList::value_type    value_type;
210             {
211                 value_type v1( 10, 50 );
212                 value_type v2( 5, 25  );
213                 value_type v3( 20, 100 );
214                 {
215                     UnordList l;
216                     CPPUNIT_ASSERT( l.empty() );
217
218                     CPPUNIT_ASSERT( l.insert( v1 ));   // true
219                     CPPUNIT_ASSERT( l.find( v1.key() ) == &v1 );
220
221                     CPPUNIT_ASSERT( v1.s.nFindCall == 0 );
222                     CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
223                     CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
224
225                     CPPUNIT_ASSERT( l.find( v3.key() ) == nullptr );
226                     CPPUNIT_ASSERT( !l.empty() );
227
228                     //CPPUNIT_ASSERT( !l.insert( v1 ))    ;   // assertion "is_empty" is raised
229
230                     {
231                         value_type v( v1 );
232                         CPPUNIT_ASSERT( !l.insert( v )) ;   // false
233                     }
234
235                     std::pair<bool, bool> ret = l.ensure( v2, ensure_functor() );
236                     CPPUNIT_ASSERT( ret.first );
237                     CPPUNIT_ASSERT( ret.second );
238                     CPPUNIT_ASSERT( v2.s.nEnsureNewCall == 1 );
239                     CPPUNIT_ASSERT( v2.s.nEnsureExistsCall == 0 );
240
241                     //CPPUNIT_ASSERT( !l.insert( v2 ))    ;   // assertion "is_empty"
242
243                     CPPUNIT_ASSERT( l.find( v1.key() ) == &v1 ) ;   // true
244
245                     CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
246                     CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
247                     CPPUNIT_ASSERT( v1.s.nFindCall == 2 );
248
249                     CPPUNIT_ASSERT( !l.find( v3.key() ));
250
251                     {
252                         value_type v( v2 );
253                         ret = l.ensure( v, ensure_functor() );
254
255                         CPPUNIT_ASSERT( ret.first );
256                         CPPUNIT_ASSERT( !ret.second );
257                         CPPUNIT_ASSERT( v2.s.nEnsureExistsCall == 1 );
258                         CPPUNIT_ASSERT( v.s.nEnsureExistsCall == 0 && v.s.nEnsureNewCall == 0 );
259                     }
260
261                     CPPUNIT_ASSERT( !l.empty() );
262
263                     CPPUNIT_ASSERT( l.insert( v3 ))     ;   // true
264                     CPPUNIT_ASSERT( l.find( v3.key() ) == &v3 );
265
266                     CPPUNIT_ASSERT( v3.s.nFindCall == 0 );
267                     CPPUNIT_ASSERT( l.find( v3.key(), find_functor() ));
268                     CPPUNIT_ASSERT( v3.s.nFindCall == 1 );
269
270                     {
271                         typename UnordList::iterator it = l.begin();
272                         typename UnordList::const_iterator cit = l.cbegin();
273                         CPPUNIT_ASSERT( it != l.end() );
274                         CPPUNIT_ASSERT( it != l.cend() );
275                         CPPUNIT_ASSERT( cit != l.end() );
276                         CPPUNIT_ASSERT( cit != l.cend() );
277                         CPPUNIT_ASSERT( cit == it );
278
279                         CPPUNIT_ASSERT( it->nKey == v1.nKey );
280                         CPPUNIT_ASSERT( it->nVal == v1.nVal );
281                         CPPUNIT_ASSERT( ++it != l.end() );
282                         CPPUNIT_ASSERT( it->nKey == v2.nKey );
283                         CPPUNIT_ASSERT( it->nVal == v2.nVal );
284                         CPPUNIT_ASSERT( it++ != l.end() );
285                         CPPUNIT_ASSERT( it->nKey == v3.nKey );
286                         CPPUNIT_ASSERT( it->nVal == v3.nVal );
287                         CPPUNIT_ASSERT( it++ != l.end() );
288                         CPPUNIT_ASSERT( it == l.end() );
289                     }
290
291                     {
292                         UnordList const & lref = l;
293                         typename UnordList::const_iterator it = lref.begin();
294                         CPPUNIT_ASSERT( it != l.end() );
295                         CPPUNIT_ASSERT( it->nKey == v1.nKey );
296                         CPPUNIT_ASSERT( it->nVal == v1.nVal );
297                         CPPUNIT_ASSERT( ++it != lref.end() );
298                         CPPUNIT_ASSERT( it->nKey == v2.nKey );
299                         CPPUNIT_ASSERT( it->nVal == v2.nVal );
300                         CPPUNIT_ASSERT( it++ != l.end() );
301                         CPPUNIT_ASSERT( it->nKey == v3.nKey );
302                         CPPUNIT_ASSERT( it->nVal == v3.nVal );
303                         CPPUNIT_ASSERT( it++ != lref.end() );
304                         CPPUNIT_ASSERT( it == l.end() );
305                     }
306                 }
307
308                 // Disposer called on list destruction
309                 CPPUNIT_ASSERT( v1.s.nDisposeCount == 1 );
310                 CPPUNIT_ASSERT( v2.s.nDisposeCount == 1 );
311                 CPPUNIT_ASSERT( v3.s.nDisposeCount == 1 );
312             }
313         }
314
315         void nogc_base_cmp();
316         void nogc_base_less();
317         void nogc_base_equal_to();
318         void nogc_base_cmpmix();
319         void nogc_base_equal_to_mix();
320         void nogc_base_ic();
321         void nogc_member_cmp();
322         void nogc_member_less();
323         void nogc_member_equal_to();
324         void nogc_member_cmpmix();
325         void nogc_member_equal_to_mix();
326         void nogc_member_ic();
327
328         CPPUNIT_TEST_SUITE(UnorderedIntrusiveLazyListHeaderTest)
329
330             CPPUNIT_TEST(nogc_base_cmp)
331             CPPUNIT_TEST(nogc_base_less)
332             CPPUNIT_TEST(nogc_base_equal_to)
333             CPPUNIT_TEST(nogc_base_cmpmix)
334             CPPUNIT_TEST(nogc_base_equal_to_mix)
335             CPPUNIT_TEST(nogc_base_ic)
336             CPPUNIT_TEST(nogc_member_cmp)
337             CPPUNIT_TEST(nogc_member_less)
338             CPPUNIT_TEST(nogc_member_equal_to)
339             CPPUNIT_TEST(nogc_member_cmpmix)
340             CPPUNIT_TEST(nogc_member_equal_to_mix)
341             CPPUNIT_TEST(nogc_member_ic)
342
343         CPPUNIT_TEST_SUITE_END()
344     };
345 }   // namespace unordlist
346
347 #endif // #ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H