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