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