1 /********************************************************************
3 * Copyright (c) 1997-2004, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
8 #include "unicode/unistr.h"
9 #include "unicode/uchar.h"
10 #include "unicode/ustring.h"
11 #include "unicode/locid.h"
12 #include "unicode/ucnv.h"
16 #include "unicode/ustream.h"
18 #if U_IOSTREAM_SOURCE >= 199711
21 #elif U_IOSTREAM_SOURCE >= 198506
27 #define LENGTHOF(array) (int32_t)((sizeof(array)/sizeof((array)[0])))
29 UnicodeStringTest::~UnicodeStringTest() {}
31 void UnicodeStringTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char *par
)
33 if (exec
) logln("TestSuite UnicodeStringTest: ");
36 name
= "StringCaseTest";
38 logln("StringCaseTest---"); logln("");
43 case 1: name
= "TestBasicManipulation"; if (exec
) TestBasicManipulation(); break;
44 case 2: name
= "TestCompare"; if (exec
) TestCompare(); break;
45 case 3: name
= "TestExtract"; if (exec
) TestExtract(); break;
46 case 4: name
= "TestRemoveReplace"; if (exec
) TestRemoveReplace(); break;
47 case 5: name
= "TestSearching"; if (exec
) TestSearching(); break;
48 case 6: name
= "TestSpacePadding"; if (exec
) TestSpacePadding(); break;
49 case 7: name
= "TestPrefixAndSuffix"; if (exec
) TestPrefixAndSuffix(); break;
50 case 8: name
= "TestFindAndReplace"; if (exec
) TestFindAndReplace(); break;
51 case 9: name
= "TestBogus"; if (exec
) TestBogus(); break;
52 case 10: name
= "TestReverse"; if (exec
) TestReverse(); break;
53 case 11: name
= "TestMiscellaneous"; if (exec
) TestMiscellaneous(); break;
54 case 12: name
= "TestStackAllocation"; if (exec
) TestStackAllocation(); break;
55 case 13: name
= "TestUnescape"; if (exec
) TestUnescape(); break;
56 case 14: name
= "TestCountChar32"; if (exec
) TestCountChar32(); break;
57 case 15: name
= "TestStringEnumeration"; if (exec
) TestStringEnumeration(); break;
59 default: name
= ""; break; //needed to end loop
64 UnicodeStringTest::TestBasicManipulation()
66 UnicodeString
test1("Now is the time for all men to come swiftly to the aid of the party.\n");
67 UnicodeString expectedValue
;
70 c
=(UnicodeString
*)test1
.clone();
71 test1
.insert(24, "good ");
72 expectedValue
= "Now is the time for all good men to come swiftly to the aid of the party.\n";
73 if (test1
!= expectedValue
)
74 errln("insert() failed: expected \"" + expectedValue
+ "\"\n,got \"" + test1
+ "\"");
76 c
->insert(24, "good ");
77 if(*c
!= expectedValue
) {
78 errln("clone()->insert() failed: expected \"" + expectedValue
+ "\"\n,got \"" + *c
+ "\"");
83 expectedValue
= "Now is the time for all good men to come to the aid of the party.\n";
84 if (test1
!= expectedValue
)
85 errln("remove() failed: expected \"" + expectedValue
+ "\"\n,got \"" + test1
+ "\"");
87 test1
.replace(58, 6, "ir country");
88 expectedValue
= "Now is the time for all good men to come to the aid of their country.\n";
89 if (test1
!= expectedValue
)
90 errln("replace() failed: expected \"" + expectedValue
+ "\"\n,got \"" + test1
+ "\"");
93 test1
.extract(0, 15, temp
);
95 UnicodeString
test2(temp
, 15);
97 expectedValue
= "Now is the time";
98 if (test2
!= expectedValue
)
99 errln("extract() failed: expected \"" + expectedValue
+ "\"\n,got \"" + test2
+ "\"");
101 test2
+= " for me to go!\n";
102 expectedValue
= "Now is the time for me to go!\n";
103 if (test2
!= expectedValue
)
104 errln("operator+=() failed: expected \"" + expectedValue
+ "\"\n,got \"" + test2
+ "\"");
106 if (test1
.length() != 70)
107 errln("length() failed: expected 70, got " + test1
.length());
108 if (test2
.length() != 30)
109 errln("length() failed: expected 30, got " + test2
.length());
112 test3
.append((UChar32
)0x20402);
113 if(test3
!= CharsToUnicodeString("\\uD841\\uDC02")){
114 errln((UnicodeString
)"append failed for UChar32, expected \"\\\\ud841\\\\udc02\", got " + prettify(test3
));
116 if(test3
.length() != 2){
117 errln("append or length failed for UChar32, expected 2, got " + test3
.length());
119 test3
.append((UChar32
)0x0074);
120 if(test3
!= CharsToUnicodeString("\\uD841\\uDC02t")){
121 errln((UnicodeString
)"append failed for UChar32, expected \"\\\\uD841\\\\uDC02t\", got " + prettify(test3
));
123 if(test3
.length() != 3){
124 errln((UnicodeString
)"append or length failed for UChar32, expected 2, got " + test3
.length());
127 // test some UChar32 overloads
128 if( test3
.setTo((UChar32
)0x10330).length() != 2 ||
129 test3
.insert(0, (UChar32
)0x20100).length() != 4 ||
130 test3
.replace(2, 2, (UChar32
)0xe0061).length() != 4 ||
131 (test3
= (UChar32
)0x14001).length() != 2
133 errln((UnicodeString
)"simple UChar32 overloads for replace, insert, setTo or = failed");
137 // test moveIndex32()
138 UnicodeString s
=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape();
141 s
.moveIndex32(2, -1)!=0 ||
142 s
.moveIndex32(2, 1)!=4 ||
143 s
.moveIndex32(2, 2)!=5 ||
144 s
.moveIndex32(5, -2)!=2 ||
145 s
.moveIndex32(0, -1)!=0 ||
146 s
.moveIndex32(6, 1)!=6
148 errln("UnicodeString::moveIndex32() failed");
151 if(s
.getChar32Start(1)!=0 || s
.getChar32Start(2)!=2) {
152 errln("UnicodeString::getChar32Start() failed");
155 if(s
.getChar32Limit(1)!=2 || s
.getChar32Limit(2)!=2) {
156 errln("UnicodeString::getChar32Limit() failed");
161 // test new 2.2 constructors and setTo function that parallel Java's substring function.
162 UnicodeString
src("Hello folks how are you?");
163 UnicodeString
target1("how are you?");
164 if (target1
!= UnicodeString(src
, 12)) {
165 errln("UnicodeString(const UnicodeString&, int32_t) failed");
167 UnicodeString
target2("folks");
168 if (target2
!= UnicodeString(src
, 6, 5)) {
169 errln("UnicodeString(const UnicodeString&, int32_t, int32_t) failed");
171 if (target1
!= target2
.setTo(src
, 12)) {
172 errln("UnicodeString::setTo(const UnicodeString&, int32_t) failed");
177 // op+ is new in ICU 2.8
178 UnicodeString s
=UnicodeString("abc", "")+UnicodeString("def", "")+UnicodeString("ghi", "");
179 if(s
!=UnicodeString("abcdefghi", "")) {
180 errln("operator+(UniStr, UniStr) failed");
185 // tests for Jitterbug 2360
186 // verify that APIs with source pointer + length accept length == -1
187 // mostly test only where modified, only few functions did not already do this
188 if(UnicodeString("abc", -1, "")!=UnicodeString("abc", "")) {
189 errln("UnicodeString(codepageData, dataLength, codepage) does not work with dataLength==-1");
192 UChar buffer
[10]={ 0x61, 0x62, 0x20ac, 0xd900, 0xdc05, 0, 0x62, 0xffff, 0xdbff, 0xdfff };
193 UnicodeString s
, t(buffer
, -1, LENGTHOF(buffer
));
195 if(s
.setTo(buffer
, -1, LENGTHOF(buffer
)).length()!=u_strlen(buffer
)) {
196 errln("UnicodeString.setTo(buffer, length, capacity) does not work with length==-1");
198 if(t
.length()!=u_strlen(buffer
)) {
199 errln("UnicodeString(buffer, length, capacity) does not work with length==-1");
202 if(0!=s
.caseCompare(buffer
, -1, U_FOLD_CASE_DEFAULT
)) {
203 errln("UnicodeString.caseCompare(const UChar *, length, options) does not work with length==-1");
206 buffer
[u_strlen(buffer
)]=0xe4;
207 UnicodeString
u(buffer
, -1, LENGTHOF(buffer
));
208 if(s
.setTo(buffer
, -1, LENGTHOF(buffer
)).length()!=LENGTHOF(buffer
)) {
209 errln("UnicodeString.setTo(buffer without NUL, length, capacity) does not work with length==-1");
211 if(u
.length()!=LENGTHOF(buffer
)) {
212 errln("UnicodeString(buffer without NUL, length, capacity) does not work with length==-1");
215 static const char cs
[]={ 0x61, (char)0xe4, (char)0x85, 0 };
217 UErrorCode errorCode
=U_ZERO_ERROR
;
219 cnv
=ucnv_open("ISO-8859-1", &errorCode
);
220 UnicodeString
v(cs
, -1, cnv
, errorCode
);
222 if(v
!=UnicodeString("a\\xe4\\x85").unescape()) {
223 errln("UnicodeString(const char *, length, cnv, errorCode) does not work with length==-1");
229 UnicodeStringTest::TestCompare()
231 UnicodeString
test1("this is a test");
232 UnicodeString
test2("this is a test");
233 UnicodeString
test3("this is a test of the emergency broadcast system");
234 UnicodeString
test4("never say, \"this is a test\"!!");
236 UnicodeString
test5((UChar
)0x5000);
237 UnicodeString
test6((UChar
)0x5100);
239 UChar uniChars
[] = { 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
240 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0 };
241 char chars
[] = "this is a test";
243 // test operator== and operator!=
244 if (test1
!= test2
|| test1
== test3
|| test1
== test4
)
245 errln("operator== or operator!= failed");
247 // test operator> and operator<
248 if (test1
> test2
|| test1
< test2
|| !(test1
< test3
) || !(test1
> test4
) ||
251 errln("operator> or operator< failed");
254 // test operator>= and operator<=
255 if (!(test1
>= test2
) || !(test1
<= test2
) || !(test1
<= test3
) || !(test1
>= test4
))
256 errln("operator>= or operator<= failed");
258 // test compare(UnicodeString)
259 if (test1
.compare(test2
) != 0 || test1
.compare(test3
) >= 0 || test1
.compare(test4
) <= 0)
260 errln("compare(UnicodeString) failed");
262 //test compare(offset, length, UnicodeString)
263 if(test1
.compare(0, 14, test2
) != 0 ||
264 test3
.compare(0, 14, test2
) != 0 ||
265 test4
.compare(12, 14, test2
) != 0 ||
266 test3
.compare(0, 18, test1
) <=0 )
267 errln("compare(offset, length, UnicodeString) failes");
269 // test compare(UChar*)
270 if (test2
.compare(uniChars
) != 0 || test3
.compare(uniChars
) <= 0 || test4
.compare(uniChars
) >= 0)
271 errln("compare(UChar*) failed");
273 // test compare(char*)
274 if (test2
.compare(chars
) != 0 || test3
.compare(chars
) <= 0 || test4
.compare(chars
) >= 0)
275 errln("compare(char*) failed");
277 // test compare(UChar*, length)
278 if (test1
.compare(uniChars
, 4) <= 0 || test1
.compare(uniChars
, 4) <= 0)
279 errln("compare(UChar*, length) failed");
281 // test compare(thisOffset, thisLength, that, thatOffset, thatLength)
282 if (test1
.compare(0, 14, test2
, 0, 14) != 0
283 || test1
.compare(0, 14, test3
, 0, 14) != 0
284 || test1
.compare(0, 14, test4
, 12, 14) != 0)
285 errln("1. compare(thisOffset, thisLength, that, thatOffset, thatLength) failed");
287 if (test1
.compare(10, 4, test2
, 0, 4) >= 0
288 || test1
.compare(10, 4, test3
, 22, 9) <= 0
289 || test1
.compare(10, 4, test4
, 22, 4) != 0)
290 errln("2. compare(thisOffset, thisLength, that, thatOffset, thatLength) failed");
292 // test compareBetween
293 if (test1
.compareBetween(0, 14, test2
, 0, 14) != 0 || test1
.compareBetween(0, 14, test3
, 0, 14) != 0
294 || test1
.compareBetween(0, 14, test4
, 12, 26) != 0)
295 errln("compareBetween failed");
297 if (test1
.compareBetween(10, 14, test2
, 0, 4) >= 0 || test1
.compareBetween(10, 14, test3
, 22, 31) <= 0
298 || test1
.compareBetween(10, 14, test4
, 22, 26) != 0)
299 errln("compareBetween failed");
301 // test compare() etc. with strings that share a buffer but are not equal
302 test2
=test1
; // share the buffer, length() too large for the stackBuffer
303 test2
.truncate(1); // change only the length, not the buffer
304 if( test1
==test2
|| test1
<=test2
||
305 test1
.compare(test2
)<=0 ||
306 test1
.compareCodePointOrder(test2
)<=0 ||
307 test1
.compareCodePointOrder(0, INT32_MAX
, test2
)<=0 ||
308 test1
.compareCodePointOrder(0, INT32_MAX
, test2
, 0, INT32_MAX
)<=0 ||
309 test1
.compareCodePointOrderBetween(0, INT32_MAX
, test2
, 0, INT32_MAX
)<=0 ||
310 test1
.caseCompare(test2
, U_FOLD_CASE_DEFAULT
)<=0
312 errln("UnicodeStrings that share a buffer but have different lengths compare as equal");
315 /* test compareCodePointOrder() */
317 /* these strings are in ascending order */
318 static const UChar strings
[][4]={
319 { 0x61, 0 }, /* U+0061 */
320 { 0x20ac, 0xd801, 0 }, /* U+20ac U+d801 */
321 { 0x20ac, 0xd800, 0xdc00, 0 }, /* U+20ac U+10000 */
322 { 0xd800, 0 }, /* U+d800 */
323 { 0xd800, 0xff61, 0 }, /* U+d800 U+ff61 */
324 { 0xdfff, 0 }, /* U+dfff */
325 { 0xff61, 0xdfff, 0 }, /* U+ff61 U+dfff */
326 { 0xff61, 0xd800, 0xdc02, 0 }, /* U+ff61 U+10002 */
327 { 0xd800, 0xdc02, 0 }, /* U+10002 */
328 { 0xd84d, 0xdc56, 0 } /* U+23456 */
330 UnicodeString u
[20]; // must be at least as long as strings[]
333 for(i
=0; i
<(int32_t)(sizeof(strings
)/sizeof(strings
[0])); ++i
) {
334 u
[i
]=UnicodeString(TRUE
, strings
[i
], -1);
337 for(i
=0; i
<(int32_t)(sizeof(strings
)/sizeof(strings
[0])-1); ++i
) {
338 if(u
[i
].compareCodePointOrder(u
[i
+1])>=0 || u
[i
].compareCodePointOrder(0, INT32_MAX
, u
[i
+1].getBuffer())>=0) {
339 errln("error: UnicodeString::compareCodePointOrder() fails for string %d and the following one\n", i
);
344 /* test caseCompare() */
347 _mixed
[]= { 0x61, 0x42, 0x131, 0x3a3, 0xdf, 0x130, 0x49, 0xfb03, 0xd93f, 0xdfff, 0 },
348 _otherDefault
[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x69, 0x307, 0x69, 0x46, 0x66, 0x49, 0xd93f, 0xdfff, 0 },
349 _otherExcludeSpecialI
[]={ 0x41, 0x62, 0x131, 0x3c3, 0x53, 0x73, 0x69, 0x131, 0x66, 0x46, 0x69, 0xd93f, 0xdfff, 0 },
350 _different
[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x130, 0x49, 0x46, 0x66, 0x49, 0xd93f, 0xdffd, 0 };
353 mixed(TRUE
, _mixed
, -1),
354 otherDefault(TRUE
, _otherDefault
, -1),
355 otherExcludeSpecialI(TRUE
, _otherExcludeSpecialI
, -1),
356 different(TRUE
, _different
, -1);
360 /* test caseCompare() */
361 result
=mixed
.caseCompare(otherDefault
, U_FOLD_CASE_DEFAULT
);
362 if(result
!=0 || 0!=mixed
.caseCompareBetween(0, INT32_MAX
, otherDefault
, 0, INT32_MAX
, U_FOLD_CASE_DEFAULT
)) {
363 errln("error: mixed.caseCompare(other, default)=%ld instead of 0\n", result
);
365 result
=mixed
.caseCompare(otherExcludeSpecialI
, U_FOLD_CASE_EXCLUDE_SPECIAL_I
);
367 errln("error: mixed.caseCompare(otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I)=%ld instead of 0\n", result
);
369 result
=mixed
.caseCompare(otherDefault
, U_FOLD_CASE_EXCLUDE_SPECIAL_I
);
370 if(result
==0 || 0==mixed
.caseCompareBetween(0, INT32_MAX
, otherDefault
, 0, INT32_MAX
, U_FOLD_CASE_EXCLUDE_SPECIAL_I
)) {
371 errln("error: mixed.caseCompare(other, U_FOLD_CASE_EXCLUDE_SPECIAL_I)=0 instead of !=0\n");
374 /* test caseCompare() */
375 result
=mixed
.caseCompare(different
, U_FOLD_CASE_DEFAULT
);
377 errln("error: mixed.caseCompare(different, default)=%ld instead of positive\n", result
);
380 /* test caseCompare() - include the folded sharp s (U+00df) with different lengths */
381 result
=mixed
.caseCompare(1, 4, different
, 1, 5, U_FOLD_CASE_DEFAULT
);
382 if(result
!=0 || 0!=mixed
.caseCompareBetween(1, 5, different
, 1, 6, U_FOLD_CASE_DEFAULT
)) {
383 errln("error: mixed.caseCompare(mixed, 1, 4, different, 1, 5, default)=%ld instead of 0\n", result
);
386 /* test caseCompare() - stop in the middle of the sharp s (U+00df) */
387 result
=mixed
.caseCompare(1, 4, different
, 1, 4, U_FOLD_CASE_DEFAULT
);
389 errln("error: mixed.caseCompare(1, 4, different, 1, 4, default)=%ld instead of positive\n", result
);
393 // test that srcLength=-1 is handled in functions that
394 // take input const UChar */int32_t srcLength (j785)
396 static const UChar u
[]={ 0x61, 0x308, 0x62, 0 };
397 UnicodeString s
=UNICODE_STRING("a\\u0308b", 8).unescape();
399 if(s
.compare(u
, -1)!=0 || s
.compare(0, 999, u
, 0, -1)!=0) {
400 errln("error UnicodeString::compare(..., const UChar *, srcLength=-1) does not work");
403 if(s
.compareCodePointOrder(u
, -1)!=0 || s
.compareCodePointOrder(0, 999, u
, 0, -1)!=0) {
404 errln("error UnicodeString::compareCodePointOrder(..., const UChar *, srcLength=-1, ...) does not work");
407 if(s
.caseCompare(u
, -1, U_FOLD_CASE_DEFAULT
)!=0 || s
.caseCompare(0, 999, u
, 0, -1, U_FOLD_CASE_DEFAULT
)!=0) {
408 errln("error UnicodeString::caseCompare(..., const UChar *, srcLength=-1, ...) does not work");
411 if(s
.indexOf(u
, 1, -1, 0, 999)!=1 || s
.indexOf(u
+1, -1, 0, 999)!=1 || s
.indexOf(u
+1, -1, 0)!=1) {
412 errln("error UnicodeString::indexOf(const UChar *, srcLength=-1, ...) does not work");
415 if(s
.lastIndexOf(u
, 1, -1, 0, 999)!=1 || s
.lastIndexOf(u
+1, -1, 0, 999)!=1 || s
.lastIndexOf(u
+1, -1, 0)!=1) {
416 errln("error UnicodeString::lastIndexOf(const UChar *, srcLength=-1, ...) does not work");
419 UnicodeString s2
, s3
;
420 s2
.replace(0, 0, u
+1, -1);
421 s3
.replace(0, 0, u
, 1, -1);
422 if(s
.compare(1, 999, s2
)!=0 || s2
!=s3
) {
423 errln("error UnicodeString::replace(..., const UChar *, srcLength=-1, ...) does not work");
429 UnicodeStringTest::TestExtract()
431 UnicodeString
test1("Now is the time for all good men to come to the aid of their country.", "");
433 UChar test3
[13] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12, 13};
434 char test4
[13] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12, 13};
436 char test6
[13] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12, 13};
438 test1
.extract(11, 12, test2
);
439 test1
.extract(11, 12, test3
);
440 if (test1
.extract(11, 12, test4
) != 12 || test4
[12] != 0) {
441 errln("UnicodeString.extract(char *) failed to return the correct size of destination buffer.");
444 // test proper pinning in extractBetween()
445 test1
.extractBetween(-3, 7, test5
);
446 if(test5
!=UNICODE_STRING("Now is ", 7)) {
447 errln("UnicodeString.extractBetween(-3, 7) did not pin properly.");
450 test1
.extractBetween(11, 23, test5
);
451 if (test1
.extract(60, 71, test6
) != 9) {
452 errln("UnicodeString.extract() failed to return the correct size of destination buffer for end of buffer.");
454 if (test1
.extract(11, 12, test6
) != 12) {
455 errln("UnicodeString.extract() failed to return the correct size of destination buffer.");
458 // convert test4 back to Unicode for comparison
459 UnicodeString
test4b(test4
, 12);
461 if (test1
.extract(11, 12, (char *)NULL
) != 12) {
462 errln("UnicodeString.extract(NULL) failed to return the correct size of destination buffer.");
464 if (test1
.extract(11, -1, test6
) != 0) {
465 errln("UnicodeString.extract(-1) failed to stop reading the string.");
468 for (int32_t i
= 0; i
< 12; i
++) {
469 if (test1
.charAt((int32_t)(11 + i
)) != test2
.charAt(i
)) {
470 errln(UnicodeString("extracting into a UnicodeString failed at position ") + i
);
473 if (test1
.charAt((int32_t)(11 + i
)) != test3
[i
]) {
474 errln(UnicodeString("extracting into an array of UChar failed at position ") + i
);
477 if (((char)test1
.charAt((int32_t)(11 + i
))) != test4b
.charAt(i
)) {
478 errln(UnicodeString("extracting into an array of char failed at position ") + i
);
481 if (test1
.charAt((int32_t)(11 + i
)) != test5
.charAt(i
)) {
482 errln(UnicodeString("extracting with extractBetween failed at position ") + i
);
487 // test preflighting and overflows with invariant conversion
488 if (test1
.extract(0, 10, (char *)NULL
, "") != 10) {
489 errln("UnicodeString.extract(0, 10, (char *)NULL, \"\") != 10");
492 test4
[2] = (char)0xff;
493 if (test1
.extract(0, 10, test4
, 2, "") != 10) {
494 errln("UnicodeString.extract(0, 10, test4, 2, \"\") != 10");
496 if (test4
[2] != (char)0xff) {
497 errln("UnicodeString.extract(0, 10, test4, 2, \"\") overwrote test4[2]");
501 // test new, NUL-terminating extract() function
502 UnicodeString
s("terminate", "");
504 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
505 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5
507 UErrorCode errorCode
;
510 errorCode
=U_ZERO_ERROR
;
511 length
=s
.extract((UChar
*)NULL
, 0, errorCode
);
512 if(errorCode
!=U_BUFFER_OVERFLOW_ERROR
|| length
!=s
.length()) {
513 errln("UnicodeString.extract(NULL, 0)==%d (%s) expected %d (U_BUFFER_OVERFLOW_ERROR)", length
, s
.length(), u_errorName(errorCode
));
516 errorCode
=U_ZERO_ERROR
;
517 length
=s
.extract(dest
, s
.length()-1, errorCode
);
518 if(errorCode
!=U_BUFFER_OVERFLOW_ERROR
|| length
!=s
.length()) {
519 errln("UnicodeString.extract(dest too short)==%d (%s) expected %d (U_BUFFER_OVERFLOW_ERROR)",
520 length
, u_errorName(errorCode
), s
.length());
523 errorCode
=U_ZERO_ERROR
;
524 length
=s
.extract(dest
, s
.length(), errorCode
);
525 if(errorCode
!=U_STRING_NOT_TERMINATED_WARNING
|| length
!=s
.length()) {
526 errln("UnicodeString.extract(dest just right without NUL)==%d (%s) expected %d (U_STRING_NOT_TERMINATED_WARNING)",
527 length
, u_errorName(errorCode
), s
.length());
529 if(dest
[length
-1]!=s
[length
-1] || dest
[length
]!=0xa5) {
530 errln("UnicodeString.extract(dest just right without NUL) did not extract the string correctly");
533 errorCode
=U_ZERO_ERROR
;
534 length
=s
.extract(dest
, s
.length()+1, errorCode
);
535 if(errorCode
!=U_ZERO_ERROR
|| length
!=s
.length()) {
536 errln("UnicodeString.extract(dest large enough)==%d (%s) expected %d (U_ZERO_ERROR)",
537 length
, u_errorName(errorCode
), s
.length());
539 if(dest
[length
-1]!=s
[length
-1] || dest
[length
]!=0 || dest
[length
+1]!=0xa5) {
540 errln("UnicodeString.extract(dest large enough) did not extract the string correctly");
545 // test new UConverter extract() and constructor
546 UnicodeString s
=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape();
548 static const char expect
[]={
549 (char)0xf0, (char)0xaf, (char)0xa6, (char)0x99,
550 (char)0xf0, (char)0x9d, (char)0x85, (char)0x9f,
551 (char)0xc3, (char)0x84,
552 (char)0xe1, (char)0xbb, (char)0x90
554 UErrorCode errorCode
=U_ZERO_ERROR
;
555 UConverter
*cnv
=ucnv_open("UTF-8", &errorCode
);
558 if(U_SUCCESS(errorCode
)) {
560 if( (length
=s
.extract(NULL
, 0, cnv
, errorCode
))!=13 ||
561 errorCode
!=U_BUFFER_OVERFLOW_ERROR
563 errln("UnicodeString::extract(NULL, UConverter) preflighting failed (length=%ld, %s)",
564 length
, u_errorName(errorCode
));
566 errorCode
=U_ZERO_ERROR
;
567 if( (length
=s
.extract(buffer
, 2, cnv
, errorCode
))!=13 ||
568 errorCode
!=U_BUFFER_OVERFLOW_ERROR
570 errln("UnicodeString::extract(too small, UConverter) preflighting failed (length=%ld, %s)",
571 length
, u_errorName(errorCode
));
575 errorCode
=U_ZERO_ERROR
;
576 if( s
.extract(NULL
, 2, cnv
, errorCode
)==13 || U_SUCCESS(errorCode
)) {
577 errln("UnicodeString::extract(UConverter) succeeded with an illegal destination");
579 errorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
580 if( s
.extract(NULL
, 0, cnv
, errorCode
)==13 || U_SUCCESS(errorCode
)) {
581 errln("UnicodeString::extract(UConverter) succeeded with a previous error code");
583 errorCode
=U_ZERO_ERROR
;
586 if( (length
=s
.extract(buffer
, sizeof(buffer
), cnv
, errorCode
))!=13 ||
587 uprv_memcmp(buffer
, expect
, 13)!=0 ||
591 errln("UnicodeString::extract(UConverter) conversion failed (length=%ld, %s)",
592 length
, u_errorName(errorCode
));
595 // try the constructor
596 UnicodeString
t(expect
, sizeof(expect
), cnv
, errorCode
);
597 if(U_FAILURE(errorCode
) || s
!=t
) {
598 errln("UnicodeString(UConverter) conversion failed (%s)",
599 u_errorName(errorCode
));
608 UnicodeStringTest::TestRemoveReplace()
610 UnicodeString
test1("The rain in Spain stays mainly on the plain");
611 UnicodeString
test2("eat SPAMburgers!");
612 UChar test3
[] = { 0x53, 0x50, 0x41, 0x4d, 0x4d, 0 };
613 char test4
[] = "SPAM";
614 UnicodeString
& test5
= test1
;
616 test1
.replace(4, 4, test2
, 4, 4);
617 test1
.replace(12, 5, test3
, 4);
619 test1
.replace(17, 4, test3
);
620 test1
.replace(23, 4, test4
);
621 test1
.replaceBetween(37, 42, test2
, 4, 8);
623 if (test1
!= "The SPAM in SPAM SPAMs SPAMly on the SPAM")
624 errln("One of the replace methods failed:\n"
625 " expected \"The SPAM in SPAM SPAMs SPAMly on the SPAM\",\n"
626 " got \"" + test1
+ "\"");
629 test1
.removeBetween(26, 28);
631 if (test1
!= "The SPAM in SPAM SPAM SPAM on the SPAM")
632 errln("One of the remove methods failed:\n"
633 " expected \"The SPAM in SPAM SPAM SPAM on the SPAM\",\n"
634 " got \"" + test1
+ "\"");
636 for (int32_t i
= 0; i
< test1
.length(); i
++) {
637 if (test5
[i
] != 0x53 && test5
[i
] != 0x50 && test5
[i
] != 0x41 && test5
[i
] != 0x4d && test5
[i
] != 0x20) {
638 test1
.setCharAt(i
, 0x78);
642 if (test1
!= "xxx SPAM xx SPAM SPAM SPAM xx xxx SPAM")
643 errln("One of the remove methods failed:\n"
644 " expected \"xxx SPAM xx SPAM SPAM SPAM xx xxx SPAM\",\n"
645 " got \"" + test1
+ "\"");
648 if (test1
.length() != 0)
649 errln("Remove() failed: expected empty string, got \"" + test1
+ "\"");
653 UnicodeStringTest::TestSearching()
655 UnicodeString
test1("test test ttest tetest testesteststt");
656 UnicodeString
test2("test");
657 UChar testChar
= 0x74;
659 UChar32 testChar32
= 0x20402;
662 0xd841, 0xdc02, 0x0071, 0xdc02, 0xd841, 0x0071, 0xd841, 0xdc02,
664 // 8 9 10 11 12 13 14 15
665 0x0071, 0x0072, 0xd841, 0xdc02, 0x0071, 0xd841, 0xdc02, 0x0071,
668 0xdc02, 0xd841, 0x0073, 0x0000
670 UnicodeString
test3(testData
);
671 UnicodeString
test4(testChar32
);
673 uint16_t occurrences
= 0;
674 int32_t startPos
= 0;
676 startPos
!= -1 && startPos
< test1
.length();
677 (startPos
= test1
.indexOf(test2
, startPos
)) != -1 ? (++occurrences
, startPos
+= 4) : 0)
679 if (occurrences
!= 6)
680 errln("indexOf failed: expected to find 6 occurrences, found " + occurrences
);
682 for ( occurrences
= 0, startPos
= 10;
683 startPos
!= -1 && startPos
< test1
.length();
684 (startPos
= test1
.indexOf(test2
, startPos
)) != -1 ? (++occurrences
, startPos
+= 4) : 0)
686 if (occurrences
!= 4)
687 errln("indexOf with starting offset failed: expected to find 4 occurrences, found " + occurrences
);
690 for ( occurrences
= 0, startPos
= 5;
691 startPos
!= -1 && startPos
< test1
.length();
692 (startPos
= test1
.indexOf(test2
, startPos
, endPos
- startPos
)) != -1 ? (++occurrences
, startPos
+= 4) : 0)
694 if (occurrences
!= 4)
695 errln("indexOf with starting and ending offsets failed: expected to find 4 occurrences, found " + occurrences
);
697 //using UChar32 string
698 for ( startPos
=0, occurrences
=0;
699 startPos
!= -1 && startPos
< test3
.length();
700 (startPos
= test3
.indexOf(test4
, startPos
)) != -1 ? (++occurrences
, startPos
+= 2) : 0)
702 if (occurrences
!= 4)
703 errln((UnicodeString
)"indexOf failed: expected to find 4 occurrences, found " + occurrences
);
705 for ( startPos
=10, occurrences
=0;
706 startPos
!= -1 && startPos
< test3
.length();
707 (startPos
= test3
.indexOf(test4
, startPos
)) != -1 ? (++occurrences
, startPos
+= 2) : 0)
709 if (occurrences
!= 2)
710 errln("indexOf failed: expected to find 2 occurrences, found " + occurrences
);
713 for ( occurrences
= 0, startPos
= 0;
714 startPos
!= -1 && startPos
< test1
.length();
715 (startPos
= test1
.indexOf(testChar
, startPos
)) != -1 ? (++occurrences
, startPos
+= 1) : 0)
717 if (occurrences
!= 16)
718 errln("indexOf with character failed: expected to find 16 occurrences, found " + occurrences
);
720 for ( occurrences
= 0, startPos
= 10;
721 startPos
!= -1 && startPos
< test1
.length();
722 (startPos
= test1
.indexOf(testChar
, startPos
)) != -1 ? (++occurrences
, startPos
+= 1) : 0)
724 if (occurrences
!= 12)
725 errln("indexOf with character & start offset failed: expected to find 12 occurrences, found " + occurrences
);
727 for ( occurrences
= 0, startPos
= 5, endPos
= 28;
728 startPos
!= -1 && startPos
< test1
.length();
729 (startPos
= test1
.indexOf(testChar
, startPos
, endPos
- startPos
)) != -1 ? (++occurrences
, startPos
+= 1) : 0)
731 if (occurrences
!= 10)
732 errln("indexOf with character & start & end offsets failed: expected to find 10 occurrences, found " + occurrences
);
734 //testing for UChar32
735 UnicodeString subString
;
736 for( occurrences
=0, startPos
=0; startPos
< test3
.length(); startPos
+=1){
737 subString
.append(test3
, startPos
, test3
.length());
738 if(subString
.indexOf(testChar32
) != -1 ){
743 if (occurrences
!= 14)
744 errln((UnicodeString
)"indexOf failed: expected to find 14 occurrences, found " + occurrences
);
746 for ( occurrences
= 0, startPos
= 0;
747 startPos
!= -1 && startPos
< test3
.length();
748 (startPos
= test3
.indexOf(testChar32
, startPos
)) != -1 ? (++occurrences
, startPos
+= 1) : 0)
750 if (occurrences
!= 4)
751 errln((UnicodeString
)"indexOf failed: expected to find 4 occurrences, found " + occurrences
);
753 endPos
=test3
.length();
754 for ( occurrences
= 0, startPos
= 5;
755 startPos
!= -1 && startPos
< test3
.length();
756 (startPos
= test3
.indexOf(testChar32
, startPos
, endPos
- startPos
)) != -1 ? (++occurrences
, startPos
+= 1) : 0)
758 if (occurrences
!= 3)
759 errln((UnicodeString
)"indexOf with character & start & end offsets failed: expected to find 2 occurrences, found " + occurrences
);
762 if(test1
.lastIndexOf(test2
)!=29) {
763 errln("test1.lastIndexOf(test2)!=29");
766 if(test1
.lastIndexOf(test2
, 15)!=29 || test1
.lastIndexOf(test2
, 29)!=29 || test1
.lastIndexOf(test2
, 30)!=-1) {
767 errln("test1.lastIndexOf(test2, start) failed");
770 for ( occurrences
= 0, startPos
= 32;
772 (startPos
= test1
.lastIndexOf(test2
, 5, startPos
- 5)) != -1 ? ++occurrences
: 0)
774 if (occurrences
!= 4)
775 errln("lastIndexOf with starting and ending offsets failed: expected to find 4 occurrences, found " + occurrences
);
777 for ( occurrences
= 0, startPos
= 32;
779 (startPos
= test1
.lastIndexOf(testChar
, 5, startPos
- 5)) != -1 ? ++occurrences
: 0)
781 if (occurrences
!= 11)
782 errln("lastIndexOf with character & start & end offsets failed: expected to find 11 occurrences, found " + occurrences
);
785 startPos
=test3
.length();
786 for ( occurrences
= 0;
788 (startPos
= test3
.lastIndexOf(testChar32
, 5, startPos
- 5)) != -1 ? ++occurrences
: 0)
790 if (occurrences
!= 3)
791 errln((UnicodeString
)"lastIndexOf with character & start & end offsets failed: expected to find 3 occurrences, found " + occurrences
);
794 for ( occurrences
= 0, endPos
= test3
.length(); endPos
> 0; endPos
-= 1){
796 subString
.append(test3
, 0, endPos
);
797 if(subString
.lastIndexOf(testChar32
) != -1 ){
801 if (occurrences
!= 18)
802 errln((UnicodeString
)"indexOf failed: expected to find 18 occurrences, found " + occurrences
);
805 // test that indexOf(UChar32) and lastIndexOf(UChar32)
806 // do not find surrogate code points when they are part of matched pairs
807 // (= part of supplementary code points)
809 if(test3
.indexOf((UChar32
)0xd841) != 4 || test3
.indexOf((UChar32
)0xdc02) != 3) {
810 errln("error: UnicodeString::indexOf(UChar32 surrogate) finds a partial supplementary code point");
812 if( UnicodeString(test3
, 0, 17).lastIndexOf((UChar
)0xd841, 0) != 4 ||
813 UnicodeString(test3
, 0, 17).lastIndexOf((UChar32
)0xd841, 2) != 4 ||
814 test3
.lastIndexOf((UChar32
)0xd841, 0, 17) != 4 || test3
.lastIndexOf((UChar32
)0xdc02, 0, 17) != 16
816 errln("error: UnicodeString::lastIndexOf(UChar32 surrogate) finds a partial supplementary code point");
821 UnicodeStringTest::TestSpacePadding()
823 UnicodeString
test1("hello");
824 UnicodeString
test2(" there");
825 UnicodeString
test3("Hi! How ya doin'? Beautiful day, isn't it?");
828 UnicodeString expectedValue
;
830 returnVal
= test1
.padLeading(15);
831 expectedValue
= " hello";
832 if (returnVal
== FALSE
|| test1
!= expectedValue
)
833 errln("padLeading() failed: expected \"" + expectedValue
+ "\", got \"" + test1
+ "\".");
835 returnVal
= test2
.padTrailing(15);
836 expectedValue
= " there ";
837 if (returnVal
== FALSE
|| test2
!= expectedValue
)
838 errln("padTrailing() failed: expected \"" + expectedValue
+ "\", got \"" + test2
+ "\".");
840 expectedValue
= test3
;
841 returnVal
= test3
.padTrailing(15);
842 if (returnVal
== TRUE
|| test3
!= expectedValue
)
843 errln("padTrailing() failed: expected \"" + expectedValue
+ "\", got \"" + test3
+ "\".");
845 expectedValue
= "hello";
846 test4
.setTo(test1
).trim();
848 if (test4
!= expectedValue
|| test1
== expectedValue
|| test4
!= expectedValue
)
849 errln("trim(UnicodeString&) failed");
852 if (test1
!= expectedValue
)
853 errln("trim() failed: expected \"" + expectedValue
+ "\", got \"" + test1
+ "\".");
856 expectedValue
= "there";
857 if (test2
!= expectedValue
)
858 errln("trim() failed: expected \"" + expectedValue
+ "\", got \"" + test2
+ "\".");
861 expectedValue
= "Hi! How ya doin'? Beautiful day, isn't it?";
862 if (test3
!= expectedValue
)
863 errln("trim() failed: expected \"" + expectedValue
+ "\", got \"" + test3
+ "\".");
865 returnVal
= test1
.truncate(15);
866 expectedValue
= "hello";
867 if (returnVal
== TRUE
|| test1
!= expectedValue
)
868 errln("truncate() failed: expected \"" + expectedValue
+ "\", got \"" + test1
+ "\".");
870 returnVal
= test2
.truncate(15);
871 expectedValue
= "there";
872 if (returnVal
== TRUE
|| test2
!= expectedValue
)
873 errln("truncate() failed: expected \"" + expectedValue
+ "\", got \"" + test2
+ "\".");
875 returnVal
= test3
.truncate(15);
876 expectedValue
= "Hi! How ya doi";
877 if (returnVal
== FALSE
|| test3
!= expectedValue
)
878 errln("truncate() failed: expected \"" + expectedValue
+ "\", got \"" + test3
+ "\".");
882 UnicodeStringTest::TestPrefixAndSuffix()
884 UnicodeString
test1("Now is the time for all good men to come to the aid of their country.");
885 UnicodeString
test2("Now");
886 UnicodeString
test3("country.");
887 UnicodeString
test4("count");
889 if (!test1
.startsWith(test2
) || !test1
.startsWith(test2
, 0, test2
.length())) {
890 errln("startsWith() failed: \"" + test2
+ "\" should be a prefix of \"" + test1
+ "\".");
893 if (test1
.startsWith(test3
) ||
894 test1
.startsWith(test3
.getBuffer(), test3
.length()) ||
895 test1
.startsWith(test3
.getTerminatedBuffer(), 0, -1)
897 errln("startsWith() failed: \"" + test3
+ "\" shouldn't be a prefix of \"" + test1
+ "\".");
900 if (test1
.endsWith(test2
)) {
901 errln("endsWith() failed: \"" + test2
+ "\" shouldn't be a suffix of \"" + test1
+ "\".");
904 if (!test1
.endsWith(test3
)) {
905 errln("endsWith(test3) failed: \"" + test3
+ "\" should be a suffix of \"" + test1
+ "\".");
907 if (!test1
.endsWith(test3
, 0, INT32_MAX
)) {
908 errln("endsWith(test3, 0, INT32_MAX) failed: \"" + test3
+ "\" should be a suffix of \"" + test1
+ "\".");
911 if(!test1
.endsWith(test3
.getBuffer(), test3
.length())) {
912 errln("endsWith(test3.getBuffer(), test3.length()) failed: \"" + test3
+ "\" should be a suffix of \"" + test1
+ "\".");
914 if(!test1
.endsWith(test3
.getTerminatedBuffer(), 0, -1)) {
915 errln("endsWith(test3.getTerminatedBuffer(), 0, -1) failed: \"" + test3
+ "\" should be a suffix of \"" + test1
+ "\".");
918 if (!test3
.startsWith(test4
)) {
919 errln("endsWith(test4) failed: \"" + test4
+ "\" should be a prefix of \"" + test3
+ "\".");
922 if (test4
.startsWith(test3
)) {
923 errln("startsWith(test3) failed: \"" + test3
+ "\" shouldn't be a prefix of \"" + test4
+ "\".");
928 UnicodeStringTest::TestFindAndReplace()
930 UnicodeString
test1("One potato, two potato, three potato, four\n");
931 UnicodeString
test2("potato");
932 UnicodeString
test3("MISSISSIPPI");
934 UnicodeString expectedValue
;
936 test1
.findAndReplace(test2
, test3
);
937 expectedValue
= "One MISSISSIPPI, two MISSISSIPPI, three MISSISSIPPI, four\n";
938 if (test1
!= expectedValue
)
939 errln("findAndReplace failed: expected \"" + expectedValue
+ "\", got \"" + test1
+ "\".");
940 test1
.findAndReplace(2, 32, test3
, test2
);
941 expectedValue
= "One potato, two potato, three MISSISSIPPI, four\n";
942 if (test1
!= expectedValue
)
943 errln("findAndReplace failed: expected \"" + expectedValue
+ "\", got \"" + test1
+ "\".");
947 UnicodeStringTest::TestReverse()
949 UnicodeString
test("backwards words say to used I");
958 if (test
!= "I used to say words backwards")
959 errln("reverse() failed: Expected \"I used to say words backwards\",\n got \""
962 test
=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape();
964 if(test
.char32At(0)!=0x1ed0 || test
.char32At(1)!=0xc4 || test
.char32At(2)!=0x1d15f || test
.char32At(4)!=0x2f999) {
965 errln("reverse() failed with supplementary characters");
970 UnicodeStringTest::TestMiscellaneous()
972 UnicodeString
test1("This is a test");
973 UnicodeString
test2("This is a test");
974 UnicodeString
test3("Me too!");
976 // test getBuffer(minCapacity) and releaseBuffer()
977 test1
=UnicodeString(); // make sure that it starts with its stackBuffer
978 UChar
*p
=test1
.getBuffer(20);
979 if(test1
.getCapacity()<20) {
980 errln("UnicodeString::getBuffer(20).getCapacity()<20");
983 test1
.append((UChar
)7); // must not be able to modify the string here
984 test1
.setCharAt(3, 7);
986 if( test1
.length()!=0 ||
987 test1
.charAt(0)!=0xffff || test1
.charAt(3)!=0xffff ||
988 test1
.getBuffer(10)!=0 || test1
.getBuffer()!=0
990 errln("UnicodeString::getBuffer(minCapacity) allows read or write access to the UnicodeString");
996 test1
.releaseBuffer(3);
997 test1
.append((UChar
)4);
999 if(test1
.length()!=4 || test1
.charAt(0)!=1 || test1
.charAt(1)!=2 || test1
.charAt(2)!=3 || test1
.charAt(3)!=4) {
1000 errln("UnicodeString::releaseBuffer(newLength) does not properly reallow access to the UnicodeString");
1003 // test releaseBuffer() without getBuffer(minCapacity) - must not have any effect
1004 test1
.releaseBuffer(1);
1005 if(test1
.length()!=4 || test1
.charAt(0)!=1 || test1
.charAt(1)!=2 || test1
.charAt(2)!=3 || test1
.charAt(3)!=4) {
1006 errln("UnicodeString::releaseBuffer(newLength) without getBuffer(minCapacity) changed the UnicodeString");
1009 // test getBuffer(const)
1010 const UChar
*q
=test1
.getBuffer(), *r
=test1
.getBuffer();
1011 if( test1
.length()!=4 ||
1012 q
[0]!=1 || q
[1]!=2 || q
[2]!=3 || q
[3]!=4 ||
1013 r
[0]!=1 || r
[1]!=2 || r
[2]!=3 || r
[3]!=4
1015 errln("UnicodeString::getBuffer(const) does not return a usable buffer pointer");
1018 // test releaseBuffer() with a NUL-terminated buffer
1019 test1
.getBuffer(20)[2]=0;
1020 test1
.releaseBuffer(); // implicit -1
1021 if(test1
.length()!=2 || test1
.charAt(0)!=1 || test1
.charAt(1) !=2) {
1022 errln("UnicodeString::releaseBuffer(-1) does not properly set the length of the UnicodeString");
1025 // test releaseBuffer() with a non-NUL-terminated buffer
1026 p
=test1
.getBuffer(256);
1027 for(int32_t i
=0; i
<test1
.getCapacity(); ++i
) {
1028 p
[i
]=(UChar
)1; // fill the buffer with all non-NUL code units
1030 test1
.releaseBuffer(); // implicit -1
1031 if(test1
.length()!=test1
.getCapacity() || test1
.charAt(1)!=1 || test1
.charAt(100)!=1 || test1
.charAt(test1
.getCapacity()-1)!=1) {
1032 errln("UnicodeString::releaseBuffer(-1 but no NUL) does not properly set the length of the UnicodeString");
1035 // test getTerminatedBuffer()
1036 test1
=UnicodeString("This is another test.", "");
1037 test2
=UnicodeString("This is another test.", "");
1038 q
=test1
.getTerminatedBuffer();
1039 if(q
[test1
.length()]!=0 || test1
!=test2
|| test2
.compare(q
, -1)!=0) {
1040 errln("getTerminatedBuffer()[length]!=0");
1043 const UChar u
[]={ 5, 6, 7, 8, 0 };
1044 test1
.setTo(FALSE
, u
, 3);
1045 q
=test1
.getTerminatedBuffer();
1046 if(q
==u
|| q
[0]!=5 || q
[1]!=6 || q
[2]!=7 || q
[3]!=0) {
1047 errln("UnicodeString(u[3]).getTerminatedBuffer() returns a bad buffer");
1050 test1
.setTo(TRUE
, u
, -1);
1051 q
=test1
.getTerminatedBuffer();
1052 if(q
!=u
|| test1
.length()!=4 || q
[3]!=8 || q
[4]!=0) {
1053 errln("UnicodeString(u[-1]).getTerminatedBuffer() returns a bad buffer");
1056 test1
=UNICODE_STRING("la", 2);
1057 test1
.append(UNICODE_STRING(" lila", 5).getTerminatedBuffer(), 0, -1);
1058 if(test1
!=UNICODE_STRING("la lila", 7)) {
1059 errln("UnicodeString::append(const UChar *, start, length) failed");
1062 test1
.insert(3, UNICODE_STRING("dudum ", 6), 0, INT32_MAX
);
1063 if(test1
!=UNICODE_STRING("la dudum lila", 13)) {
1064 errln("UnicodeString::insert(start, const UniStr &, start, length) failed");
1067 static const UChar ucs
[]={ 0x68, 0x6d, 0x20, 0 };
1068 test1
.insert(9, ucs
, -1);
1069 if(test1
!=UNICODE_STRING("la dudum hm lila", 16)) {
1070 errln("UnicodeString::insert(start, const UChar *, length) failed");
1073 test1
.replace(9, 2, (UChar
)0x2b);
1074 if(test1
!=UNICODE_STRING("la dudum + lila", 15)) {
1075 errln("UnicodeString::replace(start, length, UChar) failed");
1078 if(test1
.hasMetaData() || UnicodeString().hasMetaData()) {
1079 errln("UnicodeString::hasMetaData() returns TRUE");
1084 UnicodeStringTest::TestStackAllocation()
1086 UChar testString
[] ={
1087 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x72, 0x61, 0x7a, 0x79, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2e, 0 };
1088 UChar guardWord
= 0x4DED;
1089 UnicodeString
* test
= 0;
1091 test
= new UnicodeString(testString
);
1092 if (*test
!= "This is a crazy test.")
1093 errln("Test string failed to initialize properly.");
1094 if (guardWord
!= 0x04DED)
1095 errln("Test string initialization overwrote guard word!");
1097 test
->insert(8, "only ");
1098 test
->remove(15, 6);
1099 if (*test
!= "This is only a test.")
1100 errln("Manipulation of test string failed to work right.");
1101 if (guardWord
!= 0x4DED)
1102 errln("Manipulation of test string overwrote guard word!");
1104 // we have to deinitialize and release the backing store by calling the destructor
1105 // explicitly, since we can't overload operator delete
1108 UChar workingBuffer
[] = {
1109 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
1110 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
1111 0x63, 0x6f, 0x6d, 0x65, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1114 UChar guardWord2
= 0x4DED;
1116 test
= new UnicodeString(workingBuffer
, 35, 100);
1117 if (*test
!= "Now is the time for all men to come")
1118 errln("Stack-allocated backing store failed to initialize correctly.");
1119 if (guardWord2
!= 0x4DED)
1120 errln("Stack-allocated backing store overwrote guard word!");
1122 test
->insert(24, "good ");
1123 if (*test
!= "Now is the time for all good men to come")
1124 errln("insert() on stack-allocated UnicodeString didn't work right");
1125 if (guardWord2
!= 0x4DED)
1126 errln("insert() on stack-allocated UnicodeString overwrote guard word!");
1128 if (workingBuffer
[24] != 0x67)
1129 errln("insert() on stack-allocated UnicodeString didn't affect backing store");
1131 *test
+= " to the aid of their country.";
1132 if (*test
!= "Now is the time for all good men to come to the aid of their country.")
1133 errln("Stack-allocated UnicodeString overflow didn't work");
1134 if (guardWord2
!= 0x4DED)
1135 errln("Stack-allocated UnicodeString overflow overwrote guard word!");
1139 errln("Assignment to stack-allocated UnicodeString didn't work");
1140 if (workingBuffer
[0] != 0x4e)
1141 errln("Change to UnicodeString after overflow are still affecting original buffer");
1142 if (guardWord2
!= 0x4DED)
1143 errln("Change to UnicodeString after overflow overwrote guard word!");
1145 // test read-only aliasing with setTo()
1146 workingBuffer
[0] = 0x20ac;
1147 workingBuffer
[1] = 0x125;
1148 workingBuffer
[2] = 0;
1149 test
->setTo(TRUE
, workingBuffer
, 2);
1150 if(test
->length() != 2 || test
->charAt(0) != 0x20ac || test
->charAt(1) != 0x125) {
1151 errln("UnicodeString.setTo(readonly alias) does not alias correctly");
1154 UnicodeString
*c
=(UnicodeString
*)test
->clone();
1156 workingBuffer
[1] = 0x109;
1157 if(test
->charAt(1) != 0x109) {
1158 errln("UnicodeString.setTo(readonly alias) made a copy: did not see change in buffer");
1161 if(c
->length() != 2 || c
->charAt(1) != 0x125) {
1162 errln("clone(alias) did not copy the buffer");
1166 test
->setTo(TRUE
, workingBuffer
, -1);
1167 if(test
->length() != 2 || test
->charAt(0) != 0x20ac || test
->charAt(1) != 0x109) {
1168 errln("UnicodeString.setTo(readonly alias, length -1) does not alias correctly");
1171 test
->setTo(FALSE
, workingBuffer
, -1);
1172 if(!test
->isBogus()) {
1173 errln("UnicodeString.setTo(unterminated readonly alias, length -1) does not result in isBogus()");
1178 test
=new UnicodeString();
1179 UChar buffer
[]={0x0061, 0x0062, 0x20ac, 0x0043, 0x0042, 0x0000};
1180 test
->setTo(buffer
, 4, 10);
1181 if(test
->length() !=4 || test
->charAt(0) != 0x0061 || test
->charAt(1) != 0x0062 ||
1182 test
->charAt(2) != 0x20ac || test
->charAt(3) != 0x0043){
1183 errln((UnicodeString
)"UnicodeString.setTo(UChar*, length, capacity) does not work correctly\n" + prettify(*test
));
1188 // test the UChar32 constructor
1189 UnicodeString
c32Test((UChar32
)0x10ff2a);
1190 if( c32Test
.length() != UTF_CHAR_LENGTH(0x10ff2a) ||
1191 c32Test
.char32At(c32Test
.length() - 1) != 0x10ff2a
1193 errln("The UnicodeString(UChar32) constructor does not work with a 0x10ff2a filler");
1196 // test the (new) capacity constructor
1197 UnicodeString
capTest(5, (UChar32
)0x2a, 5);
1198 if( capTest
.length() != 5 * UTF_CHAR_LENGTH(0x2a) ||
1199 capTest
.char32At(0) != 0x2a ||
1200 capTest
.char32At(4) != 0x2a
1202 errln("The UnicodeString capacity constructor does not work with an ASCII filler");
1205 capTest
= UnicodeString(5, (UChar32
)0x10ff2a, 5);
1206 if( capTest
.length() != 5 * UTF_CHAR_LENGTH(0x10ff2a) ||
1207 capTest
.char32At(0) != 0x10ff2a ||
1208 capTest
.char32At(4) != 0x10ff2a
1210 errln("The UnicodeString capacity constructor does not work with a 0x10ff2a filler");
1213 capTest
= UnicodeString(5, (UChar32
)0, 0);
1214 if(capTest
.length() != 0) {
1215 errln("The UnicodeString capacity constructor does not work with a 0x10ff2a filler");
1220 * Test the unescape() function.
1222 void UnicodeStringTest::TestUnescape(void) {
1223 UnicodeString
IN("abc\\u4567 \\n\\r \\U00101234xyz\\x1\\x{5289}\\x1b");
1224 UnicodeString
OUT("abc");
1225 OUT
.append((UChar
)0x4567);
1227 OUT
.append((UChar
)0xA);
1228 OUT
.append((UChar
)0xD);
1230 OUT
.append((UChar32
)0x00101234);
1232 OUT
.append((UChar32
)1).append((UChar32
)0x5289).append((UChar
)0x1b);
1233 UnicodeString result
= IN
.unescape();
1234 if (result
!= OUT
) {
1235 errln("FAIL: " + prettify(IN
) + ".unescape() -> " +
1236 prettify(result
) + ", expected " +
1240 // test that an empty string is returned in case of an error
1241 if (!UNICODE_STRING("wrong \\u sequence", 17).unescape().isEmpty()) {
1242 errln("FAIL: unescaping of a string with an illegal escape sequence did not return an empty string");
1246 /* test code point counting functions --------------------------------------- */
1248 /* reference implementation of UnicodeString::hasMoreChar32Than() */
1250 _refUnicodeStringHasMoreChar32Than(const UnicodeString
&s
, int32_t start
, int32_t length
, int32_t number
) {
1251 int32_t count
=s
.countChar32(start
, length
);
1252 return count
>number
;
1255 /* compare the real function against the reference */
1257 UnicodeStringTest::_testUnicodeStringHasMoreChar32Than(const UnicodeString
&s
, int32_t start
, int32_t length
, int32_t number
) {
1258 if(s
.hasMoreChar32Than(start
, length
, number
)!=_refUnicodeStringHasMoreChar32Than(s
, start
, length
, number
)) {
1259 errln("hasMoreChar32Than(%d, %d, %d)=%hd is wrong\n",
1260 start
, length
, number
, s
.hasMoreChar32Than(start
, length
, number
));
1265 UnicodeStringTest::TestCountChar32(void) {
1267 UnicodeString s
=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape();
1269 // test countChar32()
1270 // note that this also calls and tests u_countChar32(length>=0)
1272 s
.countChar32()!=4 ||
1273 s
.countChar32(1)!=4 ||
1274 s
.countChar32(2)!=3 ||
1275 s
.countChar32(2, 3)!=2 ||
1276 s
.countChar32(2, 0)!=0
1278 errln("UnicodeString::countChar32() failed");
1281 // NUL-terminate the string buffer and test u_countChar32(length=-1)
1282 const UChar
*buffer
=s
.getTerminatedBuffer();
1284 u_countChar32(buffer
, -1)!=4 ||
1285 u_countChar32(buffer
+1, -1)!=4 ||
1286 u_countChar32(buffer
+2, -1)!=3 ||
1287 u_countChar32(buffer
+3, -1)!=3 ||
1288 u_countChar32(buffer
+4, -1)!=2 ||
1289 u_countChar32(buffer
+5, -1)!=1 ||
1290 u_countChar32(buffer
+6, -1)!=0
1292 errln("u_countChar32(length=-1) failed");
1295 // test u_countChar32() with bad input
1296 if(u_countChar32(NULL
, 5)!=0 || u_countChar32(buffer
, -2)!=0) {
1297 errln("u_countChar32(bad input) failed (returned non-zero counts)");
1301 /* test data and variables for hasMoreChar32Than() */
1302 static const UChar str
[]={
1303 0x61, 0x62, 0xd800, 0xdc00,
1304 0xd801, 0xdc01, 0x63, 0xd802,
1305 0x64, 0xdc03, 0x65, 0x66,
1306 0xd804, 0xdc04, 0xd805, 0xdc05,
1309 UnicodeString
string(str
, LENGTHOF(str
));
1310 int32_t start
, length
, number
;
1312 /* test hasMoreChar32Than() */
1313 for(length
=string
.length(); length
>=0; --length
) {
1314 for(start
=0; start
<=length
; ++start
) {
1315 for(number
=-1; number
<=((length
-start
)+2); ++number
) {
1316 _testUnicodeStringHasMoreChar32Than(string
, start
, length
-start
, number
);
1321 /* test hasMoreChar32Than() with pinning */
1322 for(start
=-1; start
<=string
.length()+1; ++start
) {
1323 for(number
=-1; number
<=((string
.length()-start
)+2); ++number
) {
1324 _testUnicodeStringHasMoreChar32Than(string
, start
, 0x7fffffff, number
);
1328 /* test hasMoreChar32Than() with a bogus string */
1329 string
.setToBogus();
1330 for(length
=-1; length
<=1; ++length
) {
1331 for(start
=-1; start
<=length
; ++start
) {
1332 for(number
=-1; number
<=((length
-start
)+2); ++number
) {
1333 _testUnicodeStringHasMoreChar32Than(string
, start
, length
-start
, number
);
1340 UnicodeStringTest::TestBogus() {
1341 UnicodeString
test1("This is a test");
1342 UnicodeString
test2("This is a test");
1343 UnicodeString
test3("Me too!");
1345 // test isBogus() and setToBogus()
1346 if (test1
.isBogus() || test2
.isBogus() || test3
.isBogus()) {
1347 errln("A string returned TRUE for isBogus()!");
1350 // NULL pointers are treated like empty strings
1351 // use other illegal arguments to make a bogus string
1352 test3
.setTo(FALSE
, test1
.getBuffer(), -2);
1353 if(!test3
.isBogus()) {
1354 errln("A bogus string returned FALSE for isBogus()!");
1356 if (test1
.hashCode() != test2
.hashCode() || test1
.hashCode() == test3
.hashCode()) {
1357 errln("hashCode() failed");
1359 if(test3
.getBuffer()!=0 || test3
.getBuffer(20)!=0 || test3
.getTerminatedBuffer()!=0) {
1360 errln("bogus.getBuffer()!=0");
1363 // verify that non-assignment modifications fail and do not revive a bogus string
1365 test3
.append((UChar
)0x61);
1366 if(!test3
.isBogus() || test3
.getBuffer()!=0) {
1367 errln("bogus.append('a') worked but must not");
1371 test3
.findAndReplace(UnicodeString((UChar
)0x61), test2
);
1372 if(!test3
.isBogus() || test3
.getBuffer()!=0) {
1373 errln("bogus.findAndReplace() worked but must not");
1378 if(!test3
.isBogus() || test3
.getBuffer()!=0) {
1379 errln("bogus.trim() revived bogus but must not");
1384 if(!test3
.isBogus() || test3
.getBuffer()!=0) {
1385 errln("bogus.remove(1) revived bogus but must not");
1389 if(!test3
.setCharAt(0, 0x62).isBogus() || !test3
.isEmpty()) {
1390 errln("bogus.setCharAt(0, 'b') worked but must not");
1394 if(test3
.truncate(1) || !test3
.isBogus() || !test3
.isEmpty()) {
1395 errln("bogus.truncate(1) revived bogus but must not");
1398 // verify that assignments revive a bogus string
1400 if(!test3
.isBogus() || (test3
=test1
).isBogus() || test3
!=test1
) {
1401 errln("bogus.operator=() failed");
1405 if(!test3
.isBogus() || test3
.fastCopyFrom(test1
).isBogus() || test3
!=test1
) {
1406 errln("bogus.fastCopyFrom() failed");
1410 if(!test3
.isBogus() || test3
.setTo(test1
).isBogus() || test3
!=test1
) {
1411 errln("bogus.setTo(UniStr) failed");
1415 if(!test3
.isBogus() || test3
.setTo(test1
, 0).isBogus() || test3
!=test1
) {
1416 errln("bogus.setTo(UniStr, 0) failed");
1420 if(!test3
.isBogus() || test3
.setTo(test1
, 0, 0x7fffffff).isBogus() || test3
!=test1
) {
1421 errln("bogus.setTo(UniStr, 0, len) failed");
1425 if(!test3
.isBogus() || test3
.setTo(test1
.getBuffer(), test1
.length()).isBogus() || test3
!=test1
) {
1426 errln("bogus.setTo(const UChar *, len) failed");
1430 if(!test3
.isBogus() || test3
.setTo((UChar
)0x2028).isBogus() || test3
!=UnicodeString((UChar
)0x2028)) {
1431 errln("bogus.setTo(UChar) failed");
1435 if(!test3
.isBogus() || test3
.setTo((UChar32
)0x1d157).isBogus() || test3
!=UnicodeString((UChar32
)0x1d157)) {
1436 errln("bogus.setTo(UChar32) failed");
1440 if(!test3
.isBogus() || test3
.setTo(FALSE
, test1
.getBuffer(), test1
.length()).isBogus() || test3
!=test1
) {
1441 errln("bogus.setTo(readonly alias) failed");
1444 // writable alias to another string's buffer: very bad idea, just convenient for this test
1446 if(!test3
.isBogus() || test3
.setTo((UChar
*)test1
.getBuffer(), test1
.length(), test1
.getCapacity()).isBogus() || test3
!=test1
) {
1447 errln("bogus.setTo(writable alias) failed");
1450 // verify simple, documented ways to turn a bogus string into an empty one
1452 if(!test3
.isBogus() || (test3
=UnicodeString()).isBogus() || !test3
.isEmpty()) {
1453 errln("bogus.operator=(UnicodeString()) failed");
1457 if(!test3
.isBogus() || test3
.setTo(UnicodeString()).isBogus() || !test3
.isEmpty()) {
1458 errln("bogus.setTo(UnicodeString()) failed");
1462 if(test3
.remove().isBogus() || test3
.getBuffer()==0 || !test3
.isEmpty()) {
1463 errln("bogus.remove() failed");
1467 if(test3
.remove(0, INT32_MAX
).isBogus() || test3
.getBuffer()==0 || !test3
.isEmpty()) {
1468 errln("bogus.remove(0, INT32_MAX) failed");
1472 if(test3
.truncate(0) || test3
.isBogus() || !test3
.isEmpty()) {
1473 errln("bogus.truncate(0) failed");
1477 if(!test3
.isBogus() || test3
.setTo((UChar32
)-1).isBogus() || !test3
.isEmpty()) {
1478 errln("bogus.setTo((UChar32)-1) failed");
1481 static const UChar nul
=0;
1484 if(!test3
.isBogus() || test3
.setTo(&nul
, 0).isBogus() || !test3
.isEmpty()) {
1485 errln("bogus.setTo(&nul, 0) failed");
1489 if(!test3
.isBogus() || test3
.getBuffer()!=0) {
1490 errln("setToBogus() failed to make a string bogus");
1494 if(test1
.isBogus() || !(test1
=test3
).isBogus()) {
1495 errln("normal=bogus failed to make the left string bogus");
1498 // test that NULL primitive input string values are treated like
1499 // empty strings, not errors (bogus)
1500 test2
.setTo((UChar32
)0x10005);
1501 if(test2
.insert(1, NULL
, 1).length()!=2) {
1502 errln("UniStr.insert(...NULL...) should not modify the string but does");
1505 UErrorCode errorCode
=U_ZERO_ERROR
;
1507 test4((const UChar
*)NULL
),
1508 test5(TRUE
, (const UChar
*)NULL
, 1),
1509 test6((UChar
*)NULL
, 5, 5),
1510 test7((const char *)NULL
, 3, NULL
, errorCode
);
1511 if(test4
.isBogus() || test5
.isBogus() || test6
.isBogus() || test7
.isBogus()) {
1512 errln("a constructor set to bogus for a NULL input string, should be empty");
1515 test4
.setTo(NULL
, 3);
1516 test5
.setTo(TRUE
, (const UChar
*)NULL
, 1);
1517 test6
.setTo((UChar
*)NULL
, 5, 5);
1518 if(test4
.isBogus() || test5
.isBogus() || test6
.isBogus()) {
1519 errln("a setTo() set to bogus for a NULL input string, should be empty");
1522 // test that bogus==bogus<any
1523 if(test1
!=test3
|| test1
.compare(test3
)!=0) {
1524 errln("bogus==bogus failed");
1528 if(test1
>=test2
|| !(test2
>test1
) || test1
.compare(test2
)>=0 || !(test2
.compare(test1
)>0)) {
1529 errln("bogus<empty failed");
1533 // StringEnumeration ------------------------------------------------------- ***
1534 // most of StringEnumeration is tested elsewhere
1535 // this test improves code coverage
1537 static const char *const
1542 "this is a long string which helps us test some buffer limits",
1543 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
1546 class TestEnumeration
: public StringEnumeration
{
1548 TestEnumeration() : i(0) {}
1550 virtual int32_t count(UErrorCode
& /*status*/) const {
1551 return LENGTHOF(testEnumStrings
);
1554 virtual const UnicodeString
*snext(UErrorCode
&status
) {
1555 if(U_SUCCESS(status
) && i
<LENGTHOF(testEnumStrings
)) {
1556 unistr
=UnicodeString(testEnumStrings
[i
++], "");
1563 virtual void reset(UErrorCode
& /*status*/) {
1567 static inline UClassID
getStaticClassID() {
1568 return (UClassID
)&fgClassID
;
1570 virtual UClassID
getDynamicClassID() const {
1571 return getStaticClassID();
1575 static const char fgClassID
;
1580 const char TestEnumeration::fgClassID
=0;
1583 UnicodeStringTest::TestStringEnumeration() {
1585 TestEnumeration ten
;
1592 // test the next() default implementation and ensureCharsCapacity()
1593 for(i
=0; i
<LENGTHOF(testEnumStrings
); ++i
) {
1594 status
=U_ZERO_ERROR
;
1595 pc
=ten
.next(&length
, status
);
1596 s
=UnicodeString(testEnumStrings
[i
], "");
1597 if(U_FAILURE(status
) || pc
==NULL
|| length
!=s
.length() || UnicodeString(pc
, length
, "")!=s
) {
1598 errln("StringEnumeration.next(%d) failed", i
);
1601 status
=U_ZERO_ERROR
;
1602 if(ten
.next(&length
, status
)!=NULL
) {
1603 errln("StringEnumeration.next(done)!=NULL");
1606 // test the unext() default implementation
1608 for(i
=0; i
<LENGTHOF(testEnumStrings
); ++i
) {
1609 status
=U_ZERO_ERROR
;
1610 pu
=ten
.unext(&length
, status
);
1611 s
=UnicodeString(testEnumStrings
[i
], "");
1612 if(U_FAILURE(status
) || pu
==NULL
|| length
!=s
.length() || UnicodeString(TRUE
, pu
, length
)!=s
) {
1613 errln("StringEnumeration.unext(%d) failed", i
);
1616 status
=U_ZERO_ERROR
;
1617 if(ten
.unext(&length
, status
)!=NULL
) {
1618 errln("StringEnumeration.unext(done)!=NULL");
1621 // test that the default clone() implementation works, and returns NULL
1622 if(ten
.clone()!=NULL
) {
1623 errln("StringEnumeration.clone()!=NULL");