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