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