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
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"
14 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
18 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
22 #if !defined (STLPORT) || defined (_STLP_THREADS)
23 # if defined (STLPORT) && defined (_STLP_PTHREADS) || \
24 defined (__GNUC__) && !defined (__MINGW32__)
25 # define USE_PTHREAD_API
29 # if defined (STLPORT) && defined (_STLP_WIN32THREADS) || \
30 defined (__GNUC__) && defined (__MINGW32__) || \
32 # define USE_WINDOWS_API
37 #include "stack_allocator.h"
38 #include "cppunit/cppunit_proxy.h"
40 #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
47 class StringTest
: public CPPUNIT_NS::TestCase
49 CPPUNIT_TEST_SUITE(StringTest
);
50 CPPUNIT_TEST(constructor
);
51 CPPUNIT_TEST(trivial_char_compare
);
52 CPPUNIT_TEST(reserve
);
57 CPPUNIT_TEST(null_char
);
59 CPPUNIT_TEST(replace
);
61 CPPUNIT_TEST(short_string
);
63 CPPUNIT_TEST(bogus_edge_find
);
65 CPPUNIT_TEST(find_last_of
);
66 CPPUNIT_TEST(find_last_not_of
);
68 #if !defined (USE_PTHREAD_API) && !defined (USE_WINDOWS_API)
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
83 #if defined (TE_TMP_TEST_IGNORED)
86 CPPUNIT_TEST(oper_tmp
);
87 #if defined (STLPORT) && defined (_STLP_NO_WCHAR_T)
90 #if defined (__CYGWIN__) && !defined (STLPORT)
93 CPPUNIT_TEST(template_wexpression
);
95 #if defined (STLPORT) && defined (_STLP_USE_NO_IOSTREAMS)
100 #if defined (STLPORT) && defined (_STLP_NO_CUSTOM_IO)
103 CPPUNIT_TEST(allocator_with_state
);
105 CPPUNIT_TEST(capacity
);
106 CPPUNIT_TEST(concat24
);
107 CPPUNIT_TEST_SUITE_END();
111 void trivial_char_compare();
122 void bogus_edge_find();
125 void find_last_not_of();
129 void short_string_optim_bug();
131 void template_expression();
134 void template_wexpression();
136 void allocator_with_state();
140 static string
func(const string
& par
) {
145 #if defined (USE_PTHREAD_API) || defined (USE_WINDOWS_API)
146 # if defined (USE_PTHREAD_API)
147 static void* f(void*)
149 static DWORD __stdcall
f(void*)
152 string
s( "qyweyuewunfkHBUKGYUGL,wehbYGUW^(@T@H!BALWD:h^&@#*@(#:JKHWJ:CND" );
154 for ( int i
= 0; i
< 2000000; ++i
) {
155 string sx
= func( s
);
164 CPPUNIT_TEST_SUITE_REGISTRATION(StringTest
);
167 // tests implementation
169 void StringTest::constructor()
171 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
173 string
s((size_t)-1, 'a');
176 catch (length_error
const&) {
179 //Expected exception is length_error:
185 void StringTest::trivial_char_compare()
187 string
s( "message" );
189 CPPUNIT_CHECK( s
== "message" );
190 CPPUNIT_CHECK( "message" == s
);
193 void StringTest::reserve()
196 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
198 s
.reserve(s
.max_size() + 1);
201 catch (length_error
const&) {
204 //Expected exception is length_error:
210 void StringTest::mt()
212 #if defined (USE_PTHREAD_API) || defined (USE_WINDOWS_API)
214 # if defined (USE_PTHREAD_API)
217 for ( int i
= 0; i
< nth
; ++i
) {
218 pthread_create( &t
[i
], 0, f
, 0 );
221 for ( int i
= 0; i
< nth
; ++i
) {
222 pthread_join( t
[i
], 0 );
226 # if defined (USE_WINDOWS_API)
227 //DWORD start = GetTickCount();
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
);
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
);
245 DWORD duration = GetTickCount() - start;
247 ostr << "Duration: " << duration << endl;
248 CPPUNIT_MESSAGE(ostr.str().c_str());
254 void StringTest::short_string()
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
);
262 CPPUNIT_ASSERT(short_str1
== ref_short_str1
);
263 CPPUNIT_ASSERT(long_str1
== ref_long_str1
);
266 string
str1(short_str1
);
268 CPPUNIT_ASSERT(str1
== ref_long_str1
);
272 string
str1(long_str1
);
274 CPPUNIT_ASSERT(str1
== ref_short_str1
);
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
);
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
);
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
);
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
);
304 const char* as
= a
.c_str();
305 const char* bs
= b
.c_str();
307 CPPUNIT_ASSERT( a
.c_str() == bs
);
308 CPPUNIT_ASSERT( b
.c_str() == as
);
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
));
325 void StringTest::erase()
327 char const* c_str
= "Hello, World!";
329 CPPUNIT_ASSERT( str
== c_str
);
331 str
.erase(str
.begin() + 1, str
.end() - 1); // Erase all but first and last.
334 for (i
= 0; i
< str
.size(); ++i
) {
337 CPPUNIT_ASSERT( str
[i
] == 'H' );
340 CPPUNIT_ASSERT( str
[i
] == '!' );
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() );
355 CPPUNIT_ASSERT( str
== c_str
);
357 str
.erase(1, str
.size() - 1); // Erase all but first and last.
358 for (i
= 0; i
< str
.size(); i
++) {
361 CPPUNIT_ASSERT( str
[i
] == 'H' );
364 CPPUNIT_ASSERT( str
[i
] == '!' );
372 CPPUNIT_ASSERT( str
== "H" );
375 void StringTest::data()
379 CPPUNIT_ASSERT( xx
.data() != 0 ); // ISO-IEC-14882:1998(E), 21.3.6, paragraph 3
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.
389 string
low( "2004-01-01" );
390 // Blocks A and B should follow each other.
394 if ( strcmp( xx
.data(), "1234562004-01-01" ) != 0 ) {
403 if ( strcmp( xx
.data(), "1234;" ) != 0 ) {
410 void StringTest::c_str()
412 string
low( "2004-01-01" );
416 CPPUNIT_ASSERT( *(yy
.c_str()) == '\0' ); // ISO-IEC-14882:1998(E), 21.3.6, paragraph 1
418 // Blocks A and B should follow each other.
422 CPPUNIT_ASSERT( strcmp( xx
.c_str(), "1234562004-01-01" ) == 0 );
428 CPPUNIT_ASSERT( strcmp( xx
.c_str(), "1234;" ) == 0 );
432 void StringTest::null_char()
434 // ISO/IEC 14882:1998(E), ISO/IEC 14882:2003(E), 21.3.4 ('... the const version')
435 const string
s( "123456" );
437 CPPUNIT_CHECK( s
[s
.size()] == '\0' );
439 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
441 //Check is only here to avoid warning about value of expression not used
442 CPPUNIT_CHECK( s
.at(s
.size()) == '\0' );
445 catch (out_of_range
const&) {
446 CPPUNIT_ASSERT( true );
454 void StringTest::insert()
456 string strorg
= "This is test string for string calls";
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
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" );
471 str
.insert(15, str
.c_str() + 5, 25);
472 CPPUNIT_ASSERT( str
== "This is test stis test string for stringring for string calls" );
475 str
.insert(0, str
.c_str() + str
.size() - 4, 4);
476 CPPUNIT_ASSERT( str
== "allsThis is test string for string calls" );
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" );
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" );
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" );
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());
500 str0
.insert(str0
.begin(), 5, '0');
501 CPPUNIT_ASSERT( str0
== "00000" );
505 string::size_type pos
= 0, nb
= 2;
506 str1
.insert(pos
, nb
, '1');
508 CPPUNIT_ASSERT( str1
== "11" );
510 str0
.insert(0, str1
);
511 CPPUNIT_ASSERT( str0
== "1100000" );
514 str0
.insert(str0
.size(), str2
, 1, 2);
515 CPPUNIT_ASSERT( str0
== "110000034" );
517 str1
.insert(str1
.begin() + 1, 2, '2');
518 CPPUNIT_ASSERT( str1
== "1221" );
520 str1
.insert(2, "333333", 3);
521 CPPUNIT_ASSERT( str1
== "1233321" );
523 str1
.insert(4, "4444");
524 CPPUNIT_ASSERT( str1
== "12334444321" );
526 str1
.insert(str1
.begin() + 6, '5');
527 CPPUNIT_ASSERT( str1
== "123344544321" );
530 void StringTest::replace()
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.
537 const string
v( "78" );
538 string
s( "123456" );
539 string
const& cs
= s
;
541 string::iterator i
= s
.begin() + 1;
542 s
.replace(i
, i
+ 3, v
.begin(), v
.end());
543 CPPUNIT_ASSERT( s
== "17856" );
547 s
.replace(i
, i
+ 1, v
.begin(), v
.end());
548 CPPUNIT_ASSERT( s
== "1783456" );
552 string::const_iterator ci
= s
.begin() + 1;
553 s
.replace(i
, i
+ 3, ci
+ 3, cs
.end());
554 CPPUNIT_ASSERT( s
== "15656" );
559 s
.replace(i
, i
+ 3, ci
, ci
+ 2);
560 CPPUNIT_ASSERT( s
== "12356" );
565 s
.replace(i
, i
+ 3, ci
+ 1, cs
.end());
566 CPPUNIT_ASSERT( s
== "1345656" );
571 s
.replace(i
, i
, ci
, ci
+ 1);
572 CPPUNIT_CHECK( s
== "2123456" );
575 s
.replace(s
.begin() + 4, s
.end(), cs
.begin(), cs
.end());
576 CPPUNIT_ASSERT( s
== "1234123456" );
579 * This is the test for the template replace method.
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" );
590 s
.replace(s
.begin() + 4, s
.end(), s
.begin(), s
.end());
591 CPPUNIT_ASSERT( s
== "1234123456" );
593 string
strorg("This is test string for string calls");
595 str
.replace(5, 15, str
.c_str(), 10);
596 CPPUNIT_ASSERT( str
== "This This is tefor string calls" );
599 str
.replace(5, 5, str
.c_str(), 10);
600 CPPUNIT_ASSERT( str
== "This This is test string for string calls" );
602 #if (defined (STLPORT) && defined(_STLP_MEMBER_TEMPLATES)) || ( !defined (STLPORT) && !defined(__GNUC__) )
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" );
610 void StringTest::resize()
616 CPPUNIT_ASSERT( *s
.c_str() == 0 );
621 CPPUNIT_ASSERT( *s
.c_str() == 0 );
625 CPPUNIT_ASSERT( s
.size() == 1 );
626 CPPUNIT_ASSERT( *s
.c_str() == '1' );
627 CPPUNIT_ASSERT( *(s
.c_str() + 1) == 0 );
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 );
638 void StringTest::find()
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
;
650 # define npos_local string::npos
652 CPPUNIT_ASSERT( s
.find("four") == npos_local
);
653 CPPUNIT_ASSERT( s
.find("one", string::npos
) == npos_local
);
655 CPPUNIT_ASSERT( s
.find_first_of("abcde") == 2 );
657 CPPUNIT_ASSERT( s
.find_first_not_of("enotw ") == 9 );
660 CPPUNIT_ASSERT( s
.substr(s
.find(empty
), empty
.size()) == empty
);
663 void StringTest::bogus_edge_find()
665 /* ISO/IEC 14882 2003, 21.3.6.1 basic_string::find [lib.string::find]
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,
675 * Notes: Uses traits::eq().
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:
684 * string::size_type p = s.find( "", 0, 0 );
688 * if ( p != string::npos ) { // normal
689 * char ch = s[p]; // Arghhhhhhhhhh
692 * People near Standard commete has opinion opposite to my. Even if it looks
693 * like bogus behaviour for me, it should be fixed.
698 string::size_type p
= s
.find( "", 0, 0 );
700 /* CPPUNIT_CHECK( p == string::npos ); */
701 CPPUNIT_CHECK( p
== 0 ); // bogus result, isn't it?
705 string::size_type p
= s
.find( "", 0, 0 );
707 CPPUNIT_CHECK( p
== 0 );
711 string::size_type p
= s
.find( "", 1, 0 );
713 CPPUNIT_CHECK( p
== 1 );
717 string::size_type p
= s
.find( "", 1, 0 );
719 CPPUNIT_CHECK( p
== string::npos
);
723 string::size_type p
= s
.find( "", 3, 0 );
725 CPPUNIT_CHECK( p
== 3 ); // bogus result, isn't it?
729 string::size_type p
= s
.rfind( "", 0, 0 );
731 /* CPPUNIT_CHECK( p == string::npos ); */
732 CPPUNIT_CHECK( p
== 0 ); // bogus result, isn't it?
736 string::size_type p
= s
.rfind( "", 0, 0 );
738 CPPUNIT_CHECK( p
== 0 );
742 string::size_type p
= s
.rfind( "", 1, 0 );
744 CPPUNIT_CHECK( p
== 1 );
748 string::size_type p
= s
.rfind( "", 1, 0 );
750 CPPUNIT_CHECK( p
== 0 ); // bogus result, isn't it?
754 string::size_type p
= s
.rfind( "", 3, 0 );
756 CPPUNIT_CHECK( p
== 3 ); // bogus result, isn't it?
760 void StringTest::rfind()
763 string
s("one two three one two three");
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 );
770 string
test( "aba" );
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 );
776 CPPUNIT_CHECK( test
.rfind( 'a', 2 ) == 2 );
777 CPPUNIT_CHECK( test
.rfind( 'a', 1 ) == 0 );
778 CPPUNIT_CHECK( test
.rfind( 'a', 0 ) == 0 );
781 void StringTest::find_last_of()
784 string
s("one two three one two three");
786 CPPUNIT_ASSERT( s
.find_last_of("abcde") == 26 );
788 string
test( "aba" );
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 );
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 );
799 void StringTest::find_last_not_of()
802 string
s("one two three one two three");
804 CPPUNIT_ASSERT( s
.find_last_not_of("ehortw ") == 15 );
806 string
test( "aba" );
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 );
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 );
823 void StringTest::copy()
827 dest
[0] = dest
[1] = dest
[2] = dest
[3] = 1;
830 CPPUNIT_ASSERT( dest
[pos
++] == 'f' );
831 CPPUNIT_ASSERT( dest
[pos
++] == 'o' );
832 CPPUNIT_ASSERT( dest
[pos
++] == 'o' );
833 CPPUNIT_ASSERT( dest
[pos
++] == 1 );
835 dest
[0] = dest
[1] = dest
[2] = dest
[3] = 1;
838 CPPUNIT_ASSERT( dest
[pos
++] == 'o' );
839 CPPUNIT_ASSERT( dest
[pos
++] == 1 );
841 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
846 catch (out_of_range
const&) {
854 void StringTest::assign()
857 char const* cstr
= "test string for assign";
859 s
.assign(cstr
, cstr
+ 22);
860 CPPUNIT_ASSERT( s
== "test string for assign" );
862 string
s2("other test string");
864 CPPUNIT_ASSERT( s
== s2
);
869 // short string optim:
871 // longer than short string:
872 str2
= "1234567890123456789012345678901234567890";
874 CPPUNIT_ASSERT(str1
[5] == '6');
875 CPPUNIT_ASSERT(str2
[29] == '0');
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.)
889 void StringTest::short_string_optim_bug()
891 string
teststr("shortest");
893 bool short_string_optim_bug_helper(string teststr
);
895 CPPUNIT_ASSERT(true == short_string_optim_bug_helper(teststr
));
898 bool short_string_optim_bug_helper(string teststr
)
900 size_t ss
= teststr
.size();
904 void StringTest::compare()
906 string
str1("abcdef");
910 CPPUNIT_ASSERT( str1
.compare(str2
) == 0 );
912 CPPUNIT_ASSERT( str1
.compare(str2
) > 0 );
914 CPPUNIT_ASSERT( str1
.compare(str2
) < 0 );
916 CPPUNIT_ASSERT( str1
.compare("abcdef") == 0 );
917 CPPUNIT_ASSERT( str1
.compare("abcde") > 0 );
918 CPPUNIT_ASSERT( str1
.compare("abcdefg") < 0 );
921 CPPUNIT_ASSERT( str1
.compare(2, 3, str2
) == 0 );
923 CPPUNIT_ASSERT( str1
.compare(2, 3, str2
) > 0 );
925 CPPUNIT_ASSERT( str1
.compare(2, 3, str2
) < 0 );
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 );
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 );
938 class mystring : public string {
941 mystring(string const& s) : string(s) {}
943 mystring& operator = (string const& s) {
944 string::operator = (s);
950 void StringTest::template_expression()
952 string
one("one"), two("two"), three("three");
953 string
space(1, ' ');
955 // check availability of [un]equality operators
967 (one
+ two
) == three
;
968 (one
+ two
) != three
;
970 one
== (two
+ three
);
971 one
!= (two
+ three
);
973 (one
+ two
) == "three";
974 (one
+ two
) != "three";
976 "one" == (two
+ three
);
977 "one" != (two
+ three
);
979 (one
+ two
) == (two
+ three
);
980 (one
+ two
) != (two
+ three
);
984 string
result(one
+ ' ' + two
+ ' ' + three
);
985 CPPUNIT_CHECK( result
== "one two three" );
989 string
result(one
+ ' ' + two
+ ' ' + three
, 4);
990 CPPUNIT_CHECK( result
== "two three" );
994 string
result(one
+ ' ' + two
+ ' ' + three
, 4, 3);
995 CPPUNIT_CHECK( result
== "two" );
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 " );
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" );
1013 //4 members expressions:
1014 CPPUNIT_CHECK( ((one
+ space
) + (two
+ space
)) == "one two " );
1019 result
= one
+ space
+ two
;
1020 CPPUNIT_CHECK( result
== "one two" );
1022 result
+= space
+ three
;
1023 CPPUNIT_CHECK( result
== "one two three" );
1026 //special append method
1029 //Use reserve to avoid reallocation and really test auto-referencing problems:
1032 result
.append(one
+ space
+ two
);
1033 CPPUNIT_CHECK( result
== "one two" );
1035 result
.append(space
+ result
+ space
+ three
);
1036 CPPUNIT_CHECK( result
== "one two one two three" );
1039 result
.append(space
+ three
, 1, 2);
1040 CPPUNIT_ASSERT( result
== "one twoth" );
1042 result
.append(space
+ result
);
1043 CPPUNIT_CHECK( result
== "one twoth one twoth" );
1046 //special assign method
1049 //Use reserve to avoid reallocation and really test auto-referencing problems:
1052 result
.assign(one
+ space
+ two
+ space
+ three
);
1053 CPPUNIT_CHECK( result
== "one two three" );
1055 result
.assign(one
+ space
+ two
+ space
+ three
, 3, 5);
1056 CPPUNIT_CHECK( result
== " two " );
1058 result
.assign(one
+ result
+ three
);
1059 CPPUNIT_CHECK( result
== "one two three" );
1063 CPPUNIT_CHECK( !(one
+ ' ' + two
).empty() );
1065 char result
= (one
+ ' ' + two
)[3];
1066 CPPUNIT_CHECK( result
== ' ' );
1068 result
= (one
+ ' ' + two
).at(3);
1069 CPPUNIT_CHECK( result
== ' ' );
1071 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
1073 result
= (one
+ ' ' + two
).at(10);
1076 catch (out_of_range
const&) {
1077 CPPUNIT_ASSERT( result
== ' ' );
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;
1093 #if !defined (TE_TMP_TEST_IGNORED)
1101 superstring( const string
& str
) :
1105 superstring
operator / (const string
& str
)
1106 { return superstring( s
+ "/" + str
); }
1108 superstring
operator / (const char* str
)
1109 { return superstring( s
+ "/" + str
); }
1116 void StringTest::te_tmp()
1118 #if !defined (TE_TMP_TEST_IGNORED)
1120 string
more( "more" );
1121 string
less( "less" );
1123 superstring r
= s
/ (more
+ less
);
1130 mypath( const string
& s
) :
1134 const mypath
& operator / ( const string
& );
1135 const string
& str() const
1142 const mypath
& mypath::operator /( const string
& s
)
1149 void StringTest::oper_tmp()
1151 string
s1( "path1" );
1152 string
s2( ".ext" );
1157 CPPUNIT_CHECK( (mypath( string( "/root" ) ) / (rs1
+ rs2
)).str() == "/root/path1.ext" );
1160 void StringTest::template_wexpression()
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
" ");
1168 wstring
result(one
+ L
' ' + two
+ L
' ' + three
);
1169 CPPUNIT_CHECK( result
== L
"one two three" );
1173 wstring
result(one
+ L
' ' + two
+ L
' ' + three
, 4);
1174 CPPUNIT_CHECK( result
== L
"two three" );
1178 wstring
result(one
+ L
' ' + two
+ L
' ' + three
, 4, 3);
1179 CPPUNIT_CHECK( result
== L
"two" );
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 " );
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" );
1197 //4 members expressions:
1198 CPPUNIT_CHECK( ((one
+ space
) + (two
+ space
)) == L
"one two " );
1203 result
= one
+ space
+ two
;
1204 CPPUNIT_CHECK( result
== L
"one two" );
1206 result
+= space
+ three
;
1207 CPPUNIT_CHECK( result
== L
"one two three" );
1210 //special append method
1213 //Use reserve to avoid reallocation and really test auto-referencing problems:
1216 result
.append(one
+ space
+ two
);
1217 CPPUNIT_CHECK( result
== L
"one two" );
1219 result
.append(space
+ result
+ space
+ three
);
1220 CPPUNIT_CHECK( result
== L
"one two one two three" );
1222 result
= L
"one two";
1223 result
.append(space
+ three
, 1, 2);
1224 CPPUNIT_ASSERT( result
== L
"one twoth" );
1226 result
.append(space
+ result
);
1227 CPPUNIT_CHECK( result
== L
"one twoth one twoth" );
1230 //special assign method
1233 //Use reserve to avoid reallocation and really test auto-referencing problems:
1236 result
.assign(one
+ space
+ two
+ space
+ three
);
1237 CPPUNIT_CHECK( result
== L
"one two three" );
1239 result
.assign(one
+ space
+ two
+ space
+ three
, 3, 5);
1240 CPPUNIT_CHECK( result
== L
" two " );
1242 result
.assign(one
+ result
+ three
);
1243 CPPUNIT_CHECK( result
== L
"one two three" );
1247 CPPUNIT_CHECK( !(one
+ L
' ' + two
).empty() );
1249 wchar_t result
= (one
+ L
' ' + two
)[3];
1250 CPPUNIT_CHECK( result
== L
' ' );
1252 result
= (one
+ L
' ' + two
).at(3);
1253 CPPUNIT_CHECK( result
== L
' ' );
1255 # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
1257 result
= (one
+ L
' ' + two
).at(10);
1260 catch (out_of_range
const&) {
1261 CPPUNIT_ASSERT( result
== L
' ' );
1272 void StringTest::io()
1274 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
1275 string
str("STLport");
1279 CPPUNIT_ASSERT( ostr
.good() );
1280 CPPUNIT_ASSERT( ostr
.str() == str
);
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
);
1290 istringstream
istr(str
);
1292 string istr_content
;
1293 istr
>> istr_content
;
1294 CPPUNIT_ASSERT( !istr
.fail() && !istr
.eof() );
1295 CPPUNIT_ASSERT( istr_content
== "STL" );
1300 void StringTest::allocator_with_state()
1302 #if !(defined (STLPORT) && defined (_STLP_NO_CUSTOM_IO))
1305 StackAllocator
<char> stack1(buf1
, buf1
+ sizeof(buf1
));
1308 StackAllocator
<char> stack2(buf2
, buf2
+ sizeof(buf2
));
1310 typedef basic_string
<char, char_traits
<char>, StackAllocator
<char> > StackString
;
1312 StackString
str1("string stack1", stack1
);
1313 StackString
str1Cpy(str1
);
1315 StackString
str2("string stack2", stack2
);
1316 StackString
str2Cpy(str2
);
1320 CPPUNIT_ASSERT( str1
.get_allocator().swaped() );
1321 CPPUNIT_ASSERT( str2
.get_allocator().swaped() );
1323 CPPUNIT_ASSERT( str1
== str2Cpy
);
1324 CPPUNIT_ASSERT( str2
== str1Cpy
);
1325 CPPUNIT_ASSERT( str1
.get_allocator() == stack2
);
1326 CPPUNIT_ASSERT( str2
.get_allocator() == stack1
);
1328 CPPUNIT_ASSERT( stack1
.ok() );
1329 CPPUNIT_ASSERT( stack2
.ok() );
1330 stack1
.reset(); stack2
.reset();
1333 StackString
str1("longer string from stack1 allocator instance for dynamic allocation", stack1
);
1334 StackString
str1Cpy(str1
);
1336 StackString
str2("longer string from stack2 allocator instance for dynamic allocation", stack2
);
1337 StackString
str2Cpy(str2
);
1341 CPPUNIT_ASSERT( str1
.get_allocator().swaped() );
1342 CPPUNIT_ASSERT( str2
.get_allocator().swaped() );
1344 CPPUNIT_ASSERT( str1
== str2Cpy
);
1345 CPPUNIT_ASSERT( str2
== str1Cpy
);
1346 CPPUNIT_ASSERT( str1
.get_allocator() == stack2
);
1347 CPPUNIT_ASSERT( str2
.get_allocator() == stack1
);
1349 CPPUNIT_ASSERT( stack1
.ok() );
1350 CPPUNIT_ASSERT( stack2
.ok() );
1351 stack1
.reset(); stack2
.reset();
1355 StackString
str1("string stack1", stack1
);
1356 StackString
str1Cpy(str1
);
1358 StackString
str2("longer string from stack2 allocator instance for dynamic allocation", stack2
);
1359 StackString
str2Cpy(str2
);
1363 CPPUNIT_ASSERT( str1
.get_allocator().swaped() );
1364 CPPUNIT_ASSERT( str2
.get_allocator().swaped() );
1366 CPPUNIT_ASSERT( str1
== str2Cpy
);
1367 CPPUNIT_ASSERT( str2
== str1Cpy
);
1368 CPPUNIT_ASSERT( str1
.get_allocator() == stack2
);
1369 CPPUNIT_ASSERT( str2
.get_allocator() == stack1
);
1371 CPPUNIT_ASSERT( stack1
.ok() );
1372 CPPUNIT_ASSERT( stack2
.ok() );
1373 stack1
.reset(); stack2
.reset();
1377 StackString
str1("longer string from stack1 allocator instance for dynamic allocation", stack1
);
1378 StackString
str1Cpy(str1
);
1380 StackString
str2("string stack2", stack2
);
1381 StackString
str2Cpy(str2
);
1385 CPPUNIT_ASSERT( str1
.get_allocator().swaped() );
1386 CPPUNIT_ASSERT( str2
.get_allocator().swaped() );
1388 CPPUNIT_ASSERT( str1
== str2Cpy
);
1389 CPPUNIT_ASSERT( str2
== str1Cpy
);
1390 CPPUNIT_ASSERT( str1
.get_allocator() == stack2
);
1391 CPPUNIT_ASSERT( str2
.get_allocator() == stack1
);
1393 CPPUNIT_ASSERT( stack1
.ok() );
1394 CPPUNIT_ASSERT( stack2
.ok() );
1395 stack1
.reset(); stack2
.reset();
1399 void StringTest::capacity()
1403 CPPUNIT_CHECK( s
.capacity() > 0 );
1404 CPPUNIT_CHECK( s
.capacity() < s
.max_size() );
1405 CPPUNIT_CHECK( s
.capacity() >= s
.size() );
1407 #ifndef _STLP_SHORT_STRING_SZ
1408 # define _STLP_SHORT_STRING_SZ 16 // see stlport/stl/_string_base.h
1411 for ( int i
= 0; i
< _STLP_SHORT_STRING_SZ
+ 2; ++i
) {
1413 CPPUNIT_CHECK( s
.capacity() > 0 );
1414 CPPUNIT_CHECK( s
.capacity() < s
.max_size() );
1415 CPPUNIT_CHECK( s
.capacity() >= s
.size() );
1419 void StringTest::concat24()
1421 string s
= string( "123456789012345678901234" ) + string( "123456789012345678901234" );
1423 CPPUNIT_CHECK( s
.length() == 48 );
1424 CPPUNIT_CHECK( s
[23] == '4' );
1425 CPPUNIT_CHECK( s
[24] == '1' );
1426 CPPUNIT_CHECK( s
[47] == '4' );