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