1 //Has to be first for StackAllocator swap overload to be taken
2 //into account (at least using GCC 4.0.1)
3 #include "stack_allocator.h"
4
5 #include <list>
6 #include <algorithm>
7 #include <functional>
8
9 #include "cppunit/cppunit_proxy.h"
10
11 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
12 using namespace std;
13 #endif
14
15 //
16 // TestCase class
17 //
18 class ListTest : public CPPUNIT_NS::TestCase
19 {
20 CPPUNIT_TEST_SUITE(ListTest);
21 CPPUNIT_TEST(list1);
22 CPPUNIT_TEST(list2);
23 CPPUNIT_TEST(list3);
24 CPPUNIT_TEST(list4);
25 CPPUNIT_TEST(erase);
26 CPPUNIT_TEST(resize);
27 CPPUNIT_TEST(push_back);
28 CPPUNIT_TEST(push_front);
29 CPPUNIT_TEST(allocator_with_state);
30 CPPUNIT_TEST(swap);
31 CPPUNIT_TEST(adl);
32 //CPPUNIT_TEST(const_list);
33 CPPUNIT_TEST_SUITE_END();
34
35 protected:
36 void list1();
37 void list2();
38 void list3();
39 void list4();
40 void erase();
41 void resize();
42 void push_back();
43 void push_front();
44 void allocator_with_state();
45 void swap();
46 void adl();
47 //void const_list();
48 };
49
50 CPPUNIT_TEST_SUITE_REGISTRATION(ListTest);
51
52 //
53 // tests implementation
54 //
list1()55 void ListTest::list1()
56 {
57 int array1 [] = { 9, 16, 36 };
58 int array2 [] = { 1, 4 };
59
60 list<int> l1(array1, array1 + 3);
61 list<int> l2(array2, array2 + 2);
62 list<int>::iterator i1 = l1.begin();
63 list<int>::iterator i2 = l2.begin();
64 list<int>::const_iterator ci(i1);
65 list<int>::const_iterator ci1(ci);
66 l1.splice(i1, l2);
67 i1 = l1.begin();
68 CPPUNIT_ASSERT( *i1++ == 1 );
69 CPPUNIT_ASSERT( *i1++ == 4 );
70 CPPUNIT_ASSERT( *i1++ == 9 );
71 CPPUNIT_ASSERT( *i1++ == 16 );
72 CPPUNIT_ASSERT( *i1++ == 36 );
73
74 #if defined (STLPORT) && \
75 (!defined (_STLP_DEBUG) || (_STLP_DEBUG_LEVEL != _STLP_STANDARD_DBG_LEVEL))
76 CPPUNIT_ASSERT( i2 == l1.begin() );
77 #endif
78
79 //Default construct check (_STLP_DEF_CONST_PLCT_NEW_BUG)
80 list<int> l(2);
81 i1 = l.begin();
82 CPPUNIT_ASSERT( *(i1++) == 0 );
83 CPPUNIT_ASSERT( *i1 == 0 );
84 #if 0
85 //A small compilation time check to be activated from time to time,
86 //compilation should fail.
87 {
88 list<char>::iterator l_char_ite;
89 list<int>::iterator l_int_ite;
90 CPPUNIT_ASSERT( l_char_ite != l_int_ite );
91 }
92 #endif
93 }
94
list2()95 void ListTest::list2()
96 {
97 int array1 [] = { 1, 16 };
98 int array2 [] = { 4, 9 };
99
100 list<int> l1(array1, array1 + 2);
101 list<int> l2(array2, array2 + 2);
102 list<int>::iterator i = l1.begin();
103 i++;
104 l1.splice(i, l2, l2.begin(), l2.end());
105 i = l1.begin();
106 CPPUNIT_ASSERT(*i++==1);
107 CPPUNIT_ASSERT(*i++==4);
108 CPPUNIT_ASSERT(*i++==9);
109 CPPUNIT_ASSERT(*i++==16);
110 }
111
list3()112 void ListTest::list3()
113 {
114 char array [] = { 'x', 'l', 'x', 't', 's', 's' };
115
116 list<char> str(array, array + 6);
117 list<char>::iterator i;
118
119 str.reverse();
120 i = str.begin();
121 CPPUNIT_ASSERT(*i++=='s');
122 CPPUNIT_ASSERT(*i++=='s');
123 CPPUNIT_ASSERT(*i++=='t');
124 CPPUNIT_ASSERT(*i++=='x');
125 CPPUNIT_ASSERT(*i++=='l');
126 CPPUNIT_ASSERT(*i++=='x');
127
128 str.remove('x');
129 i = str.begin();
130 CPPUNIT_ASSERT(*i++=='s');
131 CPPUNIT_ASSERT(*i++=='s');
132 CPPUNIT_ASSERT(*i++=='t');
133 CPPUNIT_ASSERT(*i++=='l');
134
135 str.unique();
136 i = str.begin();
137 CPPUNIT_ASSERT(*i++=='s');
138 CPPUNIT_ASSERT(*i++=='t');
139 CPPUNIT_ASSERT(*i++=='l');
140
141 str.sort();
142 i = str.begin();
143 CPPUNIT_ASSERT(*i++=='l');
144 CPPUNIT_ASSERT(*i++=='s');
145 CPPUNIT_ASSERT(*i++=='t');
146 }
147
list4()148 void ListTest::list4()
149 {
150 int array1 [] = { 1, 3, 6, 7 };
151 int array2 [] = { 2, 4 };
152
153 list<int> l1(array1, array1 + 4);
154 list<int> l2(array2, array2 + 2);
155 l1.merge(l2);
156 list<int>::iterator i = l1.begin();
157 CPPUNIT_ASSERT(*i++==1);
158 CPPUNIT_ASSERT(*i++==2);
159 CPPUNIT_ASSERT(*i++==3);
160 CPPUNIT_ASSERT(*i++==4);
161 CPPUNIT_ASSERT(*i++==6);
162 CPPUNIT_ASSERT(*i++==7);
163
164 //We use distance to avoid a simple call to an internal counter
165 CPPUNIT_ASSERT(distance(l1.begin(), l1.end()) == 6);
166 CPPUNIT_ASSERT(distance(l2.begin(), l2.end()) == 0);
167
168 l1.swap(l2);
169
170 CPPUNIT_ASSERT(distance(l1.begin(), l1.end()) == 0);
171 CPPUNIT_ASSERT(distance(l2.begin(), l2.end()) == 6);
172 }
173
erase()174 void ListTest::erase()
175 {
176 list<int> l;
177 l.push_back( 1 );
178 l.erase(l.begin());
179 CPPUNIT_ASSERT( l.empty() );
180
181 int array[] = { 0, 1, 2, 3 };
182 l.assign(array, array + 4);
183 list<int>::iterator lit;
184 lit = l.erase(l.begin());
185 CPPUNIT_ASSERT( *lit == 1 );
186
187 lit = l.erase(l.begin(), --l.end());
188 CPPUNIT_ASSERT( *lit == 3 );
189
190 l.clear();
191 CPPUNIT_ASSERT( l.empty() );
192 }
193
194
resize()195 void ListTest::resize()
196 {
197 {
198 list<int> l;
199 l.resize(5, 1);
200
201 size_t i;
202 list<int>::iterator lit(l.begin());
203 for (i = 0; i < 5; ++i) {
204 CPPUNIT_ASSERT( lit != l.end() );
205 CPPUNIT_ASSERT( *(lit++) == 1 );
206 }
207 CPPUNIT_ASSERT( lit == l.end() );
208
209 l.resize(3);
210 lit = l.begin();
211 for (i = 0; i < 3; ++i) {
212 CPPUNIT_ASSERT( lit != l.end() );
213 CPPUNIT_ASSERT( *(lit++) == 1 );
214 }
215 CPPUNIT_ASSERT( lit == l.end() );
216 }
217
218 {
219 list<int> l;
220 l.resize(5);
221
222 size_t i;
223 list<int>::iterator lit(l.begin());
224 for (i = 0; i < 5; ++i) {
225 CPPUNIT_ASSERT( lit != l.end() );
226 CPPUNIT_ASSERT( *(lit++) == 0 );
227 }
228 CPPUNIT_ASSERT( lit == l.end() );
229 }
230 }
231
push_back()232 void ListTest::push_back()
233 {
234 list<int> l;
235 l.push_back( 1 );
236 l.push_back( 2 );
237 l.push_back( 3 );
238
239 list<int>::reverse_iterator r = l.rbegin();
240
241 CPPUNIT_ASSERT( *r == 3 );
242 l.push_back( 4 );
243 /*
244 * Following lines are commented, because ones show standard contradiction
245 * (24.4.1 and 23.2.2.3); but present behaviour is valid, 24.4.1, paragraphs 1 and 2,
246 * 24.4.1.3.3 and 23.1 paragraph 9 (Table 66). The 24.4.1 is more common rule,
247 * so it has preference under 23.2.2.3, by my opinion.
248 *
249 * - ptr
250 */
251 // CPPUNIT_ASSERT( *r == 3 );
252 // ++r;
253 // CPPUNIT_ASSERT( *r == 2 );
254 }
255
push_front()256 void ListTest::push_front()
257 {
258 list<int> l;
259 l.push_back( 1 );
260 l.push_back( 2 );
261 l.push_back( 3 );
262
263 list<int>::iterator i = l.begin();
264
265 CPPUNIT_ASSERT( *i == 1 );
266 l.push_front( 0 );
267 CPPUNIT_ASSERT( *i == 1 );
268 ++i;
269 CPPUNIT_ASSERT( *i == 2 );
270 }
271
allocator_with_state()272 void ListTest::allocator_with_state()
273 {
274 char buf1[1024];
275 StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1));
276
277 char buf2[1024];
278 StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2));
279
280 typedef list<int, StackAllocator<int> > ListInt;
281 {
282 //Swap with both list non empty
283 ListInt lint1(10, 0, stack1);
284 ListInt lint1Cpy(lint1);
285
286 ListInt lint2(10, 1, stack2);
287 ListInt lint2Cpy(lint2);
288
289 lint1.swap(lint2);
290
291 CPPUNIT_ASSERT( lint1.get_allocator().swaped() );
292 CPPUNIT_ASSERT( lint2.get_allocator().swaped() );
293
294 CPPUNIT_ASSERT( lint1 == lint2Cpy );
295 CPPUNIT_ASSERT( lint2 == lint1Cpy );
296 CPPUNIT_ASSERT( lint1.get_allocator() == stack2 );
297 CPPUNIT_ASSERT( lint2.get_allocator() == stack1 );
298 }
299 CPPUNIT_CHECK( stack1.ok() );
300 CPPUNIT_CHECK( stack2.ok() );
301 stack1.reset(); stack2.reset();
302
303 {
304 //Swap with empty calle list
305 ListInt lint1(10, 0, stack1);
306 ListInt lint1Cpy(lint1);
307
308 ListInt lint2(stack2);
309 ListInt lint2Cpy(lint2);
310
311 lint1.swap(lint2);
312
313 CPPUNIT_ASSERT( lint1.get_allocator().swaped() );
314 CPPUNIT_ASSERT( lint2.get_allocator().swaped() );
315
316 CPPUNIT_ASSERT( lint1 == lint2Cpy );
317 CPPUNIT_ASSERT( lint2 == lint1Cpy );
318 CPPUNIT_ASSERT( lint1.get_allocator() == stack2 );
319 CPPUNIT_ASSERT( lint2.get_allocator() == stack1 );
320 }
321 CPPUNIT_CHECK( stack1.ok() );
322 CPPUNIT_CHECK( stack2.ok() );
323 stack1.reset(); stack2.reset();
324
325 {
326 //Swap with empty caller list
327 ListInt lint1(stack1);
328 ListInt lint1Cpy(lint1);
329
330 ListInt lint2(10, 0, stack2);
331 ListInt lint2Cpy(lint2);
332
333 lint1.swap(lint2);
334
335 CPPUNIT_ASSERT( lint1.get_allocator().swaped() );
336 CPPUNIT_ASSERT( lint2.get_allocator().swaped() );
337
338 CPPUNIT_ASSERT( lint1 == lint2Cpy );
339 CPPUNIT_ASSERT( lint2 == lint1Cpy );
340 CPPUNIT_ASSERT( lint1.get_allocator() == stack2 );
341 CPPUNIT_ASSERT( lint2.get_allocator() == stack1 );
342 }
343 CPPUNIT_CHECK( stack1.ok() );
344 CPPUNIT_CHECK( stack2.ok() );
345 stack1.reset(); stack2.reset();
346
347 {
348 ListInt lint1(10, 0, stack1);
349 ListInt lint2(10, 1, stack2);
350
351 lint1.splice(lint1.begin(), lint2);
352 CPPUNIT_ASSERT( lint1.size() == 20 );
353 CPPUNIT_ASSERT( lint2.empty() );
354 }
355 CPPUNIT_CHECK( stack1.ok() );
356 CPPUNIT_CHECK( stack2.ok() );
357 stack1.reset(); stack2.reset();
358
359 {
360 ListInt lint1(10, 0, stack1);
361 ListInt lint2(10, 1, stack2);
362
363 lint1.splice(lint1.begin(), lint2, lint2.begin());
364 CPPUNIT_ASSERT( lint1.size() == 11 );
365 CPPUNIT_ASSERT( lint2.size() == 9 );
366 }
367 CPPUNIT_CHECK( stack1.ok() );
368 CPPUNIT_CHECK( stack2.ok() );
369 stack1.reset(); stack2.reset();
370
371 {
372 ListInt lint1(10, 0, stack1);
373 ListInt lint2(10, 1, stack2);
374
375 ListInt::iterator lit(lint2.begin());
376 advance(lit, 5);
377 lint1.splice(lint1.begin(), lint2, lint2.begin(), lit);
378 CPPUNIT_ASSERT( lint1.size() == 15 );
379 CPPUNIT_ASSERT( lint2.size() == 5 );
380 }
381 CPPUNIT_CHECK( stack1.ok() );
382 CPPUNIT_CHECK( stack2.ok() );
383 stack1.reset(); stack2.reset();
384
385 {
386 ListInt lint1(10, 0, stack1);
387 ListInt lint2(10, 1, stack2);
388
389 ListInt lintref(stack2);
390 lintref.insert(lintref.begin(), 10, 1);
391 lintref.insert(lintref.begin(), 10, 0);
392
393 lint1.merge(lint2);
394 CPPUNIT_ASSERT( lint1.size() == 20 );
395 CPPUNIT_ASSERT( lint1 == lintref );
396 CPPUNIT_ASSERT( lint2.empty() );
397 }
398 CPPUNIT_CHECK( stack1.ok() );
399 CPPUNIT_CHECK( stack2.ok() );
400
401 #if defined (STLPORT) && !defined (_STLP_NO_MEMBER_TEMPLATES) && \
402 (!defined (_MSC_VER) || (_MSC_VER >= 1300))
403 {
404 //This is a compile time test.
405 //We check that sort implementation is correct when list is instanciated
406 //with an allocator that do not have a default constructor.
407 ListInt lint1(10, 0, stack1);
408 lint1.sort();
409 lint1.sort(greater<int>());
410 }
411 #endif
412 }
413
414 /*
415 void ListTest::const_list()
416 {
417 list<const int> cint_list;
418 cint_list.push_back(1);
419 cint_list.push_front(2);
420 }
421 */
swap()422 void ListTest::swap()
423 {
424 list<int> lst1;
425 list<int> lst2;
426
427 lst1.push_back(1);
428 lst2.push_back(2);
429
430 lst1.swap( lst2 );
431
432 CPPUNIT_CHECK( lst1.front() == 2 );
433 CPPUNIT_CHECK( lst2.front() == 1 );
434 CPPUNIT_CHECK( lst1.size() == 1 );
435 CPPUNIT_CHECK( lst2.size() == 1 );
436
437 lst1.pop_front();
438 lst2.pop_front();
439
440 CPPUNIT_CHECK( lst1.empty() );
441 CPPUNIT_CHECK( lst2.empty() );
442 }
443
444 namespace foo {
445 class bar {};
446
447 template <class _It>
448 size_t distance(_It, _It);
449 }
450
adl()451 void ListTest::adl()
452 {
453 list<foo::bar> lbar;
454 CPPUNIT_ASSERT( lbar.size() == 0);
455 }
456
457 #if !defined (STLPORT) || \
458 !defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
459 /* Simple compilation test: Check that nested types like iterator
460 * can be access even if type used to instanciate container is not
461 * yet completely defined.
462 */
463 class IncompleteClass
464 {
465 list<IncompleteClass> instances;
466 typedef list<IncompleteClass>::iterator it;
467 };
468 #endif
469