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