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