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