]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/ustrtest.cpp
ICU-531.30.tar.gz
[apple/icu.git] / icuSources / test / intltest / ustrtest.cpp
CommitLineData
b75a7d8f
A
1/********************************************************************
2 * COPYRIGHT:
57a6839d 3 * Copyright (c) 1997-2013, International Business Machines Corporation and
b75a7d8f
A
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7#include "ustrtest.h"
4388f060 8#include "unicode/appendable.h"
729e4ab9 9#include "unicode/std_string.h"
b75a7d8f
A
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"
729e4ab9 15#include "unicode/uenum.h"
4388f060 16#include "unicode/utf16.h"
b75a7d8f 17#include "cmemory.h"
73c04bcf 18#include "charstr.h"
b75a7d8f
A
19
20#if 0
21#include "unicode/ustream.h"
22
b75a7d8f
A
23#include <iostream>
24using namespace std;
b75a7d8f
A
25
26#endif
27
374ca955
A
28#define LENGTHOF(array) (int32_t)((sizeof(array)/sizeof((array)[0])))
29
30UnicodeStringTest::~UnicodeStringTest() {}
b75a7d8f
A
31
32void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char *par)
33{
34 if (exec) logln("TestSuite UnicodeStringTest: ");
35 switch (index) {
374ca955 36 case 0:
b75a7d8f
A
37 name = "StringCaseTest";
38 if (exec) {
39 logln("StringCaseTest---"); logln("");
40 StringCaseTest test;
41 callTest(test, par);
42 }
43 break;
374ca955
A
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;
b75a7d8f
A
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;
374ca955 58 case 15: name = "TestStringEnumeration"; if (exec) TestStringEnumeration(); break;
729e4ab9
A
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;
4388f060
A
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;
b75a7d8f
A
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)
51004dcb 116 errln(UnicodeString("length() failed: expected 70, got ") + test1.length());
b75a7d8f 117 if (test2.length() != 30)
51004dcb 118 errln(UnicodeString("length() failed: expected 30, got ") + test2.length());
b75a7d8f
A
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){
51004dcb 126 errln(UnicodeString("append or length failed for UChar32, expected 2, got ") + test3.length());
b75a7d8f
A
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
374ca955
A
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 }
73c04bcf
A
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 }
374ca955
A
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);
46f4442e 234 if(v!=CharsToUnicodeString("a\\xe4\\x85")) {
374ca955
A
235 errln("UnicodeString(const char *, length, cnv, errorCode) does not work with length==-1");
236 }
237 }
729e4ab9
A
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
b75a7d8f
A
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 }
374ca955
A
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
b75a7d8f
A
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 }
73c04bcf
A
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 }
b75a7d8f
A
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)
51004dcb
A
724 errln(UnicodeString("indexOf failed: expected to find 6 occurrences, found ") + occurrences);
725
b75a7d8f
A
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)
51004dcb
A
731 errln(UnicodeString("indexOf with starting offset failed: "
732 "expected to find 4 occurrences, found ") + occurrences);
b75a7d8f
A
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)
51004dcb
A
740 errln(UnicodeString("indexOf with starting and ending offsets failed: "
741 "expected to find 4 occurrences, found ") + occurrences);
b75a7d8f
A
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)
51004dcb 756 errln(UnicodeString("indexOf failed: expected to find 2 occurrences, found ") + occurrences);
b75a7d8f
A
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)
51004dcb
A
764 errln(UnicodeString("indexOf with character failed: "
765 "expected to find 16 occurrences, found ") + occurrences);
b75a7d8f
A
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)
51004dcb
A
772 errln(UnicodeString("indexOf with character & start offset failed: "
773 "expected to find 12 occurrences, found ") + occurrences);
b75a7d8f
A
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)
51004dcb
A
780 errln(UnicodeString("indexOf with character & start & end offsets failed: "
781 "expected to find 10 occurrences, found ") + occurrences);
b75a7d8f
A
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)
51004dcb
A
824 errln(UnicodeString("lastIndexOf with starting and ending offsets failed: "
825 "expected to find 4 occurrences, found ") + occurrences);
b75a7d8f
A
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)
51004dcb
A
832 errln(UnicodeString("lastIndexOf with character & start & end offsets failed: "
833 "expected to find 11 occurrences, found ") + occurrences);
b75a7d8f
A
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
46f4442e
A
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 }
b75a7d8f
A
976}
977
4388f060
A
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
b75a7d8f
A
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 }
729e4ab9
A
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 }
b75a7d8f
A
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 }
729e4ab9
A
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 }
57a6839d
A
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()));
b75a7d8f
A
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);
4388f060 1294 if( c32Test.length() != U16_LENGTH(0x10ff2a) ||
b75a7d8f
A
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);
4388f060 1302 if( capTest.length() != 5 * U16_LENGTH(0x2a) ||
b75a7d8f
A
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);
4388f060 1310 if( capTest.length() != 5 * U16_LENGTH(0x10ff2a) ||
b75a7d8f
A
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) {
46f4442e 1327 UnicodeString IN("abc\\u4567 \\n\\r \\U00101234xyz\\x1\\x{5289}\\x1b", -1, US_INV);
b75a7d8f
A
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 }
46f4442e
A
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 }
b75a7d8f
A
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}
374ca955
A
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
57a6839d 1693 int32_t i;
374ca955
A
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 }
73c04bcf 1741
729e4ab9
A
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;
73c04bcf 1750 }
729e4ab9
A
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);
73c04bcf
A
1781}
1782
46f4442e
A
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 */
46f4442e
A
1789namespace bogus {
1790 class UnicodeString {
1791 public:
1792 enum EInvariant { kInvariant };
1793 UnicodeString() : i(1) {}
57a6839d 1794 UnicodeString(UBool /*isTerminated*/, const UChar * /*text*/, int32_t textLength) : i(textLength) {(void)i;}
46f4442e
A
1795 UnicodeString(const char * /*src*/, int32_t length, enum EInvariant /*inv*/
1796) : i(length) {}
1797 private:
1798 int32_t i;
1799 };
1800}
46f4442e
A
1801
1802void
1803UnicodeStringTest::TestNameSpace() {
46f4442e
A
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 }
46f4442e 1818}
729e4ab9
A
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
4388f060 1897 std::string utf8_string((const char *)utf8, sizeof(utf8));
729e4ab9
A
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.
4388f060
A
1926 std::string result8 = "-->";
1927 std::string expected8 = "-->" + std::string((const char *)expected_utf8, sizeof(expected_utf8));
729e4ab9 1928 // Use the return value just for testing.
4388f060 1929 std::string &result8r = us.toUTF8String(result8);
729e4ab9
A
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}
4388f060
A
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}