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