• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //To make GLib C++ closer to STLport behavior we need this macro:
2 //Only mandatory when building unit tests without STLport, do not change
3 //anything when building with STLport
4 #define _GLIBCXX_FULLY_DYNAMIC_STRING
5 
6 //Has to be first for StackAllocator swap overload to be taken
7 //into account (at least using GCC 4.0.1)
8 #include "stack_allocator.h"
9 
10 #include <vector>
11 #include <deque>
12 #include <string>
13 #include <algorithm>
14 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
15 #  include <sstream>
16 #endif
17 
18 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
19 #  include <stdexcept>
20 #endif
21 
22 #if !defined (STLPORT) || defined (_STLP_THREADS)
23 #  if defined (STLPORT) && defined (_STLP_PTHREADS) || \
24       defined (__GNUC__) && !defined (__MINGW32__)
25 #    define USE_PTHREAD_API
26 #    include <pthread.h>
27 #  endif
28 
29 #  if defined (STLPORT) && defined (_STLP_WIN32THREADS) || \
30       defined (__GNUC__) && defined (__MINGW32__) || \
31       defined (_MSC_VER)
32 #    define USE_WINDOWS_API
33 #    include <windows.h>
34 #  endif
35 #endif
36 
37 #include "stack_allocator.h"
38 #include "cppunit/cppunit_proxy.h"
39 
40 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
41 using namespace std;
42 #endif
43 
44 //
45 // TestCase class
46 //
47 class StringTest : public CPPUNIT_NS::TestCase
48 {
49   CPPUNIT_TEST_SUITE(StringTest);
50   CPPUNIT_TEST(constructor);
51   CPPUNIT_TEST(trivial_char_compare);
52   CPPUNIT_TEST(reserve);
53   CPPUNIT_TEST(assign);
54   CPPUNIT_TEST(erase);
55   CPPUNIT_TEST(data);
56   CPPUNIT_TEST(c_str);
57   CPPUNIT_TEST(null_char);
58   CPPUNIT_TEST(insert);
59   CPPUNIT_TEST(replace);
60   CPPUNIT_TEST(resize);
61   CPPUNIT_TEST(short_string);
62   CPPUNIT_TEST(find);
63   CPPUNIT_TEST(bogus_edge_find);
64   CPPUNIT_TEST(rfind);
65   CPPUNIT_TEST(find_last_of);
66   CPPUNIT_TEST(find_last_not_of);
67   CPPUNIT_TEST(copy);
68 #if !defined (USE_PTHREAD_API) && !defined (USE_WINDOWS_API)
69   CPPUNIT_IGNORE;
70 #endif
71   CPPUNIT_TEST(mt);
72   CPPUNIT_STOP_IGNORE;
73   CPPUNIT_TEST(short_string_optim_bug);
74   CPPUNIT_TEST(compare);
75   CPPUNIT_TEST(template_expression);
76 #if defined (STLPORT) && ((defined (_STLP_MSVC) && (_STLP_MSVC < 1300)) || \
77    (defined(__GNUC__) && defined(_STLP_USE_TEMPLATE_EXPRESSION) && \
78     ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)) ) )
79 #  define TE_TMP_TEST_IGNORED
80   CPPUNIT_IGNORE;
81 #endif
82   CPPUNIT_TEST(te_tmp);
83 #if defined (TE_TMP_TEST_IGNORED)
84   CPPUNIT_STOP_IGNORE;
85 #endif
86   CPPUNIT_TEST(oper_tmp);
87 #if defined (STLPORT) && defined (_STLP_NO_WCHAR_T)
88   CPPUNIT_IGNORE;
89 #endif
90 #if defined (__CYGWIN__) && !defined (STLPORT)
91   CPPUNIT_IGNORE;
92 #endif
93   CPPUNIT_TEST(template_wexpression);
94   CPPUNIT_STOP_IGNORE;
95 #if defined (STLPORT) && defined (_STLP_USE_NO_IOSTREAMS)
96   CPPUNIT_IGNORE;
97 #endif
98   CPPUNIT_TEST(io);
99   CPPUNIT_STOP_IGNORE;
100 #if defined (STLPORT) && defined (_STLP_NO_CUSTOM_IO)
101   CPPUNIT_IGNORE;
102 #endif
103   CPPUNIT_TEST(allocator_with_state);
104   CPPUNIT_STOP_IGNORE;
105   CPPUNIT_TEST(capacity);
106   CPPUNIT_TEST(concat24);
107   CPPUNIT_TEST_SUITE_END();
108 
109 protected:
110   void constructor();
111   void trivial_char_compare();
112   void reserve();
113   void erase();
114   void data();
115   void c_str();
116   void null_char();
117   void insert();
118   void replace();
119   void resize();
120   void short_string();
121   void find();
122   void bogus_edge_find();
123   void rfind();
124   void find_last_of();
125   void find_last_not_of();
126   void copy();
127   void assign();
128   void mt();
129   void short_string_optim_bug();
130   void compare();
131   void template_expression();
132   void te_tmp();
133   void oper_tmp();
134   void template_wexpression();
135   void io();
136   void allocator_with_state();
137   void capacity();
138   void concat24();
139 
func(const string & par)140   static string func(const string& par) {
141     string tmp( par );
142     return tmp;
143   }
144 
145 #if defined (USE_PTHREAD_API) || defined (USE_WINDOWS_API)
146 #  if defined (USE_PTHREAD_API)
f(void *)147   static void* f(void*)
148 #  else
149   static DWORD __stdcall f(void*)
150 #  endif
151   {
152     string s( "qyweyuewunfkHBUKGYUGL,wehbYGUW^(@T@H!BALWD:h^&@#*@(#:JKHWJ:CND" );
153 
154     for ( int i = 0; i < 2000000; ++i ) {
155       string sx = func( s );
156     }
157 
158     return 0;
159   }
160 #endif
161 
162 };
163 
164 CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);
165 
166 //
167 // tests implementation
168 //
constructor()169 void StringTest::constructor()
170 {
171 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
172   try {
173     string s((size_t)-1, 'a');
174     CPPUNIT_FAIL;
175   }
176   catch (length_error const&) {
177   }
178   catch (...) {
179     //Expected exception is length_error:
180     CPPUNIT_FAIL;
181   }
182 #endif
183 }
184 
trivial_char_compare()185 void StringTest::trivial_char_compare()
186 {
187   string s( "message" );
188 
189   CPPUNIT_CHECK( s == "message" );
190   CPPUNIT_CHECK( "message" == s );
191 }
192 
reserve()193 void StringTest::reserve()
194 {
195   string s;
196 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
197   try {
198     s.reserve(s.max_size() + 1);
199     CPPUNIT_FAIL;
200   }
201   catch (length_error const&) {
202   }
203   catch (...) {
204     //Expected exception is length_error:
205     CPPUNIT_FAIL;
206   }
207 #endif
208 }
209 
mt()210 void StringTest::mt()
211 {
212 #if defined (USE_PTHREAD_API) || defined (USE_WINDOWS_API)
213   const int nth = 2;
214 #  if defined (USE_PTHREAD_API)
215   pthread_t t[nth];
216 
217   for ( int i = 0; i < nth; ++i ) {
218     pthread_create( &t[i], 0, f, 0 );
219   }
220 
221   for ( int i = 0; i < nth; ++i ) {
222     pthread_join( t[i], 0 );
223   }
224 #  endif // PTHREAD
225 
226 #  if defined (USE_WINDOWS_API)
227   //DWORD start = GetTickCount();
228 
229   HANDLE t[nth];
230 
231   int i; // VC6 not support in-loop scope of cycle var
232   for ( i = 0; i < nth; ++i ) {
233     t[i] = CreateThread(NULL, 0, f, 0, 0, NULL);
234   }
235 
236   if (WaitForMultipleObjects(nth, t, TRUE, INFINITE) == WAIT_FAILED) {
237     // On some platforms (evc3/evc4) WaitForMultipleObjects() with fWaitAll == TRUE
238     // is not supported. We then wait with a loop on each thread:
239     for ( i = 0; i < nth; ++i ) {
240       WaitForSingleObject(t[i], INFINITE);
241     }
242   }
243 
244   /*
245   DWORD duration = GetTickCount() - start;
246   ostringstream ostr;
247   ostr << "Duration: " << duration << endl;
248   CPPUNIT_MESSAGE(ostr.str().c_str());
249   */
250 #  endif
251 #endif
252 }
253 
short_string()254 void StringTest::short_string()
255 {
256   string const ref_short_str1("str1"), ref_short_str2("str2");
257   string short_str1(ref_short_str1), short_str2(ref_short_str2);
258   string const ref_long_str1("str                                                  1");
259   string const ref_long_str2("str                                                  2");
260   string long_str1(ref_long_str1), long_str2(ref_long_str2);
261 
262   CPPUNIT_ASSERT(short_str1 == ref_short_str1);
263   CPPUNIT_ASSERT(long_str1 == ref_long_str1);
264 
265   {
266     string str1(short_str1);
267     str1 = long_str1;
268     CPPUNIT_ASSERT(str1 == ref_long_str1);
269   }
270 
271   {
272     string str1(long_str1);
273     str1 = short_str1;
274     CPPUNIT_ASSERT(str1 == ref_short_str1);
275   }
276 
277   {
278     short_str1.swap(short_str2);
279     CPPUNIT_ASSERT((short_str1 == ref_short_str2) && (short_str2 == ref_short_str1));
280     short_str1.swap(short_str2);
281   }
282 
283   {
284     long_str1.swap(long_str2);
285     CPPUNIT_ASSERT((long_str1 == ref_long_str2) && (long_str2 == ref_long_str1));
286     long_str1.swap(long_str2);
287   }
288 
289   {
290     short_str1.swap(long_str1);
291     CPPUNIT_ASSERT((short_str1 == ref_long_str1) && (long_str1 == ref_short_str1));
292     short_str1.swap(long_str1);
293   }
294 
295   {
296     long_str1.swap(short_str1);
297     CPPUNIT_ASSERT((short_str1 == ref_long_str1) && (long_str1 == ref_short_str1));
298     long_str1.swap(short_str1);
299   }
300 
301   {
302     string a(256, 'a');
303     string b(256, 'b');
304     const char* as = a.c_str();
305     const char* bs = b.c_str();
306     swap(a, b);
307     CPPUNIT_ASSERT( a.c_str() == bs );
308     CPPUNIT_ASSERT( b.c_str() == as );
309   }
310 
311   {
312     //This is to test move constructor
313     vector<string> str_vect;
314     str_vect.push_back(short_str1);
315     str_vect.push_back(long_str1);
316     str_vect.push_back(short_str2);
317     str_vect.push_back(long_str2);
318     CPPUNIT_ASSERT((str_vect[0] == ref_short_str1) &&
319                    (str_vect[1] == ref_long_str1) &&
320                    (str_vect[2] == ref_short_str2) &&
321                    (str_vect[3] == ref_long_str2));
322   }
323 }
324 
erase()325 void StringTest::erase()
326 {
327   char const* c_str = "Hello, World!";
328   string str(c_str);
329   CPPUNIT_ASSERT( str == c_str );
330 
331   str.erase(str.begin() + 1, str.end() - 1); // Erase all but first and last.
332 
333   size_t i;
334   for (i = 0; i < str.size(); ++i) {
335     switch ( i ) {
336       case 0:
337         CPPUNIT_ASSERT( str[i] == 'H' );
338         break;
339       case 1:
340         CPPUNIT_ASSERT( str[i] == '!' );
341         break;
342       default:
343         CPPUNIT_FAIL;
344     }
345   }
346 
347   str.insert(1, c_str);
348   str.erase(str.begin()); // Erase first element.
349   str.erase(str.end() - 1); // Erase last element.
350   CPPUNIT_ASSERT( str == c_str );
351   str.clear(); // Erase all.
352   CPPUNIT_ASSERT( str.empty() );
353 
354   str = c_str;
355   CPPUNIT_ASSERT( str == c_str );
356 
357   str.erase(1, str.size() - 1); // Erase all but first and last.
358   for (i = 0; i < str.size(); i++) {
359     switch ( i ) {
360       case 0:
361         CPPUNIT_ASSERT( str[i] == 'H' );
362         break;
363       case 1:
364         CPPUNIT_ASSERT( str[i] == '!' );
365         break;
366       default:
367         CPPUNIT_FAIL;
368     }
369   }
370 
371   str.erase(1);
372   CPPUNIT_ASSERT( str == "H" );
373 }
374 
data()375 void StringTest::data()
376 {
377   string xx;
378 
379   CPPUNIT_ASSERT( xx.data() != 0 );  // ISO-IEC-14882:1998(E), 21.3.6, paragraph 3
380 #if 0
381   /* This test really not required: in ISO-IEC-14882:1998(E) paragraph 3 stated:
382    * '... and can have zero added to it', again: 'CAN', but not 'MUST'.
383    * That's why I am comment this test. But I don't remove it due to I had
384    * unevident problem with misinterpretation of data() return (i.e. data()
385    * and c_str() provide different functionality!) and expect that this is
386    * more-or-less common pitfall.
387    *    - ptr
388    */
389   string low( "2004-01-01" );
390   // Blocks A and B should follow each other.
391   // Block A:
392   xx = "123456";
393   xx += low;
394   if ( strcmp( xx.data(), "1234562004-01-01" ) != 0 ) {
395     return -1;
396   }
397   // End of block A
398 
399   // Block B:
400   xx = "1234";
401   xx += ";";
402 
403   if ( strcmp( xx.data(), "1234;" ) != 0 ) {
404     return -1;
405   }
406   // End of block B
407 #endif
408 }
409 
c_str()410 void StringTest::c_str()
411 {
412   string low( "2004-01-01" );
413   string xx;
414   string yy;
415 
416   CPPUNIT_ASSERT( *(yy.c_str()) == '\0' ); // ISO-IEC-14882:1998(E), 21.3.6, paragraph 1
417 
418   // Blocks A and B should follow each other.
419   // Block A:
420   xx = "123456";
421   xx += low;
422   CPPUNIT_ASSERT( strcmp( xx.c_str(), "1234562004-01-01" ) == 0 );
423   // End of block A
424 
425   // Block B:
426   xx = "1234";
427   xx += ";";
428   CPPUNIT_ASSERT( strcmp( xx.c_str(), "1234;" ) == 0 );
429   // End of block B
430 }
431 
null_char()432 void StringTest::null_char()
433 {
434   // ISO/IEC 14882:1998(E), ISO/IEC 14882:2003(E), 21.3.4 ('... the const version')
435   const string s( "123456" );
436 
437   CPPUNIT_CHECK( s[s.size()] == '\0' );
438 
439 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
440   try {
441     //Check is only here to avoid warning about value of expression not used
442     CPPUNIT_CHECK( s.at(s.size()) == '\0' );
443     CPPUNIT_FAIL;
444   }
445   catch (out_of_range const&) {
446     CPPUNIT_ASSERT( true );
447   }
448   catch ( ... ) {
449     CPPUNIT_FAIL;
450   }
451 #endif
452 }
453 
insert()454 void StringTest::insert()
455 {
456   string strorg = "This is test string for string calls";
457   string str;
458   /*
459    * In case of reallocation there is no auto reference problem
460    * so we reserve a big enough string to be sure to test this
461    * particular point.
462    */
463   str.reserve(100);
464   str = strorg;
465 
466   //test self insertion:
467   str.insert(10, str.c_str() + 5, 15);
468   CPPUNIT_ASSERT( str == "This is teis test string st string for string calls" );
469 
470   str = strorg;
471   str.insert(15, str.c_str() + 5, 25);
472   CPPUNIT_ASSERT( str == "This is test stis test string for stringring for string calls" );
473 
474   str = strorg;
475   str.insert(0, str.c_str() + str.size() - 4, 4);
476   CPPUNIT_ASSERT( str == "allsThis is test string for string calls" );
477 
478   str = strorg;
479   str.insert(0, str.c_str() + str.size() / 2 - 1, str.size() / 2 + 1);
480   CPPUNIT_ASSERT( str == "ng for string callsThis is test string for string calls" );
481 
482   str = strorg;
483   string::iterator b = str.begin();
484   string::const_iterator s = str.begin() + str.size() / 2 - 1;
485   string::const_iterator e = str.end();
486   str.insert( b, s, e );
487   CPPUNIT_ASSERT( str == "ng for string callsThis is test string for string calls" );
488 
489   str = strorg;
490   str.insert(str.begin(), str.begin() + str.size() / 2 - 1, str.end());
491   CPPUNIT_ASSERT( str == "ng for string callsThis is test string for string calls" );
492 
493 #ifdef _STLP_MEMBER_TEMPLATES
494   vector<int> int_vect;
495   //Just a compile time test:
496   str.insert(str.end(), int_vect.begin(), int_vect.end());
497 #endif
498 
499   string str0;
500   str0.insert(str0.begin(), 5, '0');
501   CPPUNIT_ASSERT( str0 == "00000" );
502 
503   string str1;
504   {
505     string::size_type pos = 0, nb = 2;
506     str1.insert(pos, nb, '1');
507   }
508   CPPUNIT_ASSERT( str1 == "11" );
509 
510   str0.insert(0, str1);
511   CPPUNIT_ASSERT( str0 == "1100000" );
512 
513   string str2("2345");
514   str0.insert(str0.size(), str2, 1, 2);
515   CPPUNIT_ASSERT( str0 == "110000034" );
516 
517   str1.insert(str1.begin() + 1, 2, '2');
518   CPPUNIT_ASSERT( str1 == "1221" );
519 
520   str1.insert(2, "333333", 3);
521   CPPUNIT_ASSERT( str1 == "1233321" );
522 
523   str1.insert(4, "4444");
524   CPPUNIT_ASSERT( str1 == "12334444321" );
525 
526   str1.insert(str1.begin() + 6, '5');
527   CPPUNIT_ASSERT( str1 == "123344544321" );
528 }
529 
replace()530 void StringTest::replace()
531 {
532   /*
533    * This test case is for the non template basic_string::replace method,
534    * this is why we play with the const iterators and reference to guaranty
535    * that the right method is called.
536    */
537   const string v( "78" );
538   string s( "123456" );
539   string const& cs = s;
540 
541   string::iterator i = s.begin() + 1;
542   s.replace(i, i + 3, v.begin(), v.end());
543   CPPUNIT_ASSERT( s == "17856" );
544 
545   s = "123456";
546   i = s.begin() + 1;
547   s.replace(i, i + 1, v.begin(), v.end());
548   CPPUNIT_ASSERT( s == "1783456" );
549 
550   s = "123456";
551   i = s.begin() + 1;
552   string::const_iterator ci = s.begin() + 1;
553   s.replace(i, i + 3, ci + 3, cs.end());
554   CPPUNIT_ASSERT( s == "15656" );
555 
556   s = "123456";
557   i = s.begin() + 1;
558   ci = s.begin() + 1;
559   s.replace(i, i + 3, ci, ci + 2);
560   CPPUNIT_ASSERT( s == "12356" );
561 
562   s = "123456";
563   i = s.begin() + 1;
564   ci = s.begin() + 1;
565   s.replace(i, i + 3, ci + 1, cs.end());
566   CPPUNIT_ASSERT( s == "1345656" );
567 
568   s = "123456";
569   i = s.begin();
570   ci = s.begin() + 1;
571   s.replace(i, i, ci, ci + 1);
572   CPPUNIT_CHECK( s == "2123456" );
573 
574   s = "123456";
575   s.replace(s.begin() + 4, s.end(), cs.begin(), cs.end());
576   CPPUNIT_ASSERT( s == "1234123456" );
577 
578   /*
579    * This is the test for the template replace method.
580    */
581   s = "123456";
582   string::iterator b = s.begin() + 4;
583   string::iterator e = s.end();
584   string::const_iterator rb = s.begin();
585   string::const_iterator re = s.end();
586   s.replace(b, e, rb, re);
587   CPPUNIT_ASSERT( s == "1234123456" );
588 
589   s = "123456";
590   s.replace(s.begin() + 4, s.end(), s.begin(), s.end());
591   CPPUNIT_ASSERT( s == "1234123456" );
592 
593   string strorg("This is test string for string calls");
594   string str = strorg;
595   str.replace(5, 15, str.c_str(), 10);
596   CPPUNIT_ASSERT( str == "This This is tefor string calls" );
597 
598   str = strorg;
599   str.replace(5, 5, str.c_str(), 10);
600   CPPUNIT_ASSERT( str == "This This is test string for string calls" );
601 
602 #if (defined (STLPORT) && defined(_STLP_MEMBER_TEMPLATES)) || ( !defined (STLPORT) && !defined(__GNUC__) )
603   deque<char> cdeque;
604   cdeque.push_back('I');
605   str.replace(str.begin(), str.begin() + 11, cdeque.begin(), cdeque.end());
606   CPPUNIT_ASSERT( str == "Is test string for string calls" );
607 #endif
608 }
609 
resize()610 void StringTest::resize()
611 {
612   string s;
613 
614   s.resize(0);
615 
616   CPPUNIT_ASSERT( *s.c_str() == 0 );
617 
618   s = "1234567";
619 
620   s.resize(0);
621   CPPUNIT_ASSERT( *s.c_str() == 0 );
622 
623   s = "1234567";
624   s.resize(1);
625   CPPUNIT_ASSERT( s.size() == 1 );
626   CPPUNIT_ASSERT( *s.c_str() == '1' );
627   CPPUNIT_ASSERT( *(s.c_str() + 1) == 0 );
628 
629   s = "1234567";
630   s.resize(10);
631   CPPUNIT_ASSERT( s.size() == 10 );
632   CPPUNIT_ASSERT( s[6] == '7' );
633   CPPUNIT_ASSERT( s[7] == 0 );
634   CPPUNIT_ASSERT( s[8] == 0 );
635   CPPUNIT_ASSERT( s[9] == 0 );
636 }
637 
find()638 void StringTest::find()
639 {
640   string s("one two three one two three");
641   CPPUNIT_ASSERT( s.find("one") == 0 );
642   CPPUNIT_ASSERT( s.find('t') == 4 );
643   CPPUNIT_ASSERT( s.find('t', 5) == 8 );
644   //We are trying to get a const reference to the npos string static member to
645   //force the compiler to allocate memory for this variable. It is used to reveal
646   //a bug of STLport which was simply declaring npos without instanciating it.
647 #if defined (STLPORT) && defined (_STLP_STATIC_CONST_INIT_BUG)
648   string::size_type const& npos_local = string::npos;
649 #else
650 #  define npos_local string::npos
651 #endif
652   CPPUNIT_ASSERT( s.find("four") == npos_local );
653   CPPUNIT_ASSERT( s.find("one", string::npos) == npos_local );
654 
655   CPPUNIT_ASSERT( s.find_first_of("abcde") == 2 );
656 
657   CPPUNIT_ASSERT( s.find_first_not_of("enotw ") == 9 );
658 
659   string empty;
660   CPPUNIT_ASSERT( s.substr(s.find(empty), empty.size()) == empty );
661 }
662 
bogus_edge_find()663 void StringTest::bogus_edge_find()
664 {
665   /* ISO/IEC 14882 2003, 21.3.6.1 basic_string::find [lib.string::find]
666    *
667    * size_type find(const basic_string<charT,traits,Allocator>& str,
668    *                size_type pos = 0) const;
669    * Effects: Determines the lowest position xpos, if possible, such that
670    * both of the following conditions obtain:
671    *    pos <= xpos and xpos + str.size() <= size();
672    *    at(xpos+I) == str.at(I) for all elements I of the string controlled by str.
673    * Returns: xpos if the function can determine such a value for xpos. Otherwise,
674    * returns npos.
675    * Notes: Uses traits::eq().
676    *
677    * ===
678    * So, from formal point of view
679    *   string s; string::size_type p = s.find( "", 0, 0 );
680    * should return 0 in p, i.e. position out-of-bound of string, so
681    * code like following is bad:
682    * string s;
683    *
684    * string::size_type p = s.find( "", 0, 0 );
685    *
686    * ...
687    *
688    * if ( p != string::npos ) { // normal
689    *   char ch = s[p]; // Arghhhhhhhhhh
690    * }
691    *
692    * People near Standard commete has opinion opposite to my. Even if it looks
693    * like bogus behaviour for me, it should be fixed.
694    */
695 
696   {
697     string s;
698     string::size_type p = s.find( "", 0, 0 );
699 
700     /* CPPUNIT_CHECK( p == string::npos ); */
701     CPPUNIT_CHECK( p == 0 ); // bogus result, isn't it?
702   }
703   {
704     string s( "123" );
705     string::size_type p = s.find( "", 0, 0 );
706 
707     CPPUNIT_CHECK( p == 0 );
708   }
709   {
710     string s( "123" );
711     string::size_type p = s.find( "", 1, 0 );
712 
713     CPPUNIT_CHECK( p == 1 );
714   }
715   {
716     string s( "" );
717     string::size_type p = s.find( "", 1, 0 );
718 
719     CPPUNIT_CHECK( p == string::npos );
720   }
721   {
722     string s( "123" );
723     string::size_type p = s.find( "", 3, 0 );
724 
725     CPPUNIT_CHECK( p == 3 ); // bogus result, isn't it?
726   }
727   {
728     string s;
729     string::size_type p = s.rfind( "", 0, 0 );
730 
731     /* CPPUNIT_CHECK( p == string::npos ); */
732     CPPUNIT_CHECK( p == 0 ); // bogus result, isn't it?
733   }
734   {
735     string s( "123" );
736     string::size_type p = s.rfind( "", 0, 0 );
737 
738     CPPUNIT_CHECK( p == 0 );
739   }
740   {
741     string s( "123" );
742     string::size_type p = s.rfind( "", 1, 0 );
743 
744     CPPUNIT_CHECK( p == 1 );
745   }
746   {
747     string s( "" );
748     string::size_type p = s.rfind( "", 1, 0 );
749 
750     CPPUNIT_CHECK( p == 0 ); // bogus result, isn't it?
751   }
752   {
753     string s( "123" );
754     string::size_type p = s.rfind( "", 3, 0 );
755 
756     CPPUNIT_CHECK( p == 3 ); // bogus result, isn't it?
757   }
758 }
759 
rfind()760 void StringTest::rfind()
761 {
762   // 21.3.6.2
763   string s("one two three one two three");
764 
765   CPPUNIT_ASSERT( s.rfind("two") == 18 );
766   CPPUNIT_ASSERT( s.rfind("two", 0) == string::npos );
767   CPPUNIT_ASSERT( s.rfind("two", 11) == 4 );
768   CPPUNIT_ASSERT( s.rfind('w') == 19 );
769 
770   string test( "aba" );
771 
772   CPPUNIT_CHECK( test.rfind( "a", 2, 1 ) == 2 );
773   CPPUNIT_CHECK( test.rfind( "a", 1, 1 ) == 0 );
774   CPPUNIT_CHECK( test.rfind( "a", 0, 1 ) == 0 );
775 
776   CPPUNIT_CHECK( test.rfind( 'a', 2 ) == 2 );
777   CPPUNIT_CHECK( test.rfind( 'a', 1 ) == 0 );
778   CPPUNIT_CHECK( test.rfind( 'a', 0 ) == 0 );
779 }
780 
find_last_of()781 void StringTest::find_last_of()
782 {
783   // 21.3.6.4
784   string s("one two three one two three");
785 
786   CPPUNIT_ASSERT( s.find_last_of("abcde") == 26 );
787 
788   string test( "aba" );
789 
790   CPPUNIT_CHECK( test.find_last_of( "a", 2, 1 ) == 2 );
791   CPPUNIT_CHECK( test.find_last_of( "a", 1, 1 ) == 0 );
792   CPPUNIT_CHECK( test.find_last_of( "a", 0, 1 ) == 0 );
793 
794   CPPUNIT_CHECK( test.find_last_of( 'a', 2 ) == 2 );
795   CPPUNIT_CHECK( test.find_last_of( 'a', 1 ) == 0 );
796   CPPUNIT_CHECK( test.find_last_of( 'a', 0 ) == 0 );
797 }
798 
find_last_not_of()799 void StringTest::find_last_not_of()
800 {
801   // 21.3.6.6
802   string s("one two three one two three");
803 
804   CPPUNIT_ASSERT( s.find_last_not_of("ehortw ") == 15 );
805 
806   string test( "aba" );
807 
808   CPPUNIT_CHECK( test.find_last_not_of( "a", 2, 1 ) == 1 );
809   CPPUNIT_CHECK( test.find_last_not_of( "b", 2, 1 ) == 2 );
810   CPPUNIT_CHECK( test.find_last_not_of( "a", 1, 1 ) == 1 );
811   CPPUNIT_CHECK( test.find_last_not_of( "b", 1, 1 ) == 0 );
812   CPPUNIT_CHECK( test.find_last_not_of( "a", 0, 1 ) == string::npos );
813   CPPUNIT_CHECK( test.find_last_not_of( "b", 0, 1 ) == 0 );
814 
815   CPPUNIT_CHECK( test.find_last_not_of( 'a', 2 ) == 1 );
816   CPPUNIT_CHECK( test.find_last_not_of( 'b', 2 ) == 2 );
817   CPPUNIT_CHECK( test.find_last_not_of( 'a', 1 ) == 1 );
818   CPPUNIT_CHECK( test.find_last_not_of( 'b', 1 ) == 0 );
819   CPPUNIT_CHECK( test.find_last_not_of( 'a', 0 ) == string::npos );
820   CPPUNIT_CHECK( test.find_last_not_of( 'b', 0 ) == 0 );
821 }
822 
copy()823 void StringTest::copy()
824 {
825   string s("foo");
826   char dest[4];
827   dest[0] = dest[1] = dest[2] = dest[3] = 1;
828   s.copy(dest, 4);
829   int pos = 0;
830   CPPUNIT_ASSERT( dest[pos++] == 'f' );
831   CPPUNIT_ASSERT( dest[pos++] == 'o' );
832   CPPUNIT_ASSERT( dest[pos++] == 'o' );
833   CPPUNIT_ASSERT( dest[pos++] == 1 );
834 
835   dest[0] = dest[1] = dest[2] = dest[3] = 1;
836   s.copy(dest, 4, 2);
837   pos = 0;
838   CPPUNIT_ASSERT( dest[pos++] == 'o' );
839   CPPUNIT_ASSERT( dest[pos++] == 1 );
840 
841 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
842   try {
843     s.copy(dest, 4, 5);
844     CPPUNIT_FAIL;
845   }
846   catch (out_of_range const&) {
847   }
848   catch ( ... ) {
849     CPPUNIT_FAIL;
850   }
851 #endif
852 }
853 
assign()854 void StringTest::assign()
855 {
856   string s;
857   char const* cstr = "test string for assign";
858 
859   s.assign(cstr, cstr + 22);
860   CPPUNIT_ASSERT( s == "test string for assign" );
861 
862   string s2("other test string");
863   s.assign(s2);
864   CPPUNIT_ASSERT( s == s2 );
865 
866   static string str1;
867   static string str2;
868 
869   // short string optim:
870   str1 = "123456";
871   // longer than short string:
872   str2 = "1234567890123456789012345678901234567890";
873 
874   CPPUNIT_ASSERT(str1[5] == '6');
875   CPPUNIT_ASSERT(str2[29] == '0');
876 }
877 
878 /* This test is to check if string properly supports the short string
879  * optimization. It has been found out that eMbedded Visual C++ 3.0 and .NET
880  * compilers for the ARM platform fail to pass structs and classes of certain
881  * size per value. This seems to be a known compiler bug. For other processors
882  * (e.g. x86) the error doesn't occur.
883  * (The ARM compiler creates a temporary object from teststr on the stack, to
884  * pass it to the helper function. It uses the copy constructor for this.
885  * After this the temporary object is copied to another place on the stack.
886  * The result is that the _M_finish pointer then points to the wrong buffer
887  * end and the size of the short string is incorrectly calculated.)
888  */
short_string_optim_bug()889 void StringTest::short_string_optim_bug()
890 {
891    string teststr("shortest");
892 
893    bool short_string_optim_bug_helper(string teststr);
894 
895    CPPUNIT_ASSERT(true == short_string_optim_bug_helper(teststr));
896 }
897 
short_string_optim_bug_helper(string teststr)898 bool short_string_optim_bug_helper(string teststr)
899 {
900    size_t ss = teststr.size();
901    return (ss == 8);
902 }
903 
compare()904 void StringTest::compare()
905 {
906   string str1("abcdef");
907   string str2;
908 
909   str2 = "abcdef";
910   CPPUNIT_ASSERT( str1.compare(str2) == 0 );
911   str2 = "abcde";
912   CPPUNIT_ASSERT( str1.compare(str2) > 0 );
913   str2 = "abcdefg";
914   CPPUNIT_ASSERT( str1.compare(str2) < 0 );
915 
916   CPPUNIT_ASSERT( str1.compare("abcdef") == 0 );
917   CPPUNIT_ASSERT( str1.compare("abcde") > 0 );
918   CPPUNIT_ASSERT( str1.compare("abcdefg") < 0 );
919 
920   str2 = "cde";
921   CPPUNIT_ASSERT( str1.compare(2, 3, str2) == 0 );
922   str2 = "cd";
923   CPPUNIT_ASSERT( str1.compare(2, 3, str2) > 0 );
924   str2 = "cdef";
925   CPPUNIT_ASSERT( str1.compare(2, 3, str2) < 0 );
926 
927   str2 = "abcdef";
928   CPPUNIT_ASSERT( str1.compare(2, 3, str2, 2, 3) == 0 );
929   CPPUNIT_ASSERT( str1.compare(2, 3, str2, 2, 2) > 0 );
930   CPPUNIT_ASSERT( str1.compare(2, 3, str2, 2, 4) < 0 );
931 
932   CPPUNIT_ASSERT( str1.compare(2, 3, "cdefgh", 3) == 0 );
933   CPPUNIT_ASSERT( str1.compare(2, 3, "cdefgh", 2) > 0 );
934   CPPUNIT_ASSERT( str1.compare(2, 3, "cdefgh", 4) < 0 );
935 }
936 
937 /*
938 class mystring : public string {
939 public:
940   mystring() {}
941   mystring(string const& s) : string(s) {}
942 
943   mystring& operator = (string const& s) {
944     string::operator = (s);
945     return *this;
946   };
947 };
948 */
949 
template_expression()950 void StringTest::template_expression()
951 {
952   string one("one"), two("two"), three("three");
953   string space(1, ' ');
954 
955   // check availability of [un]equality operators
956   {
957       // string-string
958       one == two;
959       one != two;
960       // string-literal
961       one == "two";
962       one != "two";
963       // literal-string
964       "one" == two;
965       "one" != two;
966       // strsum-string
967       (one + two) == three;
968       (one + two) != three;
969       // string-strsum
970       one == (two + three);
971       one != (two + three);
972       // strsum-literal
973       (one + two) == "three";
974       (one + two) != "three";
975       // literal-strsum
976       "one" == (two + three);
977       "one" != (two + three);
978       // strsum-strsum
979       (one + two) == (two + three);
980       (one + two) != (two + three);
981   }
982 
983   {
984     string result(one + ' ' + two + ' ' + three);
985     CPPUNIT_CHECK( result == "one two three" );
986   }
987 
988   {
989     string result(one + ' ' + two + ' ' + three, 4);
990     CPPUNIT_CHECK( result == "two three" );
991   }
992 
993   {
994     string result(one + ' ' + two + ' ' + three, 4, 3);
995     CPPUNIT_CHECK( result == "two" );
996   }
997 
998   //2 members expressions:
999   CPPUNIT_CHECK( (' ' + one) == " one" );
1000   CPPUNIT_CHECK( (one + ' ') == "one " );
1001   CPPUNIT_CHECK( (one + " two") == "one two" );
1002   CPPUNIT_CHECK( ("one " + two) == "one two" );
1003   CPPUNIT_CHECK( (one + space) == "one " );
1004 
1005   //3 members expressions:
1006   CPPUNIT_CHECK( ((one + space) + "two") == "one two" );
1007   CPPUNIT_CHECK( ("one" + (space + two)) == "one two" );
1008   CPPUNIT_CHECK( ((one + space) + two) == "one two" );
1009   CPPUNIT_CHECK( (one + (space + two)) == "one two" );
1010   CPPUNIT_CHECK( ((one + space) + 't') == "one t" );
1011   CPPUNIT_CHECK( ('o' + (space + two)) == "o two" );
1012 
1013   //4 members expressions:
1014   CPPUNIT_CHECK( ((one + space) + (two + space)) == "one two " );
1015 
1016   //special operators
1017   {
1018     string result;
1019     result = one + space + two;
1020     CPPUNIT_CHECK( result == "one two" );
1021 
1022     result += space + three;
1023     CPPUNIT_CHECK( result == "one two three" );
1024   }
1025 
1026   //special append method
1027   {
1028     string result;
1029     //Use reserve to avoid reallocation and really test auto-referencing problems:
1030     result.reserve(64);
1031 
1032     result.append(one + space + two);
1033     CPPUNIT_CHECK( result == "one two" );
1034 
1035     result.append(space + result + space + three);
1036     CPPUNIT_CHECK( result == "one two one two three" );
1037 
1038     result = "one two";
1039     result.append(space + three, 1, 2);
1040     CPPUNIT_ASSERT( result == "one twoth" );
1041 
1042     result.append(space + result);
1043     CPPUNIT_CHECK( result == "one twoth one twoth" );
1044   }
1045 
1046   //special assign method
1047   {
1048     string result;
1049     //Use reserve to avoid reallocation and really test auto-referencing problems:
1050     result.reserve(64);
1051 
1052     result.assign(one + space + two + space + three);
1053     CPPUNIT_CHECK( result == "one two three" );
1054 
1055     result.assign(one + space + two + space + three, 3, 5);
1056     CPPUNIT_CHECK( result == " two " );
1057 
1058     result.assign(one + result + three);
1059     CPPUNIT_CHECK( result == "one two three" );
1060   }
1061 
1062   {
1063     CPPUNIT_CHECK( !(one + ' ' + two).empty() );
1064 
1065     char result = (one + ' ' + two)[3];
1066     CPPUNIT_CHECK( result == ' ' );
1067 
1068     result = (one + ' ' + two).at(3);
1069     CPPUNIT_CHECK( result == ' ' );
1070 
1071 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
1072     try {
1073       result = (one + ' ' + two).at(10);
1074       CPPUNIT_FAIL;
1075     }
1076     catch (out_of_range const&) {
1077       CPPUNIT_ASSERT( result == ' ' );
1078     }
1079     catch (...) {
1080       CPPUNIT_FAIL;
1081     }
1082 #endif
1083   }
1084 
1085   /*
1086   mystring a("ing");
1087   //gcc failed to compile following expression when template expressions are activated.
1088   //MSVC sees no problem. gcc limitation or MSVC is too cool ??
1089   mystring b = "str" + a;
1090   */
1091 }
1092 
1093 #if !defined (TE_TMP_TEST_IGNORED)
1094 class superstring
1095 {
1096   public:
superstring()1097     superstring() :
1098       s("super")
1099     {}
1100 
superstring(const string & str)1101     superstring( const string& str ) :
1102       s( str )
1103     {}
1104 
operator /(const string & str)1105   superstring operator / (const string& str )
1106     { return superstring( s + "/" + str ); }
1107 
operator /(const char * str)1108   superstring operator / (const char* str )
1109     { return superstring( s + "/" + str ); }
1110 
1111   private:
1112     string s;
1113 };
1114 #endif
1115 
te_tmp()1116 void StringTest::te_tmp()
1117 {
1118 #if !defined (TE_TMP_TEST_IGNORED)
1119   superstring s;
1120   string more( "more" );
1121   string less( "less" );
1122 
1123   superstring r = s / (more + less);
1124 #endif
1125 }
1126 
1127 class mypath
1128 {
1129   public:
mypath(const string & s)1130     mypath( const string& s ) :
1131         p( s )
1132       { }
1133 
1134     const mypath& operator / ( const string& );
str() const1135     const string& str() const
1136       { return p; }
1137 
1138   private:
1139     string p;
1140 };
1141 
operator /(const string & s)1142 const mypath& mypath::operator /( const string& s )
1143 {
1144   p += '/';
1145   p += s;
1146   return *this;
1147 }
1148 
oper_tmp()1149 void StringTest::oper_tmp()
1150 {
1151   string s1( "path1" );
1152   string s2( ".ext" );
1153 
1154   string& rs1 = s1;
1155   string& rs2 = s2;
1156 
1157   CPPUNIT_CHECK( (mypath( string( "/root" ) ) / (rs1 + rs2)).str() == "/root/path1.ext" );
1158 }
1159 
template_wexpression()1160 void StringTest::template_wexpression()
1161 {
1162 #if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
1163 #  if !defined (__CYGWIN__) || defined (STLPORT)
1164   wstring one(L"one"), two(L"two"), three(L"three");
1165   wstring space(L" ");
1166 
1167   {
1168     wstring result(one + L' ' + two + L' ' + three);
1169     CPPUNIT_CHECK( result == L"one two three" );
1170   }
1171 
1172   {
1173     wstring result(one + L' ' + two + L' ' + three, 4);
1174     CPPUNIT_CHECK( result == L"two three" );
1175   }
1176 
1177   {
1178     wstring result(one + L' ' + two + L' ' + three, 4, 3);
1179     CPPUNIT_CHECK( result == L"two" );
1180   }
1181 
1182   //2 members expressions:
1183   CPPUNIT_CHECK( (L' ' + one) == L" one" );
1184   CPPUNIT_CHECK( (one + L' ') == L"one " );
1185   CPPUNIT_CHECK( (one + L" two") == L"one two" );
1186   CPPUNIT_CHECK( (L"one " + two) == L"one two" );
1187   CPPUNIT_CHECK( (one + space) == L"one " );
1188 
1189   //3 members expressions:
1190   CPPUNIT_CHECK( ((one + space) + L"two") == L"one two" );
1191   CPPUNIT_CHECK( (L"one" + (space + two)) == L"one two" );
1192   CPPUNIT_CHECK( ((one + space) + two) == L"one two" );
1193   CPPUNIT_CHECK( (one + (space + two)) == L"one two" );
1194   CPPUNIT_CHECK( ((one + space) + L't') == L"one t" );
1195   CPPUNIT_CHECK( (L'o' + (space + two)) == L"o two" );
1196 
1197   //4 members expressions:
1198   CPPUNIT_CHECK( ((one + space) + (two + space)) == L"one two " );
1199 
1200   //special operators
1201   {
1202     wstring result;
1203     result = one + space + two;
1204     CPPUNIT_CHECK( result == L"one two" );
1205 
1206     result += space + three;
1207     CPPUNIT_CHECK( result == L"one two three" );
1208   }
1209 
1210   //special append method
1211   {
1212     wstring result;
1213     //Use reserve to avoid reallocation and really test auto-referencing problems:
1214     result.reserve(64);
1215 
1216     result.append(one + space + two);
1217     CPPUNIT_CHECK( result == L"one two" );
1218 
1219     result.append(space + result + space + three);
1220     CPPUNIT_CHECK( result == L"one two one two three" );
1221 
1222     result = L"one two";
1223     result.append(space + three, 1, 2);
1224     CPPUNIT_ASSERT( result == L"one twoth" );
1225 
1226     result.append(space + result);
1227     CPPUNIT_CHECK( result == L"one twoth one twoth" );
1228   }
1229 
1230   //special assign method
1231   {
1232     wstring result;
1233     //Use reserve to avoid reallocation and really test auto-referencing problems:
1234     result.reserve(64);
1235 
1236     result.assign(one + space + two + space + three);
1237     CPPUNIT_CHECK( result == L"one two three" );
1238 
1239     result.assign(one + space + two + space + three, 3, 5);
1240     CPPUNIT_CHECK( result == L" two " );
1241 
1242     result.assign(one + result + three);
1243     CPPUNIT_CHECK( result == L"one two three" );
1244   }
1245 
1246   {
1247     CPPUNIT_CHECK( !(one + L' ' + two).empty() );
1248 
1249     wchar_t result = (one + L' ' + two)[3];
1250     CPPUNIT_CHECK( result == L' ' );
1251 
1252     result = (one + L' ' + two).at(3);
1253     CPPUNIT_CHECK( result == L' ' );
1254 
1255 #    if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
1256     try {
1257       result = (one + L' ' + two).at(10);
1258       CPPUNIT_FAIL;
1259     }
1260     catch (out_of_range const&) {
1261       CPPUNIT_ASSERT( result == L' ' );
1262     }
1263     catch (...) {
1264       CPPUNIT_FAIL;
1265     }
1266 #    endif
1267   }
1268 #  endif
1269 #endif
1270 }
1271 
io()1272 void StringTest::io()
1273 {
1274 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
1275   string str("STLport");
1276   {
1277     ostringstream ostr;
1278     ostr << str;
1279     CPPUNIT_ASSERT( ostr.good() );
1280     CPPUNIT_ASSERT( ostr.str() == str );
1281   }
1282   {
1283     istringstream istr(str);
1284     string istr_content;
1285     istr >> istr_content;
1286     CPPUNIT_ASSERT( !istr.fail() && istr.eof() );
1287     CPPUNIT_ASSERT( istr_content == str );
1288   }
1289   {
1290     istringstream istr(str);
1291     istr.width(3);
1292     string istr_content;
1293     istr >> istr_content;
1294     CPPUNIT_ASSERT( !istr.fail() && !istr.eof() );
1295     CPPUNIT_ASSERT( istr_content == "STL" );
1296   }
1297 #endif
1298 }
1299 
allocator_with_state()1300 void StringTest::allocator_with_state()
1301 {
1302 #if !(defined (STLPORT) && defined (_STLP_NO_CUSTOM_IO))
1303 
1304   char buf1[1024];
1305   StackAllocator<char> stack1(buf1, buf1 + sizeof(buf1));
1306 
1307   char buf2[1024];
1308   StackAllocator<char> stack2(buf2, buf2 + sizeof(buf2));
1309 
1310   typedef basic_string<char, char_traits<char>, StackAllocator<char> > StackString;
1311   {
1312     StackString str1("string stack1", stack1);
1313     StackString str1Cpy(str1);
1314 
1315     StackString str2("string stack2", stack2);
1316     StackString str2Cpy(str2);
1317 
1318     str1.swap(str2);
1319 
1320     CPPUNIT_ASSERT( str1.get_allocator().swaped() );
1321     CPPUNIT_ASSERT( str2.get_allocator().swaped() );
1322 
1323     CPPUNIT_ASSERT( str1 == str2Cpy );
1324     CPPUNIT_ASSERT( str2 == str1Cpy );
1325     CPPUNIT_ASSERT( str1.get_allocator() == stack2 );
1326     CPPUNIT_ASSERT( str2.get_allocator() == stack1 );
1327   }
1328   CPPUNIT_ASSERT( stack1.ok() );
1329   CPPUNIT_ASSERT( stack2.ok() );
1330   stack1.reset(); stack2.reset();
1331 
1332   {
1333     StackString str1("longer string from stack1 allocator instance for dynamic allocation", stack1);
1334     StackString str1Cpy(str1);
1335 
1336     StackString str2("longer string from stack2 allocator instance for dynamic allocation", stack2);
1337     StackString str2Cpy(str2);
1338 
1339     str1.swap(str2);
1340 
1341     CPPUNIT_ASSERT( str1.get_allocator().swaped() );
1342     CPPUNIT_ASSERT( str2.get_allocator().swaped() );
1343 
1344     CPPUNIT_ASSERT( str1 == str2Cpy );
1345     CPPUNIT_ASSERT( str2 == str1Cpy );
1346     CPPUNIT_ASSERT( str1.get_allocator() == stack2 );
1347     CPPUNIT_ASSERT( str2.get_allocator() == stack1 );
1348   }
1349   CPPUNIT_ASSERT( stack1.ok() );
1350   CPPUNIT_ASSERT( stack2.ok() );
1351   stack1.reset(); stack2.reset();
1352 
1353 
1354   {
1355     StackString str1("string stack1", stack1);
1356     StackString str1Cpy(str1);
1357 
1358     StackString str2("longer string from stack2 allocator instance for dynamic allocation", stack2);
1359     StackString str2Cpy(str2);
1360 
1361     str1.swap(str2);
1362 
1363     CPPUNIT_ASSERT( str1.get_allocator().swaped() );
1364     CPPUNIT_ASSERT( str2.get_allocator().swaped() );
1365 
1366     CPPUNIT_ASSERT( str1 == str2Cpy );
1367     CPPUNIT_ASSERT( str2 == str1Cpy );
1368     CPPUNIT_ASSERT( str1.get_allocator() == stack2 );
1369     CPPUNIT_ASSERT( str2.get_allocator() == stack1 );
1370   }
1371   CPPUNIT_ASSERT( stack1.ok() );
1372   CPPUNIT_ASSERT( stack2.ok() );
1373   stack1.reset(); stack2.reset();
1374 
1375 
1376   {
1377     StackString str1("longer string from stack1 allocator instance for dynamic allocation", stack1);
1378     StackString str1Cpy(str1);
1379 
1380     StackString str2("string stack2", stack2);
1381     StackString str2Cpy(str2);
1382 
1383     str1.swap(str2);
1384 
1385     CPPUNIT_ASSERT( str1.get_allocator().swaped() );
1386     CPPUNIT_ASSERT( str2.get_allocator().swaped() );
1387 
1388     CPPUNIT_ASSERT( str1 == str2Cpy );
1389     CPPUNIT_ASSERT( str2 == str1Cpy );
1390     CPPUNIT_ASSERT( str1.get_allocator() == stack2 );
1391     CPPUNIT_ASSERT( str2.get_allocator() == stack1 );
1392   }
1393   CPPUNIT_ASSERT( stack1.ok() );
1394   CPPUNIT_ASSERT( stack2.ok() );
1395   stack1.reset(); stack2.reset();
1396 #endif
1397 }
1398 
capacity()1399 void StringTest::capacity()
1400 {
1401   string s;
1402 
1403   CPPUNIT_CHECK( s.capacity() > 0 );
1404   CPPUNIT_CHECK( s.capacity() < s.max_size() );
1405   CPPUNIT_CHECK( s.capacity() >= s.size() );
1406 
1407 #ifndef _STLP_SHORT_STRING_SZ
1408 #  define _STLP_SHORT_STRING_SZ 16 // see stlport/stl/_string_base.h
1409 #endif
1410 
1411   for ( int i = 0; i < _STLP_SHORT_STRING_SZ + 2; ++i ) {
1412     s += ' ';
1413     CPPUNIT_CHECK( s.capacity() > 0 );
1414     CPPUNIT_CHECK( s.capacity() < s.max_size() );
1415     CPPUNIT_CHECK( s.capacity() >= s.size() );
1416   }
1417 }
1418 
concat24()1419 void StringTest::concat24()
1420 {
1421   string s = string( "123456789012345678901234" ) + string( "123456789012345678901234" );
1422 
1423   CPPUNIT_CHECK( s.length() == 48 );
1424   CPPUNIT_CHECK( s[23] == '4' );
1425   CPPUNIT_CHECK( s[24] == '1' );
1426   CPPUNIT_CHECK( s[47] == '4' );
1427 }
1428