1 /********************************************************************
3 * Copyright (c) 1997-2004, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /********************************************************************************
10 * Modification History:
12 * Madhu Katragadda Ported for C API
13 *********************************************************************************
19 #include "unicode/uloc.h"
20 #include "unicode/ucnv.h"
21 #include "unicode/ucnv_err.h"
22 #include "unicode/putil.h"
23 #include "unicode/ustring.h"
24 #include "ucnv_bld.h" /* for sizeof(UConverter) */
28 /* for not including "cstring.h" -begin*/
30 # define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE _stricmp(str1, str2)
32 # define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE strcasecmp(str1, str2)
34 # define ctest_stricmp(str1, str2) T_CString_stricmp(str1, str2)
38 T_CString_stricmp(const char *str1
, const char *str2
) {
45 } else if(str2
==NULL
) {
48 /* compare non-NULL strings lexically with lowercase */
52 c1
=(unsigned char)*str1
;
53 c2
=(unsigned char)*str2
;
63 /* compare non-zero characters with lowercase */
64 rc
=(int)(unsigned char)tolower(c1
)-(int)(unsigned char)tolower(c2
);
74 /* for not including "cstring.h" -end*/
76 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
78 #define NUM_CODEPAGE 1
79 #define MAX_FILE_LEN 1024*20
80 #define UCS_FILE_NAME_SIZE 512
82 /*returns an action other than the one provided*/
83 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
);
84 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
);
87 cnv_open(const char *name
, UErrorCode
*pErrorCode
) {
88 if(name
!=NULL
&& name
[0]=='*') {
89 return ucnv_openPackage(loadTestData(pErrorCode
), name
+1, pErrorCode
);
91 return ucnv_open(name
, pErrorCode
);
96 static void ListNames(void);
97 static void TestFlushCache(void);
98 static void TestDuplicateAlias(void);
99 static void TestCCSID(void);
100 static void TestJ932(void);
101 static void TestJ1968(void);
102 static void TestLMBCSMaxChar(void);
103 static void TestConvertSafeCloneCallback(void);
104 static void TestEBCDICSwapLFNL(void);
105 static void TestConvertEx(void);
106 static void TestConvertAlgorithmic(void);
107 void TestDefaultConverterError(void); /* defined in cctest.c */
109 void addTestConvert(TestNode
** root
);
111 void addTestConvert(TestNode
** root
)
113 addTest(root
, &ListNames
, "tsconv/ccapitst/ListNames");
114 addTest(root
, &TestConvert
, "tsconv/ccapitst/TestConvert");
115 addTest(root
, &TestFlushCache
, "tsconv/ccapitst/TestFlushCache");
116 addTest(root
, &TestAlias
, "tsconv/ccapitst/TestAlias");
117 addTest(root
, &TestDuplicateAlias
, "tsconv/ccapitst/TestDuplicateAlias");
118 addTest(root
, &TestConvertSafeClone
, "tsconv/ccapitst/TestConvertSafeClone");
119 addTest(root
, &TestConvertSafeCloneCallback
,"tsconv/ccapitst/TestConvertSafeCloneCallback");
120 addTest(root
, &TestCCSID
, "tsconv/ccapitst/TestCCSID");
121 addTest(root
, &TestJ932
, "tsconv/ccapitst/TestJ932");
122 addTest(root
, &TestJ1968
, "tsconv/ccapitst/TestJ1968");
123 addTest(root
, &TestLMBCSMaxChar
, "tsconv/ccapitst/TestLMBCSMaxChar");
124 addTest(root
, &TestEBCDICSwapLFNL
, "tsconv/ccapitst/TestEBCDICSwapLFNL");
125 addTest(root
, &TestConvertEx
, "tsconv/ccapitst/TestConvertEx");
126 addTest(root
, &TestConvertAlgorithmic
, "tsconv/ccapitst/TestConvertAlgorithmic");
127 addTest(root
, &TestDefaultConverterError
, "tsconv/ccapitst/TestDefaultConverterError");
130 static void ListNames(void) {
131 UErrorCode err
= U_ZERO_ERROR
;
132 int32_t testLong1
= 0;
133 const char* available_conv
;
134 UEnumeration
*allNamesEnum
= NULL
;
135 int32_t allNamesCount
= 0;
138 log_verbose("Testing ucnv_openAllNames()...");
139 allNamesEnum
= ucnv_openAllNames(&err
);
141 log_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err
));
144 const char *string
= NULL
;
148 allNamesCount
= uenum_count(allNamesEnum
, &err
);
149 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
151 log_verbose("read \"%s\", length %i\n", string
, len
);
154 uenum_reset(allNamesEnum
, &err
);
155 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
157 ucnv_close(ucnv_open(string
, &err
));
158 log_verbose("read \"%s\", length %i (%s)\n", string
, len
, U_SUCCESS(err
) ? "available" : "unavailable");
161 if (count1
!= count2
) {
162 log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
165 uenum_close(allNamesEnum
);
168 /*Tests ucnv_getAvailableName(), getAvialableCount()*/
170 log_verbose("Testing ucnv_countAvailable()...");
172 testLong1
=ucnv_countAvailable();
173 log_info("Number of available codepages: %d/%d\n", testLong1
, allNamesCount
);
175 log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */
177 available_conv
= ucnv_getAvailableName(testLong1
);
178 /*test ucnv_getAvailableName with err condition*/
179 log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
180 available_conv
= ucnv_getAvailableName(-1);
181 if(available_conv
!= NULL
){
182 log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
185 /* Test ucnv_countAliases() etc. */
186 count
= ucnv_countAliases("utf-8", &err
);
188 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err
));
189 } else if(count
<= 0) {
190 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count
);
192 /* try to get the aliases individually */
194 alias
= ucnv_getAlias("utf-8", 0, &err
);
196 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err
));
197 } else if(strcmp("UTF-8", alias
) != 0) {
198 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias
);
201 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
202 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
204 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
205 } else if(strlen(alias
) > 20) {
207 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum
, alias
);
209 log_verbose("alias %d for utf-8: %s\n", aliasNum
, alias
);
213 /* try to fill an array with all aliases */
214 const char **aliases
;
215 aliases
=(const char **)malloc(count
* sizeof(const char *));
217 ucnv_getAliases("utf-8", aliases
, &err
);
219 log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err
));
221 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
222 /* compare the pointers with the ones returned individually */
223 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
225 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
226 } else if(aliases
[aliasNum
] != alias
) {
227 log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum
, aliasNum
);
231 free((char **)aliases
);
239 static void TestConvert()
243 int32_t testLong1
= 0;
247 FILE* ucs_file_in
= NULL
;
249 UChar myUChar
= 0x0000;
250 char* mytarget
; /* [MAX_FILE_LEN] */
253 UChar
* consumedUni
= NULL
;
254 char* consumed
= NULL
;
255 char* output_cp_buffer
; /* [MAX_FILE_LEN] */
256 UChar
* ucs_file_buffer
; /* [MAX_FILE_LEN] */
257 UChar
* ucs_file_buffer_use
;
258 UChar
* my_ucs_file_buffer
; /* [MAX_FILE_LEN] */
259 UChar
* my_ucs_file_buffer_1
;
262 uint16_t codepage_index
= 0;
264 UErrorCode err
= U_ZERO_ERROR
;
265 char ucs_file_name
[UCS_FILE_NAME_SIZE
];
266 UConverterFromUCallback MIA1
, MIA1_2
;
267 UConverterToUCallback MIA2
, MIA2_2
;
268 const void *MIA1Context
, *MIA1Context2
, *MIA2Context
, *MIA2Context2
;
269 UConverter
* someConverters
[5];
270 UConverter
* myConverter
= 0;
271 UChar
* displayname
= 0;
278 int32_t targetcapacity2
;
279 int32_t targetcapacity
;
283 const UChar
* tmp_ucs_buf
;
284 const UChar
* tmp_consumedUni
=NULL
;
285 const char* tmp_mytarget_use
;
286 const char* tmp_consumed
;
288 /******************************************************************
289 Checking Unicode -> ksc
290 ******************************************************************/
292 const char* CodePagesToTest
[NUM_CODEPAGE
] =
298 const uint16_t CodePageNumberToTest
[NUM_CODEPAGE
] =
304 const int8_t CodePagesMinChars
[NUM_CODEPAGE
] =
310 const int8_t CodePagesMaxChars
[NUM_CODEPAGE
] =
316 const uint16_t CodePagesSubstitutionChars
[NUM_CODEPAGE
] =
321 const char* CodePagesTestFiles
[NUM_CODEPAGE
] =
327 const UConverterPlatform CodePagesPlatform
[NUM_CODEPAGE
] =
333 const char* CodePagesLocale
[NUM_CODEPAGE
] =
338 UConverterFromUCallback oldFromUAction
= NULL
;
339 UConverterToUCallback oldToUAction
= NULL
;
340 const void* oldFromUContext
= NULL
;
341 const void* oldToUContext
= NULL
;
343 /* Allocate memory */
344 mytarget
= (char*) malloc(MAX_FILE_LEN
* sizeof(mytarget
[0]));
345 output_cp_buffer
= (char*) malloc(MAX_FILE_LEN
* sizeof(output_cp_buffer
[0]));
346 ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(ucs_file_buffer
[0]));
347 my_ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(my_ucs_file_buffer
[0]));
349 ucs_file_buffer_use
= ucs_file_buffer
;
351 mytarget_use
= mytarget
;
352 my_ucs_file_buffer_1
=my_ucs_file_buffer
;
354 /* flush the converter cache to get a consistent state before the flushing is tested */
357 /*Testing ucnv_openU()*/
359 UChar converterName
[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
360 UChar firstSortedName
[]={ 0x0021, 0x0000}; /* ! */
361 UChar lastSortedName
[]={ 0x007E, 0x0000}; /* ~ */
362 const char *illegalNameChars
={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
363 UChar illegalName
[100];
364 UConverter
*converter
=NULL
;
366 converter
=ucnv_openU(converterName
, &err
);
368 log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err
));
370 ucnv_close(converter
);
372 converter
=ucnv_openU(NULL
, &err
);
374 log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err
));
376 ucnv_close(converter
);
377 /*testing with error value*/
378 err
=U_ILLEGAL_ARGUMENT_ERROR
;
379 converter
=ucnv_openU(converterName
, &err
);
380 if(!(converter
== NULL
)){
381 log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
383 ucnv_close(converter
);
385 u_uastrcpy(illegalName
, "");
386 u_uastrcpy(illegalName
, illegalNameChars
);
387 ucnv_openU(illegalName
, &err
);
388 if(!(err
==U_ILLEGAL_ARGUMENT_ERROR
)){
389 log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
393 ucnv_openU(firstSortedName
, &err
);
394 if(err
!=U_FILE_ACCESS_ERROR
){
395 log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
399 ucnv_openU(lastSortedName
, &err
);
400 if(err
!=U_FILE_ACCESS_ERROR
){
401 log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
406 log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
408 UConverter
*cnv
=NULL
;
410 cnv
=ucnv_open("ibm-949,Madhu", &err
);
412 log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err
));
417 /*Testing ucnv_convert()*/
419 int32_t targetLimit
=0, sourceLimit
=0, i
=0, targetCapacity
=0;
420 const uint8_t source
[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
421 const uint8_t expectedTarget
[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
423 sourceLimit
=sizeof(source
)/sizeof(source
[0]);
427 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", NULL
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
428 if(err
== U_BUFFER_OVERFLOW_ERROR
){
430 targetLimit
=targetCapacity
+1;
431 target
=(char*)malloc(sizeof(char) * targetLimit
);
432 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
435 log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err
));
438 for(i
=0; i
<targetCapacity
; i
++){
439 if(target
[i
] != expectedTarget
[i
]){
440 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
]);
444 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
+1, -1, &err
);
445 if(U_FAILURE(err
) || i
!=7){
446 log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
447 u_errorName(err
), i
);
450 /*Test error conditions*/
452 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, 0, &err
);
454 log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
457 err
=U_ILLEGAL_ARGUMENT_ERROR
;
458 sourceLimit
=sizeof(source
)/sizeof(source
[0]);
459 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
461 log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
465 sourceLimit
=sizeof(source
)/sizeof(source
[0]);
467 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
468 if(!(U_FAILURE(err
) && err
==U_BUFFER_OVERFLOW_ERROR
)){
469 log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
476 /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
477 log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
478 err
=U_ILLEGAL_ARGUMENT_ERROR
;
479 if(ucnv_open(NULL
, &err
) != NULL
){
480 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
482 if(ucnv_openCCSID(1051, UCNV_IBM
, &err
) != NULL
){
483 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
487 /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
488 log_verbose("\n---Testing ucnv_open default...\n");
489 someConverters
[0] = ucnv_open(NULL
,&err
);
490 someConverters
[1] = ucnv_open(NULL
,&err
);
491 someConverters
[2] = ucnv_open("utf8", &err
);
492 someConverters
[3] = ucnv_openCCSID(949,UCNV_IBM
,&err
);
493 ucnv_close(ucnv_openCCSID(1051, UCNV_IBM
, &err
)); /* test for j350; ucnv_close(NULL) is safe */
494 if (U_FAILURE(err
)){ log_data_err("FAILURE! %s\n", myErrorName(err
));}
496 /* Testing ucnv_getName()*/
497 /*default code page */
498 ucnv_getName(someConverters
[0], &err
);
500 log_data_err("getName[0] failed\n");
502 log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters
[0], &err
));
504 ucnv_getName(someConverters
[1], &err
);
506 log_data_err("getName[1] failed\n");
508 log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters
[1], &err
));
511 /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
513 static char defaultName
[UCNV_MAX_CONVERTER_NAME_LENGTH
+ 1];
514 strcpy(defaultName
, ucnv_getDefaultName());
516 log_verbose("getDefaultName returned %s\n", defaultName
);
518 /*change the default name by setting it */
519 ucnv_setDefaultName("changed");
520 if(strcmp(ucnv_getDefaultName(), "changed")==0)
521 log_verbose("setDefaultName o.k");
523 log_err("setDefaultName failed");
524 /*set the default name back*/
525 ucnv_setDefaultName(defaultName
);
528 ucnv_close(someConverters
[0]);
529 ucnv_close(someConverters
[1]);
530 ucnv_close(someConverters
[2]);
531 ucnv_close(someConverters
[3]);
534 for (codepage_index
=0; codepage_index
< NUM_CODEPAGE
; ++codepage_index
)
540 strcpy(ucs_file_name
, U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
);
542 strcpy(ucs_file_name
, loadTestData(&err
));
545 log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err
));
550 char* index
= strrchr(ucs_file_name
,(char)U_FILE_SEP_CHAR
);
552 if((unsigned int)(index
-ucs_file_name
) != (strlen(ucs_file_name
)-1)){
557 strcat(ucs_file_name
,".."U_FILE_SEP_STRING
);
559 strcat(ucs_file_name
, CodePagesTestFiles
[codepage_index
]);
561 ucs_file_in
= fopen(ucs_file_name
,"rb");
564 log_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name
);
568 /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
570 /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
571 /* ucnv_flushCache(); */
572 myConverter
=ucnv_open( "ibm-949", &err
);
573 if (!myConverter
|| U_FAILURE(err
))
575 log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err
));
580 /*testing for ucnv_getName() */
581 log_verbose("Testing ucnv_getName()...\n");
582 ucnv_getName(myConverter
, &err
);
584 log_err("Error in getName\n");
587 log_verbose("getName o.k. %s\n", ucnv_getName(myConverter
, &err
));
589 if (ctest_stricmp(ucnv_getName(myConverter
, &err
), CodePagesToTest
[codepage_index
]))
590 log_err("getName failed\n");
592 log_verbose("getName ok\n");
593 /*Test getName with error condition*/
596 err
=U_ILLEGAL_ARGUMENT_ERROR
;
597 log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
598 name
=ucnv_getName(myConverter
, &err
);
600 log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
606 /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
608 log_verbose("Testing ucnv_getMaxCharSize()...\n");
609 if (ucnv_getMaxCharSize(myConverter
)==CodePagesMaxChars
[codepage_index
])
610 log_verbose("Max byte per character OK\n");
612 log_err("Max byte per character failed\n");
614 log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
615 if (ucnv_getMinCharSize(myConverter
)==CodePagesMinChars
[codepage_index
])
616 log_verbose("Min byte per character OK\n");
618 log_err("Min byte per character failed\n");
621 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
622 log_verbose("\n---Testing ucnv_getSubstChars...\n");
624 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
626 log_err("ucnv_getSubstChars returned a negative number %d\n", ii
);
630 rest
= (uint16_t)(((unsigned char)rest
<< 8) + (unsigned char)myptr
[x
]);
631 if (rest
==CodePagesSubstitutionChars
[codepage_index
])
632 log_verbose("Substitution character ok\n");
634 log_err("Substitution character failed.\n");
636 log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
637 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
640 log_err("FAILURE! %s\n", myErrorName(err
));
642 ucnv_getSubstChars(myConverter
,save
, &ii
, &err
);
645 log_err("FAILURE! %s\n", myErrorName(err
));
648 if (strncmp(save
, myptr
, ii
))
649 log_err("Saved substitution character failed\n");
651 log_verbose("Saved substitution character ok\n");
653 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
654 log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
656 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
657 if(err
!= U_INDEX_OUTOFBOUNDS_ERROR
){
658 log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err
));
662 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
663 log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
664 ucnv_setSubstChars(myConverter
, myptr
, 0, &err
);
665 if(err
!= U_ILLEGAL_ARGUMENT_ERROR
){
666 log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err
));
668 log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
669 strcpy(myptr
, "abc");
670 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
672 ucnv_getSubstChars(myConverter
, save
, &ii
, &err
);
673 if(strncmp(save
, myptr
, ii
) == 0){
674 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
676 log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
678 strcpy(myptr
, "abc");
679 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
680 err
=U_ILLEGAL_ARGUMENT_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 fill the SubstChars in the buffer, it just returns\n");
688 #ifdef U_ENABLE_GENERIC_ISO_2022
689 /*resetState ucnv_reset()*/
690 log_verbose("\n---Testing ucnv_reset()..\n");
691 ucnv_reset(myConverter
);
694 const uint8_t in
[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
695 const char *source
=(const char *)in
, *limit
=(const char *)in
+sizeof(in
);
696 UConverter
*cnv
=ucnv_open("ISO_2022", &err
);
698 log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err
));
700 c
=ucnv_getNextUChar(cnv
, &source
, limit
, &err
);
701 if((U_FAILURE(err
) || c
!= (UChar32
)0x0031)) {
702 log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err
));
711 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
712 locale
=CodePagesLocale
[codepage_index
];
713 displayname
=(UChar
*)malloc(1 * sizeof(UChar
));
715 disnamelen
= ucnv_getDisplayName(myConverter
,locale
,displayname
, len
, &err
);
716 if(err
==U_BUFFER_OVERFLOW_ERROR
)
719 displayname
=(UChar
*)realloc(displayname
, (disnamelen
+1) * sizeof(UChar
));
720 ucnv_getDisplayName(myConverter
,locale
,displayname
,disnamelen
+1, &err
);
723 log_err("getDisplayName failed the error is %s\n", myErrorName(err
));
726 log_verbose(" getDisplayName o.k.\n");
728 /*test ucnv_getDiaplayName with error condition*/
729 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
730 err
= U_ILLEGAL_ARGUMENT_ERROR
;
731 len
=ucnv_getDisplayName(myConverter
,locale
,displayname
,disnamelen
+1, &err
);
733 log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
737 /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
738 ucnv_getFromUCallBack(myConverter
, &MIA1
, &MIA1Context
);
740 log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
741 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
742 if (U_FAILURE(err
) || oldFromUAction
!= MIA1
|| oldFromUContext
!= MIA1Context
)
744 log_err("FAILURE! %s\n", myErrorName(err
));
747 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
748 if (MIA1_2
!= otherUnicodeAction(MIA1
) || MIA1Context2
!= &BOM
)
749 log_err("get From UCallBack failed\n");
751 log_verbose("get From UCallBack ok\n");
753 log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
754 ucnv_setFromUCallBack(myConverter
,MIA1
, MIA1Context
, &oldFromUAction
, &oldFromUContext
, &err
);
755 if (U_FAILURE(err
) || oldFromUAction
!= otherUnicodeAction(MIA1
) || oldFromUContext
!= &BOM
)
757 log_err("FAILURE! %s\n", myErrorName(err
));
760 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
761 if (MIA1_2
!= MIA1
|| MIA1Context2
!= MIA1Context
)
762 log_err("get From UCallBack action failed\n");
764 log_verbose("get From UCallBack action ok\n");
766 /*testing ucnv_setToUCallBack with error conditions*/
767 err
=U_ILLEGAL_ARGUMENT_ERROR
;
768 log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
769 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
770 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
771 if(MIA1_2
== otherUnicodeAction(MIA1
) || MIA1Context2
== &BOM
){
772 log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
777 /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
778 ucnv_getToUCallBack(myConverter
, &MIA2
, &MIA2Context
);
780 log_verbose("\n---Testing setTo UCallBack...\n");
781 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), &BOM
, &oldToUAction
, &oldToUContext
, &err
);
782 if (U_FAILURE(err
) || oldToUAction
!= MIA2
|| oldToUContext
!= MIA2Context
)
784 log_err("FAILURE! %s\n", myErrorName(err
));
787 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
788 if (MIA2_2
!= otherCharAction(MIA2
) || MIA2Context2
!= &BOM
)
789 log_err("To UCallBack failed\n");
791 log_verbose("To UCallBack ok\n");
793 log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
794 ucnv_setToUCallBack(myConverter
,MIA2
, MIA2Context
, &oldToUAction
, &oldToUContext
, &err
);
795 if (U_FAILURE(err
) || oldToUAction
!= otherCharAction(MIA2
) || oldToUContext
!= &BOM
)
796 { log_err("FAILURE! %s\n", myErrorName(err
)); }
798 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
799 if (MIA2_2
!= MIA2
|| MIA2Context2
!= MIA2Context
)
800 log_err("To UCallBack failed\n");
802 log_verbose("To UCallBack ok\n");
804 /*testing ucnv_setToUCallBack with error conditions*/
805 err
=U_ILLEGAL_ARGUMENT_ERROR
;
806 log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
807 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), NULL
, &oldToUAction
, &oldToUContext
, &err
);
808 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
809 if (MIA2_2
== otherCharAction(MIA2
) || MIA2Context2
== &BOM
){
810 log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
815 /*getcodepageid testing ucnv_getCCSID() */
816 log_verbose("\n----Testing getCCSID....\n");
817 cp
= ucnv_getCCSID(myConverter
,&err
);
820 log_err("FAILURE!..... %s\n", myErrorName(err
));
822 if (cp
!= CodePageNumberToTest
[codepage_index
])
823 log_err("Codepage number test failed\n");
825 log_verbose("Codepage number test OK\n");
827 /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
828 err
=U_ILLEGAL_ARGUMENT_ERROR
;
829 if( ucnv_getCCSID(myConverter
,&err
) != -1){
830 log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
834 /*getCodepagePlatform testing ucnv_getPlatform()*/
835 log_verbose("\n---Testing getCodepagePlatform ..\n");
836 if (CodePagesPlatform
[codepage_index
]!=ucnv_getPlatform(myConverter
, &err
))
837 log_err("Platform codepage test failed\n");
839 log_verbose("Platform codepage test ok\n");
843 log_err("FAILURE! %s\n", myErrorName(err
));
845 /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
846 err
= U_ILLEGAL_ARGUMENT_ERROR
;
847 if(ucnv_getPlatform(myConverter
, &err
) != UCNV_UNKNOWN
){
848 log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
854 fread(&BOM
, sizeof(UChar
), 1, ucs_file_in
);
855 if (BOM
!=0xFEFF && BOM
!=0xFFFE)
857 log_err("File Missing BOM...Bailing!\n");
862 /*Reads in the file*/
863 while(!feof(ucs_file_in
)&&(i
+=fread(ucs_file_buffer
+i
, sizeof(UChar
), 1, ucs_file_in
)))
865 myUChar
= ucs_file_buffer
[i
-1];
867 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN*/
870 myUChar
= ucs_file_buffer
[i
-1];
871 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN Corner Case*/
874 /*testing ucnv_fromUChars() and ucnv_toUChars() */
875 /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
877 uchar1
=(UChar
*)malloc(sizeof(UChar
) * (i
+1));
878 u_uastrcpy(uchar1
,"");
879 u_strncpy(uchar1
,ucs_file_buffer
,i
);
882 uchar3
=(UChar
*)malloc(sizeof(UChar
)*(i
+1));
883 u_uastrcpy(uchar3
,"");
884 u_strncpy(uchar3
,ucs_file_buffer
,i
);
887 /*Calls the Conversion Routine */
888 testLong1
= MAX_FILE_LEN
;
889 log_verbose("\n---Testing ucnv_fromUChars()\n");
890 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
893 log_err("\nFAILURE...%s\n", myErrorName(err
));
896 log_verbose(" ucnv_fromUChars() o.k.\n");
898 /*test the conversion routine */
899 log_verbose("\n---Testing ucnv_toUChars()\n");
900 /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
902 targetsize
= ucnv_toUChars(myConverter
,
906 strlen(output_cp_buffer
),
908 /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
910 if(err
==U_BUFFER_OVERFLOW_ERROR
)
913 uchar2
=(UChar
*)malloc((targetsize
+1) * sizeof(UChar
));
914 targetsize
= ucnv_toUChars(myConverter
,
918 strlen(output_cp_buffer
),
922 log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err
));
924 log_verbose(" ucnv_toUChars() o.k.\n");
926 if(u_strcmp(uchar1
,uchar2
)!=0)
927 log_err("equality test failed with conversion routine\n");
931 log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
933 /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
934 err
=U_ILLEGAL_ARGUMENT_ERROR
;
935 log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
936 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
937 if (targetcapacity
!=0) {
938 log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
941 log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
942 targetcapacity
= ucnv_fromUChars(NULL
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
943 if (targetcapacity
!=0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
944 log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
947 log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
948 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, 0, &err
);
949 if (targetcapacity
!=0) {
950 log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
952 log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
953 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, 0, uchar1
, -1, &err
);
954 if (err
!= U_BUFFER_OVERFLOW_ERROR
) {
955 log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
957 /*toUChars with error conditions*/
958 targetsize
= ucnv_toUChars(myConverter
, uchar2
, targetsize
, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
960 log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
963 targetsize
= ucnv_toUChars(myConverter
, uchar2
, -1, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
964 if(targetsize
!= 0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
){
965 log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
968 targetsize
= ucnv_toUChars(myConverter
, uchar2
, 0, output_cp_buffer
, 0, &err
);
969 if (targetsize
!=0) {
970 log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
973 targetsize
= ucnv_toUChars(myConverter
, NULL
, targetcapacity2
, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
974 if (err
!= U_STRING_NOT_TERMINATED_WARNING
) {
975 log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
982 /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
983 /*Clean up re-usable vars*/
985 log_verbose("Testing ucnv_fromUnicode().....\n");
986 tmp_ucs_buf
=ucs_file_buffer_use
;
987 ucnv_fromUnicode(myConverter
, &mytarget_1
,
988 mytarget
+ MAX_FILE_LEN
,
990 ucs_file_buffer_use
+i
,
994 consumedUni
= (UChar
*)tmp_consumedUni
;
998 log_err("FAILURE! %s\n", myErrorName(err
));
1001 log_verbose("ucnv_fromUnicode() o.k.\n");
1003 /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
1004 log_verbose("Testing ucnv_toUnicode().....\n");
1005 tmp_mytarget_use
=mytarget_use
;
1006 tmp_consumed
= consumed
;
1007 ucnv_toUnicode(myConverter
, &my_ucs_file_buffer_1
,
1008 my_ucs_file_buffer
+ MAX_FILE_LEN
,
1010 mytarget_use
+ (mytarget_1
- mytarget
),
1014 consumed
= (char*)tmp_consumed
;
1017 log_err("FAILURE! %s\n", myErrorName(err
));
1020 log_verbose("ucnv_toUnicode() o.k.\n");
1023 log_verbose("\n---Testing RoundTrip ...\n");
1026 u_strncpy(uchar3
, my_ucs_file_buffer
,i
);
1029 if(u_strcmp(uchar1
,uchar3
)==0)
1030 log_verbose("Equality test o.k.\n");
1032 log_err("Equality test failed\n");
1037 log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__
);
1041 if(u_strcmp(uchar2
, uchar3
)==0)
1042 log_verbose("Equality test o.k.\n");
1044 log_err("Equality test failed\n");
1047 fclose(ucs_file_in
);
1048 ucnv_close(myConverter
);
1050 if (uchar1
!= 0) free(uchar1
);
1051 if (uchar2
!= 0) free(uchar2
);
1052 if (uchar3
!= 0) free(uchar3
);
1055 free((void*)mytarget
);
1056 free((void*)output_cp_buffer
);
1057 free((void*)ucs_file_buffer
);
1058 free((void*)my_ucs_file_buffer
);
1061 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
)
1063 return (MIA
==(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
)?(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_SUBSTITUTE
:(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
;
1067 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
)
1069 return (MIA
==(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
)?(UConverterToUCallback
)UCNV_TO_U_CALLBACK_SUBSTITUTE
:(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
;
1072 static void TestFlushCache(void) {
1073 UErrorCode err
= U_ZERO_ERROR
;
1074 UConverter
* someConverters
[5];
1077 /* flush the converter cache to get a consistent state before the flushing is tested */
1080 /*Testing ucnv_open()*/
1081 /* Note: These converters have been chosen because they do NOT
1082 encode the Latin characters (U+0041, ...), and therefore are
1083 highly unlikely to be chosen as system default codepages */
1085 someConverters
[0] = ucnv_open("ibm-1047", &err
);
1086 if (U_FAILURE(err
)) {
1087 log_data_err("FAILURE! %s\n", myErrorName(err
));
1090 someConverters
[1] = ucnv_open("ibm-1047", &err
);
1091 if (U_FAILURE(err
)) {
1092 log_data_err("FAILURE! %s\n", myErrorName(err
));
1095 someConverters
[2] = ucnv_open("ibm-1047", &err
);
1096 if (U_FAILURE(err
)) {
1097 log_data_err("FAILURE! %s\n", myErrorName(err
));
1100 someConverters
[3] = ucnv_open("gb18030", &err
);
1101 if (U_FAILURE(err
)) {
1102 log_data_err("FAILURE! %s\n", myErrorName(err
));
1105 someConverters
[4] = ucnv_open("ibm-954", &err
);
1106 if (U_FAILURE(err
)) {
1107 log_data_err("FAILURE! %s\n", myErrorName(err
));
1111 /* Testing ucnv_flushCache() */
1112 log_verbose("\n---Testing ucnv_flushCache...\n");
1113 if ((flushCount
=ucnv_flushCache())==0)
1114 log_verbose("Flush cache ok\n");
1116 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1118 /*testing ucnv_close() and ucnv_flushCache() */
1119 ucnv_close(someConverters
[0]);
1120 ucnv_close(someConverters
[1]);
1122 if ((flushCount
=ucnv_flushCache())==0)
1123 log_verbose("Flush cache ok\n");
1125 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1127 ucnv_close(someConverters
[2]);
1128 ucnv_close(someConverters
[3]);
1130 if ((flushCount
=ucnv_flushCache())==2)
1131 log_verbose("Flush cache ok\n"); /*because first, second and third are same */
1133 log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n",
1137 ucnv_close(someConverters
[4]);
1138 if ( (flushCount
=ucnv_flushCache())==1)
1139 log_verbose("Flush cache ok\n");
1141 log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__
, flushCount
);
1146 * Test the converter alias API, specifically the fuzzy matching of
1147 * alias names and the alias table integrity. Make sure each
1148 * converter has at least one alias (itself), and that its listed
1149 * aliases map back to itself. Check some hard-coded UTF-8 and
1150 * ISO_2022 aliases to make sure they work.
1152 static void TestAlias() {
1154 UErrorCode status
= U_ZERO_ERROR
;
1156 /* Predetermined aliases that we expect to map back to ISO_2022
1157 * and UTF-8. UPDATE THIS DATA AS NECESSARY. */
1158 const char* ISO_2022_NAMES
[] =
1159 {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
1160 "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
1161 int32_t ISO_2022_NAMES_LENGTH
=
1162 sizeof(ISO_2022_NAMES
) / sizeof(ISO_2022_NAMES
[0]);
1163 const char *UTF8_NAMES
[] =
1164 { "UTF-8", "utf-8", "utf8", "ibm-1208",
1165 "utf_8", "ibm1208", "cp1208" };
1166 int32_t UTF8_NAMES_LENGTH
=
1167 sizeof(UTF8_NAMES
) / sizeof(UTF8_NAMES
[0]);
1172 } CONVERTERS_NAMES
[] = {
1173 { "UTF-32BE", "UTF32_BigEndian" },
1174 { "UTF-32LE", "UTF32_LittleEndian" },
1175 { "UTF-32", "ISO-10646-UCS-4" },
1176 { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
1177 { "UTF-32", "ucs-4" }
1179 int32_t CONVERTERS_NAMES_LENGTH
= sizeof(CONVERTERS_NAMES
) / sizeof(*CONVERTERS_NAMES
);
1181 /* When there are bugs in gencnval or in ucnv_io, converters can
1182 appear to have no aliases. */
1183 ncnv
= ucnv_countAvailable();
1184 log_verbose("%d converters\n", ncnv
);
1185 for (i
=0; i
<ncnv
; ++i
) {
1186 const char *name
= ucnv_getAvailableName(i
);
1188 uint16_t na
= ucnv_countAliases(name
, &status
);
1193 log_err("FAIL: Converter \"%s\" (i=%d)"
1194 " has no aliases; expect at least one\n",
1198 cnv
= ucnv_open(name
, &status
);
1199 if (U_FAILURE(status
)) {
1200 log_data_err("FAIL: Converter \"%s\" (i=%d)"
1201 " can't be opened.\n",
1205 if (strcmp(ucnv_getName(cnv
, &status
), name
) != 0
1206 && (strstr(name
, "PlatformEndian") == 0 && strstr(name
, "OppositeEndian") == 0)) {
1207 log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
1208 "The should be the same\n",
1209 name
, ucnv_getName(cnv
, &status
));
1214 status
= U_ZERO_ERROR
;
1215 alias0
= ucnv_getAlias(name
, 0, &status
);
1216 for (j
=1; j
<na
; ++j
) {
1218 /* Make sure each alias maps back to the the same list of
1219 aliases. Assume that if alias 0 is the same, the whole
1220 list is the same (this should always be true). */
1221 const char *mapBack
;
1223 status
= U_ZERO_ERROR
;
1224 alias
= ucnv_getAlias(name
, j
, &status
);
1225 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1226 log_err("FAIL: Converter \"%s\"is ambiguous\n", name
);
1229 if (alias
== NULL
) {
1230 log_err("FAIL: Converter \"%s\" -> "
1236 mapBack
= ucnv_getAlias(alias
, 0, &status
);
1238 if (mapBack
== NULL
) {
1239 log_err("FAIL: Converter \"%s\" -> "
1240 "alias[%d]=\"%s\" -> "
1241 "alias[0]=NULL, exp. \"%s\"\n",
1242 name
, j
, alias
, alias0
);
1246 if (0 != strcmp(alias0
, mapBack
)) {
1248 UBool foundAlias
= FALSE
;
1249 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1250 /* Make sure that we only get this mismapping when there is
1251 an ambiguous alias, and the other converter has this alias too. */
1252 for (idx
= 0; idx
< ucnv_countAliases(mapBack
, &status
); idx
++) {
1253 if (strcmp(ucnv_getAlias(mapBack
, (uint16_t)idx
, &status
), alias
) == 0) {
1259 /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
1262 log_err("FAIL: Converter \"%s\" -> "
1263 "alias[%d]=\"%s\" -> "
1264 "alias[0]=\"%s\", exp. \"%s\"\n",
1265 name
, j
, alias
, mapBack
, alias0
);
1272 /* Check a list of predetermined aliases that we expect to map
1273 * back to ISO_2022 and UTF-8. */
1274 for (i
=1; i
<ISO_2022_NAMES_LENGTH
; ++i
) {
1275 const char* mapBack
= ucnv_getAlias(ISO_2022_NAMES
[i
], 0, &status
);
1277 log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES
[i
]);
1280 if (0 != strcmp(mapBack
, ISO_2022_NAMES
[0])) {
1281 log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
1282 ISO_2022_NAMES
[i
], mapBack
);
1287 for (i
=1; i
<UTF8_NAMES_LENGTH
; ++i
) {
1288 const char* mapBack
= ucnv_getAlias(UTF8_NAMES
[i
], 0, &status
);
1290 log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES
[i
]);
1293 if (mapBack
&& 0 != strcmp(mapBack
, UTF8_NAMES
[0])) {
1294 log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
1295 UTF8_NAMES
[i
], mapBack
);
1300 * Check a list of predetermined aliases that we expect to map
1301 * back to predermined converter names.
1304 for (i
= 0; i
< CONVERTERS_NAMES_LENGTH
; ++i
) {
1305 const char* mapBack
= ucnv_getAlias(CONVERTERS_NAMES
[i
].alias
, 0, &status
);
1307 log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES
[i
]);
1310 if (0 != strcmp(mapBack
, CONVERTERS_NAMES
[i
].name
)) {
1311 log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
1312 CONVERTERS_NAMES
[i
].alias
, mapBack
, CONVERTERS_NAMES
[i
].name
);
1318 static void TestDuplicateAlias(void) {
1320 UErrorCode status
= U_ZERO_ERROR
;
1322 status
= U_ZERO_ERROR
;
1323 alias
= ucnv_getStandardName("Shift_JIS", "IBM", &status
);
1324 if (alias
== NULL
|| strcmp(alias
, "ibm-943") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1325 log_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias
);
1327 status
= U_ZERO_ERROR
;
1328 alias
= ucnv_getStandardName("ibm-943", "IANA", &status
);
1329 if (alias
== NULL
|| strcmp(alias
, "Shift_JIS") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1330 log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias
);
1332 status
= U_ZERO_ERROR
;
1333 alias
= ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status
);
1334 if (alias
!= NULL
|| status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1335 log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias
);
1340 /* Test safe clone callback */
1342 static uint32_t TSCC_nextSerial()
1344 static uint32_t n
= 1;
1351 uint32_t magic
; /* 0xC0FFEE to identify that the object is OK */
1352 uint32_t serial
; /* minted from nextSerial, above */
1353 UBool wasClosed
; /* close happened on the object */
1356 static TSCCContext
*TSCC_clone(TSCCContext
*ctx
)
1358 TSCCContext
*newCtx
= (TSCCContext
*)malloc(sizeof(TSCCContext
));
1360 newCtx
->serial
= TSCC_nextSerial();
1361 newCtx
->wasClosed
= 0;
1362 newCtx
->magic
= 0xC0FFEE;
1364 log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx
, ctx
->serial
, newCtx
, newCtx
->serial
);
1369 static void TSCC_fromU(const void *context
,
1370 UConverterFromUnicodeArgs
*fromUArgs
,
1371 const UChar
* codeUnits
,
1374 UConverterCallbackReason reason
,
1377 TSCCContext
*ctx
= (TSCCContext
*)context
;
1378 UConverterFromUCallback junkFrom
;
1380 log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, fromUArgs
->converter
);
1382 if(ctx
->magic
!= 0xC0FFEE) {
1383 log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1387 if(reason
== UCNV_CLONE
) {
1388 UErrorCode subErr
= U_ZERO_ERROR
;
1389 TSCCContext
*newCtx
;
1390 TSCCContext
*junkCtx
;
1393 log_verbose("TSCC_fromU: cloning..\n");
1394 newCtx
= TSCC_clone(ctx
);
1396 if(newCtx
== NULL
) {
1397 log_err("TSCC_fromU: internal clone failed on %p\n", ctx
);
1401 ucnv_getFromUCallBack(fromUArgs
->converter
, &junkFrom
, (const void**)&junkCtx
);
1402 ucnv_setFromUCallBack(fromUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1404 if(U_FAILURE(subErr
)) {
1409 if(reason
== UCNV_CLOSE
) {
1410 log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1411 ctx
->wasClosed
= TRUE
;
1416 static void TSCC_toU(const void *context
,
1417 UConverterToUnicodeArgs
*toUArgs
,
1418 const char* codeUnits
,
1420 UConverterCallbackReason reason
,
1423 TSCCContext
*ctx
= (TSCCContext
*)context
;
1424 UConverterToUCallback junkFrom
;
1426 log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, toUArgs
->converter
);
1428 if(ctx
->magic
!= 0xC0FFEE) {
1429 log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1433 if(reason
== UCNV_CLONE
) {
1434 UErrorCode subErr
= U_ZERO_ERROR
;
1435 TSCCContext
*newCtx
;
1436 TSCCContext
*junkCtx
;
1439 log_verbose("TSCC_toU: cloning..\n");
1440 newCtx
= TSCC_clone(ctx
);
1442 if(newCtx
== NULL
) {
1443 log_err("TSCC_toU: internal clone failed on %p\n", ctx
);
1447 ucnv_getToUCallBack(toUArgs
->converter
, &junkFrom
, (const void**)&junkCtx
);
1448 ucnv_setToUCallBack(toUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1450 if(U_FAILURE(subErr
)) {
1455 if(reason
== UCNV_CLOSE
) {
1456 log_verbose("TSCC_toU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1457 ctx
->wasClosed
= TRUE
;
1461 static void TSCC_init(TSCCContext
*q
)
1463 q
->magic
= 0xC0FFEE;
1464 q
->serial
= TSCC_nextSerial();
1468 static void TSCC_print_log(TSCCContext
*q
, const char *name
)
1471 log_verbose("TSCContext: %s is NULL!!\n", name
);
1473 if(q
->magic
!= 0xC0FFEE) {
1474 log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
1475 q
,q
->serial
, q
->magic
);
1477 log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
1478 q
, q
->serial
, name
, q
->magic
, q
->wasClosed
?"CLOSED":"open");
1482 static void TestConvertSafeCloneCallback()
1484 UErrorCode err
= U_ZERO_ERROR
;
1485 TSCCContext from1
, to1
;
1486 TSCCContext
*from2
, *from3
, *to2
, *to3
;
1488 int32_t hunkSize
= 8192;
1489 UConverterFromUCallback junkFrom
;
1490 UConverterToUCallback junkTo
;
1491 UConverter
*conv1
, *conv2
= NULL
;
1493 conv1
= ucnv_open("iso-8859-3", &err
);
1495 if(U_FAILURE(err
)) {
1496 log_data_err("Err opening iso-8859-3, %s", u_errorName(err
));
1500 log_verbose("Opened conv1=%p\n", conv1
);
1505 TSCC_print_log(&from1
, "from1");
1506 TSCC_print_log(&to1
, "to1");
1508 ucnv_setFromUCallBack(conv1
, TSCC_fromU
, &from1
, NULL
, NULL
, &err
);
1509 log_verbose("Set from1 on conv1\n");
1510 TSCC_print_log(&from1
, "from1");
1512 ucnv_setToUCallBack(conv1
, TSCC_toU
, &to1
, NULL
, NULL
, &err
);
1513 log_verbose("Set to1 on conv1\n");
1514 TSCC_print_log(&to1
, "to1");
1516 conv2
= ucnv_safeClone(conv1
, hunk
, &hunkSize
, &err
);
1517 if(U_FAILURE(err
)) {
1518 log_err("safeClone failed: %s\n", u_errorName(err
));
1521 log_verbose("Cloned to conv2=%p.\n", conv2
);
1523 /********** from *********************/
1524 ucnv_getFromUCallBack(conv2
, &junkFrom
, (const void**)&from2
);
1525 ucnv_getFromUCallBack(conv1
, &junkFrom
, (const void**)&from3
);
1527 TSCC_print_log(from2
, "from2");
1528 TSCC_print_log(from3
, "from3(==from1)");
1531 log_err("FAIL! from2 is null \n");
1536 log_err("FAIL! from3 is null \n");
1540 if(from3
!= (&from1
) ) {
1541 log_err("FAIL! conv1's FROM context changed!\n");
1544 if(from2
== (&from1
) ) {
1545 log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
1548 if(from1
.wasClosed
) {
1549 log_err("FAIL! from1 is closed \n");
1552 if(from2
->wasClosed
) {
1553 log_err("FAIL! from2 was closed\n");
1556 /********** to *********************/
1557 ucnv_getToUCallBack(conv2
, &junkTo
, (const void**)&to2
);
1558 ucnv_getToUCallBack(conv1
, &junkTo
, (const void**)&to3
);
1560 TSCC_print_log(to2
, "to2");
1561 TSCC_print_log(to3
, "to3(==to1)");
1564 log_err("FAIL! to2 is null \n");
1569 log_err("FAIL! to3 is null \n");
1573 if(to3
!= (&to1
) ) {
1574 log_err("FAIL! conv1's TO context changed!\n");
1577 if(to2
== (&to1
) ) {
1578 log_err("FAIL! conv1's TO context is the same as conv2's!\n");
1582 log_err("FAIL! to1 is closed \n");
1585 if(to2
->wasClosed
) {
1586 log_err("FAIL! to2 was closed\n");
1589 /*************************************/
1592 log_verbose("ucnv_closed (conv1)\n");
1593 TSCC_print_log(&from1
, "from1");
1594 TSCC_print_log(from2
, "from2");
1595 TSCC_print_log(&to1
, "to1");
1596 TSCC_print_log(to2
, "to2");
1598 if(from1
.wasClosed
== FALSE
) {
1599 log_err("FAIL! from1 is NOT closed \n");
1602 if(from2
->wasClosed
) {
1603 log_err("FAIL! from2 was closed\n");
1606 if(to1
.wasClosed
== FALSE
) {
1607 log_err("FAIL! to1 is NOT closed \n");
1610 if(to2
->wasClosed
) {
1611 log_err("FAIL! to2 was closed\n");
1615 log_verbose("ucnv_closed (conv2)\n");
1617 TSCC_print_log(&from1
, "from1");
1618 TSCC_print_log(from2
, "from2");
1620 if(from1
.wasClosed
== FALSE
) {
1621 log_err("FAIL! from1 is NOT closed \n");
1624 if(from2
->wasClosed
== FALSE
) {
1625 log_err("FAIL! from2 was NOT closed\n");
1628 TSCC_print_log(&to1
, "to1");
1629 TSCC_print_log(to2
, "to2");
1631 if(to1
.wasClosed
== FALSE
) {
1632 log_err("FAIL! to1 is NOT closed \n");
1635 if(to2
->wasClosed
== FALSE
) {
1636 log_err("FAIL! to2 was NOT closed\n");
1640 free(to2
); /* to1 is stack based */
1642 if(from2
!= (&from1
)) {
1643 free(from2
); /* from1 is stack based */
1648 containsAnyOtherByte(uint8_t *p
, int32_t length
, uint8_t b
) {
1659 static void TestConvertSafeClone()
1661 /* one 'regular' & all the 'private stateful' converters */
1662 static const char *const names
[] = {
1664 "ISO_2022,locale=zh,version=1",
1669 "ISO_2022,locale=kr,version=1",
1670 "ISO_2022,locale=jp,version=2",
1673 "IMAP-mailbox-name",
1677 static const int32_t bufferSizes
[] = {
1678 U_CNV_SAFECLONE_BUFFERSIZE
,
1679 (int32_t)(3*sizeof(UConverter
))/2, /* 1.5*sizeof(UConverter) */
1680 (int32_t)sizeof(UConverter
)/2 /* 0.5*sizeof(UConverter) */
1683 char charBuffer
[21]; /* Leave at an odd number for alignment testing */
1684 uint8_t buffer
[3] [U_CNV_SAFECLONE_BUFFERSIZE
];
1685 int32_t bufferSize
, maxBufferSize
;
1686 const char *maxName
;
1687 UConverter
* cnv
, *cnv2
;
1691 const char *pConstCharBuffer
;
1692 const char *charBufferLimit
= charBuffer
+ sizeof(charBuffer
)/sizeof(*charBuffer
);
1693 UChar uniBuffer
[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
1694 UChar uniCharBuffer
[20];
1695 char charSourceBuffer
[] = { 0x1b, 0x24, 0x42 };
1696 const char *pCharSource
= charSourceBuffer
;
1697 const char *pCharSourceLimit
= charSourceBuffer
+ sizeof(charSourceBuffer
);
1698 UChar
*pUCharTarget
= uniCharBuffer
;
1699 UChar
*pUCharTargetLimit
= uniCharBuffer
+ sizeof(uniCharBuffer
)/sizeof(*uniCharBuffer
);
1700 const UChar
* pUniBuffer
;
1701 const UChar
*uniBufferLimit
= uniBuffer
+ sizeof(uniBuffer
)/sizeof(*uniBuffer
);
1705 cnv
= ucnv_open(names
[0], &err
);
1706 if(U_SUCCESS(err
)) {
1707 /* Check the various error & informational states: */
1709 /* Null status - just returns NULL */
1710 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1711 if (0 != ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, 0))
1713 log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
1715 /* error status - should return 0 & keep error the same */
1716 err
= U_MEMORY_ALLOCATION_ERROR
;
1717 if (0 != ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || err
!= U_MEMORY_ALLOCATION_ERROR
)
1719 log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
1723 /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/
1724 if (0 != ucnv_safeClone(cnv
, buffer
[0], 0, &err
) || err
!= U_ILLEGAL_ARGUMENT_ERROR
)
1726 log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
1730 /* buffer size pointer is 0 - fill in pbufferSize with a size */
1732 if (0 != ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || U_FAILURE(err
) || bufferSize
<= 0)
1734 log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
1736 /* Verify our define is large enough */
1737 if (U_CNV_SAFECLONE_BUFFERSIZE
< bufferSize
)
1739 log_err("FAIL: Pre-calculated buffer size is too small\n");
1741 /* Verify we can use this run-time calculated size */
1742 if (0 == (cnv2
= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
)) || U_FAILURE(err
))
1744 log_err("FAIL: Converter can't be cloned with run-time size\n");
1750 /* size one byte too small - should allocate & let us know */
1752 if (0 == (cnv2
= ucnv_safeClone(cnv
, 0, &bufferSize
, &err
)) || err
!= U_SAFECLONE_ALLOCATED_WARNING
)
1754 log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n");
1761 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1763 /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
1764 if (0 == (cnv2
= ucnv_safeClone(cnv
, 0, &bufferSize
, &err
)) || err
!= U_SAFECLONE_ALLOCATED_WARNING
)
1766 log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
1774 /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
1775 if (0 != ucnv_safeClone(0, buffer
[0], &bufferSize
, &err
) || err
!= U_ILLEGAL_ARGUMENT_ERROR
)
1777 log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
1786 /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
1788 for(j
= 0; j
< LENGTHOF(bufferSizes
); ++j
) {
1789 for (index
= 0; index
< LENGTHOF(names
); index
++)
1792 cnv
= ucnv_open(names
[index
], &err
);
1793 if(U_FAILURE(err
)) {
1794 log_data_err("ucnv_open(\"%s\") failed - %s\n", names
[index
], u_errorName(err
));
1799 /* preflight to get maxBufferSize */
1801 ucnv_safeClone(cnv
, NULL
, &bufferSize
, &err
);
1802 if(bufferSize
> maxBufferSize
) {
1803 maxBufferSize
= bufferSize
;
1804 maxName
= names
[index
];
1808 memset(buffer
, 0xaa, sizeof(buffer
));
1810 bufferSize
= bufferSizes
[j
];
1811 cnv2
= ucnv_safeClone(cnv
, buffer
[1], &bufferSize
, &err
);
1813 /* close the original immediately to make sure that the clone works by itself */
1816 /* check if the clone function overwrote any bytes that it is not supposed to touch */
1817 if(bufferSize
<= bufferSizes
[j
]) {
1818 /* used the stack buffer */
1819 if( containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
[0]), 0xaa) ||
1820 containsAnyOtherByte(buffer
[1]+bufferSize
, (int32_t)(sizeof(buffer
)-(sizeof(buffer
[0])+bufferSize
)), 0xaa)
1822 log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
1823 names
[index
], bufferSize
, bufferSizes
[j
]);
1826 /* heap-allocated the clone */
1827 if(containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
), 0xaa)) {
1828 log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
1829 names
[index
], bufferSize
, bufferSizes
[j
]);
1833 pCharBuffer
= charBuffer
;
1834 pUniBuffer
= uniBuffer
;
1836 ucnv_fromUnicode(cnv2
,
1845 log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err
));
1847 ucnv_toUnicode(cnv2
,
1858 log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err
));
1861 pConstCharBuffer
= charBuffer
;
1862 if (uniBuffer
[0] != ucnv_getNextUChar(cnv2
, &pConstCharBuffer
, pCharBuffer
, &err
))
1864 log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err
));
1870 log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1871 sizeof(UConverter
), maxBufferSize
, maxName
, (int)U_CNV_SAFECLONE_BUFFERSIZE
);
1874 static void TestCCSID() {
1876 UErrorCode errorCode
;
1877 int32_t ccsids
[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
1880 for(i
=0; i
<(int32_t)(sizeof(ccsids
)/sizeof(int32_t)); ++i
) {
1883 errorCode
=U_ZERO_ERROR
;
1884 cnv
=ucnv_openCCSID(ccsid
, UCNV_IBM
, &errorCode
);
1885 if(U_FAILURE(errorCode
)) {
1886 log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid
, u_errorName(errorCode
));
1890 if(ccsid
!=ucnv_getCCSID(cnv
, &errorCode
)) {
1891 log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid
, ucnv_getCCSID(cnv
, &errorCode
));
1894 /* skip gb18030(ccsid 1392) */
1895 if(ccsid
!= 1392 && UCNV_IBM
!=ucnv_getPlatform(cnv
, &errorCode
)) {
1896 log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid
, ucnv_getPlatform(cnv
, &errorCode
));
1903 /* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
1905 /* CHUNK_SIZE defined in common\ucnv.c: */
1906 #define CHUNK_SIZE 1024
1908 static void bug1(void);
1909 static void bug2(void);
1910 static void bug3(void);
1915 bug1(); /* Unicode intermediate buffer straddle bug */
1916 bug2(); /* pre-flighting size incorrect caused by simple overflow */
1917 bug3(); /* pre-flighting size incorrect caused by expansion overflow */
1921 * jitterbug 932: test chunking boundary conditions in
1923 int32_t ucnv_convert(const char *toConverterName,
1924 const char *fromConverterName,
1931 * See discussions on the icu mailing list in
1932 * 2001-April with the subject "converter 'flush' question".
1934 * Bug report and test code provided by Edward J. Batutis.
1938 static char char_in
[CHUNK_SIZE
+32];
1939 static char char_out
[CHUNK_SIZE
*2];
1941 /* GB 18030 equivalent of U+10000 is 90308130 */
1942 static const char test_seq
[]={ (char)0x90u
, 0x30, (char)0x81u
, 0x30 };
1944 UErrorCode err
= U_ZERO_ERROR
;
1945 int32_t i
, test_seq_len
= sizeof(test_seq
);
1948 * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
1949 * until the straddle bug appears. I didn't want to hard-code everything so this test could
1950 * be expanded - however this is the only type of straddle bug I can think of at the moment -
1951 * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
1952 * other Unicode sequences cause a bug since combining sequences are not supported by the
1956 for (i
= test_seq_len
; i
>= 0; i
--) {
1957 /* put character sequence into input buffer */
1958 memset(char_in
, 0x61, sizeof(char_in
)); /* GB 18030 'a' */
1959 memcpy(char_in
+ (CHUNK_SIZE
- i
), test_seq
, test_seq_len
);
1961 /* do the conversion */
1962 ucnv_convert("us-ascii", /* out */
1971 if (err
== U_TRUNCATED_CHAR_FOUND
) {
1972 /* this happens when surrogate pair straddles the intermediate buffer in
1973 * T_UConverter_fromCodepageToCodepage */
1974 log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
1979 /* bug2: pre-flighting loop bug: simple overflow causes bug */
1982 /* US-ASCII "1234567890" */
1983 static const char source
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
1984 static const char sourceUTF8
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
1985 static const char sourceUTF32
[]={ 0x00, 0x00, 0x00, 0x30,
1986 0x00, 0x00, 0x00, 0x31,
1987 0x00, 0x00, 0x00, 0x32,
1988 0x00, 0x00, 0x00, 0x33,
1989 0x00, 0x00, 0x00, 0x34,
1990 0x00, 0x00, 0x00, 0x35,
1991 0x00, 0x00, 0x00, 0x36,
1992 0x00, 0x00, 0x00, 0x37,
1993 0x00, 0x00, 0x00, 0x38,
1994 0x00, 0x00, (char)0xf0, 0x00};
1995 static char target
[5];
1997 UErrorCode err
= U_ZERO_ERROR
;
2000 /* do the conversion */
2001 size
= ucnv_convert("iso-8859-1", /* out */
2002 "us-ascii", /* in */
2010 /* bug2: size is 5, should be 10 */
2011 log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size
);
2015 /* do the conversion */
2016 size
= ucnv_convert("UTF-32BE", /* out */
2025 /* bug2: size is 5, should be 32 */
2026 log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size
);
2030 /* do the conversion */
2031 size
= ucnv_convert("UTF-8", /* out */
2032 "UTF-32BE", /* in */
2036 sizeof(sourceUTF32
),
2040 /* bug2: size is 5, should be 12 */
2041 log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size
);
2046 * bug3: when the characters expand going from source to target codepage
2047 * you get bug3 in addition to bug2
2051 static char char_in
[CHUNK_SIZE
*4];
2052 static char target
[5];
2053 UErrorCode err
= U_ZERO_ERROR
;
2057 * first get the buggy size from bug2 then
2058 * compare it to buggy size with an expansion
2060 memset(char_in
, 0x61, sizeof(char_in
)); /* US-ASCII 'a' */
2062 /* do the conversion */
2063 size
= ucnv_convert("lmbcs", /* out */
2064 "us-ascii", /* in */
2071 if ( size
!= sizeof(char_in
) ) {
2073 * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
2074 * in the converter?), should be CHUNK_SIZE*4
2076 * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
2078 log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in
), size
);
2082 * now do the conversion with expansion
2083 * ascii 0x08 expands to 0x0F 0x28 in lmbcs
2085 memset(char_in
, 8, sizeof(char_in
));
2088 /* do the conversion */
2089 size
= ucnv_convert("lmbcs", /* out */
2090 "us-ascii", /* in */
2097 /* expect 2X expansion */
2098 if ( size
!= sizeof(char_in
) * 2 ) {
2101 * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
2103 log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in
) * 2, size
);
2108 convertExStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2109 const char *src
, int32_t srcLength
,
2110 const char *expectTarget
, int32_t expectTargetLength
,
2112 const char *testName
,
2113 UErrorCode expectCode
) {
2114 UChar pivotBuffer
[CHUNK_SIZE
];
2115 UChar
*pivotSource
, *pivotTarget
;
2116 const UChar
*pivotLimit
;
2118 char targetBuffer
[CHUNK_SIZE
];
2120 const char *srcLimit
, *finalSrcLimit
, *targetLimit
;
2122 int32_t targetLength
;
2126 UErrorCode errorCode
;
2129 if(chunkSize
>CHUNK_SIZE
) {
2130 chunkSize
=CHUNK_SIZE
;
2133 pivotSource
=pivotTarget
=pivotBuffer
;
2134 pivotLimit
=pivotBuffer
+chunkSize
;
2136 finalSrcLimit
=src
+srcLength
;
2137 target
=targetBuffer
;
2138 targetLimit
=targetBuffer
+chunkSize
;
2140 ucnv_resetToUnicode(srcCnv
);
2141 ucnv_resetFromUnicode(targetCnv
);
2143 errorCode
=U_ZERO_ERROR
;
2146 /* convert, streaming-style (both converters and pivot keep state) */
2148 /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
2149 if(src
+chunkSize
<=finalSrcLimit
) {
2150 srcLimit
=src
+chunkSize
;
2152 srcLimit
=finalSrcLimit
;
2154 ucnv_convertEx(targetCnv
, srcCnv
,
2155 &target
, targetLimit
,
2157 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotLimit
,
2158 FALSE
, flush
, &errorCode
);
2159 targetLength
=(int32_t)(target
-targetBuffer
);
2160 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
2161 /* continue converting another chunk */
2162 errorCode
=U_ZERO_ERROR
;
2163 if(targetLength
+chunkSize
<=sizeof(targetBuffer
)) {
2164 targetLimit
=target
+chunkSize
;
2166 targetLimit
=targetBuffer
+sizeof(targetBuffer
);
2168 } else if(U_FAILURE(errorCode
)) {
2174 } else if(src
==finalSrcLimit
&& pivotSource
==pivotTarget
) {
2175 /* all consumed, now flush without input (separate from conversion for testing) */
2180 if(!(errorCode
==expectCode
|| (expectCode
==U_ZERO_ERROR
&& errorCode
==U_STRING_NOT_TERMINATED_WARNING
))) {
2181 log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
2182 testName
, chunkSize
, u_errorName(errorCode
), u_errorName(expectCode
));
2183 } else if(targetLength
!=expectTargetLength
) {
2184 log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
2185 testName
, chunkSize
, targetLength
, expectTargetLength
);
2186 } else if(memcmp(targetBuffer
, expectTarget
, targetLength
)!=0) {
2187 log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
2188 testName
, chunkSize
);
2193 convertExMultiStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2194 const char *src
, int32_t srcLength
,
2195 const char *expectTarget
, int32_t expectTargetLength
,
2196 const char *testName
,
2197 UErrorCode expectCode
) {
2198 convertExStreaming(srcCnv
, targetCnv
,
2200 expectTarget
, expectTargetLength
,
2201 1, testName
, expectCode
);
2202 convertExStreaming(srcCnv
, targetCnv
,
2204 expectTarget
, expectTargetLength
,
2205 3, testName
, expectCode
);
2206 convertExStreaming(srcCnv
, targetCnv
,
2208 expectTarget
, expectTargetLength
,
2209 7, testName
, expectCode
);
2212 static void TestConvertEx() {
2213 static const uint8_t
2215 /* 4e00 30a1 ff61 0410 */
2216 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2219 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2223 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2224 * SUB, SUB, 0x40, SUB, SUB, 0x40
2226 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
2229 char srcBuffer
[100], targetBuffer
[100];
2234 UChar pivotBuffer
[100];
2235 UChar
*pivotSource
, *pivotTarget
;
2237 UConverter
*cnv1
, *cnv2
;
2238 UErrorCode errorCode
;
2240 errorCode
=U_ZERO_ERROR
;
2241 cnv1
=ucnv_open("UTF-8", &errorCode
);
2242 if(U_FAILURE(errorCode
)) {
2243 log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode
));
2247 cnv2
=ucnv_open("Shift-JIS", &errorCode
);
2248 if(U_FAILURE(errorCode
)) {
2249 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2254 /* test ucnv_convertEx() with streaming conversion style */
2255 convertExMultiStreaming(cnv1
, cnv2
,
2256 (const char *)utf8
, sizeof(utf8
), (const char *)shiftJIS
, sizeof(shiftJIS
),
2257 "UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2259 convertExMultiStreaming(cnv2
, cnv1
,
2260 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
),
2261 "Shift-JIS -> UTF-8", U_ZERO_ERROR
);
2263 /* U_ZERO_ERROR because by default the SUB callbacks are set */
2264 convertExMultiStreaming(cnv1
, cnv2
,
2265 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)errorTarget
, sizeof(errorTarget
),
2266 "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2268 /* test some simple conversions */
2270 /* NUL-terminated source and target */
2271 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2272 memcpy(srcBuffer
, utf8
, sizeof(utf8
));
2273 srcBuffer
[sizeof(utf8
)]=0;
2275 target
=targetBuffer
;
2276 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2277 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2278 if( errorCode
!=U_ZERO_ERROR
||
2279 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2281 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2283 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
2284 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2287 /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
2288 errorCode
=U_AMBIGUOUS_ALIAS_WARNING
;
2289 memset(targetBuffer
, 0xff, sizeof(targetBuffer
));
2291 target
=targetBuffer
;
2292 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(shiftJIS
), &src
, NULL
,
2293 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2294 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2295 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2296 *target
!=(char)0xff ||
2297 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2299 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
2300 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2304 errorCode
=U_MESSAGE_PARSE_ERROR
;
2306 target
=targetBuffer
;
2307 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2308 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2309 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2310 log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2313 /* pivotLimit==pivotStart */
2314 errorCode
=U_ZERO_ERROR
;
2315 pivotSource
=pivotTarget
=pivotBuffer
;
2316 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2317 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
, TRUE
, TRUE
, &errorCode
);
2318 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2319 log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode
));
2322 /* *pivotSource==NULL */
2323 errorCode
=U_ZERO_ERROR
;
2325 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2326 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, TRUE
, &errorCode
);
2327 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2328 log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode
));
2332 errorCode
=U_ZERO_ERROR
;
2334 pivotSource
=pivotBuffer
;
2335 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2336 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, TRUE
, &errorCode
);
2337 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2338 log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode
));
2346 TestConvertAlgorithmic() {
2347 static const uint8_t
2349 /* 4e00 30a1 ff61 0410 */
2350 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2353 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2357 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2358 * SUB, SUB, 0x40, SUB, SUB, 0x40
2360 /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
2363 0xfe, 0xff /* BOM only, no text */
2366 0xff, 0xfe, 0, 0 /* BOM only, no text */
2369 char target
[100], utf8NUL
[100], shiftJISNUL
[100];
2372 UErrorCode errorCode
;
2376 errorCode
=U_ZERO_ERROR
;
2377 cnv
=ucnv_open("Shift-JIS", &errorCode
);
2378 if(U_FAILURE(errorCode
)) {
2379 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2384 memcpy(utf8NUL
, utf8
, sizeof(utf8
));
2385 utf8NUL
[sizeof(utf8
)]=0;
2386 memcpy(shiftJISNUL
, shiftJIS
, sizeof(shiftJIS
));
2387 shiftJISNUL
[sizeof(shiftJIS
)]=0;
2390 * The to/from algorithmic convenience functions share a common implementation,
2391 * so we need not test all permutations of them.
2394 /* length in, not terminated out */
2395 errorCode
=U_ZERO_ERROR
;
2396 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF8
, target
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
), &errorCode
);
2397 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2398 length
!=sizeof(shiftJIS
) ||
2399 memcmp(target
, shiftJIS
, length
)!=0
2401 log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
2402 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2405 /* terminated in and out */
2406 memset(target
, 0x55, sizeof(target
));
2407 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2408 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, -1, &errorCode
);
2409 if( errorCode
!=U_ZERO_ERROR
||
2410 length
!=sizeof(utf8
) ||
2411 memcmp(target
, utf8
, length
)!=0
2413 log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
2414 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2417 /* empty string, some target buffer */
2418 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2419 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, 0, &errorCode
);
2420 if( errorCode
!=U_ZERO_ERROR
||
2423 log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
2424 u_errorName(errorCode
), length
);
2427 /* pseudo-empty string, no target buffer */
2428 errorCode
=U_ZERO_ERROR
;
2429 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2430 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2433 log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2434 u_errorName(errorCode
), length
);
2437 errorCode
=U_ZERO_ERROR
;
2438 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF32
, target
, 0, (const char *)utf32
, 4, &errorCode
);
2439 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2442 log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2443 u_errorName(errorCode
), length
);
2447 errorCode
=U_MESSAGE_PARSE_ERROR
;
2448 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2449 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2450 log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2454 errorCode
=U_ZERO_ERROR
;
2455 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, NULL
, 2, &errorCode
);
2456 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2457 log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode
));
2460 /* illegal alg. type */
2461 errorCode
=U_ZERO_ERROR
;
2462 length
=ucnv_fromAlgorithmic(cnv
, (UConverterType
)99, target
, 0, (const char *)utf16
, 2, &errorCode
);
2463 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2464 log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode
));
2469 static void TestLMBCSMaxChar(void) {
2470 static const struct {
2474 /* some non-LMBCS converters - perfect test setup here */
2485 { 4, "IMAP-mailbox-name"},
2488 { 1, "windows-1256"},
2500 { 3, "ISO-2022-KR"},
2501 { 6, "ISO-2022-JP"},
2502 { 8, "ISO-2022-CN"},
2520 for (idx
= 0; idx
< LENGTHOF(converter
); idx
++) {
2521 UErrorCode status
= U_ZERO_ERROR
;
2522 UConverter
*cnv
= cnv_open(converter
[idx
].name
, &status
);
2523 if (U_FAILURE(status
)) {
2526 if (converter
[idx
].maxSize
!= ucnv_getMaxCharSize(cnv
)) {
2527 log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
2528 converter
[idx
].name
, converter
[idx
].maxSize
, ucnv_getMaxCharSize(cnv
));
2533 /* mostly test that the macro compiles */
2534 if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
2535 log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
2540 static void TestJ1968(void) {
2541 UErrorCode err
= U_ZERO_ERROR
;
2543 char myConvName
[] = "My really really really really really really really really really really really"
2544 " really really really really really really really really really really really"
2545 " really really really really really really really really long converter name";
2546 UChar myConvNameU
[sizeof(myConvName
)];
2548 u_charsToUChars(myConvName
, myConvNameU
, sizeof(myConvName
));
2551 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
+1] = 0;
2552 cnv
= ucnv_openU(myConvNameU
, &err
);
2553 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2554 log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2558 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
2559 cnv
= ucnv_openU(myConvNameU
, &err
);
2560 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2561 log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2565 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
2566 cnv
= ucnv_openU(myConvNameU
, &err
);
2567 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2568 log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2575 cnv
= ucnv_open(myConvName
, &err
);
2576 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2577 log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2581 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = ',';
2582 cnv
= ucnv_open(myConvName
, &err
);
2583 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2584 log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2588 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
2589 cnv
= ucnv_open(myConvName
, &err
);
2590 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2591 log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2595 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
2596 strncpy(myConvName
+ UCNV_MAX_CONVERTER_NAME_LENGTH
, "locale=", 7);
2597 cnv
= ucnv_open(myConvName
, &err
);
2598 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2599 log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2602 /* The comma isn't really a part of the converter name. */
2604 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
2605 cnv
= ucnv_open(myConvName
, &err
);
2606 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2607 log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2611 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ' ';
2612 cnv
= ucnv_open(myConvName
, &err
);
2613 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2614 log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2618 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
2619 cnv
= ucnv_open(myConvName
, &err
);
2620 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2621 log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2627 testSwap(const char *name
, UBool swap
) {
2629 * Test Unicode text.
2630 * Contains characters that are the highest for some of the
2631 * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
2632 * tables copies the entire tables.
2634 static const UChar text
[]={
2635 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
2638 UChar uNormal
[32], uSwapped
[32];
2639 char normal
[32], swapped
[32];
2643 int32_t i
, normalLength
, swappedLength
;
2647 const char *swappedName
;
2648 UConverter
*cnv
, *swapCnv
;
2649 UErrorCode errorCode
;
2651 /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
2653 /* open both the normal and the LF/NL-swapping converters */
2654 strcpy(swapped
, name
);
2655 strcat(swapped
, UCNV_SWAP_LFNL_OPTION_STRING
);
2657 errorCode
=U_ZERO_ERROR
;
2658 swapCnv
=ucnv_open(swapped
, &errorCode
);
2659 cnv
=ucnv_open(name
, &errorCode
);
2660 if(U_FAILURE(errorCode
)) {
2661 log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name
, swapped
, u_errorName(errorCode
));
2665 /* the name must contain the swap option if and only if we expect the converter to swap */
2666 swappedName
=ucnv_getName(swapCnv
, &errorCode
);
2667 if(U_FAILURE(errorCode
)) {
2668 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name
, u_errorName(errorCode
));
2672 pc
=strstr(swappedName
, UCNV_SWAP_LFNL_OPTION_STRING
);
2673 if(swap
!= (pc
!=NULL
)) {
2674 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name
, swappedName
, swap
);
2678 /* convert to EBCDIC */
2681 ucnv_fromUnicode(cnv
, &pc
, normal
+LENGTHOF(normal
), &pcu
, text
+LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
2682 normalLength
=(int32_t)(pc
-normal
);
2686 ucnv_fromUnicode(swapCnv
, &pc
, swapped
+LENGTHOF(swapped
), &pcu
, text
+LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
2687 swappedLength
=(int32_t)(pc
-swapped
);
2689 if(U_FAILURE(errorCode
)) {
2690 log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name
, u_errorName(errorCode
));
2694 /* compare EBCDIC output */
2695 if(normalLength
!=swappedLength
) {
2696 log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
2699 for(i
=0; i
<normalLength
; ++i
) {
2700 /* swap EBCDIC LF/NL for comparison */
2705 } else if(c
==0x25) {
2711 log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name
, i
, (uint8_t)swapped
[i
]);
2716 /* convert back to Unicode (may not roundtrip) */
2719 ucnv_toUnicode(cnv
, &pu
, uNormal
+LENGTHOF(uNormal
), (const char **)&pc
, normal
+normalLength
, NULL
, TRUE
, &errorCode
);
2720 normalLength
=(int32_t)(pu
-uNormal
);
2724 ucnv_toUnicode(swapCnv
, &pu
, uSwapped
+LENGTHOF(uSwapped
), (const char **)&pc
, normal
+swappedLength
, NULL
, TRUE
, &errorCode
);
2725 swappedLength
=(int32_t)(pu
-uSwapped
);
2727 if(U_FAILURE(errorCode
)) {
2728 log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name
, u_errorName(errorCode
));
2732 /* compare EBCDIC output */
2733 if(normalLength
!=swappedLength
) {
2734 log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
2737 for(i
=0; i
<normalLength
; ++i
) {
2738 /* swap EBCDIC LF/NL for comparison */
2743 } else if(u
==0x85) {
2748 if(u
!=uSwapped
[i
]) {
2749 log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name
, i
, uSwapped
[i
]);
2757 ucnv_close(swapCnv
);
2761 TestEBCDICSwapLFNL() {
2762 static const struct {
2767 { "ibm-1047", TRUE
},
2768 { "ibm-1140", TRUE
},
2769 { "ibm-930", TRUE
},
2770 { "iso-8859-3", FALSE
}
2775 for(i
=0; i
<LENGTHOF(tests
); ++i
) {
2776 testSwap(tests
[i
].name
, tests
[i
].swap
);