1/*
2*******************************************************************************
3*
4*   Copyright (C) 2002-2013, 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
33static void
34TestCaseLower(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 &&
61buffer[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
131static void
132TestCaseUpper(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
227static void
228TestCaseTitle(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
331static void
332TestCaseDutchTitle(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
397static void
398TestCaseFolding(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
623static void
624TestCaseCompare(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    (void)lenOtherDefault;    /* Suppress set but not used warning. */
643    lenOtherExcludeSpecialI=u_strlen(otherExcludeSpecialI);
644    lenDifferent=u_strlen(different);
645
646    /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */
647    u_getUnicodeVersion(unicodeVersion);
648    isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0;
649    (void)isUnicode_3_1;    /* Suppress set but not used warning. */
650
651    /* test u_strcasecmp() */
652    result=u_strcasecmp(mixed, otherDefault, U_FOLD_CASE_DEFAULT);
653    if(result!=0) {
654        log_err("error: u_strcasecmp(mixed, other, default)=%ld instead of 0\n", result);
655    }
656    result=u_strCaseCompare(mixed, -1, otherDefault, -1, U_FOLD_CASE_DEFAULT, &errorCode);
657    if(result!=0) {
658        log_err("error: u_strCaseCompare(mixed, other, default)=%ld instead of 0\n", result);
659    }
660
661    /* test u_strcasecmp() - exclude special i */
662    result=u_strcasecmp(mixed, otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I);
663    if(result!=0) {
664        log_err("error: u_strcasecmp(mixed, other, exclude special i)=%ld instead of 0\n", result);
665    }
666    result=u_strCaseCompare(mixed, lenMixed, otherExcludeSpecialI, lenOtherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode);
667    if(result!=0) {
668        log_err("error: u_strCaseCompare(mixed, other, exclude special i)=%ld instead of 0\n", result);
669    }
670
671    /* test u_strcasecmp() */
672    result=u_strcasecmp(mixed, different, U_FOLD_CASE_DEFAULT);
673    if(result<=0) {
674        log_err("error: u_strcasecmp(mixed, different, default)=%ld instead of positive\n", result);
675    }
676    result=u_strCaseCompare(mixed, -1, different, lenDifferent, U_FOLD_CASE_DEFAULT, &errorCode);
677    if(result<=0) {
678        log_err("error: u_strCaseCompare(mixed, different, default)=%ld instead of positive\n", result);
679    }
680
681    /* test u_strncasecmp() - stop before the sharp s (U+00df) */
682    result=u_strncasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT);
683    if(result!=0) {
684        log_err("error: u_strncasecmp(mixed, different, 4, default)=%ld instead of 0\n", result);
685    }
686    result=u_strCaseCompare(mixed, 4, different, 4, U_FOLD_CASE_DEFAULT, &errorCode);
687    if(result!=0) {
688        log_err("error: u_strCaseCompare(mixed, 4, different, 4, default)=%ld instead of 0\n", result);
689    }
690
691    /* test u_strncasecmp() - stop in the middle of the sharp s (U+00df) */
692    result=u_strncasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT);
693    if(result<=0) {
694        log_err("error: u_strncasecmp(mixed, different, 5, default)=%ld instead of positive\n", result);
695    }
696    result=u_strCaseCompare(mixed, 5, different, 5, U_FOLD_CASE_DEFAULT, &errorCode);
697    if(result<=0) {
698        log_err("error: u_strCaseCompare(mixed, 5, different, 5, default)=%ld instead of positive\n", result);
699    }
700
701    /* test u_memcasecmp() - stop before the sharp s (U+00df) */
702    result=u_memcasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT);
703    if(result!=0) {
704        log_err("error: u_memcasecmp(mixed, different, 4, default)=%ld instead of 0\n", result);
705    }
706
707    /* test u_memcasecmp() - stop in the middle of the sharp s (U+00df) */
708    result=u_memcasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT);
709    if(result<=0) {
710        log_err("error: u_memcasecmp(mixed, different, 5, default)=%ld instead of positive\n", result);
711    }
712}
713
714/* test UCaseMap ------------------------------------------------------------ */
715
716/*
717 * API test for UCaseMap;
718 * test cases for actual case mappings using UCaseMap see
719 * intltest utility/UnicodeStringTest/StringCaseTest/TestCasing
720 */
721static void
722TestUCaseMap(void) {
723    static const char
724        aBc[] ={ 0x61, 0x42, 0x63, 0 },
725        abc[] ={ 0x61, 0x62, 0x63, 0 },
726        ABCg[]={ 0x41, 0x42, 0x43, 0x67, 0 },
727        defg[]={ 0x64, 0x65, 0x66, 0x67, 0 };
728    char utf8Out[8];
729
730    UCaseMap *csm;
731    const char *locale;
732    uint32_t options;
733    int32_t length;
734    UErrorCode errorCode;
735
736    errorCode=U_ZERO_ERROR;
737    csm=ucasemap_open("tur", 0xa5, &errorCode);
738    if(U_FAILURE(errorCode)) {
739        log_err("ucasemap_open(\"tur\") failed - %s\n", u_errorName(errorCode));
740        return;
741    }
742    locale=ucasemap_getLocale(csm);
743    if(0!=strcmp(locale, "tr")) {
744        log_err("ucasemap_getLocale(ucasemap_open(\"tur\"))==%s!=\"tr\"\n", locale);
745    }
746    /* overly long locale IDs get truncated to their language code to avoid unnecessary allocation */
747    ucasemap_setLocale(csm, "I-kLInGOn-the-quick-brown-fox-jumps-over-the-lazy-dog", &errorCode);
748    locale=ucasemap_getLocale(csm);
749    if(0!=strcmp(locale, "i-klingon")) {
750        log_err("ucasemap_getLocale(ucasemap_setLocale(\"I-kLInGOn-the-quick-br...\"))==%s!=\"i-klingon\"\n", locale);
751    }
752
753    errorCode=U_ZERO_ERROR;
754    options=ucasemap_getOptions(csm);
755    if(options!=0xa5) {
756        log_err("ucasemap_getOptions(ucasemap_open(0xa5))==0x%lx!=0xa5\n", (long)options);
757    }
758    ucasemap_setOptions(csm, 0x333333, &errorCode);
759    options=ucasemap_getOptions(csm);
760    if(options!=0x333333) {
761        log_err("ucasemap_getOptions(ucasemap_setOptions(0x333333))==0x%lx!=0x333333\n", (long)options);
762    }
763
764    /* test case mapping API; not all permutations necessary due to shared implementation code */
765
766    /* NUL terminated source */
767    errorCode=U_ZERO_ERROR;
768    length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
769    if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) {
770        log_err("ucasemap_utf8ToLower(aBc\\0) failed\n");
771    }
772
773    /* incoming failure code */
774    errorCode=U_PARSE_ERROR;
775    strcpy(utf8Out, defg);
776    length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
777    if(errorCode!=U_PARSE_ERROR || 0!=strcmp(defg, utf8Out)) {
778        log_err("ucasemap_utf8ToLower(failure) failed\n");
779    }
780
781    /* overlapping input & output */
782    errorCode=U_ZERO_ERROR;
783    strcpy(utf8Out, aBc);
784    length=ucasemap_utf8ToUpper(csm, utf8Out, 2, utf8Out+1, 2, &errorCode);
785    if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) {
786        log_err("ucasemap_utf8ToUpper(overlap 1) failed\n");
787    }
788
789    /* overlap in the other direction */
790    errorCode=U_ZERO_ERROR;
791    strcpy(utf8Out, aBc);
792    length=ucasemap_utf8ToUpper(csm, utf8Out+1, 2, utf8Out, 2, &errorCode);
793    if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) {
794        log_err("ucasemap_utf8ToUpper(overlap 2) failed\n");
795    }
796
797    /* NULL destination */
798    errorCode=U_ZERO_ERROR;
799    strcpy(utf8Out, defg);
800    length=ucasemap_utf8ToLower(csm, NULL, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
801    if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
802        log_err("ucasemap_utf8ToLower(dest=NULL) failed\n");
803    }
804
805    /* destCapacity<0 */
806    errorCode=U_ZERO_ERROR;
807    strcpy(utf8Out, defg);
808    length=ucasemap_utf8ToLower(csm, utf8Out, -2, aBc, -1, &errorCode);
809    if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
810        log_err("ucasemap_utf8ToLower(destCapacity<0) failed\n");
811    }
812
813    /* NULL source */
814    errorCode=U_ZERO_ERROR;
815    strcpy(utf8Out, defg);
816    length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), NULL, -1, &errorCode);
817    if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
818        log_err("ucasemap_utf8ToLower(src=NULL) failed\n");
819    }
820
821    /* srcLength<-1 */
822    errorCode=U_ZERO_ERROR;
823    strcpy(utf8Out, defg);
824    length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -2, &errorCode);
825    if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
826        log_err("ucasemap_utf8ToLower(srcLength<-1) failed\n");
827    }
828
829    /* buffer overflow */
830    errorCode=U_ZERO_ERROR;
831    strcpy(utf8Out, defg);
832    length=ucasemap_utf8ToUpper(csm, utf8Out, 2, aBc, 3, &errorCode);
833    if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3 || 0!=strcmp(defg+2, utf8Out+2)) {
834        log_err("ucasemap_utf8ToUpper(overflow) failed\n");
835    }
836
837    /* dest not terminated (leaves g from defg alone) */
838    errorCode=U_ZERO_ERROR;
839    strcpy(utf8Out, defg);
840    length=ucasemap_utf8ToUpper(csm, utf8Out, 3, aBc, 3, &errorCode);
841    if(errorCode!=U_STRING_NOT_TERMINATED_WARNING || length!=3 || 0!=strcmp(ABCg, utf8Out)) {
842        log_err("ucasemap_utf8ToUpper(overflow) failed\n");
843    }
844
845    /* C API coverage for case folding. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */
846    errorCode=U_ZERO_ERROR;
847    utf8Out[0]=0;
848    length=ucasemap_utf8FoldCase(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, 3, &errorCode);
849    if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) {
850        log_err("ucasemap_utf8FoldCase(aBc) failed\n");
851    }
852
853    ucasemap_close(csm);
854}
855
856#if !UCONFIG_NO_BREAK_ITERATION
857
858/* Try titlecasing with options. */
859static void
860TestUCaseMapToTitle(void) {
861    /* "a 'CaT. A 'dOg! 'eTc." where '=U+02BB */
862    /*
863     * Note: The sentence BreakIterator does not recognize a '.'
864     * as a sentence terminator if it is followed by lowercase.
865     * That is why the example has the '!'.
866     */
867    static const UChar
868
869    beforeTitle[]=      { 0x61, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x54, 0x63, 0x2e },
870    titleWord[]=        { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x44, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x74, 0x63, 0x2e },
871    titleWordNoAdjust[]={ 0x41, 0x20, 0x2bb, 0x63, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x74, 0x63, 0x2e },
872    titleSentNoLower[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x54, 0x63, 0x2e };
873
874    UChar buffer[32];
875    UCaseMap *csm;
876    UBreakIterator *sentenceIter;
877    const UBreakIterator *iter;
878    int32_t length;
879    UErrorCode errorCode;
880
881    errorCode=U_ZERO_ERROR;
882    csm=ucasemap_open("", 0, &errorCode);
883    if(U_FAILURE(errorCode)) {
884        log_err("ucasemap_open(\"\") failed - %s\n", u_errorName(errorCode));
885        return;
886    }
887
888    iter=ucasemap_getBreakIterator(csm);
889    if(iter!=NULL) {
890        log_err("ucasemap_getBreakIterator() returns %p!=NULL before setting any iterator or titlecasing\n", iter);
891    }
892
893    /* Use default UBreakIterator: Word breaks. */
894    length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
895    if( U_FAILURE(errorCode) ||
896        length!=LENGTHOF(titleWord) ||
897        0!=u_memcmp(buffer, titleWord, length) ||
898        buffer[length]!=0
899    ) {
900        log_err_status(errorCode, "ucasemap_toTitle(default iterator)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
901    }
902    if (U_SUCCESS(errorCode)) {
903        iter=ucasemap_getBreakIterator(csm);
904        if(iter==NULL) {
905            log_err("ucasemap_getBreakIterator() returns NULL after titlecasing\n");
906        }
907    }
908
909    /* Try U_TITLECASE_NO_BREAK_ADJUSTMENT. */
910    ucasemap_setOptions(csm, U_TITLECASE_NO_BREAK_ADJUSTMENT, &errorCode);
911    if(U_FAILURE(errorCode)) {
912        log_err_status(errorCode, "error: ucasemap_setOptions(U_TITLECASE_NO_BREAK_ADJUSTMENT) failed - %s\n", u_errorName(errorCode));
913        return;
914    }
915
916    length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
917    if( U_FAILURE(errorCode) ||
918        length!=LENGTHOF(titleWordNoAdjust) ||
919        0!=u_memcmp(buffer, titleWordNoAdjust, length) ||
920        buffer[length]!=0
921    ) {
922        log_err("ucasemap_toTitle(default iterator, no break adjustment)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
923    }
924
925    /* Set a sentence break iterator. */
926    errorCode=U_ZERO_ERROR;
927    sentenceIter=ubrk_open(UBRK_SENTENCE, "", NULL, 0, &errorCode);
928    if(U_FAILURE(errorCode)) {
929        log_err("error: ubrk_open(UBRK_SENTENCE) failed - %s\n", u_errorName(errorCode));
930        ucasemap_close(csm);
931        return;
932    }
933    ucasemap_setBreakIterator(csm, sentenceIter, &errorCode);
934    if(U_FAILURE(errorCode)) {
935        log_err("error: ucasemap_setBreakIterator(sentence iterator) failed - %s\n", u_errorName(errorCode));
936        ubrk_close(sentenceIter);
937        ucasemap_close(csm);
938        return;
939    }
940    iter=ucasemap_getBreakIterator(csm);
941    if(iter!=sentenceIter) {
942        log_err("ucasemap_getBreakIterator() returns %p!=%p after setting the iterator\n", iter, sentenceIter);
943    }
944
945    ucasemap_setOptions(csm, U_TITLECASE_NO_LOWERCASE, &errorCode);
946    if(U_FAILURE(errorCode)) {
947        log_err("error: ucasemap_setOptions(U_TITLECASE_NO_LOWERCASE) failed - %s\n", u_errorName(errorCode));
948        return;
949    }
950
951    /* Use the sentence break iterator with the option. Preflight first. */
952    length=ucasemap_toTitle(csm, NULL, 0, beforeTitle, LENGTHOF(beforeTitle), &errorCode);
953    if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
954        length!=LENGTHOF(titleSentNoLower)
955    ) {
956        log_err("ucasemap_toTitle(preflight sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
957    }
958
959    errorCode=U_ZERO_ERROR;
960    buffer[0]=0;
961    length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
962    if( U_FAILURE(errorCode) ||
963        length!=LENGTHOF(titleSentNoLower) ||
964        0!=u_memcmp(buffer, titleSentNoLower, length) ||
965        buffer[length]!=0
966    ) {
967        log_err("ucasemap_toTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
968    }
969
970    /* UTF-8 C API coverage. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */
971    {
972        char utf8BeforeTitle[64], utf8TitleSentNoLower[64], utf8[64];
973        int32_t utf8BeforeTitleLength, utf8TitleSentNoLowerLength;
974
975        errorCode=U_ZERO_ERROR;
976        u_strToUTF8(utf8BeforeTitle, (int32_t)sizeof(utf8BeforeTitle), &utf8BeforeTitleLength, beforeTitle, LENGTHOF(beforeTitle), &errorCode);
977        u_strToUTF8(utf8TitleSentNoLower, (int32_t)sizeof(utf8TitleSentNoLower), &utf8TitleSentNoLowerLength, titleSentNoLower, LENGTHOF(titleSentNoLower), &errorCode);
978
979        length=ucasemap_utf8ToTitle(csm, utf8, (int32_t)sizeof(utf8), utf8BeforeTitle, utf8BeforeTitleLength, &errorCode);
980        if( U_FAILURE(errorCode) ||
981            length!=utf8TitleSentNoLowerLength ||
982            0!=uprv_memcmp(utf8, utf8TitleSentNoLower, length) ||
983            utf8[length]!=0
984        ) {
985            log_err("ucasemap_utf8ToTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
986        }
987    }
988
989    ucasemap_close(csm);
990}
991
992#endif
993
994void addCaseTest(TestNode** root);
995
996void addCaseTest(TestNode** root) {
997    /* cstrcase.c functions, declared in cucdtst.h */
998    addTest(root, &TestCaseLower, "tsutil/cstrcase/TestCaseLower");
999    addTest(root, &TestCaseUpper, "tsutil/cstrcase/TestCaseUpper");
1000#if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO
1001    addTest(root, &TestCaseTitle, "tsutil/cstrcase/TestCaseTitle");
1002    addTest(root, &TestCaseDutchTitle, "tsutil/cstrcase/TestCaseDutchTitle");
1003#endif
1004    addTest(root, &TestCaseFolding, "tsutil/cstrcase/TestCaseFolding");
1005    addTest(root, &TestCaseCompare, "tsutil/cstrcase/TestCaseCompare");
1006    addTest(root, &TestUCaseMap, "tsutil/cstrcase/TestUCaseMap");
1007#if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO
1008    addTest(root, &TestUCaseMapToTitle, "tsutil/cstrcase/TestUCaseMapToTitle");
1009#endif
1010}
1011