• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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