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