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