1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2011, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 7 #include "ustrtest.h" 8 #include "unicode/appendable.h" 9 #include "unicode/std_string.h" 10 #include "unicode/unistr.h" 11 #include "unicode/uchar.h" 12 #include "unicode/ustring.h" 13 #include "unicode/locid.h" 14 #include "unicode/ucnv.h" 15 #include "unicode/uenum.h" 16 #include "unicode/utf16.h" 17 #include "cmemory.h" 18 #include "charstr.h" 19 20 #if 0 21 #include "unicode/ustream.h" 22 23 #include <iostream> 24 using namespace std; 25 26 #endif 27 28 #define LENGTHOF(array) (int32_t)((sizeof(array)/sizeof((array)[0]))) 29 30 UnicodeStringTest::~UnicodeStringTest() {} 31 32 void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char *par) 33 { 34 if (exec) logln("TestSuite UnicodeStringTest: "); 35 switch (index) { 36 case 0: 37 name = "StringCaseTest"; 38 if (exec) { 39 logln("StringCaseTest---"); logln(""); 40 StringCaseTest test; 41 callTest(test, par); 42 } 43 break; 44 case 1: name = "TestBasicManipulation"; if (exec) TestBasicManipulation(); break; 45 case 2: name = "TestCompare"; if (exec) TestCompare(); break; 46 case 3: name = "TestExtract"; if (exec) TestExtract(); break; 47 case 4: name = "TestRemoveReplace"; if (exec) TestRemoveReplace(); break; 48 case 5: name = "TestSearching"; if (exec) TestSearching(); break; 49 case 6: name = "TestSpacePadding"; if (exec) TestSpacePadding(); break; 50 case 7: name = "TestPrefixAndSuffix"; if (exec) TestPrefixAndSuffix(); break; 51 case 8: name = "TestFindAndReplace"; if (exec) TestFindAndReplace(); break; 52 case 9: name = "TestBogus"; if (exec) TestBogus(); break; 53 case 10: name = "TestReverse"; if (exec) TestReverse(); break; 54 case 11: name = "TestMiscellaneous"; if (exec) TestMiscellaneous(); break; 55 case 12: name = "TestStackAllocation"; if (exec) TestStackAllocation(); break; 56 case 13: name = "TestUnescape"; if (exec) TestUnescape(); break; 57 case 14: name = "TestCountChar32"; if (exec) TestCountChar32(); break; 58 case 15: name = "TestStringEnumeration"; if (exec) TestStringEnumeration(); break; 59 case 16: name = "TestNameSpace"; if (exec) TestNameSpace(); break; 60 case 17: name = "TestUTF32"; if (exec) TestUTF32(); break; 61 case 18: name = "TestUTF8"; if (exec) TestUTF8(); break; 62 case 19: name = "TestReadOnlyAlias"; if (exec) TestReadOnlyAlias(); break; 63 case 20: name = "TestAppendable"; if (exec) TestAppendable(); break; 64 case 21: name = "TestUnicodeStringImplementsAppendable"; if (exec) TestUnicodeStringImplementsAppendable(); break; 65 case 22: name = "TestSizeofUnicodeString"; if (exec) TestSizeofUnicodeString(); break; 66 case 23: name = "TestStartsWithAndEndsWithNulTerminated"; if (exec) TestStartsWithAndEndsWithNulTerminated(); break; 67 68 default: name = ""; break; //needed to end loop 69 } 70 } 71 72 void 73 UnicodeStringTest::TestBasicManipulation() 74 { 75 UnicodeString test1("Now is the time for all men to come swiftly to the aid of the party.\n"); 76 UnicodeString expectedValue; 77 UnicodeString *c; 78 79 c=(UnicodeString *)test1.clone(); 80 test1.insert(24, "good "); 81 expectedValue = "Now is the time for all good men to come swiftly to the aid of the party.\n"; 82 if (test1 != expectedValue) 83 errln("insert() failed: expected \"" + expectedValue + "\"\n,got \"" + test1 + "\""); 84 85 c->insert(24, "good "); 86 if(*c != expectedValue) { 87 errln("clone()->insert() failed: expected \"" + expectedValue + "\"\n,got \"" + *c + "\""); 88 } 89 delete c; 90 91 test1.remove(41, 8); 92 expectedValue = "Now is the time for all good men to come to the aid of the party.\n"; 93 if (test1 != expectedValue) 94 errln("remove() failed: expected \"" + expectedValue + "\"\n,got \"" + test1 + "\""); 95 96 test1.replace(58, 6, "ir country"); 97 expectedValue = "Now is the time for all good men to come to the aid of their country.\n"; 98 if (test1 != expectedValue) 99 errln("replace() failed: expected \"" + expectedValue + "\"\n,got \"" + test1 + "\""); 100 101 UChar temp[80]; 102 test1.extract(0, 15, temp); 103 104 UnicodeString test2(temp, 15); 105 106 expectedValue = "Now is the time"; 107 if (test2 != expectedValue) 108 errln("extract() failed: expected \"" + expectedValue + "\"\n,got \"" + test2 + "\""); 109 110 test2 += " for me to go!\n"; 111 expectedValue = "Now is the time for me to go!\n"; 112 if (test2 != expectedValue) 113 errln("operator+=() failed: expected \"" + expectedValue + "\"\n,got \"" + test2 + "\""); 114 115 if (test1.length() != 70) 116 errln("length() failed: expected 70, got " + test1.length()); 117 if (test2.length() != 30) 118 errln("length() failed: expected 30, got " + test2.length()); 119 120 UnicodeString test3; 121 test3.append((UChar32)0x20402); 122 if(test3 != CharsToUnicodeString("\\uD841\\uDC02")){ 123 errln((UnicodeString)"append failed for UChar32, expected \"\\\\ud841\\\\udc02\", got " + prettify(test3)); 124 } 125 if(test3.length() != 2){ 126 errln("append or length failed for UChar32, expected 2, got " + test3.length()); 127 } 128 test3.append((UChar32)0x0074); 129 if(test3 != CharsToUnicodeString("\\uD841\\uDC02t")){ 130 errln((UnicodeString)"append failed for UChar32, expected \"\\\\uD841\\\\uDC02t\", got " + prettify(test3)); 131 } 132 if(test3.length() != 3){ 133 errln((UnicodeString)"append or length failed for UChar32, expected 2, got " + test3.length()); 134 } 135 136 // test some UChar32 overloads 137 if( test3.setTo((UChar32)0x10330).length() != 2 || 138 test3.insert(0, (UChar32)0x20100).length() != 4 || 139 test3.replace(2, 2, (UChar32)0xe0061).length() != 4 || 140 (test3 = (UChar32)0x14001).length() != 2 141 ) { 142 errln((UnicodeString)"simple UChar32 overloads for replace, insert, setTo or = failed"); 143 } 144 145 { 146 // test moveIndex32() 147 UnicodeString s=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape(); 148 149 if( 150 s.moveIndex32(2, -1)!=0 || 151 s.moveIndex32(2, 1)!=4 || 152 s.moveIndex32(2, 2)!=5 || 153 s.moveIndex32(5, -2)!=2 || 154 s.moveIndex32(0, -1)!=0 || 155 s.moveIndex32(6, 1)!=6 156 ) { 157 errln("UnicodeString::moveIndex32() failed"); 158 } 159 160 if(s.getChar32Start(1)!=0 || s.getChar32Start(2)!=2) { 161 errln("UnicodeString::getChar32Start() failed"); 162 } 163 164 if(s.getChar32Limit(1)!=2 || s.getChar32Limit(2)!=2) { 165 errln("UnicodeString::getChar32Limit() failed"); 166 } 167 } 168 169 { 170 // test new 2.2 constructors and setTo function that parallel Java's substring function. 171 UnicodeString src("Hello folks how are you?"); 172 UnicodeString target1("how are you?"); 173 if (target1 != UnicodeString(src, 12)) { 174 errln("UnicodeString(const UnicodeString&, int32_t) failed"); 175 } 176 UnicodeString target2("folks"); 177 if (target2 != UnicodeString(src, 6, 5)) { 178 errln("UnicodeString(const UnicodeString&, int32_t, int32_t) failed"); 179 } 180 if (target1 != target2.setTo(src, 12)) { 181 errln("UnicodeString::setTo(const UnicodeString&, int32_t) failed"); 182 } 183 } 184 185 { 186 // op+ is new in ICU 2.8 187 UnicodeString s=UnicodeString("abc", "")+UnicodeString("def", "")+UnicodeString("ghi", ""); 188 if(s!=UnicodeString("abcdefghi", "")) { 189 errln("operator+(UniStr, UniStr) failed"); 190 } 191 } 192 193 { 194 // tests for Jitterbug 2360 195 // verify that APIs with source pointer + length accept length == -1 196 // mostly test only where modified, only few functions did not already do this 197 if(UnicodeString("abc", -1, "")!=UnicodeString("abc", "")) { 198 errln("UnicodeString(codepageData, dataLength, codepage) does not work with dataLength==-1"); 199 } 200 201 UChar buffer[10]={ 0x61, 0x62, 0x20ac, 0xd900, 0xdc05, 0, 0x62, 0xffff, 0xdbff, 0xdfff }; 202 UnicodeString s, t(buffer, -1, LENGTHOF(buffer)); 203 204 if(s.setTo(buffer, -1, LENGTHOF(buffer)).length()!=u_strlen(buffer)) { 205 errln("UnicodeString.setTo(buffer, length, capacity) does not work with length==-1"); 206 } 207 if(t.length()!=u_strlen(buffer)) { 208 errln("UnicodeString(buffer, length, capacity) does not work with length==-1"); 209 } 210 211 if(0!=s.caseCompare(buffer, -1, U_FOLD_CASE_DEFAULT)) { 212 errln("UnicodeString.caseCompare(const UChar *, length, options) does not work with length==-1"); 213 } 214 if(0!=s.caseCompare(0, s.length(), buffer, U_FOLD_CASE_DEFAULT)) { 215 errln("UnicodeString.caseCompare(start, _length, const UChar *, options) does not work"); 216 } 217 218 buffer[u_strlen(buffer)]=0xe4; 219 UnicodeString u(buffer, -1, LENGTHOF(buffer)); 220 if(s.setTo(buffer, -1, LENGTHOF(buffer)).length()!=LENGTHOF(buffer)) { 221 errln("UnicodeString.setTo(buffer without NUL, length, capacity) does not work with length==-1"); 222 } 223 if(u.length()!=LENGTHOF(buffer)) { 224 errln("UnicodeString(buffer without NUL, length, capacity) does not work with length==-1"); 225 } 226 227 static const char cs[]={ 0x61, (char)0xe4, (char)0x85, 0 }; 228 UConverter *cnv; 229 UErrorCode errorCode=U_ZERO_ERROR; 230 231 cnv=ucnv_open("ISO-8859-1", &errorCode); 232 UnicodeString v(cs, -1, cnv, errorCode); 233 ucnv_close(cnv); 234 if(v!=CharsToUnicodeString("a\\xe4\\x85")) { 235 errln("UnicodeString(const char *, length, cnv, errorCode) does not work with length==-1"); 236 } 237 } 238 239 #if U_CHARSET_IS_UTF8 240 { 241 // Test the hardcoded-UTF-8 UnicodeString optimizations. 242 static const uint8_t utf8[]={ 0x61, 0xC3, 0xA4, 0xC3, 0x9F, 0xE4, 0xB8, 0x80, 0 }; 243 static const UChar utf16[]={ 0x61, 0xE4, 0xDF, 0x4E00 }; 244 UnicodeString from8a = UnicodeString((const char *)utf8); 245 UnicodeString from8b = UnicodeString((const char *)utf8, (int32_t)sizeof(utf8)-1); 246 UnicodeString from16(FALSE, utf16, LENGTHOF(utf16)); 247 if(from8a != from16 || from8b != from16) { 248 errln("UnicodeString(const char * U_CHARSET_IS_UTF8) failed"); 249 } 250 char buffer[16]; 251 int32_t length8=from16.extract(0, 0x7fffffff, buffer, (uint32_t)sizeof(buffer)); 252 if(length8!=((int32_t)sizeof(utf8)-1) || 0!=uprv_memcmp(buffer, utf8, sizeof(utf8))) { 253 errln("UnicodeString::extract(char * U_CHARSET_IS_UTF8) failed"); 254 } 255 length8=from16.extract(1, 2, buffer, (uint32_t)sizeof(buffer)); 256 if(length8!=4 || buffer[length8]!=0 || 0!=uprv_memcmp(buffer, utf8+1, length8)) { 257 errln("UnicodeString::extract(substring to char * U_CHARSET_IS_UTF8) failed"); 258 } 259 } 260 #endif 261 } 262 263 void 264 UnicodeStringTest::TestCompare() 265 { 266 UnicodeString test1("this is a test"); 267 UnicodeString test2("this is a test"); 268 UnicodeString test3("this is a test of the emergency broadcast system"); 269 UnicodeString test4("never say, \"this is a test\"!!"); 270 271 UnicodeString test5((UChar)0x5000); 272 UnicodeString test6((UChar)0x5100); 273 274 UChar uniChars[] = { 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 275 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0 }; 276 char chars[] = "this is a test"; 277 278 // test operator== and operator!= 279 if (test1 != test2 || test1 == test3 || test1 == test4) 280 errln("operator== or operator!= failed"); 281 282 // test operator> and operator< 283 if (test1 > test2 || test1 < test2 || !(test1 < test3) || !(test1 > test4) || 284 !(test5 < test6) 285 ) { 286 errln("operator> or operator< failed"); 287 } 288 289 // test operator>= and operator<= 290 if (!(test1 >= test2) || !(test1 <= test2) || !(test1 <= test3) || !(test1 >= test4)) 291 errln("operator>= or operator<= failed"); 292 293 // test compare(UnicodeString) 294 if (test1.compare(test2) != 0 || test1.compare(test3) >= 0 || test1.compare(test4) <= 0) 295 errln("compare(UnicodeString) failed"); 296 297 //test compare(offset, length, UnicodeString) 298 if(test1.compare(0, 14, test2) != 0 || 299 test3.compare(0, 14, test2) != 0 || 300 test4.compare(12, 14, test2) != 0 || 301 test3.compare(0, 18, test1) <=0 ) 302 errln("compare(offset, length, UnicodeString) failes"); 303 304 // test compare(UChar*) 305 if (test2.compare(uniChars) != 0 || test3.compare(uniChars) <= 0 || test4.compare(uniChars) >= 0) 306 errln("compare(UChar*) failed"); 307 308 // test compare(char*) 309 if (test2.compare(chars) != 0 || test3.compare(chars) <= 0 || test4.compare(chars) >= 0) 310 errln("compare(char*) failed"); 311 312 // test compare(UChar*, length) 313 if (test1.compare(uniChars, 4) <= 0 || test1.compare(uniChars, 4) <= 0) 314 errln("compare(UChar*, length) failed"); 315 316 // test compare(thisOffset, thisLength, that, thatOffset, thatLength) 317 if (test1.compare(0, 14, test2, 0, 14) != 0 318 || test1.compare(0, 14, test3, 0, 14) != 0 319 || test1.compare(0, 14, test4, 12, 14) != 0) 320 errln("1. compare(thisOffset, thisLength, that, thatOffset, thatLength) failed"); 321 322 if (test1.compare(10, 4, test2, 0, 4) >= 0 323 || test1.compare(10, 4, test3, 22, 9) <= 0 324 || test1.compare(10, 4, test4, 22, 4) != 0) 325 errln("2. compare(thisOffset, thisLength, that, thatOffset, thatLength) failed"); 326 327 // test compareBetween 328 if (test1.compareBetween(0, 14, test2, 0, 14) != 0 || test1.compareBetween(0, 14, test3, 0, 14) != 0 329 || test1.compareBetween(0, 14, test4, 12, 26) != 0) 330 errln("compareBetween failed"); 331 332 if (test1.compareBetween(10, 14, test2, 0, 4) >= 0 || test1.compareBetween(10, 14, test3, 22, 31) <= 0 333 || test1.compareBetween(10, 14, test4, 22, 26) != 0) 334 errln("compareBetween failed"); 335 336 // test compare() etc. with strings that share a buffer but are not equal 337 test2=test1; // share the buffer, length() too large for the stackBuffer 338 test2.truncate(1); // change only the length, not the buffer 339 if( test1==test2 || test1<=test2 || 340 test1.compare(test2)<=0 || 341 test1.compareCodePointOrder(test2)<=0 || 342 test1.compareCodePointOrder(0, INT32_MAX, test2)<=0 || 343 test1.compareCodePointOrder(0, INT32_MAX, test2, 0, INT32_MAX)<=0 || 344 test1.compareCodePointOrderBetween(0, INT32_MAX, test2, 0, INT32_MAX)<=0 || 345 test1.caseCompare(test2, U_FOLD_CASE_DEFAULT)<=0 346 ) { 347 errln("UnicodeStrings that share a buffer but have different lengths compare as equal"); 348 } 349 350 /* test compareCodePointOrder() */ 351 { 352 /* these strings are in ascending order */ 353 static const UChar strings[][4]={ 354 { 0x61, 0 }, /* U+0061 */ 355 { 0x20ac, 0xd801, 0 }, /* U+20ac U+d801 */ 356 { 0x20ac, 0xd800, 0xdc00, 0 }, /* U+20ac U+10000 */ 357 { 0xd800, 0 }, /* U+d800 */ 358 { 0xd800, 0xff61, 0 }, /* U+d800 U+ff61 */ 359 { 0xdfff, 0 }, /* U+dfff */ 360 { 0xff61, 0xdfff, 0 }, /* U+ff61 U+dfff */ 361 { 0xff61, 0xd800, 0xdc02, 0 }, /* U+ff61 U+10002 */ 362 { 0xd800, 0xdc02, 0 }, /* U+10002 */ 363 { 0xd84d, 0xdc56, 0 } /* U+23456 */ 364 }; 365 UnicodeString u[20]; // must be at least as long as strings[] 366 int32_t i; 367 368 for(i=0; i<(int32_t)(sizeof(strings)/sizeof(strings[0])); ++i) { 369 u[i]=UnicodeString(TRUE, strings[i], -1); 370 } 371 372 for(i=0; i<(int32_t)(sizeof(strings)/sizeof(strings[0])-1); ++i) { 373 if(u[i].compareCodePointOrder(u[i+1])>=0 || u[i].compareCodePointOrder(0, INT32_MAX, u[i+1].getBuffer())>=0) { 374 errln("error: UnicodeString::compareCodePointOrder() fails for string %d and the following one\n", i); 375 } 376 } 377 } 378 379 /* test caseCompare() */ 380 { 381 static const UChar 382 _mixed[]= { 0x61, 0x42, 0x131, 0x3a3, 0xdf, 0x130, 0x49, 0xfb03, 0xd93f, 0xdfff, 0 }, 383 _otherDefault[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x69, 0x307, 0x69, 0x46, 0x66, 0x49, 0xd93f, 0xdfff, 0 }, 384 _otherExcludeSpecialI[]={ 0x41, 0x62, 0x131, 0x3c3, 0x53, 0x73, 0x69, 0x131, 0x66, 0x46, 0x69, 0xd93f, 0xdfff, 0 }, 385 _different[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x130, 0x49, 0x46, 0x66, 0x49, 0xd93f, 0xdffd, 0 }; 386 387 UnicodeString 388 mixed(TRUE, _mixed, -1), 389 otherDefault(TRUE, _otherDefault, -1), 390 otherExcludeSpecialI(TRUE, _otherExcludeSpecialI, -1), 391 different(TRUE, _different, -1); 392 393 int8_t result; 394 395 /* test caseCompare() */ 396 result=mixed.caseCompare(otherDefault, U_FOLD_CASE_DEFAULT); 397 if(result!=0 || 0!=mixed.caseCompareBetween(0, INT32_MAX, otherDefault, 0, INT32_MAX, U_FOLD_CASE_DEFAULT)) { 398 errln("error: mixed.caseCompare(other, default)=%ld instead of 0\n", result); 399 } 400 result=mixed.caseCompare(otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I); 401 if(result!=0) { 402 errln("error: mixed.caseCompare(otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I)=%ld instead of 0\n", result); 403 } 404 result=mixed.caseCompare(otherDefault, U_FOLD_CASE_EXCLUDE_SPECIAL_I); 405 if(result==0 || 0==mixed.caseCompareBetween(0, INT32_MAX, otherDefault, 0, INT32_MAX, U_FOLD_CASE_EXCLUDE_SPECIAL_I)) { 406 errln("error: mixed.caseCompare(other, U_FOLD_CASE_EXCLUDE_SPECIAL_I)=0 instead of !=0\n"); 407 } 408 409 /* test caseCompare() */ 410 result=mixed.caseCompare(different, U_FOLD_CASE_DEFAULT); 411 if(result<=0) { 412 errln("error: mixed.caseCompare(different, default)=%ld instead of positive\n", result); 413 } 414 415 /* test caseCompare() - include the folded sharp s (U+00df) with different lengths */ 416 result=mixed.caseCompare(1, 4, different, 1, 5, U_FOLD_CASE_DEFAULT); 417 if(result!=0 || 0!=mixed.caseCompareBetween(1, 5, different, 1, 6, U_FOLD_CASE_DEFAULT)) { 418 errln("error: mixed.caseCompare(mixed, 1, 4, different, 1, 5, default)=%ld instead of 0\n", result); 419 } 420 421 /* test caseCompare() - stop in the middle of the sharp s (U+00df) */ 422 result=mixed.caseCompare(1, 4, different, 1, 4, U_FOLD_CASE_DEFAULT); 423 if(result<=0) { 424 errln("error: mixed.caseCompare(1, 4, different, 1, 4, default)=%ld instead of positive\n", result); 425 } 426 } 427 428 // test that srcLength=-1 is handled in functions that 429 // take input const UChar */int32_t srcLength (j785) 430 { 431 static const UChar u[]={ 0x61, 0x308, 0x62, 0 }; 432 UnicodeString s=UNICODE_STRING("a\\u0308b", 8).unescape(); 433 434 if(s.compare(u, -1)!=0 || s.compare(0, 999, u, 0, -1)!=0) { 435 errln("error UnicodeString::compare(..., const UChar *, srcLength=-1) does not work"); 436 } 437 438 if(s.compareCodePointOrder(u, -1)!=0 || s.compareCodePointOrder(0, 999, u, 0, -1)!=0) { 439 errln("error UnicodeString::compareCodePointOrder(..., const UChar *, srcLength=-1, ...) does not work"); 440 } 441 442 if(s.caseCompare(u, -1, U_FOLD_CASE_DEFAULT)!=0 || s.caseCompare(0, 999, u, 0, -1, U_FOLD_CASE_DEFAULT)!=0) { 443 errln("error UnicodeString::caseCompare(..., const UChar *, srcLength=-1, ...) does not work"); 444 } 445 446 if(s.indexOf(u, 1, -1, 0, 999)!=1 || s.indexOf(u+1, -1, 0, 999)!=1 || s.indexOf(u+1, -1, 0)!=1) { 447 errln("error UnicodeString::indexOf(const UChar *, srcLength=-1, ...) does not work"); 448 } 449 450 if(s.lastIndexOf(u, 1, -1, 0, 999)!=1 || s.lastIndexOf(u+1, -1, 0, 999)!=1 || s.lastIndexOf(u+1, -1, 0)!=1) { 451 errln("error UnicodeString::lastIndexOf(const UChar *, srcLength=-1, ...) does not work"); 452 } 453 454 UnicodeString s2, s3; 455 s2.replace(0, 0, u+1, -1); 456 s3.replace(0, 0, u, 1, -1); 457 if(s.compare(1, 999, s2)!=0 || s2!=s3) { 458 errln("error UnicodeString::replace(..., const UChar *, srcLength=-1, ...) does not work"); 459 } 460 } 461 } 462 463 void 464 UnicodeStringTest::TestExtract() 465 { 466 UnicodeString test1("Now is the time for all good men to come to the aid of their country.", ""); 467 UnicodeString test2; 468 UChar test3[13] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12, 13}; 469 char test4[13] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12, 13}; 470 UnicodeString test5; 471 char test6[13] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 10, 11, 12, 13}; 472 473 test1.extract(11, 12, test2); 474 test1.extract(11, 12, test3); 475 if (test1.extract(11, 12, test4) != 12 || test4[12] != 0) { 476 errln("UnicodeString.extract(char *) failed to return the correct size of destination buffer."); 477 } 478 479 // test proper pinning in extractBetween() 480 test1.extractBetween(-3, 7, test5); 481 if(test5!=UNICODE_STRING("Now is ", 7)) { 482 errln("UnicodeString.extractBetween(-3, 7) did not pin properly."); 483 } 484 485 test1.extractBetween(11, 23, test5); 486 if (test1.extract(60, 71, test6) != 9) { 487 errln("UnicodeString.extract() failed to return the correct size of destination buffer for end of buffer."); 488 } 489 if (test1.extract(11, 12, test6) != 12) { 490 errln("UnicodeString.extract() failed to return the correct size of destination buffer."); 491 } 492 493 // convert test4 back to Unicode for comparison 494 UnicodeString test4b(test4, 12); 495 496 if (test1.extract(11, 12, (char *)NULL) != 12) { 497 errln("UnicodeString.extract(NULL) failed to return the correct size of destination buffer."); 498 } 499 if (test1.extract(11, -1, test6) != 0) { 500 errln("UnicodeString.extract(-1) failed to stop reading the string."); 501 } 502 503 for (int32_t i = 0; i < 12; i++) { 504 if (test1.charAt((int32_t)(11 + i)) != test2.charAt(i)) { 505 errln(UnicodeString("extracting into a UnicodeString failed at position ") + i); 506 break; 507 } 508 if (test1.charAt((int32_t)(11 + i)) != test3[i]) { 509 errln(UnicodeString("extracting into an array of UChar failed at position ") + i); 510 break; 511 } 512 if (((char)test1.charAt((int32_t)(11 + i))) != test4b.charAt(i)) { 513 errln(UnicodeString("extracting into an array of char failed at position ") + i); 514 break; 515 } 516 if (test1.charAt((int32_t)(11 + i)) != test5.charAt(i)) { 517 errln(UnicodeString("extracting with extractBetween failed at position ") + i); 518 break; 519 } 520 } 521 522 // test preflighting and overflows with invariant conversion 523 if (test1.extract(0, 10, (char *)NULL, "") != 10) { 524 errln("UnicodeString.extract(0, 10, (char *)NULL, \"\") != 10"); 525 } 526 527 test4[2] = (char)0xff; 528 if (test1.extract(0, 10, test4, 2, "") != 10) { 529 errln("UnicodeString.extract(0, 10, test4, 2, \"\") != 10"); 530 } 531 if (test4[2] != (char)0xff) { 532 errln("UnicodeString.extract(0, 10, test4, 2, \"\") overwrote test4[2]"); 533 } 534 535 { 536 // test new, NUL-terminating extract() function 537 UnicodeString s("terminate", ""); 538 UChar dest[20]={ 539 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 540 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5 541 }; 542 UErrorCode errorCode; 543 int32_t length; 544 545 errorCode=U_ZERO_ERROR; 546 length=s.extract((UChar *)NULL, 0, errorCode); 547 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=s.length()) { 548 errln("UnicodeString.extract(NULL, 0)==%d (%s) expected %d (U_BUFFER_OVERFLOW_ERROR)", length, s.length(), u_errorName(errorCode)); 549 } 550 551 errorCode=U_ZERO_ERROR; 552 length=s.extract(dest, s.length()-1, errorCode); 553 if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=s.length()) { 554 errln("UnicodeString.extract(dest too short)==%d (%s) expected %d (U_BUFFER_OVERFLOW_ERROR)", 555 length, u_errorName(errorCode), s.length()); 556 } 557 558 errorCode=U_ZERO_ERROR; 559 length=s.extract(dest, s.length(), errorCode); 560 if(errorCode!=U_STRING_NOT_TERMINATED_WARNING || length!=s.length()) { 561 errln("UnicodeString.extract(dest just right without NUL)==%d (%s) expected %d (U_STRING_NOT_TERMINATED_WARNING)", 562 length, u_errorName(errorCode), s.length()); 563 } 564 if(dest[length-1]!=s[length-1] || dest[length]!=0xa5) { 565 errln("UnicodeString.extract(dest just right without NUL) did not extract the string correctly"); 566 } 567 568 errorCode=U_ZERO_ERROR; 569 length=s.extract(dest, s.length()+1, errorCode); 570 if(errorCode!=U_ZERO_ERROR || length!=s.length()) { 571 errln("UnicodeString.extract(dest large enough)==%d (%s) expected %d (U_ZERO_ERROR)", 572 length, u_errorName(errorCode), s.length()); 573 } 574 if(dest[length-1]!=s[length-1] || dest[length]!=0 || dest[length+1]!=0xa5) { 575 errln("UnicodeString.extract(dest large enough) did not extract the string correctly"); 576 } 577 } 578 579 { 580 // test new UConverter extract() and constructor 581 UnicodeString s=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape(); 582 char buffer[32]; 583 static const char expect[]={ 584 (char)0xf0, (char)0xaf, (char)0xa6, (char)0x99, 585 (char)0xf0, (char)0x9d, (char)0x85, (char)0x9f, 586 (char)0xc3, (char)0x84, 587 (char)0xe1, (char)0xbb, (char)0x90 588 }; 589 UErrorCode errorCode=U_ZERO_ERROR; 590 UConverter *cnv=ucnv_open("UTF-8", &errorCode); 591 int32_t length; 592 593 if(U_SUCCESS(errorCode)) { 594 // test preflighting 595 if( (length=s.extract(NULL, 0, cnv, errorCode))!=13 || 596 errorCode!=U_BUFFER_OVERFLOW_ERROR 597 ) { 598 errln("UnicodeString::extract(NULL, UConverter) preflighting failed (length=%ld, %s)", 599 length, u_errorName(errorCode)); 600 } 601 errorCode=U_ZERO_ERROR; 602 if( (length=s.extract(buffer, 2, cnv, errorCode))!=13 || 603 errorCode!=U_BUFFER_OVERFLOW_ERROR 604 ) { 605 errln("UnicodeString::extract(too small, UConverter) preflighting failed (length=%ld, %s)", 606 length, u_errorName(errorCode)); 607 } 608 609 // try error cases 610 errorCode=U_ZERO_ERROR; 611 if( s.extract(NULL, 2, cnv, errorCode)==13 || U_SUCCESS(errorCode)) { 612 errln("UnicodeString::extract(UConverter) succeeded with an illegal destination"); 613 } 614 errorCode=U_ILLEGAL_ARGUMENT_ERROR; 615 if( s.extract(NULL, 0, cnv, errorCode)==13 || U_SUCCESS(errorCode)) { 616 errln("UnicodeString::extract(UConverter) succeeded with a previous error code"); 617 } 618 errorCode=U_ZERO_ERROR; 619 620 // extract for real 621 if( (length=s.extract(buffer, sizeof(buffer), cnv, errorCode))!=13 || 622 uprv_memcmp(buffer, expect, 13)!=0 || 623 buffer[13]!=0 || 624 U_FAILURE(errorCode) 625 ) { 626 errln("UnicodeString::extract(UConverter) conversion failed (length=%ld, %s)", 627 length, u_errorName(errorCode)); 628 } 629 // Test again with just the converter name. 630 if( (length=s.extract(0, s.length(), buffer, sizeof(buffer), "UTF-8"))!=13 || 631 uprv_memcmp(buffer, expect, 13)!=0 || 632 buffer[13]!=0 || 633 U_FAILURE(errorCode) 634 ) { 635 errln("UnicodeString::extract(\"UTF-8\") conversion failed (length=%ld, %s)", 636 length, u_errorName(errorCode)); 637 } 638 639 // try the constructor 640 UnicodeString t(expect, sizeof(expect), cnv, errorCode); 641 if(U_FAILURE(errorCode) || s!=t) { 642 errln("UnicodeString(UConverter) conversion failed (%s)", 643 u_errorName(errorCode)); 644 } 645 646 ucnv_close(cnv); 647 } 648 } 649 } 650 651 void 652 UnicodeStringTest::TestRemoveReplace() 653 { 654 UnicodeString test1("The rain in Spain stays mainly on the plain"); 655 UnicodeString test2("eat SPAMburgers!"); 656 UChar test3[] = { 0x53, 0x50, 0x41, 0x4d, 0x4d, 0 }; 657 char test4[] = "SPAM"; 658 UnicodeString& test5 = test1; 659 660 test1.replace(4, 4, test2, 4, 4); 661 test1.replace(12, 5, test3, 4); 662 test3[4] = 0; 663 test1.replace(17, 4, test3); 664 test1.replace(23, 4, test4); 665 test1.replaceBetween(37, 42, test2, 4, 8); 666 667 if (test1 != "The SPAM in SPAM SPAMs SPAMly on the SPAM") 668 errln("One of the replace methods failed:\n" 669 " expected \"The SPAM in SPAM SPAMs SPAMly on the SPAM\",\n" 670 " got \"" + test1 + "\""); 671 672 test1.remove(21, 1); 673 test1.removeBetween(26, 28); 674 675 if (test1 != "The SPAM in SPAM SPAM SPAM on the SPAM") 676 errln("One of the remove methods failed:\n" 677 " expected \"The SPAM in SPAM SPAM SPAM on the SPAM\",\n" 678 " got \"" + test1 + "\""); 679 680 for (int32_t i = 0; i < test1.length(); i++) { 681 if (test5[i] != 0x53 && test5[i] != 0x50 && test5[i] != 0x41 && test5[i] != 0x4d && test5[i] != 0x20) { 682 test1.setCharAt(i, 0x78); 683 } 684 } 685 686 if (test1 != "xxx SPAM xx SPAM SPAM SPAM xx xxx SPAM") 687 errln("One of the remove methods failed:\n" 688 " expected \"xxx SPAM xx SPAM SPAM SPAM xx xxx SPAM\",\n" 689 " got \"" + test1 + "\""); 690 691 test1.remove(); 692 if (test1.length() != 0) 693 errln("Remove() failed: expected empty string, got \"" + test1 + "\""); 694 } 695 696 void 697 UnicodeStringTest::TestSearching() 698 { 699 UnicodeString test1("test test ttest tetest testesteststt"); 700 UnicodeString test2("test"); 701 UChar testChar = 0x74; 702 703 UChar32 testChar32 = 0x20402; 704 UChar testData[]={ 705 // 0 1 2 3 4 5 6 7 706 0xd841, 0xdc02, 0x0071, 0xdc02, 0xd841, 0x0071, 0xd841, 0xdc02, 707 708 // 8 9 10 11 12 13 14 15 709 0x0071, 0x0072, 0xd841, 0xdc02, 0x0071, 0xd841, 0xdc02, 0x0071, 710 711 // 16 17 18 19 712 0xdc02, 0xd841, 0x0073, 0x0000 713 }; 714 UnicodeString test3(testData); 715 UnicodeString test4(testChar32); 716 717 uint16_t occurrences = 0; 718 int32_t startPos = 0; 719 for ( ; 720 startPos != -1 && startPos < test1.length(); 721 (startPos = test1.indexOf(test2, startPos)) != -1 ? (++occurrences, startPos += 4) : 0) 722 ; 723 if (occurrences != 6) 724 errln("indexOf failed: expected to find 6 occurrences, found " + occurrences); 725 726 for ( occurrences = 0, startPos = 10; 727 startPos != -1 && startPos < test1.length(); 728 (startPos = test1.indexOf(test2, startPos)) != -1 ? (++occurrences, startPos += 4) : 0) 729 ; 730 if (occurrences != 4) 731 errln("indexOf with starting offset failed: expected to find 4 occurrences, found " + occurrences); 732 733 int32_t endPos = 28; 734 for ( occurrences = 0, startPos = 5; 735 startPos != -1 && startPos < test1.length(); 736 (startPos = test1.indexOf(test2, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 4) : 0) 737 ; 738 if (occurrences != 4) 739 errln("indexOf with starting and ending offsets failed: expected to find 4 occurrences, found " + occurrences); 740 741 //using UChar32 string 742 for ( startPos=0, occurrences=0; 743 startPos != -1 && startPos < test3.length(); 744 (startPos = test3.indexOf(test4, startPos)) != -1 ? (++occurrences, startPos += 2) : 0) 745 ; 746 if (occurrences != 4) 747 errln((UnicodeString)"indexOf failed: expected to find 4 occurrences, found " + occurrences); 748 749 for ( startPos=10, occurrences=0; 750 startPos != -1 && startPos < test3.length(); 751 (startPos = test3.indexOf(test4, startPos)) != -1 ? (++occurrences, startPos += 2) : 0) 752 ; 753 if (occurrences != 2) 754 errln("indexOf failed: expected to find 2 occurrences, found " + occurrences); 755 //--- 756 757 for ( occurrences = 0, startPos = 0; 758 startPos != -1 && startPos < test1.length(); 759 (startPos = test1.indexOf(testChar, startPos)) != -1 ? (++occurrences, startPos += 1) : 0) 760 ; 761 if (occurrences != 16) 762 errln("indexOf with character failed: expected to find 16 occurrences, found " + occurrences); 763 764 for ( occurrences = 0, startPos = 10; 765 startPos != -1 && startPos < test1.length(); 766 (startPos = test1.indexOf(testChar, startPos)) != -1 ? (++occurrences, startPos += 1) : 0) 767 ; 768 if (occurrences != 12) 769 errln("indexOf with character & start offset failed: expected to find 12 occurrences, found " + occurrences); 770 771 for ( occurrences = 0, startPos = 5, endPos = 28; 772 startPos != -1 && startPos < test1.length(); 773 (startPos = test1.indexOf(testChar, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 1) : 0) 774 ; 775 if (occurrences != 10) 776 errln("indexOf with character & start & end offsets failed: expected to find 10 occurrences, found " + occurrences); 777 778 //testing for UChar32 779 UnicodeString subString; 780 for( occurrences =0, startPos=0; startPos < test3.length(); startPos +=1){ 781 subString.append(test3, startPos, test3.length()); 782 if(subString.indexOf(testChar32) != -1 ){ 783 ++occurrences; 784 } 785 subString.remove(); 786 } 787 if (occurrences != 14) 788 errln((UnicodeString)"indexOf failed: expected to find 14 occurrences, found " + occurrences); 789 790 for ( occurrences = 0, startPos = 0; 791 startPos != -1 && startPos < test3.length(); 792 (startPos = test3.indexOf(testChar32, startPos)) != -1 ? (++occurrences, startPos += 1) : 0) 793 ; 794 if (occurrences != 4) 795 errln((UnicodeString)"indexOf failed: expected to find 4 occurrences, found " + occurrences); 796 797 endPos=test3.length(); 798 for ( occurrences = 0, startPos = 5; 799 startPos != -1 && startPos < test3.length(); 800 (startPos = test3.indexOf(testChar32, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 1) : 0) 801 ; 802 if (occurrences != 3) 803 errln((UnicodeString)"indexOf with character & start & end offsets failed: expected to find 2 occurrences, found " + occurrences); 804 //--- 805 806 if(test1.lastIndexOf(test2)!=29) { 807 errln("test1.lastIndexOf(test2)!=29"); 808 } 809 810 if(test1.lastIndexOf(test2, 15)!=29 || test1.lastIndexOf(test2, 29)!=29 || test1.lastIndexOf(test2, 30)!=-1) { 811 errln("test1.lastIndexOf(test2, start) failed"); 812 } 813 814 for ( occurrences = 0, startPos = 32; 815 startPos != -1; 816 (startPos = test1.lastIndexOf(test2, 5, startPos - 5)) != -1 ? ++occurrences : 0) 817 ; 818 if (occurrences != 4) 819 errln("lastIndexOf with starting and ending offsets failed: expected to find 4 occurrences, found " + occurrences); 820 821 for ( occurrences = 0, startPos = 32; 822 startPos != -1; 823 (startPos = test1.lastIndexOf(testChar, 5, startPos - 5)) != -1 ? ++occurrences : 0) 824 ; 825 if (occurrences != 11) 826 errln("lastIndexOf with character & start & end offsets failed: expected to find 11 occurrences, found " + occurrences); 827 828 //testing UChar32 829 startPos=test3.length(); 830 for ( occurrences = 0; 831 startPos != -1; 832 (startPos = test3.lastIndexOf(testChar32, 5, startPos - 5)) != -1 ? ++occurrences : 0) 833 ; 834 if (occurrences != 3) 835 errln((UnicodeString)"lastIndexOf with character & start & end offsets failed: expected to find 3 occurrences, found " + occurrences); 836 837 838 for ( occurrences = 0, endPos = test3.length(); endPos > 0; endPos -= 1){ 839 subString.remove(); 840 subString.append(test3, 0, endPos); 841 if(subString.lastIndexOf(testChar32) != -1 ){ 842 ++occurrences; 843 } 844 } 845 if (occurrences != 18) 846 errln((UnicodeString)"indexOf failed: expected to find 18 occurrences, found " + occurrences); 847 //--- 848 849 // test that indexOf(UChar32) and lastIndexOf(UChar32) 850 // do not find surrogate code points when they are part of matched pairs 851 // (= part of supplementary code points) 852 // Jitterbug 1542 853 if(test3.indexOf((UChar32)0xd841) != 4 || test3.indexOf((UChar32)0xdc02) != 3) { 854 errln("error: UnicodeString::indexOf(UChar32 surrogate) finds a partial supplementary code point"); 855 } 856 if( UnicodeString(test3, 0, 17).lastIndexOf((UChar)0xd841, 0) != 4 || 857 UnicodeString(test3, 0, 17).lastIndexOf((UChar32)0xd841, 2) != 4 || 858 test3.lastIndexOf((UChar32)0xd841, 0, 17) != 4 || test3.lastIndexOf((UChar32)0xdc02, 0, 17) != 16 859 ) { 860 errln("error: UnicodeString::lastIndexOf(UChar32 surrogate) finds a partial supplementary code point"); 861 } 862 } 863 864 void 865 UnicodeStringTest::TestSpacePadding() 866 { 867 UnicodeString test1("hello"); 868 UnicodeString test2(" there"); 869 UnicodeString test3("Hi! How ya doin'? Beautiful day, isn't it?"); 870 UnicodeString test4; 871 UBool returnVal; 872 UnicodeString expectedValue; 873 874 returnVal = test1.padLeading(15); 875 expectedValue = " hello"; 876 if (returnVal == FALSE || test1 != expectedValue) 877 errln("padLeading() failed: expected \"" + expectedValue + "\", got \"" + test1 + "\"."); 878 879 returnVal = test2.padTrailing(15); 880 expectedValue = " there "; 881 if (returnVal == FALSE || test2 != expectedValue) 882 errln("padTrailing() failed: expected \"" + expectedValue + "\", got \"" + test2 + "\"."); 883 884 expectedValue = test3; 885 returnVal = test3.padTrailing(15); 886 if (returnVal == TRUE || test3 != expectedValue) 887 errln("padTrailing() failed: expected \"" + expectedValue + "\", got \"" + test3 + "\"."); 888 889 expectedValue = "hello"; 890 test4.setTo(test1).trim(); 891 892 if (test4 != expectedValue || test1 == expectedValue || test4 != expectedValue) 893 errln("trim(UnicodeString&) failed"); 894 895 test1.trim(); 896 if (test1 != expectedValue) 897 errln("trim() failed: expected \"" + expectedValue + "\", got \"" + test1 + "\"."); 898 899 test2.trim(); 900 expectedValue = "there"; 901 if (test2 != expectedValue) 902 errln("trim() failed: expected \"" + expectedValue + "\", got \"" + test2 + "\"."); 903 904 test3.trim(); 905 expectedValue = "Hi! How ya doin'? Beautiful day, isn't it?"; 906 if (test3 != expectedValue) 907 errln("trim() failed: expected \"" + expectedValue + "\", got \"" + test3 + "\"."); 908 909 returnVal = test1.truncate(15); 910 expectedValue = "hello"; 911 if (returnVal == TRUE || test1 != expectedValue) 912 errln("truncate() failed: expected \"" + expectedValue + "\", got \"" + test1 + "\"."); 913 914 returnVal = test2.truncate(15); 915 expectedValue = "there"; 916 if (returnVal == TRUE || test2 != expectedValue) 917 errln("truncate() failed: expected \"" + expectedValue + "\", got \"" + test2 + "\"."); 918 919 returnVal = test3.truncate(15); 920 expectedValue = "Hi! How ya doi"; 921 if (returnVal == FALSE || test3 != expectedValue) 922 errln("truncate() failed: expected \"" + expectedValue + "\", got \"" + test3 + "\"."); 923 } 924 925 void 926 UnicodeStringTest::TestPrefixAndSuffix() 927 { 928 UnicodeString test1("Now is the time for all good men to come to the aid of their country."); 929 UnicodeString test2("Now"); 930 UnicodeString test3("country."); 931 UnicodeString test4("count"); 932 933 if (!test1.startsWith(test2) || !test1.startsWith(test2, 0, test2.length())) { 934 errln("startsWith() failed: \"" + test2 + "\" should be a prefix of \"" + test1 + "\"."); 935 } 936 937 if (test1.startsWith(test3) || 938 test1.startsWith(test3.getBuffer(), test3.length()) || 939 test1.startsWith(test3.getTerminatedBuffer(), 0, -1) 940 ) { 941 errln("startsWith() failed: \"" + test3 + "\" shouldn't be a prefix of \"" + test1 + "\"."); 942 } 943 944 if (test1.endsWith(test2)) { 945 errln("endsWith() failed: \"" + test2 + "\" shouldn't be a suffix of \"" + test1 + "\"."); 946 } 947 948 if (!test1.endsWith(test3)) { 949 errln("endsWith(test3) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\"."); 950 } 951 if (!test1.endsWith(test3, 0, INT32_MAX)) { 952 errln("endsWith(test3, 0, INT32_MAX) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\"."); 953 } 954 955 if(!test1.endsWith(test3.getBuffer(), test3.length())) { 956 errln("endsWith(test3.getBuffer(), test3.length()) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\"."); 957 } 958 if(!test1.endsWith(test3.getTerminatedBuffer(), 0, -1)) { 959 errln("endsWith(test3.getTerminatedBuffer(), 0, -1) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\"."); 960 } 961 962 if (!test3.startsWith(test4)) { 963 errln("endsWith(test4) failed: \"" + test4 + "\" should be a prefix of \"" + test3 + "\"."); 964 } 965 966 if (test4.startsWith(test3)) { 967 errln("startsWith(test3) failed: \"" + test3 + "\" shouldn't be a prefix of \"" + test4 + "\"."); 968 } 969 } 970 971 void 972 UnicodeStringTest::TestStartsWithAndEndsWithNulTerminated() { 973 UnicodeString test("abcde"); 974 const UChar ab[] = { 0x61, 0x62, 0 }; 975 const UChar de[] = { 0x64, 0x65, 0 }; 976 assertTrue("abcde.startsWith(ab, -1)", test.startsWith(ab, -1)); 977 assertTrue("abcde.startsWith(ab, 0, -1)", test.startsWith(ab, 0, -1)); 978 assertTrue("abcde.endsWith(de, -1)", test.endsWith(de, -1)); 979 assertTrue("abcde.endsWith(de, 0, -1)", test.endsWith(de, 0, -1)); 980 } 981 982 void 983 UnicodeStringTest::TestFindAndReplace() 984 { 985 UnicodeString test1("One potato, two potato, three potato, four\n"); 986 UnicodeString test2("potato"); 987 UnicodeString test3("MISSISSIPPI"); 988 989 UnicodeString expectedValue; 990 991 test1.findAndReplace(test2, test3); 992 expectedValue = "One MISSISSIPPI, two MISSISSIPPI, three MISSISSIPPI, four\n"; 993 if (test1 != expectedValue) 994 errln("findAndReplace failed: expected \"" + expectedValue + "\", got \"" + test1 + "\"."); 995 test1.findAndReplace(2, 32, test3, test2); 996 expectedValue = "One potato, two potato, three MISSISSIPPI, four\n"; 997 if (test1 != expectedValue) 998 errln("findAndReplace failed: expected \"" + expectedValue + "\", got \"" + test1 + "\"."); 999 } 1000 1001 void 1002 UnicodeStringTest::TestReverse() 1003 { 1004 UnicodeString test("backwards words say to used I"); 1005 1006 test.reverse(); 1007 test.reverse(2, 4); 1008 test.reverse(7, 2); 1009 test.reverse(10, 3); 1010 test.reverse(14, 5); 1011 test.reverse(20, 9); 1012 1013 if (test != "I used to say words backwards") 1014 errln("reverse() failed: Expected \"I used to say words backwards\",\n got \"" 1015 + test + "\""); 1016 1017 test=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape(); 1018 test.reverse(); 1019 if(test.char32At(0)!=0x1ed0 || test.char32At(1)!=0xc4 || test.char32At(2)!=0x1d15f || test.char32At(4)!=0x2f999) { 1020 errln("reverse() failed with supplementary characters"); 1021 } 1022 1023 // Test case for ticket #8091: 1024 // UnicodeString::reverse() failed to see a lead surrogate in the middle of 1025 // an odd-length string that contains no other lead surrogates. 1026 test=UNICODE_STRING_SIMPLE("ab\\U0001F4A9e").unescape(); 1027 UnicodeString expected=UNICODE_STRING_SIMPLE("e\\U0001F4A9ba").unescape(); 1028 test.reverse(); 1029 if(test!=expected) { 1030 errln("reverse() failed with only lead surrogate in the middle"); 1031 } 1032 } 1033 1034 void 1035 UnicodeStringTest::TestMiscellaneous() 1036 { 1037 UnicodeString test1("This is a test"); 1038 UnicodeString test2("This is a test"); 1039 UnicodeString test3("Me too!"); 1040 1041 // test getBuffer(minCapacity) and releaseBuffer() 1042 test1=UnicodeString(); // make sure that it starts with its stackBuffer 1043 UChar *p=test1.getBuffer(20); 1044 if(test1.getCapacity()<20) { 1045 errln("UnicodeString::getBuffer(20).getCapacity()<20"); 1046 } 1047 1048 test1.append((UChar)7); // must not be able to modify the string here 1049 test1.setCharAt(3, 7); 1050 test1.reverse(); 1051 if( test1.length()!=0 || 1052 test1.charAt(0)!=0xffff || test1.charAt(3)!=0xffff || 1053 test1.getBuffer(10)!=0 || test1.getBuffer()!=0 1054 ) { 1055 errln("UnicodeString::getBuffer(minCapacity) allows read or write access to the UnicodeString"); 1056 } 1057 1058 p[0]=1; 1059 p[1]=2; 1060 p[2]=3; 1061 test1.releaseBuffer(3); 1062 test1.append((UChar)4); 1063 1064 if(test1.length()!=4 || test1.charAt(0)!=1 || test1.charAt(1)!=2 || test1.charAt(2)!=3 || test1.charAt(3)!=4) { 1065 errln("UnicodeString::releaseBuffer(newLength) does not properly reallow access to the UnicodeString"); 1066 } 1067 1068 // test releaseBuffer() without getBuffer(minCapacity) - must not have any effect 1069 test1.releaseBuffer(1); 1070 if(test1.length()!=4 || test1.charAt(0)!=1 || test1.charAt(1)!=2 || test1.charAt(2)!=3 || test1.charAt(3)!=4) { 1071 errln("UnicodeString::releaseBuffer(newLength) without getBuffer(minCapacity) changed the UnicodeString"); 1072 } 1073 1074 // test getBuffer(const) 1075 const UChar *q=test1.getBuffer(), *r=test1.getBuffer(); 1076 if( test1.length()!=4 || 1077 q[0]!=1 || q[1]!=2 || q[2]!=3 || q[3]!=4 || 1078 r[0]!=1 || r[1]!=2 || r[2]!=3 || r[3]!=4 1079 ) { 1080 errln("UnicodeString::getBuffer(const) does not return a usable buffer pointer"); 1081 } 1082 1083 // test releaseBuffer() with a NUL-terminated buffer 1084 test1.getBuffer(20)[2]=0; 1085 test1.releaseBuffer(); // implicit -1 1086 if(test1.length()!=2 || test1.charAt(0)!=1 || test1.charAt(1) !=2) { 1087 errln("UnicodeString::releaseBuffer(-1) does not properly set the length of the UnicodeString"); 1088 } 1089 1090 // test releaseBuffer() with a non-NUL-terminated buffer 1091 p=test1.getBuffer(256); 1092 for(int32_t i=0; i<test1.getCapacity(); ++i) { 1093 p[i]=(UChar)1; // fill the buffer with all non-NUL code units 1094 } 1095 test1.releaseBuffer(); // implicit -1 1096 if(test1.length()!=test1.getCapacity() || test1.charAt(1)!=1 || test1.charAt(100)!=1 || test1.charAt(test1.getCapacity()-1)!=1) { 1097 errln("UnicodeString::releaseBuffer(-1 but no NUL) does not properly set the length of the UnicodeString"); 1098 } 1099 1100 // test getTerminatedBuffer() 1101 test1=UnicodeString("This is another test.", ""); 1102 test2=UnicodeString("This is another test.", ""); 1103 q=test1.getTerminatedBuffer(); 1104 if(q[test1.length()]!=0 || test1!=test2 || test2.compare(q, -1)!=0) { 1105 errln("getTerminatedBuffer()[length]!=0"); 1106 } 1107 1108 const UChar u[]={ 5, 6, 7, 8, 0 }; 1109 test1.setTo(FALSE, u, 3); 1110 q=test1.getTerminatedBuffer(); 1111 if(q==u || q[0]!=5 || q[1]!=6 || q[2]!=7 || q[3]!=0) { 1112 errln("UnicodeString(u[3]).getTerminatedBuffer() returns a bad buffer"); 1113 } 1114 1115 test1.setTo(TRUE, u, -1); 1116 q=test1.getTerminatedBuffer(); 1117 if(q!=u || test1.length()!=4 || q[3]!=8 || q[4]!=0) { 1118 errln("UnicodeString(u[-1]).getTerminatedBuffer() returns a bad buffer"); 1119 } 1120 1121 test1=UNICODE_STRING("la", 2); 1122 test1.append(UNICODE_STRING(" lila", 5).getTerminatedBuffer(), 0, -1); 1123 if(test1!=UNICODE_STRING("la lila", 7)) { 1124 errln("UnicodeString::append(const UChar *, start, length) failed"); 1125 } 1126 1127 test1.insert(3, UNICODE_STRING("dudum ", 6), 0, INT32_MAX); 1128 if(test1!=UNICODE_STRING("la dudum lila", 13)) { 1129 errln("UnicodeString::insert(start, const UniStr &, start, length) failed"); 1130 } 1131 1132 static const UChar ucs[]={ 0x68, 0x6d, 0x20, 0 }; 1133 test1.insert(9, ucs, -1); 1134 if(test1!=UNICODE_STRING("la dudum hm lila", 16)) { 1135 errln("UnicodeString::insert(start, const UChar *, length) failed"); 1136 } 1137 1138 test1.replace(9, 2, (UChar)0x2b); 1139 if(test1!=UNICODE_STRING("la dudum + lila", 15)) { 1140 errln("UnicodeString::replace(start, length, UChar) failed"); 1141 } 1142 1143 if(test1.hasMetaData() || UnicodeString().hasMetaData()) { 1144 errln("UnicodeString::hasMetaData() returns TRUE"); 1145 } 1146 1147 // test getTerminatedBuffer() on a truncated, shared, heap-allocated string 1148 test1=UNICODE_STRING_SIMPLE("abcdefghijklmnopqrstuvwxyz0123456789."); 1149 test1.truncate(36); // ensure length()<getCapacity() 1150 test2=test1; // share the buffer 1151 test1.truncate(5); 1152 if(test1.length()!=5 || test1.getTerminatedBuffer()[5]!=0) { 1153 errln("UnicodeString(shared buffer).truncate() failed"); 1154 } 1155 if(test2.length()!=36 || test2[5]!=0x66 || u_strlen(test2.getTerminatedBuffer())!=36) { 1156 errln("UnicodeString(shared buffer).truncate().getTerminatedBuffer() " 1157 "modified another copy of the string!"); 1158 } 1159 test1=UNICODE_STRING_SIMPLE("abcdefghijklmnopqrstuvwxyz0123456789."); 1160 test1.truncate(36); // ensure length()<getCapacity() 1161 test2=test1; // share the buffer 1162 test1.remove(); 1163 if(test1.length()!=0 || test1.getTerminatedBuffer()[0]!=0) { 1164 errln("UnicodeString(shared buffer).remove() failed"); 1165 } 1166 if(test2.length()!=36 || test2[0]!=0x61 || u_strlen(test2.getTerminatedBuffer())!=36) { 1167 errln("UnicodeString(shared buffer).remove().getTerminatedBuffer() " 1168 "modified another copy of the string!"); 1169 } 1170 } 1171 1172 void 1173 UnicodeStringTest::TestStackAllocation() 1174 { 1175 UChar testString[] ={ 1176 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x72, 0x61, 0x7a, 0x79, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2e, 0 }; 1177 UChar guardWord = 0x4DED; 1178 UnicodeString* test = 0; 1179 1180 test = new UnicodeString(testString); 1181 if (*test != "This is a crazy test.") 1182 errln("Test string failed to initialize properly."); 1183 if (guardWord != 0x04DED) 1184 errln("Test string initialization overwrote guard word!"); 1185 1186 test->insert(8, "only "); 1187 test->remove(15, 6); 1188 if (*test != "This is only a test.") 1189 errln("Manipulation of test string failed to work right."); 1190 if (guardWord != 0x4DED) 1191 errln("Manipulation of test string overwrote guard word!"); 1192 1193 // we have to deinitialize and release the backing store by calling the destructor 1194 // explicitly, since we can't overload operator delete 1195 delete test; 1196 1197 UChar workingBuffer[] = { 1198 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 1199 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 1200 0x63, 0x6f, 0x6d, 0x65, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1201 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, 1202 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 1203 UChar guardWord2 = 0x4DED; 1204 1205 test = new UnicodeString(workingBuffer, 35, 100); 1206 if (*test != "Now is the time for all men to come") 1207 errln("Stack-allocated backing store failed to initialize correctly."); 1208 if (guardWord2 != 0x4DED) 1209 errln("Stack-allocated backing store overwrote guard word!"); 1210 1211 test->insert(24, "good "); 1212 if (*test != "Now is the time for all good men to come") 1213 errln("insert() on stack-allocated UnicodeString didn't work right"); 1214 if (guardWord2 != 0x4DED) 1215 errln("insert() on stack-allocated UnicodeString overwrote guard word!"); 1216 1217 if (workingBuffer[24] != 0x67) 1218 errln("insert() on stack-allocated UnicodeString didn't affect backing store"); 1219 1220 *test += " to the aid of their country."; 1221 if (*test != "Now is the time for all good men to come to the aid of their country.") 1222 errln("Stack-allocated UnicodeString overflow didn't work"); 1223 if (guardWord2 != 0x4DED) 1224 errln("Stack-allocated UnicodeString overflow overwrote guard word!"); 1225 1226 *test = "ha!"; 1227 if (*test != "ha!") 1228 errln("Assignment to stack-allocated UnicodeString didn't work"); 1229 if (workingBuffer[0] != 0x4e) 1230 errln("Change to UnicodeString after overflow are still affecting original buffer"); 1231 if (guardWord2 != 0x4DED) 1232 errln("Change to UnicodeString after overflow overwrote guard word!"); 1233 1234 // test read-only aliasing with setTo() 1235 workingBuffer[0] = 0x20ac; 1236 workingBuffer[1] = 0x125; 1237 workingBuffer[2] = 0; 1238 test->setTo(TRUE, workingBuffer, 2); 1239 if(test->length() != 2 || test->charAt(0) != 0x20ac || test->charAt(1) != 0x125) { 1240 errln("UnicodeString.setTo(readonly alias) does not alias correctly"); 1241 } 1242 1243 UnicodeString *c=(UnicodeString *)test->clone(); 1244 1245 workingBuffer[1] = 0x109; 1246 if(test->charAt(1) != 0x109) { 1247 errln("UnicodeString.setTo(readonly alias) made a copy: did not see change in buffer"); 1248 } 1249 1250 if(c->length() != 2 || c->charAt(1) != 0x125) { 1251 errln("clone(alias) did not copy the buffer"); 1252 } 1253 delete c; 1254 1255 test->setTo(TRUE, workingBuffer, -1); 1256 if(test->length() != 2 || test->charAt(0) != 0x20ac || test->charAt(1) != 0x109) { 1257 errln("UnicodeString.setTo(readonly alias, length -1) does not alias correctly"); 1258 } 1259 1260 test->setTo(FALSE, workingBuffer, -1); 1261 if(!test->isBogus()) { 1262 errln("UnicodeString.setTo(unterminated readonly alias, length -1) does not result in isBogus()"); 1263 } 1264 1265 delete test; 1266 1267 test=new UnicodeString(); 1268 UChar buffer[]={0x0061, 0x0062, 0x20ac, 0x0043, 0x0042, 0x0000}; 1269 test->setTo(buffer, 4, 10); 1270 if(test->length() !=4 || test->charAt(0) != 0x0061 || test->charAt(1) != 0x0062 || 1271 test->charAt(2) != 0x20ac || test->charAt(3) != 0x0043){ 1272 errln((UnicodeString)"UnicodeString.setTo(UChar*, length, capacity) does not work correctly\n" + prettify(*test)); 1273 } 1274 delete test; 1275 1276 1277 // test the UChar32 constructor 1278 UnicodeString c32Test((UChar32)0x10ff2a); 1279 if( c32Test.length() != U16_LENGTH(0x10ff2a) || 1280 c32Test.char32At(c32Test.length() - 1) != 0x10ff2a 1281 ) { 1282 errln("The UnicodeString(UChar32) constructor does not work with a 0x10ff2a filler"); 1283 } 1284 1285 // test the (new) capacity constructor 1286 UnicodeString capTest(5, (UChar32)0x2a, 5); 1287 if( capTest.length() != 5 * U16_LENGTH(0x2a) || 1288 capTest.char32At(0) != 0x2a || 1289 capTest.char32At(4) != 0x2a 1290 ) { 1291 errln("The UnicodeString capacity constructor does not work with an ASCII filler"); 1292 } 1293 1294 capTest = UnicodeString(5, (UChar32)0x10ff2a, 5); 1295 if( capTest.length() != 5 * U16_LENGTH(0x10ff2a) || 1296 capTest.char32At(0) != 0x10ff2a || 1297 capTest.char32At(4) != 0x10ff2a 1298 ) { 1299 errln("The UnicodeString capacity constructor does not work with a 0x10ff2a filler"); 1300 } 1301 1302 capTest = UnicodeString(5, (UChar32)0, 0); 1303 if(capTest.length() != 0) { 1304 errln("The UnicodeString capacity constructor does not work with a 0x10ff2a filler"); 1305 } 1306 } 1307 1308 /** 1309 * Test the unescape() function. 1310 */ 1311 void UnicodeStringTest::TestUnescape(void) { 1312 UnicodeString IN("abc\\u4567 \\n\\r \\U00101234xyz\\x1\\x{5289}\\x1b", -1, US_INV); 1313 UnicodeString OUT("abc"); 1314 OUT.append((UChar)0x4567); 1315 OUT.append(" "); 1316 OUT.append((UChar)0xA); 1317 OUT.append((UChar)0xD); 1318 OUT.append(" "); 1319 OUT.append((UChar32)0x00101234); 1320 OUT.append("xyz"); 1321 OUT.append((UChar32)1).append((UChar32)0x5289).append((UChar)0x1b); 1322 UnicodeString result = IN.unescape(); 1323 if (result != OUT) { 1324 errln("FAIL: " + prettify(IN) + ".unescape() -> " + 1325 prettify(result) + ", expected " + 1326 prettify(OUT)); 1327 } 1328 1329 // test that an empty string is returned in case of an error 1330 if (!UNICODE_STRING("wrong \\u sequence", 17).unescape().isEmpty()) { 1331 errln("FAIL: unescaping of a string with an illegal escape sequence did not return an empty string"); 1332 } 1333 } 1334 1335 /* test code point counting functions --------------------------------------- */ 1336 1337 /* reference implementation of UnicodeString::hasMoreChar32Than() */ 1338 static int32_t 1339 _refUnicodeStringHasMoreChar32Than(const UnicodeString &s, int32_t start, int32_t length, int32_t number) { 1340 int32_t count=s.countChar32(start, length); 1341 return count>number; 1342 } 1343 1344 /* compare the real function against the reference */ 1345 void 1346 UnicodeStringTest::_testUnicodeStringHasMoreChar32Than(const UnicodeString &s, int32_t start, int32_t length, int32_t number) { 1347 if(s.hasMoreChar32Than(start, length, number)!=_refUnicodeStringHasMoreChar32Than(s, start, length, number)) { 1348 errln("hasMoreChar32Than(%d, %d, %d)=%hd is wrong\n", 1349 start, length, number, s.hasMoreChar32Than(start, length, number)); 1350 } 1351 } 1352 1353 void 1354 UnicodeStringTest::TestCountChar32(void) { 1355 { 1356 UnicodeString s=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape(); 1357 1358 // test countChar32() 1359 // note that this also calls and tests u_countChar32(length>=0) 1360 if( 1361 s.countChar32()!=4 || 1362 s.countChar32(1)!=4 || 1363 s.countChar32(2)!=3 || 1364 s.countChar32(2, 3)!=2 || 1365 s.countChar32(2, 0)!=0 1366 ) { 1367 errln("UnicodeString::countChar32() failed"); 1368 } 1369 1370 // NUL-terminate the string buffer and test u_countChar32(length=-1) 1371 const UChar *buffer=s.getTerminatedBuffer(); 1372 if( 1373 u_countChar32(buffer, -1)!=4 || 1374 u_countChar32(buffer+1, -1)!=4 || 1375 u_countChar32(buffer+2, -1)!=3 || 1376 u_countChar32(buffer+3, -1)!=3 || 1377 u_countChar32(buffer+4, -1)!=2 || 1378 u_countChar32(buffer+5, -1)!=1 || 1379 u_countChar32(buffer+6, -1)!=0 1380 ) { 1381 errln("u_countChar32(length=-1) failed"); 1382 } 1383 1384 // test u_countChar32() with bad input 1385 if(u_countChar32(NULL, 5)!=0 || u_countChar32(buffer, -2)!=0) { 1386 errln("u_countChar32(bad input) failed (returned non-zero counts)"); 1387 } 1388 } 1389 1390 /* test data and variables for hasMoreChar32Than() */ 1391 static const UChar str[]={ 1392 0x61, 0x62, 0xd800, 0xdc00, 1393 0xd801, 0xdc01, 0x63, 0xd802, 1394 0x64, 0xdc03, 0x65, 0x66, 1395 0xd804, 0xdc04, 0xd805, 0xdc05, 1396 0x67 1397 }; 1398 UnicodeString string(str, LENGTHOF(str)); 1399 int32_t start, length, number; 1400 1401 /* test hasMoreChar32Than() */ 1402 for(length=string.length(); length>=0; --length) { 1403 for(start=0; start<=length; ++start) { 1404 for(number=-1; number<=((length-start)+2); ++number) { 1405 _testUnicodeStringHasMoreChar32Than(string, start, length-start, number); 1406 } 1407 } 1408 } 1409 1410 /* test hasMoreChar32Than() with pinning */ 1411 for(start=-1; start<=string.length()+1; ++start) { 1412 for(number=-1; number<=((string.length()-start)+2); ++number) { 1413 _testUnicodeStringHasMoreChar32Than(string, start, 0x7fffffff, number); 1414 } 1415 } 1416 1417 /* test hasMoreChar32Than() with a bogus string */ 1418 string.setToBogus(); 1419 for(length=-1; length<=1; ++length) { 1420 for(start=-1; start<=length; ++start) { 1421 for(number=-1; number<=((length-start)+2); ++number) { 1422 _testUnicodeStringHasMoreChar32Than(string, start, length-start, number); 1423 } 1424 } 1425 } 1426 } 1427 1428 void 1429 UnicodeStringTest::TestBogus() { 1430 UnicodeString test1("This is a test"); 1431 UnicodeString test2("This is a test"); 1432 UnicodeString test3("Me too!"); 1433 1434 // test isBogus() and setToBogus() 1435 if (test1.isBogus() || test2.isBogus() || test3.isBogus()) { 1436 errln("A string returned TRUE for isBogus()!"); 1437 } 1438 1439 // NULL pointers are treated like empty strings 1440 // use other illegal arguments to make a bogus string 1441 test3.setTo(FALSE, test1.getBuffer(), -2); 1442 if(!test3.isBogus()) { 1443 errln("A bogus string returned FALSE for isBogus()!"); 1444 } 1445 if (test1.hashCode() != test2.hashCode() || test1.hashCode() == test3.hashCode()) { 1446 errln("hashCode() failed"); 1447 } 1448 if(test3.getBuffer()!=0 || test3.getBuffer(20)!=0 || test3.getTerminatedBuffer()!=0) { 1449 errln("bogus.getBuffer()!=0"); 1450 } 1451 if (test1.indexOf(test3) != -1) { 1452 errln("bogus.indexOf() != -1"); 1453 } 1454 if (test1.lastIndexOf(test3) != -1) { 1455 errln("bogus.lastIndexOf() != -1"); 1456 } 1457 if (test1.caseCompare(test3, U_FOLD_CASE_DEFAULT) != 1 || test3.caseCompare(test1, U_FOLD_CASE_DEFAULT) != -1) { 1458 errln("caseCompare() doesn't work with bogus strings"); 1459 } 1460 if (test1.compareCodePointOrder(test3) != 1 || test3.compareCodePointOrder(test1) != -1) { 1461 errln("compareCodePointOrder() doesn't work with bogus strings"); 1462 } 1463 1464 // verify that non-assignment modifications fail and do not revive a bogus string 1465 test3.setToBogus(); 1466 test3.append((UChar)0x61); 1467 if(!test3.isBogus() || test3.getBuffer()!=0) { 1468 errln("bogus.append('a') worked but must not"); 1469 } 1470 1471 test3.setToBogus(); 1472 test3.findAndReplace(UnicodeString((UChar)0x61), test2); 1473 if(!test3.isBogus() || test3.getBuffer()!=0) { 1474 errln("bogus.findAndReplace() worked but must not"); 1475 } 1476 1477 test3.setToBogus(); 1478 test3.trim(); 1479 if(!test3.isBogus() || test3.getBuffer()!=0) { 1480 errln("bogus.trim() revived bogus but must not"); 1481 } 1482 1483 test3.setToBogus(); 1484 test3.remove(1); 1485 if(!test3.isBogus() || test3.getBuffer()!=0) { 1486 errln("bogus.remove(1) revived bogus but must not"); 1487 } 1488 1489 test3.setToBogus(); 1490 if(!test3.setCharAt(0, 0x62).isBogus() || !test3.isEmpty()) { 1491 errln("bogus.setCharAt(0, 'b') worked but must not"); 1492 } 1493 1494 test3.setToBogus(); 1495 if(test3.truncate(1) || !test3.isBogus() || !test3.isEmpty()) { 1496 errln("bogus.truncate(1) revived bogus but must not"); 1497 } 1498 1499 // verify that assignments revive a bogus string 1500 test3.setToBogus(); 1501 if(!test3.isBogus() || (test3=test1).isBogus() || test3!=test1) { 1502 errln("bogus.operator=() failed"); 1503 } 1504 1505 test3.setToBogus(); 1506 if(!test3.isBogus() || test3.fastCopyFrom(test1).isBogus() || test3!=test1) { 1507 errln("bogus.fastCopyFrom() failed"); 1508 } 1509 1510 test3.setToBogus(); 1511 if(!test3.isBogus() || test3.setTo(test1).isBogus() || test3!=test1) { 1512 errln("bogus.setTo(UniStr) failed"); 1513 } 1514 1515 test3.setToBogus(); 1516 if(!test3.isBogus() || test3.setTo(test1, 0).isBogus() || test3!=test1) { 1517 errln("bogus.setTo(UniStr, 0) failed"); 1518 } 1519 1520 test3.setToBogus(); 1521 if(!test3.isBogus() || test3.setTo(test1, 0, 0x7fffffff).isBogus() || test3!=test1) { 1522 errln("bogus.setTo(UniStr, 0, len) failed"); 1523 } 1524 1525 test3.setToBogus(); 1526 if(!test3.isBogus() || test3.setTo(test1.getBuffer(), test1.length()).isBogus() || test3!=test1) { 1527 errln("bogus.setTo(const UChar *, len) failed"); 1528 } 1529 1530 test3.setToBogus(); 1531 if(!test3.isBogus() || test3.setTo((UChar)0x2028).isBogus() || test3!=UnicodeString((UChar)0x2028)) { 1532 errln("bogus.setTo(UChar) failed"); 1533 } 1534 1535 test3.setToBogus(); 1536 if(!test3.isBogus() || test3.setTo((UChar32)0x1d157).isBogus() || test3!=UnicodeString((UChar32)0x1d157)) { 1537 errln("bogus.setTo(UChar32) failed"); 1538 } 1539 1540 test3.setToBogus(); 1541 if(!test3.isBogus() || test3.setTo(FALSE, test1.getBuffer(), test1.length()).isBogus() || test3!=test1) { 1542 errln("bogus.setTo(readonly alias) failed"); 1543 } 1544 1545 // writable alias to another string's buffer: very bad idea, just convenient for this test 1546 test3.setToBogus(); 1547 if(!test3.isBogus() || test3.setTo((UChar *)test1.getBuffer(), test1.length(), test1.getCapacity()).isBogus() || test3!=test1) { 1548 errln("bogus.setTo(writable alias) failed"); 1549 } 1550 1551 // verify simple, documented ways to turn a bogus string into an empty one 1552 test3.setToBogus(); 1553 if(!test3.isBogus() || (test3=UnicodeString()).isBogus() || !test3.isEmpty()) { 1554 errln("bogus.operator=(UnicodeString()) failed"); 1555 } 1556 1557 test3.setToBogus(); 1558 if(!test3.isBogus() || test3.setTo(UnicodeString()).isBogus() || !test3.isEmpty()) { 1559 errln("bogus.setTo(UnicodeString()) failed"); 1560 } 1561 1562 test3.setToBogus(); 1563 if(test3.remove().isBogus() || test3.getBuffer()==0 || !test3.isEmpty()) { 1564 errln("bogus.remove() failed"); 1565 } 1566 1567 test3.setToBogus(); 1568 if(test3.remove(0, INT32_MAX).isBogus() || test3.getBuffer()==0 || !test3.isEmpty()) { 1569 errln("bogus.remove(0, INT32_MAX) failed"); 1570 } 1571 1572 test3.setToBogus(); 1573 if(test3.truncate(0) || test3.isBogus() || !test3.isEmpty()) { 1574 errln("bogus.truncate(0) failed"); 1575 } 1576 1577 test3.setToBogus(); 1578 if(!test3.isBogus() || test3.setTo((UChar32)-1).isBogus() || !test3.isEmpty()) { 1579 errln("bogus.setTo((UChar32)-1) failed"); 1580 } 1581 1582 static const UChar nul=0; 1583 1584 test3.setToBogus(); 1585 if(!test3.isBogus() || test3.setTo(&nul, 0).isBogus() || !test3.isEmpty()) { 1586 errln("bogus.setTo(&nul, 0) failed"); 1587 } 1588 1589 test3.setToBogus(); 1590 if(!test3.isBogus() || test3.getBuffer()!=0) { 1591 errln("setToBogus() failed to make a string bogus"); 1592 } 1593 1594 test3.setToBogus(); 1595 if(test1.isBogus() || !(test1=test3).isBogus()) { 1596 errln("normal=bogus failed to make the left string bogus"); 1597 } 1598 1599 // test that NULL primitive input string values are treated like 1600 // empty strings, not errors (bogus) 1601 test2.setTo((UChar32)0x10005); 1602 if(test2.insert(1, NULL, 1).length()!=2) { 1603 errln("UniStr.insert(...NULL...) should not modify the string but does"); 1604 } 1605 1606 UErrorCode errorCode=U_ZERO_ERROR; 1607 UnicodeString 1608 test4((const UChar *)NULL), 1609 test5(TRUE, (const UChar *)NULL, 1), 1610 test6((UChar *)NULL, 5, 5), 1611 test7((const char *)NULL, 3, NULL, errorCode); 1612 if(test4.isBogus() || test5.isBogus() || test6.isBogus() || test7.isBogus()) { 1613 errln("a constructor set to bogus for a NULL input string, should be empty"); 1614 } 1615 1616 test4.setTo(NULL, 3); 1617 test5.setTo(TRUE, (const UChar *)NULL, 1); 1618 test6.setTo((UChar *)NULL, 5, 5); 1619 if(test4.isBogus() || test5.isBogus() || test6.isBogus()) { 1620 errln("a setTo() set to bogus for a NULL input string, should be empty"); 1621 } 1622 1623 // test that bogus==bogus<any 1624 if(test1!=test3 || test1.compare(test3)!=0) { 1625 errln("bogus==bogus failed"); 1626 } 1627 1628 test2.remove(); 1629 if(test1>=test2 || !(test2>test1) || test1.compare(test2)>=0 || !(test2.compare(test1)>0)) { 1630 errln("bogus<empty failed"); 1631 } 1632 } 1633 1634 // StringEnumeration ------------------------------------------------------- *** 1635 // most of StringEnumeration is tested elsewhere 1636 // this test improves code coverage 1637 1638 static const char *const 1639 testEnumStrings[]={ 1640 "a", 1641 "b", 1642 "c", 1643 "this is a long string which helps us test some buffer limits", 1644 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" 1645 }; 1646 1647 class TestEnumeration : public StringEnumeration { 1648 public: 1649 TestEnumeration() : i(0) {} 1650 1651 virtual int32_t count(UErrorCode& /*status*/) const { 1652 return LENGTHOF(testEnumStrings); 1653 } 1654 1655 virtual const UnicodeString *snext(UErrorCode &status) { 1656 if(U_SUCCESS(status) && i<LENGTHOF(testEnumStrings)) { 1657 unistr=UnicodeString(testEnumStrings[i++], ""); 1658 return &unistr; 1659 } 1660 1661 return NULL; 1662 } 1663 1664 virtual void reset(UErrorCode& /*status*/) { 1665 i=0; 1666 } 1667 1668 static inline UClassID getStaticClassID() { 1669 return (UClassID)&fgClassID; 1670 } 1671 virtual UClassID getDynamicClassID() const { 1672 return getStaticClassID(); 1673 } 1674 1675 private: 1676 static const char fgClassID; 1677 1678 int32_t i, length; 1679 }; 1680 1681 const char TestEnumeration::fgClassID=0; 1682 1683 void 1684 UnicodeStringTest::TestStringEnumeration() { 1685 UnicodeString s; 1686 TestEnumeration ten; 1687 int32_t i, length; 1688 UErrorCode status; 1689 1690 const UChar *pu; 1691 const char *pc; 1692 1693 // test the next() default implementation and ensureCharsCapacity() 1694 for(i=0; i<LENGTHOF(testEnumStrings); ++i) { 1695 status=U_ZERO_ERROR; 1696 pc=ten.next(&length, status); 1697 s=UnicodeString(testEnumStrings[i], ""); 1698 if(U_FAILURE(status) || pc==NULL || length!=s.length() || UnicodeString(pc, length, "")!=s) { 1699 errln("StringEnumeration.next(%d) failed", i); 1700 } 1701 } 1702 status=U_ZERO_ERROR; 1703 if(ten.next(&length, status)!=NULL) { 1704 errln("StringEnumeration.next(done)!=NULL"); 1705 } 1706 1707 // test the unext() default implementation 1708 ten.reset(status); 1709 for(i=0; i<LENGTHOF(testEnumStrings); ++i) { 1710 status=U_ZERO_ERROR; 1711 pu=ten.unext(&length, status); 1712 s=UnicodeString(testEnumStrings[i], ""); 1713 if(U_FAILURE(status) || pu==NULL || length!=s.length() || UnicodeString(TRUE, pu, length)!=s) { 1714 errln("StringEnumeration.unext(%d) failed", i); 1715 } 1716 } 1717 status=U_ZERO_ERROR; 1718 if(ten.unext(&length, status)!=NULL) { 1719 errln("StringEnumeration.unext(done)!=NULL"); 1720 } 1721 1722 // test that the default clone() implementation works, and returns NULL 1723 if(ten.clone()!=NULL) { 1724 errln("StringEnumeration.clone()!=NULL"); 1725 } 1726 1727 // test that uenum_openFromStringEnumeration() works 1728 // Need a heap allocated string enumeration because it is adopted by the UEnumeration. 1729 StringEnumeration *newTen = new TestEnumeration; 1730 status=U_ZERO_ERROR; 1731 UEnumeration *uten = uenum_openFromStringEnumeration(newTen, &status); 1732 if (uten==NULL || U_FAILURE(status)) { 1733 errln("fail at file %s, line %d, UErrorCode is %s\n", __FILE__, __LINE__, u_errorName(status)); 1734 return; 1735 } 1736 1737 // test uenum_next() 1738 for(i=0; i<LENGTHOF(testEnumStrings); ++i) { 1739 status=U_ZERO_ERROR; 1740 pc=uenum_next(uten, &length, &status); 1741 if(U_FAILURE(status) || pc==NULL || strcmp(pc, testEnumStrings[i]) != 0) { 1742 errln("File %s, line %d, StringEnumeration.next(%d) failed", __FILE__, __LINE__, i); 1743 } 1744 } 1745 status=U_ZERO_ERROR; 1746 if(uenum_next(uten, &length, &status)!=NULL) { 1747 errln("File %s, line %d, uenum_next(done)!=NULL"); 1748 } 1749 1750 // test the uenum_unext() 1751 uenum_reset(uten, &status); 1752 for(i=0; i<LENGTHOF(testEnumStrings); ++i) { 1753 status=U_ZERO_ERROR; 1754 pu=uenum_unext(uten, &length, &status); 1755 s=UnicodeString(testEnumStrings[i], ""); 1756 if(U_FAILURE(status) || pu==NULL || length!=s.length() || UnicodeString(TRUE, pu, length)!=s) { 1757 errln("File %s, Line %d, uenum_unext(%d) failed", __FILE__, __LINE__, i); 1758 } 1759 } 1760 status=U_ZERO_ERROR; 1761 if(uenum_unext(uten, &length, &status)!=NULL) { 1762 errln("File %s, Line %d, uenum_unext(done)!=NULL" __FILE__, __LINE__); 1763 } 1764 1765 uenum_close(uten); 1766 } 1767 1768 /* 1769 * Namespace test, to make sure that macros like UNICODE_STRING include the 1770 * namespace qualifier. 1771 * 1772 * Define a (bogus) UnicodeString class in another namespace and check for ambiguity. 1773 */ 1774 namespace bogus { 1775 class UnicodeString { 1776 public: 1777 enum EInvariant { kInvariant }; 1778 UnicodeString() : i(1) {} 1779 UnicodeString(UBool /*isTerminated*/, const UChar * /*text*/, int32_t textLength) : i(textLength) {} 1780 UnicodeString(const char * /*src*/, int32_t length, enum EInvariant /*inv*/ 1781 ) : i(length) {} 1782 private: 1783 int32_t i; 1784 }; 1785 } 1786 1787 void 1788 UnicodeStringTest::TestNameSpace() { 1789 // Provoke name collision unless the UnicodeString macros properly 1790 // qualify the icu::UnicodeString class. 1791 using namespace bogus; 1792 1793 // Use all UnicodeString macros from unistr.h. 1794 icu::UnicodeString s1=icu::UnicodeString("abc", 3, US_INV); 1795 icu::UnicodeString s2=UNICODE_STRING("def", 3); 1796 icu::UnicodeString s3=UNICODE_STRING_SIMPLE("ghi"); 1797 1798 // Make sure the compiler does not optimize away instantiation of s1, s2, s3. 1799 icu::UnicodeString s4=s1+s2+s3; 1800 if(s4.length()!=9) { 1801 errln("Something wrong with UnicodeString::operator+()."); 1802 } 1803 } 1804 1805 void 1806 UnicodeStringTest::TestUTF32() { 1807 // Input string length US_STACKBUF_SIZE to cause overflow of the 1808 // initially chosen fStackBuffer due to supplementary characters. 1809 static const UChar32 utf32[] = { 1810 0x41, 0xd900, 0x61, 0xdc00, -1, 0x110000, 0x5a, 0x50000, 0x7a, 1811 0x10000, 0x20000, 0xe0000, 0x10ffff 1812 }; 1813 static const UChar expected_utf16[] = { 1814 0x41, 0xfffd, 0x61, 0xfffd, 0xfffd, 0xfffd, 0x5a, 0xd900, 0xdc00, 0x7a, 1815 0xd800, 0xdc00, 0xd840, 0xdc00, 0xdb40, 0xdc00, 0xdbff, 0xdfff 1816 }; 1817 UnicodeString from32 = UnicodeString::fromUTF32(utf32, LENGTHOF(utf32)); 1818 UnicodeString expected(FALSE, expected_utf16, LENGTHOF(expected_utf16)); 1819 if(from32 != expected) { 1820 errln("UnicodeString::fromUTF32() did not create the expected string."); 1821 } 1822 1823 static const UChar utf16[] = { 1824 0x41, 0xd900, 0x61, 0xdc00, 0x5a, 0xd900, 0xdc00, 0x7a, 0xd800, 0xdc00, 0xdbff, 0xdfff 1825 }; 1826 static const UChar32 expected_utf32[] = { 1827 0x41, 0xfffd, 0x61, 0xfffd, 0x5a, 0x50000, 0x7a, 0x10000, 0x10ffff 1828 }; 1829 UChar32 result32[16]; 1830 UErrorCode errorCode = U_ZERO_ERROR; 1831 int32_t length32 = 1832 UnicodeString(FALSE, utf16, LENGTHOF(utf16)). 1833 toUTF32(result32, LENGTHOF(result32), errorCode); 1834 if( length32 != LENGTHOF(expected_utf32) || 1835 0 != uprv_memcmp(result32, expected_utf32, length32*4) || 1836 result32[length32] != 0 1837 ) { 1838 errln("UnicodeString::toUTF32() did not create the expected string."); 1839 } 1840 } 1841 1842 class TestCheckedArrayByteSink : public CheckedArrayByteSink { 1843 public: 1844 TestCheckedArrayByteSink(char* outbuf, int32_t capacity) 1845 : CheckedArrayByteSink(outbuf, capacity), calledFlush(FALSE) {} 1846 virtual void Flush() { calledFlush = TRUE; } 1847 UBool calledFlush; 1848 }; 1849 1850 void 1851 UnicodeStringTest::TestUTF8() { 1852 static const uint8_t utf8[] = { 1853 // Code points: 1854 // 0x41, 0xd900, 1855 // 0x61, 0xdc00, 1856 // 0x110000, 0x5a, 1857 // 0x50000, 0x7a, 1858 // 0x10000, 0x20000, 1859 // 0xe0000, 0x10ffff 1860 0x41, 0xed, 0xa4, 0x80, 1861 0x61, 0xed, 0xb0, 0x80, 1862 0xf4, 0x90, 0x80, 0x80, 0x5a, 1863 0xf1, 0x90, 0x80, 0x80, 0x7a, 1864 0xf0, 0x90, 0x80, 0x80, 0xf0, 0xa0, 0x80, 0x80, 1865 0xf3, 0xa0, 0x80, 0x80, 0xf4, 0x8f, 0xbf, 0xbf 1866 }; 1867 static const UChar expected_utf16[] = { 1868 0x41, 0xfffd, 1869 0x61, 0xfffd, 1870 0xfffd, 0x5a, 1871 0xd900, 0xdc00, 0x7a, 1872 0xd800, 0xdc00, 0xd840, 0xdc00, 1873 0xdb40, 0xdc00, 0xdbff, 0xdfff 1874 }; 1875 UnicodeString from8 = UnicodeString::fromUTF8(StringPiece((const char *)utf8, (int32_t)sizeof(utf8))); 1876 UnicodeString expected(FALSE, expected_utf16, LENGTHOF(expected_utf16)); 1877 1878 if(from8 != expected) { 1879 errln("UnicodeString::fromUTF8(StringPiece) did not create the expected string."); 1880 } 1881 #if U_HAVE_STD_STRING 1882 std::string utf8_string((const char *)utf8, sizeof(utf8)); 1883 UnicodeString from8b = UnicodeString::fromUTF8(utf8_string); 1884 if(from8b != expected) { 1885 errln("UnicodeString::fromUTF8(std::string) did not create the expected string."); 1886 } 1887 #endif 1888 1889 static const UChar utf16[] = { 1890 0x41, 0xd900, 0x61, 0xdc00, 0x5a, 0xd900, 0xdc00, 0x7a, 0xd800, 0xdc00, 0xdbff, 0xdfff 1891 }; 1892 static const uint8_t expected_utf8[] = { 1893 0x41, 0xef, 0xbf, 0xbd, 0x61, 0xef, 0xbf, 0xbd, 0x5a, 0xf1, 0x90, 0x80, 0x80, 0x7a, 1894 0xf0, 0x90, 0x80, 0x80, 0xf4, 0x8f, 0xbf, 0xbf 1895 }; 1896 UnicodeString us(FALSE, utf16, LENGTHOF(utf16)); 1897 1898 char buffer[64]; 1899 TestCheckedArrayByteSink sink(buffer, (int32_t)sizeof(buffer)); 1900 us.toUTF8(sink); 1901 if( sink.NumberOfBytesWritten() != (int32_t)sizeof(expected_utf8) || 1902 0 != uprv_memcmp(buffer, expected_utf8, sizeof(expected_utf8)) 1903 ) { 1904 errln("UnicodeString::toUTF8() did not create the expected string."); 1905 } 1906 if(!sink.calledFlush) { 1907 errln("UnicodeString::toUTF8(sink) did not sink.Flush()."); 1908 } 1909 #if U_HAVE_STD_STRING 1910 // Initial contents for testing that toUTF8String() appends. 1911 std::string result8 = "-->"; 1912 std::string expected8 = "-->" + std::string((const char *)expected_utf8, sizeof(expected_utf8)); 1913 // Use the return value just for testing. 1914 std::string &result8r = us.toUTF8String(result8); 1915 if(result8r != expected8 || &result8r != &result8) { 1916 errln("UnicodeString::toUTF8String() did not create the expected string."); 1917 } 1918 #endif 1919 } 1920 1921 // Test if this compiler supports Return Value Optimization of unnamed temporary objects. 1922 static UnicodeString wrapUChars(const UChar *uchars) { 1923 return UnicodeString(TRUE, uchars, -1); 1924 } 1925 1926 void 1927 UnicodeStringTest::TestReadOnlyAlias() { 1928 UChar uchars[]={ 0x61, 0x62, 0 }; 1929 UnicodeString alias(TRUE, uchars, 2); 1930 if(alias.length()!=2 || alias.getBuffer()!=uchars || alias.getTerminatedBuffer()!=uchars) { 1931 errln("UnicodeString read-only-aliasing constructor does not behave as expected."); 1932 return; 1933 } 1934 alias.truncate(1); 1935 if(alias.length()!=1 || alias.getBuffer()!=uchars) { 1936 errln("UnicodeString(read-only-alias).truncate() did not preserve aliasing as expected."); 1937 } 1938 if(alias.getTerminatedBuffer()==uchars) { 1939 errln("UnicodeString(read-only-alias).truncate().getTerminatedBuffer() " 1940 "did not allocate and copy as expected."); 1941 } 1942 if(uchars[1]!=0x62) { 1943 errln("UnicodeString(read-only-alias).truncate().getTerminatedBuffer() " 1944 "modified the original buffer."); 1945 } 1946 if(1!=u_strlen(alias.getTerminatedBuffer())) { 1947 errln("UnicodeString(read-only-alias).truncate().getTerminatedBuffer() " 1948 "does not return a buffer terminated at the proper length."); 1949 } 1950 1951 alias.setTo(TRUE, uchars, 2); 1952 if(alias.length()!=2 || alias.getBuffer()!=uchars || alias.getTerminatedBuffer()!=uchars) { 1953 errln("UnicodeString read-only-aliasing setTo() does not behave as expected."); 1954 return; 1955 } 1956 alias.remove(); 1957 if(alias.length()!=0) { 1958 errln("UnicodeString(read-only-alias).remove() did not work."); 1959 } 1960 if(alias.getTerminatedBuffer()==uchars) { 1961 errln("UnicodeString(read-only-alias).remove().getTerminatedBuffer() " 1962 "did not un-alias as expected."); 1963 } 1964 if(uchars[0]!=0x61) { 1965 errln("UnicodeString(read-only-alias).remove().getTerminatedBuffer() " 1966 "modified the original buffer."); 1967 } 1968 if(0!=u_strlen(alias.getTerminatedBuffer())) { 1969 errln("UnicodeString.setTo(read-only-alias).remove().getTerminatedBuffer() " 1970 "does not return a buffer terminated at length 0."); 1971 } 1972 1973 UnicodeString longString=UNICODE_STRING_SIMPLE("abcdefghijklmnopqrstuvwxyz0123456789"); 1974 alias.setTo(FALSE, longString.getBuffer(), longString.length()); 1975 alias.remove(0, 10); 1976 if(longString.compare(10, INT32_MAX, alias)!=0 || alias.getBuffer()!=longString.getBuffer()+10) { 1977 errln("UnicodeString.setTo(read-only-alias).remove(0, 10) did not preserve aliasing as expected."); 1978 } 1979 alias.setTo(FALSE, longString.getBuffer(), longString.length()); 1980 alias.remove(27, 99); 1981 if(longString.compare(0, 27, alias)!=0 || alias.getBuffer()!=longString.getBuffer()) { 1982 errln("UnicodeString.setTo(read-only-alias).remove(27, 99) did not preserve aliasing as expected."); 1983 } 1984 alias.setTo(FALSE, longString.getBuffer(), longString.length()); 1985 alias.retainBetween(6, 30); 1986 if(longString.compare(6, 24, alias)!=0 || alias.getBuffer()!=longString.getBuffer()+6) { 1987 errln("UnicodeString.setTo(read-only-alias).retainBetween(6, 30) did not preserve aliasing as expected."); 1988 } 1989 1990 UChar abc[]={ 0x61, 0x62, 0x63, 0 }; 1991 UBool hasRVO= wrapUChars(abc).getBuffer()==abc; 1992 1993 UnicodeString temp; 1994 temp.fastCopyFrom(longString.tempSubString()); 1995 if(temp!=longString || (hasRVO && temp.getBuffer()!=longString.getBuffer())) { 1996 errln("UnicodeString.tempSubString() failed"); 1997 } 1998 temp.fastCopyFrom(longString.tempSubString(-3, 5)); 1999 if(longString.compare(0, 5, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer())) { 2000 errln("UnicodeString.tempSubString(-3, 5) failed"); 2001 } 2002 temp.fastCopyFrom(longString.tempSubString(17)); 2003 if(longString.compare(17, INT32_MAX, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer()+17)) { 2004 errln("UnicodeString.tempSubString(17) failed"); 2005 } 2006 temp.fastCopyFrom(longString.tempSubString(99)); 2007 if(!temp.isEmpty()) { 2008 errln("UnicodeString.tempSubString(99) failed"); 2009 } 2010 temp.fastCopyFrom(longString.tempSubStringBetween(6)); 2011 if(longString.compare(6, INT32_MAX, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer()+6)) { 2012 errln("UnicodeString.tempSubStringBetween(6) failed"); 2013 } 2014 temp.fastCopyFrom(longString.tempSubStringBetween(8, 18)); 2015 if(longString.compare(8, 10, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer()+8)) { 2016 errln("UnicodeString.tempSubStringBetween(8, 18) failed"); 2017 } 2018 UnicodeString bogusString; 2019 bogusString.setToBogus(); 2020 temp.fastCopyFrom(bogusString.tempSubStringBetween(8, 18)); 2021 if(!temp.isBogus()) { 2022 errln("UnicodeString.setToBogus().tempSubStringBetween(8, 18) failed"); 2023 } 2024 } 2025 2026 void 2027 UnicodeStringTest::doTestAppendable(UnicodeString &dest, Appendable &app) { 2028 static const UChar cde[3]={ 0x63, 0x64, 0x65 }; 2029 static const UChar fg[3]={ 0x66, 0x67, 0 }; 2030 if(!app.reserveAppendCapacity(12)) { 2031 errln("Appendable.reserve(12) failed"); 2032 } 2033 app.appendCodeUnit(0x61); 2034 app.appendCodePoint(0x62); 2035 app.appendCodePoint(0x50000); 2036 app.appendString(cde, 3); 2037 app.appendString(fg, -1); 2038 UChar scratch[3]; 2039 int32_t capacity=-1; 2040 UChar *buffer=app.getAppendBuffer(3, 3, scratch, 3, &capacity); 2041 if(capacity<3) { 2042 errln("Appendable.getAppendBuffer(min=3) returned capacity=%d<3", (int)capacity); 2043 return; 2044 } 2045 static const UChar hij[3]={ 0x68, 0x69, 0x6a }; 2046 u_memcpy(buffer, hij, 3); 2047 app.appendString(buffer, 3); 2048 if(dest!=UNICODE_STRING_SIMPLE("ab\\U00050000cdefghij").unescape()) { 2049 errln("Appendable.append(...) failed"); 2050 } 2051 buffer=app.getAppendBuffer(0, 3, scratch, 3, &capacity); 2052 if(buffer!=NULL || capacity!=0) { 2053 errln("Appendable.getAppendBuffer(min=0) failed"); 2054 } 2055 capacity=1; 2056 buffer=app.getAppendBuffer(3, 3, scratch, 2, &capacity); 2057 if(buffer!=NULL || capacity!=0) { 2058 errln("Appendable.getAppendBuffer(scratch<min) failed"); 2059 } 2060 } 2061 2062 class SimpleAppendable : public Appendable { 2063 public: 2064 explicit SimpleAppendable(UnicodeString &dest) : str(dest) {} 2065 virtual UBool appendCodeUnit(UChar c) { str.append(c); return TRUE; } 2066 SimpleAppendable &reset() { str.remove(); return *this; } 2067 private: 2068 UnicodeString &str; 2069 }; 2070 2071 void 2072 UnicodeStringTest::TestAppendable() { 2073 UnicodeString dest; 2074 SimpleAppendable app(dest); 2075 doTestAppendable(dest, app); 2076 } 2077 2078 void 2079 UnicodeStringTest::TestUnicodeStringImplementsAppendable() { 2080 UnicodeString dest; 2081 UnicodeStringAppendable app(dest); 2082 doTestAppendable(dest, app); 2083 } 2084 2085 void 2086 UnicodeStringTest::TestSizeofUnicodeString() { 2087 // See the comments in unistr.h near the declaration of UnicodeString's fields. 2088 size_t sizeofUniStr=sizeof(UnicodeString); 2089 size_t expected; 2090 switch(sizeof(void *)) { 2091 case 4: 2092 expected=32; 2093 break; 2094 case 8: 2095 expected=40; 2096 break; 2097 default: 2098 logln("This platform has neither 32-bit nor 64-bit pointers."); 2099 return; 2100 } 2101 if(expected!=sizeofUniStr) { 2102 errln("sizeof(UnicodeString)=%d, expected %d", (int)sizeofUniStr, (int)expected); 2103 } 2104 } 2105