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