• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 2002-2009, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 *******************************************************************************
8 *   file name:  cstrcase.c
9 *   encoding:   US-ASCII
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 *   created on: 2002feb21
14 *   created by: Markus W. Scherer
15 *
16 *   Test file for string casing C API functions.
17 */
18 
19 #include <string.h>
20 #include "unicode/utypes.h"
21 #include "unicode/uchar.h"
22 #include "unicode/ustring.h"
23 #include "unicode/uloc.h"
24 #include "unicode/ubrk.h"
25 #include "unicode/ucasemap.h"
26 #include "cmemory.h"
27 #include "cintltst.h"
28 
29 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
30 
31 /* test string case mapping functions --------------------------------------- */
32 
33 static void
TestCaseLower(void)34 TestCaseLower(void) {
35     static const UChar
36 
37     beforeLower[]= { 0x61, 0x42, 0x49,  0x3a3, 0xdf, 0x3a3, 0x2f, 0xd93f, 0xdfff },
38     lowerRoot[]=   { 0x61, 0x62, 0x69,  0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff },
39     lowerTurkish[]={ 0x61, 0x62, 0x131, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff };
40 
41     UChar buffer[32];
42     int32_t length;
43     UErrorCode errorCode;
44 
45     /* lowercase with root locale and separate buffers */
46     buffer[0]=0xabcd;
47     errorCode=U_ZERO_ERROR;
48     length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
49                         beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
50                         "",
51                         &errorCode);
52     if( U_FAILURE(errorCode) ||
53         length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) ||
54         uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)!=0 ||
55         buffer[length]!=0
56     ) {
57         log_err("error in u_strToLower(root locale)=%ld error=%s string matches: %s\t\nlowerRoot=%s\t\nbuffer=%s\n",
58             length,
59             u_errorName(errorCode),
60             uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)==0 &&
61 buffer[length]==0 ? "yes" : "no",
62             aescstrdup(lowerRoot,-1),
63             aescstrdup(buffer,-1));
64     }
65 
66     /* lowercase with turkish locale and in the same buffer */
67     uprv_memcpy(buffer, beforeLower, sizeof(beforeLower));
68     buffer[sizeof(beforeLower)/U_SIZEOF_UCHAR]=0;
69     errorCode=U_ZERO_ERROR;
70     length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
71                         buffer, -1, /* implicit srcLength */
72                         "tr",
73                         &errorCode);
74     if( U_FAILURE(errorCode) ||
75         length!=(sizeof(lowerTurkish)/U_SIZEOF_UCHAR) ||
76         uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)!=0 ||
77         buffer[length]!=0
78     ) {
79         log_err("error in u_strToLower(turkish locale)=%ld error=%s string matches: %s\n",
80             length,
81             u_errorName(errorCode),
82             uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
83     }
84 
85     /* test preflighting */
86     buffer[0]=buffer[2]=0xabcd;
87     errorCode=U_ZERO_ERROR;
88     length=u_strToLower(buffer, 2, /* set destCapacity=2 */
89                         beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
90                         "",
91                         &errorCode);
92     if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
93         length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) ||
94         uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)!=0 ||
95         buffer[2]!=0xabcd
96     ) {
97         log_err("error in u_strToLower(root locale preflighting)=%ld error=%s string matches: %s\n",
98             length,
99             u_errorName(errorCode),
100             uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no");
101     }
102 
103     /* test error handling */
104     errorCode=U_ZERO_ERROR;
105     length=u_strToLower(NULL, sizeof(buffer)/U_SIZEOF_UCHAR,
106                         beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
107                         "",
108                         &errorCode);
109     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
110         log_err("error in u_strToLower(root locale dest=NULL)=%ld error=%s\n",
111             length,
112             u_errorName(errorCode));
113     }
114 
115     buffer[0]=0xabcd;
116     errorCode=U_ZERO_ERROR;
117     length=u_strToLower(buffer, -1,
118                         beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
119                         "",
120                         &errorCode);
121     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
122         buffer[0]!=0xabcd
123     ) {
124         log_err("error in u_strToLower(root locale destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n",
125             length,
126             u_errorName(errorCode),
127             buffer[0]);
128     }
129 }
130 
131 static void
TestCaseUpper(void)132 TestCaseUpper(void) {
133     static const UChar
134 
135     beforeUpper[]= { 0x61, 0x42, 0x69,  0x3c2, 0xdf,       0x3c3, 0x2f, 0xfb03,           0xd93f, 0xdfff },
136     upperRoot[]=   { 0x41, 0x42, 0x49,  0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0xd93f, 0xdfff },
137     upperTurkish[]={ 0x41, 0x42, 0x130, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0xd93f, 0xdfff };
138 
139     UChar buffer[32];
140     int32_t length;
141     UErrorCode errorCode;
142 
143     /* uppercase with root locale and in the same buffer */
144     uprv_memcpy(buffer, beforeUpper, sizeof(beforeUpper));
145     errorCode=U_ZERO_ERROR;
146     length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
147                         buffer, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
148                         "",
149                         &errorCode);
150     if( U_FAILURE(errorCode) ||
151         length!=(sizeof(upperRoot)/U_SIZEOF_UCHAR) ||
152         uprv_memcmp(upperRoot, buffer, length*U_SIZEOF_UCHAR)!=0 ||
153         buffer[length]!=0
154     ) {
155         log_err("error in u_strToUpper(root locale)=%ld error=%s string matches: %s\n",
156             length,
157             u_errorName(errorCode),
158             uprv_memcmp(upperRoot, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
159     }
160 
161     /* uppercase with turkish locale and separate buffers */
162     buffer[0]=0xabcd;
163     errorCode=U_ZERO_ERROR;
164     length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
165                         beforeUpper, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
166                         "tr",
167                         &errorCode);
168     if( U_FAILURE(errorCode) ||
169         length!=(sizeof(upperTurkish)/U_SIZEOF_UCHAR) ||
170         uprv_memcmp(upperTurkish, buffer, length*U_SIZEOF_UCHAR)!=0 ||
171         buffer[length]!=0
172     ) {
173         log_err("error in u_strToUpper(turkish locale)=%ld error=%s string matches: %s\n",
174             length,
175             u_errorName(errorCode),
176             uprv_memcmp(upperTurkish, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
177     }
178 
179     /* test preflighting */
180     errorCode=U_ZERO_ERROR;
181     length=u_strToUpper(NULL, 0,
182                         beforeUpper, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
183                         "tr",
184                         &errorCode);
185     if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
186         length!=(sizeof(upperTurkish)/U_SIZEOF_UCHAR)
187     ) {
188         log_err("error in u_strToUpper(turkish locale pure preflighting)=%ld error=%s\n",
189             length,
190             u_errorName(errorCode));
191     }
192 
193     /* test error handling */
194     buffer[0]=0xabcd;
195     errorCode=U_ZERO_ERROR;
196     length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
197                         NULL, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
198                         "tr",
199                         &errorCode);
200     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
201         buffer[0]!=0xabcd
202     ) {
203         log_err("error in u_strToUpper(turkish locale src=NULL)=%ld error=%s buffer[0]==0x%lx\n",
204             length,
205             u_errorName(errorCode),
206             buffer[0]);
207     }
208 
209     buffer[0]=0xabcd;
210     errorCode=U_ZERO_ERROR;
211     length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
212                         beforeUpper, -2,
213                         "tr",
214                         &errorCode);
215     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
216         buffer[0]!=0xabcd
217     ) {
218         log_err("error in u_strToUpper(turkish locale srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n",
219             length,
220             u_errorName(errorCode),
221             buffer[0]);
222     }
223 }
224 
225 #if !UCONFIG_NO_BREAK_ITERATION
226 
227 static void
TestCaseTitle(void)228 TestCaseTitle(void) {
229     static const UChar
230 
231     beforeTitle[]= { 0x61, 0x42, 0x20, 0x69,  0x3c2, 0x20, 0xdf,       0x3c3, 0x2f, 0xfb03,           0xd93f, 0xdfff },
232     titleWord[]=   { 0x41, 0x62, 0x20, 0x49,  0x3c2, 0x20, 0x53, 0x73, 0x3c3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff },
233     titleChar[]=   { 0x41, 0x42, 0x20, 0x49,  0x3a3, 0x20, 0x53, 0x73, 0x3a3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff };
234 
235     UChar buffer[32];
236     UBreakIterator *titleIterChars;
237     int32_t length;
238     UErrorCode errorCode;
239 
240     errorCode=U_ZERO_ERROR;
241     titleIterChars=ubrk_open(UBRK_CHARACTER, "", beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, &errorCode);
242     if(U_FAILURE(errorCode)) {
243         log_err_status(errorCode, "error: ubrk_open(UBRK_CHARACTER)->%s\n", u_errorName(errorCode));
244         return;
245     }
246 
247     /* titlecase with standard break iterator and in the same buffer */
248     uprv_memcpy(buffer, beforeTitle, sizeof(beforeTitle));
249     errorCode=U_ZERO_ERROR;
250     length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
251                         buffer, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
252                         NULL, "",
253                         &errorCode);
254     if( U_FAILURE(errorCode) ||
255         length!=(sizeof(titleWord)/U_SIZEOF_UCHAR) ||
256         uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)!=0 ||
257         buffer[length]!=0
258     ) {
259         log_err("error in u_strToTitle(standard iterator)=%ld error=%s string matches: %s\n",
260             length,
261             u_errorName(errorCode),
262             uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
263     }
264 
265     /* titlecase with UBRK_CHARACTERS and separate buffers */
266     buffer[0]=0xabcd;
267     errorCode=U_ZERO_ERROR;
268     length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
269                         beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
270                         titleIterChars, "",
271                         &errorCode);
272     if( U_FAILURE(errorCode) ||
273         length!=(sizeof(titleChar)/U_SIZEOF_UCHAR) ||
274         uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)!=0 ||
275         buffer[length]!=0
276     ) {
277         log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s string matches: %s\n",
278             length,
279             u_errorName(errorCode),
280             uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
281     }
282 
283     /* test preflighting */
284     errorCode=U_ZERO_ERROR;
285     length=u_strToTitle(NULL, 0,
286                         beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
287                         titleIterChars, "",
288                         &errorCode);
289     if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
290         length!=(sizeof(titleChar)/U_SIZEOF_UCHAR)
291     ) {
292         log_err("error in u_strToTitle(UBRK_CHARACTERS pure preflighting)=%ld error=%s\n",
293             length,
294             u_errorName(errorCode));
295     }
296 
297     /* test error handling */
298     buffer[0]=0xabcd;
299     errorCode=U_ZERO_ERROR;
300     length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
301                         NULL, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
302                         titleIterChars, "",
303                         &errorCode);
304     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
305         buffer[0]!=0xabcd
306     ) {
307         log_err("error in u_strToTitle(UBRK_CHARACTERS src=NULL)=%ld error=%s buffer[0]==0x%lx\n",
308             length,
309             u_errorName(errorCode),
310             buffer[0]);
311     }
312 
313     buffer[0]=0xabcd;
314     errorCode=U_ZERO_ERROR;
315     length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
316                         beforeTitle, -2,
317                         titleIterChars, "",
318                         &errorCode);
319     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
320         buffer[0]!=0xabcd
321     ) {
322         log_err("error in u_strToTitle(UBRK_CHARACTERS srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n",
323             length,
324             u_errorName(errorCode),
325             buffer[0]);
326     }
327 
328     ubrk_close(titleIterChars);
329 }
330 
331 static void
TestCaseDutchTitle(void)332 TestCaseDutchTitle(void) {
333     static const UChar
334 
335     beforeTitle[]= { 0x69, 0x6A, 0x73, 0x73,  0x45, 0x6c, 0x20, 0x69, 0x67, 0x6c, 0x4f, 0x6f , 0x20 , 0x49, 0x4A, 0x53, 0x53, 0x45, 0x4C },
336     titleRoot[]=   { 0x49, 0x6A, 0x73, 0x73,  0x65, 0x6c, 0x20, 0x49, 0x67, 0x6c, 0x6f, 0x6f , 0x20 , 0x49, 0x6A, 0x73, 0x73, 0x65, 0x6C },
337     titleDutch[]=  { 0x49, 0x4A, 0x73, 0x73,  0x65, 0x6c, 0x20, 0x49, 0x67, 0x6c, 0x6f, 0x6f , 0x20 , 0x49, 0x4A, 0x73, 0x73, 0x65, 0x6C };
338 
339     UChar buffer[32];
340     UBreakIterator *titleIterWord;
341     int32_t length;
342     UErrorCode errorCode;
343 
344     errorCode=U_ZERO_ERROR;
345     titleIterWord=ubrk_open(UBRK_WORD, "", beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, &errorCode);
346     if(U_FAILURE(errorCode)) {
347         log_err_status(errorCode, "error: ubrk_open(UBRK_WORD)->%s\n", u_errorName(errorCode));
348         return;
349     }
350 
351     /* titlecase with default locale */
352     buffer[0]=0xabcd;
353     errorCode=U_ZERO_ERROR;
354     length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
355                         beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
356                         titleIterWord, "",
357                         &errorCode);
358     if( U_FAILURE(errorCode) ||
359         length!=(sizeof(titleRoot)/U_SIZEOF_UCHAR) ||
360         uprv_memcmp(titleRoot, buffer, length*U_SIZEOF_UCHAR)!=0 ||
361         buffer[length]!=0
362     ) {
363         char charsOut[21];
364         u_UCharsToChars(buffer,charsOut,sizeof(charsOut));
365         log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s root locale string matches: %s\noutput buffer is {%s}\n",
366             length,
367             u_errorName(errorCode),
368             uprv_memcmp(titleRoot, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no", charsOut);
369     }
370     /* titlecase with Dutch locale */
371     buffer[0]=0xabcd;
372     errorCode=U_ZERO_ERROR;
373     length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
374                         beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
375                         titleIterWord, "nl",
376                         &errorCode);
377     if( U_FAILURE(errorCode) ||
378         length!=(sizeof(titleDutch)/U_SIZEOF_UCHAR) ||
379         uprv_memcmp(titleDutch, buffer, length*U_SIZEOF_UCHAR)!=0 ||
380         buffer[length]!=0
381     ) {
382         char charsOut[21];
383         u_UCharsToChars(buffer,charsOut,sizeof(charsOut));
384         log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s dutch locale string matches: %s\noutput buffer is {%s}\n",
385             length,
386             u_errorName(errorCode),
387             uprv_memcmp(titleDutch, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no", charsOut);
388     }
389 
390     ubrk_close(titleIterWord);
391 }
392 
393 #endif
394 
395 /* test case folding and case-insensitive string compare -------------------- */
396 
397 static void
TestCaseFolding(void)398 TestCaseFolding(void) {
399     /*
400      * CaseFolding.txt says about i and its cousins:
401      *   0049; C; 0069; # LATIN CAPITAL LETTER I
402      *   0049; T; 0131; # LATIN CAPITAL LETTER I
403      *
404      *   0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE
405      *   0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE
406      * That's all.
407      * See CaseFolding.txt and the Unicode Standard for how to apply the case foldings.
408      */
409     static const UChar32
410     simple[]={
411         /* input, default, exclude special i */
412         0x61,   0x61,  0x61,
413         0x49,   0x69,  0x131,
414         0x130,  0x130, 0x69,
415         0x131,  0x131, 0x131,
416         0xdf,   0xdf,  0xdf,
417         0xfb03, 0xfb03, 0xfb03,
418         0x1040e,0x10436,0x10436,
419         0x5ffff,0x5ffff,0x5ffff
420     };
421 
422     static const UChar
423     mixed[]=                { 0x61, 0x42, 0x130,       0x49,  0x131, 0x3d0, 0xdf,       0xfb03,           0xd93f, 0xdfff },
424     foldedDefault[]=        { 0x61, 0x62, 0x69, 0x307, 0x69,  0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff },
425     foldedExcludeSpecialI[]={ 0x61, 0x62, 0x69,        0x131, 0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff };
426 
427     UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 };
428 
429     const UChar32 *p;
430     int32_t i;
431 
432     UChar buffer[32];
433     int32_t length;
434     UErrorCode errorCode;
435     UBool isUnicode_3_1;
436 
437     /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */
438     u_getUnicodeVersion(unicodeVersion);
439     isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0;
440 
441     /* test simple case folding */
442     p=simple;
443     for(i=0; i<sizeof(simple)/12; p+=3, ++i) {
444         if(u_foldCase(p[0], U_FOLD_CASE_DEFAULT)!=p[1]) {
445             log_err("error: u_foldCase(0x%04lx, default)=0x%04lx instead of 0x%04lx\n",
446                     p[0], u_foldCase(p[0], U_FOLD_CASE_DEFAULT), p[1]);
447             return;
448         }
449 
450         if(isUnicode_3_1 && u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I)!=p[2]) {
451             log_err("error: u_foldCase(0x%04lx, exclude special i)=0x%04lx instead of 0x%04lx\n",
452                     p[0], u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I), p[2]);
453             return;
454         }
455     }
456 
457     /* test full string case folding with default option and separate buffers */
458     buffer[0]=0xabcd;
459     errorCode=U_ZERO_ERROR;
460     length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
461                         mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
462                         U_FOLD_CASE_DEFAULT,
463                         &errorCode);
464     if( U_FAILURE(errorCode) ||
465         length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) ||
466         uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 ||
467         buffer[length]!=0
468     ) {
469         log_err("error in u_strFoldCase(default)=%ld error=%s string matches: %s\n",
470             length,
471             u_errorName(errorCode),
472             uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
473     }
474 
475     /* exclude special i */
476     if(isUnicode_3_1) {
477         buffer[0]=0xabcd;
478         errorCode=U_ZERO_ERROR;
479         length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
480                             mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
481                             U_FOLD_CASE_EXCLUDE_SPECIAL_I,
482                             &errorCode);
483         if( U_FAILURE(errorCode) ||
484             length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) ||
485             uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 ||
486             buffer[length]!=0
487         ) {
488             log_err("error in u_strFoldCase(exclude special i)=%ld error=%s string matches: %s\n",
489                 length,
490                 u_errorName(errorCode),
491                 uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
492         }
493     }
494 
495     /* test full string case folding with default option and in the same buffer */
496     uprv_memcpy(buffer, mixed, sizeof(mixed));
497     buffer[sizeof(mixed)/U_SIZEOF_UCHAR]=0;
498     errorCode=U_ZERO_ERROR;
499     length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
500                         buffer, -1, /* implicit srcLength */
501                         U_FOLD_CASE_DEFAULT,
502                         &errorCode);
503     if( U_FAILURE(errorCode) ||
504         length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) ||
505         uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 ||
506         buffer[length]!=0
507     ) {
508         log_err("error in u_strFoldCase(default same buffer)=%ld error=%s string matches: %s\n",
509             length,
510             u_errorName(errorCode),
511             uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
512     }
513 
514     /* test full string case folding, exclude special i, in the same buffer */
515     if(isUnicode_3_1) {
516         uprv_memcpy(buffer, mixed, sizeof(mixed));
517         errorCode=U_ZERO_ERROR;
518         length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
519                             buffer, sizeof(mixed)/U_SIZEOF_UCHAR,
520                             U_FOLD_CASE_EXCLUDE_SPECIAL_I,
521                             &errorCode);
522         if( U_FAILURE(errorCode) ||
523             length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) ||
524             uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 ||
525             buffer[length]!=0
526         ) {
527             log_err("error in u_strFoldCase(exclude special i same buffer)=%ld error=%s string matches: %s\n",
528                 length,
529                 u_errorName(errorCode),
530                 uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
531         }
532     }
533 
534     /* test preflighting */
535     buffer[0]=buffer[2]=0xabcd;
536     errorCode=U_ZERO_ERROR;
537     length=u_strFoldCase(buffer, 2, /* set destCapacity=2 */
538                         mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
539                         U_FOLD_CASE_DEFAULT,
540                         &errorCode);
541     if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
542         length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) ||
543         uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)!=0 ||
544         buffer[2]!=0xabcd
545     ) {
546         log_err("error in u_strFoldCase(default preflighting)=%ld error=%s string matches: %s\n",
547             length,
548             u_errorName(errorCode),
549             uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no");
550     }
551 
552     errorCode=U_ZERO_ERROR;
553     length=u_strFoldCase(NULL, 0,
554                         mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
555                         U_FOLD_CASE_DEFAULT,
556                         &errorCode);
557     if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
558         length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR)
559     ) {
560         log_err("error in u_strFoldCase(default pure preflighting)=%ld error=%s\n",
561             length,
562             u_errorName(errorCode));
563     }
564 
565     /* test error handling */
566     errorCode=U_ZERO_ERROR;
567     length=u_strFoldCase(NULL, sizeof(buffer)/U_SIZEOF_UCHAR,
568                         mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
569                         U_FOLD_CASE_DEFAULT,
570                         &errorCode);
571     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
572         log_err("error in u_strFoldCase(default dest=NULL)=%ld error=%s\n",
573             length,
574             u_errorName(errorCode));
575     }
576 
577     buffer[0]=0xabcd;
578     errorCode=U_ZERO_ERROR;
579     length=u_strFoldCase(buffer, -1,
580                         mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
581                         U_FOLD_CASE_DEFAULT,
582                         &errorCode);
583     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
584         buffer[0]!=0xabcd
585     ) {
586         log_err("error in u_strFoldCase(default destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n",
587             length,
588             u_errorName(errorCode),
589             buffer[0]);
590     }
591 
592     buffer[0]=0xabcd;
593     errorCode=U_ZERO_ERROR;
594     length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
595                         NULL, sizeof(mixed)/U_SIZEOF_UCHAR,
596                         U_FOLD_CASE_EXCLUDE_SPECIAL_I,
597                         &errorCode);
598     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
599         buffer[0]!=0xabcd
600     ) {
601         log_err("error in u_strFoldCase(exclude special i src=NULL)=%ld error=%s buffer[0]==0x%lx\n",
602             length,
603             u_errorName(errorCode),
604             buffer[0]);
605     }
606 
607     buffer[0]=0xabcd;
608     errorCode=U_ZERO_ERROR;
609     length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
610                         mixed, -2,
611                         U_FOLD_CASE_EXCLUDE_SPECIAL_I,
612                         &errorCode);
613     if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
614         buffer[0]!=0xabcd
615     ) {
616         log_err("error in u_strFoldCase(exclude special i srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n",
617             length,
618             u_errorName(errorCode),
619             buffer[0]);
620     }
621 }
622 
623 static void
TestCaseCompare(void)624 TestCaseCompare(void) {
625     static const UChar
626 
627     mixed[]=               { 0x61, 0x42, 0x131, 0x3a3, 0xdf,       0xfb03,           0xd93f, 0xdfff, 0 },
628     otherDefault[]=        { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdfff, 0 },
629     otherExcludeSpecialI[]={ 0x41, 0x62, 0x131, 0x3c3, 0x53, 0x73, 0x66, 0x46, 0x69, 0xd93f, 0xdfff, 0 },
630     different[]=           { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdffd, 0 };
631 
632     UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 };
633 
634     int32_t result, lenMixed, lenOtherDefault, lenOtherExcludeSpecialI, lenDifferent;
635     UErrorCode errorCode;
636     UBool isUnicode_3_1;
637 
638     errorCode=U_ZERO_ERROR;
639 
640     lenMixed=u_strlen(mixed);
641     lenOtherDefault=u_strlen(otherDefault);
642     lenOtherExcludeSpecialI=u_strlen(otherExcludeSpecialI);
643     lenDifferent=u_strlen(different);
644 
645     /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */
646     u_getUnicodeVersion(unicodeVersion);
647     isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0;
648 
649     /* test u_strcasecmp() */
650     result=u_strcasecmp(mixed, otherDefault, U_FOLD_CASE_DEFAULT);
651     if(result!=0) {
652         log_err("error: u_strcasecmp(mixed, other, default)=%ld instead of 0\n", result);
653     }
654     result=u_strCaseCompare(mixed, -1, otherDefault, -1, U_FOLD_CASE_DEFAULT, &errorCode);
655     if(result!=0) {
656         log_err("error: u_strCaseCompare(mixed, other, default)=%ld instead of 0\n", result);
657     }
658 
659     /* test u_strcasecmp() - exclude special i */
660     result=u_strcasecmp(mixed, otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I);
661     if(result!=0) {
662         log_err("error: u_strcasecmp(mixed, other, exclude special i)=%ld instead of 0\n", result);
663     }
664     result=u_strCaseCompare(mixed, lenMixed, otherExcludeSpecialI, lenOtherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode);
665     if(result!=0) {
666         log_err("error: u_strCaseCompare(mixed, other, exclude special i)=%ld instead of 0\n", result);
667     }
668 
669     /* test u_strcasecmp() */
670     result=u_strcasecmp(mixed, different, U_FOLD_CASE_DEFAULT);
671     if(result<=0) {
672         log_err("error: u_strcasecmp(mixed, different, default)=%ld instead of positive\n", result);
673     }
674     result=u_strCaseCompare(mixed, -1, different, lenDifferent, U_FOLD_CASE_DEFAULT, &errorCode);
675     if(result<=0) {
676         log_err("error: u_strCaseCompare(mixed, different, default)=%ld instead of positive\n", result);
677     }
678 
679     /* test u_strncasecmp() - stop before the sharp s (U+00df) */
680     result=u_strncasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT);
681     if(result!=0) {
682         log_err("error: u_strncasecmp(mixed, different, 4, default)=%ld instead of 0\n", result);
683     }
684     result=u_strCaseCompare(mixed, 4, different, 4, U_FOLD_CASE_DEFAULT, &errorCode);
685     if(result!=0) {
686         log_err("error: u_strCaseCompare(mixed, 4, different, 4, default)=%ld instead of 0\n", result);
687     }
688 
689     /* test u_strncasecmp() - stop in the middle of the sharp s (U+00df) */
690     result=u_strncasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT);
691     if(result<=0) {
692         log_err("error: u_strncasecmp(mixed, different, 5, default)=%ld instead of positive\n", result);
693     }
694     result=u_strCaseCompare(mixed, 5, different, 5, U_FOLD_CASE_DEFAULT, &errorCode);
695     if(result<=0) {
696         log_err("error: u_strCaseCompare(mixed, 5, different, 5, default)=%ld instead of positive\n", result);
697     }
698 
699     /* test u_memcasecmp() - stop before the sharp s (U+00df) */
700     result=u_memcasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT);
701     if(result!=0) {
702         log_err("error: u_memcasecmp(mixed, different, 4, default)=%ld instead of 0\n", result);
703     }
704 
705     /* test u_memcasecmp() - stop in the middle of the sharp s (U+00df) */
706     result=u_memcasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT);
707     if(result<=0) {
708         log_err("error: u_memcasecmp(mixed, different, 5, default)=%ld instead of positive\n", result);
709     }
710 }
711 
712 /* test UCaseMap ------------------------------------------------------------ */
713 
714 /*
715  * API test for UCaseMap;
716  * test cases for actual case mappings using UCaseMap see
717  * intltest utility/UnicodeStringTest/StringCaseTest/TestCasing
718  */
719 static void
TestUCaseMap(void)720 TestUCaseMap(void) {
721     static const char
722         aBc[] ={ 0x61, 0x42, 0x63, 0 },
723         abc[] ={ 0x61, 0x62, 0x63, 0 },
724         ABCg[]={ 0x41, 0x42, 0x43, 0x67, 0 },
725         defg[]={ 0x64, 0x65, 0x66, 0x67, 0 };
726     char utf8Out[8];
727 
728     UCaseMap *csm;
729     const char *locale;
730     uint32_t options;
731     int32_t length;
732     UErrorCode errorCode;
733 
734     errorCode=U_ZERO_ERROR;
735     csm=ucasemap_open("tur", 0xa5, &errorCode);
736     if(U_FAILURE(errorCode)) {
737         log_err("ucasemap_open(\"tur\") failed - %s\n", u_errorName(errorCode));
738         return;
739     }
740     locale=ucasemap_getLocale(csm);
741     if(0!=strcmp(locale, "tr")) {
742         log_err("ucasemap_getLocale(ucasemap_open(\"tur\"))==%s!=\"tr\"\n", locale);
743     }
744     /* overly long locale IDs get truncated to their language code to avoid unnecessary allocation */
745     ucasemap_setLocale(csm, "I-kLInGOn-the-quick-brown-fox-jumps-over-the-lazy-dog", &errorCode);
746     locale=ucasemap_getLocale(csm);
747     if(0!=strcmp(locale, "i-klingon")) {
748         log_err("ucasemap_getLocale(ucasemap_setLocale(\"I-kLInGOn-the-quick-br...\"))==%s!=\"i-klingon\"\n", locale);
749     }
750 
751     errorCode=U_ZERO_ERROR;
752     options=ucasemap_getOptions(csm);
753     if(options!=0xa5) {
754         log_err("ucasemap_getOptions(ucasemap_open(0xa5))==0x%lx!=0xa5\n", (long)options);
755     }
756     ucasemap_setOptions(csm, 0x333333, &errorCode);
757     options=ucasemap_getOptions(csm);
758     if(options!=0x333333) {
759         log_err("ucasemap_getOptions(ucasemap_setOptions(0x333333))==0x%lx!=0x333333\n", (long)options);
760     }
761 
762     /* test case mapping API; not all permutations necessary due to shared implementation code */
763 
764     /* NUL terminated source */
765     errorCode=U_ZERO_ERROR;
766     length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
767     if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) {
768         log_err("ucasemap_utf8ToLower(aBc\\0) failed\n");
769     }
770 
771     /* incoming failure code */
772     errorCode=U_PARSE_ERROR;
773     strcpy(utf8Out, defg);
774     length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
775     if(errorCode!=U_PARSE_ERROR || 0!=strcmp(defg, utf8Out)) {
776         log_err("ucasemap_utf8ToLower(failure) failed\n");
777     }
778 
779     /* overlapping input & output */
780     errorCode=U_ZERO_ERROR;
781     strcpy(utf8Out, aBc);
782     length=ucasemap_utf8ToUpper(csm, utf8Out, 2, utf8Out+1, 2, &errorCode);
783     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) {
784         log_err("ucasemap_utf8ToUpper(overlap 1) failed\n");
785     }
786 
787     /* overlap in the other direction */
788     errorCode=U_ZERO_ERROR;
789     strcpy(utf8Out, aBc);
790     length=ucasemap_utf8ToUpper(csm, utf8Out+1, 2, utf8Out, 2, &errorCode);
791     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) {
792         log_err("ucasemap_utf8ToUpper(overlap 2) failed\n");
793     }
794 
795     /* NULL destination */
796     errorCode=U_ZERO_ERROR;
797     strcpy(utf8Out, defg);
798     length=ucasemap_utf8ToLower(csm, NULL, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
799     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
800         log_err("ucasemap_utf8ToLower(dest=NULL) failed\n");
801     }
802 
803     /* destCapacity<0 */
804     errorCode=U_ZERO_ERROR;
805     strcpy(utf8Out, defg);
806     length=ucasemap_utf8ToLower(csm, utf8Out, -2, aBc, -1, &errorCode);
807     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
808         log_err("ucasemap_utf8ToLower(destCapacity<0) failed\n");
809     }
810 
811     /* NULL source */
812     errorCode=U_ZERO_ERROR;
813     strcpy(utf8Out, defg);
814     length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), NULL, -1, &errorCode);
815     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
816         log_err("ucasemap_utf8ToLower(src=NULL) failed\n");
817     }
818 
819     /* srcLength<-1 */
820     errorCode=U_ZERO_ERROR;
821     strcpy(utf8Out, defg);
822     length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -2, &errorCode);
823     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
824         log_err("ucasemap_utf8ToLower(srcLength<-1) failed\n");
825     }
826 
827     /* buffer overflow */
828     errorCode=U_ZERO_ERROR;
829     strcpy(utf8Out, defg);
830     length=ucasemap_utf8ToUpper(csm, utf8Out, 2, aBc, 3, &errorCode);
831     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3 || 0!=strcmp(defg+2, utf8Out+2)) {
832         log_err("ucasemap_utf8ToUpper(overflow) failed\n");
833     }
834 
835     /* dest not terminated (leaves g from defg alone) */
836     errorCode=U_ZERO_ERROR;
837     strcpy(utf8Out, defg);
838     length=ucasemap_utf8ToUpper(csm, utf8Out, 3, aBc, 3, &errorCode);
839     if(errorCode!=U_STRING_NOT_TERMINATED_WARNING || length!=3 || 0!=strcmp(ABCg, utf8Out)) {
840         log_err("ucasemap_utf8ToUpper(overflow) failed\n");
841     }
842 
843     /* C API coverage for case folding. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */
844     errorCode=U_ZERO_ERROR;
845     utf8Out[0]=0;
846     length=ucasemap_utf8FoldCase(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, 3, &errorCode);
847     if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) {
848         log_err("ucasemap_utf8FoldCase(aBc) failed\n");
849     }
850 
851     ucasemap_close(csm);
852 }
853 
854 #if !UCONFIG_NO_BREAK_ITERATION
855 
856 /* Try titlecasing with options. */
857 static void
TestUCaseMapToTitle(void)858 TestUCaseMapToTitle(void) {
859     /* "a 'CaT. A 'dOg! 'eTc." where '=U+02BB */
860     /*
861      * Note: The sentence BreakIterator does not recognize a '.'
862      * as a sentence terminator if it is followed by lowercase.
863      * That is why the example has the '!'.
864      */
865     static const UChar
866 
867     beforeTitle[]=      { 0x61, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x54, 0x63, 0x2e },
868     titleWord[]=        { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x44, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x74, 0x63, 0x2e },
869     titleWordNoAdjust[]={ 0x41, 0x20, 0x2bb, 0x63, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x74, 0x63, 0x2e },
870     titleSentNoLower[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x54, 0x63, 0x2e };
871 
872     UChar buffer[32];
873     UCaseMap *csm;
874     UBreakIterator *sentenceIter;
875     const UBreakIterator *iter;
876     int32_t length;
877     UErrorCode errorCode;
878 
879     errorCode=U_ZERO_ERROR;
880     csm=ucasemap_open("", 0, &errorCode);
881     if(U_FAILURE(errorCode)) {
882         log_err("ucasemap_open(\"\") failed - %s\n", u_errorName(errorCode));
883         return;
884     }
885 
886     iter=ucasemap_getBreakIterator(csm);
887     if(iter!=NULL) {
888         log_err("ucasemap_getBreakIterator() returns %p!=NULL before setting any iterator or titlecasing\n", iter);
889     }
890 
891     /* Use default UBreakIterator: Word breaks. */
892     length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
893     if( U_FAILURE(errorCode) ||
894         length!=LENGTHOF(titleWord) ||
895         0!=u_memcmp(buffer, titleWord, length) ||
896         buffer[length]!=0
897     ) {
898         log_err_status(errorCode, "ucasemap_toTitle(default iterator)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
899     }
900     if (U_SUCCESS(errorCode)) {
901         iter=ucasemap_getBreakIterator(csm);
902         if(iter==NULL) {
903             log_err("ucasemap_getBreakIterator() returns NULL after titlecasing\n");
904         }
905     }
906 
907     /* Try U_TITLECASE_NO_BREAK_ADJUSTMENT. */
908     ucasemap_setOptions(csm, U_TITLECASE_NO_BREAK_ADJUSTMENT, &errorCode);
909     if(U_FAILURE(errorCode)) {
910         log_err_status(errorCode, "error: ucasemap_setOptions(U_TITLECASE_NO_BREAK_ADJUSTMENT) failed - %s\n", u_errorName(errorCode));
911         return;
912     }
913 
914     length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
915     if( U_FAILURE(errorCode) ||
916         length!=LENGTHOF(titleWordNoAdjust) ||
917         0!=u_memcmp(buffer, titleWordNoAdjust, length) ||
918         buffer[length]!=0
919     ) {
920         log_err("ucasemap_toTitle(default iterator, no break adjustment)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
921     }
922 
923     /* Set a sentence break iterator. */
924     errorCode=U_ZERO_ERROR;
925     sentenceIter=ubrk_open(UBRK_SENTENCE, "", NULL, 0, &errorCode);
926     if(U_FAILURE(errorCode)) {
927         log_err("error: ubrk_open(UBRK_SENTENCE) failed - %s\n", u_errorName(errorCode));
928         ucasemap_close(csm);
929         return;
930     }
931     ucasemap_setBreakIterator(csm, sentenceIter, &errorCode);
932     if(U_FAILURE(errorCode)) {
933         log_err("error: ucasemap_setBreakIterator(sentence iterator) failed - %s\n", u_errorName(errorCode));
934         ubrk_close(sentenceIter);
935         ucasemap_close(csm);
936         return;
937     }
938     iter=ucasemap_getBreakIterator(csm);
939     if(iter!=sentenceIter) {
940         log_err("ucasemap_getBreakIterator() returns %p!=%p after setting the iterator\n", iter, sentenceIter);
941     }
942 
943     ucasemap_setOptions(csm, U_TITLECASE_NO_LOWERCASE, &errorCode);
944     if(U_FAILURE(errorCode)) {
945         log_err("error: ucasemap_setOptions(U_TITLECASE_NO_LOWERCASE) failed - %s\n", u_errorName(errorCode));
946         return;
947     }
948 
949     /* Use the sentence break iterator with the option. Preflight first. */
950     length=ucasemap_toTitle(csm, NULL, 0, beforeTitle, LENGTHOF(beforeTitle), &errorCode);
951     if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
952         length!=LENGTHOF(titleSentNoLower)
953     ) {
954         log_err("ucasemap_toTitle(preflight sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
955     }
956 
957     errorCode=U_ZERO_ERROR;
958     buffer[0]=0;
959     length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
960     if( U_FAILURE(errorCode) ||
961         length!=LENGTHOF(titleSentNoLower) ||
962         0!=u_memcmp(buffer, titleSentNoLower, length) ||
963         buffer[length]!=0
964     ) {
965         log_err("ucasemap_toTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
966     }
967 
968     /* UTF-8 C API coverage. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */
969     {
970         char utf8BeforeTitle[64], utf8TitleSentNoLower[64], utf8[64];
971         int32_t utf8BeforeTitleLength, utf8TitleSentNoLowerLength;
972 
973         errorCode=U_ZERO_ERROR;
974         u_strToUTF8(utf8BeforeTitle, (int32_t)sizeof(utf8BeforeTitle), &utf8BeforeTitleLength, beforeTitle, LENGTHOF(beforeTitle), &errorCode);
975         u_strToUTF8(utf8TitleSentNoLower, (int32_t)sizeof(utf8TitleSentNoLower), &utf8TitleSentNoLowerLength, titleSentNoLower, LENGTHOF(titleSentNoLower), &errorCode);
976 
977         length=ucasemap_utf8ToTitle(csm, utf8, (int32_t)sizeof(utf8), utf8BeforeTitle, utf8BeforeTitleLength, &errorCode);
978         if( U_FAILURE(errorCode) ||
979             length!=utf8TitleSentNoLowerLength ||
980             0!=uprv_memcmp(utf8, utf8TitleSentNoLower, length) ||
981             utf8[length]!=0
982         ) {
983             log_err("ucasemap_utf8ToTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
984         }
985     }
986 
987     ucasemap_close(csm);
988 }
989 
990 #endif
991 
992 void addCaseTest(TestNode** root);
993 
addCaseTest(TestNode ** root)994 void addCaseTest(TestNode** root) {
995     /* cstrcase.c functions, declared in cucdtst.h */
996     addTest(root, &TestCaseLower, "tsutil/cstrcase/TestCaseLower");
997     addTest(root, &TestCaseUpper, "tsutil/cstrcase/TestCaseUpper");
998 #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO
999     addTest(root, &TestCaseTitle, "tsutil/cstrcase/TestCaseTitle");
1000     addTest(root, &TestCaseDutchTitle, "tsutil/cstrcase/TestCaseDutchTitle");
1001 #endif
1002     addTest(root, &TestCaseFolding, "tsutil/cstrcase/TestCaseFolding");
1003     addTest(root, &TestCaseCompare, "tsutil/cstrcase/TestCaseCompare");
1004     addTest(root, &TestUCaseMap, "tsutil/cstrcase/TestUCaseMap");
1005 #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO
1006     addTest(root, &TestUCaseMapToTitle, "tsutil/cstrcase/TestUCaseMapToTitle");
1007 #endif
1008 }
1009