]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/ustrtest.cpp
ICU-551.24.tar.gz
[apple/icu.git] / icuSources / test / intltest / ustrtest.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7 #include "ustrtest.h"
8 #include "unicode/appendable.h"
9 #include "unicode/std_string.h"
10 #include "unicode/unistr.h"
11 #include "unicode/uchar.h"
12 #include "unicode/ustring.h"
13 #include "unicode/locid.h"
14 #include "unicode/ucnv.h"
15 #include "unicode/uenum.h"
16 #include "unicode/utf16.h"
17 #include "cmemory.h"
18 #include "charstr.h"
19
20 #if 0
21 #include "unicode/ustream.h"
22
23 #include <iostream>
24 using namespace std;
25
26 #endif
27
28 UnicodeStringTest::~UnicodeStringTest() {}
29
30 void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char *par)
31 {
32 if (exec) logln("TestSuite UnicodeStringTest: ");
33 switch (index) {
34 case 0:
35 name = "StringCaseTest";
36 if (exec) {
37 logln("StringCaseTest---"); logln("");
38 StringCaseTest test;
39 callTest(test, par);
40 }
41 break;
42 case 1: name = "TestBasicManipulation"; if (exec) TestBasicManipulation(); break;
43 case 2: name = "TestCompare"; if (exec) TestCompare(); break;
44 case 3: name = "TestExtract"; if (exec) TestExtract(); break;
45 case 4: name = "TestRemoveReplace"; if (exec) TestRemoveReplace(); break;
46 case 5: name = "TestSearching"; if (exec) TestSearching(); break;
47 case 6: name = "TestSpacePadding"; if (exec) TestSpacePadding(); break;
48 case 7: name = "TestPrefixAndSuffix"; if (exec) TestPrefixAndSuffix(); break;
49 case 8: name = "TestFindAndReplace"; if (exec) TestFindAndReplace(); break;
50 case 9: name = "TestBogus"; if (exec) TestBogus(); break;
51 case 10: name = "TestReverse"; if (exec) TestReverse(); break;
52 case 11: name = "TestMiscellaneous"; if (exec) TestMiscellaneous(); break;
53 case 12: name = "TestStackAllocation"; if (exec) TestStackAllocation(); break;
54 case 13: name = "TestUnescape"; if (exec) TestUnescape(); break;
55 case 14: name = "TestCountChar32"; if (exec) TestCountChar32(); break;
56 case 15: name = "TestStringEnumeration"; if (exec) TestStringEnumeration(); break;
57 case 16: name = "TestNameSpace"; if (exec) TestNameSpace(); break;
58 case 17: name = "TestUTF32"; if (exec) TestUTF32(); break;
59 case 18: name = "TestUTF8"; if (exec) TestUTF8(); break;
60 case 19: name = "TestReadOnlyAlias"; if (exec) TestReadOnlyAlias(); break;
61 case 20: name = "TestAppendable"; if (exec) TestAppendable(); break;
62 case 21: name = "TestUnicodeStringImplementsAppendable"; if (exec) TestUnicodeStringImplementsAppendable(); break;
63 case 22: name = "TestSizeofUnicodeString"; if (exec) TestSizeofUnicodeString(); break;
64 case 23: name = "TestStartsWithAndEndsWithNulTerminated"; if (exec) TestStartsWithAndEndsWithNulTerminated(); break;
65
66 default: name = ""; break; //needed to end loop
67 }
68 }
69
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(UnicodeString("length() failed: expected 70, got ") + test1.length());
115 if (test2.length() != 30)
116 errln(UnicodeString("length() failed: expected 30, got ") + test2.length());
117
118 UnicodeString test3;
119 test3.append((UChar32)0x20402);
120 if(test3 != CharsToUnicodeString("\\uD841\\uDC02")){
121 errln((UnicodeString)"append failed for UChar32, expected \"\\\\ud841\\\\udc02\", got " + prettify(test3));
122 }
123 if(test3.length() != 2){
124 errln(UnicodeString("append or length failed for UChar32, expected 2, got ") + test3.length());
125 }
126 test3.append((UChar32)0x0074);
127 if(test3 != CharsToUnicodeString("\\uD841\\uDC02t")){
128 errln((UnicodeString)"append failed for UChar32, expected \"\\\\uD841\\\\uDC02t\", got " + prettify(test3));
129 }
130 if(test3.length() != 3){
131 errln((UnicodeString)"append or length failed for UChar32, expected 2, got " + test3.length());
132 }
133
134 // test some UChar32 overloads
135 if( test3.setTo((UChar32)0x10330).length() != 2 ||
136 test3.insert(0, (UChar32)0x20100).length() != 4 ||
137 test3.replace(2, 2, (UChar32)0xe0061).length() != 4 ||
138 (test3 = (UChar32)0x14001).length() != 2
139 ) {
140 errln((UnicodeString)"simple UChar32 overloads for replace, insert, setTo or = failed");
141 }
142
143 {
144 // test moveIndex32()
145 UnicodeString s=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape();
146
147 if(
148 s.moveIndex32(2, -1)!=0 ||
149 s.moveIndex32(2, 1)!=4 ||
150 s.moveIndex32(2, 2)!=5 ||
151 s.moveIndex32(5, -2)!=2 ||
152 s.moveIndex32(0, -1)!=0 ||
153 s.moveIndex32(6, 1)!=6
154 ) {
155 errln("UnicodeString::moveIndex32() failed");
156 }
157
158 if(s.getChar32Start(1)!=0 || s.getChar32Start(2)!=2) {
159 errln("UnicodeString::getChar32Start() failed");
160 }
161
162 if(s.getChar32Limit(1)!=2 || s.getChar32Limit(2)!=2) {
163 errln("UnicodeString::getChar32Limit() failed");
164 }
165 }
166
167 {
168 // test new 2.2 constructors and setTo function that parallel Java's substring function.
169 UnicodeString src("Hello folks how are you?");
170 UnicodeString target1("how are you?");
171 if (target1 != UnicodeString(src, 12)) {
172 errln("UnicodeString(const UnicodeString&, int32_t) failed");
173 }
174 UnicodeString target2("folks");
175 if (target2 != UnicodeString(src, 6, 5)) {
176 errln("UnicodeString(const UnicodeString&, int32_t, int32_t) failed");
177 }
178 if (target1 != target2.setTo(src, 12)) {
179 errln("UnicodeString::setTo(const UnicodeString&, int32_t) failed");
180 }
181 }
182
183 {
184 // op+ is new in ICU 2.8
185 UnicodeString s=UnicodeString("abc", "")+UnicodeString("def", "")+UnicodeString("ghi", "");
186 if(s!=UnicodeString("abcdefghi", "")) {
187 errln("operator+(UniStr, UniStr) failed");
188 }
189 }
190
191 {
192 // tests for Jitterbug 2360
193 // verify that APIs with source pointer + length accept length == -1
194 // mostly test only where modified, only few functions did not already do this
195 if(UnicodeString("abc", -1, "")!=UnicodeString("abc", "")) {
196 errln("UnicodeString(codepageData, dataLength, codepage) does not work with dataLength==-1");
197 }
198
199 UChar buffer[10]={ 0x61, 0x62, 0x20ac, 0xd900, 0xdc05, 0, 0x62, 0xffff, 0xdbff, 0xdfff };
200 UnicodeString s, t(buffer, -1, UPRV_LENGTHOF(buffer));
201
202 if(s.setTo(buffer, -1, UPRV_LENGTHOF(buffer)).length()!=u_strlen(buffer)) {
203 errln("UnicodeString.setTo(buffer, length, capacity) does not work with length==-1");
204 }
205 if(t.length()!=u_strlen(buffer)) {
206 errln("UnicodeString(buffer, length, capacity) does not work with length==-1");
207 }
208
209 if(0!=s.caseCompare(buffer, -1, U_FOLD_CASE_DEFAULT)) {
210 errln("UnicodeString.caseCompare(const UChar *, length, options) does not work with length==-1");
211 }
212 if(0!=s.caseCompare(0, s.length(), buffer, U_FOLD_CASE_DEFAULT)) {
213 errln("UnicodeString.caseCompare(start, _length, const UChar *, options) does not work");
214 }
215
216 buffer[u_strlen(buffer)]=0xe4;
217 UnicodeString u(buffer, -1, UPRV_LENGTHOF(buffer));
218 if(s.setTo(buffer, -1, UPRV_LENGTHOF(buffer)).length()!=UPRV_LENGTHOF(buffer)) {
219 errln("UnicodeString.setTo(buffer without NUL, length, capacity) does not work with length==-1");
220 }
221 if(u.length()!=UPRV_LENGTHOF(buffer)) {
222 errln("UnicodeString(buffer without NUL, length, capacity) does not work with length==-1");
223 }
224
225 static const char cs[]={ 0x61, (char)0xe4, (char)0x85, 0 };
226 UConverter *cnv;
227 UErrorCode errorCode=U_ZERO_ERROR;
228
229 cnv=ucnv_open("ISO-8859-1", &errorCode);
230 UnicodeString v(cs, -1, cnv, errorCode);
231 ucnv_close(cnv);
232 if(v!=CharsToUnicodeString("a\\xe4\\x85")) {
233 errln("UnicodeString(const char *, length, cnv, errorCode) does not work with length==-1");
234 }
235 }
236
237 #if U_CHARSET_IS_UTF8
238 {
239 // Test the hardcoded-UTF-8 UnicodeString optimizations.
240 static const uint8_t utf8[]={ 0x61, 0xC3, 0xA4, 0xC3, 0x9F, 0xE4, 0xB8, 0x80, 0 };
241 static const UChar utf16[]={ 0x61, 0xE4, 0xDF, 0x4E00 };
242 UnicodeString from8a = UnicodeString((const char *)utf8);
243 UnicodeString from8b = UnicodeString((const char *)utf8, (int32_t)sizeof(utf8)-1);
244 UnicodeString from16(FALSE, utf16, UPRV_LENGTHOF(utf16));
245 if(from8a != from16 || from8b != from16) {
246 errln("UnicodeString(const char * U_CHARSET_IS_UTF8) failed");
247 }
248 char buffer[16];
249 int32_t length8=from16.extract(0, 0x7fffffff, buffer, (uint32_t)sizeof(buffer));
250 if(length8!=((int32_t)sizeof(utf8)-1) || 0!=uprv_memcmp(buffer, utf8, sizeof(utf8))) {
251 errln("UnicodeString::extract(char * U_CHARSET_IS_UTF8) failed");
252 }
253 length8=from16.extract(1, 2, buffer, (uint32_t)sizeof(buffer));
254 if(length8!=4 || buffer[length8]!=0 || 0!=uprv_memcmp(buffer, utf8+1, length8)) {
255 errln("UnicodeString::extract(substring to char * U_CHARSET_IS_UTF8) failed");
256 }
257 }
258 #endif
259 }
260
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(UnicodeString("indexOf failed: expected to find 6 occurrences, found ") + occurrences);
723
724 for ( occurrences = 0, startPos = 10;
725 startPos != -1 && startPos < test1.length();
726 (startPos = test1.indexOf(test2, startPos)) != -1 ? (++occurrences, startPos += 4) : 0)
727 ;
728 if (occurrences != 4)
729 errln(UnicodeString("indexOf with starting offset failed: "
730 "expected to find 4 occurrences, found ") + occurrences);
731
732 int32_t endPos = 28;
733 for ( occurrences = 0, startPos = 5;
734 startPos != -1 && startPos < test1.length();
735 (startPos = test1.indexOf(test2, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 4) : 0)
736 ;
737 if (occurrences != 4)
738 errln(UnicodeString("indexOf with starting and ending offsets failed: "
739 "expected to find 4 occurrences, found ") + occurrences);
740
741 //using UChar32 string
742 for ( startPos=0, occurrences=0;
743 startPos != -1 && startPos < test3.length();
744 (startPos = test3.indexOf(test4, startPos)) != -1 ? (++occurrences, startPos += 2) : 0)
745 ;
746 if (occurrences != 4)
747 errln((UnicodeString)"indexOf failed: expected to find 4 occurrences, found " + occurrences);
748
749 for ( startPos=10, occurrences=0;
750 startPos != -1 && startPos < test3.length();
751 (startPos = test3.indexOf(test4, startPos)) != -1 ? (++occurrences, startPos += 2) : 0)
752 ;
753 if (occurrences != 2)
754 errln(UnicodeString("indexOf failed: expected to find 2 occurrences, found ") + occurrences);
755 //---
756
757 for ( occurrences = 0, startPos = 0;
758 startPos != -1 && startPos < test1.length();
759 (startPos = test1.indexOf(testChar, startPos)) != -1 ? (++occurrences, startPos += 1) : 0)
760 ;
761 if (occurrences != 16)
762 errln(UnicodeString("indexOf with character failed: "
763 "expected to find 16 occurrences, found ") + occurrences);
764
765 for ( occurrences = 0, startPos = 10;
766 startPos != -1 && startPos < test1.length();
767 (startPos = test1.indexOf(testChar, startPos)) != -1 ? (++occurrences, startPos += 1) : 0)
768 ;
769 if (occurrences != 12)
770 errln(UnicodeString("indexOf with character & start offset failed: "
771 "expected to find 12 occurrences, found ") + occurrences);
772
773 for ( occurrences = 0, startPos = 5, endPos = 28;
774 startPos != -1 && startPos < test1.length();
775 (startPos = test1.indexOf(testChar, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 1) : 0)
776 ;
777 if (occurrences != 10)
778 errln(UnicodeString("indexOf with character & start & end offsets failed: "
779 "expected to find 10 occurrences, found ") + occurrences);
780
781 //testing for UChar32
782 UnicodeString subString;
783 for( occurrences =0, startPos=0; startPos < test3.length(); startPos +=1){
784 subString.append(test3, startPos, test3.length());
785 if(subString.indexOf(testChar32) != -1 ){
786 ++occurrences;
787 }
788 subString.remove();
789 }
790 if (occurrences != 14)
791 errln((UnicodeString)"indexOf failed: expected to find 14 occurrences, found " + occurrences);
792
793 for ( occurrences = 0, startPos = 0;
794 startPos != -1 && startPos < test3.length();
795 (startPos = test3.indexOf(testChar32, startPos)) != -1 ? (++occurrences, startPos += 1) : 0)
796 ;
797 if (occurrences != 4)
798 errln((UnicodeString)"indexOf failed: expected to find 4 occurrences, found " + occurrences);
799
800 endPos=test3.length();
801 for ( occurrences = 0, startPos = 5;
802 startPos != -1 && startPos < test3.length();
803 (startPos = test3.indexOf(testChar32, startPos, endPos - startPos)) != -1 ? (++occurrences, startPos += 1) : 0)
804 ;
805 if (occurrences != 3)
806 errln((UnicodeString)"indexOf with character & start & end offsets failed: expected to find 2 occurrences, found " + occurrences);
807 //---
808
809 if(test1.lastIndexOf(test2)!=29) {
810 errln("test1.lastIndexOf(test2)!=29");
811 }
812
813 if(test1.lastIndexOf(test2, 15)!=29 || test1.lastIndexOf(test2, 29)!=29 || test1.lastIndexOf(test2, 30)!=-1) {
814 errln("test1.lastIndexOf(test2, start) failed");
815 }
816
817 for ( occurrences = 0, startPos = 32;
818 startPos != -1;
819 (startPos = test1.lastIndexOf(test2, 5, startPos - 5)) != -1 ? ++occurrences : 0)
820 ;
821 if (occurrences != 4)
822 errln(UnicodeString("lastIndexOf with starting and ending offsets failed: "
823 "expected to find 4 occurrences, found ") + occurrences);
824
825 for ( occurrences = 0, startPos = 32;
826 startPos != -1;
827 (startPos = test1.lastIndexOf(testChar, 5, startPos - 5)) != -1 ? ++occurrences : 0)
828 ;
829 if (occurrences != 11)
830 errln(UnicodeString("lastIndexOf with character & start & end offsets failed: "
831 "expected to find 11 occurrences, found ") + occurrences);
832
833 //testing UChar32
834 startPos=test3.length();
835 for ( occurrences = 0;
836 startPos != -1;
837 (startPos = test3.lastIndexOf(testChar32, 5, startPos - 5)) != -1 ? ++occurrences : 0)
838 ;
839 if (occurrences != 3)
840 errln((UnicodeString)"lastIndexOf with character & start & end offsets failed: expected to find 3 occurrences, found " + occurrences);
841
842
843 for ( occurrences = 0, endPos = test3.length(); endPos > 0; endPos -= 1){
844 subString.remove();
845 subString.append(test3, 0, endPos);
846 if(subString.lastIndexOf(testChar32) != -1 ){
847 ++occurrences;
848 }
849 }
850 if (occurrences != 18)
851 errln((UnicodeString)"indexOf failed: expected to find 18 occurrences, found " + occurrences);
852 //---
853
854 // test that indexOf(UChar32) and lastIndexOf(UChar32)
855 // do not find surrogate code points when they are part of matched pairs
856 // (= part of supplementary code points)
857 // Jitterbug 1542
858 if(test3.indexOf((UChar32)0xd841) != 4 || test3.indexOf((UChar32)0xdc02) != 3) {
859 errln("error: UnicodeString::indexOf(UChar32 surrogate) finds a partial supplementary code point");
860 }
861 if( UnicodeString(test3, 0, 17).lastIndexOf((UChar)0xd841, 0) != 4 ||
862 UnicodeString(test3, 0, 17).lastIndexOf((UChar32)0xd841, 2) != 4 ||
863 test3.lastIndexOf((UChar32)0xd841, 0, 17) != 4 || test3.lastIndexOf((UChar32)0xdc02, 0, 17) != 16
864 ) {
865 errln("error: UnicodeString::lastIndexOf(UChar32 surrogate) finds a partial supplementary code point");
866 }
867 }
868
869 void
870 UnicodeStringTest::TestSpacePadding()
871 {
872 UnicodeString test1("hello");
873 UnicodeString test2(" there");
874 UnicodeString test3("Hi! How ya doin'? Beautiful day, isn't it?");
875 UnicodeString test4;
876 UBool returnVal;
877 UnicodeString expectedValue;
878
879 returnVal = test1.padLeading(15);
880 expectedValue = " hello";
881 if (returnVal == FALSE || test1 != expectedValue)
882 errln("padLeading() failed: expected \"" + expectedValue + "\", got \"" + test1 + "\".");
883
884 returnVal = test2.padTrailing(15);
885 expectedValue = " there ";
886 if (returnVal == FALSE || test2 != expectedValue)
887 errln("padTrailing() failed: expected \"" + expectedValue + "\", got \"" + test2 + "\".");
888
889 expectedValue = test3;
890 returnVal = test3.padTrailing(15);
891 if (returnVal == TRUE || test3 != expectedValue)
892 errln("padTrailing() failed: expected \"" + expectedValue + "\", got \"" + test3 + "\".");
893
894 expectedValue = "hello";
895 test4.setTo(test1).trim();
896
897 if (test4 != expectedValue || test1 == expectedValue || test4 != expectedValue)
898 errln("trim(UnicodeString&) failed");
899
900 test1.trim();
901 if (test1 != expectedValue)
902 errln("trim() failed: expected \"" + expectedValue + "\", got \"" + test1 + "\".");
903
904 test2.trim();
905 expectedValue = "there";
906 if (test2 != expectedValue)
907 errln("trim() failed: expected \"" + expectedValue + "\", got \"" + test2 + "\".");
908
909 test3.trim();
910 expectedValue = "Hi! How ya doin'? Beautiful day, isn't it?";
911 if (test3 != expectedValue)
912 errln("trim() failed: expected \"" + expectedValue + "\", got \"" + test3 + "\".");
913
914 returnVal = test1.truncate(15);
915 expectedValue = "hello";
916 if (returnVal == TRUE || test1 != expectedValue)
917 errln("truncate() failed: expected \"" + expectedValue + "\", got \"" + test1 + "\".");
918
919 returnVal = test2.truncate(15);
920 expectedValue = "there";
921 if (returnVal == TRUE || test2 != expectedValue)
922 errln("truncate() failed: expected \"" + expectedValue + "\", got \"" + test2 + "\".");
923
924 returnVal = test3.truncate(15);
925 expectedValue = "Hi! How ya doi";
926 if (returnVal == FALSE || test3 != expectedValue)
927 errln("truncate() failed: expected \"" + expectedValue + "\", got \"" + test3 + "\".");
928 }
929
930 void
931 UnicodeStringTest::TestPrefixAndSuffix()
932 {
933 UnicodeString test1("Now is the time for all good men to come to the aid of their country.");
934 UnicodeString test2("Now");
935 UnicodeString test3("country.");
936 UnicodeString test4("count");
937
938 if (!test1.startsWith(test2) || !test1.startsWith(test2, 0, test2.length())) {
939 errln("startsWith() failed: \"" + test2 + "\" should be a prefix of \"" + test1 + "\".");
940 }
941
942 if (test1.startsWith(test3) ||
943 test1.startsWith(test3.getBuffer(), test3.length()) ||
944 test1.startsWith(test3.getTerminatedBuffer(), 0, -1)
945 ) {
946 errln("startsWith() failed: \"" + test3 + "\" shouldn't be a prefix of \"" + test1 + "\".");
947 }
948
949 if (test1.endsWith(test2)) {
950 errln("endsWith() failed: \"" + test2 + "\" shouldn't be a suffix of \"" + test1 + "\".");
951 }
952
953 if (!test1.endsWith(test3)) {
954 errln("endsWith(test3) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\".");
955 }
956 if (!test1.endsWith(test3, 0, INT32_MAX)) {
957 errln("endsWith(test3, 0, INT32_MAX) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\".");
958 }
959
960 if(!test1.endsWith(test3.getBuffer(), test3.length())) {
961 errln("endsWith(test3.getBuffer(), test3.length()) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\".");
962 }
963 if(!test1.endsWith(test3.getTerminatedBuffer(), 0, -1)) {
964 errln("endsWith(test3.getTerminatedBuffer(), 0, -1) failed: \"" + test3 + "\" should be a suffix of \"" + test1 + "\".");
965 }
966
967 if (!test3.startsWith(test4)) {
968 errln("endsWith(test4) failed: \"" + test4 + "\" should be a prefix of \"" + test3 + "\".");
969 }
970
971 if (test4.startsWith(test3)) {
972 errln("startsWith(test3) failed: \"" + test3 + "\" shouldn't be a prefix of \"" + test4 + "\".");
973 }
974 }
975
976 void
977 UnicodeStringTest::TestStartsWithAndEndsWithNulTerminated() {
978 UnicodeString test("abcde");
979 const UChar ab[] = { 0x61, 0x62, 0 };
980 const UChar de[] = { 0x64, 0x65, 0 };
981 assertTrue("abcde.startsWith(ab, -1)", test.startsWith(ab, -1));
982 assertTrue("abcde.startsWith(ab, 0, -1)", test.startsWith(ab, 0, -1));
983 assertTrue("abcde.endsWith(de, -1)", test.endsWith(de, -1));
984 assertTrue("abcde.endsWith(de, 0, -1)", test.endsWith(de, 0, -1));
985 }
986
987 void
988 UnicodeStringTest::TestFindAndReplace()
989 {
990 UnicodeString test1("One potato, two potato, three potato, four\n");
991 UnicodeString test2("potato");
992 UnicodeString test3("MISSISSIPPI");
993
994 UnicodeString expectedValue;
995
996 test1.findAndReplace(test2, test3);
997 expectedValue = "One MISSISSIPPI, two MISSISSIPPI, three MISSISSIPPI, four\n";
998 if (test1 != expectedValue)
999 errln("findAndReplace failed: expected \"" + expectedValue + "\", got \"" + test1 + "\".");
1000 test1.findAndReplace(2, 32, test3, test2);
1001 expectedValue = "One potato, two potato, three MISSISSIPPI, four\n";
1002 if (test1 != expectedValue)
1003 errln("findAndReplace failed: expected \"" + expectedValue + "\", got \"" + test1 + "\".");
1004 }
1005
1006 void
1007 UnicodeStringTest::TestReverse()
1008 {
1009 UnicodeString test("backwards words say to used I");
1010
1011 test.reverse();
1012 test.reverse(2, 4);
1013 test.reverse(7, 2);
1014 test.reverse(10, 3);
1015 test.reverse(14, 5);
1016 test.reverse(20, 9);
1017
1018 if (test != "I used to say words backwards")
1019 errln("reverse() failed: Expected \"I used to say words backwards\",\n got \""
1020 + test + "\"");
1021
1022 test=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape();
1023 test.reverse();
1024 if(test.char32At(0)!=0x1ed0 || test.char32At(1)!=0xc4 || test.char32At(2)!=0x1d15f || test.char32At(4)!=0x2f999) {
1025 errln("reverse() failed with supplementary characters");
1026 }
1027
1028 // Test case for ticket #8091:
1029 // UnicodeString::reverse() failed to see a lead surrogate in the middle of
1030 // an odd-length string that contains no other lead surrogates.
1031 test=UNICODE_STRING_SIMPLE("ab\\U0001F4A9e").unescape();
1032 UnicodeString expected=UNICODE_STRING_SIMPLE("e\\U0001F4A9ba").unescape();
1033 test.reverse();
1034 if(test!=expected) {
1035 errln("reverse() failed with only lead surrogate in the middle");
1036 }
1037 }
1038
1039 void
1040 UnicodeStringTest::TestMiscellaneous()
1041 {
1042 UnicodeString test1("This is a test");
1043 UnicodeString test2("This is a test");
1044 UnicodeString test3("Me too!");
1045
1046 // test getBuffer(minCapacity) and releaseBuffer()
1047 test1=UnicodeString(); // make sure that it starts with its stackBuffer
1048 UChar *p=test1.getBuffer(20);
1049 if(test1.getCapacity()<20) {
1050 errln("UnicodeString::getBuffer(20).getCapacity()<20");
1051 }
1052
1053 test1.append((UChar)7); // must not be able to modify the string here
1054 test1.setCharAt(3, 7);
1055 test1.reverse();
1056 if( test1.length()!=0 ||
1057 test1.charAt(0)!=0xffff || test1.charAt(3)!=0xffff ||
1058 test1.getBuffer(10)!=0 || test1.getBuffer()!=0
1059 ) {
1060 errln("UnicodeString::getBuffer(minCapacity) allows read or write access to the UnicodeString");
1061 }
1062
1063 p[0]=1;
1064 p[1]=2;
1065 p[2]=3;
1066 test1.releaseBuffer(3);
1067 test1.append((UChar)4);
1068
1069 if(test1.length()!=4 || test1.charAt(0)!=1 || test1.charAt(1)!=2 || test1.charAt(2)!=3 || test1.charAt(3)!=4) {
1070 errln("UnicodeString::releaseBuffer(newLength) does not properly reallow access to the UnicodeString");
1071 }
1072
1073 // test releaseBuffer() without getBuffer(minCapacity) - must not have any effect
1074 test1.releaseBuffer(1);
1075 if(test1.length()!=4 || test1.charAt(0)!=1 || test1.charAt(1)!=2 || test1.charAt(2)!=3 || test1.charAt(3)!=4) {
1076 errln("UnicodeString::releaseBuffer(newLength) without getBuffer(minCapacity) changed the UnicodeString");
1077 }
1078
1079 // test getBuffer(const)
1080 const UChar *q=test1.getBuffer(), *r=test1.getBuffer();
1081 if( test1.length()!=4 ||
1082 q[0]!=1 || q[1]!=2 || q[2]!=3 || q[3]!=4 ||
1083 r[0]!=1 || r[1]!=2 || r[2]!=3 || r[3]!=4
1084 ) {
1085 errln("UnicodeString::getBuffer(const) does not return a usable buffer pointer");
1086 }
1087
1088 // test releaseBuffer() with a NUL-terminated buffer
1089 test1.getBuffer(20)[2]=0;
1090 test1.releaseBuffer(); // implicit -1
1091 if(test1.length()!=2 || test1.charAt(0)!=1 || test1.charAt(1) !=2) {
1092 errln("UnicodeString::releaseBuffer(-1) does not properly set the length of the UnicodeString");
1093 }
1094
1095 // test releaseBuffer() with a non-NUL-terminated buffer
1096 p=test1.getBuffer(256);
1097 for(int32_t i=0; i<test1.getCapacity(); ++i) {
1098 p[i]=(UChar)1; // fill the buffer with all non-NUL code units
1099 }
1100 test1.releaseBuffer(); // implicit -1
1101 if(test1.length()!=test1.getCapacity() || test1.charAt(1)!=1 || test1.charAt(100)!=1 || test1.charAt(test1.getCapacity()-1)!=1) {
1102 errln("UnicodeString::releaseBuffer(-1 but no NUL) does not properly set the length of the UnicodeString");
1103 }
1104
1105 // test getTerminatedBuffer()
1106 test1=UnicodeString("This is another test.", "");
1107 test2=UnicodeString("This is another test.", "");
1108 q=test1.getTerminatedBuffer();
1109 if(q[test1.length()]!=0 || test1!=test2 || test2.compare(q, -1)!=0) {
1110 errln("getTerminatedBuffer()[length]!=0");
1111 }
1112
1113 const UChar u[]={ 5, 6, 7, 8, 0 };
1114 test1.setTo(FALSE, u, 3);
1115 q=test1.getTerminatedBuffer();
1116 if(q==u || q[0]!=5 || q[1]!=6 || q[2]!=7 || q[3]!=0) {
1117 errln("UnicodeString(u[3]).getTerminatedBuffer() returns a bad buffer");
1118 }
1119
1120 test1.setTo(TRUE, u, -1);
1121 q=test1.getTerminatedBuffer();
1122 if(q!=u || test1.length()!=4 || q[3]!=8 || q[4]!=0) {
1123 errln("UnicodeString(u[-1]).getTerminatedBuffer() returns a bad buffer");
1124 }
1125
1126 test1=UNICODE_STRING("la", 2);
1127 test1.append(UNICODE_STRING(" lila", 5).getTerminatedBuffer(), 0, -1);
1128 if(test1!=UNICODE_STRING("la lila", 7)) {
1129 errln("UnicodeString::append(const UChar *, start, length) failed");
1130 }
1131
1132 test1.insert(3, UNICODE_STRING("dudum ", 6), 0, INT32_MAX);
1133 if(test1!=UNICODE_STRING("la dudum lila", 13)) {
1134 errln("UnicodeString::insert(start, const UniStr &, start, length) failed");
1135 }
1136
1137 static const UChar ucs[]={ 0x68, 0x6d, 0x20, 0 };
1138 test1.insert(9, ucs, -1);
1139 if(test1!=UNICODE_STRING("la dudum hm lila", 16)) {
1140 errln("UnicodeString::insert(start, const UChar *, length) failed");
1141 }
1142
1143 test1.replace(9, 2, (UChar)0x2b);
1144 if(test1!=UNICODE_STRING("la dudum + lila", 15)) {
1145 errln("UnicodeString::replace(start, length, UChar) failed");
1146 }
1147
1148 if(test1.hasMetaData() || UnicodeString().hasMetaData()) {
1149 errln("UnicodeString::hasMetaData() returns TRUE");
1150 }
1151
1152 // test getTerminatedBuffer() on a truncated, shared, heap-allocated string
1153 test1=UNICODE_STRING_SIMPLE("abcdefghijklmnopqrstuvwxyz0123456789.");
1154 test1.truncate(36); // ensure length()<getCapacity()
1155 test2=test1; // share the buffer
1156 test1.truncate(5);
1157 if(test1.length()!=5 || test1.getTerminatedBuffer()[5]!=0) {
1158 errln("UnicodeString(shared buffer).truncate() failed");
1159 }
1160 if(test2.length()!=36 || test2[5]!=0x66 || u_strlen(test2.getTerminatedBuffer())!=36) {
1161 errln("UnicodeString(shared buffer).truncate().getTerminatedBuffer() "
1162 "modified another copy of the string!");
1163 }
1164 test1=UNICODE_STRING_SIMPLE("abcdefghijklmnopqrstuvwxyz0123456789.");
1165 test1.truncate(36); // ensure length()<getCapacity()
1166 test2=test1; // share the buffer
1167 test1.remove();
1168 if(test1.length()!=0 || test1.getTerminatedBuffer()[0]!=0) {
1169 errln("UnicodeString(shared buffer).remove() failed");
1170 }
1171 if(test2.length()!=36 || test2[0]!=0x61 || u_strlen(test2.getTerminatedBuffer())!=36) {
1172 errln("UnicodeString(shared buffer).remove().getTerminatedBuffer() "
1173 "modified another copy of the string!");
1174 }
1175
1176 // ticket #9740
1177 test1.setTo(TRUE, ucs, 3);
1178 assertEquals("length of read-only alias", 3, test1.length());
1179 test1.trim();
1180 assertEquals("length of read-only alias after trim()", 2, test1.length());
1181 assertEquals("length of terminated buffer of read-only alias + trim()",
1182 2, u_strlen(test1.getTerminatedBuffer()));
1183 }
1184
1185 void
1186 UnicodeStringTest::TestStackAllocation()
1187 {
1188 UChar testString[] ={
1189 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x72, 0x61, 0x7a, 0x79, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2e, 0 };
1190 UChar guardWord = 0x4DED;
1191 UnicodeString* test = 0;
1192
1193 test = new UnicodeString(testString);
1194 if (*test != "This is a crazy test.")
1195 errln("Test string failed to initialize properly.");
1196 if (guardWord != 0x04DED)
1197 errln("Test string initialization overwrote guard word!");
1198
1199 test->insert(8, "only ");
1200 test->remove(15, 6);
1201 if (*test != "This is only a test.")
1202 errln("Manipulation of test string failed to work right.");
1203 if (guardWord != 0x4DED)
1204 errln("Manipulation of test string overwrote guard word!");
1205
1206 // we have to deinitialize and release the backing store by calling the destructor
1207 // explicitly, since we can't overload operator delete
1208 delete test;
1209
1210 UChar workingBuffer[] = {
1211 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
1212 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
1213 0x63, 0x6f, 0x6d, 0x65, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1214 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1215 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1216 UChar guardWord2 = 0x4DED;
1217
1218 test = new UnicodeString(workingBuffer, 35, 100);
1219 if (*test != "Now is the time for all men to come")
1220 errln("Stack-allocated backing store failed to initialize correctly.");
1221 if (guardWord2 != 0x4DED)
1222 errln("Stack-allocated backing store overwrote guard word!");
1223
1224 test->insert(24, "good ");
1225 if (*test != "Now is the time for all good men to come")
1226 errln("insert() on stack-allocated UnicodeString didn't work right");
1227 if (guardWord2 != 0x4DED)
1228 errln("insert() on stack-allocated UnicodeString overwrote guard word!");
1229
1230 if (workingBuffer[24] != 0x67)
1231 errln("insert() on stack-allocated UnicodeString didn't affect backing store");
1232
1233 *test += " to the aid of their country.";
1234 if (*test != "Now is the time for all good men to come to the aid of their country.")
1235 errln("Stack-allocated UnicodeString overflow didn't work");
1236 if (guardWord2 != 0x4DED)
1237 errln("Stack-allocated UnicodeString overflow overwrote guard word!");
1238
1239 *test = "ha!";
1240 if (*test != "ha!")
1241 errln("Assignment to stack-allocated UnicodeString didn't work");
1242 if (workingBuffer[0] != 0x4e)
1243 errln("Change to UnicodeString after overflow are still affecting original buffer");
1244 if (guardWord2 != 0x4DED)
1245 errln("Change to UnicodeString after overflow overwrote guard word!");
1246
1247 // test read-only aliasing with setTo()
1248 workingBuffer[0] = 0x20ac;
1249 workingBuffer[1] = 0x125;
1250 workingBuffer[2] = 0;
1251 test->setTo(TRUE, workingBuffer, 2);
1252 if(test->length() != 2 || test->charAt(0) != 0x20ac || test->charAt(1) != 0x125) {
1253 errln("UnicodeString.setTo(readonly alias) does not alias correctly");
1254 }
1255
1256 UnicodeString *c=(UnicodeString *)test->clone();
1257
1258 workingBuffer[1] = 0x109;
1259 if(test->charAt(1) != 0x109) {
1260 errln("UnicodeString.setTo(readonly alias) made a copy: did not see change in buffer");
1261 }
1262
1263 if(c->length() != 2 || c->charAt(1) != 0x125) {
1264 errln("clone(alias) did not copy the buffer");
1265 }
1266 delete c;
1267
1268 test->setTo(TRUE, workingBuffer, -1);
1269 if(test->length() != 2 || test->charAt(0) != 0x20ac || test->charAt(1) != 0x109) {
1270 errln("UnicodeString.setTo(readonly alias, length -1) does not alias correctly");
1271 }
1272
1273 test->setTo(FALSE, workingBuffer, -1);
1274 if(!test->isBogus()) {
1275 errln("UnicodeString.setTo(unterminated readonly alias, length -1) does not result in isBogus()");
1276 }
1277
1278 delete test;
1279
1280 test=new UnicodeString();
1281 UChar buffer[]={0x0061, 0x0062, 0x20ac, 0x0043, 0x0042, 0x0000};
1282 test->setTo(buffer, 4, 10);
1283 if(test->length() !=4 || test->charAt(0) != 0x0061 || test->charAt(1) != 0x0062 ||
1284 test->charAt(2) != 0x20ac || test->charAt(3) != 0x0043){
1285 errln((UnicodeString)"UnicodeString.setTo(UChar*, length, capacity) does not work correctly\n" + prettify(*test));
1286 }
1287 delete test;
1288
1289
1290 // test the UChar32 constructor
1291 UnicodeString c32Test((UChar32)0x10ff2a);
1292 if( c32Test.length() != U16_LENGTH(0x10ff2a) ||
1293 c32Test.char32At(c32Test.length() - 1) != 0x10ff2a
1294 ) {
1295 errln("The UnicodeString(UChar32) constructor does not work with a 0x10ff2a filler");
1296 }
1297
1298 // test the (new) capacity constructor
1299 UnicodeString capTest(5, (UChar32)0x2a, 5);
1300 if( capTest.length() != 5 * U16_LENGTH(0x2a) ||
1301 capTest.char32At(0) != 0x2a ||
1302 capTest.char32At(4) != 0x2a
1303 ) {
1304 errln("The UnicodeString capacity constructor does not work with an ASCII filler");
1305 }
1306
1307 capTest = UnicodeString(5, (UChar32)0x10ff2a, 5);
1308 if( capTest.length() != 5 * U16_LENGTH(0x10ff2a) ||
1309 capTest.char32At(0) != 0x10ff2a ||
1310 capTest.char32At(4) != 0x10ff2a
1311 ) {
1312 errln("The UnicodeString capacity constructor does not work with a 0x10ff2a filler");
1313 }
1314
1315 capTest = UnicodeString(5, (UChar32)0, 0);
1316 if(capTest.length() != 0) {
1317 errln("The UnicodeString capacity constructor does not work with a 0x10ff2a filler");
1318 }
1319 }
1320
1321 /**
1322 * Test the unescape() function.
1323 */
1324 void UnicodeStringTest::TestUnescape(void) {
1325 UnicodeString IN("abc\\u4567 \\n\\r \\U00101234xyz\\x1\\x{5289}\\x1b", -1, US_INV);
1326 UnicodeString OUT("abc");
1327 OUT.append((UChar)0x4567);
1328 OUT.append(" ");
1329 OUT.append((UChar)0xA);
1330 OUT.append((UChar)0xD);
1331 OUT.append(" ");
1332 OUT.append((UChar32)0x00101234);
1333 OUT.append("xyz");
1334 OUT.append((UChar32)1).append((UChar32)0x5289).append((UChar)0x1b);
1335 UnicodeString result = IN.unescape();
1336 if (result != OUT) {
1337 errln("FAIL: " + prettify(IN) + ".unescape() -> " +
1338 prettify(result) + ", expected " +
1339 prettify(OUT));
1340 }
1341
1342 // test that an empty string is returned in case of an error
1343 if (!UNICODE_STRING("wrong \\u sequence", 17).unescape().isEmpty()) {
1344 errln("FAIL: unescaping of a string with an illegal escape sequence did not return an empty string");
1345 }
1346 }
1347
1348 /* test code point counting functions --------------------------------------- */
1349
1350 /* reference implementation of UnicodeString::hasMoreChar32Than() */
1351 static int32_t
1352 _refUnicodeStringHasMoreChar32Than(const UnicodeString &s, int32_t start, int32_t length, int32_t number) {
1353 int32_t count=s.countChar32(start, length);
1354 return count>number;
1355 }
1356
1357 /* compare the real function against the reference */
1358 void
1359 UnicodeStringTest::_testUnicodeStringHasMoreChar32Than(const UnicodeString &s, int32_t start, int32_t length, int32_t number) {
1360 if(s.hasMoreChar32Than(start, length, number)!=_refUnicodeStringHasMoreChar32Than(s, start, length, number)) {
1361 errln("hasMoreChar32Than(%d, %d, %d)=%hd is wrong\n",
1362 start, length, number, s.hasMoreChar32Than(start, length, number));
1363 }
1364 }
1365
1366 void
1367 UnicodeStringTest::TestCountChar32(void) {
1368 {
1369 UnicodeString s=UNICODE_STRING("\\U0002f999\\U0001d15f\\u00c4\\u1ed0", 32).unescape();
1370
1371 // test countChar32()
1372 // note that this also calls and tests u_countChar32(length>=0)
1373 if(
1374 s.countChar32()!=4 ||
1375 s.countChar32(1)!=4 ||
1376 s.countChar32(2)!=3 ||
1377 s.countChar32(2, 3)!=2 ||
1378 s.countChar32(2, 0)!=0
1379 ) {
1380 errln("UnicodeString::countChar32() failed");
1381 }
1382
1383 // NUL-terminate the string buffer and test u_countChar32(length=-1)
1384 const UChar *buffer=s.getTerminatedBuffer();
1385 if(
1386 u_countChar32(buffer, -1)!=4 ||
1387 u_countChar32(buffer+1, -1)!=4 ||
1388 u_countChar32(buffer+2, -1)!=3 ||
1389 u_countChar32(buffer+3, -1)!=3 ||
1390 u_countChar32(buffer+4, -1)!=2 ||
1391 u_countChar32(buffer+5, -1)!=1 ||
1392 u_countChar32(buffer+6, -1)!=0
1393 ) {
1394 errln("u_countChar32(length=-1) failed");
1395 }
1396
1397 // test u_countChar32() with bad input
1398 if(u_countChar32(NULL, 5)!=0 || u_countChar32(buffer, -2)!=0) {
1399 errln("u_countChar32(bad input) failed (returned non-zero counts)");
1400 }
1401 }
1402
1403 /* test data and variables for hasMoreChar32Than() */
1404 static const UChar str[]={
1405 0x61, 0x62, 0xd800, 0xdc00,
1406 0xd801, 0xdc01, 0x63, 0xd802,
1407 0x64, 0xdc03, 0x65, 0x66,
1408 0xd804, 0xdc04, 0xd805, 0xdc05,
1409 0x67
1410 };
1411 UnicodeString string(str, UPRV_LENGTHOF(str));
1412 int32_t start, length, number;
1413
1414 /* test hasMoreChar32Than() */
1415 for(length=string.length(); length>=0; --length) {
1416 for(start=0; start<=length; ++start) {
1417 for(number=-1; number<=((length-start)+2); ++number) {
1418 _testUnicodeStringHasMoreChar32Than(string, start, length-start, number);
1419 }
1420 }
1421 }
1422
1423 /* test hasMoreChar32Than() with pinning */
1424 for(start=-1; start<=string.length()+1; ++start) {
1425 for(number=-1; number<=((string.length()-start)+2); ++number) {
1426 _testUnicodeStringHasMoreChar32Than(string, start, 0x7fffffff, number);
1427 }
1428 }
1429
1430 /* test hasMoreChar32Than() with a bogus string */
1431 string.setToBogus();
1432 for(length=-1; length<=1; ++length) {
1433 for(start=-1; start<=length; ++start) {
1434 for(number=-1; number<=((length-start)+2); ++number) {
1435 _testUnicodeStringHasMoreChar32Than(string, start, length-start, number);
1436 }
1437 }
1438 }
1439 }
1440
1441 void
1442 UnicodeStringTest::TestBogus() {
1443 UnicodeString test1("This is a test");
1444 UnicodeString test2("This is a test");
1445 UnicodeString test3("Me too!");
1446
1447 // test isBogus() and setToBogus()
1448 if (test1.isBogus() || test2.isBogus() || test3.isBogus()) {
1449 errln("A string returned TRUE for isBogus()!");
1450 }
1451
1452 // NULL pointers are treated like empty strings
1453 // use other illegal arguments to make a bogus string
1454 test3.setTo(FALSE, test1.getBuffer(), -2);
1455 if(!test3.isBogus()) {
1456 errln("A bogus string returned FALSE for isBogus()!");
1457 }
1458 if (test1.hashCode() != test2.hashCode() || test1.hashCode() == test3.hashCode()) {
1459 errln("hashCode() failed");
1460 }
1461 if(test3.getBuffer()!=0 || test3.getBuffer(20)!=0 || test3.getTerminatedBuffer()!=0) {
1462 errln("bogus.getBuffer()!=0");
1463 }
1464 if (test1.indexOf(test3) != -1) {
1465 errln("bogus.indexOf() != -1");
1466 }
1467 if (test1.lastIndexOf(test3) != -1) {
1468 errln("bogus.lastIndexOf() != -1");
1469 }
1470 if (test1.caseCompare(test3, U_FOLD_CASE_DEFAULT) != 1 || test3.caseCompare(test1, U_FOLD_CASE_DEFAULT) != -1) {
1471 errln("caseCompare() doesn't work with bogus strings");
1472 }
1473 if (test1.compareCodePointOrder(test3) != 1 || test3.compareCodePointOrder(test1) != -1) {
1474 errln("compareCodePointOrder() doesn't work with bogus strings");
1475 }
1476
1477 // verify that non-assignment modifications fail and do not revive a bogus string
1478 test3.setToBogus();
1479 test3.append((UChar)0x61);
1480 if(!test3.isBogus() || test3.getBuffer()!=0) {
1481 errln("bogus.append('a') worked but must not");
1482 }
1483
1484 test3.setToBogus();
1485 test3.findAndReplace(UnicodeString((UChar)0x61), test2);
1486 if(!test3.isBogus() || test3.getBuffer()!=0) {
1487 errln("bogus.findAndReplace() worked but must not");
1488 }
1489
1490 test3.setToBogus();
1491 test3.trim();
1492 if(!test3.isBogus() || test3.getBuffer()!=0) {
1493 errln("bogus.trim() revived bogus but must not");
1494 }
1495
1496 test3.setToBogus();
1497 test3.remove(1);
1498 if(!test3.isBogus() || test3.getBuffer()!=0) {
1499 errln("bogus.remove(1) revived bogus but must not");
1500 }
1501
1502 test3.setToBogus();
1503 if(!test3.setCharAt(0, 0x62).isBogus() || !test3.isEmpty()) {
1504 errln("bogus.setCharAt(0, 'b') worked but must not");
1505 }
1506
1507 test3.setToBogus();
1508 if(test3.truncate(1) || !test3.isBogus() || !test3.isEmpty()) {
1509 errln("bogus.truncate(1) revived bogus but must not");
1510 }
1511
1512 // verify that assignments revive a bogus string
1513 test3.setToBogus();
1514 if(!test3.isBogus() || (test3=test1).isBogus() || test3!=test1) {
1515 errln("bogus.operator=() failed");
1516 }
1517
1518 test3.setToBogus();
1519 if(!test3.isBogus() || test3.fastCopyFrom(test1).isBogus() || test3!=test1) {
1520 errln("bogus.fastCopyFrom() failed");
1521 }
1522
1523 test3.setToBogus();
1524 if(!test3.isBogus() || test3.setTo(test1).isBogus() || test3!=test1) {
1525 errln("bogus.setTo(UniStr) failed");
1526 }
1527
1528 test3.setToBogus();
1529 if(!test3.isBogus() || test3.setTo(test1, 0).isBogus() || test3!=test1) {
1530 errln("bogus.setTo(UniStr, 0) failed");
1531 }
1532
1533 test3.setToBogus();
1534 if(!test3.isBogus() || test3.setTo(test1, 0, 0x7fffffff).isBogus() || test3!=test1) {
1535 errln("bogus.setTo(UniStr, 0, len) failed");
1536 }
1537
1538 test3.setToBogus();
1539 if(!test3.isBogus() || test3.setTo(test1.getBuffer(), test1.length()).isBogus() || test3!=test1) {
1540 errln("bogus.setTo(const UChar *, len) failed");
1541 }
1542
1543 test3.setToBogus();
1544 if(!test3.isBogus() || test3.setTo((UChar)0x2028).isBogus() || test3!=UnicodeString((UChar)0x2028)) {
1545 errln("bogus.setTo(UChar) failed");
1546 }
1547
1548 test3.setToBogus();
1549 if(!test3.isBogus() || test3.setTo((UChar32)0x1d157).isBogus() || test3!=UnicodeString((UChar32)0x1d157)) {
1550 errln("bogus.setTo(UChar32) failed");
1551 }
1552
1553 test3.setToBogus();
1554 if(!test3.isBogus() || test3.setTo(FALSE, test1.getBuffer(), test1.length()).isBogus() || test3!=test1) {
1555 errln("bogus.setTo(readonly alias) failed");
1556 }
1557
1558 // writable alias to another string's buffer: very bad idea, just convenient for this test
1559 test3.setToBogus();
1560 if(!test3.isBogus() || test3.setTo((UChar *)test1.getBuffer(), test1.length(), test1.getCapacity()).isBogus() || test3!=test1) {
1561 errln("bogus.setTo(writable alias) failed");
1562 }
1563
1564 // verify simple, documented ways to turn a bogus string into an empty one
1565 test3.setToBogus();
1566 if(!test3.isBogus() || (test3=UnicodeString()).isBogus() || !test3.isEmpty()) {
1567 errln("bogus.operator=(UnicodeString()) failed");
1568 }
1569
1570 test3.setToBogus();
1571 if(!test3.isBogus() || test3.setTo(UnicodeString()).isBogus() || !test3.isEmpty()) {
1572 errln("bogus.setTo(UnicodeString()) failed");
1573 }
1574
1575 test3.setToBogus();
1576 if(test3.remove().isBogus() || test3.getBuffer()==0 || !test3.isEmpty()) {
1577 errln("bogus.remove() failed");
1578 }
1579
1580 test3.setToBogus();
1581 if(test3.remove(0, INT32_MAX).isBogus() || test3.getBuffer()==0 || !test3.isEmpty()) {
1582 errln("bogus.remove(0, INT32_MAX) failed");
1583 }
1584
1585 test3.setToBogus();
1586 if(test3.truncate(0) || test3.isBogus() || !test3.isEmpty()) {
1587 errln("bogus.truncate(0) failed");
1588 }
1589
1590 test3.setToBogus();
1591 if(!test3.isBogus() || test3.setTo((UChar32)-1).isBogus() || !test3.isEmpty()) {
1592 errln("bogus.setTo((UChar32)-1) failed");
1593 }
1594
1595 static const UChar nul=0;
1596
1597 test3.setToBogus();
1598 if(!test3.isBogus() || test3.setTo(&nul, 0).isBogus() || !test3.isEmpty()) {
1599 errln("bogus.setTo(&nul, 0) failed");
1600 }
1601
1602 test3.setToBogus();
1603 if(!test3.isBogus() || test3.getBuffer()!=0) {
1604 errln("setToBogus() failed to make a string bogus");
1605 }
1606
1607 test3.setToBogus();
1608 if(test1.isBogus() || !(test1=test3).isBogus()) {
1609 errln("normal=bogus failed to make the left string bogus");
1610 }
1611
1612 // test that NULL primitive input string values are treated like
1613 // empty strings, not errors (bogus)
1614 test2.setTo((UChar32)0x10005);
1615 if(test2.insert(1, NULL, 1).length()!=2) {
1616 errln("UniStr.insert(...NULL...) should not modify the string but does");
1617 }
1618
1619 UErrorCode errorCode=U_ZERO_ERROR;
1620 UnicodeString
1621 test4((const UChar *)NULL),
1622 test5(TRUE, (const UChar *)NULL, 1),
1623 test6((UChar *)NULL, 5, 5),
1624 test7((const char *)NULL, 3, NULL, errorCode);
1625 if(test4.isBogus() || test5.isBogus() || test6.isBogus() || test7.isBogus()) {
1626 errln("a constructor set to bogus for a NULL input string, should be empty");
1627 }
1628
1629 test4.setTo(NULL, 3);
1630 test5.setTo(TRUE, (const UChar *)NULL, 1);
1631 test6.setTo((UChar *)NULL, 5, 5);
1632 if(test4.isBogus() || test5.isBogus() || test6.isBogus()) {
1633 errln("a setTo() set to bogus for a NULL input string, should be empty");
1634 }
1635
1636 // test that bogus==bogus<any
1637 if(test1!=test3 || test1.compare(test3)!=0) {
1638 errln("bogus==bogus failed");
1639 }
1640
1641 test2.remove();
1642 if(test1>=test2 || !(test2>test1) || test1.compare(test2)>=0 || !(test2.compare(test1)>0)) {
1643 errln("bogus<empty failed");
1644 }
1645 }
1646
1647 // StringEnumeration ------------------------------------------------------- ***
1648 // most of StringEnumeration is tested elsewhere
1649 // this test improves code coverage
1650
1651 static const char *const
1652 testEnumStrings[]={
1653 "a",
1654 "b",
1655 "c",
1656 "this is a long string which helps us test some buffer limits",
1657 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
1658 };
1659
1660 class TestEnumeration : public StringEnumeration {
1661 public:
1662 TestEnumeration() : i(0) {}
1663
1664 virtual int32_t count(UErrorCode& /*status*/) const {
1665 return UPRV_LENGTHOF(testEnumStrings);
1666 }
1667
1668 virtual const UnicodeString *snext(UErrorCode &status) {
1669 if(U_SUCCESS(status) && i<UPRV_LENGTHOF(testEnumStrings)) {
1670 unistr=UnicodeString(testEnumStrings[i++], "");
1671 return &unistr;
1672 }
1673
1674 return NULL;
1675 }
1676
1677 virtual void reset(UErrorCode& /*status*/) {
1678 i=0;
1679 }
1680
1681 static inline UClassID getStaticClassID() {
1682 return (UClassID)&fgClassID;
1683 }
1684 virtual UClassID getDynamicClassID() const {
1685 return getStaticClassID();
1686 }
1687
1688 private:
1689 static const char fgClassID;
1690
1691 int32_t i;
1692 };
1693
1694 const char TestEnumeration::fgClassID=0;
1695
1696 void
1697 UnicodeStringTest::TestStringEnumeration() {
1698 UnicodeString s;
1699 TestEnumeration ten;
1700 int32_t i, length;
1701 UErrorCode status;
1702
1703 const UChar *pu;
1704 const char *pc;
1705
1706 // test the next() default implementation and ensureCharsCapacity()
1707 for(i=0; i<UPRV_LENGTHOF(testEnumStrings); ++i) {
1708 status=U_ZERO_ERROR;
1709 pc=ten.next(&length, status);
1710 s=UnicodeString(testEnumStrings[i], "");
1711 if(U_FAILURE(status) || pc==NULL || length!=s.length() || UnicodeString(pc, length, "")!=s) {
1712 errln("StringEnumeration.next(%d) failed", i);
1713 }
1714 }
1715 status=U_ZERO_ERROR;
1716 if(ten.next(&length, status)!=NULL) {
1717 errln("StringEnumeration.next(done)!=NULL");
1718 }
1719
1720 // test the unext() default implementation
1721 ten.reset(status);
1722 for(i=0; i<UPRV_LENGTHOF(testEnumStrings); ++i) {
1723 status=U_ZERO_ERROR;
1724 pu=ten.unext(&length, status);
1725 s=UnicodeString(testEnumStrings[i], "");
1726 if(U_FAILURE(status) || pu==NULL || length!=s.length() || UnicodeString(TRUE, pu, length)!=s) {
1727 errln("StringEnumeration.unext(%d) failed", i);
1728 }
1729 }
1730 status=U_ZERO_ERROR;
1731 if(ten.unext(&length, status)!=NULL) {
1732 errln("StringEnumeration.unext(done)!=NULL");
1733 }
1734
1735 // test that the default clone() implementation works, and returns NULL
1736 if(ten.clone()!=NULL) {
1737 errln("StringEnumeration.clone()!=NULL");
1738 }
1739
1740 // test that uenum_openFromStringEnumeration() works
1741 // Need a heap allocated string enumeration because it is adopted by the UEnumeration.
1742 StringEnumeration *newTen = new TestEnumeration;
1743 status=U_ZERO_ERROR;
1744 UEnumeration *uten = uenum_openFromStringEnumeration(newTen, &status);
1745 if (uten==NULL || U_FAILURE(status)) {
1746 errln("fail at file %s, line %d, UErrorCode is %s\n", __FILE__, __LINE__, u_errorName(status));
1747 return;
1748 }
1749
1750 // test uenum_next()
1751 for(i=0; i<UPRV_LENGTHOF(testEnumStrings); ++i) {
1752 status=U_ZERO_ERROR;
1753 pc=uenum_next(uten, &length, &status);
1754 if(U_FAILURE(status) || pc==NULL || strcmp(pc, testEnumStrings[i]) != 0) {
1755 errln("File %s, line %d, StringEnumeration.next(%d) failed", __FILE__, __LINE__, i);
1756 }
1757 }
1758 status=U_ZERO_ERROR;
1759 if(uenum_next(uten, &length, &status)!=NULL) {
1760 errln("File %s, line %d, uenum_next(done)!=NULL");
1761 }
1762
1763 // test the uenum_unext()
1764 uenum_reset(uten, &status);
1765 for(i=0; i<UPRV_LENGTHOF(testEnumStrings); ++i) {
1766 status=U_ZERO_ERROR;
1767 pu=uenum_unext(uten, &length, &status);
1768 s=UnicodeString(testEnumStrings[i], "");
1769 if(U_FAILURE(status) || pu==NULL || length!=s.length() || UnicodeString(TRUE, pu, length)!=s) {
1770 errln("File %s, Line %d, uenum_unext(%d) failed", __FILE__, __LINE__, i);
1771 }
1772 }
1773 status=U_ZERO_ERROR;
1774 if(uenum_unext(uten, &length, &status)!=NULL) {
1775 errln("File %s, Line %d, uenum_unext(done)!=NULL" __FILE__, __LINE__);
1776 }
1777
1778 uenum_close(uten);
1779 }
1780
1781 /*
1782 * Namespace test, to make sure that macros like UNICODE_STRING include the
1783 * namespace qualifier.
1784 *
1785 * Define a (bogus) UnicodeString class in another namespace and check for ambiguity.
1786 */
1787 namespace bogus {
1788 class UnicodeString {
1789 public:
1790 enum EInvariant { kInvariant };
1791 UnicodeString() : i(1) {}
1792 UnicodeString(UBool /*isTerminated*/, const UChar * /*text*/, int32_t textLength) : i(textLength) {(void)i;}
1793 UnicodeString(const char * /*src*/, int32_t length, enum EInvariant /*inv*/
1794 ) : i(length) {}
1795 private:
1796 int32_t i;
1797 };
1798 }
1799
1800 void
1801 UnicodeStringTest::TestNameSpace() {
1802 // Provoke name collision unless the UnicodeString macros properly
1803 // qualify the icu::UnicodeString class.
1804 using namespace bogus;
1805
1806 // Use all UnicodeString macros from unistr.h.
1807 icu::UnicodeString s1=icu::UnicodeString("abc", 3, US_INV);
1808 icu::UnicodeString s2=UNICODE_STRING("def", 3);
1809 icu::UnicodeString s3=UNICODE_STRING_SIMPLE("ghi");
1810
1811 // Make sure the compiler does not optimize away instantiation of s1, s2, s3.
1812 icu::UnicodeString s4=s1+s2+s3;
1813 if(s4.length()!=9) {
1814 errln("Something wrong with UnicodeString::operator+().");
1815 }
1816 }
1817
1818 void
1819 UnicodeStringTest::TestUTF32() {
1820 // Input string length US_STACKBUF_SIZE to cause overflow of the
1821 // initially chosen fStackBuffer due to supplementary characters.
1822 static const UChar32 utf32[] = {
1823 0x41, 0xd900, 0x61, 0xdc00, -1, 0x110000, 0x5a, 0x50000, 0x7a,
1824 0x10000, 0x20000, 0xe0000, 0x10ffff
1825 };
1826 static const UChar expected_utf16[] = {
1827 0x41, 0xfffd, 0x61, 0xfffd, 0xfffd, 0xfffd, 0x5a, 0xd900, 0xdc00, 0x7a,
1828 0xd800, 0xdc00, 0xd840, 0xdc00, 0xdb40, 0xdc00, 0xdbff, 0xdfff
1829 };
1830 UnicodeString from32 = UnicodeString::fromUTF32(utf32, UPRV_LENGTHOF(utf32));
1831 UnicodeString expected(FALSE, expected_utf16, UPRV_LENGTHOF(expected_utf16));
1832 if(from32 != expected) {
1833 errln("UnicodeString::fromUTF32() did not create the expected string.");
1834 }
1835
1836 static const UChar utf16[] = {
1837 0x41, 0xd900, 0x61, 0xdc00, 0x5a, 0xd900, 0xdc00, 0x7a, 0xd800, 0xdc00, 0xdbff, 0xdfff
1838 };
1839 static const UChar32 expected_utf32[] = {
1840 0x41, 0xfffd, 0x61, 0xfffd, 0x5a, 0x50000, 0x7a, 0x10000, 0x10ffff
1841 };
1842 UChar32 result32[16];
1843 UErrorCode errorCode = U_ZERO_ERROR;
1844 int32_t length32 =
1845 UnicodeString(FALSE, utf16, UPRV_LENGTHOF(utf16)).
1846 toUTF32(result32, UPRV_LENGTHOF(result32), errorCode);
1847 if( length32 != UPRV_LENGTHOF(expected_utf32) ||
1848 0 != uprv_memcmp(result32, expected_utf32, length32*4) ||
1849 result32[length32] != 0
1850 ) {
1851 errln("UnicodeString::toUTF32() did not create the expected string.");
1852 }
1853 }
1854
1855 class TestCheckedArrayByteSink : public CheckedArrayByteSink {
1856 public:
1857 TestCheckedArrayByteSink(char* outbuf, int32_t capacity)
1858 : CheckedArrayByteSink(outbuf, capacity), calledFlush(FALSE) {}
1859 virtual void Flush() { calledFlush = TRUE; }
1860 UBool calledFlush;
1861 };
1862
1863 void
1864 UnicodeStringTest::TestUTF8() {
1865 static const uint8_t utf8[] = {
1866 // Code points:
1867 // 0x41, 0xd900,
1868 // 0x61, 0xdc00,
1869 // 0x110000, 0x5a,
1870 // 0x50000, 0x7a,
1871 // 0x10000, 0x20000,
1872 // 0xe0000, 0x10ffff
1873 0x41, 0xed, 0xa4, 0x80,
1874 0x61, 0xed, 0xb0, 0x80,
1875 0xf4, 0x90, 0x80, 0x80, 0x5a,
1876 0xf1, 0x90, 0x80, 0x80, 0x7a,
1877 0xf0, 0x90, 0x80, 0x80, 0xf0, 0xa0, 0x80, 0x80,
1878 0xf3, 0xa0, 0x80, 0x80, 0xf4, 0x8f, 0xbf, 0xbf
1879 };
1880 static const UChar expected_utf16[] = {
1881 0x41, 0xfffd,
1882 0x61, 0xfffd,
1883 0xfffd, 0x5a,
1884 0xd900, 0xdc00, 0x7a,
1885 0xd800, 0xdc00, 0xd840, 0xdc00,
1886 0xdb40, 0xdc00, 0xdbff, 0xdfff
1887 };
1888 UnicodeString from8 = UnicodeString::fromUTF8(StringPiece((const char *)utf8, (int32_t)sizeof(utf8)));
1889 UnicodeString expected(FALSE, expected_utf16, UPRV_LENGTHOF(expected_utf16));
1890
1891 if(from8 != expected) {
1892 errln("UnicodeString::fromUTF8(StringPiece) did not create the expected string.");
1893 }
1894 #if U_HAVE_STD_STRING
1895 std::string utf8_string((const char *)utf8, sizeof(utf8));
1896 UnicodeString from8b = UnicodeString::fromUTF8(utf8_string);
1897 if(from8b != expected) {
1898 errln("UnicodeString::fromUTF8(std::string) did not create the expected string.");
1899 }
1900 #endif
1901
1902 static const UChar utf16[] = {
1903 0x41, 0xd900, 0x61, 0xdc00, 0x5a, 0xd900, 0xdc00, 0x7a, 0xd800, 0xdc00, 0xdbff, 0xdfff
1904 };
1905 static const uint8_t expected_utf8[] = {
1906 0x41, 0xef, 0xbf, 0xbd, 0x61, 0xef, 0xbf, 0xbd, 0x5a, 0xf1, 0x90, 0x80, 0x80, 0x7a,
1907 0xf0, 0x90, 0x80, 0x80, 0xf4, 0x8f, 0xbf, 0xbf
1908 };
1909 UnicodeString us(FALSE, utf16, UPRV_LENGTHOF(utf16));
1910
1911 char buffer[64];
1912 TestCheckedArrayByteSink sink(buffer, (int32_t)sizeof(buffer));
1913 us.toUTF8(sink);
1914 if( sink.NumberOfBytesWritten() != (int32_t)sizeof(expected_utf8) ||
1915 0 != uprv_memcmp(buffer, expected_utf8, sizeof(expected_utf8))
1916 ) {
1917 errln("UnicodeString::toUTF8() did not create the expected string.");
1918 }
1919 if(!sink.calledFlush) {
1920 errln("UnicodeString::toUTF8(sink) did not sink.Flush().");
1921 }
1922 #if U_HAVE_STD_STRING
1923 // Initial contents for testing that toUTF8String() appends.
1924 std::string result8 = "-->";
1925 std::string expected8 = "-->" + std::string((const char *)expected_utf8, sizeof(expected_utf8));
1926 // Use the return value just for testing.
1927 std::string &result8r = us.toUTF8String(result8);
1928 if(result8r != expected8 || &result8r != &result8) {
1929 errln("UnicodeString::toUTF8String() did not create the expected string.");
1930 }
1931 #endif
1932 }
1933
1934 // Test if this compiler supports Return Value Optimization of unnamed temporary objects.
1935 static UnicodeString wrapUChars(const UChar *uchars) {
1936 return UnicodeString(TRUE, uchars, -1);
1937 }
1938
1939 void
1940 UnicodeStringTest::TestReadOnlyAlias() {
1941 UChar uchars[]={ 0x61, 0x62, 0 };
1942 UnicodeString alias(TRUE, uchars, 2);
1943 if(alias.length()!=2 || alias.getBuffer()!=uchars || alias.getTerminatedBuffer()!=uchars) {
1944 errln("UnicodeString read-only-aliasing constructor does not behave as expected.");
1945 return;
1946 }
1947 alias.truncate(1);
1948 if(alias.length()!=1 || alias.getBuffer()!=uchars) {
1949 errln("UnicodeString(read-only-alias).truncate() did not preserve aliasing as expected.");
1950 }
1951 if(alias.getTerminatedBuffer()==uchars) {
1952 errln("UnicodeString(read-only-alias).truncate().getTerminatedBuffer() "
1953 "did not allocate and copy as expected.");
1954 }
1955 if(uchars[1]!=0x62) {
1956 errln("UnicodeString(read-only-alias).truncate().getTerminatedBuffer() "
1957 "modified the original buffer.");
1958 }
1959 if(1!=u_strlen(alias.getTerminatedBuffer())) {
1960 errln("UnicodeString(read-only-alias).truncate().getTerminatedBuffer() "
1961 "does not return a buffer terminated at the proper length.");
1962 }
1963
1964 alias.setTo(TRUE, uchars, 2);
1965 if(alias.length()!=2 || alias.getBuffer()!=uchars || alias.getTerminatedBuffer()!=uchars) {
1966 errln("UnicodeString read-only-aliasing setTo() does not behave as expected.");
1967 return;
1968 }
1969 alias.remove();
1970 if(alias.length()!=0) {
1971 errln("UnicodeString(read-only-alias).remove() did not work.");
1972 }
1973 if(alias.getTerminatedBuffer()==uchars) {
1974 errln("UnicodeString(read-only-alias).remove().getTerminatedBuffer() "
1975 "did not un-alias as expected.");
1976 }
1977 if(uchars[0]!=0x61) {
1978 errln("UnicodeString(read-only-alias).remove().getTerminatedBuffer() "
1979 "modified the original buffer.");
1980 }
1981 if(0!=u_strlen(alias.getTerminatedBuffer())) {
1982 errln("UnicodeString.setTo(read-only-alias).remove().getTerminatedBuffer() "
1983 "does not return a buffer terminated at length 0.");
1984 }
1985
1986 UnicodeString longString=UNICODE_STRING_SIMPLE("abcdefghijklmnopqrstuvwxyz0123456789");
1987 alias.setTo(FALSE, longString.getBuffer(), longString.length());
1988 alias.remove(0, 10);
1989 if(longString.compare(10, INT32_MAX, alias)!=0 || alias.getBuffer()!=longString.getBuffer()+10) {
1990 errln("UnicodeString.setTo(read-only-alias).remove(0, 10) did not preserve aliasing as expected.");
1991 }
1992 alias.setTo(FALSE, longString.getBuffer(), longString.length());
1993 alias.remove(27, 99);
1994 if(longString.compare(0, 27, alias)!=0 || alias.getBuffer()!=longString.getBuffer()) {
1995 errln("UnicodeString.setTo(read-only-alias).remove(27, 99) did not preserve aliasing as expected.");
1996 }
1997 alias.setTo(FALSE, longString.getBuffer(), longString.length());
1998 alias.retainBetween(6, 30);
1999 if(longString.compare(6, 24, alias)!=0 || alias.getBuffer()!=longString.getBuffer()+6) {
2000 errln("UnicodeString.setTo(read-only-alias).retainBetween(6, 30) did not preserve aliasing as expected.");
2001 }
2002
2003 UChar abc[]={ 0x61, 0x62, 0x63, 0 };
2004 UBool hasRVO= wrapUChars(abc).getBuffer()==abc;
2005
2006 UnicodeString temp;
2007 temp.fastCopyFrom(longString.tempSubString());
2008 if(temp!=longString || (hasRVO && temp.getBuffer()!=longString.getBuffer())) {
2009 errln("UnicodeString.tempSubString() failed");
2010 }
2011 temp.fastCopyFrom(longString.tempSubString(-3, 5));
2012 if(longString.compare(0, 5, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer())) {
2013 errln("UnicodeString.tempSubString(-3, 5) failed");
2014 }
2015 temp.fastCopyFrom(longString.tempSubString(17));
2016 if(longString.compare(17, INT32_MAX, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer()+17)) {
2017 errln("UnicodeString.tempSubString(17) failed");
2018 }
2019 temp.fastCopyFrom(longString.tempSubString(99));
2020 if(!temp.isEmpty()) {
2021 errln("UnicodeString.tempSubString(99) failed");
2022 }
2023 temp.fastCopyFrom(longString.tempSubStringBetween(6));
2024 if(longString.compare(6, INT32_MAX, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer()+6)) {
2025 errln("UnicodeString.tempSubStringBetween(6) failed");
2026 }
2027 temp.fastCopyFrom(longString.tempSubStringBetween(8, 18));
2028 if(longString.compare(8, 10, temp)!=0 || (hasRVO && temp.getBuffer()!=longString.getBuffer()+8)) {
2029 errln("UnicodeString.tempSubStringBetween(8, 18) failed");
2030 }
2031 UnicodeString bogusString;
2032 bogusString.setToBogus();
2033 temp.fastCopyFrom(bogusString.tempSubStringBetween(8, 18));
2034 if(!temp.isBogus()) {
2035 errln("UnicodeString.setToBogus().tempSubStringBetween(8, 18) failed");
2036 }
2037 }
2038
2039 void
2040 UnicodeStringTest::doTestAppendable(UnicodeString &dest, Appendable &app) {
2041 static const UChar cde[3]={ 0x63, 0x64, 0x65 };
2042 static const UChar fg[3]={ 0x66, 0x67, 0 };
2043 if(!app.reserveAppendCapacity(12)) {
2044 errln("Appendable.reserve(12) failed");
2045 }
2046 app.appendCodeUnit(0x61);
2047 app.appendCodePoint(0x62);
2048 app.appendCodePoint(0x50000);
2049 app.appendString(cde, 3);
2050 app.appendString(fg, -1);
2051 UChar scratch[3];
2052 int32_t capacity=-1;
2053 UChar *buffer=app.getAppendBuffer(3, 3, scratch, 3, &capacity);
2054 if(capacity<3) {
2055 errln("Appendable.getAppendBuffer(min=3) returned capacity=%d<3", (int)capacity);
2056 return;
2057 }
2058 static const UChar hij[3]={ 0x68, 0x69, 0x6a };
2059 u_memcpy(buffer, hij, 3);
2060 app.appendString(buffer, 3);
2061 if(dest!=UNICODE_STRING_SIMPLE("ab\\U00050000cdefghij").unescape()) {
2062 errln("Appendable.append(...) failed");
2063 }
2064 buffer=app.getAppendBuffer(0, 3, scratch, 3, &capacity);
2065 if(buffer!=NULL || capacity!=0) {
2066 errln("Appendable.getAppendBuffer(min=0) failed");
2067 }
2068 capacity=1;
2069 buffer=app.getAppendBuffer(3, 3, scratch, 2, &capacity);
2070 if(buffer!=NULL || capacity!=0) {
2071 errln("Appendable.getAppendBuffer(scratch<min) failed");
2072 }
2073 }
2074
2075 class SimpleAppendable : public Appendable {
2076 public:
2077 explicit SimpleAppendable(UnicodeString &dest) : str(dest) {}
2078 virtual UBool appendCodeUnit(UChar c) { str.append(c); return TRUE; }
2079 SimpleAppendable &reset() { str.remove(); return *this; }
2080 private:
2081 UnicodeString &str;
2082 };
2083
2084 void
2085 UnicodeStringTest::TestAppendable() {
2086 UnicodeString dest;
2087 SimpleAppendable app(dest);
2088 doTestAppendable(dest, app);
2089 }
2090
2091 void
2092 UnicodeStringTest::TestUnicodeStringImplementsAppendable() {
2093 UnicodeString dest;
2094 UnicodeStringAppendable app(dest);
2095 doTestAppendable(dest, app);
2096 }
2097
2098 void
2099 UnicodeStringTest::TestSizeofUnicodeString() {
2100 // See the comments in unistr.h near the declaration of UnicodeString's fields.
2101 size_t sizeofUniStr=sizeof(UnicodeString);
2102 size_t expected;
2103 switch(sizeof(void *)) {
2104 case 4:
2105 expected=32;
2106 break;
2107 case 8:
2108 expected=40;
2109 break;
2110 default:
2111 logln("This platform has neither 32-bit nor 64-bit pointers.");
2112 return;
2113 }
2114 if(expected!=sizeofUniStr) {
2115 errln("sizeof(UnicodeString)=%d, expected %d", (int)sizeofUniStr, (int)expected);
2116 }
2117 }