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