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