Home | History | Annotate | Download | only in unit
      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 
    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)
    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 //
    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 
    185 void StringTest::trivial_char_compare()
    186 {
    187   string s( "message" );
    188 
    189   CPPUNIT_CHECK( s == "message" );
    190   CPPUNIT_CHECK( "message" == s );
    191 }
    192 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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 
    898 bool short_string_optim_bug_helper(string teststr)
    899 {
    900    size_t ss = teststr.size();
    901    return (ss == 8);
    902 }
    903 
    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 
    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:
   1097     superstring() :
   1098       s("super")
   1099     {}
   1100 
   1101     superstring( const string& str ) :
   1102       s( str )
   1103     {}
   1104 
   1105   superstring operator / (const string& str )
   1106     { return superstring( s + "/" + str ); }
   1107 
   1108   superstring operator / (const char* str )
   1109     { return superstring( s + "/" + str ); }
   1110 
   1111   private:
   1112     string s;
   1113 };
   1114 #endif
   1115 
   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:
   1130     mypath( const string& s ) :
   1131         p( s )
   1132       { }
   1133 
   1134     const mypath& operator / ( const string& );
   1135     const string& str() const
   1136       { return p; }
   1137 
   1138   private:
   1139     string p;
   1140 };
   1141 
   1142 const mypath& mypath::operator /( const string& s )
   1143 {
   1144   p += '/';
   1145   p += s;
   1146   return *this;
   1147 }
   1148 
   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 
   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 
   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 
   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 
   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 
   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