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