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