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