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