~ubuntu-branches/ubuntu/precise/icu/precise

« back to all changes in this revision

Viewing changes to source/test/intltest/ustrtest.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2009-09-04 11:56:06 UTC
  • mfrom: (10.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20090904115606-sqxxuizelam5tozb
Tags: 4.2.1-3
Change install-doc target to not fail if there are subdirectories of
doc/html.  This is necessary to handle the doc/html/search directory
created by doxygen 3.6.1.  (Closes: #544799)

Show diffs side-by-side

added added

removed removed

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