1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2015, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6 /*****************************************************************************
7 *
8 * File ccapitst.c
9 *
10 * Modification History:
11 *        Name                      Description
12 *     Madhu Katragadda              Ported for C API
13 ******************************************************************************
14 */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include "unicode/uloc.h"
20 #include "unicode/ucnv.h"
21 #include "unicode/ucnv_err.h"
22 #include "unicode/putil.h"
23 #include "unicode/uset.h"
24 #include "unicode/ustring.h"
25 #include "ucnv_bld.h" /* for sizeof(UConverter) */
26 #include "cmemory.h"  /* for UAlignedMemory */
27 #include "cintltst.h"
28 #include "ccapitst.h"
29 #include "cstring.h"
30 
31 #define NUM_CODEPAGE 1
32 #define MAX_FILE_LEN 1024*20
33 #define UCS_FILE_NAME_SIZE 512
34 
35 /*returns an action other than the one provided*/
36 #if !UCONFIG_NO_LEGACY_CONVERSION
37 static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA);
38 static UConverterToUCallback otherCharAction(UConverterToUCallback MIA);
39 #endif
40 
41 static UConverter *
cnv_open(const char * name,UErrorCode * pErrorCode)42 cnv_open(const char *name, UErrorCode *pErrorCode) {
43     if(name!=NULL && name[0]=='*') {
44         return ucnv_openPackage(loadTestData(pErrorCode), name+1, pErrorCode);
45     } else {
46         return ucnv_open(name, pErrorCode);
47     }
48 }
49 
50 
51 static void ListNames(void);
52 static void TestFlushCache(void);
53 static void TestDuplicateAlias(void);
54 static void TestCCSID(void);
55 static void TestJ932(void);
56 static void TestJ1968(void);
57 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
58 static void TestLMBCSMaxChar(void);
59 #endif
60 
61 #if !UCONFIG_NO_LEGACY_CONVERSION
62 static void TestConvertSafeCloneCallback(void);
63 #endif
64 
65 static void TestEBCDICSwapLFNL(void);
66 static void TestConvertEx(void);
67 static void TestConvertExFromUTF8(void);
68 static void TestConvertExFromUTF8_C5F0(void);
69 static void TestConvertAlgorithmic(void);
70        void TestDefaultConverterError(void);    /* defined in cctest.c */
71        void TestDefaultConverterSet(void);    /* defined in cctest.c */
72 static void TestToUCountPending(void);
73 static void TestFromUCountPending(void);
74 static void TestDefaultName(void);
75 static void TestCompareNames(void);
76 static void TestSubstString(void);
77 static void InvalidArguments(void);
78 static void TestGetName(void);
79 static void TestUTFBOM(void);
80 
81 void addTestConvert(TestNode** root);
82 
addTestConvert(TestNode ** root)83 void addTestConvert(TestNode** root)
84 {
85     addTest(root, &ListNames,                   "tsconv/ccapitst/ListNames");
86     addTest(root, &TestConvert,                 "tsconv/ccapitst/TestConvert");
87     addTest(root, &TestFlushCache,              "tsconv/ccapitst/TestFlushCache");
88     addTest(root, &TestAlias,                   "tsconv/ccapitst/TestAlias");
89     addTest(root, &TestDuplicateAlias,          "tsconv/ccapitst/TestDuplicateAlias");
90     addTest(root, &TestConvertSafeClone,        "tsconv/ccapitst/TestConvertSafeClone");
91 #if !UCONFIG_NO_LEGACY_CONVERSION
92     addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback");
93 #endif
94     addTest(root, &TestCCSID,                   "tsconv/ccapitst/TestCCSID");
95     addTest(root, &TestJ932,                    "tsconv/ccapitst/TestJ932");
96     addTest(root, &TestJ1968,                   "tsconv/ccapitst/TestJ1968");
97 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
98     addTest(root, &TestLMBCSMaxChar,            "tsconv/ccapitst/TestLMBCSMaxChar");
99 #endif
100     addTest(root, &TestEBCDICSwapLFNL,          "tsconv/ccapitst/TestEBCDICSwapLFNL");
101     addTest(root, &TestConvertEx,               "tsconv/ccapitst/TestConvertEx");
102     addTest(root, &TestConvertExFromUTF8,       "tsconv/ccapitst/TestConvertExFromUTF8");
103     addTest(root, &TestConvertExFromUTF8_C5F0,  "tsconv/ccapitst/TestConvertExFromUTF8_C5F0");
104     addTest(root, &TestConvertAlgorithmic,      "tsconv/ccapitst/TestConvertAlgorithmic");
105     addTest(root, &TestDefaultConverterError,   "tsconv/ccapitst/TestDefaultConverterError");
106     addTest(root, &TestDefaultConverterSet,     "tsconv/ccapitst/TestDefaultConverterSet");
107 #if !UCONFIG_NO_FILE_IO
108     addTest(root, &TestToUCountPending,         "tsconv/ccapitst/TestToUCountPending");
109     addTest(root, &TestFromUCountPending,       "tsconv/ccapitst/TestFromUCountPending");
110 #endif
111     addTest(root, &TestDefaultName,             "tsconv/ccapitst/TestDefaultName");
112     addTest(root, &TestCompareNames,            "tsconv/ccapitst/TestCompareNames");
113     addTest(root, &TestSubstString,             "tsconv/ccapitst/TestSubstString");
114     addTest(root, &InvalidArguments,            "tsconv/ccapitst/InvalidArguments");
115     addTest(root, &TestGetName,                 "tsconv/ccapitst/TestGetName");
116     addTest(root, &TestUTFBOM,                  "tsconv/ccapitst/TestUTFBOM");
117 }
118 
ListNames(void)119 static void ListNames(void) {
120     UErrorCode          err                 =   U_ZERO_ERROR;
121     int32_t             testLong1           =   0;
122     const char*            available_conv;
123     UEnumeration *allNamesEnum = NULL;
124     int32_t allNamesCount = 0;
125     uint16_t            count;
126 
127     log_verbose("Testing ucnv_openAllNames()...");
128     allNamesEnum = ucnv_openAllNames(&err);
129     if(U_FAILURE(err)) {
130         log_data_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err));
131     }
132     else {
133         const char *string = NULL;
134         int32_t len = 0;
135         int32_t count1 = 0;
136         int32_t count2 = 0;
137         allNamesCount = uenum_count(allNamesEnum, &err);
138         while ((string = uenum_next(allNamesEnum, &len, &err))) {
139             count1++;
140             log_verbose("read \"%s\", length %i\n", string, len);
141         }
142         if (U_FAILURE(err)) {
143             log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err));
144             err = U_ZERO_ERROR;
145         }
146         uenum_reset(allNamesEnum, &err);
147         while ((string = uenum_next(allNamesEnum, &len, &err))) {
148             count2++;
149             ucnv_close(ucnv_open(string, &err));
150             log_verbose("read \"%s\", length %i (%s)\n", string, len, U_SUCCESS(err) ? "available" : "unavailable");
151             err = U_ZERO_ERROR;
152         }
153         if (count1 != count2) {
154             log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
155         }
156     }
157     uenum_close(allNamesEnum);
158     err = U_ZERO_ERROR;
159 
160     /*Tests ucnv_getAvailableName(), getAvialableCount()*/
161 
162     log_verbose("Testing ucnv_countAvailable()...");
163 
164     testLong1=ucnv_countAvailable();
165     log_info("Number of available codepages: %d/%d\n", testLong1, allNamesCount);
166 
167     log_verbose("\n---Testing ucnv_getAvailableName..");  /*need to check this out */
168 
169     available_conv = ucnv_getAvailableName(testLong1);
170        /*test ucnv_getAvailableName with err condition*/
171     log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
172     available_conv = ucnv_getAvailableName(-1);
173     if(available_conv != NULL){
174         log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
175     }
176 
177     /* Test ucnv_countAliases() etc. */
178     count = ucnv_countAliases("utf-8", &err);
179     if(U_FAILURE(err)) {
180         log_data_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err));
181     } else if(count <= 0) {
182         log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count);
183     } else {
184         /* try to get the aliases individually */
185         const char *alias;
186         alias = ucnv_getAlias("utf-8", 0, &err);
187         if(U_FAILURE(err)) {
188             log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err));
189         } else if(strcmp("UTF-8", alias) != 0) {
190             log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias);
191         } else {
192             uint16_t aliasNum;
193             for(aliasNum = 0; aliasNum < count; ++aliasNum) {
194                 alias = ucnv_getAlias("utf-8", aliasNum, &err);
195                 if(U_FAILURE(err)) {
196                     log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
197                 } else if(strlen(alias) > 20) {
198                     /* sanity check */
199                     log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum, alias);
200                 } else {
201                     log_verbose("alias %d for utf-8: %s\n", aliasNum, alias);
202                 }
203             }
204             if(U_SUCCESS(err)) {
205                 /* try to fill an array with all aliases */
206                 const char **aliases;
207                 aliases=(const char **)malloc(count * sizeof(const char *));
208                 if(aliases != 0) {
209                     ucnv_getAliases("utf-8", aliases, &err);
210                     if(U_FAILURE(err)) {
211                         log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err));
212                     } else {
213                         for(aliasNum = 0; aliasNum < count; ++aliasNum) {
214                             /* compare the pointers with the ones returned individually */
215                             alias = ucnv_getAlias("utf-8", aliasNum, &err);
216                             if(U_FAILURE(err)) {
217                                 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
218                             } else if(aliases[aliasNum] != alias) {
219                                 log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum, aliasNum);
220                             }
221                         }
222                     }
223                     free((char **)aliases);
224                 }
225             }
226         }
227     }
228 }
229 
230 
TestConvert()231 static void TestConvert()
232 {
233 #if !UCONFIG_NO_LEGACY_CONVERSION
234     char                myptr[4];
235     char                save[4];
236     int32_t             testLong1           =   0;
237     uint16_t            rest                =   0;
238     int32_t             len                 =   0;
239     int32_t             x                   =   0;
240     FILE*               ucs_file_in         =   NULL;
241     UChar                BOM                 =   0x0000;
242     UChar                myUChar           =   0x0000;
243     char*               mytarget; /*    [MAX_FILE_LEN] */
244     char*               mytarget_1;
245     char*               mytarget_use;
246     UChar*                consumedUni         =   NULL;
247     char*               consumed            =   NULL;
248     char*                 output_cp_buffer; /*    [MAX_FILE_LEN] */
249     UChar*                ucs_file_buffer; /*    [MAX_FILE_LEN] */
250     UChar*                ucs_file_buffer_use;
251     UChar*                my_ucs_file_buffer; /*    [MAX_FILE_LEN] */
252     UChar*                my_ucs_file_buffer_1;
253     int8_t                ii                  =   0;
254     uint16_t            codepage_index      =   0;
255     int32_t             cp                  =   0;
256     UErrorCode          err                 =   U_ZERO_ERROR;
257     char                ucs_file_name[UCS_FILE_NAME_SIZE];
258     UConverterFromUCallback          MIA1, MIA1_2;
259     UConverterToUCallback              MIA2, MIA2_2;
260     const void         *MIA1Context, *MIA1Context2, *MIA2Context, *MIA2Context2;
261     UConverter*            someConverters[5];
262     UConverter*         myConverter = 0;
263     UChar*                displayname = 0;
264 
265     const char* locale;
266 
267     UChar* uchar1 = 0;
268     UChar* uchar2 = 0;
269     UChar* uchar3 = 0;
270     int32_t targetcapacity2;
271     int32_t targetcapacity;
272     int32_t targetsize;
273     int32_t disnamelen;
274 
275     const UChar* tmp_ucs_buf;
276     const UChar* tmp_consumedUni=NULL;
277     const char* tmp_mytarget_use;
278     const char* tmp_consumed;
279 
280     /******************************************************************
281                                 Checking Unicode -> ksc
282      ******************************************************************/
283 
284     const char*      CodePagesToTest[NUM_CODEPAGE]       =
285     {
286        "ibm-949_P110-1999"
287 
288 
289     };
290     const uint16_t CodePageNumberToTest[NUM_CODEPAGE]             =
291     {
292         949
293     };
294 
295 
296     const int8_t     CodePagesMinChars[NUM_CODEPAGE] =
297     {
298         1
299 
300     };
301 
302     const int8_t     CodePagesMaxChars[NUM_CODEPAGE] =
303     {
304         2
305 
306     };
307 
308     const uint16_t        CodePagesSubstitutionChars[NUM_CODEPAGE]    =
309     {
310         0xAFFE
311     };
312 
313     const char* CodePagesTestFiles[NUM_CODEPAGE]    =
314     {
315       "uni-text.bin"
316     };
317 
318 
319     const UConverterPlatform        CodePagesPlatform[NUM_CODEPAGE]    =
320     {
321         UCNV_IBM
322 
323     };
324 
325     const char* CodePagesLocale[NUM_CODEPAGE] =
326     {
327         "ko_KR"
328     };
329 
330     UConverterFromUCallback oldFromUAction = NULL;
331     UConverterToUCallback oldToUAction = NULL;
332     const void* oldFromUContext = NULL;
333     const void* oldToUContext = NULL;
334 
335     /* Allocate memory */
336     mytarget = (char*) malloc(MAX_FILE_LEN * sizeof(mytarget[0]));
337     output_cp_buffer = (char*) malloc(MAX_FILE_LEN * sizeof(output_cp_buffer[0]));
338     ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(ucs_file_buffer[0]));
339     my_ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(my_ucs_file_buffer[0]));
340 
341     ucs_file_buffer_use = ucs_file_buffer;
342     mytarget_1=mytarget;
343     mytarget_use        = mytarget;
344     my_ucs_file_buffer_1=my_ucs_file_buffer;
345 
346     /* flush the converter cache to get a consistent state before the flushing is tested */
347     ucnv_flushCache();
348 
349     /*Testing ucnv_openU()*/
350     {
351         UChar converterName[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
352         UChar firstSortedName[]={ 0x0021, 0x0000}; /* ! */
353         UChar lastSortedName[]={ 0x007E, 0x0000}; /* ~ */
354         const char *illegalNameChars={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
355         UChar illegalName[100];
356         UConverter *converter=NULL;
357         err=U_ZERO_ERROR;
358         converter=ucnv_openU(converterName, &err);
359         if(U_FAILURE(err)){
360             log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err));
361         }
362         ucnv_close(converter);
363         err=U_ZERO_ERROR;
364         converter=ucnv_openU(NULL, &err);
365         if(U_FAILURE(err)){
366             log_err("FAILURE! ucnv_openU(NULL, err)  failed. %s\n", myErrorName(err));
367         }
368         ucnv_close(converter);
369         /*testing with error value*/
370         err=U_ILLEGAL_ARGUMENT_ERROR;
371         converter=ucnv_openU(converterName, &err);
372         if(!(converter == NULL)){
373             log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
374         }
375         ucnv_close(converter);
376         err=U_ZERO_ERROR;
377         u_uastrcpy(illegalName, "");
378         u_uastrcpy(illegalName, illegalNameChars);
379         ucnv_openU(illegalName, &err);
380         if(!(err==U_ILLEGAL_ARGUMENT_ERROR)){
381             log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
382         }
383 
384         err=U_ZERO_ERROR;
385         ucnv_openU(firstSortedName, &err);
386         if(err!=U_FILE_ACCESS_ERROR){
387             log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
388         }
389 
390         err=U_ZERO_ERROR;
391         ucnv_openU(lastSortedName, &err);
392         if(err!=U_FILE_ACCESS_ERROR){
393             log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
394         }
395 
396         err=U_ZERO_ERROR;
397     }
398     log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
399     {
400          UConverter *cnv=NULL;
401          err=U_ZERO_ERROR;
402          cnv=ucnv_open("ibm-949,Madhu", &err);
403          if(U_FAILURE(err)){
404             log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err)  failed. %s\n", myErrorName(err));
405          }
406          ucnv_close(cnv);
407 
408     }
409       /*Testing ucnv_convert()*/
410     {
411         int32_t targetLimit=0, sourceLimit=0, i=0, targetCapacity=0;
412         const uint8_t source[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
413         const uint8_t expectedTarget[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
414         char *target=0;
415         sourceLimit=sizeof(source)/sizeof(source[0]);
416         err=U_ZERO_ERROR;
417         targetLimit=0;
418 
419         targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", NULL, targetLimit , (const char*)source, sourceLimit, &err);
420         if(err == U_BUFFER_OVERFLOW_ERROR){
421             err=U_ZERO_ERROR;
422             targetLimit=targetCapacity+1;
423             target=(char*)malloc(sizeof(char) * targetLimit);
424             targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
425         }
426         if(U_FAILURE(err)){
427             log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err));
428         }
429         else {
430             for(i=0; i<targetCapacity; i++){
431                 if(target[i] != expectedTarget[i]){
432                     log_err("FAIL: ucnv_convert(ibm-1363->ibm-1364) failed.at index \n i=%d,  Expected: %lx Got: %lx\n", i, (UChar)expectedTarget[i], (uint8_t)target[i]);
433                 }
434             }
435 
436             i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source+1, -1, &err);
437             if(U_FAILURE(err) || i!=7){
438                 log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
439                     u_errorName(err), i);
440             }
441 
442             /*Test error conditions*/
443             err=U_ZERO_ERROR;
444             i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, 0, &err);
445             if(i !=0){
446                 log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
447             }
448 
449             err=U_ILLEGAL_ARGUMENT_ERROR;
450             sourceLimit=sizeof(source)/sizeof(source[0]);
451             i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
452             if(i !=0 ){
453                 log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
454             }
455 
456             err=U_ZERO_ERROR;
457             sourceLimit=sizeof(source)/sizeof(source[0]);
458             targetLimit=0;
459             i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
460             if(!(U_FAILURE(err) && err==U_BUFFER_OVERFLOW_ERROR)){
461                 log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
462             }
463             err=U_ZERO_ERROR;
464             free(target);
465         }
466     }
467 
468     /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
469     log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
470     err=U_ILLEGAL_ARGUMENT_ERROR;
471     if(ucnv_open(NULL, &err) != NULL){
472         log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
473     }
474     if(ucnv_openCCSID(1051, UCNV_IBM, &err) != NULL){
475         log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
476     }
477     err=U_ZERO_ERROR;
478 
479     /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
480     log_verbose("\n---Testing ucnv_open default...\n");
481     someConverters[0] = ucnv_open(NULL,&err);
482     someConverters[1] = ucnv_open(NULL,&err);
483     someConverters[2] = ucnv_open("utf8", &err);
484     someConverters[3] = ucnv_openCCSID(949,UCNV_IBM,&err);
485     ucnv_close(ucnv_openCCSID(1051, UCNV_IBM, &err)); /* test for j350; ucnv_close(NULL) is safe */
486     if (U_FAILURE(err)){ log_data_err("FAILURE! %s\n", myErrorName(err));}
487 
488     /* Testing ucnv_getName()*/
489     /*default code page */
490     ucnv_getName(someConverters[0], &err);
491     if(U_FAILURE(err)) {
492         log_data_err("getName[0] failed\n");
493     } else {
494         log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters[0], &err));
495     }
496     ucnv_getName(someConverters[1], &err);
497     if(U_FAILURE(err)) {
498         log_data_err("getName[1] failed\n");
499     } else {
500         log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters[1], &err));
501     }
502 
503     ucnv_close(someConverters[0]);
504     ucnv_close(someConverters[1]);
505     ucnv_close(someConverters[2]);
506     ucnv_close(someConverters[3]);
507 
508 
509     for (codepage_index=0; codepage_index <  NUM_CODEPAGE; ++codepage_index)
510     {
511         int32_t i = 0;
512 
513         err = U_ZERO_ERROR;
514 #ifdef U_TOPSRCDIR
515         strcpy(ucs_file_name, U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING);
516 #else
517         strcpy(ucs_file_name, loadTestData(&err));
518 
519         if(U_FAILURE(err)){
520             log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err));
521             return;
522         }
523 
524         {
525             char* index = strrchr(ucs_file_name,(char)U_FILE_SEP_CHAR);
526 
527             if((unsigned int)(index-ucs_file_name) != (strlen(ucs_file_name)-1)){
528                     *(index+1)=0;
529             }
530         }
531 
532         strcat(ucs_file_name,".."U_FILE_SEP_STRING);
533 #endif
534         strcat(ucs_file_name, CodePagesTestFiles[codepage_index]);
535 
536         ucs_file_in = fopen(ucs_file_name,"rb");
537         if (!ucs_file_in)
538         {
539             log_data_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name);
540             return;
541         }
542 
543         /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
544 
545         /*  myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
546         /*  ucnv_flushCache(); */
547         myConverter =ucnv_open( "ibm-949", &err);
548         if (!myConverter || U_FAILURE(err))
549         {
550             log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err));
551             fclose(ucs_file_in);
552             break;
553         }
554 
555         /*testing for ucnv_getName()  */
556         log_verbose("Testing ucnv_getName()...\n");
557         ucnv_getName(myConverter, &err);
558         if(U_FAILURE(err))
559             log_err("Error in getName\n");
560         else
561         {
562             log_verbose("getName o.k. %s\n", ucnv_getName(myConverter, &err));
563         }
564         if (uprv_stricmp(ucnv_getName(myConverter, &err), CodePagesToTest[codepage_index]))
565             log_err("getName failed\n");
566         else
567             log_verbose("getName ok\n");
568         /*Test getName with error condition*/
569         {
570             const char* name=0;
571             err=U_ILLEGAL_ARGUMENT_ERROR;
572             log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
573             name=ucnv_getName(myConverter, &err);
574             if(name != NULL){
575                 log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
576             }
577             err=U_ZERO_ERROR;
578         }
579 
580 
581         /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
582 
583         log_verbose("Testing ucnv_getMaxCharSize()...\n");
584         if (ucnv_getMaxCharSize(myConverter)==CodePagesMaxChars[codepage_index])
585             log_verbose("Max byte per character OK\n");
586         else
587             log_err("Max byte per character failed\n");
588 
589         log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
590         if (ucnv_getMinCharSize(myConverter)==CodePagesMinChars[codepage_index])
591             log_verbose("Min byte per character OK\n");
592         else
593             log_err("Min byte per character failed\n");
594 
595 
596         /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
597         log_verbose("\n---Testing ucnv_getSubstChars...\n");
598         ii=4;
599         ucnv_getSubstChars(myConverter, myptr, &ii, &err);
600         if (ii <= 0) {
601             log_err("ucnv_getSubstChars returned a negative number %d\n", ii);
602         }
603 
604         for(x=0;x<ii;x++)
605             rest = (uint16_t)(((unsigned char)rest << 8) + (unsigned char)myptr[x]);
606         if (rest==CodePagesSubstitutionChars[codepage_index])
607             log_verbose("Substitution character ok\n");
608         else
609             log_err("Substitution character failed.\n");
610 
611         log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
612         ucnv_setSubstChars(myConverter, myptr, ii, &err);
613         if (U_FAILURE(err))
614         {
615             log_err("FAILURE! %s\n", myErrorName(err));
616         }
617         ucnv_getSubstChars(myConverter,save, &ii, &err);
618         if (U_FAILURE(err))
619         {
620             log_err("FAILURE! %s\n", myErrorName(err));
621         }
622 
623         if (strncmp(save, myptr, ii))
624             log_err("Saved substitution character failed\n");
625         else
626             log_verbose("Saved substitution character ok\n");
627 
628         /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
629         log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
630         ii=1;
631         ucnv_getSubstChars(myConverter, myptr, &ii, &err);
632         if(err != U_INDEX_OUTOFBOUNDS_ERROR){
633             log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err));
634         }
635         err=U_ZERO_ERROR;
636         ii=4;
637         ucnv_getSubstChars(myConverter, myptr, &ii, &err);
638         log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
639         ucnv_setSubstChars(myConverter, myptr, 0, &err);
640         if(err != U_ILLEGAL_ARGUMENT_ERROR){
641             log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err));
642         }
643         log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
644         strcpy(myptr, "abc");
645         ucnv_setSubstChars(myConverter, myptr, ii, &err);
646         err=U_ZERO_ERROR;
647         ucnv_getSubstChars(myConverter, save, &ii, &err);
648         if(strncmp(save, myptr, ii) == 0){
649             log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
650         }
651         log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
652         err=U_ZERO_ERROR;
653         strcpy(myptr, "abc");
654         ucnv_setSubstChars(myConverter, myptr, ii, &err);
655         err=U_ILLEGAL_ARGUMENT_ERROR;
656         ucnv_getSubstChars(myConverter, save, &ii, &err);
657         if(strncmp(save, myptr, ii) == 0){
658             log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n");
659         }
660         err=U_ZERO_ERROR;
661         /*------*/
662 
663 #ifdef U_ENABLE_GENERIC_ISO_2022
664         /*resetState  ucnv_reset()*/
665         log_verbose("\n---Testing ucnv_reset()..\n");
666         ucnv_reset(myConverter);
667         {
668              UChar32 c;
669              const uint8_t in[]={  0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
670              const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
671              UConverter *cnv=ucnv_open("ISO_2022", &err);
672              if(U_FAILURE(err)) {
673                 log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err));
674              }
675              c=ucnv_getNextUChar(cnv, &source, limit, &err);
676              if((U_FAILURE(err) || c != (UChar32)0x0031)) {
677                 log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err));
678              }
679              ucnv_reset(cnv);
680              ucnv_close(cnv);
681 
682         }
683 #endif
684 
685         /*getDisplayName*/
686         log_verbose("\n---Testing ucnv_getDisplayName()...\n");
687         locale=CodePagesLocale[codepage_index];
688         len=0;
689         displayname=NULL;
690         disnamelen = ucnv_getDisplayName(myConverter, locale, displayname, len, &err);
691         if(err==U_BUFFER_OVERFLOW_ERROR) {
692             err=U_ZERO_ERROR;
693             displayname=(UChar*)malloc((disnamelen+1) * sizeof(UChar));
694             ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err);
695             if(U_FAILURE(err)) {
696                 log_err("getDisplayName failed. The error is  %s\n", myErrorName(err));
697             }
698             else {
699                 log_verbose(" getDisplayName o.k.\n");
700             }
701             free(displayname);
702             displayname=NULL;
703         }
704         else {
705             log_err("getDisplayName preflight doesn't work. Error is  %s\n", myErrorName(err));
706         }
707         /*test ucnv_getDiaplayName with error condition*/
708         err= U_ILLEGAL_ARGUMENT_ERROR;
709         len=ucnv_getDisplayName(myConverter,locale,NULL,0, &err);
710         if( len !=0 ){
711             log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
712         }
713         /*test ucnv_getDiaplayName with error condition*/
714         err=U_ZERO_ERROR;
715         len=ucnv_getDisplayName(NULL,locale,NULL,0, &err);
716         if( len !=0 || U_SUCCESS(err)){
717             log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n");
718         }
719         err=U_ZERO_ERROR;
720 
721         /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
722         ucnv_getFromUCallBack(myConverter, &MIA1, &MIA1Context);
723 
724         log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
725         ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
726         if (U_FAILURE(err) || oldFromUAction != MIA1 || oldFromUContext != MIA1Context)
727         {
728             log_err("FAILURE! %s\n", myErrorName(err));
729         }
730 
731         ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
732         if (MIA1_2 != otherUnicodeAction(MIA1) || MIA1Context2 != &BOM)
733             log_err("get From UCallBack failed\n");
734         else
735             log_verbose("get From UCallBack ok\n");
736 
737         log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
738         ucnv_setFromUCallBack(myConverter,MIA1, MIA1Context, &oldFromUAction, &oldFromUContext, &err);
739         if (U_FAILURE(err) || oldFromUAction != otherUnicodeAction(MIA1) || oldFromUContext != &BOM)
740         {
741             log_err("FAILURE! %s\n", myErrorName(err));
742         }
743 
744         ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
745         if (MIA1_2 != MIA1 || MIA1Context2 != MIA1Context)
746             log_err("get From UCallBack action failed\n");
747         else
748             log_verbose("get From UCallBack action ok\n");
749 
750         /*testing ucnv_setToUCallBack with error conditions*/
751         err=U_ILLEGAL_ARGUMENT_ERROR;
752         log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
753         ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
754         ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
755         if(MIA1_2 == otherUnicodeAction(MIA1) || MIA1Context2 == &BOM){
756             log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
757         }
758         err=U_ZERO_ERROR;
759 
760 
761         /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
762         ucnv_getToUCallBack(myConverter, &MIA2, &MIA2Context);
763 
764         log_verbose("\n---Testing setTo UCallBack...\n");
765         ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), &BOM, &oldToUAction, &oldToUContext, &err);
766         if (U_FAILURE(err) || oldToUAction != MIA2 || oldToUContext != MIA2Context)
767         {
768             log_err("FAILURE! %s\n", myErrorName(err));
769         }
770 
771         ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
772         if (MIA2_2 != otherCharAction(MIA2) || MIA2Context2 != &BOM)
773             log_err("To UCallBack failed\n");
774         else
775             log_verbose("To UCallBack ok\n");
776 
777         log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
778         ucnv_setToUCallBack(myConverter,MIA2, MIA2Context, &oldToUAction, &oldToUContext, &err);
779         if (U_FAILURE(err) || oldToUAction != otherCharAction(MIA2) || oldToUContext != &BOM)
780         { log_err("FAILURE! %s\n", myErrorName(err));  }
781 
782         ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
783         if (MIA2_2 != MIA2 || MIA2Context2 != MIA2Context)
784             log_err("To UCallBack failed\n");
785         else
786             log_verbose("To UCallBack ok\n");
787 
788         /*testing ucnv_setToUCallBack with error conditions*/
789         err=U_ILLEGAL_ARGUMENT_ERROR;
790         log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
791         ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), NULL, &oldToUAction, &oldToUContext, &err);
792         ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
793         if (MIA2_2 == otherCharAction(MIA2) || MIA2Context2 == &BOM){
794             log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
795         }
796         err=U_ZERO_ERROR;
797 
798 
799         /*getcodepageid testing ucnv_getCCSID() */
800         log_verbose("\n----Testing getCCSID....\n");
801         cp =    ucnv_getCCSID(myConverter,&err);
802         if (U_FAILURE(err))
803         {
804             log_err("FAILURE!..... %s\n", myErrorName(err));
805         }
806         if (cp != CodePageNumberToTest[codepage_index])
807             log_err("Codepage number test failed\n");
808         else
809             log_verbose("Codepage number test OK\n");
810 
811         /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
812         err=U_ILLEGAL_ARGUMENT_ERROR;
813         if( ucnv_getCCSID(myConverter,&err) != -1){
814             log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
815         }
816         err=U_ZERO_ERROR;
817 
818         /*getCodepagePlatform testing ucnv_getPlatform()*/
819         log_verbose("\n---Testing getCodepagePlatform ..\n");
820         if (CodePagesPlatform[codepage_index]!=ucnv_getPlatform(myConverter, &err))
821             log_err("Platform codepage test failed\n");
822         else
823             log_verbose("Platform codepage test ok\n");
824 
825         if (U_FAILURE(err))
826         {
827             log_err("FAILURE! %s\n", myErrorName(err));
828         }
829         /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
830         err= U_ILLEGAL_ARGUMENT_ERROR;
831         if(ucnv_getPlatform(myConverter, &err) != UCNV_UNKNOWN){
832             log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
833         }
834         err=U_ZERO_ERROR;
835 
836 
837         /*Reads the BOM*/
838         {
839             // Note: gcc produces a compile warning if the return value from fread() is ignored.
840             size_t numRead = fread(&BOM, sizeof(UChar), 1, ucs_file_in);
841             (void)numRead;
842         }
843         if (BOM!=0xFEFF && BOM!=0xFFFE)
844         {
845             log_err("File Missing BOM...Bailing!\n");
846             fclose(ucs_file_in);
847             break;
848         }
849 
850 
851         /*Reads in the file*/
852         while(!feof(ucs_file_in)&&(i+=fread(ucs_file_buffer+i, sizeof(UChar), 1, ucs_file_in)))
853         {
854             myUChar = ucs_file_buffer[i-1];
855 
856             ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN*/
857         }
858 
859         myUChar = ucs_file_buffer[i-1];
860         ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN Corner Case*/
861 
862 
863         /*testing ucnv_fromUChars() and ucnv_toUChars() */
864         /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
865 
866         uchar1=(UChar*)malloc(sizeof(UChar) * (i+1));
867         u_uastrcpy(uchar1,"");
868         u_strncpy(uchar1,ucs_file_buffer,i);
869         uchar1[i] = 0;
870 
871         uchar3=(UChar*)malloc(sizeof(UChar)*(i+1));
872         u_uastrcpy(uchar3,"");
873         u_strncpy(uchar3,ucs_file_buffer,i);
874         uchar3[i] = 0;
875 
876         /*Calls the Conversion Routine */
877         testLong1 = MAX_FILE_LEN;
878         log_verbose("\n---Testing ucnv_fromUChars()\n");
879         targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1,  uchar1, -1, &err);
880         if (U_FAILURE(err))
881         {
882             log_err("\nFAILURE...%s\n", myErrorName(err));
883         }
884         else
885             log_verbose(" ucnv_fromUChars() o.k.\n");
886 
887         /*test the conversion routine */
888         log_verbose("\n---Testing ucnv_toUChars()\n");
889         /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
890         targetcapacity2=0;
891         targetsize = ucnv_toUChars(myConverter,
892                      NULL,
893                      targetcapacity2,
894                      output_cp_buffer,
895                      strlen(output_cp_buffer),
896                      &err);
897         /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
898 
899         if(err==U_BUFFER_OVERFLOW_ERROR)
900         {
901             err=U_ZERO_ERROR;
902             uchar2=(UChar*)malloc((targetsize+1) * sizeof(UChar));
903             targetsize = ucnv_toUChars(myConverter,
904                    uchar2,
905                    targetsize+1,
906                    output_cp_buffer,
907                    strlen(output_cp_buffer),
908                    &err);
909 
910             if(U_FAILURE(err))
911                 log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err));
912             else
913                 log_verbose(" ucnv_toUChars() o.k.\n");
914 
915             if(u_strcmp(uchar1,uchar2)!=0)
916                 log_err("equality test failed with conversion routine\n");
917         }
918         else
919         {
920             log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
921         }
922         /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
923         err=U_ILLEGAL_ARGUMENT_ERROR;
924         log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
925         targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1,  uchar1, -1, &err);
926         if (targetcapacity !=0) {
927             log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
928         }
929         err=U_ZERO_ERROR;
930         log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
931         targetcapacity = ucnv_fromUChars(NULL, output_cp_buffer, testLong1,  uchar1, -1, &err);
932         if (targetcapacity !=0 || err != U_ILLEGAL_ARGUMENT_ERROR) {
933             log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
934         }
935         err=U_ZERO_ERROR;
936         log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
937         targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1,  uchar1, 0, &err);
938         if (targetcapacity !=0) {
939             log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
940         }
941         log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
942         targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, 0,  uchar1, -1, &err);
943         if (err != U_BUFFER_OVERFLOW_ERROR) {
944             log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
945         }
946         /*toUChars with error conditions*/
947         targetsize = ucnv_toUChars(myConverter, uchar2, targetsize, output_cp_buffer, strlen(output_cp_buffer), &err);
948         if(targetsize != 0){
949             log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
950         }
951         err=U_ZERO_ERROR;
952         targetsize = ucnv_toUChars(myConverter, uchar2, -1, output_cp_buffer, strlen(output_cp_buffer), &err);
953         if(targetsize != 0 || err != U_ILLEGAL_ARGUMENT_ERROR){
954             log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
955         }
956         err=U_ZERO_ERROR;
957         targetsize = ucnv_toUChars(myConverter, uchar2, 0, output_cp_buffer, 0, &err);
958         if (targetsize !=0) {
959             log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
960         }
961         targetcapacity2=0;
962         targetsize = ucnv_toUChars(myConverter, NULL, targetcapacity2, output_cp_buffer,  strlen(output_cp_buffer), &err);
963         if (err != U_STRING_NOT_TERMINATED_WARNING) {
964             log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
965                     u_errorName(err));
966         }
967         err=U_ZERO_ERROR;
968         /*-----*/
969 
970 
971         /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
972         /*Clean up re-usable vars*/
973         log_verbose("Testing ucnv_fromUnicode().....\n");
974         tmp_ucs_buf=ucs_file_buffer_use;
975         ucnv_fromUnicode(myConverter, &mytarget_1,
976                  mytarget + MAX_FILE_LEN,
977                  &tmp_ucs_buf,
978                  ucs_file_buffer_use+i,
979                  NULL,
980                  TRUE,
981                  &err);
982         consumedUni = (UChar*)tmp_consumedUni;
983         (void)consumedUni;   /* Suppress set but not used warning. */
984 
985         if (U_FAILURE(err))
986         {
987             log_err("FAILURE! %s\n", myErrorName(err));
988         }
989         else
990             log_verbose("ucnv_fromUnicode()   o.k.\n");
991 
992         /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
993         log_verbose("Testing ucnv_toUnicode().....\n");
994         tmp_mytarget_use=mytarget_use;
995         tmp_consumed = consumed;
996         ucnv_toUnicode(myConverter, &my_ucs_file_buffer_1,
997                 my_ucs_file_buffer + MAX_FILE_LEN,
998                 &tmp_mytarget_use,
999                 mytarget_use + (mytarget_1 - mytarget),
1000                 NULL,
1001                 FALSE,
1002                 &err);
1003         consumed = (char*)tmp_consumed;
1004         if (U_FAILURE(err))
1005         {
1006             log_err("FAILURE! %s\n", myErrorName(err));
1007         }
1008         else
1009             log_verbose("ucnv_toUnicode()  o.k.\n");
1010 
1011 
1012         log_verbose("\n---Testing   RoundTrip ...\n");
1013 
1014 
1015         u_strncpy(uchar3, my_ucs_file_buffer,i);
1016         uchar3[i] = 0;
1017 
1018         if(u_strcmp(uchar1,uchar3)==0)
1019             log_verbose("Equality test o.k.\n");
1020         else
1021             log_err("Equality test failed\n");
1022 
1023         /*sanity compare */
1024         if(uchar2 == NULL)
1025         {
1026             log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__);
1027         }
1028         else
1029         {
1030             if(u_strcmp(uchar2, uchar3)==0)
1031                 log_verbose("Equality test o.k.\n");
1032             else
1033                 log_err("Equality test failed\n");
1034         }
1035 
1036         fclose(ucs_file_in);
1037         ucnv_close(myConverter);
1038         if (uchar1 != 0) free(uchar1);
1039         if (uchar2 != 0) free(uchar2);
1040         if (uchar3 != 0) free(uchar3);
1041     }
1042 
1043     free((void*)mytarget);
1044     free((void*)output_cp_buffer);
1045     free((void*)ucs_file_buffer);
1046     free((void*)my_ucs_file_buffer);
1047 #endif
1048 }
1049 
1050 #if !UCONFIG_NO_LEGACY_CONVERSION
otherUnicodeAction(UConverterFromUCallback MIA)1051 static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA)
1052 {
1053     return (MIA==(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP)?(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_SUBSTITUTE:(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP;
1054 }
1055 
otherCharAction(UConverterToUCallback MIA)1056 static UConverterToUCallback otherCharAction(UConverterToUCallback MIA)
1057 {
1058     return (MIA==(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP)?(UConverterToUCallback)UCNV_TO_U_CALLBACK_SUBSTITUTE:(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP;
1059 }
1060 #endif
1061 
TestFlushCache(void)1062 static void TestFlushCache(void) {
1063 #if !UCONFIG_NO_LEGACY_CONVERSION
1064     UErrorCode          err                 =   U_ZERO_ERROR;
1065     UConverter*            someConverters[5];
1066     int flushCount = 0;
1067 
1068     /* flush the converter cache to get a consistent state before the flushing is tested */
1069     ucnv_flushCache();
1070 
1071     /*Testing ucnv_open()*/
1072     /* Note: These converters have been chosen because they do NOT
1073        encode the Latin characters (U+0041, ...), and therefore are
1074        highly unlikely to be chosen as system default codepages */
1075 
1076     someConverters[0] = ucnv_open("ibm-1047", &err);
1077     if (U_FAILURE(err)) {
1078         log_data_err("FAILURE! %s\n", myErrorName(err));
1079     }
1080 
1081     someConverters[1] = ucnv_open("ibm-1047", &err);
1082     if (U_FAILURE(err)) {
1083         log_data_err("FAILURE! %s\n", myErrorName(err));
1084     }
1085 
1086     someConverters[2] = ucnv_open("ibm-1047", &err);
1087     if (U_FAILURE(err)) {
1088         log_data_err("FAILURE! %s\n", myErrorName(err));
1089     }
1090 
1091     someConverters[3] = ucnv_open("gb18030", &err);
1092     if (U_FAILURE(err)) {
1093         log_data_err("FAILURE! %s\n", myErrorName(err));
1094     }
1095 
1096     someConverters[4] = ucnv_open("ibm-954", &err);
1097     if (U_FAILURE(err)) {
1098         log_data_err("FAILURE! %s\n", myErrorName(err));
1099     }
1100 
1101 
1102     /* Testing ucnv_flushCache() */
1103     log_verbose("\n---Testing ucnv_flushCache...\n");
1104     if ((flushCount=ucnv_flushCache())==0)
1105         log_verbose("Flush cache ok\n");
1106     else
1107         log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
1108 
1109     /*testing ucnv_close() and ucnv_flushCache() */
1110     ucnv_close(someConverters[0]);
1111     ucnv_close(someConverters[1]);
1112 
1113     if ((flushCount=ucnv_flushCache())==0)
1114         log_verbose("Flush cache ok\n");
1115     else
1116         log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
1117 
1118     ucnv_close(someConverters[2]);
1119     ucnv_close(someConverters[3]);
1120 
1121     if ((flushCount=ucnv_flushCache())==2)
1122         log_verbose("Flush cache ok\n");  /*because first, second and third are same  */
1123     else
1124         log_data_err("Flush Cache failed  line %d, got %d expected 2 or there is an error in ucnv_close()\n",
1125             __LINE__,
1126             flushCount);
1127 
1128     ucnv_close(someConverters[4]);
1129     if ( (flushCount=ucnv_flushCache())==1)
1130         log_verbose("Flush cache ok\n");
1131     else
1132         log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__, flushCount);
1133 #endif
1134 }
1135 
1136 /**
1137  * Test the converter alias API, specifically the fuzzy matching of
1138  * alias names and the alias table integrity.  Make sure each
1139  * converter has at least one alias (itself), and that its listed
1140  * aliases map back to itself.  Check some hard-coded UTF-8 and
1141  * ISO_2022 aliases to make sure they work.
1142  */
TestAlias()1143 static void TestAlias() {
1144     int32_t i, ncnv;
1145     UErrorCode status = U_ZERO_ERROR;
1146 
1147     /* Predetermined aliases that we expect to map back to ISO_2022
1148      * and UTF-8.  UPDATE THIS DATA AS NECESSARY. */
1149     const char* ISO_2022_NAMES[] =
1150         {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
1151          "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
1152     int32_t ISO_2022_NAMES_LENGTH = UPRV_LENGTHOF(ISO_2022_NAMES);
1153     const char *UTF8_NAMES[] =
1154         { "UTF-8", "utf-8", "utf8", "ibm-1208",
1155           "utf_8", "ibm1208", "cp1208" };
1156     int32_t UTF8_NAMES_LENGTH = UPRV_LENGTHOF(UTF8_NAMES);
1157 
1158     struct {
1159         const char *name;
1160         const char *alias;
1161     } CONVERTERS_NAMES[] = {
1162         { "UTF-32BE", "UTF32_BigEndian" },
1163         { "UTF-32LE", "UTF32_LittleEndian" },
1164         { "UTF-32",   "ISO-10646-UCS-4" },
1165         { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
1166         { "UTF-32",   "ucs-4" }
1167     };
1168     int32_t CONVERTERS_NAMES_LENGTH = sizeof(CONVERTERS_NAMES) / sizeof(*CONVERTERS_NAMES);
1169 
1170     /* When there are bugs in gencnval or in ucnv_io, converters can
1171        appear to have no aliases. */
1172     ncnv = ucnv_countAvailable();
1173     log_verbose("%d converters\n", ncnv);
1174     for (i=0; i<ncnv; ++i) {
1175         const char *name = ucnv_getAvailableName(i);
1176         const char *alias0;
1177         uint16_t na = ucnv_countAliases(name, &status);
1178         uint16_t j;
1179         UConverter *cnv;
1180 
1181         if (na == 0) {
1182             log_err("FAIL: Converter \"%s\" (i=%d)"
1183                     " has no aliases; expect at least one\n",
1184                     name, i);
1185             continue;
1186         }
1187         cnv = ucnv_open(name, &status);
1188         if (U_FAILURE(status)) {
1189             log_data_err("FAIL: Converter \"%s\" (i=%d)"
1190                     " can't be opened.\n",
1191                     name, i);
1192         }
1193         else {
1194             if (strcmp(ucnv_getName(cnv, &status), name) != 0
1195                 && (strstr(name, "PlatformEndian") == 0 && strstr(name, "OppositeEndian") == 0)) {
1196                 log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
1197                         "They should be the same\n",
1198                         name, ucnv_getName(cnv, &status));
1199             }
1200         }
1201         ucnv_close(cnv);
1202 
1203         status = U_ZERO_ERROR;
1204         alias0 = ucnv_getAlias(name, 0, &status);
1205         for (j=1; j<na; ++j) {
1206             const char *alias;
1207             /* Make sure each alias maps back to the the same list of
1208                aliases.  Assume that if alias 0 is the same, the whole
1209                list is the same (this should always be true). */
1210             const char *mapBack;
1211 
1212             status = U_ZERO_ERROR;
1213             alias = ucnv_getAlias(name, j, &status);
1214             if (status == U_AMBIGUOUS_ALIAS_WARNING) {
1215                 log_err("FAIL: Converter \"%s\"is ambiguous\n", name);
1216             }
1217 
1218             if (alias == NULL) {
1219                 log_err("FAIL: Converter \"%s\" -> "
1220                         "alias[%d]=NULL\n",
1221                         name, j);
1222                 continue;
1223             }
1224 
1225             mapBack = ucnv_getAlias(alias, 0, &status);
1226 
1227             if (mapBack == NULL) {
1228                 log_err("FAIL: Converter \"%s\" -> "
1229                         "alias[%d]=\"%s\" -> "
1230                         "alias[0]=NULL, exp. \"%s\"\n",
1231                         name, j, alias, alias0);
1232                 continue;
1233             }
1234 
1235             if (0 != strcmp(alias0, mapBack)) {
1236                 int32_t idx;
1237                 UBool foundAlias = FALSE;
1238                 if (status == U_AMBIGUOUS_ALIAS_WARNING) {
1239                     /* Make sure that we only get this mismapping when there is
1240                        an ambiguous alias, and the other converter has this alias too. */
1241                     for (idx = 0; idx < ucnv_countAliases(mapBack, &status); idx++) {
1242                         if (strcmp(ucnv_getAlias(mapBack, (uint16_t)idx, &status), alias) == 0) {
1243                             foundAlias = TRUE;
1244                             break;
1245                         }
1246                     }
1247                 }
1248                 /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
1249 
1250                 if (!foundAlias) {
1251                     log_err("FAIL: Converter \"%s\" -> "
1252                             "alias[%d]=\"%s\" -> "
1253                             "alias[0]=\"%s\", exp. \"%s\"\n",
1254                             name, j, alias, mapBack, alias0);
1255                 }
1256             }
1257         }
1258     }
1259 
1260 
1261     /* Check a list of predetermined aliases that we expect to map
1262      * back to ISO_2022 and UTF-8. */
1263     for (i=1; i<ISO_2022_NAMES_LENGTH; ++i) {
1264         const char* mapBack = ucnv_getAlias(ISO_2022_NAMES[i], 0, &status);
1265         if(!mapBack) {
1266           log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES[i]);
1267           continue;
1268         }
1269         if (0 != strcmp(mapBack, ISO_2022_NAMES[0])) {
1270             log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
1271                     ISO_2022_NAMES[i], mapBack);
1272         }
1273     }
1274 
1275 
1276     for (i=1; i<UTF8_NAMES_LENGTH; ++i) {
1277         const char* mapBack = ucnv_getAlias(UTF8_NAMES[i], 0, &status);
1278         if(!mapBack) {
1279           log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES[i]);
1280           continue;
1281         }
1282         if (mapBack && 0 != strcmp(mapBack, UTF8_NAMES[0])) {
1283             log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
1284                     UTF8_NAMES[i], mapBack);
1285         }
1286     }
1287 
1288     /*
1289      * Check a list of predetermined aliases that we expect to map
1290      * back to predermined converter names.
1291      */
1292 
1293     for (i = 0; i < CONVERTERS_NAMES_LENGTH; ++i) {
1294         const char* mapBack = ucnv_getAlias(CONVERTERS_NAMES[i].alias, 0, &status);
1295         if(!mapBack) {
1296           log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES[i].name);
1297           continue;
1298         }
1299         if (0 != strcmp(mapBack, CONVERTERS_NAMES[i].name)) {
1300             log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
1301                     CONVERTERS_NAMES[i].alias, mapBack, CONVERTERS_NAMES[i].name);
1302         }
1303     }
1304 
1305 }
1306 
TestDuplicateAlias(void)1307 static void TestDuplicateAlias(void) {
1308     const char *alias;
1309     UErrorCode status = U_ZERO_ERROR;
1310 
1311     status = U_ZERO_ERROR;
1312     alias = ucnv_getStandardName("Shift_JIS", "IBM", &status);
1313     if (alias == NULL || strcmp(alias, "ibm-943") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
1314         log_data_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias);
1315     }
1316     status = U_ZERO_ERROR;
1317     alias = ucnv_getStandardName("ibm-943", "IANA", &status);
1318     if (alias == NULL || strcmp(alias, "Shift_JIS") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
1319         log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias);
1320     }
1321     status = U_ZERO_ERROR;
1322     alias = ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status);
1323     if (alias != NULL || status == U_AMBIGUOUS_ALIAS_WARNING) {
1324         log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias);
1325     }
1326 }
1327 
1328 
1329 /* Test safe clone callback */
1330 
TSCC_nextSerial()1331 static uint32_t    TSCC_nextSerial()
1332 {
1333     static uint32_t n = 1;
1334 
1335     return (n++);
1336 }
1337 
1338 typedef struct
1339 {
1340     uint32_t       magic;      /* 0xC0FFEE to identify that the object is OK */
1341     uint32_t       serial;     /* minted from nextSerial, above */
1342     UBool          wasClosed;  /* close happened on the object */
1343 } TSCCContext;
1344 
TSCC_clone(TSCCContext * ctx)1345 static TSCCContext *TSCC_clone(TSCCContext *ctx)
1346 {
1347     TSCCContext *newCtx = (TSCCContext *)malloc(sizeof(TSCCContext));
1348 
1349     newCtx->serial = TSCC_nextSerial();
1350     newCtx->wasClosed = 0;
1351     newCtx->magic = 0xC0FFEE;
1352 
1353     log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx, ctx->serial, newCtx, newCtx->serial);
1354 
1355     return newCtx;
1356 }
1357 
1358 #if !UCONFIG_NO_LEGACY_CONVERSION
TSCC_fromU(const void * context,UConverterFromUnicodeArgs * fromUArgs,const UChar * codeUnits,int32_t length,UChar32 codePoint,UConverterCallbackReason reason,UErrorCode * err)1359 static void TSCC_fromU(const void *context,
1360                         UConverterFromUnicodeArgs *fromUArgs,
1361                         const UChar* codeUnits,
1362                         int32_t length,
1363                         UChar32 codePoint,
1364                         UConverterCallbackReason reason,
1365                         UErrorCode * err)
1366 {
1367     TSCCContext *ctx = (TSCCContext*)context;
1368     UConverterFromUCallback junkFrom;
1369 
1370     log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, fromUArgs->converter);
1371 
1372     if(ctx->magic != 0xC0FFEE) {
1373         log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
1374         return;
1375     }
1376 
1377     if(reason == UCNV_CLONE) {
1378         UErrorCode subErr = U_ZERO_ERROR;
1379         TSCCContext *newCtx;
1380         TSCCContext *junkCtx;
1381         TSCCContext **pjunkCtx = &junkCtx;
1382 
1383         /* "recreate" it */
1384         log_verbose("TSCC_fromU: cloning..\n");
1385         newCtx = TSCC_clone(ctx);
1386 
1387         if(newCtx == NULL) {
1388             log_err("TSCC_fromU: internal clone failed on %p\n", ctx);
1389         }
1390 
1391         /* now, SET it */
1392         ucnv_getFromUCallBack(fromUArgs->converter, &junkFrom, (const void**)pjunkCtx);
1393         ucnv_setFromUCallBack(fromUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
1394 
1395         if(U_FAILURE(subErr)) {
1396             *err = subErr;
1397         }
1398     }
1399 
1400     if(reason == UCNV_CLOSE) {
1401         log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx, ctx->serial);
1402         ctx->wasClosed = TRUE;
1403     }
1404 }
1405 
TSCC_toU(const void * context,UConverterToUnicodeArgs * toUArgs,const char * codeUnits,int32_t length,UConverterCallbackReason reason,UErrorCode * err)1406 static void TSCC_toU(const void *context,
1407                         UConverterToUnicodeArgs *toUArgs,
1408                         const char* codeUnits,
1409                         int32_t length,
1410                         UConverterCallbackReason reason,
1411                         UErrorCode * err)
1412 {
1413     TSCCContext *ctx = (TSCCContext*)context;
1414     UConverterToUCallback junkFrom;
1415 
1416     log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, toUArgs->converter);
1417 
1418     if(ctx->magic != 0xC0FFEE) {
1419         log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
1420         return;
1421     }
1422 
1423     if(reason == UCNV_CLONE) {
1424         UErrorCode subErr = U_ZERO_ERROR;
1425         TSCCContext *newCtx;
1426         TSCCContext *junkCtx;
1427         TSCCContext **pjunkCtx = &junkCtx;
1428 
1429         /* "recreate" it */
1430         log_verbose("TSCC_toU: cloning..\n");
1431         newCtx = TSCC_clone(ctx);
1432 
1433         if(newCtx == NULL) {
1434             log_err("TSCC_toU: internal clone failed on %p\n", ctx);
1435         }
1436 
1437         /* now, SET it */
1438         ucnv_getToUCallBack(toUArgs->converter, &junkFrom, (const void**)pjunkCtx);
1439         ucnv_setToUCallBack(toUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
1440 
1441         if(U_FAILURE(subErr)) {
1442             *err = subErr;
1443         }
1444     }
1445 
1446     if(reason == UCNV_CLOSE) {
1447         log_verbose("TSCC_toU: Context %p:%d closing\n", ctx, ctx->serial);
1448         ctx->wasClosed = TRUE;
1449     }
1450 }
1451 
TSCC_init(TSCCContext * q)1452 static void TSCC_init(TSCCContext *q)
1453 {
1454     q->magic = 0xC0FFEE;
1455     q->serial = TSCC_nextSerial();
1456     q->wasClosed = 0;
1457 }
1458 
TSCC_print_log(TSCCContext * q,const char * name)1459 static void TSCC_print_log(TSCCContext *q, const char *name)
1460 {
1461     if(q==NULL) {
1462         log_verbose("TSCContext: %s is NULL!!\n", name);
1463     } else {
1464         if(q->magic != 0xC0FFEE) {
1465             log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
1466                     q,q->serial, q->magic);
1467         }
1468         log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
1469                     q, q->serial, name, q->magic, q->wasClosed?"CLOSED":"open");
1470     }
1471 }
1472 
TestConvertSafeCloneCallback()1473 static void TestConvertSafeCloneCallback()
1474 {
1475     UErrorCode err = U_ZERO_ERROR;
1476     TSCCContext from1, to1;
1477     TSCCContext *from2, *from3, *to2, *to3;
1478     TSCCContext **pfrom2 = &from2, **pfrom3 = &from3, **pto2 = &to2, **pto3 = &to3;
1479     char hunk[8192];
1480     int32_t hunkSize = 8192;
1481     UConverterFromUCallback junkFrom;
1482     UConverterToUCallback junkTo;
1483     UConverter *conv1, *conv2 = NULL;
1484 
1485     conv1 = ucnv_open("iso-8859-3", &err);
1486 
1487     if(U_FAILURE(err)) {
1488         log_data_err("Err opening iso-8859-3, %s\n", u_errorName(err));
1489         return;
1490     }
1491 
1492     log_verbose("Opened conv1=%p\n", conv1);
1493 
1494     TSCC_init(&from1);
1495     TSCC_init(&to1);
1496 
1497     TSCC_print_log(&from1, "from1");
1498     TSCC_print_log(&to1, "to1");
1499 
1500     ucnv_setFromUCallBack(conv1, TSCC_fromU, &from1, NULL, NULL, &err);
1501     log_verbose("Set from1 on conv1\n");
1502     TSCC_print_log(&from1, "from1");
1503 
1504     ucnv_setToUCallBack(conv1, TSCC_toU, &to1, NULL, NULL, &err);
1505     log_verbose("Set to1 on conv1\n");
1506     TSCC_print_log(&to1, "to1");
1507 
1508     conv2 = ucnv_safeClone(conv1, hunk, &hunkSize, &err);
1509     if(U_FAILURE(err)) {
1510         log_err("safeClone failed: %s\n", u_errorName(err));
1511         return;
1512     }
1513     log_verbose("Cloned to conv2=%p.\n", conv2);
1514 
1515 /**********   from *********************/
1516     ucnv_getFromUCallBack(conv2, &junkFrom, (const void**)pfrom2);
1517     ucnv_getFromUCallBack(conv1, &junkFrom, (const void**)pfrom3);
1518 
1519     TSCC_print_log(from2, "from2");
1520     TSCC_print_log(from3, "from3(==from1)");
1521 
1522     if(from2 == NULL) {
1523         log_err("FAIL! from2 is null \n");
1524         return;
1525     }
1526 
1527     if(from3 == NULL) {
1528         log_err("FAIL! from3 is null \n");
1529         return;
1530     }
1531 
1532     if(from3 != (&from1) ) {
1533         log_err("FAIL! conv1's FROM context changed!\n");
1534     }
1535 
1536     if(from2 == (&from1) ) {
1537         log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
1538     }
1539 
1540     if(from1.wasClosed) {
1541         log_err("FAIL! from1 is closed \n");
1542     }
1543 
1544     if(from2->wasClosed) {
1545         log_err("FAIL! from2 was closed\n");
1546     }
1547 
1548 /**********   to *********************/
1549     ucnv_getToUCallBack(conv2, &junkTo, (const void**)pto2);
1550     ucnv_getToUCallBack(conv1, &junkTo, (const void**)pto3);
1551 
1552     TSCC_print_log(to2, "to2");
1553     TSCC_print_log(to3, "to3(==to1)");
1554 
1555     if(to2 == NULL) {
1556         log_err("FAIL! to2 is null \n");
1557         return;
1558     }
1559 
1560     if(to3 == NULL) {
1561         log_err("FAIL! to3 is null \n");
1562         return;
1563     }
1564 
1565     if(to3 != (&to1) ) {
1566         log_err("FAIL! conv1's TO context changed!\n");
1567     }
1568 
1569     if(to2 == (&to1) ) {
1570         log_err("FAIL! conv1's TO context is the same as conv2's!\n");
1571     }
1572 
1573     if(to1.wasClosed) {
1574         log_err("FAIL! to1 is closed \n");
1575     }
1576 
1577     if(to2->wasClosed) {
1578         log_err("FAIL! to2 was closed\n");
1579     }
1580 
1581 /*************************************/
1582 
1583     ucnv_close(conv1);
1584     log_verbose("ucnv_closed (conv1)\n");
1585     TSCC_print_log(&from1, "from1");
1586     TSCC_print_log(from2, "from2");
1587     TSCC_print_log(&to1, "to1");
1588     TSCC_print_log(to2, "to2");
1589 
1590     if(from1.wasClosed == FALSE) {
1591         log_err("FAIL! from1 is NOT closed \n");
1592     }
1593 
1594     if(from2->wasClosed) {
1595         log_err("FAIL! from2 was closed\n");
1596     }
1597 
1598     if(to1.wasClosed == FALSE) {
1599         log_err("FAIL! to1 is NOT closed \n");
1600     }
1601 
1602     if(to2->wasClosed) {
1603         log_err("FAIL! to2 was closed\n");
1604     }
1605 
1606     ucnv_close(conv2);
1607     log_verbose("ucnv_closed (conv2)\n");
1608 
1609     TSCC_print_log(&from1, "from1");
1610     TSCC_print_log(from2, "from2");
1611 
1612     if(from1.wasClosed == FALSE) {
1613         log_err("FAIL! from1 is NOT closed \n");
1614     }
1615 
1616     if(from2->wasClosed == FALSE) {
1617         log_err("FAIL! from2 was NOT closed\n");
1618     }
1619 
1620     TSCC_print_log(&to1, "to1");
1621     TSCC_print_log(to2, "to2");
1622 
1623     if(to1.wasClosed == FALSE) {
1624         log_err("FAIL! to1 is NOT closed \n");
1625     }
1626 
1627     if(to2->wasClosed == FALSE) {
1628         log_err("FAIL! to2 was NOT closed\n");
1629     }
1630 
1631     if(to2 != (&to1)) {
1632         free(to2); /* to1 is stack based */
1633     }
1634     if(from2 != (&from1)) {
1635         free(from2); /* from1 is stack based */
1636     }
1637 }
1638 #endif
1639 
1640 static UBool
containsAnyOtherByte(uint8_t * p,int32_t length,uint8_t b)1641 containsAnyOtherByte(uint8_t *p, int32_t length, uint8_t b) {
1642     while(length>0) {
1643         if(*p!=b) {
1644             return TRUE;
1645         }
1646         ++p;
1647         --length;
1648     }
1649     return FALSE;
1650 }
1651 
TestConvertSafeClone()1652 static void TestConvertSafeClone()
1653 {
1654     /* one 'regular' & all the 'private stateful' converters */
1655     static const char *const names[] = {
1656 #if !UCONFIG_NO_LEGACY_CONVERSION
1657         "ibm-1047",
1658         "ISO_2022,locale=zh,version=1",
1659 #endif
1660         "SCSU",
1661 #if !UCONFIG_NO_LEGACY_CONVERSION
1662         "HZ",
1663         "lmbcs",
1664         "ISCII,version=0",
1665         "ISO_2022,locale=kr,version=1",
1666         "ISO_2022,locale=jp,version=2",
1667 #endif
1668         "BOCU-1",
1669         "UTF-7",
1670 #if !UCONFIG_NO_LEGACY_CONVERSION
1671         "IMAP-mailbox-name",
1672         "ibm-1047-s390"
1673 #else
1674         "IMAP=mailbox-name"
1675 #endif
1676     };
1677 
1678     /* store the actual sizes of each converter */
1679     int32_t actualSizes[UPRV_LENGTHOF(names)];
1680 
1681     static const int32_t bufferSizes[] = {
1682         U_CNV_SAFECLONE_BUFFERSIZE,
1683         (int32_t)(3*sizeof(UConverter))/2,  /* 1.5*sizeof(UConverter) */
1684         (int32_t)sizeof(UConverter)/2       /* 0.5*sizeof(UConverter) */
1685     };
1686 
1687     char charBuffer[21];   /* Leave at an odd number for alignment testing */
1688     uint8_t buffer[3] [U_CNV_SAFECLONE_BUFFERSIZE];
1689     int32_t bufferSize, maxBufferSize;
1690     const char *maxName;
1691     UConverter * cnv, *cnv2;
1692     UErrorCode err;
1693 
1694     char *pCharBuffer;
1695     const char *pConstCharBuffer;
1696     const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer);
1697     UChar uniBuffer[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
1698     UChar uniCharBuffer[20];
1699     char  charSourceBuffer[] = { 0x1b, 0x24, 0x42 };
1700     const char *pCharSource = charSourceBuffer;
1701     const char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer);
1702     UChar *pUCharTarget = uniCharBuffer;
1703     UChar *pUCharTargetLimit = uniCharBuffer + sizeof(uniCharBuffer)/sizeof(*uniCharBuffer);
1704     const UChar * pUniBuffer;
1705     const UChar *uniBufferLimit = uniBuffer + sizeof(uniBuffer)/sizeof(*uniBuffer);
1706     int32_t idx, j;
1707 
1708     err = U_ZERO_ERROR;
1709     cnv = ucnv_open(names[0], &err);
1710     if(U_SUCCESS(err)) {
1711         /* Check the various error & informational states: */
1712 
1713         /* Null status - just returns NULL */
1714         bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
1715         if (NULL != ucnv_safeClone(cnv, buffer[0], &bufferSize, NULL))
1716         {
1717             log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
1718         }
1719         /* error status - should return 0 & keep error the same */
1720         err = U_MEMORY_ALLOCATION_ERROR;
1721         if (NULL != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || err != U_MEMORY_ALLOCATION_ERROR)
1722         {
1723             log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
1724         }
1725         err = U_ZERO_ERROR;
1726 
1727         /* Null buffer size pointer is ok */
1728         if (NULL == (cnv2 = ucnv_safeClone(cnv, buffer[0], NULL, &err)) || U_FAILURE(err))
1729         {
1730             log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
1731         }
1732         ucnv_close(cnv2);
1733         err = U_ZERO_ERROR;
1734 
1735         /* buffer size pointer is 0 - fill in pbufferSize with a size */
1736         bufferSize = 0;
1737         if (NULL != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || U_FAILURE(err) || bufferSize <= 0)
1738         {
1739             log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
1740         }
1741         /* Verify our define is large enough  */
1742         if (U_CNV_SAFECLONE_BUFFERSIZE < bufferSize)
1743         {
1744             log_err("FAIL: Pre-calculated buffer size is too small\n");
1745         }
1746         /* Verify we can use this run-time calculated size */
1747         if (NULL == (cnv2 = ucnv_safeClone(cnv, buffer[0], &bufferSize, &err)) || U_FAILURE(err))
1748         {
1749             log_err("FAIL: Converter can't be cloned with run-time size\n");
1750         }
1751         if (cnv2) {
1752             ucnv_close(cnv2);
1753         }
1754 
1755         /* size one byte too small - should allocate & let us know */
1756         --bufferSize;
1757         if (NULL == (cnv2 = ucnv_safeClone(cnv, NULL, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
1758         {
1759             log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n");
1760         }
1761         if (cnv2) {
1762             ucnv_close(cnv2);
1763         }
1764 
1765         err = U_ZERO_ERROR;
1766         bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
1767 
1768         /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
1769         if (NULL == (cnv2 = ucnv_safeClone(cnv, NULL, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
1770         {
1771             log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
1772         }
1773         if (cnv2) {
1774             ucnv_close(cnv2);
1775         }
1776 
1777         err = U_ZERO_ERROR;
1778 
1779         /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
1780         if (NULL != ucnv_safeClone(NULL, buffer[0], &bufferSize, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
1781         {
1782             log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
1783         }
1784 
1785         ucnv_close(cnv);
1786     }
1787 
1788     maxBufferSize = 0;
1789     maxName = "";
1790 
1791     /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
1792 
1793     for(j = 0; j < UPRV_LENGTHOF(bufferSizes); ++j) {
1794         for (idx = 0; idx < UPRV_LENGTHOF(names); idx++)
1795         {
1796             err = U_ZERO_ERROR;
1797             cnv = ucnv_open(names[idx], &err);
1798             if(U_FAILURE(err)) {
1799                 log_data_err("ucnv_open(\"%s\") failed - %s\n", names[idx], u_errorName(err));
1800                 continue;
1801             }
1802 
1803             if(j == 0) {
1804                 /* preflight to get maxBufferSize */
1805                 actualSizes[idx] = 0;
1806                 ucnv_safeClone(cnv, NULL, &actualSizes[idx], &err);
1807                 if(actualSizes[idx] > maxBufferSize) {
1808                     maxBufferSize = actualSizes[idx];
1809                     maxName = names[idx];
1810                 }
1811             }
1812 
1813             memset(buffer, 0xaa, sizeof(buffer));
1814 
1815             bufferSize = bufferSizes[j];
1816             cnv2 = ucnv_safeClone(cnv, buffer[1], &bufferSize, &err);
1817 
1818             /* close the original immediately to make sure that the clone works by itself */
1819             ucnv_close(cnv);
1820 
1821             if( actualSizes[idx] <= (bufferSizes[j] - (int32_t)sizeof(UAlignedMemory)) &&
1822                 err == U_SAFECLONE_ALLOCATED_WARNING
1823             ) {
1824                 log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names[idx]);
1825             }
1826 
1827             /* check if the clone function overwrote any bytes that it is not supposed to touch */
1828             if(bufferSize <= bufferSizes[j]) {
1829                 /* used the stack buffer */
1830                 if( containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer[0]), 0xaa) ||
1831                     containsAnyOtherByte(buffer[1]+bufferSize, (int32_t)(sizeof(buffer)-(sizeof(buffer[0])+bufferSize)), 0xaa)
1832                 ) {
1833                     log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
1834                         names[idx], bufferSize, bufferSizes[j]);
1835                 }
1836             } else {
1837                 /* heap-allocated the clone */
1838                 if(containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer), 0xaa)) {
1839                     log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
1840                         names[idx], bufferSize, bufferSizes[j]);
1841                 }
1842             }
1843 
1844             pCharBuffer = charBuffer;
1845             pUniBuffer = uniBuffer;
1846 
1847             ucnv_fromUnicode(cnv2,
1848                             &pCharBuffer,
1849                             charBufferLimit,
1850                             &pUniBuffer,
1851                             uniBufferLimit,
1852                             NULL,
1853                             TRUE,
1854                             &err);
1855             if(U_FAILURE(err)){
1856                 log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err));
1857             }
1858             ucnv_toUnicode(cnv2,
1859                            &pUCharTarget,
1860                            pUCharTargetLimit,
1861                            &pCharSource,
1862                            pCharSourceLimit,
1863                            NULL,
1864                            TRUE,
1865                            &err
1866                            );
1867 
1868             if(U_FAILURE(err)){
1869                 log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err));
1870             }
1871 
1872             pConstCharBuffer = charBuffer;
1873             if (uniBuffer [0] != ucnv_getNextUChar(cnv2, &pConstCharBuffer, pCharBuffer, &err))
1874             {
1875                 log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err));
1876             }
1877             ucnv_close(cnv2);
1878         }
1879     }
1880 
1881     log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu  max preflighted clone size=%d (%s)  U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1882         sizeof(UConverter), maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
1883     if(maxBufferSize > U_CNV_SAFECLONE_BUFFERSIZE) {
1884         log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1885             maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
1886     }
1887 }
1888 
TestCCSID()1889 static void TestCCSID() {
1890 #if !UCONFIG_NO_LEGACY_CONVERSION
1891     UConverter *cnv;
1892     UErrorCode errorCode;
1893     int32_t ccsids[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
1894     int32_t i, ccsid;
1895 
1896     for(i=0; i<(int32_t)(sizeof(ccsids)/sizeof(int32_t)); ++i) {
1897         ccsid=ccsids[i];
1898 
1899         errorCode=U_ZERO_ERROR;
1900         cnv=ucnv_openCCSID(ccsid, UCNV_IBM, &errorCode);
1901         if(U_FAILURE(errorCode)) {
1902         log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid, u_errorName(errorCode));
1903             continue;
1904         }
1905 
1906         if(ccsid!=ucnv_getCCSID(cnv, &errorCode)) {
1907             log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid, ucnv_getCCSID(cnv, &errorCode));
1908         }
1909 
1910         /* skip gb18030(ccsid 1392) */
1911         if(ccsid != 1392 && UCNV_IBM!=ucnv_getPlatform(cnv, &errorCode)) {
1912             log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid, ucnv_getPlatform(cnv, &errorCode));
1913         }
1914 
1915         ucnv_close(cnv);
1916     }
1917 #endif
1918 }
1919 
1920 /* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
1921 
1922 /* CHUNK_SIZE defined in common\ucnv.c: */
1923 #define CHUNK_SIZE 1024
1924 
1925 static void bug1(void);
1926 static void bug2(void);
1927 static void bug3(void);
1928 
1929 static void
TestJ932(void)1930 TestJ932(void)
1931 {
1932    bug1(); /* Unicode intermediate buffer straddle bug */
1933    bug2(); /* pre-flighting size incorrect caused by simple overflow */
1934    bug3(); /* pre-flighting size incorrect caused by expansion overflow */
1935 }
1936 
1937 /*
1938  * jitterbug 932: test chunking boundary conditions in
1939 
1940     int32_t  ucnv_convert(const char *toConverterName,
1941                           const char *fromConverterName,
1942                           char *target,
1943                           int32_t targetSize,
1944                           const char *source,
1945                           int32_t sourceSize,
1946                           UErrorCode * err)
1947 
1948  * See discussions on the icu mailing list in
1949  * 2001-April with the subject "converter 'flush' question".
1950  *
1951  * Bug report and test code provided by Edward J. Batutis.
1952  */
bug1()1953 static void bug1()
1954 {
1955 #if !UCONFIG_NO_LEGACY_CONVERSION
1956    char char_in[CHUNK_SIZE+32];
1957    char char_out[CHUNK_SIZE*2];
1958 
1959    /* GB 18030 equivalent of U+10000 is 90308130 */
1960    static const char test_seq[]={ (char)0x90u, 0x30, (char)0x81u, 0x30 };
1961 
1962    UErrorCode err = U_ZERO_ERROR;
1963    int32_t i, test_seq_len = sizeof(test_seq);
1964 
1965    /*
1966     * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
1967     * until the straddle bug appears. I didn't want to hard-code everything so this test could
1968     * be expanded - however this is the only type of straddle bug I can think of at the moment -
1969     * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
1970     * other Unicode sequences cause a bug since combining sequences are not supported by the
1971     * converters.
1972     */
1973 
1974    for (i = test_seq_len; i >= 0; i--) {
1975       /* put character sequence into input buffer */
1976       memset(char_in, 0x61, sizeof(char_in)); /* GB 18030 'a' */
1977       memcpy(char_in + (CHUNK_SIZE - i), test_seq, test_seq_len);
1978 
1979       /* do the conversion */
1980       ucnv_convert("us-ascii", /* out */
1981                    "gb18030",  /* in */
1982                    char_out,
1983                    sizeof(char_out),
1984                    char_in,
1985                    sizeof(char_in),
1986                    &err);
1987 
1988       /* bug1: */
1989       if (err == U_TRUNCATED_CHAR_FOUND) {
1990          /* this happens when surrogate pair straddles the intermediate buffer in
1991           * T_UConverter_fromCodepageToCodepage */
1992          log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
1993       }
1994    }
1995 #endif
1996 }
1997 
1998 /* bug2: pre-flighting loop bug: simple overflow causes bug */
bug2()1999 static void bug2()
2000 {
2001     /* US-ASCII "1234567890" */
2002     static const char source[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
2003 #if !UCONFIG_ONLY_HTML_CONVERSION
2004     static const char sourceUTF8[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
2005     static const char sourceUTF32[]={ 0x00, 0x00, 0x00, 0x30,
2006                                       0x00, 0x00, 0x00, 0x31,
2007                                       0x00, 0x00, 0x00, 0x32,
2008                                       0x00, 0x00, 0x00, 0x33,
2009                                       0x00, 0x00, 0x00, 0x34,
2010                                       0x00, 0x00, 0x00, 0x35,
2011                                       0x00, 0x00, 0x00, 0x36,
2012                                       0x00, 0x00, 0x00, 0x37,
2013                                       0x00, 0x00, 0x00, 0x38,
2014                                       0x00, 0x00, (char)0xf0, 0x00};
2015 #endif
2016 
2017     static char target[5];
2018 
2019     UErrorCode err = U_ZERO_ERROR;
2020     int32_t size;
2021 
2022     /* do the conversion */
2023     size = ucnv_convert("iso-8859-1", /* out */
2024                         "us-ascii",  /* in */
2025                         target,
2026                         sizeof(target),
2027                         source,
2028                         sizeof(source),
2029                         &err);
2030 
2031     if ( size != 10 ) {
2032         /* bug2: size is 5, should be 10 */
2033         log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size);
2034     }
2035 
2036 #if !UCONFIG_ONLY_HTML_CONVERSION
2037     err = U_ZERO_ERROR;
2038     /* do the conversion */
2039     size = ucnv_convert("UTF-32BE", /* out */
2040                         "UTF-8",  /* in */
2041                         target,
2042                         sizeof(target),
2043                         sourceUTF8,
2044                         sizeof(sourceUTF8),
2045                         &err);
2046 
2047     if ( size != 32 ) {
2048         /* bug2: size is 5, should be 32 */
2049         log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size);
2050     }
2051 
2052     err = U_ZERO_ERROR;
2053     /* do the conversion */
2054     size = ucnv_convert("UTF-8", /* out */
2055                         "UTF-32BE",  /* in */
2056                         target,
2057                         sizeof(target),
2058                         sourceUTF32,
2059                         sizeof(sourceUTF32),
2060                         &err);
2061 
2062     if ( size != 12 ) {
2063         /* bug2: size is 5, should be 12 */
2064         log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size);
2065     }
2066 #endif
2067 }
2068 
2069 /*
2070  * bug3: when the characters expand going from source to target codepage
2071  *       you get bug3 in addition to bug2
2072  */
bug3()2073 static void bug3()
2074 {
2075 #if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
2076     char char_in[CHUNK_SIZE*4];
2077     char target[5];
2078     UErrorCode err = U_ZERO_ERROR;
2079     int32_t size;
2080 
2081     /*
2082      * first get the buggy size from bug2 then
2083      * compare it to buggy size with an expansion
2084      */
2085     memset(char_in, 0x61, sizeof(char_in)); /* US-ASCII 'a' */
2086 
2087     /* do the conversion */
2088     size = ucnv_convert("lmbcs",     /* out */
2089                         "us-ascii",  /* in */
2090                         target,
2091                         sizeof(target),
2092                         char_in,
2093                         sizeof(char_in),
2094                         &err);
2095 
2096     if ( size != sizeof(char_in) ) {
2097         /*
2098          * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
2099          * in the converter?), should be CHUNK_SIZE*4
2100          *
2101          * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
2102          */
2103         log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in), size);
2104     }
2105 
2106     /*
2107      * now do the conversion with expansion
2108      * ascii 0x08 expands to 0x0F 0x28 in lmbcs
2109      */
2110     memset(char_in, 8, sizeof(char_in));
2111     err = U_ZERO_ERROR;
2112 
2113     /* do the conversion */
2114     size = ucnv_convert("lmbcs", /* out */
2115                         "us-ascii",  /* in */
2116                         target,
2117                         sizeof(target),
2118                         char_in,
2119                         sizeof(char_in),
2120                         &err);
2121 
2122     /* expect 2X expansion */
2123     if ( size != sizeof(char_in) * 2 ) {
2124         /*
2125          * bug3:
2126          * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
2127          */
2128         log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in) * 2, size);
2129     }
2130 #endif
2131 }
2132 
2133 static void
convertExStreaming(UConverter * srcCnv,UConverter * targetCnv,const char * src,int32_t srcLength,const char * expectTarget,int32_t expectTargetLength,int32_t chunkSize,const char * testName,UErrorCode expectCode)2134 convertExStreaming(UConverter *srcCnv, UConverter *targetCnv,
2135                    const char *src, int32_t srcLength,
2136                    const char *expectTarget, int32_t expectTargetLength,
2137                    int32_t chunkSize,
2138                    const char *testName,
2139                    UErrorCode expectCode) {
2140     UChar pivotBuffer[CHUNK_SIZE];
2141     UChar *pivotSource, *pivotTarget;
2142     const UChar *pivotLimit;
2143 
2144     char targetBuffer[CHUNK_SIZE];
2145     char *target;
2146     const char *srcLimit, *finalSrcLimit, *targetLimit;
2147 
2148     int32_t targetLength;
2149 
2150     UBool flush;
2151 
2152     UErrorCode errorCode;
2153 
2154     /* setup */
2155     if(chunkSize>CHUNK_SIZE) {
2156         chunkSize=CHUNK_SIZE;
2157     }
2158 
2159     pivotSource=pivotTarget=pivotBuffer;
2160     pivotLimit=pivotBuffer+chunkSize;
2161 
2162     finalSrcLimit=src+srcLength;
2163     target=targetBuffer;
2164     targetLimit=targetBuffer+chunkSize;
2165 
2166     ucnv_resetToUnicode(srcCnv);
2167     ucnv_resetFromUnicode(targetCnv);
2168 
2169     errorCode=U_ZERO_ERROR;
2170     flush=FALSE;
2171 
2172     /* convert, streaming-style (both converters and pivot keep state) */
2173     for(;;) {
2174         /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
2175         if(src+chunkSize<=finalSrcLimit) {
2176             srcLimit=src+chunkSize;
2177         } else {
2178             srcLimit=finalSrcLimit;
2179         }
2180         ucnv_convertEx(targetCnv, srcCnv,
2181                        &target, targetLimit,
2182                        &src, srcLimit,
2183                        pivotBuffer, &pivotSource, &pivotTarget, pivotLimit,
2184                        FALSE, flush, &errorCode);
2185         targetLength=(int32_t)(target-targetBuffer);
2186         if(target>targetLimit) {
2187             log_err("ucnv_convertEx(%s) chunk[%d] target %p exceeds targetLimit %p\n",
2188                     testName, chunkSize, target, targetLimit);
2189             break; /* TODO: major problem! */
2190         }
2191         if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
2192             /* continue converting another chunk */
2193             errorCode=U_ZERO_ERROR;
2194             if(targetLength+chunkSize<=sizeof(targetBuffer)) {
2195                 targetLimit=target+chunkSize;
2196             } else {
2197                 targetLimit=targetBuffer+sizeof(targetBuffer);
2198             }
2199         } else if(U_FAILURE(errorCode)) {
2200             /* failure */
2201             break;
2202         } else if(flush) {
2203             /* all done */
2204             break;
2205         } else if(src==finalSrcLimit && pivotSource==pivotTarget) {
2206             /* all consumed, now flush without input (separate from conversion for testing) */
2207             flush=TRUE;
2208         }
2209     }
2210 
2211     if(!(errorCode==expectCode || (expectCode==U_ZERO_ERROR && errorCode==U_STRING_NOT_TERMINATED_WARNING))) {
2212         log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
2213                 testName, chunkSize, u_errorName(errorCode), u_errorName(expectCode));
2214     } else if(targetLength!=expectTargetLength) {
2215         log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
2216                 testName, chunkSize, targetLength, expectTargetLength);
2217     } else if(memcmp(targetBuffer, expectTarget, targetLength)!=0) {
2218         log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
2219                 testName, chunkSize);
2220     }
2221 }
2222 
2223 static void
convertExMultiStreaming(UConverter * srcCnv,UConverter * targetCnv,const char * src,int32_t srcLength,const char * expectTarget,int32_t expectTargetLength,const char * testName,UErrorCode expectCode)2224 convertExMultiStreaming(UConverter *srcCnv, UConverter *targetCnv,
2225                         const char *src, int32_t srcLength,
2226                         const char *expectTarget, int32_t expectTargetLength,
2227                         const char *testName,
2228                         UErrorCode expectCode) {
2229     convertExStreaming(srcCnv, targetCnv,
2230                        src, srcLength,
2231                        expectTarget, expectTargetLength,
2232                        1, testName, expectCode);
2233     convertExStreaming(srcCnv, targetCnv,
2234                        src, srcLength,
2235                        expectTarget, expectTargetLength,
2236                        3, testName, expectCode);
2237     convertExStreaming(srcCnv, targetCnv,
2238                        src, srcLength,
2239                        expectTarget, expectTargetLength,
2240                        7, testName, expectCode);
2241 }
2242 
TestConvertEx()2243 static void TestConvertEx() {
2244 #if !UCONFIG_NO_LEGACY_CONVERSION
2245     static const uint8_t
2246     utf8[]={
2247         /* 4e00           30a1              ff61              0410 */
2248         0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2249     },
2250     shiftJIS[]={
2251         0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2252     },
2253     errorTarget[]={
2254         /*
2255          * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2256          * SUB, SUB, 0x40, SUB, SUB, 0x40
2257          */
2258         0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
2259     };
2260 
2261     char srcBuffer[100], targetBuffer[100];
2262 
2263     const char *src;
2264     char *target;
2265 
2266     UChar pivotBuffer[100];
2267     UChar *pivotSource, *pivotTarget;
2268 
2269     UConverter *cnv1, *cnv2;
2270     UErrorCode errorCode;
2271 
2272     errorCode=U_ZERO_ERROR;
2273     cnv1=ucnv_open("UTF-8", &errorCode);
2274     if(U_FAILURE(errorCode)) {
2275         log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode));
2276         return;
2277     }
2278 
2279     cnv2=ucnv_open("Shift-JIS", &errorCode);
2280     if(U_FAILURE(errorCode)) {
2281         log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
2282         ucnv_close(cnv1);
2283         return;
2284     }
2285 
2286     /* test ucnv_convertEx() with streaming conversion style */
2287     convertExMultiStreaming(cnv1, cnv2,
2288         (const char *)utf8, sizeof(utf8), (const char *)shiftJIS, sizeof(shiftJIS),
2289         "UTF-8 -> Shift-JIS", U_ZERO_ERROR);
2290 
2291     convertExMultiStreaming(cnv2, cnv1,
2292         (const char *)shiftJIS, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8),
2293         "Shift-JIS -> UTF-8", U_ZERO_ERROR);
2294 
2295     /* U_ZERO_ERROR because by default the SUB callbacks are set */
2296     convertExMultiStreaming(cnv1, cnv2,
2297         (const char *)shiftJIS, sizeof(shiftJIS), (const char *)errorTarget, sizeof(errorTarget),
2298         "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR);
2299 
2300     /* test some simple conversions */
2301 
2302     /* NUL-terminated source and target */
2303     errorCode=U_STRING_NOT_TERMINATED_WARNING;
2304     memcpy(srcBuffer, utf8, sizeof(utf8));
2305     srcBuffer[sizeof(utf8)]=0;
2306     src=srcBuffer;
2307     target=targetBuffer;
2308     ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2309                    NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2310     if( errorCode!=U_ZERO_ERROR ||
2311         target-targetBuffer!=sizeof(shiftJIS) ||
2312         *target!=0 ||
2313         memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
2314     ) {
2315         log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
2316                 u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
2317     }
2318 
2319     /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
2320     errorCode=U_AMBIGUOUS_ALIAS_WARNING;
2321     memset(targetBuffer, 0xff, sizeof(targetBuffer));
2322     src=srcBuffer;
2323     target=targetBuffer;
2324     ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(shiftJIS), &src, NULL,
2325                    NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2326     if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2327         target-targetBuffer!=sizeof(shiftJIS) ||
2328         *target!=(char)0xff ||
2329         memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
2330     ) {
2331         log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
2332                 u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
2333     }
2334 
2335     /* bad arguments */
2336     errorCode=U_MESSAGE_PARSE_ERROR;
2337     src=srcBuffer;
2338     target=targetBuffer;
2339     ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2340                    NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2341     if(errorCode!=U_MESSAGE_PARSE_ERROR) {
2342         log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
2343     }
2344 
2345     /* pivotLimit==pivotStart */
2346     errorCode=U_ZERO_ERROR;
2347     pivotSource=pivotTarget=pivotBuffer;
2348     ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2349                    pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer, TRUE, TRUE, &errorCode);
2350     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2351         log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode));
2352     }
2353 
2354     /* *pivotSource==NULL */
2355     errorCode=U_ZERO_ERROR;
2356     pivotSource=NULL;
2357     ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2358                    pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
2359     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2360         log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode));
2361     }
2362 
2363     /* *source==NULL */
2364     errorCode=U_ZERO_ERROR;
2365     src=NULL;
2366     pivotSource=pivotBuffer;
2367     ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2368                    pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
2369     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2370         log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode));
2371     }
2372 
2373     /* streaming conversion without a pivot buffer */
2374     errorCode=U_ZERO_ERROR;
2375     src=srcBuffer;
2376     pivotSource=pivotBuffer;
2377     ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2378                    NULL, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, FALSE, &errorCode);
2379     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2380         log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode));
2381     }
2382 
2383     ucnv_close(cnv1);
2384     ucnv_close(cnv2);
2385 #endif
2386 }
2387 
2388 /* Test illegal UTF-8 input: Data and functions for TestConvertExFromUTF8(). */
2389 static const char *const badUTF8[]={
2390     /* trail byte */
2391     "\x80",
2392 
2393     /* truncated multi-byte sequences */
2394     "\xd0",
2395     "\xe0",
2396     "\xe1",
2397     "\xed",
2398     "\xee",
2399     "\xf0",
2400     "\xf1",
2401     "\xf4",
2402     "\xf8",
2403     "\xfc",
2404 
2405     "\xe0\x80",
2406     "\xe0\xa0",
2407     "\xe1\x80",
2408     "\xed\x80",
2409     "\xed\xa0",
2410     "\xee\x80",
2411     "\xf0\x80",
2412     "\xf0\x90",
2413     "\xf1\x80",
2414     "\xf4\x80",
2415     "\xf4\x90",
2416     "\xf8\x80",
2417     "\xfc\x80",
2418 
2419     "\xf0\x80\x80",
2420     "\xf0\x90\x80",
2421     "\xf1\x80\x80",
2422     "\xf4\x80\x80",
2423     "\xf4\x90\x80",
2424     "\xf8\x80\x80",
2425     "\xfc\x80\x80",
2426 
2427     "\xf8\x80\x80\x80",
2428     "\xfc\x80\x80\x80",
2429 
2430     "\xfc\x80\x80\x80\x80",
2431 
2432     /* complete sequences but non-shortest forms or out of range etc. */
2433     "\xc0\x80",
2434     "\xe0\x80\x80",
2435     "\xed\xa0\x80",
2436     "\xf0\x80\x80\x80",
2437     "\xf4\x90\x80\x80",
2438     "\xf8\x80\x80\x80\x80",
2439     "\xfc\x80\x80\x80\x80\x80",
2440     "\xfe",
2441     "\xff"
2442 };
2443 
2444 #define ARG_CHAR_ARR_SIZE 8
2445 
2446 /* get some character that can be converted and convert it */
getTestChar(UConverter * cnv,const char * converterName,char charUTF8[4],int32_t * pCharUTF8Length,char char0[ARG_CHAR_ARR_SIZE],int32_t * pChar0Length,char char1[ARG_CHAR_ARR_SIZE],int32_t * pChar1Length)2447 static UBool getTestChar(UConverter *cnv, const char *converterName,
2448                          char charUTF8[4], int32_t *pCharUTF8Length,
2449                          char char0[ARG_CHAR_ARR_SIZE], int32_t *pChar0Length,
2450                          char char1[ARG_CHAR_ARR_SIZE], int32_t *pChar1Length) {
2451     UChar utf16[U16_MAX_LENGTH];
2452     int32_t utf16Length;
2453 
2454     const UChar *utf16Source;
2455     char *target;
2456 
2457     USet *set;
2458     UChar32 c;
2459     UErrorCode errorCode;
2460 
2461     errorCode=U_ZERO_ERROR;
2462     set=uset_open(1, 0);
2463     ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode);
2464     c=uset_charAt(set, uset_size(set)/2);
2465     uset_close(set);
2466 
2467     utf16Length=0;
2468     U16_APPEND_UNSAFE(utf16, utf16Length, c);
2469     *pCharUTF8Length=0;
2470     U8_APPEND_UNSAFE(charUTF8, *pCharUTF8Length, c);
2471 
2472     utf16Source=utf16;
2473     target=char0;
2474     ucnv_fromUnicode(cnv,
2475                      &target, char0+ARG_CHAR_ARR_SIZE,
2476                      &utf16Source, utf16+utf16Length,
2477                      NULL, FALSE, &errorCode);
2478     *pChar0Length=(int32_t)(target-char0);
2479 
2480     utf16Source=utf16;
2481     target=char1;
2482     ucnv_fromUnicode(cnv,
2483                      &target, char1+ARG_CHAR_ARR_SIZE,
2484                      &utf16Source, utf16+utf16Length,
2485                      NULL, FALSE, &errorCode);
2486     *pChar1Length=(int32_t)(target-char1);
2487 
2488     if(U_FAILURE(errorCode)) {
2489         log_err("unable to get test character for %s - %s\n", converterName, u_errorName(errorCode));
2490         return FALSE;
2491     }
2492     return TRUE;
2493 }
2494 
testFromTruncatedUTF8(UConverter * utf8Cnv,UConverter * cnv,const char * converterName,char charUTF8[4],int32_t charUTF8Length,char char0[8],int32_t char0Length,char char1[8],int32_t char1Length)2495 static void testFromTruncatedUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName,
2496                                   char charUTF8[4], int32_t charUTF8Length,
2497                                   char char0[8], int32_t char0Length,
2498                                   char char1[8], int32_t char1Length) {
2499     char utf8[16];
2500     int32_t utf8Length;
2501 
2502     char output[16];
2503     int32_t outputLength;
2504 
2505     char invalidChars[8];
2506     int8_t invalidLength;
2507 
2508     const char *source;
2509     char *target;
2510 
2511     UChar pivotBuffer[8];
2512     UChar *pivotSource, *pivotTarget;
2513 
2514     UErrorCode errorCode;
2515     int32_t i;
2516 
2517     /* test truncated sequences */
2518     errorCode=U_ZERO_ERROR;
2519     ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
2520 
2521     memcpy(utf8, charUTF8, charUTF8Length);
2522 
2523     for(i=0; i<UPRV_LENGTHOF(badUTF8); ++i) {
2524         /* truncated sequence? */
2525         int32_t length=strlen(badUTF8[i]);
2526         if(length>=(1+U8_COUNT_TRAIL_BYTES(badUTF8[i][0]))) {
2527             continue;
2528         }
2529 
2530         /* assemble a string with the test character and the truncated sequence */
2531         memcpy(utf8+charUTF8Length, badUTF8[i], length);
2532         utf8Length=charUTF8Length+length;
2533 
2534         /* convert and check the invalidChars */
2535         source=utf8;
2536         target=output;
2537         pivotSource=pivotTarget=pivotBuffer;
2538         errorCode=U_ZERO_ERROR;
2539         ucnv_convertEx(cnv, utf8Cnv,
2540                        &target, output+sizeof(output),
2541                        &source, utf8+utf8Length,
2542                        pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+UPRV_LENGTHOF(pivotBuffer),
2543                        TRUE, TRUE, /* reset & flush */
2544                        &errorCode);
2545         outputLength=(int32_t)(target-output);
2546         (void)outputLength;   /* Suppress set but not used warning. */
2547         if(errorCode!=U_TRUNCATED_CHAR_FOUND || pivotSource!=pivotBuffer) {
2548             log_err("unexpected error %s from %s badUTF8[%ld]\n", u_errorName(errorCode), converterName, (long)i);
2549             continue;
2550         }
2551 
2552         errorCode=U_ZERO_ERROR;
2553         invalidLength=(int8_t)sizeof(invalidChars);
2554         ucnv_getInvalidChars(utf8Cnv, invalidChars, &invalidLength, &errorCode);
2555         if(invalidLength!=length || 0!=memcmp(invalidChars, badUTF8[i], length)) {
2556             log_err("wrong invalidChars from %s badUTF8[%ld]\n", converterName, (long)i);
2557         }
2558     }
2559 }
2560 
testFromBadUTF8(UConverter * utf8Cnv,UConverter * cnv,const char * converterName,char charUTF8[4],int32_t charUTF8Length,char char0[8],int32_t char0Length,char char1[8],int32_t char1Length)2561 static void testFromBadUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName,
2562                             char charUTF8[4], int32_t charUTF8Length,
2563                             char char0[8], int32_t char0Length,
2564                             char char1[8], int32_t char1Length) {
2565     char utf8[600], expect[600];
2566     int32_t utf8Length, expectLength;
2567 
2568     char testName[32];
2569 
2570     UErrorCode errorCode;
2571     int32_t i;
2572 
2573     errorCode=U_ZERO_ERROR;
2574     ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, NULL, NULL, &errorCode);
2575 
2576     /*
2577      * assemble an input string with the test character between each
2578      * bad sequence,
2579      * and an expected string with repeated test character output
2580      */
2581     memcpy(utf8, charUTF8, charUTF8Length);
2582     utf8Length=charUTF8Length;
2583 
2584     memcpy(expect, char0, char0Length);
2585     expectLength=char0Length;
2586 
2587     for(i=0; i<UPRV_LENGTHOF(badUTF8); ++i) {
2588         int32_t length=strlen(badUTF8[i]);
2589         memcpy(utf8+utf8Length, badUTF8[i], length);
2590         utf8Length+=length;
2591 
2592         memcpy(utf8+utf8Length, charUTF8, charUTF8Length);
2593         utf8Length+=charUTF8Length;
2594 
2595         memcpy(expect+expectLength, char1, char1Length);
2596         expectLength+=char1Length;
2597     }
2598 
2599     /* expect that each bad UTF-8 sequence is detected and skipped */
2600     strcpy(testName, "from bad UTF-8 to ");
2601     strcat(testName, converterName);
2602 
2603     convertExMultiStreaming(utf8Cnv, cnv,
2604                             utf8, utf8Length,
2605                             expect, expectLength,
2606                             testName,
2607                             U_ZERO_ERROR);
2608 }
2609 
2610 /* Test illegal UTF-8 input. */
TestConvertExFromUTF8()2611 static void TestConvertExFromUTF8() {
2612     static const char *const converterNames[]={
2613 #if !UCONFIG_NO_LEGACY_CONVERSION
2614         "windows-1252",
2615         "shift-jis",
2616 #endif
2617         "us-ascii",
2618         "iso-8859-1",
2619         "utf-8"
2620     };
2621 
2622     UConverter *utf8Cnv, *cnv;
2623     UErrorCode errorCode;
2624     int32_t i;
2625 
2626     /* fromUnicode versions of some character, from initial state and later */
2627     char charUTF8[4], char0[8], char1[8];
2628     int32_t charUTF8Length, char0Length, char1Length;
2629 
2630     errorCode=U_ZERO_ERROR;
2631     utf8Cnv=ucnv_open("UTF-8", &errorCode);
2632     if(U_FAILURE(errorCode)) {
2633         log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode));
2634         return;
2635     }
2636 
2637     for(i=0; i<UPRV_LENGTHOF(converterNames); ++i) {
2638         errorCode=U_ZERO_ERROR;
2639         cnv=ucnv_open(converterNames[i], &errorCode);
2640         if(U_FAILURE(errorCode)) {
2641             log_data_err("unable to open %s converter - %s\n", converterNames[i], u_errorName(errorCode));
2642             continue;
2643         }
2644         if(!getTestChar(cnv, converterNames[i], charUTF8, &charUTF8Length, char0, &char0Length, char1, &char1Length)) {
2645             continue;
2646         }
2647         testFromTruncatedUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length);
2648         testFromBadUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length);
2649         ucnv_close(cnv);
2650     }
2651     ucnv_close(utf8Cnv);
2652 }
2653 
TestConvertExFromUTF8_C5F0()2654 static void TestConvertExFromUTF8_C5F0() {
2655     static const char *const converterNames[]={
2656 #if !UCONFIG_NO_LEGACY_CONVERSION
2657         "windows-1251",
2658         "shift-jis",
2659 #endif
2660         "us-ascii",
2661         "iso-8859-1",
2662         "utf-8"
2663     };
2664 
2665     UConverter *utf8Cnv, *cnv;
2666     UErrorCode errorCode;
2667     int32_t i;
2668 
2669     static const char bad_utf8[2]={ (char)0xC5, (char)0xF0 };
2670     /* Expect "&#65533;&#65533;" (2x U+FFFD as decimal NCRs) */
2671     static const char twoNCRs[16]={
2672         0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B,
2673         0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B
2674     };
2675     static const char twoFFFD[6]={
2676         (char)0xef, (char)0xbf, (char)0xbd,
2677         (char)0xef, (char)0xbf, (char)0xbd
2678     };
2679     const char *expected;
2680     int32_t expectedLength;
2681     char dest[20];  /* longer than longest expectedLength */
2682 
2683     const char *src;
2684     char *target;
2685 
2686     UChar pivotBuffer[128];
2687     UChar *pivotSource, *pivotTarget;
2688 
2689     errorCode=U_ZERO_ERROR;
2690     utf8Cnv=ucnv_open("UTF-8", &errorCode);
2691     if(U_FAILURE(errorCode)) {
2692         log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode));
2693         return;
2694     }
2695 
2696     for(i=0; i<UPRV_LENGTHOF(converterNames); ++i) {
2697         errorCode=U_ZERO_ERROR;
2698         cnv=ucnv_open(converterNames[i], &errorCode);
2699         ucnv_setFromUCallBack(cnv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_XML_DEC,
2700                               NULL, NULL, &errorCode);
2701         if(U_FAILURE(errorCode)) {
2702             log_data_err("unable to open %s converter - %s\n",
2703                          converterNames[i], u_errorName(errorCode));
2704             continue;
2705         }
2706         src=bad_utf8;
2707         target=dest;
2708         uprv_memset(dest, 9, sizeof(dest));
2709         if(i==UPRV_LENGTHOF(converterNames)-1) {
2710             /* conversion to UTF-8 yields two U+FFFD directly */
2711             expected=twoFFFD;
2712             expectedLength=6;
2713         } else {
2714             /* conversion to a non-Unicode charset yields two NCRs */
2715             expected=twoNCRs;
2716             expectedLength=16;
2717         }
2718         pivotBuffer[0]=0;
2719         pivotBuffer[1]=1;
2720         pivotBuffer[2]=2;
2721         pivotSource=pivotTarget=pivotBuffer;
2722         ucnv_convertEx(
2723             cnv, utf8Cnv,
2724             &target, dest+expectedLength,
2725             &src, bad_utf8+sizeof(bad_utf8),
2726             pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+UPRV_LENGTHOF(pivotBuffer),
2727             TRUE, TRUE, &errorCode);
2728         if( errorCode!=U_STRING_NOT_TERMINATED_WARNING || src!=bad_utf8+2 ||
2729             target!=dest+expectedLength || 0!=uprv_memcmp(dest, expected, expectedLength) ||
2730             dest[expectedLength]!=9
2731         ) {
2732             log_err("ucnv_convertEx(UTF-8 C5 F0 -> %s/decimal NCRs) failed\n", converterNames[i]);
2733         }
2734         ucnv_close(cnv);
2735     }
2736     ucnv_close(utf8Cnv);
2737 }
2738 
2739 static void
TestConvertAlgorithmic()2740 TestConvertAlgorithmic() {
2741 #if !UCONFIG_NO_LEGACY_CONVERSION
2742     static const uint8_t
2743     utf8[]={
2744         /* 4e00           30a1              ff61              0410 */
2745         0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2746     },
2747     shiftJIS[]={
2748         0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2749     },
2750   /*errorTarget[]={*/
2751         /*
2752          * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2753          * SUB, SUB, 0x40, SUB, SUB, 0x40
2754          */
2755   /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
2756   /*},*/
2757     utf16[]={
2758         0xfe, 0xff /* BOM only, no text */
2759     };
2760 #if !UCONFIG_ONLY_HTML_CONVERSION
2761     static const uint8_t utf32[]={
2762         0xff, 0xfe, 0, 0 /* BOM only, no text */
2763     };
2764 #endif
2765 
2766     char target[100], utf8NUL[100], shiftJISNUL[100];
2767 
2768     UConverter *cnv;
2769     UErrorCode errorCode;
2770 
2771     int32_t length;
2772 
2773     errorCode=U_ZERO_ERROR;
2774     cnv=ucnv_open("Shift-JIS", &errorCode);
2775     if(U_FAILURE(errorCode)) {
2776         log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
2777         ucnv_close(cnv);
2778         return;
2779     }
2780 
2781     memcpy(utf8NUL, utf8, sizeof(utf8));
2782     utf8NUL[sizeof(utf8)]=0;
2783     memcpy(shiftJISNUL, shiftJIS, sizeof(shiftJIS));
2784     shiftJISNUL[sizeof(shiftJIS)]=0;
2785 
2786     /*
2787      * The to/from algorithmic convenience functions share a common implementation,
2788      * so we need not test all permutations of them.
2789      */
2790 
2791     /* length in, not terminated out */
2792     errorCode=U_ZERO_ERROR;
2793     length=ucnv_fromAlgorithmic(cnv, UCNV_UTF8, target, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8), &errorCode);
2794     if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2795         length!=sizeof(shiftJIS) ||
2796         memcmp(target, shiftJIS, length)!=0
2797     ) {
2798         log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
2799                 u_errorName(errorCode), length, sizeof(shiftJIS));
2800     }
2801 
2802     /* terminated in and out */
2803     memset(target, 0x55, sizeof(target));
2804     errorCode=U_STRING_NOT_TERMINATED_WARNING;
2805     length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, -1, &errorCode);
2806     if( errorCode!=U_ZERO_ERROR ||
2807         length!=sizeof(utf8) ||
2808         memcmp(target, utf8, length)!=0
2809     ) {
2810         log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
2811                 u_errorName(errorCode), length, sizeof(shiftJIS));
2812     }
2813 
2814     /* empty string, some target buffer */
2815     errorCode=U_STRING_NOT_TERMINATED_WARNING;
2816     length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, 0, &errorCode);
2817     if( errorCode!=U_ZERO_ERROR ||
2818         length!=0
2819     ) {
2820         log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
2821                 u_errorName(errorCode), length);
2822     }
2823 
2824     /* pseudo-empty string, no target buffer */
2825     errorCode=U_ZERO_ERROR;
2826     length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
2827     if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2828         length!=0
2829     ) {
2830         log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2831                 u_errorName(errorCode), length);
2832     }
2833 
2834 #if !UCONFIG_ONLY_HTML_CONVERSION
2835     errorCode=U_ZERO_ERROR;
2836     length=ucnv_fromAlgorithmic(cnv, UCNV_UTF32, target, 0, (const char *)utf32, 4, &errorCode);
2837     if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2838         length!=0
2839     ) {
2840         log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2841                 u_errorName(errorCode), length);
2842     }
2843 #endif
2844 
2845     /* bad arguments */
2846     errorCode=U_MESSAGE_PARSE_ERROR;
2847     length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
2848     if(errorCode!=U_MESSAGE_PARSE_ERROR) {
2849         log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
2850     }
2851 
2852     /* source==NULL */
2853     errorCode=U_ZERO_ERROR;
2854     length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, NULL, 2, &errorCode);
2855     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2856         log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode));
2857     }
2858 
2859     /* illegal alg. type */
2860     errorCode=U_ZERO_ERROR;
2861     length=ucnv_fromAlgorithmic(cnv, (UConverterType)99, target, 0, (const char *)utf16, 2, &errorCode);
2862     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2863         log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode));
2864     }
2865 ucnv_close(cnv);
2866 #endif
2867 }
2868 
2869 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
TestLMBCSMaxChar(void)2870 static void TestLMBCSMaxChar(void) {
2871     static const struct {
2872         int8_t maxSize;
2873         const char *name;
2874     } converter[] = {
2875         /* some non-LMBCS converters - perfect test setup here */
2876         { 1, "US-ASCII"},
2877         { 1, "ISO-8859-1"},
2878 
2879         { 2, "UTF-16"},
2880         { 2, "UTF-16BE"},
2881         { 3, "UTF-8"},
2882         { 3, "CESU-8"},
2883         { 3, "SCSU"},
2884         { 4, "UTF-32"},
2885         { 4, "UTF-7"},
2886         { 4, "IMAP-mailbox-name"},
2887         { 4, "BOCU-1"},
2888 
2889         { 1, "windows-1256"},
2890         { 2, "Shift-JIS"},
2891         { 2, "ibm-16684"},
2892         { 3, "ibm-930"},
2893         { 3, "ibm-1390"},
2894         { 4, "*test3"},
2895         { 16,"*test4"},
2896 
2897         { 4, "ISCII"},
2898         { 4, "HZ"},
2899 
2900         { 3, "ISO-2022"},
2901         { 3, "ISO-2022-KR"},
2902         { 6, "ISO-2022-JP"},
2903         { 8, "ISO-2022-CN"},
2904 
2905         /* LMBCS */
2906         { 3, "LMBCS-1"},
2907         { 3, "LMBCS-2"},
2908         { 3, "LMBCS-3"},
2909         { 3, "LMBCS-4"},
2910         { 3, "LMBCS-5"},
2911         { 3, "LMBCS-6"},
2912         { 3, "LMBCS-8"},
2913         { 3, "LMBCS-11"},
2914         { 3, "LMBCS-16"},
2915         { 3, "LMBCS-17"},
2916         { 3, "LMBCS-18"},
2917         { 3, "LMBCS-19"}
2918     };
2919     int32_t idx;
2920 
2921     for (idx = 0; idx < UPRV_LENGTHOF(converter); idx++) {
2922         UErrorCode status = U_ZERO_ERROR;
2923         UConverter *cnv = cnv_open(converter[idx].name, &status);
2924         if (U_FAILURE(status)) {
2925             continue;
2926         }
2927         if (converter[idx].maxSize != ucnv_getMaxCharSize(cnv)) {
2928             log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
2929                 converter[idx].name, converter[idx].maxSize, ucnv_getMaxCharSize(cnv));
2930         }
2931         ucnv_close(cnv);
2932     }
2933 
2934     /* mostly test that the macro compiles */
2935     if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
2936         log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
2937     }
2938 }
2939 #endif
2940 
TestJ1968(void)2941 static void TestJ1968(void) {
2942     UErrorCode err = U_ZERO_ERROR;
2943     UConverter *cnv;
2944     char myConvName[] = "My really really really really really really really really really really really"
2945                           " really really really really really really really really really really really"
2946                           " really really really really really really really really long converter name";
2947     UChar myConvNameU[sizeof(myConvName)];
2948 
2949     u_charsToUChars(myConvName, myConvNameU, sizeof(myConvName));
2950 
2951     err = U_ZERO_ERROR;
2952     myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH+1] = 0;
2953     cnv = ucnv_openU(myConvNameU, &err);
2954     if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2955         log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2956     }
2957 
2958     err = U_ZERO_ERROR;
2959     myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
2960     cnv = ucnv_openU(myConvNameU, &err);
2961     if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2962         log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2963     }
2964 
2965     err = U_ZERO_ERROR;
2966     myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
2967     cnv = ucnv_openU(myConvNameU, &err);
2968     if (cnv || err != U_FILE_ACCESS_ERROR) {
2969         log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2970     }
2971 
2972 
2973 
2974 
2975     err = U_ZERO_ERROR;
2976     cnv = ucnv_open(myConvName, &err);
2977     if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2978         log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2979     }
2980 
2981     err = U_ZERO_ERROR;
2982     myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = ',';
2983     cnv = ucnv_open(myConvName, &err);
2984     if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2985         log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2986     }
2987 
2988     err = U_ZERO_ERROR;
2989     myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
2990     cnv = ucnv_open(myConvName, &err);
2991     if (cnv || err != U_FILE_ACCESS_ERROR) {
2992         log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2993     }
2994 
2995     err = U_ZERO_ERROR;
2996     myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
2997     strncpy(myConvName + UCNV_MAX_CONVERTER_NAME_LENGTH, "locale=", 7);
2998     cnv = ucnv_open(myConvName, &err);
2999     if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
3000         log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
3001     }
3002 
3003     /* The comma isn't really a part of the converter name. */
3004     err = U_ZERO_ERROR;
3005     myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
3006     cnv = ucnv_open(myConvName, &err);
3007     if (cnv || err != U_FILE_ACCESS_ERROR) {
3008         log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
3009     }
3010 
3011     err = U_ZERO_ERROR;
3012     myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ' ';
3013     cnv = ucnv_open(myConvName, &err);
3014     if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
3015         log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
3016     }
3017 
3018     err = U_ZERO_ERROR;
3019     myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
3020     cnv = ucnv_open(myConvName, &err);
3021     if (cnv || err != U_FILE_ACCESS_ERROR) {
3022         log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
3023     }
3024 
3025 }
3026 
3027 #if !UCONFIG_NO_LEGACY_CONVERSION
3028 static void
testSwap(const char * name,UBool swap)3029 testSwap(const char *name, UBool swap) {
3030     /*
3031      * Test Unicode text.
3032      * Contains characters that are the highest for some of the
3033      * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
3034      * tables copies the entire tables.
3035      */
3036     static const UChar text[]={
3037         0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
3038     };
3039 
3040     UChar uNormal[32], uSwapped[32];
3041     char normal[32], swapped[32];
3042     const UChar *pcu;
3043     UChar *pu;
3044     char *pc;
3045     int32_t i, normalLength, swappedLength;
3046     UChar u;
3047     char c;
3048 
3049     const char *swappedName;
3050     UConverter *cnv, *swapCnv;
3051     UErrorCode errorCode;
3052 
3053     /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
3054 
3055     /* open both the normal and the LF/NL-swapping converters */
3056     strcpy(swapped, name);
3057     strcat(swapped, UCNV_SWAP_LFNL_OPTION_STRING);
3058 
3059     errorCode=U_ZERO_ERROR;
3060     swapCnv=ucnv_open(swapped, &errorCode);
3061     cnv=ucnv_open(name, &errorCode);
3062     if(U_FAILURE(errorCode)) {
3063         log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name, swapped, u_errorName(errorCode));
3064         goto cleanup;
3065     }
3066 
3067     /* the name must contain the swap option if and only if we expect the converter to swap */
3068     swappedName=ucnv_getName(swapCnv, &errorCode);
3069     if(U_FAILURE(errorCode)) {
3070         log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name, u_errorName(errorCode));
3071         goto cleanup;
3072     }
3073 
3074     pc=strstr(swappedName, UCNV_SWAP_LFNL_OPTION_STRING);
3075     if(swap != (pc!=NULL)) {
3076         log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name, swappedName, swap);
3077         goto cleanup;
3078     }
3079 
3080     /* convert to EBCDIC */
3081     pcu=text;
3082     pc=normal;
3083     ucnv_fromUnicode(cnv, &pc, normal+UPRV_LENGTHOF(normal), &pcu, text+UPRV_LENGTHOF(text), NULL, TRUE, &errorCode);
3084     normalLength=(int32_t)(pc-normal);
3085 
3086     pcu=text;
3087     pc=swapped;
3088     ucnv_fromUnicode(swapCnv, &pc, swapped+UPRV_LENGTHOF(swapped), &pcu, text+UPRV_LENGTHOF(text), NULL, TRUE, &errorCode);
3089     swappedLength=(int32_t)(pc-swapped);
3090 
3091     if(U_FAILURE(errorCode)) {
3092         log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name, u_errorName(errorCode));
3093         goto cleanup;
3094     }
3095 
3096     /* compare EBCDIC output */
3097     if(normalLength!=swappedLength) {
3098         log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
3099         goto cleanup;
3100     }
3101     for(i=0; i<normalLength; ++i) {
3102         /* swap EBCDIC LF/NL for comparison */
3103         c=normal[i];
3104         if(swap) {
3105             if(c==0x15) {
3106                 c=0x25;
3107             } else if(c==0x25) {
3108                 c=0x15;
3109             }
3110         }
3111 
3112         if(c!=swapped[i]) {
3113             log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name, i, (uint8_t)swapped[i]);
3114             goto cleanup;
3115         }
3116     }
3117 
3118     /* convert back to Unicode (may not roundtrip) */
3119     pc=normal;
3120     pu=uNormal;
3121     ucnv_toUnicode(cnv, &pu, uNormal+UPRV_LENGTHOF(uNormal), (const char **)&pc, normal+normalLength, NULL, TRUE, &errorCode);
3122     normalLength=(int32_t)(pu-uNormal);
3123 
3124     pc=normal;
3125     pu=uSwapped;
3126     ucnv_toUnicode(swapCnv, &pu, uSwapped+UPRV_LENGTHOF(uSwapped), (const char **)&pc, normal+swappedLength, NULL, TRUE, &errorCode);
3127     swappedLength=(int32_t)(pu-uSwapped);
3128 
3129     if(U_FAILURE(errorCode)) {
3130         log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name, u_errorName(errorCode));
3131         goto cleanup;
3132     }
3133 
3134     /* compare EBCDIC output */
3135     if(normalLength!=swappedLength) {
3136         log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
3137         goto cleanup;
3138     }
3139     for(i=0; i<normalLength; ++i) {
3140         /* swap EBCDIC LF/NL for comparison */
3141         u=uNormal[i];
3142         if(swap) {
3143             if(u==0xa) {
3144                 u=0x85;
3145             } else if(u==0x85) {
3146                 u=0xa;
3147             }
3148         }
3149 
3150         if(u!=uSwapped[i]) {
3151             log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name, i, uSwapped[i]);
3152             goto cleanup;
3153         }
3154     }
3155 
3156     /* clean up */
3157 cleanup:
3158     ucnv_close(cnv);
3159     ucnv_close(swapCnv);
3160 }
3161 
3162 static void
TestEBCDICSwapLFNL()3163 TestEBCDICSwapLFNL() {
3164     static const struct {
3165         const char *name;
3166         UBool swap;
3167     } tests[]={
3168         { "ibm-37", TRUE },
3169         { "ibm-1047", TRUE },
3170         { "ibm-1140", TRUE },
3171         { "ibm-930", TRUE },
3172         { "iso-8859-3", FALSE }
3173     };
3174 
3175     int i;
3176 
3177     for(i=0; i<UPRV_LENGTHOF(tests); ++i) {
3178         testSwap(tests[i].name, tests[i].swap);
3179     }
3180 }
3181 #else
3182 static void
TestEBCDICSwapLFNL()3183 TestEBCDICSwapLFNL() {
3184   /* test nothing... */
3185 }
3186 #endif
3187 
TestFromUCountPending()3188 static void TestFromUCountPending(){
3189 #if !UCONFIG_NO_LEGACY_CONVERSION
3190     UErrorCode status = U_ZERO_ERROR;
3191 /*       const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */
3192     static const struct {
3193         UChar input[6];
3194         int32_t len;
3195         int32_t exp;
3196     }fromUnicodeTests[] = {
3197         /*m:n conversion*/
3198         {{0xdbc4},1,1},
3199         {{ 0xdbc4, 0xde34, 0xd84d},3,1},
3200         {{ 0xdbc4, 0xde34, 0xd900},3,3},
3201     };
3202     int i;
3203     UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
3204     if(U_FAILURE(status)){
3205         log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
3206         return;
3207     }
3208     for(i=0; i<UPRV_LENGTHOF(fromUnicodeTests); ++i) {
3209         char tgt[10];
3210         char* target = tgt;
3211         char* targetLimit = target + 10;
3212         const UChar* source = fromUnicodeTests[i].input;
3213         const UChar* sourceLimit = source + fromUnicodeTests[i].len;
3214         int32_t len = 0;
3215         ucnv_reset(cnv);
3216         ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3217         len = ucnv_fromUCountPending(cnv, &status);
3218         if(U_FAILURE(status)){
3219             log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3220             status = U_ZERO_ERROR;
3221             continue;
3222         }
3223         if(len != fromUnicodeTests[i].exp){
3224             log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n");
3225         }
3226     }
3227     status = U_ZERO_ERROR;
3228     {
3229         /*
3230          * The converter has to read the tail before it knows that
3231          * only head alone matches.
3232          * At the end, the output for head will overflow the target,
3233          * middle will be pending, and tail will not have been consumed.
3234          */
3235         /*
3236         \U00101234  -> x (<U101234>   \x07 |0)
3237         \U00101234\U00050005 -> y (<U101234>+<U50005>          \x07+\x00+\x01\x02\x0e+\x05 |0)
3238         \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0)
3239         \U00060007 -> unassigned
3240         */
3241         static const UChar head[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */
3242         static const UChar middle[] = {0xD940,0x0000};     /* first half of \U00060006 or \U00060007 */
3243         static const UChar tail[] = {0xDC07,0x0000};/* second half of \U00060007 */
3244         char tgt[10];
3245         char* target = tgt;
3246         char* targetLimit = target + 2; /* expect overflow from converting \U00101234\U00050005 */
3247         const UChar* source = head;
3248         const UChar* sourceLimit = source + u_strlen(head);
3249         int32_t len = 0;
3250         ucnv_reset(cnv);
3251         ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3252         len = ucnv_fromUCountPending(cnv, &status);
3253         if(U_FAILURE(status)){
3254             log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3255             status = U_ZERO_ERROR;
3256         }
3257         if(len!=4){
3258             log_err("ucnv_fromUInputHeld did not return correct length for head\n");
3259         }
3260         source = middle;
3261         sourceLimit = source + u_strlen(middle);
3262         ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3263         len = ucnv_fromUCountPending(cnv, &status);
3264         if(U_FAILURE(status)){
3265             log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3266             status = U_ZERO_ERROR;
3267         }
3268         if(len!=5){
3269             log_err("ucnv_fromUInputHeld did not return correct length for middle\n");
3270         }
3271         source = tail;
3272         sourceLimit = source + u_strlen(tail);
3273         ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3274         if(status != U_BUFFER_OVERFLOW_ERROR){
3275             log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3276         }
3277         status = U_ZERO_ERROR;
3278         len = ucnv_fromUCountPending(cnv, &status);
3279         /* middle[1] is pending, tail has not been consumed */
3280         if(U_FAILURE(status)){
3281             log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status));
3282         }
3283         if(len!=1){
3284             log_err("ucnv_fromUInputHeld did not return correct length for tail\n");
3285         }
3286     }
3287     ucnv_close(cnv);
3288 #endif
3289 }
3290 
3291 static void
TestToUCountPending()3292 TestToUCountPending(){
3293 #if !UCONFIG_NO_LEGACY_CONVERSION
3294     UErrorCode status = U_ZERO_ERROR;
3295     static const struct {
3296         char input[6];
3297         int32_t len;
3298         int32_t exp;
3299     }toUnicodeTests[] = {
3300         /*m:n conversion*/
3301         {{0x05, 0x01, 0x02},3,3},
3302         {{0x01, 0x02},2,2},
3303         {{0x07,  0x00, 0x01, 0x02},4,4},
3304     };
3305 
3306     int i;
3307     UConverterToUCallback *oldToUAction= NULL;
3308     UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
3309     if(U_FAILURE(status)){
3310         log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
3311         return;
3312     }
3313     ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
3314     for(i=0; i<UPRV_LENGTHOF(toUnicodeTests); ++i) {
3315         UChar tgt[20];
3316         UChar* target = tgt;
3317         UChar* targetLimit = target + 20;
3318         const char* source = toUnicodeTests[i].input;
3319         const char* sourceLimit = source + toUnicodeTests[i].len;
3320         int32_t len = 0;
3321         ucnv_reset(cnv);
3322         ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3323         len = ucnv_toUCountPending(cnv,&status);
3324         if(U_FAILURE(status)){
3325             log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3326             status = U_ZERO_ERROR;
3327             continue;
3328         }
3329         if(len != toUnicodeTests[i].exp){
3330             log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n");
3331         }
3332     }
3333     status = U_ZERO_ERROR;
3334     ucnv_close(cnv);
3335 
3336     {
3337         /*
3338          * The converter has to read the tail before it knows that
3339          * only head alone matches.
3340          * At the end, the output for head will overflow the target,
3341          * mid will be pending, and tail will not have been consumed.
3342          */
3343         char head[] = { 0x01, 0x02, 0x03, 0x0a , 0x00};
3344         char mid[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 };
3345         char tail[] = {  0x01, 0x02, 0x03, 0x0d, 0x00 };
3346         /*
3347         0x01, 0x02, 0x03, 0x0a  -> x (<U23456>    \x01\x02\x03\x0a |0)
3348         0x01, 0x02, 0x03, 0x0b  -> y (<U000b>     \x01\x02\x03\x0b |0)
3349         0x01, 0x02, 0x03, 0x0d  -> z (<U34567>    \x01\x02\x03\x0d |3)
3350         0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar")
3351         */
3352         UChar tgt[10];
3353         UChar* target = tgt;
3354         UChar* targetLimit = target + 1; /* expect overflow from converting */
3355         const char* source = head;
3356         const char* sourceLimit = source + strlen(head);
3357         int32_t len = 0;
3358         cnv = ucnv_openPackage(loadTestData(&status), "test4", &status);
3359         if(U_FAILURE(status)){
3360             log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
3361             return;
3362         }
3363         ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
3364         ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3365         len = ucnv_toUCountPending(cnv,&status);
3366         if(U_FAILURE(status)){
3367             log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3368         }
3369         if(len != 4){
3370             log_err("Did not get the expected len for head.\n");
3371         }
3372         source=mid;
3373         sourceLimit = source+strlen(mid);
3374         ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3375         len = ucnv_toUCountPending(cnv,&status);
3376         if(U_FAILURE(status)){
3377             log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3378         }
3379         if(len != 8){
3380             log_err("Did not get the expected len for mid.\n");
3381         }
3382 
3383         source=tail;
3384         sourceLimit = source+strlen(tail);
3385         targetLimit = target;
3386         ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3387         if(status != U_BUFFER_OVERFLOW_ERROR){
3388             log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3389         }
3390         status = U_ZERO_ERROR;
3391         len = ucnv_toUCountPending(cnv,&status);
3392         /* mid[4] is pending, tail has not been consumed */
3393         if(U_FAILURE(status)){
3394             log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status));
3395         }
3396         if(len != 4){
3397             log_err("Did not get the expected len for tail.\n");
3398         }
3399         ucnv_close(cnv);
3400     }
3401 #endif
3402 }
3403 
TestOneDefaultNameChange(const char * name,const char * expected)3404 static void TestOneDefaultNameChange(const char *name, const char *expected) {
3405     UErrorCode status = U_ZERO_ERROR;
3406     UConverter *cnv;
3407     ucnv_setDefaultName(name);
3408     if(strcmp(ucnv_getDefaultName(), expected)==0)
3409         log_verbose("setDefaultName of %s works.\n", name);
3410     else
3411         log_err("setDefaultName of %s failed\n", name);
3412     cnv=ucnv_open(NULL, &status);
3413     if (U_FAILURE(status) || cnv == NULL) {
3414         log_err("opening the default converter of %s failed\n", name);
3415         return;
3416     }
3417     if(strcmp(ucnv_getName(cnv, &status), expected)==0)
3418         log_verbose("ucnv_getName of %s works.\n", name);
3419     else
3420         log_err("ucnv_getName of %s failed\n", name);
3421     ucnv_close(cnv);
3422 }
3423 
TestDefaultName(void)3424 static void TestDefaultName(void) {
3425     /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
3426     static char defaultName[UCNV_MAX_CONVERTER_NAME_LENGTH + 1];
3427     strcpy(defaultName, ucnv_getDefaultName());
3428 
3429     log_verbose("getDefaultName returned %s\n", defaultName);
3430 
3431     /*change the default name by setting it */
3432     TestOneDefaultNameChange("UTF-8", "UTF-8");
3433 #if U_CHARSET_IS_UTF8
3434     TestOneDefaultNameChange("ISCII,version=1", "UTF-8");
3435     TestOneDefaultNameChange("ISCII,version=2", "UTF-8");
3436     TestOneDefaultNameChange("ISO-8859-1", "UTF-8");
3437 #else
3438 # if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
3439     TestOneDefaultNameChange("ISCII,version=1", "ISCII,version=1");
3440     TestOneDefaultNameChange("ISCII,version=2", "ISCII,version=2");
3441 # endif
3442     TestOneDefaultNameChange("ISO-8859-1", "ISO-8859-1");
3443 #endif
3444 
3445     /*set the default name back*/
3446     ucnv_setDefaultName(defaultName);
3447 }
3448 
3449 /* Test that ucnv_compareNames() matches names according to spec. ----------- */
3450 
3451 static int
sign(int n)3452 sign(int n) {
3453     if(n==0) {
3454         return 0;
3455     } else if(n<0) {
3456         return -1;
3457     } else /* n>0 */ {
3458         return 1;
3459     }
3460 }
3461 
3462 static void
compareNames(const char ** names)3463 compareNames(const char **names) {
3464     const char *relation, *name1, *name2;
3465     int rel, result;
3466 
3467     relation=*names++;
3468     if(*relation=='=') {
3469         rel = 0;
3470     } else if(*relation=='<') {
3471         rel = -1;
3472     } else {
3473         rel = 1;
3474     }
3475 
3476     name1=*names++;
3477     if(name1==NULL) {
3478         return;
3479     }
3480     while((name2=*names++)!=NULL) {
3481         result=ucnv_compareNames(name1, name2);
3482         if(sign(result)!=rel) {
3483             log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1, name2, result, rel);
3484         }
3485         name1=name2;
3486     }
3487 }
3488 
3489 static void
TestCompareNames()3490 TestCompareNames() {
3491     static const char *equalUTF8[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL };
3492     static const char *equalIBM[]={ "=", "ibm-37", "IBM037", "i-B-m  00037", "ibm-0037", "IBM00037", NULL };
3493     static const char *lessMac[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL };
3494     static const char *lessUTF080[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL };
3495 
3496     compareNames(equalUTF8);
3497     compareNames(equalIBM);
3498     compareNames(lessMac);
3499     compareNames(lessUTF080);
3500 }
3501 
3502 static void
TestSubstString()3503 TestSubstString() {
3504     static const UChar surrogate[1]={ 0xd900 };
3505     char buffer[16];
3506 
3507     static const UChar sub[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3508     static const char subChars[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3509     UConverter *cnv;
3510     UErrorCode errorCode;
3511     int32_t length;
3512     int8_t len8;
3513 
3514     /* UTF-16/32: test that the BOM is output before the sub character */
3515     errorCode=U_ZERO_ERROR;
3516     cnv=ucnv_open("UTF-16", &errorCode);
3517     if(U_FAILURE(errorCode)) {
3518         log_data_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode));
3519         return;
3520     }
3521     length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
3522     ucnv_close(cnv);
3523     if(U_FAILURE(errorCode) ||
3524         length!=4 ||
3525         NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
3526     ) {
3527         log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n");
3528     }
3529 
3530     errorCode=U_ZERO_ERROR;
3531     cnv=ucnv_open("UTF-32", &errorCode);
3532     if(U_FAILURE(errorCode)) {
3533         log_data_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode));
3534         return;
3535     }
3536     length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
3537     ucnv_close(cnv);
3538     if(U_FAILURE(errorCode) ||
3539         length!=8 ||
3540         NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
3541     ) {
3542         log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n");
3543     }
3544 
3545     /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */
3546     errorCode=U_ZERO_ERROR;
3547     cnv=ucnv_open("ISO-8859-1", &errorCode);
3548     if(U_FAILURE(errorCode)) {
3549         log_data_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode));
3550         return;
3551     }
3552     ucnv_setSubstString(cnv, sub, UPRV_LENGTHOF(sub), &errorCode);
3553     if(U_FAILURE(errorCode)) {
3554         log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode));
3555     } else {
3556         len8 = sizeof(buffer);
3557         ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
3558         /* Stateless converter, we expect the string converted to charset bytes. */
3559         if(U_FAILURE(errorCode) || len8!=sizeof(subChars) || 0!=uprv_memcmp(buffer, subChars, len8)) {
3560             log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode));
3561         }
3562     }
3563     ucnv_close(cnv);
3564 
3565 #if !UCONFIG_NO_LEGACY_CONVERSION
3566     errorCode=U_ZERO_ERROR;
3567     cnv=ucnv_open("HZ", &errorCode);
3568     if(U_FAILURE(errorCode)) {
3569         log_data_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode));
3570         return;
3571     }
3572     ucnv_setSubstString(cnv, sub, UPRV_LENGTHOF(sub), &errorCode);
3573     if(U_FAILURE(errorCode)) {
3574         log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode));
3575     } else {
3576         len8 = sizeof(buffer);
3577         ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
3578         /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */
3579         if(U_FAILURE(errorCode) || len8!=0) {
3580             log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode));
3581         }
3582     }
3583     ucnv_close(cnv);
3584 #endif
3585     /*
3586      * Further testing of ucnv_setSubstString() is done via intltest convert.
3587      * We do not test edge cases of illegal arguments and similar because the
3588      * function implementation uses all of its parameters in calls to other
3589      * functions with UErrorCode parameters.
3590      */
3591 }
3592 
3593 static void
InvalidArguments()3594 InvalidArguments() {
3595     UConverter *cnv;
3596     UErrorCode errorCode;
3597     char charBuffer[2] = {1, 1};
3598     char ucharAsCharBuffer[2] = {2, 2};
3599     char *charsPtr = charBuffer;
3600     UChar *ucharsPtr = (UChar *)ucharAsCharBuffer;
3601     UChar *ucharsBadPtr = (UChar *)(ucharAsCharBuffer + 1);
3602 
3603     errorCode=U_ZERO_ERROR;
3604     cnv=ucnv_open("UTF-8", &errorCode);
3605     if(U_FAILURE(errorCode)) {
3606         log_err("ucnv_open() failed - %s\n", u_errorName(errorCode));
3607         return;
3608     }
3609 
3610     errorCode=U_ZERO_ERROR;
3611     /* This one should fail because an incomplete UChar is being passed in */
3612     ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsPtr, ucharsBadPtr, NULL, TRUE, &errorCode);
3613     if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3614         log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode));
3615     }
3616 
3617     errorCode=U_ZERO_ERROR;
3618     /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3619     ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsBadPtr, ucharsPtr, NULL, TRUE, &errorCode);
3620     if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3621         log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode));
3622     }
3623 
3624     errorCode=U_ZERO_ERROR;
3625     /* This one should fail because an incomplete UChar is being passed in */
3626     ucnv_toUnicode(cnv, &ucharsPtr, ucharsBadPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode);
3627     if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3628         log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode));
3629     }
3630 
3631     errorCode=U_ZERO_ERROR;
3632     /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3633     ucnv_toUnicode(cnv, &ucharsBadPtr, ucharsPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode);
3634     if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3635         log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode));
3636     }
3637 
3638     if (charBuffer[0] != 1 || charBuffer[1] != 1
3639         || ucharAsCharBuffer[0] != 2 || ucharAsCharBuffer[1] != 2)
3640     {
3641         log_err("Data was incorrectly written to buffers\n");
3642     }
3643 
3644     ucnv_close(cnv);
3645 }
3646 
TestGetName()3647 static void TestGetName() {
3648     static const char *const names[] = {
3649         "Unicode",                  "UTF-16",
3650         "UnicodeBigUnmarked",       "UTF-16BE",
3651         "UnicodeBig",               "UTF-16BE,version=1",
3652         "UnicodeLittleUnmarked",    "UTF-16LE",
3653         "UnicodeLittle",            "UTF-16LE,version=1",
3654         "x-UTF-16LE-BOM",           "UTF-16LE,version=1"
3655     };
3656     int32_t i;
3657     for(i = 0; i < UPRV_LENGTHOF(names); i += 2) {
3658         UErrorCode errorCode = U_ZERO_ERROR;
3659         UConverter *cnv = ucnv_open(names[i], &errorCode);
3660         if(U_SUCCESS(errorCode)) {
3661             const char *name = ucnv_getName(cnv, &errorCode);
3662             if(U_FAILURE(errorCode) || 0 != strcmp(name, names[i+1])) {
3663                 log_err("ucnv_getName(%s) = %s != %s -- %s\n",
3664                         names[i], name, names[i+1], u_errorName(errorCode));
3665             }
3666             ucnv_close(cnv);
3667         }
3668     }
3669 }
3670 
TestUTFBOM()3671 static void TestUTFBOM() {
3672     static const UChar a16[] = { 0x61 };
3673     static const char *const names[] = {
3674         "UTF-16",
3675         "UTF-16,version=1",
3676         "UTF-16BE",
3677         "UnicodeBig",
3678         "UTF-16LE",
3679         "UnicodeLittle"
3680     };
3681     static const uint8_t expected[][5] = {
3682 #if U_IS_BIG_ENDIAN
3683         { 4, 0xfe, 0xff, 0, 0x61 },
3684         { 4, 0xfe, 0xff, 0, 0x61 },
3685 #else
3686         { 4, 0xff, 0xfe, 0x61, 0 },
3687         { 4, 0xff, 0xfe, 0x61, 0 },
3688 #endif
3689 
3690         { 2, 0, 0x61 },
3691         { 4, 0xfe, 0xff, 0, 0x61 },
3692 
3693         { 2, 0x61, 0 },
3694         { 4, 0xff, 0xfe, 0x61, 0 }
3695     };
3696 
3697     char bytes[10];
3698     int32_t i;
3699 
3700     for(i = 0; i < UPRV_LENGTHOF(names); ++i) {
3701         UErrorCode errorCode = U_ZERO_ERROR;
3702         UConverter *cnv = ucnv_open(names[i], &errorCode);
3703         int32_t length = 0;
3704         const uint8_t *exp = expected[i];
3705         if (U_FAILURE(errorCode)) {
3706            log_err_status(errorCode, "Unable to open converter: %s got error code: %s\n", names[i], u_errorName(errorCode));
3707            continue;
3708         }
3709         length = ucnv_fromUChars(cnv, bytes, (int32_t)sizeof(bytes), a16, 1, &errorCode);
3710 
3711         if(U_FAILURE(errorCode) || length != exp[0] || 0 != memcmp(bytes, exp+1, length)) {
3712             log_err("unexpected %s BOM writing behavior -- %s\n",
3713                     names[i], u_errorName(errorCode));
3714         }
3715         ucnv_close(cnv);
3716     }
3717 }
3718