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