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 <algorithm>
6#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)
7#  include <slist>
8#  if !defined (_STLP_USE_NO_IOSTREAMS)
9#    include <sstream>
10#  endif
11#  include <iterator>
12#  include <functional>
13#endif
14
15#include "cppunit/cppunit_proxy.h"
16
17#if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
18using namespace std;
19#endif
20
21#if !defined (STLPORT) && defined(__GNUC__)
22using namespace __gnu_cxx;
23#endif
24
25//
26// TestCase class
27//
28class SlistTest : public CPPUNIT_NS::TestCase
29{
30  CPPUNIT_TEST_SUITE(SlistTest);
31#if !defined (STLPORT) || defined (_STLP_NO_EXTENSIONS) || defined (_STLP_USE_NO_IOSTREAMS)
32  CPPUNIT_IGNORE;
33#endif
34  CPPUNIT_TEST(slist1);
35#if defined (STLPORT) && defined (_STLP_USE_NO_IOSTREAMS)
36  CPPUNIT_STOP_IGNORE;
37#endif
38  CPPUNIT_TEST(erase);
39  CPPUNIT_TEST(insert);
40  CPPUNIT_TEST(splice);
41  CPPUNIT_TEST(allocator_with_state);
42  CPPUNIT_TEST_SUITE_END();
43
44protected:
45  void slist1();
46  void erase();
47  void insert();
48  void splice();
49  void allocator_with_state();
50};
51
52CPPUNIT_TEST_SUITE_REGISTRATION(SlistTest);
53
54//
55// tests implementation
56//
57void SlistTest::slist1()
58{
59#if defined (STLPORT) && !defined (_STLP_USE_NO_IOSTREAMS) && !defined (_STLP_NO_EXTENSIONS)
60/*
61original: xlxtss
62reversed: sstxlx
63removed: sstl
64uniqued: stl
65sorted: lst
66*/
67
68  char array [] = { 'x', 'l', 'x', 't', 's', 's' };
69  ostringstream os;
70  ostream_iterator<char> o(os,"");
71  slist<char> str(array+0, array + 6);
72  slist<char>::iterator i;
73  //Check const_iterator construction from iterator
74  slist<char>::const_iterator ci(i);
75  slist<char>::const_iterator ci2(ci);
76//  cout << "reversed: ";
77  str.reverse();
78  for(i = str.begin(); i != str.end(); i++)
79    os << *i;
80  stringbuf* buff=os.rdbuf();
81  string result=buff->str();
82  CPPUNIT_ASSERT(!strcmp(result.c_str(),"sstxlx"));
83
84  //cout << "removed: ";
85  str.remove('x');
86  ostringstream os2;
87  for(i = str.begin(); i != str.end(); i++)
88    os2 << *i;
89  buff=os2.rdbuf();
90  result=buff->str();
91  CPPUNIT_ASSERT(!strcmp(result.c_str(),"sstl"));
92
93
94  //cout << "uniqued: ";
95  str.unique();
96  ostringstream os3;
97  for(i = str.begin(); i != str.end(); i++)
98    os3 << *i;
99  buff=os3.rdbuf();
100  result=buff->str();
101  CPPUNIT_ASSERT(!strcmp(result.c_str(),"stl"));
102
103  //cout << "sorted: ";
104  str.sort();
105  ostringstream os4;
106  for(i = str.begin(); i != str.end(); i++)
107    os4 << *i;
108  buff = os4.rdbuf();
109  result = buff->str();
110  CPPUNIT_ASSERT(!strcmp(result.c_str(),"lst"));
111
112  //A small compilation time check to be activated from time to time:
113#  if 0
114  {
115    slist<char>::iterator sl_char_ite;
116    slist<int>::iterator sl_int_ite;
117    CPPUNIT_ASSERT( sl_char_ite != sl_int_ite );
118  }
119#  endif
120#endif
121}
122
123void SlistTest::erase()
124{
125#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)
126  int array[] = { 0, 1, 2, 3, 4 };
127  slist<int> sl(array, array + 5);
128  slist<int>::iterator slit;
129
130  slit = sl.erase(sl.begin());
131  CPPUNIT_ASSERT( *slit == 1);
132
133  ++slit++; ++slit;
134  slit = sl.erase(sl.begin(), slit);
135  CPPUNIT_ASSERT( *slit == 3 );
136
137  sl.assign(array, array + 5);
138
139  slit = sl.erase_after(sl.begin());
140  CPPUNIT_ASSERT( *slit == 2 );
141
142  slit = sl.begin(); ++slit; ++slit;
143  slit = sl.erase_after(sl.begin(), slit);
144  CPPUNIT_ASSERT( *slit == 3 );
145
146  sl.erase_after(sl.before_begin());
147  CPPUNIT_ASSERT( sl.front() == 3 );
148#endif
149}
150
151void SlistTest::insert()
152{
153#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)
154  int array[] = { 0, 1, 2, 3, 4 };
155
156  //insert
157  {
158    slist<int> sl;
159
160    sl.insert(sl.begin(), 5);
161    CPPUNIT_ASSERT( sl.front() == 5 );
162    CPPUNIT_ASSERT( sl.size() == 1 );
163
164    //debug mode check:
165    //sl.insert(sl.before_begin(), array, array + 5);
166
167    sl.insert(sl.begin(), array, array + 5);
168    CPPUNIT_ASSERT( sl.size() == 6 );
169    int i;
170    slist<int>::iterator slit(sl.begin());
171    for (i = 0; slit != sl.end(); ++slit, ++i) {
172      CPPUNIT_ASSERT( *slit == i );
173    }
174  }
175
176  //insert_after
177  {
178    slist<int> sl;
179
180    //debug check:
181    //sl.insert_after(sl.begin(), 5);
182
183    sl.insert_after(sl.before_begin(), 5);
184    CPPUNIT_ASSERT( sl.front() == 5 );
185    CPPUNIT_ASSERT( sl.size() == 1 );
186
187    sl.insert_after(sl.before_begin(), array, array + 5);
188    CPPUNIT_ASSERT( sl.size() == 6 );
189    int i;
190    slist<int>::iterator slit(sl.begin());
191    for (i = 0; slit != sl.end(); ++slit, ++i) {
192      CPPUNIT_ASSERT( *slit == i );
193    }
194  }
195#endif
196}
197
198void SlistTest::splice()
199{
200#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)
201  int array[] = { 0, 1, 2, 3, 4 };
202
203  //splice
204  {
205    slist<int> sl1(array, array + 5);
206    slist<int> sl2(array, array + 5);
207    slist<int>::iterator slit;
208
209    //a no op:
210    sl1.splice(sl1.begin(), sl1, sl1.begin());
211    CPPUNIT_ASSERT( sl1 == sl2 );
212
213    slit = sl1.begin(); ++slit;
214    //a no op:
215    sl1.splice(slit, sl1, sl1.begin());
216    CPPUNIT_ASSERT( sl1 == sl2 );
217
218    sl1.splice(sl1.end(), sl1, sl1.begin());
219    slit = sl1.begin();
220    CPPUNIT_ASSERT( *(slit++) == 1 );
221    CPPUNIT_ASSERT( *(slit++) == 2 );
222    CPPUNIT_ASSERT( *(slit++) == 3 );
223    CPPUNIT_ASSERT( *(slit++) == 4 );
224    CPPUNIT_ASSERT( *slit == 0 );
225    sl1.splice(sl1.begin(), sl1, slit);
226    CPPUNIT_ASSERT( sl1 == sl2 );
227
228    sl1.splice(sl1.begin(), sl2);
229    size_t i;
230    for (i = 0, slit = sl1.begin(); slit != sl1.end(); ++slit, ++i) {
231      if (i == 5) i = 0;
232      CPPUNIT_ASSERT( *slit == array[i] );
233    }
234
235    slit = sl1.begin();
236    advance(slit, 5);
237    CPPUNIT_ASSERT( *slit == 0 );
238    sl2.splice(sl2.begin(), sl1, sl1.begin(), slit);
239    CPPUNIT_ASSERT( sl1 == sl2 );
240
241    slit = sl1.begin(); ++slit;
242    sl1.splice(sl1.begin(), sl1, slit, sl1.end());
243    slit = sl1.begin();
244    CPPUNIT_ASSERT( *(slit++) == 1 );
245    CPPUNIT_ASSERT( *(slit++) == 2 );
246    CPPUNIT_ASSERT( *(slit++) == 3 );
247    CPPUNIT_ASSERT( *(slit++) == 4 );
248    CPPUNIT_ASSERT( *slit == 0 );
249
250    // a no op
251    sl2.splice(sl2.end(), sl2, sl2.begin(), sl2.end());
252    for (i = 0, slit = sl2.begin(); slit != sl2.end(); ++slit, ++i) {
253      CPPUNIT_ASSERT( i < 5 );
254      CPPUNIT_ASSERT( *slit == array[i] );
255    }
256
257    slit = sl2.begin();
258    advance(slit, 3);
259    sl2.splice(sl2.end(), sl2, sl2.begin(), slit);
260    slit = sl2.begin();
261    CPPUNIT_ASSERT( *(slit++) == 3 );
262    CPPUNIT_ASSERT( *(slit++) == 4 );
263    CPPUNIT_ASSERT( *(slit++) == 0 );
264    CPPUNIT_ASSERT( *(slit++) == 1 );
265    CPPUNIT_ASSERT( *slit == 2 );
266  }
267
268  //splice_after
269  {
270    slist<int> sl1(array, array + 5);
271    slist<int> sl2(array, array + 5);
272    slist<int>::iterator slit;
273
274    //a no op:
275    sl1.splice_after(sl1.begin(), sl1, sl1.begin());
276    CPPUNIT_ASSERT( sl1 == sl2 );
277
278    sl1.splice_after(sl1.before_begin(), sl1, sl1.begin());
279    slit = sl1.begin();
280    CPPUNIT_ASSERT( *(slit++) == 1 );
281    CPPUNIT_ASSERT( *(slit++) == 0 );
282    CPPUNIT_ASSERT( *(slit++) == 2 );
283    CPPUNIT_ASSERT( *(slit++) == 3 );
284    CPPUNIT_ASSERT( *slit == 4 );
285    sl1.splice_after(sl1.before_begin(), sl1, sl1.begin());
286    CPPUNIT_ASSERT( sl1 == sl2 );
287
288    sl1.splice_after(sl1.before_begin(), sl2);
289    size_t i;
290    for (i = 0, slit = sl1.begin(); slit != sl1.end(); ++slit, ++i) {
291      if (i == 5) i = 0;
292      CPPUNIT_ASSERT( *slit == array[i] );
293    }
294
295    slit = sl1.begin();
296    advance(slit, 4);
297    CPPUNIT_ASSERT( *slit == 4 );
298    sl2.splice_after(sl2.before_begin(), sl1, sl1.before_begin(), slit);
299    CPPUNIT_ASSERT( sl1 == sl2 );
300
301    sl1.splice_after(sl1.before_begin(), sl1, sl1.begin(), sl1.previous(sl1.end()));
302    slit = sl1.begin();
303    CPPUNIT_ASSERT( *(slit++) == 1 );
304    CPPUNIT_ASSERT( *(slit++) == 2 );
305    CPPUNIT_ASSERT( *(slit++) == 3 );
306    CPPUNIT_ASSERT( *(slit++) == 4 );
307    CPPUNIT_ASSERT( *slit == 0 );
308
309    // a no op
310    sl2.splice_after(sl2.before_begin(), sl2, sl2.before_begin(), sl2.previous(sl2.end()));
311    for (i = 0, slit = sl2.begin(); slit != sl2.end(); ++slit, ++i) {
312      CPPUNIT_ASSERT( i < 5 );
313      CPPUNIT_ASSERT( *slit == array[i] );
314    }
315
316    slit = sl2.begin();
317    advance(slit, 2);
318    sl2.splice_after(sl2.previous(sl2.end()), sl2, sl2.before_begin(), slit);
319    slit = sl2.begin();
320    CPPUNIT_ASSERT( *(slit++) == 3 );
321    CPPUNIT_ASSERT( *(slit++) == 4 );
322    CPPUNIT_ASSERT( *(slit++) == 0 );
323    CPPUNIT_ASSERT( *(slit++) == 1 );
324    CPPUNIT_ASSERT( *slit == 2 );
325  }
326#endif
327}
328
329
330void SlistTest::allocator_with_state()
331{
332#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS)
333  char buf1[1024];
334  StackAllocator<int> stack1(buf1, buf1 + sizeof(buf1));
335
336  char buf2[1024];
337  StackAllocator<int> stack2(buf2, buf2 + sizeof(buf2));
338
339  typedef slist<int, StackAllocator<int> > SlistInt;
340  {
341    SlistInt slint1(10, 0, stack1);
342    SlistInt slint1Cpy(slint1);
343
344    SlistInt slint2(10, 1, stack2);
345    SlistInt slint2Cpy(slint2);
346
347    slint1.swap(slint2);
348
349    CPPUNIT_ASSERT( slint1.get_allocator().swaped() );
350    CPPUNIT_ASSERT( slint2.get_allocator().swaped() );
351
352    CPPUNIT_ASSERT( slint1 == slint2Cpy );
353    CPPUNIT_ASSERT( slint2 == slint1Cpy );
354    CPPUNIT_ASSERT( slint1.get_allocator() == stack2 );
355    CPPUNIT_ASSERT( slint2.get_allocator() == stack1 );
356  }
357  CPPUNIT_CHECK( stack1.ok() );
358  CPPUNIT_CHECK( stack2.ok() );
359  stack1.reset(); stack2.reset();
360
361  {
362    SlistInt slint1(stack1);
363    SlistInt slint1Cpy(slint1);
364
365    SlistInt slint2(10, 1, stack2);
366    SlistInt slint2Cpy(slint2);
367
368    slint1.swap(slint2);
369
370    CPPUNIT_ASSERT( slint1.get_allocator().swaped() );
371    CPPUNIT_ASSERT( slint2.get_allocator().swaped() );
372
373    CPPUNIT_ASSERT( slint1 == slint2Cpy );
374    CPPUNIT_ASSERT( slint2 == slint1Cpy );
375    CPPUNIT_ASSERT( slint1.get_allocator() == stack2 );
376    CPPUNIT_ASSERT( slint2.get_allocator() == stack1 );
377  }
378  CPPUNIT_CHECK( stack1.ok() );
379  CPPUNIT_CHECK( stack2.ok() );
380  stack1.reset(); stack2.reset();
381
382  {
383    SlistInt slint1(10, 0, stack1);
384    SlistInt slint1Cpy(slint1);
385
386    SlistInt slint2(stack2);
387    SlistInt slint2Cpy(slint2);
388
389    slint1.swap(slint2);
390
391    CPPUNIT_ASSERT( slint1.get_allocator().swaped() );
392    CPPUNIT_ASSERT( slint2.get_allocator().swaped() );
393
394    CPPUNIT_ASSERT( slint1 == slint2Cpy );
395    CPPUNIT_ASSERT( slint2 == slint1Cpy );
396    CPPUNIT_ASSERT( slint1.get_allocator() == stack2 );
397    CPPUNIT_ASSERT( slint2.get_allocator() == stack1 );
398  }
399  CPPUNIT_CHECK( stack1.ok() );
400  CPPUNIT_CHECK( stack2.ok() );
401  stack1.reset(); stack2.reset();
402
403  //splice(iterator, slist)
404  {
405    SlistInt slint1(10, 0, stack1);
406    SlistInt slint2(10, 1, stack2);
407
408    slint1.splice(slint1.begin(), slint2);
409    CPPUNIT_ASSERT( slint1.size() == 20 );
410    CPPUNIT_ASSERT( slint2.empty() );
411  }
412  CPPUNIT_CHECK( stack1.ok() );
413  CPPUNIT_CHECK( stack2.ok() );
414  stack1.reset(); stack2.reset();
415
416  //splice(iterator, slist, iterator)
417  {
418    SlistInt slint1(10, 0, stack1);
419    SlistInt slint2(10, 1, stack2);
420
421    slint1.splice(slint1.begin(), slint2, slint2.begin());
422    CPPUNIT_ASSERT( slint1.size() == 11 );
423    CPPUNIT_ASSERT( slint2.size() == 9 );
424  }
425  CPPUNIT_CHECK( stack1.ok() );
426  CPPUNIT_CHECK( stack2.ok() );
427  stack1.reset(); stack2.reset();
428
429  //splice(iterator, slist, iterator, iterator)
430  {
431    SlistInt slint1(10, 0, stack1);
432    SlistInt slint2(10, 1, stack2);
433
434    SlistInt::iterator lit(slint2.begin());
435    advance(lit, 5);
436    slint1.splice(slint1.begin(), slint2, slint2.begin(), lit);
437    CPPUNIT_ASSERT( slint1.size() == 15 );
438    CPPUNIT_ASSERT( slint2.size() == 5 );
439  }
440  CPPUNIT_CHECK( stack1.ok() );
441  CPPUNIT_CHECK( stack2.ok() );
442  stack1.reset(); stack2.reset();
443
444  //splice_after(iterator, slist)
445  {
446    SlistInt slint1(10, 0, stack1);
447    SlistInt slint2(10, 1, stack2);
448
449    slint1.splice_after(slint1.before_begin(), slint2);
450    CPPUNIT_ASSERT( slint1.size() == 20 );
451    CPPUNIT_ASSERT( slint2.empty() );
452  }
453  CPPUNIT_CHECK( stack1.ok() );
454  CPPUNIT_CHECK( stack2.ok() );
455  stack1.reset(); stack2.reset();
456
457  //splice_after(iterator, slist, iterator)
458  {
459    SlistInt slint1(10, 0, stack1);
460    SlistInt slint2(10, 1, stack2);
461
462    slint1.splice_after(slint1.before_begin(), slint2, slint2.before_begin());
463    CPPUNIT_ASSERT( slint1.size() == 11 );
464    CPPUNIT_ASSERT( slint2.size() == 9 );
465  }
466  CPPUNIT_CHECK( stack1.ok() );
467  CPPUNIT_CHECK( stack2.ok() );
468  stack1.reset(); stack2.reset();
469
470  //splice_after(iterator, slist, iterator, iterator)
471  {
472    SlistInt slint1(10, 0, stack1);
473    SlistInt slint2(10, 1, stack2);
474
475    SlistInt::iterator lit(slint2.begin());
476    advance(lit, 4);
477    slint1.splice_after(slint1.before_begin(), slint2, slint2.before_begin(), lit);
478    CPPUNIT_ASSERT( slint1.size() == 15 );
479    CPPUNIT_ASSERT( slint2.size() == 5 );
480  }
481  CPPUNIT_CHECK( stack1.ok() );
482  CPPUNIT_CHECK( stack2.ok() );
483  stack1.reset(); stack2.reset();
484
485  //merge(slist)
486  {
487    SlistInt slint1(10, 0, stack1);
488    SlistInt slint2(10, 1, stack2);
489
490    SlistInt slintref(stack2);
491    slintref.insert_after(slintref.before_begin(), 10, 1);
492    slintref.insert_after(slintref.before_begin(), 10, 0);
493
494    slint1.merge(slint2);
495    CPPUNIT_ASSERT( slint1.size() == 20 );
496    CPPUNIT_ASSERT( slint1 == slintref );
497    CPPUNIT_ASSERT( slint2.empty() );
498  }
499  CPPUNIT_CHECK( stack1.ok() );
500  CPPUNIT_CHECK( stack2.ok() );
501
502  //merge(slist, predicate)
503#  if (!defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)) && \
504      (!defined (_MSC_VER) || (_MSC_VER >= 1300))
505  {
506    SlistInt slint1(10, 0, stack1);
507    SlistInt slint2(10, 1, stack2);
508
509    SlistInt slintref(stack2);
510    slintref.insert_after(slintref.before_begin(), 10, 0);
511    slintref.insert_after(slintref.before_begin(), 10, 1);
512
513    slint1.merge(slint2, greater<int>());
514    CPPUNIT_ASSERT( slint1.size() == 20 );
515    CPPUNIT_ASSERT( slint1 == slintref );
516    CPPUNIT_ASSERT( slint2.empty() );
517  }
518  CPPUNIT_CHECK( stack1.ok() );
519  CPPUNIT_CHECK( stack2.ok() );
520
521  //sort
522  {
523    //This is rather a compile time test.
524    //We check that sort implementation is correct when list is instanciated
525    //with an allocator that do not have a default constructor.
526    SlistInt slint1(stack1);
527    slint1.push_front(1);
528    slint1.insert_after(slint1.before_begin(), 10, 0);
529    greater<int> gt;
530    slint1.sort(gt);
531    CPPUNIT_ASSERT( slint1.front() == 1 );
532    slint1.sort();
533    SlistInt::iterator slit(slint1.begin());
534    advance(slit, 10);
535    CPPUNIT_ASSERT( *slit == 1 );
536  }
537#  endif
538#endif
539}
540
541#if defined (STLPORT) && !defined (_STLP_NO_EXTENSIONS) && \
542    (!defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION))
543#  if !defined (__DMC__)
544/* Simple compilation test: Check that nested types like iterator
545 * can be access even if type used to instanciate container is not
546 * yet completely defined.
547 */
548class IncompleteClass
549{
550  slist<IncompleteClass> instances;
551  typedef slist<IncompleteClass>::iterator it;
552};
553#  endif
554#endif
555