| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 ******************************************************************************* | |
| 3 * Copyright (C) 1997-2009,2014 International Business Machines | |
| 4 * Corporation and others. All Rights Reserved. | |
| 5 ******************************************************************************* | |
| 6 * Date Name Description | |
| 7 * 06/23/00 aliu Creation. | |
| 8 ******************************************************************************* | |
| 9 */ | |
| 10 | |
| 11 #include "unicode/utypes.h" | |
| 12 | |
| 13 #if !UCONFIG_NO_TRANSLITERATION | |
| 14 | |
| 15 #include <stdlib.h> | |
| 16 #include <string.h> | |
| 17 #include "unicode/utrans.h" | |
| 18 #include "unicode/ustring.h" | |
| 19 #include "unicode/uset.h" | |
| 20 #include "cintltst.h" | |
| 21 | |
| 22 #define TEST(x) addTest(root, &x, "utrans/" # x) | |
| 23 | |
| 24 static void TestAPI(void); | |
| 25 static void TestSimpleRules(void); | |
| 26 static void TestFilter(void); | |
| 27 static void TestOpenInverse(void); | |
| 28 static void TestClone(void); | |
| 29 static void TestRegisterUnregister(void); | |
| 30 static void TestExtractBetween(void); | |
| 31 static void TestUnicodeIDs(void); | |
| 32 static void TestGetRulesAndSourceSet(void); | |
| 33 | |
| 34 static void _expectRules(const char*, const char*, const char*); | |
| 35 static void _expect(const UTransliterator* trans, const char* cfrom, const char*
cto); | |
| 36 | |
| 37 void addUTransTest(TestNode** root); | |
| 38 | |
| 39 | |
| 40 void | |
| 41 addUTransTest(TestNode** root) { | |
| 42 TEST(TestAPI); | |
| 43 TEST(TestSimpleRules); | |
| 44 TEST(TestFilter); | |
| 45 TEST(TestOpenInverse); | |
| 46 TEST(TestClone); | |
| 47 TEST(TestRegisterUnregister); | |
| 48 TEST(TestExtractBetween); | |
| 49 TEST(TestUnicodeIDs); | |
| 50 TEST(TestGetRulesAndSourceSet); | |
| 51 } | |
| 52 | |
| 53 /*------------------------------------------------------------------ | |
| 54 * Replaceable glue | |
| 55 * | |
| 56 * To test the Replaceable glue we have to dummy up a C-based | |
| 57 * Replaceable callback. This code is for testing purposes only. | |
| 58 *------------------------------------------------------------------*/ | |
| 59 | |
| 60 typedef struct XReplaceable { | |
| 61 UChar* text; /* MUST BE null-terminated */ | |
| 62 } XReplaceable; | |
| 63 | |
| 64 static void InitXReplaceable(XReplaceable* rep, const char* cstring) { | |
| 65 rep->text = malloc(sizeof(UChar) * (strlen(cstring)+1)); | |
| 66 u_uastrcpy(rep->text, cstring); | |
| 67 } | |
| 68 | |
| 69 static void FreeXReplaceable(XReplaceable* rep) { | |
| 70 if (rep->text != NULL) { | |
| 71 free(rep->text); | |
| 72 rep->text = NULL; | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 /* UReplaceableCallbacks callback */ | |
| 77 static int32_t Xlength(const UReplaceable* rep) { | |
| 78 const XReplaceable* x = (const XReplaceable*)rep; | |
| 79 return u_strlen(x->text); | |
| 80 } | |
| 81 | |
| 82 /* UReplaceableCallbacks callback */ | |
| 83 static UChar XcharAt(const UReplaceable* rep, int32_t offset) { | |
| 84 const XReplaceable* x = (const XReplaceable*)rep; | |
| 85 return x->text[offset]; | |
| 86 } | |
| 87 | |
| 88 /* UReplaceableCallbacks callback */ | |
| 89 static UChar32 Xchar32At(const UReplaceable* rep, int32_t offset) { | |
| 90 const XReplaceable* x = (const XReplaceable*)rep; | |
| 91 return x->text[offset]; | |
| 92 } | |
| 93 | |
| 94 /* UReplaceableCallbacks callback */ | |
| 95 static void Xreplace(UReplaceable* rep, int32_t start, int32_t limit, | |
| 96 const UChar* text, int32_t textLength) { | |
| 97 XReplaceable* x = (XReplaceable*)rep; | |
| 98 int32_t newLen = Xlength(rep) + limit - start + textLength; | |
| 99 UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1)); | |
| 100 u_strncpy(newText, x->text, start); | |
| 101 u_strncpy(newText + start, text, textLength); | |
| 102 u_strcpy(newText + start + textLength, x->text + limit); | |
| 103 free(x->text); | |
| 104 x->text = newText; | |
| 105 } | |
| 106 | |
| 107 /* UReplaceableCallbacks callback */ | |
| 108 static void Xcopy(UReplaceable* rep, int32_t start, int32_t limit, int32_t dest)
{ | |
| 109 XReplaceable* x = (XReplaceable*)rep; | |
| 110 int32_t newLen = Xlength(rep) + limit - start; | |
| 111 UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1)); | |
| 112 u_strncpy(newText, x->text, dest); | |
| 113 u_strncpy(newText + dest, x->text + start, limit - start); | |
| 114 u_strcpy(newText + dest + limit - start, x->text + dest); | |
| 115 free(x->text); | |
| 116 x->text = newText; | |
| 117 } | |
| 118 | |
| 119 /* UReplaceableCallbacks callback */ | |
| 120 static void Xextract(UReplaceable* rep, int32_t start, int32_t limit, UChar* dst
) { | |
| 121 XReplaceable* x = (XReplaceable*)rep; | |
| 122 int32_t len = limit - start; | |
| 123 u_strncpy(dst, x->text, len); | |
| 124 } | |
| 125 | |
| 126 static void InitXReplaceableCallbacks(UReplaceableCallbacks* callbacks) { | |
| 127 callbacks->length = Xlength; | |
| 128 callbacks->charAt = XcharAt; | |
| 129 callbacks->char32At = Xchar32At; | |
| 130 callbacks->replace = Xreplace; | |
| 131 callbacks->extract = Xextract; | |
| 132 callbacks->copy = Xcopy; | |
| 133 } | |
| 134 | |
| 135 /*------------------------------------------------------------------ | |
| 136 * Tests | |
| 137 *------------------------------------------------------------------*/ | |
| 138 | |
| 139 static void TestAPI() { | |
| 140 enum { BUF_CAP = 128 }; | |
| 141 char buf[BUF_CAP], buf2[BUF_CAP]; | |
| 142 UErrorCode status = U_ZERO_ERROR; | |
| 143 UTransliterator* trans = NULL; | |
| 144 int32_t i, n; | |
| 145 | |
| 146 /* Test getAvailableIDs */ | |
| 147 n = utrans_countAvailableIDs(); | |
| 148 if (n < 1) { | |
| 149 log_err("FAIL: utrans_countAvailableIDs() returned %d\n", n); | |
| 150 } else { | |
| 151 log_verbose("System ID count: %d\n", n); | |
| 152 } | |
| 153 for (i=0; i<n; ++i) { | |
| 154 utrans_getAvailableID(i, buf, BUF_CAP); | |
| 155 if (*buf == 0) { | |
| 156 log_err("FAIL: System transliterator %d: \"\"\n", i); | |
| 157 } else { | |
| 158 log_verbose("System transliterator %d: \"%s\"\n", i, buf); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 /* Test open */ | |
| 163 utrans_getAvailableID(0, buf, BUF_CAP); | |
| 164 trans = utrans_open(buf, UTRANS_FORWARD,NULL,0,NULL, &status); | |
| 165 if (U_FAILURE(status)) { | |
| 166 log_err("FAIL: utrans_open(%s) failed, error=%s\n", | |
| 167 buf, u_errorName(status)); | |
| 168 } | |
| 169 | |
| 170 else { | |
| 171 /* Test getID */ | |
| 172 utrans_getID(trans, buf2, BUF_CAP); | |
| 173 if (0 != strcmp(buf, buf2)) { | |
| 174 log_err("FAIL: utrans_getID(%s) returned %s\n", | |
| 175 buf, buf2); | |
| 176 } | |
| 177 utrans_close(trans); | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 static void TestUnicodeIDs() { | |
| 182 UEnumeration *uenum; | |
| 183 UTransliterator *utrans; | |
| 184 const UChar *id, *id2; | |
| 185 int32_t idLength, id2Length, count, count2; | |
| 186 | |
| 187 UErrorCode errorCode; | |
| 188 | |
| 189 errorCode=U_ZERO_ERROR; | |
| 190 uenum=utrans_openIDs(&errorCode); | |
| 191 if(U_FAILURE(errorCode)) { | |
| 192 log_err("utrans_openIDs() failed - %s\n", u_errorName(errorCode)); | |
| 193 return; | |
| 194 } | |
| 195 | |
| 196 count=uenum_count(uenum, &errorCode); | |
| 197 if(U_FAILURE(errorCode) || count<1) { | |
| 198 log_err("uenum_count(transliterator IDs)=%d - %s\n", count, u_errorName(
errorCode)); | |
| 199 } | |
| 200 | |
| 201 count=0; | |
| 202 for(;;) { | |
| 203 id=uenum_unext(uenum, &idLength, &errorCode); | |
| 204 if(U_FAILURE(errorCode)) { | |
| 205 log_err("uenum_unext(transliterator ID %d) failed - %s\n", count, u_
errorName(errorCode)); | |
| 206 break; | |
| 207 } | |
| 208 if(id==NULL) { | |
| 209 break; | |
| 210 } | |
| 211 | |
| 212 if(++count>10) { | |
| 213 /* try to actually open only a few transliterators */ | |
| 214 continue; | |
| 215 } | |
| 216 | |
| 217 utrans=utrans_openU(id, idLength, UTRANS_FORWARD, NULL, 0, NULL, &errorC
ode); | |
| 218 if(U_FAILURE(errorCode)) { | |
| 219 log_err("utrans_openU(%s) failed - %s\n", aescstrdup(id, idLength),
u_errorName(errorCode)); | |
| 220 continue; | |
| 221 } | |
| 222 | |
| 223 id2=utrans_getUnicodeID(utrans, &id2Length); | |
| 224 if(idLength!=id2Length || 0!=u_memcmp(id, id2, idLength)) { | |
| 225 log_err("utrans_getUnicodeID(%s) does not match the original ID\n",
aescstrdup(id, idLength)); | |
| 226 } | |
| 227 | |
| 228 utrans_close(utrans); | |
| 229 } | |
| 230 | |
| 231 uenum_reset(uenum, &errorCode); | |
| 232 if(U_FAILURE(errorCode) || count<1) { | |
| 233 log_err("uenum_reset(transliterator IDs) failed - %s\n", u_errorName(err
orCode)); | |
| 234 } else { | |
| 235 count2=uenum_count(uenum, &errorCode); | |
| 236 if(U_FAILURE(errorCode) || count<1) { | |
| 237 log_err("2nd uenum_count(transliterator IDs)=%d - %s\n", count2, u_e
rrorName(errorCode)); | |
| 238 } else if(count!=count2) { | |
| 239 log_err("uenum_unext(transliterator IDs) returned %d IDs but uenum_c
ount() after uenum_reset() claims there are %d\n", count, count2); | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 uenum_close(uenum); | |
| 244 } | |
| 245 | |
| 246 static void TestOpenInverse(){ | |
| 247 UErrorCode status=U_ZERO_ERROR; | |
| 248 UTransliterator* t1=NULL; | |
| 249 UTransliterator* inverse1=NULL; | |
| 250 enum { BUF_CAP = 128 }; | |
| 251 char buf1[BUF_CAP]; | |
| 252 int32_t i=0; | |
| 253 | |
| 254 const char TransID[][25]={ | |
| 255 "Halfwidth-Fullwidth", | |
| 256 "Fullwidth-Halfwidth", | |
| 257 "Greek-Latin" , | |
| 258 "Latin-Greek", | |
| 259 /*"Arabic-Latin", // Removed in 2.0*/ | |
| 260 /*"Latin-Arabic", // Removed in 2.0*/ | |
| 261 "Katakana-Latin", | |
| 262 "Latin-Katakana", | |
| 263 /*"Hebrew-Latin", // Removed in 2.0*/ | |
| 264 /*"Latin-Hebrew", // Removed in 2.0*/ | |
| 265 "Cyrillic-Latin", | |
| 266 "Latin-Cyrillic", | |
| 267 "Devanagari-Latin", | |
| 268 "Latin-Devanagari", | |
| 269 "Any-Hex", | |
| 270 "Hex-Any" | |
| 271 }; | |
| 272 | |
| 273 for(i=0; i<sizeof(TransID)/sizeof(TransID[0]); i=i+2){ | |
| 274 status = U_ZERO_ERROR; | |
| 275 t1=utrans_open(TransID[i], UTRANS_FORWARD,NULL,0,NULL, &status); | |
| 276 if(t1 == NULL || U_FAILURE(status)){ | |
| 277 log_data_err("FAIL: in instantiation for id=%s -> %s (Are you missin
g data?)\n", TransID[i], u_errorName(status)); | |
| 278 continue; | |
| 279 } | |
| 280 inverse1=utrans_openInverse(t1, &status); | |
| 281 if(U_FAILURE(status)){ | |
| 282 log_err("FAIL: utrans_openInverse() failed for id=%s. Error=%s\n", T
ransID[i], myErrorName(status)); | |
| 283 continue; | |
| 284 } | |
| 285 utrans_getID(inverse1, buf1, BUF_CAP); | |
| 286 if(strcmp(buf1, TransID[i+1]) != 0){ | |
| 287 log_err("FAIL :openInverse() for %s returned %s instead of %s\n", Tr
ansID[i], buf1, TransID[i+1]); | |
| 288 } | |
| 289 utrans_close(t1); | |
| 290 utrans_close(inverse1); | |
| 291 } | |
| 292 } | |
| 293 | |
| 294 static void TestClone(){ | |
| 295 UErrorCode status=U_ZERO_ERROR; | |
| 296 UTransliterator* t1=NULL; | |
| 297 UTransliterator* t2=NULL; | |
| 298 UTransliterator* t3=NULL; | |
| 299 UTransliterator* t4=NULL; | |
| 300 enum { BUF_CAP = 128 }; | |
| 301 char buf1[BUF_CAP], buf2[BUF_CAP], buf3[BUF_CAP]; | |
| 302 | |
| 303 t1=utrans_open("Latin-Devanagari", UTRANS_FORWARD, NULL,0,NULL,&status); | |
| 304 if(U_FAILURE(status)){ | |
| 305 log_data_err("FAIL: construction -> %s (Are you missing data?)\n", u_err
orName(status)); | |
| 306 return; | |
| 307 } | |
| 308 t2=utrans_open("Latin-Greek", UTRANS_FORWARD, NULL,0,NULL,&status); | |
| 309 if(U_FAILURE(status)){ | |
| 310 log_err("FAIL: construction\n"); | |
| 311 utrans_close(t1); | |
| 312 return; | |
| 313 } | |
| 314 | |
| 315 t3=utrans_clone(t1, &status); | |
| 316 t4=utrans_clone(t2, &status); | |
| 317 | |
| 318 utrans_getID(t1, buf1, BUF_CAP); | |
| 319 utrans_getID(t2, buf2, BUF_CAP); | |
| 320 utrans_getID(t3, buf3, BUF_CAP); | |
| 321 | |
| 322 if(strcmp(buf1, buf3) != 0 || | |
| 323 strcmp(buf1, buf2) == 0) { | |
| 324 log_err("FAIL: utrans_clone() failed\n"); | |
| 325 } | |
| 326 | |
| 327 utrans_getID(t4, buf3, BUF_CAP); | |
| 328 | |
| 329 if(strcmp(buf2, buf3) != 0 || | |
| 330 strcmp(buf1, buf3) == 0) { | |
| 331 log_err("FAIL: utrans_clone() failed\n"); | |
| 332 } | |
| 333 | |
| 334 utrans_close(t1); | |
| 335 utrans_close(t2); | |
| 336 utrans_close(t3); | |
| 337 utrans_close(t4); | |
| 338 | |
| 339 } | |
| 340 | |
| 341 static void TestRegisterUnregister(){ | |
| 342 UErrorCode status=U_ZERO_ERROR; | |
| 343 UTransliterator* t1=NULL; | |
| 344 UTransliterator* rules=NULL, *rules2; | |
| 345 UTransliterator* inverse1=NULL; | |
| 346 UChar rule[]={ 0x0061, 0x003c, 0x003e, 0x0063}; /*a<>b*/ | |
| 347 | |
| 348 U_STRING_DECL(ID, "TestA-TestB", 11); | |
| 349 U_STRING_INIT(ID, "TestA-TestB", 11); | |
| 350 | |
| 351 /* Make sure it doesn't exist */ | |
| 352 t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status); | |
| 353 if(t1 != NULL || U_SUCCESS(status)) { | |
| 354 log_err("FAIL: TestA-TestB already registered\n"); | |
| 355 return; | |
| 356 } | |
| 357 status=U_ZERO_ERROR; | |
| 358 /* Check inverse too */ | |
| 359 inverse1=utrans_open("TestA-TestB", UTRANS_REVERSE, NULL,0,NULL,&status); | |
| 360 if(inverse1 != NULL || U_SUCCESS(status)) { | |
| 361 log_err("FAIL: TestA-TestB already registered\n"); | |
| 362 return; | |
| 363 } | |
| 364 status=U_ZERO_ERROR; | |
| 365 /* Create it */ | |
| 366 rules=utrans_open("TestA-TestB",UTRANS_FORWARD, rule, 4, NULL, &status); | |
| 367 if(U_FAILURE(status)){ | |
| 368 log_err("FAIL: utrans_openRules(a<>B) failed with error=%s\n", myErrorNa
me(status)); | |
| 369 return; | |
| 370 } | |
| 371 | |
| 372 /* clone it so we can register it a second time */ | |
| 373 rules2=utrans_clone(rules, &status); | |
| 374 if(U_FAILURE(status)) { | |
| 375 log_err("FAIL: utrans_clone(a<>B) failed with error=%s\n", myErrorName(s
tatus)); | |
| 376 return; | |
| 377 } | |
| 378 | |
| 379 status=U_ZERO_ERROR; | |
| 380 /* Register it */ | |
| 381 utrans_register(rules, &status); | |
| 382 if(U_FAILURE(status)){ | |
| 383 log_err("FAIL: utrans_register failed with error=%s\n", myErrorName(stat
us)); | |
| 384 return; | |
| 385 } | |
| 386 status=U_ZERO_ERROR; | |
| 387 /* Now check again -- should exist now*/ | |
| 388 t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status); | |
| 389 if(U_FAILURE(status) || t1 == NULL){ | |
| 390 log_err("FAIL: TestA-TestB not registered\n"); | |
| 391 return; | |
| 392 } | |
| 393 utrans_close(t1); | |
| 394 | |
| 395 /*unregister the instance*/ | |
| 396 status=U_ZERO_ERROR; | |
| 397 utrans_unregister("TestA-TestB"); | |
| 398 /* now Make sure it doesn't exist */ | |
| 399 t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status); | |
| 400 if(U_SUCCESS(status) || t1 != NULL) { | |
| 401 log_err("FAIL: TestA-TestB isn't unregistered\n"); | |
| 402 return; | |
| 403 } | |
| 404 utrans_close(t1); | |
| 405 | |
| 406 /* now with utrans_unregisterID(const UChar *) */ | |
| 407 status=U_ZERO_ERROR; | |
| 408 utrans_register(rules2, &status); | |
| 409 if(U_FAILURE(status)){ | |
| 410 log_err("FAIL: 2nd utrans_register failed with error=%s\n", myErrorName(
status)); | |
| 411 return; | |
| 412 } | |
| 413 status=U_ZERO_ERROR; | |
| 414 /* Now check again -- should exist now*/ | |
| 415 t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status); | |
| 416 if(U_FAILURE(status) || t1 == NULL){ | |
| 417 log_err("FAIL: 2nd TestA-TestB not registered\n"); | |
| 418 return; | |
| 419 } | |
| 420 utrans_close(t1); | |
| 421 | |
| 422 /*unregister the instance*/ | |
| 423 status=U_ZERO_ERROR; | |
| 424 utrans_unregisterID(ID, -1); | |
| 425 /* now Make sure it doesn't exist */ | |
| 426 t1=utrans_openU(ID, -1, UTRANS_FORWARD,NULL,0,NULL, &status); | |
| 427 if(U_SUCCESS(status) || t1 != NULL) { | |
| 428 log_err("FAIL: 2nd TestA-TestB isn't unregistered\n"); | |
| 429 return; | |
| 430 } | |
| 431 | |
| 432 utrans_close(t1); | |
| 433 utrans_close(inverse1); | |
| 434 } | |
| 435 | |
| 436 static void TestSimpleRules() { | |
| 437 /* Test rules */ | |
| 438 /* Example: rules 1. ab>x|y | |
| 439 * 2. yc>z | |
| 440 * | |
| 441 * []|eabcd start - no match, copy e to tranlated buffer | |
| 442 * [e]|abcd match rule 1 - copy output & adjust cursor | |
| 443 * [ex|y]cd match rule 2 - copy output & adjust cursor | |
| 444 * [exz]|d no match, copy d to transliterated buffer | |
| 445 * [exzd]| done | |
| 446 */ | |
| 447 _expectRules("ab>x|y;" | |
| 448 "yc>z", | |
| 449 "eabcd", "exzd"); | |
| 450 | |
| 451 /* Another set of rules: | |
| 452 * 1. ab>x|yzacw | |
| 453 * 2. za>q | |
| 454 * 3. qc>r | |
| 455 * 4. cw>n | |
| 456 * | |
| 457 * []|ab Rule 1 | |
| 458 * [x|yzacw] No match | |
| 459 * [xy|zacw] Rule 2 | |
| 460 * [xyq|cw] Rule 4 | |
| 461 * [xyqn]| Done | |
| 462 */ | |
| 463 _expectRules("ab>x|yzacw;" | |
| 464 "za>q;" | |
| 465 "qc>r;" | |
| 466 "cw>n", | |
| 467 "ab", "xyqn"); | |
| 468 | |
| 469 /* Test categories | |
| 470 */ | |
| 471 _expectRules("$dummy=" "\\uE100" ";" /* careful here with E100 */ | |
| 472 "$vowel=[aeiouAEIOU];" | |
| 473 "$lu=[:Lu:];" | |
| 474 "$vowel } $lu > '!';" | |
| 475 "$vowel > '&';" | |
| 476 "'!' { $lu > '^';" | |
| 477 "$lu > '*';" | |
| 478 "a > ERROR", | |
| 479 "abcdefgABCDEFGU", "&bcd&fg!^**!^*&"); | |
| 480 | |
| 481 /* Test multiple passes | |
| 482 */ | |
| 483 _expectRules("abc > xy;" | |
| 484 "::Null;" | |
| 485 "aba > z;", | |
| 486 "abc ababc aba", "xy abxy z"); | |
| 487 } | |
| 488 | |
| 489 static void TestFilter() { | |
| 490 UErrorCode status = U_ZERO_ERROR; | |
| 491 UChar filt[128]; | |
| 492 UChar buf[128]; | |
| 493 UChar exp[128]; | |
| 494 char *cbuf; | |
| 495 int32_t limit; | |
| 496 const char* DATA[] = { | |
| 497 "[^c]", /* Filter out 'c' */ | |
| 498 "abcde", | |
| 499 "\\u0061\\u0062c\\u0064\\u0065", | |
| 500 | |
| 501 "", /* No filter */ | |
| 502 "abcde", | |
| 503 "\\u0061\\u0062\\u0063\\u0064\\u0065" | |
| 504 }; | |
| 505 int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]); | |
| 506 int32_t i; | |
| 507 | |
| 508 UTransliterator* hex = utrans_open("Any-Hex", UTRANS_FORWARD, NULL,0,NULL,&s
tatus); | |
| 509 | |
| 510 if (hex == 0 || U_FAILURE(status)) { | |
| 511 log_err("FAIL: utrans_open(Unicode-Hex) failed, error=%s\n", | |
| 512 u_errorName(status)); | |
| 513 goto exit; | |
| 514 } | |
| 515 | |
| 516 for (i=0; i<DATA_length; i+=3) { | |
| 517 /*u_uastrcpy(filt, DATA[i]);*/ | |
| 518 u_charsToUChars(DATA[i], filt, (int32_t)strlen(DATA[i])+1); | |
| 519 utrans_setFilter(hex, filt, -1, &status); | |
| 520 | |
| 521 if (U_FAILURE(status)) { | |
| 522 log_err("FAIL: utrans_setFilter() failed, error=%s\n", | |
| 523 u_errorName(status)); | |
| 524 goto exit; | |
| 525 } | |
| 526 | |
| 527 /*u_uastrcpy(buf, DATA[i+1]);*/ | |
| 528 u_charsToUChars(DATA[i+1], buf, (int32_t)strlen(DATA[i+1])+1); | |
| 529 limit = 5; | |
| 530 utrans_transUChars(hex, buf, NULL, 128, 0, &limit, &status); | |
| 531 | |
| 532 if (U_FAILURE(status)) { | |
| 533 log_err("FAIL: utrans_transUChars() failed, error=%s\n", | |
| 534 u_errorName(status)); | |
| 535 goto exit; | |
| 536 } | |
| 537 | |
| 538 cbuf=aescstrdup(buf, -1); | |
| 539 u_charsToUChars(DATA[i+2], exp, (int32_t)strlen(DATA[i+2])+1); | |
| 540 if (0 == u_strcmp(buf, exp)) { | |
| 541 log_verbose("Ok: %s | %s -> %s\n", DATA[i+1], DATA[i], cbuf); | |
| 542 } else { | |
| 543 log_err("FAIL: %s | %s -> %s, expected %s\n", DATA[i+1], DATA[i], cb
uf, DATA[i+2]); | |
| 544 } | |
| 545 } | |
| 546 | |
| 547 exit: | |
| 548 utrans_close(hex); | |
| 549 } | |
| 550 | |
| 551 /** | |
| 552 * Test the UReplaceableCallback extractBetween support. We use a | |
| 553 * transliterator known to rely on this call. | |
| 554 */ | |
| 555 static void TestExtractBetween() { | |
| 556 | |
| 557 UTransliterator *trans; | |
| 558 UErrorCode status = U_ZERO_ERROR; | |
| 559 UParseError parseErr; | |
| 560 | |
| 561 trans = utrans_open("Lower", UTRANS_FORWARD, NULL, -1, | |
| 562 &parseErr, &status); | |
| 563 | |
| 564 if (U_FAILURE(status)) { | |
| 565 log_err("FAIL: utrans_open(Lower) failed, error=%s\n", | |
| 566 u_errorName(status)); | |
| 567 } else { | |
| 568 _expect(trans, "ABC", "abc"); | |
| 569 | |
| 570 utrans_close(trans); | |
| 571 } | |
| 572 } | |
| 573 | |
| 574 /** | |
| 575 * Test utrans_toRules, utrans_getSourceSet | |
| 576 */ | |
| 577 | |
| 578 /* A simple transform with a small filter & source set: rules 50-100 chars unesc
aped, 100-200 chars escaped, | |
| 579 filter & source set 4-20 chars */ | |
| 580 static const UChar transSimpleID[] = { 0x79,0x6F,0x2D,0x79,0x6F,0x5F,0x42,0x4A,0
}; /* "yo-yo_BJ" */ | |
| 581 static const char* transSimpleCName = "yo-yo_BJ"; | |
| 582 | |
| 583 enum { kUBufMax = 256 }; | |
| 584 static void TestGetRulesAndSourceSet() { | |
| 585 UErrorCode status = U_ZERO_ERROR; | |
| 586 UTransliterator *utrans = utrans_openU(transSimpleID, -1, UTRANS_FORWARD, NU
LL, 0, NULL, &status); | |
| 587 if ( U_SUCCESS(status) ) { | |
| 588 USet* uset; | |
| 589 UChar ubuf[kUBufMax]; | |
| 590 int32_t ulen; | |
| 591 | |
| 592 status = U_ZERO_ERROR; | |
| 593 ulen = utrans_toRules(utrans, FALSE, ubuf, kUBufMax, &status); | |
| 594 if ( U_FAILURE(status) || ulen <= 50 || ulen >= 100) { | |
| 595 log_err("FAIL: utrans_toRules unescaped, expected noErr and len 50-1
00, got error=%s and len=%d\n", | |
| 596 u_errorName(status), ulen); | |
| 597 } | |
| 598 | |
| 599 status = U_ZERO_ERROR; | |
| 600 ulen = utrans_toRules(utrans, FALSE, NULL, 0, &status); | |
| 601 if ( status != U_BUFFER_OVERFLOW_ERROR || ulen <= 50 || ulen >= 100) { | |
| 602 log_err("FAIL: utrans_toRules unescaped, expected U_BUFFER_OVERFLOW_
ERROR and len 50-100, got error=%s and len=%d\n", | |
| 603 u_errorName(status), ulen); | |
| 604 } | |
| 605 | |
| 606 status = U_ZERO_ERROR; | |
| 607 ulen = utrans_toRules(utrans, TRUE, ubuf, kUBufMax, &status); | |
| 608 if ( U_FAILURE(status) || ulen <= 100 || ulen >= 200) { | |
| 609 log_err("FAIL: utrans_toRules escaped, expected noErr and len 100-20
0, got error=%s and len=%d\n", | |
| 610 u_errorName(status), ulen); | |
| 611 } | |
| 612 | |
| 613 status = U_ZERO_ERROR; | |
| 614 uset = utrans_getSourceSet(utrans, FALSE, NULL, &status); | |
| 615 ulen = uset_toPattern(uset, ubuf, kUBufMax, FALSE, &status); | |
| 616 uset_close(uset); | |
| 617 if ( U_FAILURE(status) || ulen <= 4 || ulen >= 20) { | |
| 618 log_err("FAIL: utrans_getSourceSet useFilter, expected noErr and len
4-20, got error=%s and len=%d\n", | |
| 619 u_errorName(status), ulen); | |
| 620 } | |
| 621 | |
| 622 status = U_ZERO_ERROR; | |
| 623 uset = utrans_getSourceSet(utrans, TRUE, NULL, &status); | |
| 624 ulen = uset_toPattern(uset, ubuf, kUBufMax, FALSE, &status); | |
| 625 uset_close(uset); | |
| 626 if ( U_FAILURE(status) || ulen <= 4 || ulen >= 20) { | |
| 627 log_err("FAIL: utrans_getSourceSet ignoreFilter, expected noErr and
len 4-20, got error=%s and len=%d\n", | |
| 628 u_errorName(status), ulen); | |
| 629 } | |
| 630 | |
| 631 utrans_close(utrans); | |
| 632 } else { | |
| 633 log_data_err("FAIL: utrans_openRules(%s) failed, error=%s (Are you missi
ng data?)\n", | |
| 634 transSimpleCName, u_errorName(status)); | |
| 635 } | |
| 636 } | |
| 637 | |
| 638 | |
| 639 static void _expectRules(const char* crules, | |
| 640 const char* cfrom, | |
| 641 const char* cto) { | |
| 642 /* u_uastrcpy has no capacity param for the buffer -- so just | |
| 643 * make all buffers way too big */ | |
| 644 enum { CAP = 256 }; | |
| 645 UChar rules[CAP]; | |
| 646 UTransliterator *trans; | |
| 647 UErrorCode status = U_ZERO_ERROR; | |
| 648 UParseError parseErr; | |
| 649 | |
| 650 u_uastrcpy(rules, crules); | |
| 651 | |
| 652 trans = utrans_open(crules /*use rules as ID*/, UTRANS_FORWARD, rules, -1, | |
| 653 &parseErr, &status); | |
| 654 if (U_FAILURE(status)) { | |
| 655 utrans_close(trans); | |
| 656 log_data_err("FAIL: utrans_openRules(%s) failed, error=%s (Are you missi
ng data?)\n", | |
| 657 crules, u_errorName(status)); | |
| 658 return; | |
| 659 } | |
| 660 | |
| 661 _expect(trans, cfrom, cto); | |
| 662 | |
| 663 utrans_close(trans); | |
| 664 } | |
| 665 | |
| 666 static void _expect(const UTransliterator* trans, | |
| 667 const char* cfrom, | |
| 668 const char* cto) { | |
| 669 /* u_uastrcpy has no capacity param for the buffer -- so just | |
| 670 * make all buffers way too big */ | |
| 671 enum { CAP = 256 }; | |
| 672 UChar from[CAP]; | |
| 673 UChar to[CAP]; | |
| 674 UChar buf[CAP]; | |
| 675 const UChar *ID; | |
| 676 int32_t IDLength; | |
| 677 const char *id; | |
| 678 | |
| 679 UErrorCode status = U_ZERO_ERROR; | |
| 680 int32_t limit; | |
| 681 UTransPosition pos; | |
| 682 XReplaceable xrep; | |
| 683 XReplaceable *xrepPtr = &xrep; | |
| 684 UReplaceableCallbacks xrepVtable; | |
| 685 | |
| 686 u_uastrcpy(from, cfrom); | |
| 687 u_uastrcpy(to, cto); | |
| 688 | |
| 689 ID = utrans_getUnicodeID(trans, &IDLength); | |
| 690 id = aescstrdup(ID, IDLength); | |
| 691 | |
| 692 /* utrans_transUChars() */ | |
| 693 u_strcpy(buf, from); | |
| 694 limit = u_strlen(buf); | |
| 695 utrans_transUChars(trans, buf, NULL, CAP, 0, &limit, &status); | |
| 696 if (U_FAILURE(status)) { | |
| 697 log_err("FAIL: utrans_transUChars() failed, error=%s\n", | |
| 698 u_errorName(status)); | |
| 699 return; | |
| 700 } | |
| 701 | |
| 702 if (0 == u_strcmp(buf, to)) { | |
| 703 log_verbose("Ok: utrans_transUChars(%s) x %s -> %s\n", | |
| 704 id, cfrom, cto); | |
| 705 } else { | |
| 706 char actual[CAP]; | |
| 707 u_austrcpy(actual, buf); | |
| 708 log_err("FAIL: utrans_transUChars(%s) x %s -> %s, expected %s\n", | |
| 709 id, cfrom, actual, cto); | |
| 710 } | |
| 711 | |
| 712 /* utrans_transIncrementalUChars() */ | |
| 713 u_strcpy(buf, from); | |
| 714 pos.start = pos.contextStart = 0; | |
| 715 pos.limit = pos.contextLimit = u_strlen(buf); | |
| 716 utrans_transIncrementalUChars(trans, buf, NULL, CAP, &pos, &status); | |
| 717 utrans_transUChars(trans, buf, NULL, CAP, pos.start, &pos.limit, &status); | |
| 718 if (U_FAILURE(status)) { | |
| 719 log_err("FAIL: utrans_transIncrementalUChars() failed, error=%s\n", | |
| 720 u_errorName(status)); | |
| 721 return; | |
| 722 } | |
| 723 | |
| 724 if (0 == u_strcmp(buf, to)) { | |
| 725 log_verbose("Ok: utrans_transIncrementalUChars(%s) x %s -> %s\n", | |
| 726 id, cfrom, cto); | |
| 727 } else { | |
| 728 char actual[CAP]; | |
| 729 u_austrcpy(actual, buf); | |
| 730 log_err("FAIL: utrans_transIncrementalUChars(%s) x %s -> %s, expected %s
\n", | |
| 731 id, cfrom, actual, cto); | |
| 732 } | |
| 733 | |
| 734 /* utrans_trans() */ | |
| 735 InitXReplaceableCallbacks(&xrepVtable); | |
| 736 InitXReplaceable(&xrep, cfrom); | |
| 737 limit = u_strlen(from); | |
| 738 utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, 0, &limit, &status)
; | |
| 739 if (U_FAILURE(status)) { | |
| 740 log_err("FAIL: utrans_trans() failed, error=%s\n", | |
| 741 u_errorName(status)); | |
| 742 FreeXReplaceable(&xrep); | |
| 743 return; | |
| 744 } | |
| 745 | |
| 746 if (0 == u_strcmp(xrep.text, to)) { | |
| 747 log_verbose("Ok: utrans_trans(%s) x %s -> %s\n", | |
| 748 id, cfrom, cto); | |
| 749 } else { | |
| 750 char actual[CAP]; | |
| 751 u_austrcpy(actual, xrep.text); | |
| 752 log_err("FAIL: utrans_trans(%s) x %s -> %s, expected %s\n", | |
| 753 id, cfrom, actual, cto); | |
| 754 } | |
| 755 FreeXReplaceable(&xrep); | |
| 756 | |
| 757 /* utrans_transIncremental() */ | |
| 758 InitXReplaceable(&xrep, cfrom); | |
| 759 pos.start = pos.contextStart = 0; | |
| 760 pos.limit = pos.contextLimit = u_strlen(from); | |
| 761 utrans_transIncremental(trans, (UReplaceable*)xrepPtr, &xrepVtable, &pos, &s
tatus); | |
| 762 utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, pos.start, &pos.lim
it, &status); | |
| 763 if (U_FAILURE(status)) { | |
| 764 log_err("FAIL: utrans_transIncremental() failed, error=%s\n", | |
| 765 u_errorName(status)); | |
| 766 FreeXReplaceable(&xrep); | |
| 767 return; | |
| 768 } | |
| 769 | |
| 770 if (0 == u_strcmp(xrep.text, to)) { | |
| 771 log_verbose("Ok: utrans_transIncremental(%s) x %s -> %s\n", | |
| 772 id, cfrom, cto); | |
| 773 } else { | |
| 774 char actual[CAP]; | |
| 775 u_austrcpy(actual, xrep.text); | |
| 776 log_err("FAIL: utrans_transIncremental(%s) x %s -> %s, expected %s\n", | |
| 777 id, cfrom, actual, cto); | |
| 778 } | |
| 779 FreeXReplaceable(&xrep); | |
| 780 } | |
| 781 | |
| 782 #endif /* #if !UCONFIG_NO_TRANSLITERATION */ | |
| OLD | NEW |