Move libcds 1.6.0 from SVN
[libcds.git] / tests / test-hdr / deque / hdr_intrusive_deque.h
1 //$$CDS-header$$
2
3 #include "cppunit/cppunit_proxy.h"
4 #include "cppunit/test_beans.h"
5
6 namespace deque {
7     namespace ci = cds::intrusive;
8     namespace co = cds::opt;
9
10     class IntrusiveDequeHeaderTest: public CppUnitMini::TestCase
11     {
12     public:
13         template <typename NodeType>
14         struct base_hook_item: public NodeType
15         {
16             int nVal;
17             int nDisposeCount;
18
19             base_hook_item()
20                 : nDisposeCount(0)
21             {}
22         };
23
24         template <typename NodeType>
25         struct member_hook_item
26         {
27             int nVal;
28             int nDisposeCount;
29             NodeType hMember;
30
31             member_hook_item()
32                 : nDisposeCount(0)
33             {}
34         };
35
36         struct faked_disposer
37         {
38             template <typename T>
39             void operator ()( T * p )
40             {
41                 ++p->nDisposeCount;
42             }
43         };
44
45         template <class Deque>
46         void test()
47         {
48             test_beans::check_item_counter<typename Deque::item_counter> check_ic;
49
50             typedef typename Deque::value_type value_type;
51             value_type v1, v2, v3;
52
53             Deque q;
54             CPPUNIT_ASSERT( q.empty() );
55             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
56
57             v1.nVal = 1;
58             v2.nVal = 2;
59             v3.nVal = 3;
60
61             // push_left / pop_right
62             CPPUNIT_ASSERT( q.push_front(v1));
63             CPPUNIT_ASSERT( !q.empty() );
64             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
65             CPPUNIT_ASSERT( q.push_front(v2));
66             CPPUNIT_ASSERT( !q.empty() );
67             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
68             CPPUNIT_ASSERT( q.push_front(v3));
69             CPPUNIT_ASSERT( !q.empty() );
70             CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
71
72             CPPUNIT_ASSERT( v1.nDisposeCount == 0 );
73             CPPUNIT_ASSERT( v2.nDisposeCount == 0 );
74             CPPUNIT_ASSERT( v3.nDisposeCount == 0 );
75
76             value_type * pv;
77             pv = q.pop_back();
78             Deque::gc::scan();
79             CPPUNIT_ASSERT( pv != NULL );
80             CPPUNIT_ASSERT( pv->nVal == 1 );
81             CPPUNIT_ASSERT( !q.empty() );
82             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
83             CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
84             CPPUNIT_ASSERT( v2.nDisposeCount == 0 );
85             CPPUNIT_ASSERT( v3.nDisposeCount == 0 );
86
87             pv = q.pop_back();
88             Deque::gc::scan();
89             CPPUNIT_ASSERT( pv != NULL );
90             CPPUNIT_ASSERT( pv->nVal == 2 );
91             CPPUNIT_ASSERT( !q.empty() );
92             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
93             CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
94             CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
95             CPPUNIT_ASSERT( v3.nDisposeCount == 0 );
96
97             pv = q.pop_back();
98             Deque::gc::scan();
99             CPPUNIT_ASSERT( pv != NULL );
100             CPPUNIT_ASSERT( pv->nVal == 3 );
101             CPPUNIT_ASSERT( q.empty() );
102             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
103             CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
104             CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
105             CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
106
107             pv = q.pop_back();
108             Deque::gc::scan();
109             CPPUNIT_ASSERT( pv == NULL );
110             CPPUNIT_ASSERT( q.empty() );
111             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
112             CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
113             CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
114             CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
115
116
117             // push_right / pop_left
118             CPPUNIT_ASSERT( q.push_back(v1));
119             CPPUNIT_ASSERT( !q.empty() );
120             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
121             CPPUNIT_ASSERT( q.push_back(v2));
122             CPPUNIT_ASSERT( !q.empty() );
123             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
124             CPPUNIT_ASSERT( q.push_back(v3));
125             CPPUNIT_ASSERT( !q.empty() );
126             CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
127
128             CPPUNIT_ASSERT( v1.nDisposeCount == 1 );
129             CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
130             CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
131
132             pv = q.pop_front();
133             Deque::gc::scan();
134             CPPUNIT_ASSERT( pv != NULL );
135             CPPUNIT_ASSERT( pv->nVal == 1 );
136             CPPUNIT_ASSERT( !q.empty() );
137             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
138             CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
139             CPPUNIT_ASSERT( v2.nDisposeCount == 1 );
140             CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
141
142             pv = q.pop_front();
143             Deque::gc::scan();
144             CPPUNIT_ASSERT( pv != NULL );
145             CPPUNIT_ASSERT( pv->nVal == 2 );
146             CPPUNIT_ASSERT( !q.empty() );
147             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
148             CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
149             CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
150             CPPUNIT_ASSERT( v3.nDisposeCount == 1 );
151
152             pv = q.pop_front();
153             Deque::gc::scan();
154             CPPUNIT_ASSERT( pv != NULL );
155             CPPUNIT_ASSERT( pv->nVal == 3 );
156             CPPUNIT_ASSERT( q.empty() );
157             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
158             CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
159             CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
160             CPPUNIT_ASSERT( v3.nDisposeCount == 2 );
161
162             pv = q.pop_front();
163             Deque::gc::scan();
164             CPPUNIT_ASSERT( pv == NULL );
165             CPPUNIT_ASSERT( q.empty() );
166             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
167             CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
168             CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
169             CPPUNIT_ASSERT( v3.nDisposeCount == 2 );
170
171
172             // push_right / pop_right
173             CPPUNIT_ASSERT( q.push_back(v1));
174             CPPUNIT_ASSERT( !q.empty() );
175             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
176             CPPUNIT_ASSERT( q.push_back(v2));
177             CPPUNIT_ASSERT( !q.empty() );
178             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
179             CPPUNIT_ASSERT( q.push_back(v3));
180             CPPUNIT_ASSERT( !q.empty() );
181             CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
182
183             CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
184             CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
185             CPPUNIT_ASSERT( v3.nDisposeCount == 2 );
186
187             pv = q.pop_back();
188             Deque::gc::scan();
189             CPPUNIT_ASSERT( pv != NULL );
190             CPPUNIT_ASSERT( pv->nVal == 3 );
191             CPPUNIT_ASSERT( !q.empty() );
192             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
193             CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
194             CPPUNIT_ASSERT( v2.nDisposeCount == 2 );
195             CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
196
197             pv = q.pop_back();
198             Deque::gc::scan();
199             CPPUNIT_ASSERT( pv != NULL );
200             CPPUNIT_ASSERT( pv->nVal == 2 );
201             CPPUNIT_ASSERT( !q.empty() );
202             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
203             CPPUNIT_ASSERT( v1.nDisposeCount == 2 );
204             CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
205             CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
206
207             pv = q.pop_back();
208             Deque::gc::scan();
209             CPPUNIT_ASSERT( pv != NULL );
210             CPPUNIT_ASSERT( pv->nVal == 1 );
211             CPPUNIT_ASSERT( q.empty() );
212             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
213             CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
214             CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
215             CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
216
217             pv = q.pop_back();
218             Deque::gc::scan();
219             CPPUNIT_ASSERT( pv == NULL );
220             CPPUNIT_ASSERT( q.empty() );
221             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
222             CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
223             CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
224             CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
225
226
227             // push_left / pop_left
228             CPPUNIT_ASSERT( q.push_front(v1));
229             CPPUNIT_ASSERT( !q.empty() );
230             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
231             CPPUNIT_ASSERT( q.push_front(v2));
232             CPPUNIT_ASSERT( !q.empty() );
233             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
234             CPPUNIT_ASSERT( q.push_front(v3));
235             CPPUNIT_ASSERT( !q.empty() );
236             CPPUNIT_ASSERT( check_ic( q.size(), 3 ));
237
238             CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
239             CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
240             CPPUNIT_ASSERT( v3.nDisposeCount == 3 );
241
242             pv = q.pop_front();
243             Deque::gc::scan();
244             CPPUNIT_ASSERT( pv != NULL );
245             CPPUNIT_ASSERT( pv->nVal == 3 );
246             CPPUNIT_ASSERT( !q.empty() );
247             CPPUNIT_ASSERT( check_ic( q.size(), 2 ));
248             CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
249             CPPUNIT_ASSERT( v2.nDisposeCount == 3 );
250             CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
251
252             pv = q.pop_front();
253             Deque::gc::scan();
254             CPPUNIT_ASSERT( pv != NULL );
255             CPPUNIT_ASSERT( pv->nVal == 2 );
256             CPPUNIT_ASSERT( !q.empty() );
257             CPPUNIT_ASSERT( check_ic( q.size(), 1 ));
258             CPPUNIT_ASSERT( v1.nDisposeCount == 3 );
259             CPPUNIT_ASSERT( v2.nDisposeCount == 4 );
260             CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
261
262             pv = q.pop_front();
263             Deque::gc::scan();
264             CPPUNIT_ASSERT( pv != NULL );
265             CPPUNIT_ASSERT( pv->nVal == 1 );
266             CPPUNIT_ASSERT( q.empty() );
267             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
268             CPPUNIT_ASSERT( v1.nDisposeCount == 4 );
269             CPPUNIT_ASSERT( v2.nDisposeCount == 4 );
270             CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
271
272             pv = q.pop_front();
273             Deque::gc::scan();
274             CPPUNIT_ASSERT( pv == NULL );
275             CPPUNIT_ASSERT( q.empty() );
276             CPPUNIT_ASSERT( check_ic( q.size(), 0 ));
277             CPPUNIT_ASSERT( v1.nDisposeCount == 4 );
278             CPPUNIT_ASSERT( v2.nDisposeCount == 4 );
279             CPPUNIT_ASSERT( v3.nDisposeCount == 4 );
280         }
281
282         void test_MichaelDeque_HP_default();
283         void test_MichaelDeque_HP_default_ic();
284         void test_MichaelDeque_HP_default_stat();
285         void test_MichaelDeque_HP_base();
286         void test_MichaelDeque_HP_member();
287         void test_MichaelDeque_HP_base_ic();
288         void test_MichaelDeque_HP_member_ic();
289         void test_MichaelDeque_HP_base_stat();
290         void test_MichaelDeque_HP_member_stat();
291         void test_MichaelDeque_HP_base_align();
292         void test_MichaelDeque_HP_member_align();
293         void test_MichaelDeque_HP_base_noalign();
294         void test_MichaelDeque_HP_member_noalign();
295         void test_MichaelDeque_PTB_base();
296         void test_MichaelDeque_PTB_member();
297         void test_MichaelDeque_PTB_base_ic();
298         void test_MichaelDeque_PTB_member_ic();
299         void test_MichaelDeque_PTB_base_stat();
300         void test_MichaelDeque_PTB_member_stat();
301         void test_MichaelDeque_PTB_base_align();
302         void test_MichaelDeque_PTB_member_align();
303         void test_MichaelDeque_PTB_base_noalign();
304         void test_MichaelDeque_PTB_member_noalign();
305
306         CPPUNIT_TEST_SUITE(IntrusiveDequeHeaderTest)
307             CPPUNIT_TEST( test_MichaelDeque_HP_default);
308             CPPUNIT_TEST( test_MichaelDeque_HP_default_ic);
309             CPPUNIT_TEST( test_MichaelDeque_HP_default_stat);
310             CPPUNIT_TEST( test_MichaelDeque_HP_base);
311             CPPUNIT_TEST( test_MichaelDeque_HP_member);
312             CPPUNIT_TEST( test_MichaelDeque_HP_base_ic);
313             CPPUNIT_TEST( test_MichaelDeque_HP_member_ic);
314             CPPUNIT_TEST( test_MichaelDeque_HP_base_stat);
315             CPPUNIT_TEST( test_MichaelDeque_HP_member_stat);
316             CPPUNIT_TEST( test_MichaelDeque_HP_base_align);
317             CPPUNIT_TEST( test_MichaelDeque_HP_member_align);
318             CPPUNIT_TEST( test_MichaelDeque_HP_base_noalign);
319             CPPUNIT_TEST( test_MichaelDeque_HP_member_noalign);
320             CPPUNIT_TEST( test_MichaelDeque_PTB_base);
321             CPPUNIT_TEST( test_MichaelDeque_PTB_member);
322             CPPUNIT_TEST( test_MichaelDeque_PTB_base_ic);
323             CPPUNIT_TEST( test_MichaelDeque_PTB_member_ic);
324             CPPUNIT_TEST( test_MichaelDeque_PTB_base_stat);
325             CPPUNIT_TEST( test_MichaelDeque_PTB_member_stat);
326             CPPUNIT_TEST( test_MichaelDeque_PTB_base_align);
327             CPPUNIT_TEST( test_MichaelDeque_PTB_member_align);
328             CPPUNIT_TEST( test_MichaelDeque_PTB_base_noalign);
329             CPPUNIT_TEST( test_MichaelDeque_PTB_member_noalign);
330
331         CPPUNIT_TEST_SUITE_END()
332     };
333
334 }   // namespace deque