1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*******************************************************************************
7 *
8 * File CUCDTST.C
9 *
10 * Modification History:
11 * Name Description
12 * Madhu Katragadda Ported for C API, added tests for string functions
13 ********************************************************************************
14 */
15
16 #include <string.h>
17 #include <math.h>
18 #include <stdlib.h>
19
20 #include "unicode/utypes.h"
21 #include "unicode/uchar.h"
22 #include "unicode/putil.h"
23 #include "unicode/ustring.h"
24 #include "unicode/uloc.h"
25 #include "unicode/unorm2.h"
26
27 #include "cintltst.h"
28 #include "putilimp.h"
29 #include "uparse.h"
30 #include "ucase.h"
31 #include "ubidi_props.h"
32 #include "uprops.h"
33 #include "uset_imp.h"
34 #include "usc_impl.h"
35 #include "udatamem.h" /* for testing ucase_openBinary() */
36 #include "cucdapi.h"
37 #include "cmemory.h"
38
39 /* prototypes --------------------------------------------------------------- */
40
41 static void TestUpperLower(void);
42 static void TestLetterNumber(void);
43 static void TestMisc(void);
44 static void TestPOSIX(void);
45 static void TestControlPrint(void);
46 static void TestIdentifier(void);
47 static void TestUnicodeData(void);
48 static void TestCodeUnit(void);
49 static void TestCodePoint(void);
50 static void TestCharLength(void);
51 static void TestCharNames(void);
52 static void TestUCharFromNameUnderflow(void);
53 static void TestMirroring(void);
54 static void TestUScriptRunAPI(void);
55 static void TestAdditionalProperties(void);
56 static void TestNumericProperties(void);
57 static void TestPropertyNames(void);
58 static void TestPropertyValues(void);
59 static void TestConsistency(void);
60 static void TestUCase(void);
61 static void TestUBiDiProps(void);
62 static void TestCaseFolding(void);
63
64 /* internal methods used */
65 static int32_t MakeProp(char* str);
66 static int32_t MakeDir(char* str);
67
68 /* helpers ------------------------------------------------------------------ */
69
70 static void
parseUCDFile(const char * filename,char * fields[][2],int32_t fieldCount,UParseLineFn * lineFn,void * context,UErrorCode * pErrorCode)71 parseUCDFile(const char *filename,
72 char *fields[][2], int32_t fieldCount,
73 UParseLineFn *lineFn, void *context,
74 UErrorCode *pErrorCode) {
75 char path[256];
76 char backupPath[256];
77
78 if(U_FAILURE(*pErrorCode)) {
79 return;
80 }
81
82 /* Look inside ICU_DATA first */
83 strcpy(path, u_getDataDirectory());
84 strcat(path, ".." U_FILE_SEP_STRING "unidata" U_FILE_SEP_STRING);
85 strcat(path, filename);
86
87 /* As a fallback, try to guess where the source data was located
88 * at the time ICU was built, and look there.
89 */
90 strcpy(backupPath, ctest_dataSrcDir());
91 strcat(backupPath, U_FILE_SEP_STRING);
92 strcat(backupPath, "unidata" U_FILE_SEP_STRING);
93 strcat(backupPath, filename);
94
95 u_parseDelimitedFile(path, ';', fields, fieldCount, lineFn, context, pErrorCode);
96 if(*pErrorCode==U_FILE_ACCESS_ERROR) {
97 *pErrorCode=U_ZERO_ERROR;
98 u_parseDelimitedFile(backupPath, ';', fields, fieldCount, lineFn, context, pErrorCode);
99 }
100 if(U_FAILURE(*pErrorCode)) {
101 log_err_status(*pErrorCode, "error parsing %s: %s\n", filename, u_errorName(*pErrorCode));
102 }
103 }
104
105 /* test data ---------------------------------------------------------------- */
106
107 static const char tagStrings[] = "MnMcMeNdNlNoZsZlZpCcCfCsCoCnLuLlLtLmLoPcPdPsPePoSmScSkSoPiPf";
108 static const int32_t tagValues[] =
109 {
110 /* Mn */ U_NON_SPACING_MARK,
111 /* Mc */ U_COMBINING_SPACING_MARK,
112 /* Me */ U_ENCLOSING_MARK,
113 /* Nd */ U_DECIMAL_DIGIT_NUMBER,
114 /* Nl */ U_LETTER_NUMBER,
115 /* No */ U_OTHER_NUMBER,
116 /* Zs */ U_SPACE_SEPARATOR,
117 /* Zl */ U_LINE_SEPARATOR,
118 /* Zp */ U_PARAGRAPH_SEPARATOR,
119 /* Cc */ U_CONTROL_CHAR,
120 /* Cf */ U_FORMAT_CHAR,
121 /* Cs */ U_SURROGATE,
122 /* Co */ U_PRIVATE_USE_CHAR,
123 /* Cn */ U_UNASSIGNED,
124 /* Lu */ U_UPPERCASE_LETTER,
125 /* Ll */ U_LOWERCASE_LETTER,
126 /* Lt */ U_TITLECASE_LETTER,
127 /* Lm */ U_MODIFIER_LETTER,
128 /* Lo */ U_OTHER_LETTER,
129 /* Pc */ U_CONNECTOR_PUNCTUATION,
130 /* Pd */ U_DASH_PUNCTUATION,
131 /* Ps */ U_START_PUNCTUATION,
132 /* Pe */ U_END_PUNCTUATION,
133 /* Po */ U_OTHER_PUNCTUATION,
134 /* Sm */ U_MATH_SYMBOL,
135 /* Sc */ U_CURRENCY_SYMBOL,
136 /* Sk */ U_MODIFIER_SYMBOL,
137 /* So */ U_OTHER_SYMBOL,
138 /* Pi */ U_INITIAL_PUNCTUATION,
139 /* Pf */ U_FINAL_PUNCTUATION
140 };
141
142 static const char dirStrings[][5] = {
143 "L",
144 "R",
145 "EN",
146 "ES",
147 "ET",
148 "AN",
149 "CS",
150 "B",
151 "S",
152 "WS",
153 "ON",
154 "LRE",
155 "LRO",
156 "AL",
157 "RLE",
158 "RLO",
159 "PDF",
160 "NSM",
161 "BN",
162 /* new in Unicode 6.3/ICU 52 */
163 "FSI",
164 "LRI",
165 "RLI",
166 "PDI"
167 };
168
169 void addUnicodeTest(TestNode** root);
170
addUnicodeTest(TestNode ** root)171 void addUnicodeTest(TestNode** root)
172 {
173 addTest(root, &TestCodeUnit, "tsutil/cucdtst/TestCodeUnit");
174 addTest(root, &TestCodePoint, "tsutil/cucdtst/TestCodePoint");
175 addTest(root, &TestCharLength, "tsutil/cucdtst/TestCharLength");
176 addTest(root, &TestBinaryValues, "tsutil/cucdtst/TestBinaryValues");
177 addTest(root, &TestUnicodeData, "tsutil/cucdtst/TestUnicodeData");
178 addTest(root, &TestAdditionalProperties, "tsutil/cucdtst/TestAdditionalProperties");
179 addTest(root, &TestNumericProperties, "tsutil/cucdtst/TestNumericProperties");
180 addTest(root, &TestUpperLower, "tsutil/cucdtst/TestUpperLower");
181 addTest(root, &TestLetterNumber, "tsutil/cucdtst/TestLetterNumber");
182 addTest(root, &TestMisc, "tsutil/cucdtst/TestMisc");
183 addTest(root, &TestPOSIX, "tsutil/cucdtst/TestPOSIX");
184 addTest(root, &TestControlPrint, "tsutil/cucdtst/TestControlPrint");
185 addTest(root, &TestIdentifier, "tsutil/cucdtst/TestIdentifier");
186 addTest(root, &TestCharNames, "tsutil/cucdtst/TestCharNames");
187 addTest(root, &TestUCharFromNameUnderflow, "tsutil/cucdtst/TestUCharFromNameUnderflow");
188 addTest(root, &TestMirroring, "tsutil/cucdtst/TestMirroring");
189 addTest(root, &TestUScriptCodeAPI, "tsutil/cucdtst/TestUScriptCodeAPI");
190 addTest(root, &TestHasScript, "tsutil/cucdtst/TestHasScript");
191 addTest(root, &TestGetScriptExtensions, "tsutil/cucdtst/TestGetScriptExtensions");
192 addTest(root, &TestScriptMetadataAPI, "tsutil/cucdtst/TestScriptMetadataAPI");
193 addTest(root, &TestUScriptRunAPI, "tsutil/cucdtst/TestUScriptRunAPI");
194 addTest(root, &TestPropertyNames, "tsutil/cucdtst/TestPropertyNames");
195 addTest(root, &TestPropertyValues, "tsutil/cucdtst/TestPropertyValues");
196 addTest(root, &TestConsistency, "tsutil/cucdtst/TestConsistency");
197 addTest(root, &TestUCase, "tsutil/cucdtst/TestUCase");
198 addTest(root, &TestUBiDiProps, "tsutil/cucdtst/TestUBiDiProps");
199 addTest(root, &TestCaseFolding, "tsutil/cucdtst/TestCaseFolding");
200 }
201
202 /*==================================================== */
203 /* test u_toupper() and u_tolower() */
204 /*==================================================== */
TestUpperLower()205 static void TestUpperLower()
206 {
207 const UChar upper[] = {0x41, 0x42, 0x00b2, 0x01c4, 0x01c6, 0x01c9, 0x01c8, 0x01c9, 0x000c, 0x0000};
208 const UChar lower[] = {0x61, 0x62, 0x00b2, 0x01c6, 0x01c6, 0x01c9, 0x01c9, 0x01c9, 0x000c, 0x0000};
209 U_STRING_DECL(upperTest, "abcdefg123hij.?:klmno", 21);
210 U_STRING_DECL(lowerTest, "ABCDEFG123HIJ.?:KLMNO", 21);
211 int32_t i;
212
213 U_STRING_INIT(upperTest, "abcdefg123hij.?:klmno", 21);
214 U_STRING_INIT(lowerTest, "ABCDEFG123HIJ.?:KLMNO", 21);
215
216 /*
217 Checks LetterLike Symbols which were previously a source of confusion
218 [Bertrand A. D. 02/04/98]
219 */
220 for (i=0x2100;i<0x2138;i++)
221 {
222 /* Unicode 5.0 adds lowercase U+214E (TURNED SMALL F) to U+2132 (TURNED CAPITAL F) */
223 if(i!=0x2126 && i!=0x212a && i!=0x212b && i!=0x2132)
224 {
225 if (i != (int)u_tolower(i)) /* itself */
226 log_err("Failed case conversion with itself: U+%04x\n", i);
227 if (i != (int)u_toupper(i))
228 log_err("Failed case conversion with itself: U+%04x\n", i);
229 }
230 }
231
232 for(i=0; i < u_strlen(upper); i++){
233 if(u_tolower(upper[i]) != lower[i]){
234 log_err("FAILED u_tolower() for %lx Expected %lx Got %lx\n", upper[i], lower[i], u_tolower(upper[i]));
235 }
236 }
237
238 log_verbose("testing upper lower\n");
239 for (i = 0; i < 21; i++) {
240
241 if (u_isalpha(upperTest[i]) && !u_islower(upperTest[i]))
242 {
243 log_err("Failed isLowerCase test at %c\n", upperTest[i]);
244 }
245 else if (u_isalpha(lowerTest[i]) && !u_isupper(lowerTest[i]))
246 {
247 log_err("Failed isUpperCase test at %c\n", lowerTest[i]);
248 }
249 else if (upperTest[i] != u_tolower(lowerTest[i]))
250 {
251 log_err("Failed case conversion from %c To %c :\n", lowerTest[i], upperTest[i]);
252 }
253 else if (lowerTest[i] != u_toupper(upperTest[i]))
254 {
255 log_err("Failed case conversion : %c To %c \n", upperTest[i], lowerTest[i]);
256 }
257 else if (upperTest[i] != u_tolower(upperTest[i]))
258 {
259 log_err("Failed case conversion with itself: %c\n", upperTest[i]);
260 }
261 else if (lowerTest[i] != u_toupper(lowerTest[i]))
262 {
263 log_err("Failed case conversion with itself: %c\n", lowerTest[i]);
264 }
265 }
266 log_verbose("done testing upper lower\n");
267
268 log_verbose("testing u_istitle\n");
269 {
270 static const UChar expected[] = {
271 0x1F88,
272 0x1F89,
273 0x1F8A,
274 0x1F8B,
275 0x1F8C,
276 0x1F8D,
277 0x1F8E,
278 0x1F8F,
279 0x1F88,
280 0x1F89,
281 0x1F8A,
282 0x1F8B,
283 0x1F8C,
284 0x1F8D,
285 0x1F8E,
286 0x1F8F,
287 0x1F98,
288 0x1F99,
289 0x1F9A,
290 0x1F9B,
291 0x1F9C,
292 0x1F9D,
293 0x1F9E,
294 0x1F9F,
295 0x1F98,
296 0x1F99,
297 0x1F9A,
298 0x1F9B,
299 0x1F9C,
300 0x1F9D,
301 0x1F9E,
302 0x1F9F,
303 0x1FA8,
304 0x1FA9,
305 0x1FAA,
306 0x1FAB,
307 0x1FAC,
308 0x1FAD,
309 0x1FAE,
310 0x1FAF,
311 0x1FA8,
312 0x1FA9,
313 0x1FAA,
314 0x1FAB,
315 0x1FAC,
316 0x1FAD,
317 0x1FAE,
318 0x1FAF,
319 0x1FBC,
320 0x1FBC,
321 0x1FCC,
322 0x1FCC,
323 0x1FFC,
324 0x1FFC,
325 };
326 int32_t num = sizeof(expected)/sizeof(expected[0]);
327 for(i=0; i<num; i++){
328 if(!u_istitle(expected[i])){
329 log_err("u_istitle failed for 0x%4X. Expected TRUE, got FALSE\n",expected[i]);
330 }
331 }
332
333 }
334 }
335
336 /* compare two sets and verify that their difference or intersection is empty */
337 static UBool
showADiffB(const USet * a,const USet * b,const char * a_name,const char * b_name,UBool expect,UBool diffIsError)338 showADiffB(const USet *a, const USet *b,
339 const char *a_name, const char *b_name,
340 UBool expect, UBool diffIsError) {
341 USet *aa;
342 int32_t i, start, end, length;
343 UErrorCode errorCode;
344
345 /*
346 * expect:
347 * TRUE -> a-b should be empty, that is, b should contain all of a
348 * FALSE -> a&b should be empty, that is, a should contain none of b (and vice versa)
349 */
350 if(expect ? uset_containsAll(b, a) : uset_containsNone(a, b)) {
351 return TRUE;
352 }
353
354 /* clone a to aa because a is const */
355 aa=uset_open(1, 0);
356 if(aa==NULL) {
357 /* unusual problem - out of memory? */
358 return FALSE;
359 }
360 uset_addAll(aa, a);
361
362 /* compute the set in question */
363 if(expect) {
364 /* a-b */
365 uset_removeAll(aa, b);
366 } else {
367 /* a&b */
368 uset_retainAll(aa, b);
369 }
370
371 /* aa is not empty because of the initial tests above; show its contents */
372 errorCode=U_ZERO_ERROR;
373 i=0;
374 for(;;) {
375 length=uset_getItem(aa, i, &start, &end, NULL, 0, &errorCode);
376 if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) {
377 break; /* done */
378 }
379 if(U_FAILURE(errorCode)) {
380 log_err("error comparing %s with %s at difference item %d: %s\n",
381 a_name, b_name, i, u_errorName(errorCode));
382 break;
383 }
384 if(length!=0) {
385 break; /* done with code points, got a string or -1 */
386 }
387
388 if(diffIsError) {
389 if(expect) {
390 log_err("error: %s contains U+%04x..U+%04x but %s does not\n", a_name, start, end, b_name);
391 } else {
392 log_err("error: %s and %s both contain U+%04x..U+%04x but should not intersect\n", a_name, b_name, start, end);
393 }
394 } else {
395 if(expect) {
396 log_verbose("info: %s contains U+%04x..U+%04x but %s does not\n", a_name, start, end, b_name);
397 } else {
398 log_verbose("info: %s and %s both contain U+%04x..U+%04x but should not intersect\n", a_name, b_name, start, end);
399 }
400 }
401
402 ++i;
403 }
404
405 uset_close(aa);
406 return FALSE;
407 }
408
409 static UBool
showAMinusB(const USet * a,const USet * b,const char * a_name,const char * b_name,UBool diffIsError)410 showAMinusB(const USet *a, const USet *b,
411 const char *a_name, const char *b_name,
412 UBool diffIsError) {
413 return showADiffB(a, b, a_name, b_name, TRUE, diffIsError);
414 }
415
416 static UBool
showAIntersectB(const USet * a,const USet * b,const char * a_name,const char * b_name,UBool diffIsError)417 showAIntersectB(const USet *a, const USet *b,
418 const char *a_name, const char *b_name,
419 UBool diffIsError) {
420 return showADiffB(a, b, a_name, b_name, FALSE, diffIsError);
421 }
422
423 static UBool
compareUSets(const USet * a,const USet * b,const char * a_name,const char * b_name,UBool diffIsError)424 compareUSets(const USet *a, const USet *b,
425 const char *a_name, const char *b_name,
426 UBool diffIsError) {
427 /*
428 * Use an arithmetic & not a logical && so that both branches
429 * are always taken and all differences are shown.
430 */
431 return
432 showAMinusB(a, b, a_name, b_name, diffIsError) &
433 showAMinusB(b, a, b_name, a_name, diffIsError);
434 }
435
436 /* test isLetter(u_isapha()) and isDigit(u_isdigit()) */
TestLetterNumber()437 static void TestLetterNumber()
438 {
439 UChar i = 0x0000;
440
441 log_verbose("Testing for isalpha\n");
442 for (i = 0x0041; i < 0x005B; i++) {
443 if (!u_isalpha(i))
444 {
445 log_err("Failed isLetter test at %.4X\n", i);
446 }
447 }
448 for (i = 0x0660; i < 0x066A; i++) {
449 if (u_isalpha(i))
450 {
451 log_err("Failed isLetter test with numbers at %.4X\n", i);
452 }
453 }
454
455 log_verbose("Testing for isdigit\n");
456 for (i = 0x0660; i < 0x066A; i++) {
457 if (!u_isdigit(i))
458 {
459 log_verbose("Failed isNumber test at %.4X\n", i);
460 }
461 }
462
463 log_verbose("Testing for isalnum\n");
464 for (i = 0x0041; i < 0x005B; i++) {
465 if (!u_isalnum(i))
466 {
467 log_err("Failed isAlNum test at %.4X\n", i);
468 }
469 }
470 for (i = 0x0660; i < 0x066A; i++) {
471 if (!u_isalnum(i))
472 {
473 log_err("Failed isAlNum test at %.4X\n", i);
474 }
475 }
476
477 {
478 /*
479 * The following checks work only starting from Unicode 4.0.
480 * Check the version number here.
481 */
482 static UVersionInfo u401={ 4, 0, 1, 0 };
483 UVersionInfo version;
484 u_getUnicodeVersion(version);
485 if(version[0]<4 || 0==memcmp(version, u401, 4)) {
486 return;
487 }
488 }
489
490 {
491 /*
492 * Sanity check:
493 * Verify that exactly the digit characters have decimal digit values.
494 * This assumption is used in the implementation of u_digit()
495 * (which checks nt=de)
496 * compared with the parallel java.lang.Character.digit()
497 * (which checks Nd).
498 *
499 * This was not true in Unicode 3.2 and earlier.
500 * Unicode 4.0 fixed discrepancies.
501 * Unicode 4.0.1 re-introduced problems in this area due to an
502 * unintentionally incomplete last-minute change.
503 */
504 U_STRING_DECL(digitsPattern, "[:Nd:]", 6);
505 U_STRING_DECL(decimalValuesPattern, "[:Numeric_Type=Decimal:]", 24);
506
507 USet *digits, *decimalValues;
508 UErrorCode errorCode;
509
510 U_STRING_INIT(digitsPattern, "[:Nd:]", 6);
511 U_STRING_INIT(decimalValuesPattern, "[:Numeric_Type=Decimal:]", 24);
512 errorCode=U_ZERO_ERROR;
513 digits=uset_openPattern(digitsPattern, 6, &errorCode);
514 decimalValues=uset_openPattern(decimalValuesPattern, 24, &errorCode);
515
516 if(U_SUCCESS(errorCode)) {
517 compareUSets(digits, decimalValues, "[:Nd:]", "[:Numeric_Type=Decimal:]", TRUE);
518 }
519
520 uset_close(digits);
521 uset_close(decimalValues);
522 }
523 }
524
testSampleCharProps(UBool propFn (UChar32),const char * propName,const UChar32 * sampleChars,int32_t sampleCharsLength,UBool expected)525 static void testSampleCharProps(UBool propFn(UChar32), const char *propName,
526 const UChar32 *sampleChars, int32_t sampleCharsLength,
527 UBool expected) {
528 int32_t i;
529 for (i = 0; i < sampleCharsLength; ++i) {
530 UBool result = propFn(sampleChars[i]);
531 if (result != expected) {
532 log_err("error: character property function %s(U+%04x)=%d is wrong\n",
533 propName, sampleChars[i], result);
534 }
535 }
536 }
537
538 /* Tests for isDefined(u_isdefined)(, isBaseForm(u_isbase()), isSpaceChar(u_isspace()), isWhiteSpace(), u_CharDigitValue() */
TestMisc()539 static void TestMisc()
540 {
541 static const UChar32 sampleSpaces[] = {0x0020, 0x00a0, 0x2000, 0x2001, 0x2005};
542 static const UChar32 sampleNonSpaces[] = {0x61, 0x62, 0x63, 0x64, 0x74};
543 static const UChar32 sampleUndefined[] = {0xfff1, 0xfff7, 0xfa6e};
544 static const UChar32 sampleDefined[] = {0x523E, 0x4f88, 0xfffd};
545 static const UChar32 sampleBase[] = {0x0061, 0x0031, 0x03d2};
546 static const UChar32 sampleNonBase[] = {0x002B, 0x0020, 0x203B};
547 /* static const UChar sampleChars[] = {0x000a, 0x0045, 0x4e00, 0xDC00, 0xFFE8, 0xFFF0};*/
548 static const UChar32 sampleDigits[]= {0x0030, 0x0662, 0x0F23, 0x0ED5};
549 static const UChar32 sampleNonDigits[] = {0x0010, 0x0041, 0x0122, 0x68FE};
550 static const UChar32 sampleWhiteSpaces[] = {0x2008, 0x2009, 0x200a, 0x001c, 0x000c};
551 static const UChar32 sampleNonWhiteSpaces[] = {0x61, 0x62, 0x3c, 0x28, 0x3f, 0x85, 0x2007, 0xffef};
552
553 static const int32_t sampleDigitValues[] = {0, 2, 3, 5};
554
555 uint32_t mask;
556
557 int32_t i;
558 char icuVersion[U_MAX_VERSION_STRING_LENGTH];
559 UVersionInfo realVersion;
560
561 memset(icuVersion, 0, U_MAX_VERSION_STRING_LENGTH);
562
563 testSampleCharProps(u_isspace, "u_isspace", sampleSpaces, UPRV_LENGTHOF(sampleSpaces), TRUE);
564 testSampleCharProps(u_isspace, "u_isspace", sampleNonSpaces, UPRV_LENGTHOF(sampleNonSpaces), FALSE);
565
566 testSampleCharProps(u_isJavaSpaceChar, "u_isJavaSpaceChar",
567 sampleSpaces, UPRV_LENGTHOF(sampleSpaces), TRUE);
568 testSampleCharProps(u_isJavaSpaceChar, "u_isJavaSpaceChar",
569 sampleNonSpaces, UPRV_LENGTHOF(sampleNonSpaces), FALSE);
570
571 testSampleCharProps(u_isWhitespace, "u_isWhitespace",
572 sampleWhiteSpaces, UPRV_LENGTHOF(sampleWhiteSpaces), TRUE);
573 testSampleCharProps(u_isWhitespace, "u_isWhitespace",
574 sampleNonWhiteSpaces, UPRV_LENGTHOF(sampleNonWhiteSpaces), FALSE);
575
576 testSampleCharProps(u_isdefined, "u_isdefined",
577 sampleDefined, UPRV_LENGTHOF(sampleDefined), TRUE);
578 testSampleCharProps(u_isdefined, "u_isdefined",
579 sampleUndefined, UPRV_LENGTHOF(sampleUndefined), FALSE);
580
581 testSampleCharProps(u_isbase, "u_isbase", sampleBase, UPRV_LENGTHOF(sampleBase), TRUE);
582 testSampleCharProps(u_isbase, "u_isbase", sampleNonBase, UPRV_LENGTHOF(sampleNonBase), FALSE);
583
584 testSampleCharProps(u_isdigit, "u_isdigit", sampleDigits, UPRV_LENGTHOF(sampleDigits), TRUE);
585 testSampleCharProps(u_isdigit, "u_isdigit", sampleNonDigits, UPRV_LENGTHOF(sampleNonDigits), FALSE);
586
587 for (i = 0; i < UPRV_LENGTHOF(sampleDigits); i++) {
588 if (u_charDigitValue(sampleDigits[i]) != sampleDigitValues[i]) {
589 log_err("error: u_charDigitValue(U+04x)=%d != %d\n",
590 sampleDigits[i], u_charDigitValue(sampleDigits[i]), sampleDigitValues[i]);
591 }
592 }
593
594 /* Tests the ICU version #*/
595 u_getVersion(realVersion);
596 u_versionToString(realVersion, icuVersion);
597 if (strncmp(icuVersion, U_ICU_VERSION, uprv_min((int32_t)strlen(icuVersion), (int32_t)strlen(U_ICU_VERSION))) != 0)
598 {
599 log_err("ICU version test failed. Header says=%s, got=%s \n", U_ICU_VERSION, icuVersion);
600 }
601 #if defined(ICU_VERSION)
602 /* test only happens where we have configure.in with VERSION - sanity check. */
603 if(strcmp(U_ICU_VERSION, ICU_VERSION))
604 {
605 log_err("ICU version mismatch: Header says %s, build environment says %s.\n", U_ICU_VERSION, ICU_VERSION);
606 }
607 #endif
608
609 /* test U_GC_... */
610 if(
611 U_GET_GC_MASK(0x41)!=U_GC_LU_MASK ||
612 U_GET_GC_MASK(0x662)!=U_GC_ND_MASK ||
613 U_GET_GC_MASK(0xa0)!=U_GC_ZS_MASK ||
614 U_GET_GC_MASK(0x28)!=U_GC_PS_MASK ||
615 U_GET_GC_MASK(0x2044)!=U_GC_SM_MASK ||
616 U_GET_GC_MASK(0xe0063)!=U_GC_CF_MASK
617 ) {
618 log_err("error: U_GET_GC_MASK does not work properly\n");
619 }
620
621 mask=0;
622 mask=(mask&~U_GC_CN_MASK)|U_GC_CN_MASK;
623
624 mask=(mask&~U_GC_LU_MASK)|U_GC_LU_MASK;
625 mask=(mask&~U_GC_LL_MASK)|U_GC_LL_MASK;
626 mask=(mask&~U_GC_LT_MASK)|U_GC_LT_MASK;
627 mask=(mask&~U_GC_LM_MASK)|U_GC_LM_MASK;
628 mask=(mask&~U_GC_LO_MASK)|U_GC_LO_MASK;
629
630 mask=(mask&~U_GC_MN_MASK)|U_GC_MN_MASK;
631 mask=(mask&~U_GC_ME_MASK)|U_GC_ME_MASK;
632 mask=(mask&~U_GC_MC_MASK)|U_GC_MC_MASK;
633
634 mask=(mask&~U_GC_ND_MASK)|U_GC_ND_MASK;
635 mask=(mask&~U_GC_NL_MASK)|U_GC_NL_MASK;
636 mask=(mask&~U_GC_NO_MASK)|U_GC_NO_MASK;
637
638 mask=(mask&~U_GC_ZS_MASK)|U_GC_ZS_MASK;
639 mask=(mask&~U_GC_ZL_MASK)|U_GC_ZL_MASK;
640 mask=(mask&~U_GC_ZP_MASK)|U_GC_ZP_MASK;
641
642 mask=(mask&~U_GC_CC_MASK)|U_GC_CC_MASK;
643 mask=(mask&~U_GC_CF_MASK)|U_GC_CF_MASK;
644 mask=(mask&~U_GC_CO_MASK)|U_GC_CO_MASK;
645 mask=(mask&~U_GC_CS_MASK)|U_GC_CS_MASK;
646
647 mask=(mask&~U_GC_PD_MASK)|U_GC_PD_MASK;
648 mask=(mask&~U_GC_PS_MASK)|U_GC_PS_MASK;
649 mask=(mask&~U_GC_PE_MASK)|U_GC_PE_MASK;
650 mask=(mask&~U_GC_PC_MASK)|U_GC_PC_MASK;
651 mask=(mask&~U_GC_PO_MASK)|U_GC_PO_MASK;
652
653 mask=(mask&~U_GC_SM_MASK)|U_GC_SM_MASK;
654 mask=(mask&~U_GC_SC_MASK)|U_GC_SC_MASK;
655 mask=(mask&~U_GC_SK_MASK)|U_GC_SK_MASK;
656 mask=(mask&~U_GC_SO_MASK)|U_GC_SO_MASK;
657
658 mask=(mask&~U_GC_PI_MASK)|U_GC_PI_MASK;
659 mask=(mask&~U_GC_PF_MASK)|U_GC_PF_MASK;
660
661 if(mask!=(U_CHAR_CATEGORY_COUNT<32 ? U_MASK(U_CHAR_CATEGORY_COUNT)-1: 0xffffffff)) {
662 log_err("error: problems with U_GC_XX_MASK constants\n");
663 }
664
665 mask=0;
666 mask=(mask&~U_GC_C_MASK)|U_GC_C_MASK;
667 mask=(mask&~U_GC_L_MASK)|U_GC_L_MASK;
668 mask=(mask&~U_GC_M_MASK)|U_GC_M_MASK;
669 mask=(mask&~U_GC_N_MASK)|U_GC_N_MASK;
670 mask=(mask&~U_GC_Z_MASK)|U_GC_Z_MASK;
671 mask=(mask&~U_GC_P_MASK)|U_GC_P_MASK;
672 mask=(mask&~U_GC_S_MASK)|U_GC_S_MASK;
673
674 if(mask!=(U_CHAR_CATEGORY_COUNT<32 ? U_MASK(U_CHAR_CATEGORY_COUNT)-1: 0xffffffff)) {
675 log_err("error: problems with U_GC_Y_MASK constants\n");
676 }
677 {
678 static const UChar32 digit[10]={ 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039 };
679 for(i=0; i<10; i++){
680 if(digit[i]!=u_forDigit(i,10)){
681 log_err("u_forDigit failed for %i. Expected: 0x%4X Got: 0x%4X\n",i,digit[i],u_forDigit(i,10));
682 }
683 }
684 }
685
686 /* test u_digit() */
687 {
688 static const struct {
689 UChar32 c;
690 int8_t radix, value;
691 } data[]={
692 /* base 16 */
693 { 0x0031, 16, 1 },
694 { 0x0038, 16, 8 },
695 { 0x0043, 16, 12 },
696 { 0x0066, 16, 15 },
697 { 0x00e4, 16, -1 },
698 { 0x0662, 16, 2 },
699 { 0x06f5, 16, 5 },
700 { 0xff13, 16, 3 },
701 { 0xff41, 16, 10 },
702
703 /* base 8 */
704 { 0x0031, 8, 1 },
705 { 0x0038, 8, -1 },
706 { 0x0043, 8, -1 },
707 { 0x0066, 8, -1 },
708 { 0x00e4, 8, -1 },
709 { 0x0662, 8, 2 },
710 { 0x06f5, 8, 5 },
711 { 0xff13, 8, 3 },
712 { 0xff41, 8, -1 },
713
714 /* base 36 */
715 { 0x5a, 36, 35 },
716 { 0x7a, 36, 35 },
717 { 0xff3a, 36, 35 },
718 { 0xff5a, 36, 35 },
719
720 /* wrong radix values */
721 { 0x0031, 1, -1 },
722 { 0xff3a, 37, -1 }
723 };
724
725 for(i=0; i<UPRV_LENGTHOF(data); ++i) {
726 if(u_digit(data[i].c, data[i].radix)!=data[i].value) {
727 log_err("u_digit(U+%04x, %d)=%d expected %d\n",
728 data[i].c,
729 data[i].radix,
730 u_digit(data[i].c, data[i].radix),
731 data[i].value);
732 }
733 }
734 }
735 }
736
737 /* test C/POSIX-style functions --------------------------------------------- */
738
739 /* bit flags */
740 #define ISAL 1
741 #define ISLO 2
742 #define ISUP 4
743
744 #define ISDI 8
745 #define ISXD 0x10
746
747 #define ISAN 0x20
748
749 #define ISPU 0x40
750 #define ISGR 0x80
751 #define ISPR 0x100
752
753 #define ISSP 0x200
754 #define ISBL 0x400
755 #define ISCN 0x800
756
757 /* C/POSIX-style functions, in the same order as the bit flags */
758 typedef UBool U_EXPORT2 IsPOSIXClass(UChar32 c);
759
760 static const struct {
761 IsPOSIXClass *fn;
762 const char *name;
763 } posixClasses[]={
764 { u_isalpha, "isalpha" },
765 { u_islower, "islower" },
766 { u_isupper, "isupper" },
767 { u_isdigit, "isdigit" },
768 { u_isxdigit, "isxdigit" },
769 { u_isalnum, "isalnum" },
770 { u_ispunct, "ispunct" },
771 { u_isgraph, "isgraph" },
772 { u_isprint, "isprint" },
773 { u_isspace, "isspace" },
774 { u_isblank, "isblank" },
775 { u_iscntrl, "iscntrl" }
776 };
777
778 static const struct {
779 UChar32 c;
780 uint32_t posixResults;
781 } posixData[]={
782 { 0x0008, ISCN }, /* backspace */
783 { 0x0009, ISSP|ISBL|ISCN }, /* TAB */
784 { 0x000a, ISSP| ISCN }, /* LF */
785 { 0x000c, ISSP| ISCN }, /* FF */
786 { 0x000d, ISSP| ISCN }, /* CR */
787 { 0x0020, ISPR|ISSP|ISBL }, /* space */
788 { 0x0021, ISPU|ISGR|ISPR }, /* ! */
789 { 0x0033, ISDI|ISXD|ISAN| ISGR|ISPR }, /* 3 */
790 { 0x0040, ISPU|ISGR|ISPR }, /* @ */
791 { 0x0041, ISAL| ISUP| ISXD|ISAN| ISGR|ISPR }, /* A */
792 { 0x007a, ISAL|ISLO| ISAN| ISGR|ISPR }, /* z */
793 { 0x007b, ISPU|ISGR|ISPR }, /* { */
794 { 0x0085, ISSP| ISCN }, /* NEL */
795 { 0x00a0, ISPR|ISSP|ISBL }, /* NBSP */
796 { 0x00a4, ISGR|ISPR }, /* currency sign */
797 { 0x00e4, ISAL|ISLO| ISAN| ISGR|ISPR }, /* a-umlaut */
798 { 0x0300, ISGR|ISPR }, /* combining grave */
799 { 0x0600, ISCN }, /* arabic number sign */
800 { 0x0627, ISAL| ISAN| ISGR|ISPR }, /* alef */
801 { 0x0663, ISDI|ISXD|ISAN| ISGR|ISPR }, /* arabic 3 */
802 { 0x2002, ISPR|ISSP|ISBL }, /* en space */
803 { 0x2007, ISPR|ISSP|ISBL }, /* figure space */
804 { 0x2009, ISPR|ISSP|ISBL }, /* thin space */
805 { 0x200b, ISCN }, /* ZWSP */
806 /*{ 0x200b, ISPR|ISSP },*/ /* ZWSP */ /* ZWSP became a control char in 4.0.1*/
807 { 0x200e, ISCN }, /* LRM */
808 { 0x2028, ISPR|ISSP| ISCN }, /* LS */
809 { 0x2029, ISPR|ISSP| ISCN }, /* PS */
810 { 0x20ac, ISGR|ISPR }, /* Euro */
811 { 0xff15, ISDI|ISXD|ISAN| ISGR|ISPR }, /* fullwidth 5 */
812 { 0xff25, ISAL| ISUP| ISXD|ISAN| ISGR|ISPR }, /* fullwidth E */
813 { 0xff35, ISAL| ISUP| ISAN| ISGR|ISPR }, /* fullwidth U */
814 { 0xff45, ISAL|ISLO| ISXD|ISAN| ISGR|ISPR }, /* fullwidth e */
815 { 0xff55, ISAL|ISLO| ISAN| ISGR|ISPR } /* fullwidth u */
816 };
817
818 static void
TestPOSIX()819 TestPOSIX() {
820 uint32_t mask;
821 int32_t cl, i;
822 UBool expect;
823
824 mask=1;
825 for(cl=0; cl<12; ++cl) {
826 for(i=0; i<UPRV_LENGTHOF(posixData); ++i) {
827 expect=(UBool)((posixData[i].posixResults&mask)!=0);
828 if(posixClasses[cl].fn(posixData[i].c)!=expect) {
829 log_err("u_%s(U+%04x)=%s is wrong\n",
830 posixClasses[cl].name, posixData[i].c, expect ? "FALSE" : "TRUE");
831 }
832 }
833 mask<<=1;
834 }
835 }
836
837 /* Tests for isControl(u_iscntrl()) and isPrintable(u_isprint()) */
TestControlPrint()838 static void TestControlPrint()
839 {
840 const UChar32 sampleControl[] = {0x1b, 0x97, 0x82, 0x2028, 0x2029, 0x200c, 0x202b};
841 const UChar32 sampleNonControl[] = {0x61, 0x0031, 0x00e2};
842 const UChar32 samplePrintable[] = {0x0042, 0x005f, 0x2014};
843 const UChar32 sampleNonPrintable[] = {0x200c, 0x009f, 0x001b};
844 UChar32 c;
845
846 testSampleCharProps(u_iscntrl, "u_iscntrl", sampleControl, UPRV_LENGTHOF(sampleControl), TRUE);
847 testSampleCharProps(u_iscntrl, "u_iscntrl", sampleNonControl, UPRV_LENGTHOF(sampleNonControl), FALSE);
848
849 testSampleCharProps(u_isprint, "u_isprint",
850 samplePrintable, UPRV_LENGTHOF(samplePrintable), TRUE);
851 testSampleCharProps(u_isprint, "u_isprint",
852 sampleNonPrintable, UPRV_LENGTHOF(sampleNonPrintable), FALSE);
853
854 /* test all ISO 8 controls */
855 for(c=0; c<=0x9f; ++c) {
856 if(c==0x20) {
857 /* skip ASCII graphic characters and continue with DEL */
858 c=0x7f;
859 }
860 if(!u_iscntrl(c)) {
861 log_err("error: u_iscntrl(ISO 8 control U+%04x)=FALSE\n", c);
862 }
863 if(!u_isISOControl(c)) {
864 log_err("error: u_isISOControl(ISO 8 control U+%04x)=FALSE\n", c);
865 }
866 if(u_isprint(c)) {
867 log_err("error: u_isprint(ISO 8 control U+%04x)=TRUE\n", c);
868 }
869 }
870
871 /* test all Latin-1 graphic characters */
872 for(c=0x20; c<=0xff; ++c) {
873 if(c==0x7f) {
874 c=0xa0;
875 } else if(c==0xad) {
876 /* Unicode 4 changes 00AD Soft Hyphen to Cf (and it is in fact not printable) */
877 ++c;
878 }
879 if(!u_isprint(c)) {
880 log_err("error: u_isprint(Latin-1 graphic character U+%04x)=FALSE\n", c);
881 }
882 }
883 }
884
885 /* u_isJavaIDStart, u_isJavaIDPart, u_isIDStart(), u_isIDPart(), u_isIDIgnorable()*/
TestIdentifier()886 static void TestIdentifier()
887 {
888 const UChar32 sampleJavaIDStart[] = {0x0071, 0x00e4, 0x005f};
889 const UChar32 sampleNonJavaIDStart[] = {0x0020, 0x2030, 0x0082};
890 const UChar32 sampleJavaIDPart[] = {0x005f, 0x0032, 0x0045};
891 const UChar32 sampleNonJavaIDPart[] = {0x2030, 0x2020, 0x0020};
892 const UChar32 sampleUnicodeIDStart[] = {0x0250, 0x00e2, 0x0061};
893 const UChar32 sampleNonUnicodeIDStart[] = {0x2000, 0x000a, 0x2019};
894 const UChar32 sampleUnicodeIDPart[] = {0x005f, 0x0032, 0x0045};
895 const UChar32 sampleNonUnicodeIDPart[] = {0x2030, 0x00a3, 0x0020};
896 const UChar32 sampleIDIgnore[] = {0x0006, 0x0010, 0x206b, 0x85};
897 const UChar32 sampleNonIDIgnore[] = {0x0075, 0x00a3, 0x0061};
898
899 testSampleCharProps(u_isJavaIDStart, "u_isJavaIDStart",
900 sampleJavaIDStart, UPRV_LENGTHOF(sampleJavaIDStart), TRUE);
901 testSampleCharProps(u_isJavaIDStart, "u_isJavaIDStart",
902 sampleNonJavaIDStart, UPRV_LENGTHOF(sampleNonJavaIDStart), FALSE);
903
904 testSampleCharProps(u_isJavaIDPart, "u_isJavaIDPart",
905 sampleJavaIDPart, UPRV_LENGTHOF(sampleJavaIDPart), TRUE);
906 testSampleCharProps(u_isJavaIDPart, "u_isJavaIDPart",
907 sampleNonJavaIDPart, UPRV_LENGTHOF(sampleNonJavaIDPart), FALSE);
908
909 /* IDPart should imply IDStart */
910 testSampleCharProps(u_isJavaIDPart, "u_isJavaIDPart",
911 sampleJavaIDStart, UPRV_LENGTHOF(sampleJavaIDStart), TRUE);
912
913 testSampleCharProps(u_isIDStart, "u_isIDStart",
914 sampleUnicodeIDStart, UPRV_LENGTHOF(sampleUnicodeIDStart), TRUE);
915 testSampleCharProps(u_isIDStart, "u_isIDStart",
916 sampleNonUnicodeIDStart, UPRV_LENGTHOF(sampleNonUnicodeIDStart), FALSE);
917
918 testSampleCharProps(u_isIDPart, "u_isIDPart",
919 sampleUnicodeIDPart, UPRV_LENGTHOF(sampleUnicodeIDPart), TRUE);
920 testSampleCharProps(u_isIDPart, "u_isIDPart",
921 sampleNonUnicodeIDPart, UPRV_LENGTHOF(sampleNonUnicodeIDPart), FALSE);
922
923 /* IDPart should imply IDStart */
924 testSampleCharProps(u_isIDPart, "u_isIDPart",
925 sampleUnicodeIDStart, UPRV_LENGTHOF(sampleUnicodeIDStart), TRUE);
926
927 testSampleCharProps(u_isIDIgnorable, "u_isIDIgnorable",
928 sampleIDIgnore, UPRV_LENGTHOF(sampleIDIgnore), TRUE);
929 testSampleCharProps(u_isIDIgnorable, "u_isIDIgnorable",
930 sampleNonIDIgnore, UPRV_LENGTHOF(sampleNonIDIgnore), FALSE);
931 }
932
933 /* for each line of UnicodeData.txt, check some of the properties */
934 typedef struct UnicodeDataContext {
935 #if UCONFIG_NO_NORMALIZATION
936 const void *dummy;
937 #else
938 const UNormalizer2 *nfc;
939 const UNormalizer2 *nfkc;
940 #endif
941 } UnicodeDataContext;
942
943 /*
944 * ### TODO
945 * This test fails incorrectly if the First or Last code point of a repetitive area
946 * is overridden, which is allowed and is encouraged for the PUAs.
947 * Currently, this means that both area First/Last and override lines are
948 * tested against the properties from the API,
949 * and the area boundary will not match and cause an error.
950 *
951 * This function should detect area boundaries and skip them for the test of individual
952 * code points' properties.
953 * Then it should check that the areas contain all the same properties except where overridden.
954 * For this, it would have had to set a flag for which code points were listed explicitly.
955 */
956 static void U_CALLCONV
unicodeDataLineFn(void * context,char * fields[][2],int32_t fieldCount,UErrorCode * pErrorCode)957 unicodeDataLineFn(void *context,
958 char *fields[][2], int32_t fieldCount,
959 UErrorCode *pErrorCode)
960 {
961 char buffer[100];
962 const char *d;
963 char *end;
964 uint32_t value;
965 UChar32 c;
966 int32_t i;
967 int8_t type;
968 int32_t dt;
969 UChar dm[32], s[32];
970 int32_t dmLength, length;
971
972 #if !UCONFIG_NO_NORMALIZATION
973 const UNormalizer2 *nfc, *nfkc;
974 #endif
975
976 /* get the character code, field 0 */
977 c=strtoul(fields[0][0], &end, 16);
978 if(end<=fields[0][0] || end!=fields[0][1]) {
979 log_err("error: syntax error in field 0 at %s\n", fields[0][0]);
980 return;
981 }
982 if((uint32_t)c>=UCHAR_MAX_VALUE + 1) {
983 log_err("error in UnicodeData.txt: code point %lu out of range\n", c);
984 return;
985 }
986
987 /* get general category, field 2 */
988 *fields[2][1]=0;
989 type = (int8_t)tagValues[MakeProp(fields[2][0])];
990 if(u_charType(c)!=type) {
991 log_err("error: u_charType(U+%04lx)==%u instead of %u\n", c, u_charType(c), type);
992 }
993 if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) {
994 log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c);
995 }
996
997 /* get canonical combining class, field 3 */
998 value=strtoul(fields[3][0], &end, 10);
999 if(end<=fields[3][0] || end!=fields[3][1]) {
1000 log_err("error: syntax error in field 3 at code 0x%lx\n", c);
1001 return;
1002 }
1003 if(value>255) {
1004 log_err("error in UnicodeData.txt: combining class %lu out of range\n", value);
1005 return;
1006 }
1007 #if !UCONFIG_NO_NORMALIZATION
1008 if(value!=u_getCombiningClass(c) || value!=(uint32_t)u_getIntPropertyValue(c, UCHAR_CANONICAL_COMBINING_CLASS)) {
1009 log_err("error: u_getCombiningClass(U+%04lx)==%hu instead of %lu\n", c, u_getCombiningClass(c), value);
1010 }
1011 nfkc=((UnicodeDataContext *)context)->nfkc;
1012 if(value!=unorm2_getCombiningClass(nfkc, c)) {
1013 log_err("error: unorm2_getCombiningClass(nfkc, U+%04lx)==%hu instead of %lu\n", c, unorm2_getCombiningClass(nfkc, c), value);
1014 }
1015 #endif
1016
1017 /* get BiDi category, field 4 */
1018 *fields[4][1]=0;
1019 i=MakeDir(fields[4][0]);
1020 if(i!=u_charDirection(c) || i!=u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)) {
1021 log_err("error: u_charDirection(U+%04lx)==%u instead of %u (%s)\n", c, u_charDirection(c), MakeDir(fields[4][0]), fields[4][0]);
1022 }
1023
1024 /* get Decomposition_Type & Decomposition_Mapping, field 5 */
1025 d=NULL;
1026 if(fields[5][0]==fields[5][1]) {
1027 /* no decomposition, except UnicodeData.txt omits Hangul syllable decompositions */
1028 if(c==0xac00 || c==0xd7a3) {
1029 dt=U_DT_CANONICAL;
1030 } else {
1031 dt=U_DT_NONE;
1032 }
1033 } else {
1034 d=fields[5][0];
1035 *fields[5][1]=0;
1036 dt=UCHAR_INVALID_CODE;
1037 if(*d=='<') {
1038 end=strchr(++d, '>');
1039 if(end!=NULL) {
1040 *end=0;
1041 dt=u_getPropertyValueEnum(UCHAR_DECOMPOSITION_TYPE, d);
1042 d=u_skipWhitespace(end+1);
1043 }
1044 } else {
1045 dt=U_DT_CANONICAL;
1046 }
1047 }
1048 if(dt>U_DT_NONE) {
1049 if(c==0xac00) {
1050 dm[0]=0x1100;
1051 dm[1]=0x1161;
1052 dm[2]=0;
1053 dmLength=2;
1054 } else if(c==0xd7a3) {
1055 dm[0]=0xd788;
1056 dm[1]=0x11c2;
1057 dm[2]=0;
1058 dmLength=2;
1059 } else {
1060 dmLength=u_parseString(d, dm, 32, NULL, pErrorCode);
1061 }
1062 } else {
1063 dmLength=-1;
1064 }
1065 if(dt<0 || U_FAILURE(*pErrorCode)) {
1066 log_err("error in UnicodeData.txt: syntax error in U+%04lX decomposition field\n", (long)c);
1067 return;
1068 }
1069 #if !UCONFIG_NO_NORMALIZATION
1070 i=u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE);
1071 if(i!=dt) {
1072 log_err("error: u_getIntPropertyValue(U+%04lx, UCHAR_DECOMPOSITION_TYPE)==%d instead of %d\n", c, i, dt);
1073 }
1074 /* Expect Decomposition_Mapping=nfkc.getRawDecomposition(c). */
1075 length=unorm2_getRawDecomposition(nfkc, c, s, 32, pErrorCode);
1076 if(U_FAILURE(*pErrorCode) || length!=dmLength || (length>0 && 0!=u_strcmp(s, dm))) {
1077 log_err("error: unorm2_getRawDecomposition(nfkc, U+%04lx)==%d instead of %d "
1078 "or the Decomposition_Mapping is different (%s)\n",
1079 c, length, dmLength, u_errorName(*pErrorCode));
1080 return;
1081 }
1082 /* For canonical decompositions only, expect Decomposition_Mapping=nfc.getRawDecomposition(c). */
1083 if(dt!=U_DT_CANONICAL) {
1084 dmLength=-1;
1085 }
1086 nfc=((UnicodeDataContext *)context)->nfc;
1087 length=unorm2_getRawDecomposition(nfc, c, s, 32, pErrorCode);
1088 if(U_FAILURE(*pErrorCode) || length!=dmLength || (length>0 && 0!=u_strcmp(s, dm))) {
1089 log_err("error: unorm2_getRawDecomposition(nfc, U+%04lx)==%d instead of %d "
1090 "or the Decomposition_Mapping is different (%s)\n",
1091 c, length, dmLength, u_errorName(*pErrorCode));
1092 return;
1093 }
1094 /* recompose */
1095 if(dt==U_DT_CANONICAL && !u_hasBinaryProperty(c, UCHAR_FULL_COMPOSITION_EXCLUSION)) {
1096 UChar32 a, b, composite;
1097 i=0;
1098 U16_NEXT(dm, i, dmLength, a);
1099 U16_NEXT(dm, i, dmLength, b);
1100 /* i==dmLength */
1101 composite=unorm2_composePair(nfc, a, b);
1102 if(composite!=c) {
1103 log_err("error: nfc U+%04lX decomposes to U+%04lX+U+%04lX but does not compose back (instead U+%04lX)\n",
1104 (long)c, (long)a, (long)b, (long)composite);
1105 }
1106 /*
1107 * Note: NFKC has fewer round-trip mappings than NFC,
1108 * so we can't just test unorm2_composePair(nfkc, a, b) here without further data.
1109 */
1110 }
1111 #endif
1112
1113 /* get ISO Comment, field 11 */
1114 *fields[11][1]=0;
1115 i=u_getISOComment(c, buffer, sizeof(buffer), pErrorCode);
1116 if(U_FAILURE(*pErrorCode) || 0!=strcmp(fields[11][0], buffer)) {
1117 log_err_status(*pErrorCode, "error: u_getISOComment(U+%04lx) wrong (%s): \"%s\" should be \"%s\"\n",
1118 c, u_errorName(*pErrorCode),
1119 U_FAILURE(*pErrorCode) ? buffer : "[error]",
1120 fields[11][0]);
1121 }
1122
1123 /* get uppercase mapping, field 12 */
1124 if(fields[12][0]!=fields[12][1]) {
1125 value=strtoul(fields[12][0], &end, 16);
1126 if(end!=fields[12][1]) {
1127 log_err("error: syntax error in field 12 at code 0x%lx\n", c);
1128 return;
1129 }
1130 if((UChar32)value!=u_toupper(c)) {
1131 log_err("error: u_toupper(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_toupper(c), value);
1132 }
1133 } else {
1134 /* no case mapping: the API must map the code point to itself */
1135 if(c!=u_toupper(c)) {
1136 log_err("error: U+%04lx does not have an uppercase mapping but u_toupper()==U+%04lx\n", c, u_toupper(c));
1137 }
1138 }
1139
1140 /* get lowercase mapping, field 13 */
1141 if(fields[13][0]!=fields[13][1]) {
1142 value=strtoul(fields[13][0], &end, 16);
1143 if(end!=fields[13][1]) {
1144 log_err("error: syntax error in field 13 at code 0x%lx\n", c);
1145 return;
1146 }
1147 if((UChar32)value!=u_tolower(c)) {
1148 log_err("error: u_tolower(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_tolower(c), value);
1149 }
1150 } else {
1151 /* no case mapping: the API must map the code point to itself */
1152 if(c!=u_tolower(c)) {
1153 log_err("error: U+%04lx does not have a lowercase mapping but u_tolower()==U+%04lx\n", c, u_tolower(c));
1154 }
1155 }
1156
1157 /* get titlecase mapping, field 14 */
1158 if(fields[14][0]!=fields[14][1]) {
1159 value=strtoul(fields[14][0], &end, 16);
1160 if(end!=fields[14][1]) {
1161 log_err("error: syntax error in field 14 at code 0x%lx\n", c);
1162 return;
1163 }
1164 if((UChar32)value!=u_totitle(c)) {
1165 log_err("error: u_totitle(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_totitle(c), value);
1166 }
1167 } else {
1168 /* no case mapping: the API must map the code point to itself */
1169 if(c!=u_totitle(c)) {
1170 log_err("error: U+%04lx does not have a titlecase mapping but u_totitle()==U+%04lx\n", c, u_totitle(c));
1171 }
1172 }
1173 }
1174
1175 static UBool U_CALLCONV
enumTypeRange(const void * context,UChar32 start,UChar32 limit,UCharCategory type)1176 enumTypeRange(const void *context, UChar32 start, UChar32 limit, UCharCategory type) {
1177 static const UChar32 test[][2]={
1178 {0x41, U_UPPERCASE_LETTER},
1179 {0x308, U_NON_SPACING_MARK},
1180 {0xfffe, U_GENERAL_OTHER_TYPES},
1181 {0xe0041, U_FORMAT_CHAR},
1182 {0xeffff, U_UNASSIGNED}
1183 };
1184
1185 int32_t i, count;
1186
1187 if(0!=strcmp((const char *)context, "a1")) {
1188 log_err("error: u_enumCharTypes() passes on an incorrect context pointer\n");
1189 return FALSE;
1190 }
1191
1192 count=UPRV_LENGTHOF(test);
1193 for(i=0; i<count; ++i) {
1194 if(start<=test[i][0] && test[i][0]<limit) {
1195 if(type!=(UCharCategory)test[i][1]) {
1196 log_err("error: u_enumCharTypes() has range [U+%04lx, U+%04lx[ with %ld instead of U+%04lx with %ld\n",
1197 start, limit, (long)type, test[i][0], test[i][1]);
1198 }
1199 /* stop at the range that includes the last test code point (increases code coverage for enumeration) */
1200 return i==(count-1) ? FALSE : TRUE;
1201 }
1202 }
1203
1204 if(start>test[count-1][0]) {
1205 log_err("error: u_enumCharTypes() has range [U+%04lx, U+%04lx[ with %ld after it should have stopped\n",
1206 start, limit, (long)type);
1207 return FALSE;
1208 }
1209
1210 return TRUE;
1211 }
1212
1213 static UBool U_CALLCONV
enumDefaultsRange(const void * context,UChar32 start,UChar32 limit,UCharCategory type)1214 enumDefaultsRange(const void *context, UChar32 start, UChar32 limit, UCharCategory type) {
1215 /* default Bidi classes for unassigned code points, from the DerivedBidiClass.txt header */
1216 static const int32_t defaultBidi[][2]={ /* { limit, class } */
1217 { 0x0590, U_LEFT_TO_RIGHT },
1218 { 0x0600, U_RIGHT_TO_LEFT },
1219 { 0x07C0, U_RIGHT_TO_LEFT_ARABIC },
1220 { 0x08A0, U_RIGHT_TO_LEFT },
1221 { 0x0900, U_RIGHT_TO_LEFT_ARABIC }, /* Unicode 6.1 changes U+08A0..U+08FF from R to AL */
1222 { 0x20A0, U_LEFT_TO_RIGHT },
1223 { 0x20D0, U_EUROPEAN_NUMBER_TERMINATOR }, /* Unicode 6.3 changes the currency symbols block U+20A0..U+20CF to default to ET not L */
1224 { 0xFB1D, U_LEFT_TO_RIGHT },
1225 { 0xFB50, U_RIGHT_TO_LEFT },
1226 { 0xFE00, U_RIGHT_TO_LEFT_ARABIC },
1227 { 0xFE70, U_LEFT_TO_RIGHT },
1228 { 0xFF00, U_RIGHT_TO_LEFT_ARABIC },
1229 { 0x10800, U_LEFT_TO_RIGHT },
1230 { 0x11000, U_RIGHT_TO_LEFT },
1231 { 0x1E800, U_LEFT_TO_RIGHT }, /* new default-R range in Unicode 5.2: U+1E800 - U+1EFFF */
1232 { 0x1EE00, U_RIGHT_TO_LEFT },
1233 { 0x1EF00, U_RIGHT_TO_LEFT_ARABIC }, /* Unicode 6.1 changes U+1EE00..U+1EEFF from R to AL */
1234 { 0x1F000, U_RIGHT_TO_LEFT },
1235 { 0x110000, U_LEFT_TO_RIGHT }
1236 };
1237
1238 UChar32 c;
1239 int32_t i;
1240 UCharDirection shouldBeDir;
1241
1242 /*
1243 * LineBreak.txt specifies:
1244 * # - Assigned characters that are not listed explicitly are given the value
1245 * # "AL".
1246 * # - Unassigned characters are given the value "XX".
1247 *
1248 * PUA characters are listed explicitly with "XX".
1249 * Verify that no assigned character has "XX".
1250 */
1251 if(type!=U_UNASSIGNED && type!=U_PRIVATE_USE_CHAR) {
1252 c=start;
1253 while(c<limit) {
1254 if(0==u_getIntPropertyValue(c, UCHAR_LINE_BREAK)) {
1255 log_err("error UCHAR_LINE_BREAK(assigned U+%04lx)=XX\n", c);
1256 }
1257 ++c;
1258 }
1259 }
1260
1261 /*
1262 * Verify default Bidi classes.
1263 * For recent Unicode versions, see UCD.html.
1264 *
1265 * For older Unicode versions:
1266 * See table 3-7 "Bidirectional Character Types" in UAX #9.
1267 * http://www.unicode.org/reports/tr9/
1268 *
1269 * See also DerivedBidiClass.txt for Cn code points!
1270 *
1271 * Unicode 4.0.1/Public Review Issue #28 (http://www.unicode.org/review/resolved-pri.html)
1272 * changed some default values.
1273 * In particular, non-characters and unassigned Default Ignorable Code Points
1274 * change from L to BN.
1275 *
1276 * UCD.html version 4.0.1 does not yet reflect these changes.
1277 */
1278 if(type==U_UNASSIGNED || type==U_PRIVATE_USE_CHAR) {
1279 /* enumerate the intersections of defaultBidi ranges with [start..limit[ */
1280 c=start;
1281 for(i=0; i<UPRV_LENGTHOF(defaultBidi) && c<limit; ++i) {
1282 if((int32_t)c<defaultBidi[i][0]) {
1283 while(c<limit && (int32_t)c<defaultBidi[i][0]) {
1284 if(U_IS_UNICODE_NONCHAR(c) || u_hasBinaryProperty(c, UCHAR_DEFAULT_IGNORABLE_CODE_POINT)) {
1285 shouldBeDir=U_BOUNDARY_NEUTRAL;
1286 } else {
1287 shouldBeDir=(UCharDirection)defaultBidi[i][1];
1288 }
1289
1290 if( u_charDirection(c)!=shouldBeDir ||
1291 u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)!=shouldBeDir
1292 ) {
1293 log_err("error: u_charDirection(unassigned/PUA U+%04lx)=%s should be %s\n",
1294 c, dirStrings[u_charDirection(c)], dirStrings[shouldBeDir]);
1295 }
1296 ++c;
1297 }
1298 }
1299 }
1300 }
1301
1302 return TRUE;
1303 }
1304
1305 /* tests for several properties */
TestUnicodeData()1306 static void TestUnicodeData()
1307 {
1308 UVersionInfo expectVersionArray;
1309 UVersionInfo versionArray;
1310 char *fields[15][2];
1311 UErrorCode errorCode;
1312 UChar32 c;
1313 int8_t type;
1314
1315 UnicodeDataContext context;
1316
1317 u_versionFromString(expectVersionArray, U_UNICODE_VERSION);
1318 u_getUnicodeVersion(versionArray);
1319 if(memcmp(versionArray, expectVersionArray, U_MAX_VERSION_LENGTH) != 0)
1320 {
1321 log_err("Testing u_getUnicodeVersion() - expected " U_UNICODE_VERSION " got %d.%d.%d.%d\n",
1322 versionArray[0], versionArray[1], versionArray[2], versionArray[3]);
1323 }
1324
1325 #if defined(ICU_UNICODE_VERSION)
1326 /* test only happens where we have configure.in with UNICODE_VERSION - sanity check. */
1327 if(strcmp(U_UNICODE_VERSION, ICU_UNICODE_VERSION))
1328 {
1329 log_err("Testing configure.in's ICU_UNICODE_VERSION - expected " U_UNICODE_VERSION " got " ICU_UNICODE_VERSION "\n");
1330 }
1331 #endif
1332
1333 if (ublock_getCode((UChar)0x0041) != UBLOCK_BASIC_LATIN || u_getIntPropertyValue(0x41, UCHAR_BLOCK)!=(int32_t)UBLOCK_BASIC_LATIN) {
1334 log_err("ublock_getCode(U+0041) property failed! Expected : %i Got: %i \n", UBLOCK_BASIC_LATIN,ublock_getCode((UChar)0x0041));
1335 }
1336
1337 errorCode=U_ZERO_ERROR;
1338 #if !UCONFIG_NO_NORMALIZATION
1339 context.nfc=unorm2_getNFCInstance(&errorCode);
1340 context.nfkc=unorm2_getNFKCInstance(&errorCode);
1341 if(U_FAILURE(errorCode)) {
1342 log_data_err("error: unable to open an NFC or NFKC UNormalizer2 - %s\n", u_errorName(errorCode));
1343 return;
1344 }
1345 #endif
1346 parseUCDFile("UnicodeData.txt", fields, 15, unicodeDataLineFn, &context, &errorCode);
1347 if(U_FAILURE(errorCode)) {
1348 return; /* if we couldn't parse UnicodeData.txt, we should return */
1349 }
1350
1351 /* sanity check on repeated properties */
1352 for(c=0xfffe; c<=0x10ffff;) {
1353 type=u_charType(c);
1354 if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) {
1355 log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c);
1356 }
1357 if(type!=U_UNASSIGNED) {
1358 log_err("error: u_charType(U+%04lx)!=U_UNASSIGNED (returns %d)\n", c, u_charType(c));
1359 }
1360 if((c&0xffff)==0xfffe) {
1361 ++c;
1362 } else {
1363 c+=0xffff;
1364 }
1365 }
1366
1367 /* test that PUA is not "unassigned" */
1368 for(c=0xe000; c<=0x10fffd;) {
1369 type=u_charType(c);
1370 if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) {
1371 log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c);
1372 }
1373 if(type==U_UNASSIGNED) {
1374 log_err("error: u_charType(U+%04lx)==U_UNASSIGNED\n", c);
1375 } else if(type!=U_PRIVATE_USE_CHAR) {
1376 log_verbose("PUA override: u_charType(U+%04lx)=%d\n", c, type);
1377 }
1378 if(c==0xf8ff) {
1379 c=0xf0000;
1380 } else if(c==0xffffd) {
1381 c=0x100000;
1382 } else {
1383 ++c;
1384 }
1385 }
1386
1387 /* test u_enumCharTypes() */
1388 u_enumCharTypes(enumTypeRange, "a1");
1389
1390 /* check default properties */
1391 u_enumCharTypes(enumDefaultsRange, NULL);
1392 }
1393
TestCodeUnit()1394 static void TestCodeUnit(){
1395 const UChar codeunit[]={0x0000,0xe065,0x20ac,0xd7ff,0xd800,0xd841,0xd905,0xdbff,0xdc00,0xdc02,0xddee,0xdfff,0};
1396
1397 int32_t i;
1398
1399 for(i=0; i<(int32_t)(sizeof(codeunit)/sizeof(codeunit[0])); i++){
1400 UChar c=codeunit[i];
1401 if(i<4){
1402 if(!(UTF_IS_SINGLE(c)) || (UTF_IS_LEAD(c)) || (UTF_IS_TRAIL(c)) ||(UTF_IS_SURROGATE(c))){
1403 log_err("ERROR: U+%04x is a single", c);
1404 }
1405
1406 }
1407 if(i >= 4 && i< 8){
1408 if(!(UTF_IS_LEAD(c)) || UTF_IS_SINGLE(c) || UTF_IS_TRAIL(c) || !(UTF_IS_SURROGATE(c))){
1409 log_err("ERROR: U+%04x is a first surrogate", c);
1410 }
1411 }
1412 if(i >= 8 && i< 12){
1413 if(!(UTF_IS_TRAIL(c)) || UTF_IS_SINGLE(c) || UTF_IS_LEAD(c) || !(UTF_IS_SURROGATE(c))){
1414 log_err("ERROR: U+%04x is a second surrogate", c);
1415 }
1416 }
1417 }
1418
1419 }
1420
TestCodePoint()1421 static void TestCodePoint(){
1422 const UChar32 codePoint[]={
1423 /*surrogate, notvalid(codepoint), not a UnicodeChar, not Error */
1424 0xd800,
1425 0xdbff,
1426 0xdc00,
1427 0xdfff,
1428 0xdc04,
1429 0xd821,
1430 /*not a surrogate, valid, isUnicodeChar , not Error*/
1431 0x20ac,
1432 0xd7ff,
1433 0xe000,
1434 0xe123,
1435 0x0061,
1436 0xe065,
1437 0x20402,
1438 0x24506,
1439 0x23456,
1440 0x20402,
1441 0x10402,
1442 0x23456,
1443 /*not a surrogate, not valid, isUnicodeChar, isError */
1444 0x0015,
1445 0x009f,
1446 /*not a surrogate, not valid, not isUnicodeChar, isError */
1447 0xffff,
1448 0xfffe,
1449 };
1450 int32_t i;
1451 for(i=0; i<(int32_t)(sizeof(codePoint)/sizeof(codePoint[0])); i++){
1452 UChar32 c=codePoint[i];
1453 if(i<6){
1454 if(!UTF_IS_SURROGATE(c) || !U_IS_SURROGATE(c) || !U16_IS_SURROGATE(c)){
1455 log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
1456 }
1457 if(UTF_IS_VALID(c)){
1458 log_err("ERROR: isValid() failed for U+%04x\n", c);
1459 }
1460 if(UTF_IS_UNICODE_CHAR(c) || U_IS_UNICODE_CHAR(c)){
1461 log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
1462 }
1463 if(UTF_IS_ERROR(c)){
1464 log_err("ERROR: isError() failed for U+%04x\n", c);
1465 }
1466 }else if(i >=6 && i<18){
1467 if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){
1468 log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
1469 }
1470 if(!UTF_IS_VALID(c)){
1471 log_err("ERROR: isValid() failed for U+%04x\n", c);
1472 }
1473 if(!UTF_IS_UNICODE_CHAR(c) || !U_IS_UNICODE_CHAR(c)){
1474 log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
1475 }
1476 if(UTF_IS_ERROR(c)){
1477 log_err("ERROR: isError() failed for U+%04x\n", c);
1478 }
1479 }else if(i >=18 && i<20){
1480 if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){
1481 log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
1482 }
1483 if(UTF_IS_VALID(c)){
1484 log_err("ERROR: isValid() failed for U+%04x\n", c);
1485 }
1486 if(!UTF_IS_UNICODE_CHAR(c) || !U_IS_UNICODE_CHAR(c)){
1487 log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
1488 }
1489 if(!UTF_IS_ERROR(c)){
1490 log_err("ERROR: isError() failed for U+%04x\n", c);
1491 }
1492 }
1493 else if(i >=18 && i<(int32_t)(sizeof(codePoint)/sizeof(codePoint[0]))){
1494 if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){
1495 log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
1496 }
1497 if(UTF_IS_VALID(c)){
1498 log_err("ERROR: isValid() failed for U+%04x\n", c);
1499 }
1500 if(UTF_IS_UNICODE_CHAR(c) || U_IS_UNICODE_CHAR(c)){
1501 log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
1502 }
1503 if(!UTF_IS_ERROR(c)){
1504 log_err("ERROR: isError() failed for U+%04x\n", c);
1505 }
1506 }
1507 }
1508
1509 if(
1510 !U_IS_BMP(0) || !U_IS_BMP(0x61) || !U_IS_BMP(0x20ac) ||
1511 !U_IS_BMP(0xd9da) || !U_IS_BMP(0xdfed) || !U_IS_BMP(0xffff) ||
1512 U_IS_BMP(U_SENTINEL) || U_IS_BMP(0x10000) || U_IS_BMP(0x50005) ||
1513 U_IS_BMP(0x10ffff) || U_IS_BMP(0x110000) || U_IS_BMP(0x7fffffff)
1514 ) {
1515 log_err("error with U_IS_BMP()\n");
1516 }
1517
1518 if(
1519 U_IS_SUPPLEMENTARY(0) || U_IS_SUPPLEMENTARY(0x61) || U_IS_SUPPLEMENTARY(0x20ac) ||
1520 U_IS_SUPPLEMENTARY(0xd9da) || U_IS_SUPPLEMENTARY(0xdfed) || U_IS_SUPPLEMENTARY(0xffff) ||
1521 U_IS_SUPPLEMENTARY(U_SENTINEL) || !U_IS_SUPPLEMENTARY(0x10000) || !U_IS_SUPPLEMENTARY(0x50005) ||
1522 !U_IS_SUPPLEMENTARY(0x10ffff) || U_IS_SUPPLEMENTARY(0x110000) || U_IS_SUPPLEMENTARY(0x7fffffff)
1523 ) {
1524 log_err("error with U_IS_SUPPLEMENTARY()\n");
1525 }
1526 }
1527
TestCharLength()1528 static void TestCharLength()
1529 {
1530 const int32_t codepoint[]={
1531 1, 0x0061,
1532 1, 0xe065,
1533 1, 0x20ac,
1534 2, 0x20402,
1535 2, 0x23456,
1536 2, 0x24506,
1537 2, 0x20402,
1538 2, 0x10402,
1539 1, 0xd7ff,
1540 1, 0xe000
1541 };
1542
1543 int32_t i;
1544 UBool multiple;
1545 for(i=0; i<(int32_t)(sizeof(codepoint)/sizeof(codepoint[0])); i=(int16_t)(i+2)){
1546 UChar32 c=codepoint[i+1];
1547 if(UTF_CHAR_LENGTH(c) != codepoint[i] || U16_LENGTH(c) != codepoint[i]){
1548 log_err("The no: of code units for U+%04x:- Expected: %d Got: %d\n", c, codepoint[i], U16_LENGTH(c));
1549 }
1550 multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE);
1551 if(UTF_NEED_MULTIPLE_UCHAR(c) != multiple){
1552 log_err("ERROR: Unicode::needMultipleUChar() failed for U+%04x\n", c);
1553 }
1554 }
1555 }
1556
1557 /*internal functions ----*/
MakeProp(char * str)1558 static int32_t MakeProp(char* str)
1559 {
1560 int32_t result = 0;
1561 char* matchPosition =0;
1562
1563 matchPosition = strstr(tagStrings, str);
1564 if (matchPosition == 0)
1565 {
1566 log_err("unrecognized type letter ");
1567 log_err(str);
1568 }
1569 else
1570 result = (int32_t)((matchPosition - tagStrings) / 2);
1571 return result;
1572 }
1573
MakeDir(char * str)1574 static int32_t MakeDir(char* str)
1575 {
1576 int32_t pos = 0;
1577 for (pos = 0; pos < U_CHAR_DIRECTION_COUNT; pos++) {
1578 if (strcmp(str, dirStrings[pos]) == 0) {
1579 return pos;
1580 }
1581 }
1582 return -1;
1583 }
1584
1585 /* test u_charName() -------------------------------------------------------- */
1586
1587 static const struct {
1588 uint32_t code;
1589 const char *name, *oldName, *extName, *alias;
1590 } names[]={
1591 {0x0061, "LATIN SMALL LETTER A", "", "LATIN SMALL LETTER A"},
1592 {0x01a2, "LATIN CAPITAL LETTER OI", "",
1593 "LATIN CAPITAL LETTER OI",
1594 "LATIN CAPITAL LETTER GHA"},
1595 {0x0284, "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK", "",
1596 "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK" },
1597 {0x0fd0, "TIBETAN MARK BSKA- SHOG GI MGO RGYAN", "",
1598 "TIBETAN MARK BSKA- SHOG GI MGO RGYAN",
1599 "TIBETAN MARK BKA- SHOG GI MGO RGYAN"},
1600 {0x3401, "CJK UNIFIED IDEOGRAPH-3401", "", "CJK UNIFIED IDEOGRAPH-3401" },
1601 {0x7fed, "CJK UNIFIED IDEOGRAPH-7FED", "", "CJK UNIFIED IDEOGRAPH-7FED" },
1602 {0xac00, "HANGUL SYLLABLE GA", "", "HANGUL SYLLABLE GA" },
1603 {0xd7a3, "HANGUL SYLLABLE HIH", "", "HANGUL SYLLABLE HIH" },
1604 {0xd800, "", "", "<lead surrogate-D800>" },
1605 {0xdc00, "", "", "<trail surrogate-DC00>" },
1606 {0xff08, "FULLWIDTH LEFT PARENTHESIS", "", "FULLWIDTH LEFT PARENTHESIS" },
1607 {0xffe5, "FULLWIDTH YEN SIGN", "", "FULLWIDTH YEN SIGN" },
1608 {0xffff, "", "", "<noncharacter-FFFF>" },
1609 {0x1d0c5, "BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS", "",
1610 "BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS",
1611 "BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA VASIS"},
1612 {0x23456, "CJK UNIFIED IDEOGRAPH-23456", "", "CJK UNIFIED IDEOGRAPH-23456" }
1613 };
1614
1615 static UBool
enumCharNamesFn(void * context,UChar32 code,UCharNameChoice nameChoice,const char * name,int32_t length)1616 enumCharNamesFn(void *context,
1617 UChar32 code, UCharNameChoice nameChoice,
1618 const char *name, int32_t length) {
1619 int32_t *pCount=(int32_t *)context;
1620 const char *expected;
1621 int i;
1622
1623 if(length<=0 || length!=(int32_t)strlen(name)) {
1624 /* should not be called with an empty string or invalid length */
1625 log_err("u_enumCharName(0x%lx)=%s but length=%ld\n", name, length);
1626 return TRUE;
1627 }
1628
1629 ++*pCount;
1630 for(i=0; i<sizeof(names)/sizeof(names[0]); ++i) {
1631 if(code==(UChar32)names[i].code) {
1632 switch (nameChoice) {
1633 case U_EXTENDED_CHAR_NAME:
1634 if(0!=strcmp(name, names[i].extName)) {
1635 log_err("u_enumCharName(0x%lx - Extended)=%s instead of %s\n", code, name, names[i].extName);
1636 }
1637 break;
1638 case U_UNICODE_CHAR_NAME:
1639 if(0!=strcmp(name, names[i].name)) {
1640 log_err("u_enumCharName(0x%lx)=%s instead of %s\n", code, name, names[i].name);
1641 }
1642 break;
1643 case U_UNICODE_10_CHAR_NAME:
1644 expected=names[i].oldName;
1645 if(expected[0]==0 || 0!=strcmp(name, expected)) {
1646 log_err("u_enumCharName(0x%lx - 1.0)=%s instead of %s\n", code, name, expected);
1647 }
1648 break;
1649 case U_CHAR_NAME_ALIAS:
1650 expected=names[i].alias;
1651 if(expected==NULL || expected[0]==0 || 0!=strcmp(name, expected)) {
1652 log_err("u_enumCharName(0x%lx - alias)=%s instead of %s\n", code, name, expected);
1653 }
1654 break;
1655 case U_CHAR_NAME_CHOICE_COUNT:
1656 break;
1657 }
1658 break;
1659 }
1660 }
1661 return TRUE;
1662 }
1663
1664 struct enumExtCharNamesContext {
1665 uint32_t length;
1666 int32_t last;
1667 };
1668
1669 static UBool
enumExtCharNamesFn(void * context,UChar32 code,UCharNameChoice nameChoice,const char * name,int32_t length)1670 enumExtCharNamesFn(void *context,
1671 UChar32 code, UCharNameChoice nameChoice,
1672 const char *name, int32_t length) {
1673 struct enumExtCharNamesContext *ecncp = (struct enumExtCharNamesContext *) context;
1674
1675 if (ecncp->last != (int32_t) code - 1) {
1676 if (ecncp->last < 0) {
1677 log_err("u_enumCharName(0x%lx - Ext) after u_enumCharName(0x%lx - Ext) instead of u_enumCharName(0x%lx - Ext)\n", code, ecncp->last, ecncp->last + 1);
1678 } else {
1679 log_err("u_enumCharName(0x%lx - Ext) instead of u_enumCharName(0x0 - Ext)\n", code);
1680 }
1681 }
1682 ecncp->last = (int32_t) code;
1683
1684 if (!*name) {
1685 log_err("u_enumCharName(0x%lx - Ext) should not be an empty string\n", code);
1686 }
1687
1688 return enumCharNamesFn(&ecncp->length, code, nameChoice, name, length);
1689 }
1690
1691 /**
1692 * This can be made more efficient by moving it into putil.c and having
1693 * it directly access the ebcdic translation tables.
1694 * TODO: If we get this method in putil.c, then delete it from here.
1695 */
1696 static UChar
u_charToUChar(char c)1697 u_charToUChar(char c) {
1698 UChar uc;
1699 u_charsToUChars(&c, &uc, 1);
1700 return uc;
1701 }
1702
1703 static void
TestCharNames()1704 TestCharNames() {
1705 static char name[80];
1706 UErrorCode errorCode=U_ZERO_ERROR;
1707 struct enumExtCharNamesContext extContext;
1708 const char *expected;
1709 int32_t length;
1710 UChar32 c;
1711 int32_t i;
1712
1713 log_verbose("Testing uprv_getMaxCharNameLength()\n");
1714 length=uprv_getMaxCharNameLength();
1715 if(length==0) {
1716 /* no names data available */
1717 return;
1718 }
1719 if(length<83) { /* Unicode 3.2 max char name length */
1720 log_err("uprv_getMaxCharNameLength()=%d is too short");
1721 }
1722 /* ### TODO same tests for max ISO comment length as for max name length */
1723
1724 log_verbose("Testing u_charName()\n");
1725 for(i=0; i<(int32_t)(sizeof(names)/sizeof(names[0])); ++i) {
1726 /* modern Unicode character name */
1727 length=u_charName(names[i].code, U_UNICODE_CHAR_NAME, name, sizeof(name), &errorCode);
1728 if(U_FAILURE(errorCode)) {
1729 log_err("u_charName(0x%lx) error %s\n", names[i].code, u_errorName(errorCode));
1730 return;
1731 }
1732 if(length<0 || 0!=strcmp(name, names[i].name) || length!=(uint16_t)strlen(name)) {
1733 log_err("u_charName(0x%lx) gets: %s (length %ld) instead of: %s\n", names[i].code, name, length, names[i].name);
1734 }
1735
1736 /* find the modern name */
1737 if (*names[i].name) {
1738 c=u_charFromName(U_UNICODE_CHAR_NAME, names[i].name, &errorCode);
1739 if(U_FAILURE(errorCode)) {
1740 log_err("u_charFromName(%s) error %s\n", names[i].name, u_errorName(errorCode));
1741 return;
1742 }
1743 if(c!=(UChar32)names[i].code) {
1744 log_err("u_charFromName(%s) gets 0x%lx instead of 0x%lx\n", names[i].name, c, names[i].code);
1745 }
1746 }
1747
1748 /* Unicode 1.0 character name */
1749 length=u_charName(names[i].code, U_UNICODE_10_CHAR_NAME, name, sizeof(name), &errorCode);
1750 if(U_FAILURE(errorCode)) {
1751 log_err("u_charName(0x%lx - 1.0) error %s\n", names[i].code, u_errorName(errorCode));
1752 return;
1753 }
1754 if(length<0 || (length>0 && 0!=strcmp(name, names[i].oldName)) || length!=(uint16_t)strlen(name)) {
1755 log_err("u_charName(0x%lx - 1.0) gets %s length %ld instead of nothing or %s\n", names[i].code, name, length, names[i].oldName);
1756 }
1757
1758 /* find the Unicode 1.0 name if it is stored (length>0 means that we could read it) */
1759 if(names[i].oldName[0]!=0 /* && length>0 */) {
1760 c=u_charFromName(U_UNICODE_10_CHAR_NAME, names[i].oldName, &errorCode);
1761 if(U_FAILURE(errorCode)) {
1762 log_err("u_charFromName(%s - 1.0) error %s\n", names[i].oldName, u_errorName(errorCode));
1763 return;
1764 }
1765 if(c!=(UChar32)names[i].code) {
1766 log_err("u_charFromName(%s - 1.0) gets 0x%lx instead of 0x%lx\n", names[i].oldName, c, names[i].code);
1767 }
1768 }
1769
1770 /* Unicode character name alias */
1771 length=u_charName(names[i].code, U_CHAR_NAME_ALIAS, name, sizeof(name), &errorCode);
1772 if(U_FAILURE(errorCode)) {
1773 log_err("u_charName(0x%lx - alias) error %s\n", names[i].code, u_errorName(errorCode));
1774 return;
1775 }
1776 expected=names[i].alias;
1777 if(expected==NULL) {
1778 expected="";
1779 }
1780 if(length<0 || (length>0 && 0!=strcmp(name, expected)) || length!=(uint16_t)strlen(name)) {
1781 log_err("u_charName(0x%lx - alias) gets %s length %ld instead of nothing or %s\n",
1782 names[i].code, name, length, expected);
1783 }
1784
1785 /* find the Unicode character name alias if it is stored (length>0 means that we could read it) */
1786 if(expected[0]!=0 /* && length>0 */) {
1787 c=u_charFromName(U_CHAR_NAME_ALIAS, expected, &errorCode);
1788 if(U_FAILURE(errorCode)) {
1789 log_err("u_charFromName(%s - alias) error %s\n",
1790 expected, u_errorName(errorCode));
1791 return;
1792 }
1793 if(c!=(UChar32)names[i].code) {
1794 log_err("u_charFromName(%s - alias) gets 0x%lx instead of 0x%lx\n",
1795 expected, c, names[i].code);
1796 }
1797 }
1798 }
1799
1800 /* test u_enumCharNames() */
1801 length=0;
1802 errorCode=U_ZERO_ERROR;
1803 u_enumCharNames(UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, enumCharNamesFn, &length, U_UNICODE_CHAR_NAME, &errorCode);
1804 if(U_FAILURE(errorCode) || length<94140) {
1805 log_err("u_enumCharNames(%ld..%lx) error %s names count=%ld\n", UCHAR_MIN_VALUE, UCHAR_MAX_VALUE, u_errorName(errorCode), length);
1806 }
1807
1808 extContext.length = 0;
1809 extContext.last = -1;
1810 errorCode=U_ZERO_ERROR;
1811 u_enumCharNames(UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, enumExtCharNamesFn, &extContext, U_EXTENDED_CHAR_NAME, &errorCode);
1812 if(U_FAILURE(errorCode) || extContext.length<UCHAR_MAX_VALUE + 1) {
1813 log_err("u_enumCharNames(%ld..0x%lx - Extended) error %s names count=%ld\n", UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, u_errorName(errorCode), extContext.length);
1814 }
1815
1816 /* test that u_charFromName() uppercases the input name, i.e., works with mixed-case names (new in 2.0) */
1817 if(0x61!=u_charFromName(U_UNICODE_CHAR_NAME, "LATin smALl letTER A", &errorCode)) {
1818 log_err("u_charFromName(U_UNICODE_CHAR_NAME, \"LATin smALl letTER A\") did not find U+0061 (%s)\n", u_errorName(errorCode));
1819 }
1820
1821 /* Test getCharNameCharacters */
1822 if(!getTestOption(QUICK_OPTION)) {
1823 enum { BUFSIZE = 256 };
1824 UErrorCode ec = U_ZERO_ERROR;
1825 char buf[BUFSIZE];
1826 int32_t maxLength;
1827 UChar32 cp;
1828 UChar pat[BUFSIZE], dumbPat[BUFSIZE];
1829 int32_t l1, l2;
1830 UBool map[256];
1831 UBool ok;
1832
1833 USet* set = uset_open(1, 0); /* empty set */
1834 USet* dumb = uset_open(1, 0); /* empty set */
1835
1836 /*
1837 * uprv_getCharNameCharacters() will likely return more lowercase
1838 * letters than actual character names contain because
1839 * it includes all the characters in lowercased names of
1840 * general categories, for the full possible set of extended names.
1841 */
1842 {
1843 USetAdder sa={
1844 NULL,
1845 uset_add,
1846 uset_addRange,
1847 uset_addString,
1848 NULL /* don't need remove() */
1849 };
1850 sa.set=set;
1851 uprv_getCharNameCharacters(&sa);
1852 }
1853
1854 /* build set the dumb (but sure-fire) way */
1855 for (i=0; i<256; ++i) {
1856 map[i] = FALSE;
1857 }
1858
1859 maxLength=0;
1860 for (cp=0; cp<0x110000; ++cp) {
1861 int32_t len = u_charName(cp, U_EXTENDED_CHAR_NAME,
1862 buf, BUFSIZE, &ec);
1863 if (U_FAILURE(ec)) {
1864 log_err("FAIL: u_charName failed when it shouldn't\n");
1865 uset_close(set);
1866 uset_close(dumb);
1867 return;
1868 }
1869 if(len>maxLength) {
1870 maxLength=len;
1871 }
1872
1873 for (i=0; i<len; ++i) {
1874 if (!map[(uint8_t) buf[i]]) {
1875 uset_add(dumb, (UChar32)u_charToUChar(buf[i]));
1876 map[(uint8_t) buf[i]] = TRUE;
1877 }
1878 }
1879
1880 /* test for leading/trailing whitespace */
1881 if(buf[0]==' ' || buf[0]=='\t' || buf[len-1]==' ' || buf[len-1]=='\t') {
1882 log_err("u_charName(U+%04x) returns a name with leading or trailing whitespace\n", cp);
1883 }
1884 }
1885
1886 if(map[(uint8_t)'\t']) {
1887 log_err("u_charName() returned a name with a TAB for some code point\n", cp);
1888 }
1889
1890 length=uprv_getMaxCharNameLength();
1891 if(length!=maxLength) {
1892 log_err("uprv_getMaxCharNameLength()=%d differs from the maximum length %d of all extended names\n",
1893 length, maxLength);
1894 }
1895
1896 /* compare the sets. Where is my uset_equals?!! */
1897 ok=TRUE;
1898 for(i=0; i<256; ++i) {
1899 if(uset_contains(set, i)!=uset_contains(dumb, i)) {
1900 if(0x61<=i && i<=0x7a /* a-z */ && uset_contains(set, i) && !uset_contains(dumb, i)) {
1901 /* ignore lowercase a-z that are in set but not in dumb */
1902 ok=TRUE;
1903 } else {
1904 ok=FALSE;
1905 break;
1906 }
1907 }
1908 }
1909
1910 l1 = uset_toPattern(set, pat, BUFSIZE, TRUE, &ec);
1911 l2 = uset_toPattern(dumb, dumbPat, BUFSIZE, TRUE, &ec);
1912 if (U_FAILURE(ec)) {
1913 log_err("FAIL: uset_toPattern failed when it shouldn't\n");
1914 uset_close(set);
1915 uset_close(dumb);
1916 return;
1917 }
1918
1919 if (l1 >= BUFSIZE) {
1920 l1 = BUFSIZE-1;
1921 pat[l1] = 0;
1922 }
1923 if (l2 >= BUFSIZE) {
1924 l2 = BUFSIZE-1;
1925 dumbPat[l2] = 0;
1926 }
1927
1928 if (!ok) {
1929 log_err("FAIL: uprv_getCharNameCharacters() returned %s, expected %s (too many lowercase a-z are ok)\n",
1930 aescstrdup(pat, l1), aescstrdup(dumbPat, l2));
1931 } else if(getTestOption(VERBOSITY_OPTION)) {
1932 log_verbose("Ok: uprv_getCharNameCharacters() returned %s\n", aescstrdup(pat, l1));
1933 }
1934
1935 uset_close(set);
1936 uset_close(dumb);
1937 }
1938
1939 /* ### TODO: test error cases and other interesting things */
1940 }
1941
1942 static void
TestUCharFromNameUnderflow()1943 TestUCharFromNameUnderflow() {
1944 // Ticket #10889: Underflow crash when there is no dash.
1945 UErrorCode errorCode=U_ZERO_ERROR;
1946 UChar32 c=u_charFromName(U_EXTENDED_CHAR_NAME, "<NO BREAK SPACE>", &errorCode);
1947 if(U_SUCCESS(errorCode)) {
1948 log_err("u_charFromName(<NO BREAK SPACE>) = U+%04x but should fail - %s\n", c, u_errorName(errorCode));
1949 }
1950
1951 // Test related edge cases.
1952 errorCode=U_ZERO_ERROR;
1953 c=u_charFromName(U_EXTENDED_CHAR_NAME, "<-00a0>", &errorCode);
1954 if(U_SUCCESS(errorCode)) {
1955 log_err("u_charFromName(<-00a0>) = U+%04x but should fail - %s\n", c, u_errorName(errorCode));
1956 }
1957
1958 errorCode=U_ZERO_ERROR;
1959 c=u_charFromName(U_EXTENDED_CHAR_NAME, "<control->", &errorCode);
1960 if(U_SUCCESS(errorCode)) {
1961 log_err("u_charFromName(<control->) = U+%04x but should fail - %s\n", c, u_errorName(errorCode));
1962 }
1963
1964 errorCode=U_ZERO_ERROR;
1965 c=u_charFromName(U_EXTENDED_CHAR_NAME, "<control-111111>", &errorCode);
1966 if(U_SUCCESS(errorCode)) {
1967 log_err("u_charFromName(<control-111111>) = U+%04x but should fail - %s\n", c, u_errorName(errorCode));
1968 }
1969 }
1970
1971 /* test u_isMirrored() and u_charMirror() ----------------------------------- */
1972
1973 static void
TestMirroring()1974 TestMirroring() {
1975 USet *set;
1976 UErrorCode errorCode;
1977
1978 UChar32 start, end, c2, c3;
1979 int32_t i;
1980
1981 U_STRING_DECL(mirroredPattern, "[:Bidi_Mirrored:]", 17);
1982
1983 U_STRING_INIT(mirroredPattern, "[:Bidi_Mirrored:]", 17);
1984
1985 log_verbose("Testing u_isMirrored()\n");
1986 if(!(u_isMirrored(0x28) && u_isMirrored(0xbb) && u_isMirrored(0x2045) && u_isMirrored(0x232a) &&
1987 !u_isMirrored(0x27) && !u_isMirrored(0x61) && !u_isMirrored(0x284) && !u_isMirrored(0x3400)
1988 )
1989 ) {
1990 log_err("u_isMirrored() does not work correctly\n");
1991 }
1992
1993 log_verbose("Testing u_charMirror()\n");
1994 if(!(u_charMirror(0x3c)==0x3e && u_charMirror(0x5d)==0x5b && u_charMirror(0x208d)==0x208e && u_charMirror(0x3017)==0x3016 &&
1995 u_charMirror(0xbb)==0xab && u_charMirror(0x2215)==0x29F5 && u_charMirror(0x29F5)==0x2215 && /* large delta between the code points */
1996 u_charMirror(0x2e)==0x2e && u_charMirror(0x6f3)==0x6f3 && u_charMirror(0x301c)==0x301c && u_charMirror(0xa4ab)==0xa4ab &&
1997 /* see Unicode Corrigendum #6 at http://www.unicode.org/versions/corrigendum6.html */
1998 u_charMirror(0x2018)==0x2018 && u_charMirror(0x201b)==0x201b && u_charMirror(0x301d)==0x301d
1999 )
2000 ) {
2001 log_err("u_charMirror() does not work correctly\n");
2002 }
2003
2004 /* verify that Bidi_Mirroring_Glyph roundtrips */
2005 errorCode=U_ZERO_ERROR;
2006 set=uset_openPattern(mirroredPattern, 17, &errorCode);
2007
2008 if (U_FAILURE(errorCode)) {
2009 log_data_err("uset_openPattern(mirroredPattern, 17, &errorCode) failed!\n");
2010 } else {
2011 for(i=0; 0==uset_getItem(set, i, &start, &end, NULL, 0, &errorCode); ++i) {
2012 do {
2013 c2=u_charMirror(start);
2014 c3=u_charMirror(c2);
2015 if(c3!=start) {
2016 log_err("u_charMirror() does not roundtrip: U+%04lx->U+%04lx->U+%04lx\n", (long)start, (long)c2, (long)c3);
2017 }
2018 c3=u_getBidiPairedBracket(start);
2019 if(u_getIntPropertyValue(start, UCHAR_BIDI_PAIRED_BRACKET_TYPE)==U_BPT_NONE) {
2020 if(c3!=start) {
2021 log_err("u_getBidiPairedBracket(U+%04lx) != self for bpt(c)==None\n",
2022 (long)start);
2023 }
2024 } else {
2025 if(c3!=c2) {
2026 log_err("u_getBidiPairedBracket(U+%04lx) != U+%04lx = bmg(c)'\n",
2027 (long)start, (long)c2);
2028 }
2029 }
2030 } while(++start<=end);
2031 }
2032 }
2033
2034 uset_close(set);
2035 }
2036
2037
2038 struct RunTestData
2039 {
2040 const char *runText;
2041 UScriptCode runCode;
2042 };
2043
2044 typedef struct RunTestData RunTestData;
2045
2046 static void
CheckScriptRuns(UScriptRun * scriptRun,int32_t * runStarts,const RunTestData * testData,int32_t nRuns,const char * prefix)2047 CheckScriptRuns(UScriptRun *scriptRun, int32_t *runStarts, const RunTestData *testData, int32_t nRuns,
2048 const char *prefix)
2049 {
2050 int32_t run, runStart, runLimit;
2051 UScriptCode runCode;
2052
2053 /* iterate over all the runs */
2054 run = 0;
2055 while (uscript_nextRun(scriptRun, &runStart, &runLimit, &runCode)) {
2056 if (runStart != runStarts[run]) {
2057 log_err("%s: incorrect start offset for run %d: expected %d, got %d\n",
2058 prefix, run, runStarts[run], runStart);
2059 }
2060
2061 if (runLimit != runStarts[run + 1]) {
2062 log_err("%s: incorrect limit offset for run %d: expected %d, got %d\n",
2063 prefix, run, runStarts[run + 1], runLimit);
2064 }
2065
2066 if (runCode != testData[run].runCode) {
2067 log_err("%s: incorrect script for run %d: expected \"%s\", got \"%s\"\n",
2068 prefix, run, uscript_getName(testData[run].runCode), uscript_getName(runCode));
2069 }
2070
2071 run += 1;
2072
2073 /* stop when we've seen all the runs we expect to see */
2074 if (run >= nRuns) {
2075 break;
2076 }
2077 }
2078
2079 /* Complain if we didn't see then number of runs we expected */
2080 if (run != nRuns) {
2081 log_err("%s: incorrect number of runs: expected %d, got %d\n", prefix, run, nRuns);
2082 }
2083 }
2084
2085 static void
TestUScriptRunAPI()2086 TestUScriptRunAPI()
2087 {
2088 static const RunTestData testData1[] = {
2089 {"\\u0020\\u0946\\u0939\\u093F\\u0928\\u094D\\u0926\\u0940\\u0020", USCRIPT_DEVANAGARI},
2090 {"\\u0627\\u0644\\u0639\\u0631\\u0628\\u064A\\u0629\\u0020", USCRIPT_ARABIC},
2091 {"\\u0420\\u0443\\u0441\\u0441\\u043A\\u0438\\u0439\\u0020", USCRIPT_CYRILLIC},
2092 {"English (", USCRIPT_LATIN},
2093 {"\\u0E44\\u0E17\\u0E22", USCRIPT_THAI},
2094 {") ", USCRIPT_LATIN},
2095 {"\\u6F22\\u5B75", USCRIPT_HAN},
2096 {"\\u3068\\u3072\\u3089\\u304C\\u306A\\u3068", USCRIPT_HIRAGANA},
2097 {"\\u30AB\\u30BF\\u30AB\\u30CA", USCRIPT_KATAKANA},
2098 {"\\U00010400\\U00010401\\U00010402\\U00010403", USCRIPT_DESERET}
2099 };
2100
2101 static const RunTestData testData2[] = {
2102 {"((((((((((abc))))))))))", USCRIPT_LATIN}
2103 };
2104
2105 static const struct {
2106 const RunTestData *testData;
2107 int32_t nRuns;
2108 } testDataEntries[] = {
2109 {testData1, UPRV_LENGTHOF(testData1)},
2110 {testData2, UPRV_LENGTHOF(testData2)}
2111 };
2112
2113 static const int32_t nTestEntries = UPRV_LENGTHOF(testDataEntries);
2114 int32_t testEntry;
2115
2116 for (testEntry = 0; testEntry < nTestEntries; testEntry += 1) {
2117 UChar testString[1024];
2118 int32_t runStarts[256];
2119 int32_t nTestRuns = testDataEntries[testEntry].nRuns;
2120 const RunTestData *testData = testDataEntries[testEntry].testData;
2121
2122 int32_t run, stringLimit;
2123 UScriptRun *scriptRun = NULL;
2124 UErrorCode err;
2125
2126 /*
2127 * Fill in the test string and the runStarts array.
2128 */
2129 stringLimit = 0;
2130 for (run = 0; run < nTestRuns; run += 1) {
2131 runStarts[run] = stringLimit;
2132 stringLimit += u_unescape(testData[run].runText, &testString[stringLimit], 1024 - stringLimit);
2133 /*stringLimit -= 1;*/
2134 }
2135
2136 /* The limit of the last run */
2137 runStarts[nTestRuns] = stringLimit;
2138
2139 /*
2140 * Make sure that calling uscript_OpenRun with a NULL text pointer
2141 * and a non-zero text length returns the correct error.
2142 */
2143 err = U_ZERO_ERROR;
2144 scriptRun = uscript_openRun(NULL, stringLimit, &err);
2145
2146 if (err != U_ILLEGAL_ARGUMENT_ERROR) {
2147 log_err("uscript_openRun(NULL, stringLimit, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
2148 }
2149
2150 if (scriptRun != NULL) {
2151 log_err("uscript_openRun(NULL, stringLimit, &err) returned a non-NULL result.\n");
2152 uscript_closeRun(scriptRun);
2153 }
2154
2155 /*
2156 * Make sure that calling uscript_OpenRun with a non-NULL text pointer
2157 * and a zero text length returns the correct error.
2158 */
2159 err = U_ZERO_ERROR;
2160 scriptRun = uscript_openRun(testString, 0, &err);
2161
2162 if (err != U_ILLEGAL_ARGUMENT_ERROR) {
2163 log_err("uscript_openRun(testString, 0, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
2164 }
2165
2166 if (scriptRun != NULL) {
2167 log_err("uscript_openRun(testString, 0, &err) returned a non-NULL result.\n");
2168 uscript_closeRun(scriptRun);
2169 }
2170
2171 /*
2172 * Make sure that calling uscript_openRun with a NULL text pointer
2173 * and a zero text length doesn't return an error.
2174 */
2175 err = U_ZERO_ERROR;
2176 scriptRun = uscript_openRun(NULL, 0, &err);
2177
2178 if (U_FAILURE(err)) {
2179 log_err("Got error %s from uscript_openRun(NULL, 0, &err)\n", u_errorName(err));
2180 }
2181
2182 /* Make sure that the empty iterator doesn't find any runs */
2183 if (uscript_nextRun(scriptRun, NULL, NULL, NULL)) {
2184 log_err("uscript_nextRun(...) returned TRUE for an empty iterator.\n");
2185 }
2186
2187 /*
2188 * Make sure that calling uscript_setRunText with a NULL text pointer
2189 * and a non-zero text length returns the correct error.
2190 */
2191 err = U_ZERO_ERROR;
2192 uscript_setRunText(scriptRun, NULL, stringLimit, &err);
2193
2194 if (err != U_ILLEGAL_ARGUMENT_ERROR) {
2195 log_err("uscript_setRunText(scriptRun, NULL, stringLimit, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
2196 }
2197
2198 /*
2199 * Make sure that calling uscript_OpenRun with a non-NULL text pointer
2200 * and a zero text length returns the correct error.
2201 */
2202 err = U_ZERO_ERROR;
2203 uscript_setRunText(scriptRun, testString, 0, &err);
2204
2205 if (err != U_ILLEGAL_ARGUMENT_ERROR) {
2206 log_err("uscript_setRunText(scriptRun, testString, 0, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
2207 }
2208
2209 /*
2210 * Now call uscript_setRunText on the empty iterator
2211 * and make sure that it works.
2212 */
2213 err = U_ZERO_ERROR;
2214 uscript_setRunText(scriptRun, testString, stringLimit, &err);
2215
2216 if (U_FAILURE(err)) {
2217 log_err("Got error %s from uscript_setRunText(...)\n", u_errorName(err));
2218 } else {
2219 CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_setRunText");
2220 }
2221
2222 uscript_closeRun(scriptRun);
2223
2224 /*
2225 * Now open an interator over the testString
2226 * using uscript_openRun and make sure that it works
2227 */
2228 scriptRun = uscript_openRun(testString, stringLimit, &err);
2229
2230 if (U_FAILURE(err)) {
2231 log_err("Got error %s from uscript_openRun(...)\n", u_errorName(err));
2232 } else {
2233 CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_openRun");
2234 }
2235
2236 /* Now reset the iterator, and make sure
2237 * that it still works.
2238 */
2239 uscript_resetRun(scriptRun);
2240
2241 CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_resetRun");
2242
2243 /* Close the iterator */
2244 uscript_closeRun(scriptRun);
2245 }
2246 }
2247
2248 /* test additional, non-core properties */
2249 static void
TestAdditionalProperties()2250 TestAdditionalProperties() {
2251 /* test data for u_charAge() */
2252 static const struct {
2253 UChar32 c;
2254 UVersionInfo version;
2255 } charAges[]={
2256 {0x41, { 1, 1, 0, 0 }},
2257 {0xffff, { 1, 1, 0, 0 }},
2258 {0x20ab, { 2, 0, 0, 0 }},
2259 {0x2fffe, { 2, 0, 0, 0 }},
2260 {0x20ac, { 2, 1, 0, 0 }},
2261 {0xfb1d, { 3, 0, 0, 0 }},
2262 {0x3f4, { 3, 1, 0, 0 }},
2263 {0x10300, { 3, 1, 0, 0 }},
2264 {0x220, { 3, 2, 0, 0 }},
2265 {0xff60, { 3, 2, 0, 0 }}
2266 };
2267
2268 /* test data for u_hasBinaryProperty() */
2269 static const int32_t
2270 props[][3]={ /* code point, property, value */
2271 { 0x0627, UCHAR_ALPHABETIC, TRUE },
2272 { 0x1034a, UCHAR_ALPHABETIC, TRUE },
2273 { 0x2028, UCHAR_ALPHABETIC, FALSE },
2274
2275 { 0x0066, UCHAR_ASCII_HEX_DIGIT, TRUE },
2276 { 0x0067, UCHAR_ASCII_HEX_DIGIT, FALSE },
2277
2278 { 0x202c, UCHAR_BIDI_CONTROL, TRUE },
2279 { 0x202f, UCHAR_BIDI_CONTROL, FALSE },
2280
2281 { 0x003c, UCHAR_BIDI_MIRRORED, TRUE },
2282 { 0x003d, UCHAR_BIDI_MIRRORED, FALSE },
2283
2284 /* see Unicode Corrigendum #6 at http://www.unicode.org/versions/corrigendum6.html */
2285 { 0x2018, UCHAR_BIDI_MIRRORED, FALSE },
2286 { 0x201d, UCHAR_BIDI_MIRRORED, FALSE },
2287 { 0x201f, UCHAR_BIDI_MIRRORED, FALSE },
2288 { 0x301e, UCHAR_BIDI_MIRRORED, FALSE },
2289
2290 { 0x058a, UCHAR_DASH, TRUE },
2291 { 0x007e, UCHAR_DASH, FALSE },
2292
2293 { 0x0c4d, UCHAR_DIACRITIC, TRUE },
2294 { 0x3000, UCHAR_DIACRITIC, FALSE },
2295
2296 { 0x0e46, UCHAR_EXTENDER, TRUE },
2297 { 0x0020, UCHAR_EXTENDER, FALSE },
2298
2299 #if !UCONFIG_NO_NORMALIZATION
2300 { 0xfb1d, UCHAR_FULL_COMPOSITION_EXCLUSION, TRUE },
2301 { 0x1d15f, UCHAR_FULL_COMPOSITION_EXCLUSION, TRUE },
2302 { 0xfb1e, UCHAR_FULL_COMPOSITION_EXCLUSION, FALSE },
2303
2304 { 0x110a, UCHAR_NFD_INERT, TRUE }, /* Jamo L */
2305 { 0x0308, UCHAR_NFD_INERT, FALSE },
2306
2307 { 0x1164, UCHAR_NFKD_INERT, TRUE }, /* Jamo V */
2308 { 0x1d79d, UCHAR_NFKD_INERT, FALSE }, /* math compat version of xi */
2309
2310 { 0x0021, UCHAR_NFC_INERT, TRUE }, /* ! */
2311 { 0x0061, UCHAR_NFC_INERT, FALSE }, /* a */
2312 { 0x00e4, UCHAR_NFC_INERT, FALSE }, /* a-umlaut */
2313 { 0x0102, UCHAR_NFC_INERT, FALSE }, /* a-breve */
2314 { 0xac1c, UCHAR_NFC_INERT, FALSE }, /* Hangul LV */
2315 { 0xac1d, UCHAR_NFC_INERT, TRUE }, /* Hangul LVT */
2316
2317 { 0x1d79d, UCHAR_NFKC_INERT, FALSE }, /* math compat version of xi */
2318 { 0x2a6d6, UCHAR_NFKC_INERT, TRUE }, /* Han, last of CJK ext. B */
2319
2320 { 0x00e4, UCHAR_SEGMENT_STARTER, TRUE },
2321 { 0x0308, UCHAR_SEGMENT_STARTER, FALSE },
2322 { 0x110a, UCHAR_SEGMENT_STARTER, TRUE }, /* Jamo L */
2323 { 0x1164, UCHAR_SEGMENT_STARTER, FALSE },/* Jamo V */
2324 { 0xac1c, UCHAR_SEGMENT_STARTER, TRUE }, /* Hangul LV */
2325 { 0xac1d, UCHAR_SEGMENT_STARTER, TRUE }, /* Hangul LVT */
2326 #endif
2327
2328 { 0x0044, UCHAR_HEX_DIGIT, TRUE },
2329 { 0xff46, UCHAR_HEX_DIGIT, TRUE },
2330 { 0x0047, UCHAR_HEX_DIGIT, FALSE },
2331
2332 { 0x30fb, UCHAR_HYPHEN, TRUE },
2333 { 0xfe58, UCHAR_HYPHEN, FALSE },
2334
2335 { 0x2172, UCHAR_ID_CONTINUE, TRUE },
2336 { 0x0307, UCHAR_ID_CONTINUE, TRUE },
2337 { 0x005c, UCHAR_ID_CONTINUE, FALSE },
2338
2339 { 0x2172, UCHAR_ID_START, TRUE },
2340 { 0x007a, UCHAR_ID_START, TRUE },
2341 { 0x0039, UCHAR_ID_START, FALSE },
2342
2343 { 0x4db5, UCHAR_IDEOGRAPHIC, TRUE },
2344 { 0x2f999, UCHAR_IDEOGRAPHIC, TRUE },
2345 { 0x2f99, UCHAR_IDEOGRAPHIC, FALSE },
2346
2347 { 0x200c, UCHAR_JOIN_CONTROL, TRUE },
2348 { 0x2029, UCHAR_JOIN_CONTROL, FALSE },
2349
2350 { 0x1d7bc, UCHAR_LOWERCASE, TRUE },
2351 { 0x0345, UCHAR_LOWERCASE, TRUE },
2352 { 0x0030, UCHAR_LOWERCASE, FALSE },
2353
2354 { 0x1d7a9, UCHAR_MATH, TRUE },
2355 { 0x2135, UCHAR_MATH, TRUE },
2356 { 0x0062, UCHAR_MATH, FALSE },
2357
2358 { 0xfde1, UCHAR_NONCHARACTER_CODE_POINT, TRUE },
2359 { 0x10ffff, UCHAR_NONCHARACTER_CODE_POINT, TRUE },
2360 { 0x10fffd, UCHAR_NONCHARACTER_CODE_POINT, FALSE },
2361
2362 { 0x0022, UCHAR_QUOTATION_MARK, TRUE },
2363 { 0xff62, UCHAR_QUOTATION_MARK, TRUE },
2364 { 0xd840, UCHAR_QUOTATION_MARK, FALSE },
2365
2366 { 0x061f, UCHAR_TERMINAL_PUNCTUATION, TRUE },
2367 { 0xe003f, UCHAR_TERMINAL_PUNCTUATION, FALSE },
2368
2369 { 0x1d44a, UCHAR_UPPERCASE, TRUE },
2370 { 0x2162, UCHAR_UPPERCASE, TRUE },
2371 { 0x0345, UCHAR_UPPERCASE, FALSE },
2372
2373 { 0x0020, UCHAR_WHITE_SPACE, TRUE },
2374 { 0x202f, UCHAR_WHITE_SPACE, TRUE },
2375 { 0x3001, UCHAR_WHITE_SPACE, FALSE },
2376
2377 { 0x0711, UCHAR_XID_CONTINUE, TRUE },
2378 { 0x1d1aa, UCHAR_XID_CONTINUE, TRUE },
2379 { 0x007c, UCHAR_XID_CONTINUE, FALSE },
2380
2381 { 0x16ee, UCHAR_XID_START, TRUE },
2382 { 0x23456, UCHAR_XID_START, TRUE },
2383 { 0x1d1aa, UCHAR_XID_START, FALSE },
2384
2385 /*
2386 * Version break:
2387 * The following properties are only supported starting with the
2388 * Unicode version indicated in the second field.
2389 */
2390 { -1, 0x320, 0 },
2391
2392 { 0x180c, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, TRUE },
2393 { 0xfe02, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, TRUE },
2394 { 0x1801, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, FALSE },
2395
2396 { 0x0149, UCHAR_DEPRECATED, TRUE }, /* changed in Unicode 5.2 */
2397 { 0x0341, UCHAR_DEPRECATED, FALSE }, /* changed in Unicode 5.2 */
2398 { 0xe0041, UCHAR_DEPRECATED, TRUE }, /* changed from Unicode 5 to 5.1 */
2399 { 0xe0100, UCHAR_DEPRECATED, FALSE },
2400
2401 { 0x00a0, UCHAR_GRAPHEME_BASE, TRUE },
2402 { 0x0a4d, UCHAR_GRAPHEME_BASE, FALSE },
2403 { 0xff9d, UCHAR_GRAPHEME_BASE, TRUE },
2404 { 0xff9f, UCHAR_GRAPHEME_BASE, FALSE }, /* changed from Unicode 3.2 to 4 and again from 5 to 5.1 */
2405
2406 { 0x0300, UCHAR_GRAPHEME_EXTEND, TRUE },
2407 { 0xff9d, UCHAR_GRAPHEME_EXTEND, FALSE },
2408 { 0xff9f, UCHAR_GRAPHEME_EXTEND, TRUE }, /* changed from Unicode 3.2 to 4 and again from 5 to 5.1 */
2409 { 0x0603, UCHAR_GRAPHEME_EXTEND, FALSE },
2410
2411 { 0x0a4d, UCHAR_GRAPHEME_LINK, TRUE },
2412 { 0xff9f, UCHAR_GRAPHEME_LINK, FALSE },
2413
2414 { 0x2ff7, UCHAR_IDS_BINARY_OPERATOR, TRUE },
2415 { 0x2ff3, UCHAR_IDS_BINARY_OPERATOR, FALSE },
2416
2417 { 0x2ff3, UCHAR_IDS_TRINARY_OPERATOR, TRUE },
2418 { 0x2f03, UCHAR_IDS_TRINARY_OPERATOR, FALSE },
2419
2420 { 0x0ec1, UCHAR_LOGICAL_ORDER_EXCEPTION, TRUE },
2421 { 0xdcba, UCHAR_LOGICAL_ORDER_EXCEPTION, FALSE },
2422
2423 { 0x2e9b, UCHAR_RADICAL, TRUE },
2424 { 0x4e00, UCHAR_RADICAL, FALSE },
2425
2426 { 0x012f, UCHAR_SOFT_DOTTED, TRUE },
2427 { 0x0049, UCHAR_SOFT_DOTTED, FALSE },
2428
2429 { 0xfa11, UCHAR_UNIFIED_IDEOGRAPH, TRUE },
2430 { 0xfa12, UCHAR_UNIFIED_IDEOGRAPH, FALSE },
2431
2432 { -1, 0x401, 0 }, /* version break for Unicode 4.0.1 */
2433
2434 { 0x002e, UCHAR_S_TERM, TRUE },
2435 { 0x0061, UCHAR_S_TERM, FALSE },
2436
2437 { 0x180c, UCHAR_VARIATION_SELECTOR, TRUE },
2438 { 0xfe03, UCHAR_VARIATION_SELECTOR, TRUE },
2439 { 0xe01ef, UCHAR_VARIATION_SELECTOR, TRUE },
2440 { 0xe0200, UCHAR_VARIATION_SELECTOR, FALSE },
2441
2442 /* enum/integer type properties */
2443
2444 /* UCHAR_BIDI_CLASS tested for assigned characters in TestUnicodeData() */
2445 /* test default Bidi classes for unassigned code points */
2446 { 0x0590, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2447 { 0x05cf, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2448 { 0x05ed, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2449 { 0x07f2, UCHAR_BIDI_CLASS, U_DIR_NON_SPACING_MARK }, /* Nko, new in Unicode 5.0 */
2450 { 0x07fe, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, /* unassigned R */
2451 { 0x089f, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2452 { 0xfb37, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2453 { 0xfb42, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2454 { 0x10806, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2455 { 0x10909, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2456 { 0x10fe4, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2457
2458 { 0x061d, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2459 { 0x063f, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2460 { 0x070e, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2461 { 0x0775, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2462 { 0xfbc2, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2463 { 0xfd90, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2464 { 0xfefe, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2465
2466 { 0x02AF, UCHAR_BLOCK, UBLOCK_IPA_EXTENSIONS },
2467 { 0x0C4E, UCHAR_BLOCK, UBLOCK_TELUGU },
2468 { 0x155A, UCHAR_BLOCK, UBLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS },
2469 { 0x1717, UCHAR_BLOCK, UBLOCK_TAGALOG },
2470 { 0x1900, UCHAR_BLOCK, UBLOCK_LIMBU },
2471 { 0x1CBF, UCHAR_BLOCK, UBLOCK_NO_BLOCK },
2472 { 0x3040, UCHAR_BLOCK, UBLOCK_HIRAGANA },
2473 { 0x1D0FF, UCHAR_BLOCK, UBLOCK_BYZANTINE_MUSICAL_SYMBOLS },
2474 { 0x50000, UCHAR_BLOCK, UBLOCK_NO_BLOCK },
2475 { 0xEFFFF, UCHAR_BLOCK, UBLOCK_NO_BLOCK },
2476 { 0x10D0FF, UCHAR_BLOCK, UBLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_B },
2477
2478 /* UCHAR_CANONICAL_COMBINING_CLASS tested for assigned characters in TestUnicodeData() */
2479 { 0xd7d7, UCHAR_CANONICAL_COMBINING_CLASS, 0 },
2480
2481 { 0x00A0, UCHAR_DECOMPOSITION_TYPE, U_DT_NOBREAK },
2482 { 0x00A8, UCHAR_DECOMPOSITION_TYPE, U_DT_COMPAT },
2483 { 0x00bf, UCHAR_DECOMPOSITION_TYPE, U_DT_NONE },
2484 { 0x00c0, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL },
2485 { 0x1E9B, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL },
2486 { 0xBCDE, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL },
2487 { 0xFB5D, UCHAR_DECOMPOSITION_TYPE, U_DT_MEDIAL },
2488 { 0x1D736, UCHAR_DECOMPOSITION_TYPE, U_DT_FONT },
2489 { 0xe0033, UCHAR_DECOMPOSITION_TYPE, U_DT_NONE },
2490
2491 { 0x0009, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL },
2492 { 0x0020, UCHAR_EAST_ASIAN_WIDTH, U_EA_NARROW },
2493 { 0x00B1, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
2494 { 0x20A9, UCHAR_EAST_ASIAN_WIDTH, U_EA_HALFWIDTH },
2495 { 0x2FFB, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
2496 { 0x3000, UCHAR_EAST_ASIAN_WIDTH, U_EA_FULLWIDTH },
2497 { 0x35bb, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
2498 { 0x58bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
2499 { 0xD7A3, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
2500 { 0xEEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
2501 { 0x1D198, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL },
2502 { 0x20000, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
2503 { 0x2F8C7, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
2504 { 0x3a5bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, /* plane 3 got default W values in Unicode 4 */
2505 { 0x5a5bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL },
2506 { 0xFEEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
2507 { 0x10EEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
2508
2509 /* UCHAR_GENERAL_CATEGORY tested for assigned characters in TestUnicodeData() */
2510 { 0xd7c7, UCHAR_GENERAL_CATEGORY, 0 },
2511 { 0xd7d7, UCHAR_GENERAL_CATEGORY, U_OTHER_LETTER }, /* changed in Unicode 5.2 */
2512
2513 { 0x0444, UCHAR_JOINING_GROUP, U_JG_NO_JOINING_GROUP },
2514 { 0x0639, UCHAR_JOINING_GROUP, U_JG_AIN },
2515 { 0x072A, UCHAR_JOINING_GROUP, U_JG_DALATH_RISH },
2516 { 0x0647, UCHAR_JOINING_GROUP, U_JG_HEH },
2517 { 0x06C1, UCHAR_JOINING_GROUP, U_JG_HEH_GOAL },
2518
2519 { 0x200C, UCHAR_JOINING_TYPE, U_JT_NON_JOINING },
2520 { 0x200D, UCHAR_JOINING_TYPE, U_JT_JOIN_CAUSING },
2521 { 0x0639, UCHAR_JOINING_TYPE, U_JT_DUAL_JOINING },
2522 { 0x0640, UCHAR_JOINING_TYPE, U_JT_JOIN_CAUSING },
2523 { 0x06C3, UCHAR_JOINING_TYPE, U_JT_RIGHT_JOINING },
2524 { 0x0300, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT },
2525 { 0x070F, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT },
2526 { 0xe0033, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT },
2527
2528 /* TestUnicodeData() verifies that no assigned character has "XX" (unknown) */
2529 { 0xe7e7, UCHAR_LINE_BREAK, U_LB_UNKNOWN },
2530 { 0x10fffd, UCHAR_LINE_BREAK, U_LB_UNKNOWN },
2531 { 0x0028, UCHAR_LINE_BREAK, U_LB_OPEN_PUNCTUATION },
2532 { 0x232A, UCHAR_LINE_BREAK, U_LB_CLOSE_PUNCTUATION },
2533 { 0x3401, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
2534 { 0x4e02, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
2535 { 0x20004, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
2536 { 0xf905, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
2537 { 0xdb7e, UCHAR_LINE_BREAK, U_LB_SURROGATE },
2538 { 0xdbfd, UCHAR_LINE_BREAK, U_LB_SURROGATE },
2539 { 0xdffc, UCHAR_LINE_BREAK, U_LB_SURROGATE },
2540 { 0x2762, UCHAR_LINE_BREAK, U_LB_EXCLAMATION },
2541 { 0x002F, UCHAR_LINE_BREAK, U_LB_BREAK_SYMBOLS },
2542 { 0x1D49C, UCHAR_LINE_BREAK, U_LB_ALPHABETIC },
2543 { 0x1731, UCHAR_LINE_BREAK, U_LB_ALPHABETIC },
2544
2545 /* UCHAR_NUMERIC_TYPE tested in TestNumericProperties() */
2546
2547 /* UCHAR_SCRIPT tested in TestUScriptCodeAPI() */
2548
2549 { 0x10ff, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2550 { 0x1100, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
2551 { 0x1111, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
2552 { 0x1159, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
2553 { 0x115a, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, /* changed in Unicode 5.2 */
2554 { 0x115e, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, /* changed in Unicode 5.2 */
2555 { 0x115f, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
2556
2557 { 0xa95f, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2558 { 0xa960, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, /* changed in Unicode 5.2 */
2559 { 0xa97c, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, /* changed in Unicode 5.2 */
2560 { 0xa97d, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2561
2562 { 0x1160, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
2563 { 0x1161, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
2564 { 0x1172, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
2565 { 0x11a2, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
2566 { 0x11a3, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, /* changed in Unicode 5.2 */
2567 { 0x11a7, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, /* changed in Unicode 5.2 */
2568
2569 { 0xd7af, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2570 { 0xd7b0, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, /* changed in Unicode 5.2 */
2571 { 0xd7c6, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, /* changed in Unicode 5.2 */
2572 { 0xd7c7, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2573
2574 { 0x11a8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
2575 { 0x11b8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
2576 { 0x11c8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
2577 { 0x11f9, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
2578 { 0x11fa, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, /* changed in Unicode 5.2 */
2579 { 0x11ff, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, /* changed in Unicode 5.2 */
2580 { 0x1200, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2581
2582 { 0xd7ca, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2583 { 0xd7cb, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, /* changed in Unicode 5.2 */
2584 { 0xd7fb, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, /* changed in Unicode 5.2 */
2585 { 0xd7fc, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2586
2587 { 0xac00, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
2588 { 0xac1c, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
2589 { 0xc5ec, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
2590 { 0xd788, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
2591
2592 { 0xac01, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
2593 { 0xac1b, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
2594 { 0xac1d, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
2595 { 0xc5ee, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
2596 { 0xd7a3, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
2597
2598 { 0xd7a4, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
2599
2600 { -1, 0x410, 0 }, /* version break for Unicode 4.1 */
2601
2602 { 0x00d7, UCHAR_PATTERN_SYNTAX, TRUE },
2603 { 0xfe45, UCHAR_PATTERN_SYNTAX, TRUE },
2604 { 0x0061, UCHAR_PATTERN_SYNTAX, FALSE },
2605
2606 { 0x0020, UCHAR_PATTERN_WHITE_SPACE, TRUE },
2607 { 0x0085, UCHAR_PATTERN_WHITE_SPACE, TRUE },
2608 { 0x200f, UCHAR_PATTERN_WHITE_SPACE, TRUE },
2609 { 0x00a0, UCHAR_PATTERN_WHITE_SPACE, FALSE },
2610 { 0x3000, UCHAR_PATTERN_WHITE_SPACE, FALSE },
2611
2612 { 0x1d200, UCHAR_BLOCK, UBLOCK_ANCIENT_GREEK_MUSICAL_NOTATION },
2613 { 0x2c8e, UCHAR_BLOCK, UBLOCK_COPTIC },
2614 { 0xfe17, UCHAR_BLOCK, UBLOCK_VERTICAL_FORMS },
2615
2616 { 0x1a00, UCHAR_SCRIPT, USCRIPT_BUGINESE },
2617 { 0x2cea, UCHAR_SCRIPT, USCRIPT_COPTIC },
2618 { 0xa82b, UCHAR_SCRIPT, USCRIPT_SYLOTI_NAGRI },
2619 { 0x103d0, UCHAR_SCRIPT, USCRIPT_OLD_PERSIAN },
2620
2621 { 0xcc28, UCHAR_LINE_BREAK, U_LB_H2 },
2622 { 0xcc29, UCHAR_LINE_BREAK, U_LB_H3 },
2623 { 0xac03, UCHAR_LINE_BREAK, U_LB_H3 },
2624 { 0x115f, UCHAR_LINE_BREAK, U_LB_JL },
2625 { 0x11aa, UCHAR_LINE_BREAK, U_LB_JT },
2626 { 0x11a1, UCHAR_LINE_BREAK, U_LB_JV },
2627
2628 { 0xb2c9, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_LVT },
2629 { 0x036f, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_EXTEND },
2630 { 0x0000, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_CONTROL },
2631 { 0x1160, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_V },
2632
2633 { 0x05f4, UCHAR_WORD_BREAK, U_WB_MIDLETTER },
2634 { 0x4ef0, UCHAR_WORD_BREAK, U_WB_OTHER },
2635 { 0x19d9, UCHAR_WORD_BREAK, U_WB_NUMERIC },
2636 { 0x2044, UCHAR_WORD_BREAK, U_WB_MIDNUM },
2637
2638 { 0xfffd, UCHAR_SENTENCE_BREAK, U_SB_OTHER },
2639 { 0x1ffc, UCHAR_SENTENCE_BREAK, U_SB_UPPER },
2640 { 0xff63, UCHAR_SENTENCE_BREAK, U_SB_CLOSE },
2641 { 0x2028, UCHAR_SENTENCE_BREAK, U_SB_SEP },
2642
2643 { -1, 0x520, 0 }, /* version break for Unicode 5.2 */
2644
2645 /* unassigned code points in new default Bidi R blocks */
2646 { 0x1ede4, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2647 { 0x1efe4, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
2648
2649 /* test some script codes >127 */
2650 { 0xa6e6, UCHAR_SCRIPT, USCRIPT_BAMUM },
2651 { 0xa4d0, UCHAR_SCRIPT, USCRIPT_LISU },
2652 { 0x10a7f, UCHAR_SCRIPT, USCRIPT_OLD_SOUTH_ARABIAN },
2653
2654 { -1, 0x600, 0 }, /* version break for Unicode 6.0 */
2655
2656 /* value changed in Unicode 6.0 */
2657 { 0x06C3, UCHAR_JOINING_GROUP, U_JG_TEH_MARBUTA_GOAL },
2658
2659 { -1, 0x610, 0 }, /* version break for Unicode 6.1 */
2660
2661 /* unassigned code points in new/changed default Bidi AL blocks */
2662 { 0x08ba, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2663 { 0x1eee4, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
2664
2665 { -1, 0x630, 0 }, /* version break for Unicode 6.3 */
2666
2667 /* unassigned code points in the currency symbols block now default to ET */
2668 { 0x20C0, UCHAR_BIDI_CLASS, U_EUROPEAN_NUMBER_TERMINATOR },
2669 { 0x20CF, UCHAR_BIDI_CLASS, U_EUROPEAN_NUMBER_TERMINATOR },
2670
2671 /* new property in Unicode 6.3 */
2672 { 0x0027, UCHAR_BIDI_PAIRED_BRACKET_TYPE, U_BPT_NONE },
2673 { 0x0028, UCHAR_BIDI_PAIRED_BRACKET_TYPE, U_BPT_OPEN },
2674 { 0x0029, UCHAR_BIDI_PAIRED_BRACKET_TYPE, U_BPT_CLOSE },
2675 { 0xFF5C, UCHAR_BIDI_PAIRED_BRACKET_TYPE, U_BPT_NONE },
2676 { 0xFF5B, UCHAR_BIDI_PAIRED_BRACKET_TYPE, U_BPT_OPEN },
2677 { 0xFF5D, UCHAR_BIDI_PAIRED_BRACKET_TYPE, U_BPT_CLOSE },
2678
2679 { -1, 0x700, 0 }, /* version break for Unicode 7.0 */
2680
2681 /* new character range with Joining_Group values */
2682 { 0x10ABF, UCHAR_JOINING_GROUP, U_JG_NO_JOINING_GROUP },
2683 { 0x10AC0, UCHAR_JOINING_GROUP, U_JG_MANICHAEAN_ALEPH },
2684 { 0x10AC1, UCHAR_JOINING_GROUP, U_JG_MANICHAEAN_BETH },
2685 { 0x10AEF, UCHAR_JOINING_GROUP, U_JG_MANICHAEAN_HUNDRED },
2686 { 0x10AF0, UCHAR_JOINING_GROUP, U_JG_NO_JOINING_GROUP },
2687
2688 /* undefined UProperty values */
2689 { 0x61, 0x4a7, 0 },
2690 { 0x234bc, 0x15ed, 0 }
2691 };
2692
2693 UVersionInfo version;
2694 UChar32 c;
2695 int32_t i, result, uVersion;
2696 UProperty which;
2697
2698 /* what is our Unicode version? */
2699 u_getUnicodeVersion(version);
2700 uVersion=((int32_t)version[0]<<8)|(version[1]<<4)|version[2]; /* major/minor/update version numbers */
2701
2702 u_charAge(0x20, version);
2703 if(version[0]==0) {
2704 /* no additional properties available */
2705 log_err("TestAdditionalProperties: no additional properties available, not tested\n");
2706 return;
2707 }
2708
2709 /* test u_charAge() */
2710 for(i=0; i<sizeof(charAges)/sizeof(charAges[0]); ++i) {
2711 u_charAge(charAges[i].c, version);
2712 if(0!=memcmp(version, charAges[i].version, sizeof(UVersionInfo))) {
2713 log_err("error: u_charAge(U+%04lx)={ %u, %u, %u, %u } instead of { %u, %u, %u, %u }\n",
2714 charAges[i].c,
2715 version[0], version[1], version[2], version[3],
2716 charAges[i].version[0], charAges[i].version[1], charAges[i].version[2], charAges[i].version[3]);
2717 }
2718 }
2719
2720 if( u_getIntPropertyMinValue(UCHAR_DASH)!=0 ||
2721 u_getIntPropertyMinValue(UCHAR_BIDI_CLASS)!=0 ||
2722 u_getIntPropertyMinValue(UCHAR_BLOCK)!=0 || /* j2478 */
2723 u_getIntPropertyMinValue(UCHAR_SCRIPT)!=0 || /*JB#2410*/
2724 u_getIntPropertyMinValue(0x2345)!=0
2725 ) {
2726 log_err("error: u_getIntPropertyMinValue() wrong\n");
2727 }
2728 if( u_getIntPropertyMaxValue(UCHAR_DASH)!=1) {
2729 log_err("error: u_getIntPropertyMaxValue(UCHAR_DASH) wrong\n");
2730 }
2731 if( u_getIntPropertyMaxValue(UCHAR_ID_CONTINUE)!=1) {
2732 log_err("error: u_getIntPropertyMaxValue(UCHAR_ID_CONTINUE) wrong\n");
2733 }
2734 if( u_getIntPropertyMaxValue((UProperty)(UCHAR_BINARY_LIMIT-1))!=1) {
2735 log_err("error: u_getIntPropertyMaxValue(UCHAR_BINARY_LIMIT-1) wrong\n");
2736 }
2737 if( u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS)!=(int32_t)U_CHAR_DIRECTION_COUNT-1 ) {
2738 log_err("error: u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS) wrong\n");
2739 }
2740 if( u_getIntPropertyMaxValue(UCHAR_BLOCK)!=(int32_t)UBLOCK_COUNT-1 ) {
2741 log_err("error: u_getIntPropertyMaxValue(UCHAR_BLOCK) wrong\n");
2742 }
2743 if(u_getIntPropertyMaxValue(UCHAR_LINE_BREAK)!=(int32_t)U_LB_COUNT-1) {
2744 log_err("error: u_getIntPropertyMaxValue(UCHAR_LINE_BREAK) wrong\n");
2745 }
2746 if(u_getIntPropertyMaxValue(UCHAR_SCRIPT)!=(int32_t)USCRIPT_CODE_LIMIT-1) {
2747 log_err("error: u_getIntPropertyMaxValue(UCHAR_SCRIPT) wrong\n");
2748 }
2749 if(u_getIntPropertyMaxValue(UCHAR_NUMERIC_TYPE)!=(int32_t)U_NT_COUNT-1) {
2750 log_err("error: u_getIntPropertyMaxValue(UCHAR_NUMERIC_TYPE) wrong\n");
2751 }
2752 if(u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY)!=(int32_t)U_CHAR_CATEGORY_COUNT-1) {
2753 log_err("error: u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY) wrong\n");
2754 }
2755 if(u_getIntPropertyMaxValue(UCHAR_HANGUL_SYLLABLE_TYPE)!=(int32_t)U_HST_COUNT-1) {
2756 log_err("error: u_getIntPropertyMaxValue(UCHAR_HANGUL_SYLLABLE_TYPE) wrong\n");
2757 }
2758 if(u_getIntPropertyMaxValue(UCHAR_GRAPHEME_CLUSTER_BREAK)!=(int32_t)U_GCB_COUNT-1) {
2759 log_err("error: u_getIntPropertyMaxValue(UCHAR_GRAPHEME_CLUSTER_BREAK) wrong\n");
2760 }
2761 if(u_getIntPropertyMaxValue(UCHAR_SENTENCE_BREAK)!=(int32_t)U_SB_COUNT-1) {
2762 log_err("error: u_getIntPropertyMaxValue(UCHAR_SENTENCE_BREAK) wrong\n");
2763 }
2764 if(u_getIntPropertyMaxValue(UCHAR_WORD_BREAK)!=(int32_t)U_WB_COUNT-1) {
2765 log_err("error: u_getIntPropertyMaxValue(UCHAR_WORD_BREAK) wrong\n");
2766 }
2767 if(u_getIntPropertyMaxValue(UCHAR_BIDI_PAIRED_BRACKET_TYPE)!=(int32_t)U_BPT_COUNT-1) {
2768 log_err("error: u_getIntPropertyMaxValue(UCHAR_BIDI_PAIRED_BRACKET_TYPE) wrong\n");
2769 }
2770 /*JB#2410*/
2771 if( u_getIntPropertyMaxValue(0x2345)!=-1) {
2772 log_err("error: u_getIntPropertyMaxValue(0x2345) wrong\n");
2773 }
2774 if( u_getIntPropertyMaxValue(UCHAR_DECOMPOSITION_TYPE) != (int32_t) (U_DT_COUNT - 1)) {
2775 log_err("error: u_getIntPropertyMaxValue(UCHAR_DECOMPOSITION_TYPE) wrong\n");
2776 }
2777 if( u_getIntPropertyMaxValue(UCHAR_JOINING_GROUP) != (int32_t) (U_JG_COUNT -1)) {
2778 log_err("error: u_getIntPropertyMaxValue(UCHAR_JOINING_GROUP) wrong\n");
2779 }
2780 if( u_getIntPropertyMaxValue(UCHAR_JOINING_TYPE) != (int32_t) (U_JT_COUNT -1)) {
2781 log_err("error: u_getIntPropertyMaxValue(UCHAR_JOINING_TYPE) wrong\n");
2782 }
2783 if( u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH) != (int32_t) (U_EA_COUNT -1)) {
2784 log_err("error: u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH) wrong\n");
2785 }
2786
2787 /* test u_hasBinaryProperty() and u_getIntPropertyValue() */
2788 for(i=0; i<sizeof(props)/sizeof(props[0]); ++i) {
2789 const char *whichName;
2790
2791 if(props[i][0]<0) {
2792 /* Unicode version break */
2793 if(uVersion<props[i][1]) {
2794 break; /* do not test properties that are not yet supported */
2795 } else {
2796 continue; /* skip this row */
2797 }
2798 }
2799
2800 c=(UChar32)props[i][0];
2801 which=(UProperty)props[i][1];
2802 whichName=u_getPropertyName(which, U_LONG_PROPERTY_NAME);
2803
2804 if(which<UCHAR_INT_START) {
2805 result=u_hasBinaryProperty(c, which);
2806 if(result!=props[i][2]) {
2807 log_data_err("error: u_hasBinaryProperty(U+%04lx, %s)=%d is wrong (props[%d]) - (Are you missing data?)\n",
2808 c, whichName, result, i);
2809 }
2810 }
2811
2812 result=u_getIntPropertyValue(c, which);
2813 if(result!=props[i][2]) {
2814 log_data_err("error: u_getIntPropertyValue(U+%04lx, %s)=%d is wrong, should be %d (props[%d]) - (Are you missing data?)\n",
2815 c, whichName, result, props[i][2], i);
2816 }
2817
2818 /* test separate functions, too */
2819 switch((UProperty)props[i][1]) {
2820 case UCHAR_ALPHABETIC:
2821 if(u_isUAlphabetic((UChar32)props[i][0])!=(UBool)props[i][2]) {
2822 log_err("error: u_isUAlphabetic(U+%04lx)=%d is wrong (props[%d])\n",
2823 props[i][0], result, i);
2824 }
2825 break;
2826 case UCHAR_LOWERCASE:
2827 if(u_isULowercase((UChar32)props[i][0])!=(UBool)props[i][2]) {
2828 log_err("error: u_isULowercase(U+%04lx)=%d is wrong (props[%d])\n",
2829 props[i][0], result, i);
2830 }
2831 break;
2832 case UCHAR_UPPERCASE:
2833 if(u_isUUppercase((UChar32)props[i][0])!=(UBool)props[i][2]) {
2834 log_err("error: u_isUUppercase(U+%04lx)=%d is wrong (props[%d])\n",
2835 props[i][0], result, i);
2836 }
2837 break;
2838 case UCHAR_WHITE_SPACE:
2839 if(u_isUWhiteSpace((UChar32)props[i][0])!=(UBool)props[i][2]) {
2840 log_err("error: u_isUWhiteSpace(U+%04lx)=%d is wrong (props[%d])\n",
2841 props[i][0], result, i);
2842 }
2843 break;
2844 default:
2845 break;
2846 }
2847 }
2848 }
2849
2850 static void
TestNumericProperties(void)2851 TestNumericProperties(void) {
2852 /* see UnicodeData.txt, DerivedNumericValues.txt */
2853 static const struct {
2854 UChar32 c;
2855 int32_t type;
2856 double numValue;
2857 } values[]={
2858 { 0x0F33, U_NT_NUMERIC, -1./2. },
2859 { 0x0C66, U_NT_DECIMAL, 0 },
2860 { 0x96f6, U_NT_NUMERIC, 0 },
2861 { 0xa833, U_NT_NUMERIC, 1./16. },
2862 { 0x2152, U_NT_NUMERIC, 1./10. },
2863 { 0x2151, U_NT_NUMERIC, 1./9. },
2864 { 0x1245f, U_NT_NUMERIC, 1./8. },
2865 { 0x2150, U_NT_NUMERIC, 1./7. },
2866 { 0x2159, U_NT_NUMERIC, 1./6. },
2867 { 0x09f6, U_NT_NUMERIC, 3./16. },
2868 { 0x2155, U_NT_NUMERIC, 1./5. },
2869 { 0x00BD, U_NT_NUMERIC, 1./2. },
2870 { 0x0031, U_NT_DECIMAL, 1. },
2871 { 0x4e00, U_NT_NUMERIC, 1. },
2872 { 0x58f1, U_NT_NUMERIC, 1. },
2873 { 0x10320, U_NT_NUMERIC, 1. },
2874 { 0x0F2B, U_NT_NUMERIC, 3./2. },
2875 { 0x00B2, U_NT_DIGIT, 2. },
2876 { 0x5f10, U_NT_NUMERIC, 2. },
2877 { 0x1813, U_NT_DECIMAL, 3. },
2878 { 0x5f0e, U_NT_NUMERIC, 3. },
2879 { 0x2173, U_NT_NUMERIC, 4. },
2880 { 0x8086, U_NT_NUMERIC, 4. },
2881 { 0x278E, U_NT_DIGIT, 5. },
2882 { 0x1D7F2, U_NT_DECIMAL, 6. },
2883 { 0x247A, U_NT_DIGIT, 7. },
2884 { 0x7396, U_NT_NUMERIC, 9. },
2885 { 0x1372, U_NT_NUMERIC, 10. },
2886 { 0x216B, U_NT_NUMERIC, 12. },
2887 { 0x16EE, U_NT_NUMERIC, 17. },
2888 { 0x249A, U_NT_NUMERIC, 19. },
2889 { 0x303A, U_NT_NUMERIC, 30. },
2890 { 0x5345, U_NT_NUMERIC, 30. },
2891 { 0x32B2, U_NT_NUMERIC, 37. },
2892 { 0x1375, U_NT_NUMERIC, 40. },
2893 { 0x10323, U_NT_NUMERIC, 50. },
2894 { 0x0BF1, U_NT_NUMERIC, 100. },
2895 { 0x964c, U_NT_NUMERIC, 100. },
2896 { 0x217E, U_NT_NUMERIC, 500. },
2897 { 0x2180, U_NT_NUMERIC, 1000. },
2898 { 0x4edf, U_NT_NUMERIC, 1000. },
2899 { 0x2181, U_NT_NUMERIC, 5000. },
2900 { 0x137C, U_NT_NUMERIC, 10000. },
2901 { 0x4e07, U_NT_NUMERIC, 10000. },
2902 { 0x12432, U_NT_NUMERIC, 216000. },
2903 { 0x12433, U_NT_NUMERIC, 432000. },
2904 { 0x4ebf, U_NT_NUMERIC, 100000000. },
2905 { 0x5146, U_NT_NUMERIC, 1000000000000. },
2906 { -1, U_NT_NONE, U_NO_NUMERIC_VALUE },
2907 { 0x61, U_NT_NONE, U_NO_NUMERIC_VALUE },
2908 { 0x3000, U_NT_NONE, U_NO_NUMERIC_VALUE },
2909 { 0xfffe, U_NT_NONE, U_NO_NUMERIC_VALUE },
2910 { 0x10301, U_NT_NONE, U_NO_NUMERIC_VALUE },
2911 { 0xe0033, U_NT_NONE, U_NO_NUMERIC_VALUE },
2912 { 0x10ffff, U_NT_NONE, U_NO_NUMERIC_VALUE },
2913 { 0x110000, U_NT_NONE, U_NO_NUMERIC_VALUE }
2914 };
2915
2916 double nv;
2917 UChar32 c;
2918 int32_t i, type;
2919
2920 for(i=0; i<UPRV_LENGTHOF(values); ++i) {
2921 c=values[i].c;
2922 type=u_getIntPropertyValue(c, UCHAR_NUMERIC_TYPE);
2923 nv=u_getNumericValue(c);
2924
2925 if(type!=values[i].type) {
2926 log_err("UCHAR_NUMERIC_TYPE(U+%04lx)=%d should be %d\n", c, type, values[i].type);
2927 }
2928 if(0.000001 <= fabs(nv - values[i].numValue)) {
2929 log_err("u_getNumericValue(U+%04lx)=%g should be %g\n", c, nv, values[i].numValue);
2930 }
2931 }
2932 }
2933
2934 /**
2935 * Test the property names and property value names API.
2936 */
2937 static void
TestPropertyNames(void)2938 TestPropertyNames(void) {
2939 int32_t p, v, choice=0, rev;
2940 UBool atLeastSomething = FALSE;
2941
2942 for (p=0; ; ++p) {
2943 UProperty propEnum = (UProperty)p;
2944 UBool sawProp = FALSE;
2945 if(p > 10 && !atLeastSomething) {
2946 log_data_err("Never got anything after 10 tries.\nYour data is probably fried. Quitting this test\n", p, choice);
2947 return;
2948 }
2949
2950 for (choice=0; ; ++choice) {
2951 const char* name = u_getPropertyName(propEnum, (UPropertyNameChoice)choice);
2952 if (name) {
2953 if (!sawProp)
2954 log_verbose("prop 0x%04x+%2d:", p&~0xfff, p&0xfff);
2955 log_verbose("%d=\"%s\"", choice, name);
2956 sawProp = TRUE;
2957 atLeastSomething = TRUE;
2958
2959 /* test reverse mapping */
2960 rev = u_getPropertyEnum(name);
2961 if (rev != p) {
2962 log_err("Property round-trip failure: %d -> %s -> %d\n",
2963 p, name, rev);
2964 }
2965 }
2966 if (!name && choice>0) break;
2967 }
2968 if (sawProp) {
2969 /* looks like a valid property; check the values */
2970 const char* pname = u_getPropertyName(propEnum, U_LONG_PROPERTY_NAME);
2971 int32_t max = 0;
2972 if (p == UCHAR_CANONICAL_COMBINING_CLASS) {
2973 max = 255;
2974 } else if (p == UCHAR_GENERAL_CATEGORY_MASK) {
2975 /* it's far too slow to iterate all the way up to
2976 the real max, U_GC_P_MASK */
2977 max = U_GC_NL_MASK;
2978 } else if (p == UCHAR_BLOCK) {
2979 /* UBlockCodes, unlike other values, start at 1 */
2980 max = 1;
2981 }
2982 log_verbose("\n");
2983 for (v=-1; ; ++v) {
2984 UBool sawValue = FALSE;
2985 for (choice=0; ; ++choice) {
2986 const char* vname = u_getPropertyValueName(propEnum, v, (UPropertyNameChoice)choice);
2987 if (vname) {
2988 if (!sawValue) log_verbose(" %s, value %d:", pname, v);
2989 log_verbose("%d=\"%s\"", choice, vname);
2990 sawValue = TRUE;
2991
2992 /* test reverse mapping */
2993 rev = u_getPropertyValueEnum(propEnum, vname);
2994 if (rev != v) {
2995 log_err("Value round-trip failure (%s): %d -> %s -> %d\n",
2996 pname, v, vname, rev);
2997 }
2998 }
2999 if (!vname && choice>0) break;
3000 }
3001 if (sawValue) {
3002 log_verbose("\n");
3003 }
3004 if (!sawValue && v>=max) break;
3005 }
3006 }
3007 if (!sawProp) {
3008 if (p>=UCHAR_STRING_LIMIT) {
3009 break;
3010 } else if (p>=UCHAR_DOUBLE_LIMIT) {
3011 p = UCHAR_STRING_START - 1;
3012 } else if (p>=UCHAR_MASK_LIMIT) {
3013 p = UCHAR_DOUBLE_START - 1;
3014 } else if (p>=UCHAR_INT_LIMIT) {
3015 p = UCHAR_MASK_START - 1;
3016 } else if (p>=UCHAR_BINARY_LIMIT) {
3017 p = UCHAR_INT_START - 1;
3018 }
3019 }
3020 }
3021 }
3022
3023 /**
3024 * Test the property values API. See JB#2410.
3025 */
3026 static void
TestPropertyValues(void)3027 TestPropertyValues(void) {
3028 int32_t i, p, min, max;
3029 UErrorCode ec;
3030
3031 /* Min should be 0 for everything. */
3032 /* Until JB#2478 is fixed, the one exception is UCHAR_BLOCK. */
3033 for (p=UCHAR_INT_START; p<UCHAR_INT_LIMIT; ++p) {
3034 UProperty propEnum = (UProperty)p;
3035 min = u_getIntPropertyMinValue(propEnum);
3036 if (min != 0) {
3037 if (p == UCHAR_BLOCK) {
3038 /* This is okay...for now. See JB#2487.
3039 TODO Update this for JB#2487. */
3040 } else {
3041 const char* name;
3042 name = u_getPropertyName(propEnum, U_LONG_PROPERTY_NAME);
3043 if (name == NULL)
3044 name = "<ERROR>";
3045 log_err("FAIL: u_getIntPropertyMinValue(%s) = %d, exp. 0\n",
3046 name, min);
3047 }
3048 }
3049 }
3050
3051 if( u_getIntPropertyMinValue(UCHAR_GENERAL_CATEGORY_MASK)!=0 ||
3052 u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY_MASK)!=-1) {
3053 log_err("error: u_getIntPropertyMin/MaxValue(UCHAR_GENERAL_CATEGORY_MASK) is wrong\n");
3054 }
3055
3056 /* Max should be -1 for invalid properties. */
3057 max = u_getIntPropertyMaxValue(UCHAR_INVALID_CODE);
3058 if (max != -1) {
3059 log_err("FAIL: u_getIntPropertyMaxValue(-1) = %d, exp. -1\n",
3060 max);
3061 }
3062
3063 /* Script should return USCRIPT_INVALID_CODE for an invalid code point. */
3064 for (i=0; i<2; ++i) {
3065 int32_t script;
3066 const char* desc;
3067 ec = U_ZERO_ERROR;
3068 switch (i) {
3069 case 0:
3070 script = uscript_getScript(-1, &ec);
3071 desc = "uscript_getScript(-1)";
3072 break;
3073 case 1:
3074 script = u_getIntPropertyValue(-1, UCHAR_SCRIPT);
3075 desc = "u_getIntPropertyValue(-1, UCHAR_SCRIPT)";
3076 break;
3077 default:
3078 log_err("Internal test error. Too many scripts\n");
3079 return;
3080 }
3081 /* We don't explicitly test ec. It should be U_FAILURE but it
3082 isn't documented as such. */
3083 if (script != (int32_t)USCRIPT_INVALID_CODE) {
3084 log_err("FAIL: %s = %d, exp. 0\n",
3085 desc, script);
3086 }
3087 }
3088 }
3089
3090 /* various tests for consistency of UCD data and API behavior */
3091 static void
TestConsistency()3092 TestConsistency() {
3093 char buffer[300];
3094 USet *set1, *set2, *set3, *set4;
3095 UErrorCode errorCode;
3096
3097 UChar32 start, end;
3098 int32_t i, length;
3099
3100 U_STRING_DECL(hyphenPattern, "[:Hyphen:]", 10);
3101 U_STRING_DECL(dashPattern, "[:Dash:]", 8);
3102 U_STRING_DECL(lowerPattern, "[:Lowercase:]", 13);
3103 U_STRING_DECL(formatPattern, "[:Cf:]", 6);
3104 U_STRING_DECL(alphaPattern, "[:Alphabetic:]", 14);
3105
3106 U_STRING_DECL(mathBlocksPattern,
3107 "[[:block=Mathematical Operators:][:block=Miscellaneous Mathematical Symbols-A:][:block=Miscellaneous Mathematical Symbols-B:][:block=Supplemental Mathematical Operators:][:block=Mathematical Alphanumeric Symbols:]]",
3108 214);
3109 U_STRING_DECL(mathPattern, "[:Math:]", 8);
3110 U_STRING_DECL(unassignedPattern, "[:Cn:]", 6);
3111 U_STRING_DECL(unknownPattern, "[:sc=Unknown:]", 14);
3112 U_STRING_DECL(reservedPattern, "[[:Cn:][:Co:][:Cs:]]", 20);
3113
3114 U_STRING_INIT(hyphenPattern, "[:Hyphen:]", 10);
3115 U_STRING_INIT(dashPattern, "[:Dash:]", 8);
3116 U_STRING_INIT(lowerPattern, "[:Lowercase:]", 13);
3117 U_STRING_INIT(formatPattern, "[:Cf:]", 6);
3118 U_STRING_INIT(alphaPattern, "[:Alphabetic:]", 14);
3119
3120 U_STRING_INIT(mathBlocksPattern,
3121 "[[:block=Mathematical Operators:][:block=Miscellaneous Mathematical Symbols-A:][:block=Miscellaneous Mathematical Symbols-B:][:block=Supplemental Mathematical Operators:][:block=Mathematical Alphanumeric Symbols:]]",
3122 214);
3123 U_STRING_INIT(mathPattern, "[:Math:]", 8);
3124 U_STRING_INIT(unassignedPattern, "[:Cn:]", 6);
3125 U_STRING_INIT(unknownPattern, "[:sc=Unknown:]", 14);
3126 U_STRING_INIT(reservedPattern, "[[:Cn:][:Co:][:Cs:]]", 20);
3127
3128 /*
3129 * It used to be that UCD.html and its precursors said
3130 * "Those dashes used to mark connections between pieces of words,
3131 * plus the Katakana middle dot."
3132 *
3133 * Unicode 4 changed 00AD Soft Hyphen to Cf and removed it from Dash
3134 * but not from Hyphen.
3135 * UTC 94 (2003mar) decided to leave it that way and to change UCD.html.
3136 * Therefore, do not show errors when testing the Hyphen property.
3137 */
3138 log_verbose("Starting with Unicode 4, inconsistencies with [:Hyphen:] are\n"
3139 "known to the UTC and not considered errors.\n");
3140
3141 errorCode=U_ZERO_ERROR;
3142 set1=uset_openPattern(hyphenPattern, 10, &errorCode);
3143 set2=uset_openPattern(dashPattern, 8, &errorCode);
3144 if(U_SUCCESS(errorCode)) {
3145 /* remove the Katakana middle dot(s) from set1 */
3146 uset_remove(set1, 0x30fb);
3147 uset_remove(set1, 0xff65); /* halfwidth variant */
3148 showAMinusB(set1, set2, "[:Hyphen:]", "[:Dash:]", FALSE);
3149 } else {
3150 log_data_err("error opening [:Hyphen:] or [:Dash:] - %s (Are you missing data?)\n", u_errorName(errorCode));
3151 }
3152
3153 /* check that Cf is neither Hyphen nor Dash nor Alphabetic */
3154 set3=uset_openPattern(formatPattern, 6, &errorCode);
3155 set4=uset_openPattern(alphaPattern, 14, &errorCode);
3156 if(U_SUCCESS(errorCode)) {
3157 showAIntersectB(set3, set1, "[:Cf:]", "[:Hyphen:]", FALSE);
3158 showAIntersectB(set3, set2, "[:Cf:]", "[:Dash:]", TRUE);
3159 showAIntersectB(set3, set4, "[:Cf:]", "[:Alphabetic:]", TRUE);
3160 } else {
3161 log_data_err("error opening [:Cf:] or [:Alpbabetic:] - %s (Are you missing data?)\n", u_errorName(errorCode));
3162 }
3163
3164 uset_close(set1);
3165 uset_close(set2);
3166 uset_close(set3);
3167 uset_close(set4);
3168
3169 /*
3170 * Check that each lowercase character has "small" in its name
3171 * and not "capital".
3172 * There are some such characters, some of which seem odd.
3173 * Use the verbose flag to see these notices.
3174 */
3175 errorCode=U_ZERO_ERROR;
3176 set1=uset_openPattern(lowerPattern, 13, &errorCode);
3177 if(U_SUCCESS(errorCode)) {
3178 for(i=0;; ++i) {
3179 length=uset_getItem(set1, i, &start, &end, NULL, 0, &errorCode);
3180 if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) {
3181 break; /* done */
3182 }
3183 if(U_FAILURE(errorCode)) {
3184 log_err("error iterating over [:Lowercase:] at item %d: %s\n",
3185 i, u_errorName(errorCode));
3186 break;
3187 }
3188 if(length!=0) {
3189 break; /* done with code points, got a string or -1 */
3190 }
3191
3192 while(start<=end) {
3193 length=u_charName(start, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
3194 if(U_FAILURE(errorCode)) {
3195 log_data_err("error getting the name of U+%04x - %s\n", start, u_errorName(errorCode));
3196 errorCode=U_ZERO_ERROR;
3197 }
3198 if( (strstr(buffer, "SMALL")==NULL || strstr(buffer, "CAPITAL")!=NULL) &&
3199 strstr(buffer, "SMALL CAPITAL")==NULL
3200 ) {
3201 log_verbose("info: [:Lowercase:] contains U+%04x whose name does not suggest lowercase: %s\n", start, buffer);
3202 }
3203 ++start;
3204 }
3205 }
3206 } else {
3207 log_data_err("error opening [:Lowercase:] - %s (Are you missing data?)\n", u_errorName(errorCode));
3208 }
3209 uset_close(set1);
3210
3211 /* verify that all assigned characters in Math blocks are exactly Math characters */
3212 errorCode=U_ZERO_ERROR;
3213 set1=uset_openPattern(mathBlocksPattern, -1, &errorCode);
3214 set2=uset_openPattern(mathPattern, 8, &errorCode);
3215 set3=uset_openPattern(unassignedPattern, 6, &errorCode);
3216 if(U_SUCCESS(errorCode)) {
3217 uset_retainAll(set2, set1); /* [math blocks]&[:Math:] */
3218 uset_complement(set3); /* assigned characters */
3219 uset_retainAll(set1, set3); /* [math blocks]&[assigned] */
3220 compareUSets(set1, set2,
3221 "[assigned Math block chars]", "[math blocks]&[:Math:]",
3222 TRUE);
3223 } else {
3224 log_data_err("error opening [math blocks] or [:Math:] or [:Cn:] - %s (Are you missing data?)\n", u_errorName(errorCode));
3225 }
3226 uset_close(set1);
3227 uset_close(set2);
3228 uset_close(set3);
3229
3230 /* new in Unicode 5.0: exactly all unassigned+PUA+surrogate code points have script=Unknown */
3231 errorCode=U_ZERO_ERROR;
3232 set1=uset_openPattern(unknownPattern, 14, &errorCode);
3233 set2=uset_openPattern(reservedPattern, 20, &errorCode);
3234 if(U_SUCCESS(errorCode)) {
3235 compareUSets(set1, set2,
3236 "[:sc=Unknown:]", "[[:Cn:][:Co:][:Cs:]]",
3237 TRUE);
3238 } else {
3239 log_data_err("error opening [:sc=Unknown:] or [[:Cn:][:Co:][:Cs:]] - %s (Are you missing data?)\n", u_errorName(errorCode));
3240 }
3241 uset_close(set1);
3242 uset_close(set2);
3243 }
3244
3245 /*
3246 * Starting with ICU4C 3.4, the core Unicode properties files
3247 * (uprops.icu, ucase.icu, ubidi.icu, unorm.icu)
3248 * are hardcoded in the common DLL and therefore not included
3249 * in the data package any more.
3250 * Test requiring these files are disabled so that
3251 * we need not jump through hoops (like adding snapshots of these files
3252 * to testdata).
3253 * See Jitterbug 4497.
3254 */
3255 #define HARDCODED_DATA_4497 1
3256
3257 /* API coverage for ucase.c */
TestUCase()3258 static void TestUCase() {
3259 #if !HARDCODED_DATA_4497
3260 UDataMemory *pData;
3261 UCaseProps *csp;
3262 const UCaseProps *ccsp;
3263 UErrorCode errorCode;
3264
3265 /* coverage for ucase_openBinary() */
3266 errorCode=U_ZERO_ERROR;
3267 pData=udata_open(NULL, UCASE_DATA_TYPE, UCASE_DATA_NAME, &errorCode);
3268 if(U_FAILURE(errorCode)) {
3269 log_data_err("unable to open " UCASE_DATA_NAME "." UCASE_DATA_TYPE ": %s\n",
3270 u_errorName(errorCode));
3271 return;
3272 }
3273
3274 csp=ucase_openBinary((const uint8_t *)pData->pHeader, -1, &errorCode);
3275 if(U_FAILURE(errorCode)) {
3276 log_err("ucase_openBinary() fails for the contents of " UCASE_DATA_NAME "." UCASE_DATA_TYPE ": %s\n",
3277 u_errorName(errorCode));
3278 udata_close(pData);
3279 return;
3280 }
3281
3282 if(UCASE_LOWER!=ucase_getType(csp, 0xdf)) { /* verify islower(sharp s) */
3283 log_err("ucase_openBinary() does not seem to return working UCaseProps\n");
3284 }
3285
3286 ucase_close(csp);
3287 udata_close(pData);
3288
3289 /* coverage for ucase_getDummy() */
3290 errorCode=U_ZERO_ERROR;
3291 ccsp=ucase_getDummy(&errorCode);
3292 if(ucase_tolower(ccsp, 0x41)!=0x41) {
3293 log_err("ucase_tolower(dummy, A)!=A\n");
3294 }
3295 #endif
3296 }
3297
3298 /* API coverage for ubidi_props.c */
TestUBiDiProps()3299 static void TestUBiDiProps() {
3300 #if !HARDCODED_DATA_4497
3301 UDataMemory *pData;
3302 UBiDiProps *bdp;
3303 const UBiDiProps *cbdp;
3304 UErrorCode errorCode;
3305
3306 /* coverage for ubidi_openBinary() */
3307 errorCode=U_ZERO_ERROR;
3308 pData=udata_open(NULL, UBIDI_DATA_TYPE, UBIDI_DATA_NAME, &errorCode);
3309 if(U_FAILURE(errorCode)) {
3310 log_data_err("unable to open " UBIDI_DATA_NAME "." UBIDI_DATA_TYPE ": %s\n",
3311 u_errorName(errorCode));
3312 return;
3313 }
3314
3315 bdp=ubidi_openBinary((const uint8_t *)pData->pHeader, -1, &errorCode);
3316 if(U_FAILURE(errorCode)) {
3317 log_err("ubidi_openBinary() fails for the contents of " UBIDI_DATA_NAME "." UBIDI_DATA_TYPE ": %s\n",
3318 u_errorName(errorCode));
3319 udata_close(pData);
3320 return;
3321 }
3322
3323 if(0x2215!=ubidi_getMirror(bdp, 0x29F5)) { /* verify some data */
3324 log_err("ubidi_openBinary() does not seem to return working UBiDiProps\n");
3325 }
3326
3327 ubidi_closeProps(bdp);
3328 udata_close(pData);
3329
3330 /* coverage for ubidi_getDummy() */
3331 errorCode=U_ZERO_ERROR;
3332 cbdp=ubidi_getDummy(&errorCode);
3333 if(ubidi_getClass(cbdp, 0x20)!=0) {
3334 log_err("ubidi_getClass(dummy, space)!=0\n");
3335 }
3336 #endif
3337 }
3338
3339 /* test case folding, compare return values with CaseFolding.txt ------------ */
3340
3341 /* bit set for which case foldings for a character have been tested already */
3342 enum {
3343 CF_SIMPLE=1,
3344 CF_FULL=2,
3345 CF_TURKIC=4,
3346 CF_ALL=7
3347 };
3348
3349 static void
testFold(UChar32 c,int which,UChar32 simple,UChar32 turkic,const UChar * full,int32_t fullLength,const UChar * turkicFull,int32_t turkicFullLength)3350 testFold(UChar32 c, int which,
3351 UChar32 simple, UChar32 turkic,
3352 const UChar *full, int32_t fullLength,
3353 const UChar *turkicFull, int32_t turkicFullLength) {
3354 UChar s[2], t[32];
3355 UChar32 c2;
3356 int32_t length, length2;
3357
3358 UErrorCode errorCode=U_ZERO_ERROR;
3359
3360 length=0;
3361 U16_APPEND_UNSAFE(s, length, c);
3362
3363 if((which&CF_SIMPLE)!=0 && (c2=u_foldCase(c, 0))!=simple) {
3364 log_err("u_foldCase(U+%04lx, default)=U+%04lx != U+%04lx\n", (long)c, (long)c2, (long)simple);
3365 }
3366 if((which&CF_FULL)!=0) {
3367 length2=u_strFoldCase(t, UPRV_LENGTHOF(t), s, length, 0, &errorCode);
3368 if(length2!=fullLength || 0!=u_memcmp(t, full, fullLength)) {
3369 log_err("u_strFoldCase(U+%04lx, default) does not fold properly\n", (long)c);
3370 }
3371 }
3372 if((which&CF_TURKIC)!=0) {
3373 if((c2=u_foldCase(c, U_FOLD_CASE_EXCLUDE_SPECIAL_I))!=turkic) {
3374 log_err("u_foldCase(U+%04lx, turkic)=U+%04lx != U+%04lx\n", (long)c, (long)c2, (long)simple);
3375 }
3376
3377 length2=u_strFoldCase(t, UPRV_LENGTHOF(t), s, length, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode);
3378 if(length2!=turkicFullLength || 0!=u_memcmp(t, turkicFull, length2)) {
3379 log_err("u_strFoldCase(U+%04lx, turkic) does not fold properly\n", (long)c);
3380 }
3381 }
3382 }
3383
3384 /* test that c case-folds to itself */
3385 static void
testFoldToSelf(UChar32 c,int which)3386 testFoldToSelf(UChar32 c, int which) {
3387 UChar s[2];
3388 int32_t length;
3389
3390 length=0;
3391 U16_APPEND_UNSAFE(s, length, c);
3392 testFold(c, which, c, c, s, length, s, length);
3393 }
3394
3395 struct CaseFoldingData {
3396 USet *notSeen;
3397 UChar32 prev, prevSimple;
3398 UChar prevFull[32];
3399 int32_t prevFullLength;
3400 int which;
3401 };
3402 typedef struct CaseFoldingData CaseFoldingData;
3403
3404 static void U_CALLCONV
caseFoldingLineFn(void * context,char * fields[][2],int32_t fieldCount,UErrorCode * pErrorCode)3405 caseFoldingLineFn(void *context,
3406 char *fields[][2], int32_t fieldCount,
3407 UErrorCode *pErrorCode) {
3408 CaseFoldingData *pData=(CaseFoldingData *)context;
3409 char *end;
3410 UChar full[32];
3411 UChar32 c, prev, simple;
3412 int32_t count;
3413 int which;
3414 char status;
3415
3416 /* get code point */
3417 const char *s=u_skipWhitespace(fields[0][0]);
3418 if(0==strncmp(s, "0000..10FFFF", 12)) {
3419 /*
3420 * Ignore the line
3421 * # @missing: 0000..10FFFF; C; <code point>
3422 * because maps-to-self is already our default, and this line breaks this parser.
3423 */
3424 return;
3425 }
3426 c=(UChar32)strtoul(s, &end, 16);
3427 end=(char *)u_skipWhitespace(end);
3428 if(end<=fields[0][0] || end!=fields[0][1]) {
3429 log_err("syntax error in CaseFolding.txt field 0 at %s\n", fields[0][0]);
3430 *pErrorCode=U_PARSE_ERROR;
3431 return;
3432 }
3433
3434 /* get the status of this mapping */
3435 status=*u_skipWhitespace(fields[1][0]);
3436 if(status!='C' && status!='S' && status!='F' && status!='T') {
3437 log_err("unrecognized status field in CaseFolding.txt at %s\n", fields[0][0]);
3438 *pErrorCode=U_PARSE_ERROR;
3439 return;
3440 }
3441
3442 /* get the mapping */
3443 count=u_parseString(fields[2][0], full, 32, (uint32_t *)&simple, pErrorCode);
3444 if(U_FAILURE(*pErrorCode)) {
3445 log_err("error parsing CaseFolding.txt mapping at %s\n", fields[0][0]);
3446 return;
3447 }
3448
3449 /* there is a simple mapping only if there is exactly one code point (count is in UChars) */
3450 if(count==0 || count>2 || (count==2 && U16_IS_SINGLE(full[1]))) {
3451 simple=c;
3452 }
3453
3454 if(c!=(prev=pData->prev)) {
3455 /*
3456 * Test remaining mappings for the previous code point.
3457 * If a turkic folding was not mentioned, then it should fold the same
3458 * as the regular simple case folding.
3459 */
3460 UChar prevString[2];
3461 int32_t length;
3462
3463 length=0;
3464 U16_APPEND_UNSAFE(prevString, length, prev);
3465 testFold(prev, (~pData->which)&CF_ALL,
3466 prev, pData->prevSimple,
3467 prevString, length,
3468 pData->prevFull, pData->prevFullLength);
3469 pData->prev=pData->prevSimple=c;
3470 length=0;
3471 U16_APPEND_UNSAFE(pData->prevFull, length, c);
3472 pData->prevFullLength=length;
3473 pData->which=0;
3474 }
3475
3476 /*
3477 * Turn the status into a bit set of case foldings to test.
3478 * Remember non-Turkic case foldings as defaults for Turkic mode.
3479 */
3480 switch(status) {
3481 case 'C':
3482 which=CF_SIMPLE|CF_FULL;
3483 pData->prevSimple=simple;
3484 u_memcpy(pData->prevFull, full, count);
3485 pData->prevFullLength=count;
3486 break;
3487 case 'S':
3488 which=CF_SIMPLE;
3489 pData->prevSimple=simple;
3490 break;
3491 case 'F':
3492 which=CF_FULL;
3493 u_memcpy(pData->prevFull, full, count);
3494 pData->prevFullLength=count;
3495 break;
3496 case 'T':
3497 which=CF_TURKIC;
3498 break;
3499 default:
3500 which=0;
3501 break; /* won't happen because of test above */
3502 }
3503
3504 testFold(c, which, simple, simple, full, count, full, count);
3505
3506 /* remember which case foldings of c have been tested */
3507 pData->which|=which;
3508
3509 /* remove c from the set of ones not mentioned in CaseFolding.txt */
3510 uset_remove(pData->notSeen, c);
3511 }
3512
3513 static void
TestCaseFolding()3514 TestCaseFolding() {
3515 CaseFoldingData data={ NULL };
3516 char *fields[3][2];
3517 UErrorCode errorCode;
3518
3519 static char *lastLine= (char *)"10FFFF; C; 10FFFF;";
3520
3521 errorCode=U_ZERO_ERROR;
3522 /* test BMP & plane 1 - nothing interesting above */
3523 data.notSeen=uset_open(0, 0x1ffff);
3524 data.prevFullLength=1; /* length of full case folding of U+0000 */
3525
3526 parseUCDFile("CaseFolding.txt", fields, 3, caseFoldingLineFn, &data, &errorCode);
3527 if(U_SUCCESS(errorCode)) {
3528 int32_t i, start, end;
3529
3530 /* add a pseudo-last line to finish testing of the actual last one */
3531 fields[0][0]=lastLine;
3532 fields[0][1]=lastLine+6;
3533 fields[1][0]=lastLine+7;
3534 fields[1][1]=lastLine+9;
3535 fields[2][0]=lastLine+10;
3536 fields[2][1]=lastLine+17;
3537 caseFoldingLineFn(&data, fields, 3, &errorCode);
3538
3539 /* verify that all code points that are not mentioned in CaseFolding.txt fold to themselves */
3540 for(i=0;
3541 0==uset_getItem(data.notSeen, i, &start, &end, NULL, 0, &errorCode) &&
3542 U_SUCCESS(errorCode);
3543 ++i
3544 ) {
3545 do {
3546 testFoldToSelf(start, CF_ALL);
3547 } while(++start<=end);
3548 }
3549 }
3550
3551 uset_close(data.notSeen);
3552 }
3553