1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2010, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 7 #include "cintltst.h" 8 #include "unicode/ures.h" 9 #include "unicode/ucurr.h" 10 #include "unicode/ustring.h" 11 #include "unicode/uset.h" 12 #include "unicode/udat.h" 13 #include "unicode/uscript.h" 14 #include "unicode/ulocdata.h" 15 #include "cstring.h" 16 #include "locmap.h" 17 #include "uresimp.h" 18 19 /*-------------------------------------------------------------------- 20 Time bomb - allows temporary behavior that expires at a given 21 release 22 ---------------------------------------------------------------------*/ 23 static const UVersionInfo ICU_37 = {3,7,0,0}; 24 25 /* 26 returns a new UnicodeSet that is a flattened form of the original 27 UnicodeSet. 28 */ 29 static USet* 30 createFlattenSet(USet *origSet, UErrorCode *status) { 31 32 33 USet *newSet = NULL; 34 int32_t origItemCount = 0; 35 int32_t idx, graphmeSize; 36 UChar32 start, end; 37 UChar graphme[64]; 38 if (U_FAILURE(*status)) { 39 log_err("createFlattenSet called with %s\n", u_errorName(*status)); 40 return NULL; 41 } 42 newSet = uset_open(1, 0); 43 origItemCount = uset_getItemCount(origSet); 44 for (idx = 0; idx < origItemCount; idx++) { 45 graphmeSize = uset_getItem(origSet, idx, 46 &start, &end, 47 graphme, (int32_t)(sizeof(graphme)/sizeof(graphme[0])), 48 status); 49 if (U_FAILURE(*status)) { 50 log_err("ERROR: uset_getItem returned %s\n", u_errorName(*status)); 51 *status = U_ZERO_ERROR; 52 } 53 if (graphmeSize) { 54 uset_addAllCodePoints(newSet, graphme, graphmeSize); 55 } 56 else { 57 uset_addRange(newSet, start, end); 58 } 59 } 60 return newSet; 61 } 62 static UBool 63 isCurrencyPreEuro(const char* currencyKey){ 64 if( strcmp(currencyKey, "PTE") == 0 || 65 strcmp(currencyKey, "ESP") == 0 || 66 strcmp(currencyKey, "LUF") == 0 || 67 strcmp(currencyKey, "GRD") == 0 || 68 strcmp(currencyKey, "BEF") == 0 || 69 strcmp(currencyKey, "ITL") == 0 || 70 strcmp(currencyKey, "EEK") == 0){ 71 return TRUE; 72 } 73 return FALSE; 74 } 75 static void 76 TestKeyInRootRecursive(UResourceBundle *root, const char *rootName, 77 UResourceBundle *currentBundle, const char *locale) { 78 UErrorCode errorCode = U_ZERO_ERROR; 79 UResourceBundle *subRootBundle = NULL, *subBundle = NULL, *arr = NULL; 80 81 ures_resetIterator(root); 82 ures_resetIterator(currentBundle); 83 while (ures_hasNext(currentBundle)) { 84 const char *subBundleKey = NULL; 85 const char *currentBundleKey = NULL; 86 87 errorCode = U_ZERO_ERROR; 88 currentBundleKey = ures_getKey(currentBundle); 89 subBundle = ures_getNextResource(currentBundle, NULL, &errorCode); 90 if (U_FAILURE(errorCode)) { 91 log_err("Can't open a resource for lnocale %s. Error: %s\n", locale, u_errorName(errorCode)); 92 continue; 93 } 94 subBundleKey = ures_getKey(subBundle); 95 96 97 subRootBundle = ures_getByKey(root, subBundleKey, NULL, &errorCode); 98 if (U_FAILURE(errorCode)) { 99 log_err("Can't open a resource with key \"%s\" in \"%s\" from %s for locale \"%s\"\n", 100 subBundleKey, 101 ures_getKey(currentBundle), 102 rootName, 103 locale); 104 ures_close(subBundle); 105 continue; 106 } 107 if (ures_getType(subRootBundle) != ures_getType(subBundle)) { 108 log_err("key \"%s\" in \"%s\" has a different type from root for locale \"%s\"\n" 109 "\troot=%d, locale=%d\n", 110 subBundleKey, 111 ures_getKey(currentBundle), 112 locale, 113 ures_getType(subRootBundle), 114 ures_getType(subBundle)); 115 ures_close(subBundle); 116 continue; 117 } 118 else if (ures_getType(subBundle) == URES_INT_VECTOR) { 119 int32_t minSize; 120 int32_t subBundleSize; 121 int32_t idx; 122 UBool sameArray = TRUE; 123 const int32_t *subRootBundleArr = ures_getIntVector(subRootBundle, &minSize, &errorCode); 124 const int32_t *subBundleArr = ures_getIntVector(subBundle, &subBundleSize, &errorCode); 125 126 if (minSize > subBundleSize) { 127 minSize = subBundleSize; 128 log_err("Arrays are different size with key \"%s\" in \"%s\" from root for locale \"%s\"\n", 129 subBundleKey, 130 ures_getKey(currentBundle), 131 locale); 132 } 133 134 for (idx = 0; idx < minSize && sameArray; idx++) { 135 if (subRootBundleArr[idx] != subBundleArr[idx]) { 136 sameArray = FALSE; 137 } 138 if (strcmp(subBundleKey, "DateTimeElements") == 0 139 && (subBundleArr[idx] < 1 || 7 < subBundleArr[idx])) 140 { 141 log_err("Value out of range with key \"%s\" at index %d in \"%s\" for locale \"%s\"\n", 142 subBundleKey, 143 idx, 144 ures_getKey(currentBundle), 145 locale); 146 } 147 } 148 /* Special exception es_US and DateTimeElements */ 149 if (sameArray 150 && !(strcmp(locale, "es_US") == 0 && strcmp(subBundleKey, "DateTimeElements") == 0)) 151 { 152 log_err("Integer vectors are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n", 153 subBundleKey, 154 ures_getKey(currentBundle), 155 locale); 156 } 157 } 158 else if (ures_getType(subBundle) == URES_ARRAY) { 159 UResourceBundle *subSubBundle = ures_getByIndex(subBundle, 0, NULL, &errorCode); 160 UResourceBundle *subSubRootBundle = ures_getByIndex(subRootBundle, 0, NULL, &errorCode); 161 162 if (U_SUCCESS(errorCode) 163 && (ures_getType(subSubBundle) == URES_ARRAY || ures_getType(subSubRootBundle) == URES_ARRAY)) 164 { 165 /* Here is one of the recursive parts */ 166 TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale); 167 } 168 else { 169 int32_t minSize = ures_getSize(subRootBundle); 170 int32_t idx; 171 UBool sameArray = TRUE; 172 173 if (minSize > ures_getSize(subBundle)) { 174 minSize = ures_getSize(subBundle); 175 } 176 177 if ((subBundleKey == NULL 178 || (subBundleKey != NULL && strcmp(subBundleKey, "LocaleScript") != 0 && !isCurrencyPreEuro(subBundleKey))) 179 && ures_getSize(subRootBundle) != ures_getSize(subBundle)) 180 { 181 log_err("Different size array with key \"%s\" in \"%s\" from root for locale \"%s\"\n" 182 "\troot array size=%d, locale array size=%d\n", 183 subBundleKey, 184 ures_getKey(currentBundle), 185 locale, 186 ures_getSize(subRootBundle), 187 ures_getSize(subBundle)); 188 } 189 /* 190 if(isCurrencyPreEuro(subBundleKey) && ures_getSize(subBundle)!=3){ 191 log_err("Different size array with key \"%s\" in \"%s\" for locale \"%s\" the expected size is 3 got size=%d\n", 192 subBundleKey, 193 ures_getKey(currentBundle), 194 locale, 195 ures_getSize(subBundle)); 196 } 197 */ 198 for (idx = 0; idx < minSize; idx++) { 199 int32_t rootStrLen, localeStrLen; 200 const UChar *rootStr = ures_getStringByIndex(subRootBundle,idx,&rootStrLen,&errorCode); 201 const UChar *localeStr = ures_getStringByIndex(subBundle,idx,&localeStrLen,&errorCode); 202 if (rootStr && localeStr && U_SUCCESS(errorCode)) { 203 if (u_strcmp(rootStr, localeStr) != 0) { 204 sameArray = FALSE; 205 } 206 } 207 else { 208 if ( rootStrLen > 1 && rootStr[0] == 0x41 && rootStr[1] >= 0x30 && rootStr[1] <= 0x39 ) { 209 /* A2 or A4 in the root string indicates that the resource can optionally be an array instead of a */ 210 /* string. Attempt to read it as an array. */ 211 errorCode = U_ZERO_ERROR; 212 arr = ures_getByIndex(subBundle,idx,NULL,&errorCode); 213 if (U_FAILURE(errorCode)) { 214 log_err("Got a NULL string with key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n", 215 subBundleKey, 216 ures_getKey(currentBundle), 217 idx, 218 locale); 219 continue; 220 } 221 if (ures_getType(arr) != URES_ARRAY || ures_getSize(arr) != (int32_t)rootStr[1] - 0x30) { 222 log_err("Got something other than a string or array of size %d for key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n", 223 rootStr[1] - 0x30, 224 subBundleKey, 225 ures_getKey(currentBundle), 226 idx, 227 locale); 228 ures_close(arr); 229 continue; 230 } 231 localeStr = ures_getStringByIndex(arr,0,&localeStrLen,&errorCode); 232 ures_close(arr); 233 if (U_FAILURE(errorCode)) { 234 log_err("Got something other than a string or array for key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n", 235 subBundleKey, 236 ures_getKey(currentBundle), 237 idx, 238 locale); 239 continue; 240 } 241 } else { 242 log_err("Got a NULL string with key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n", 243 subBundleKey, 244 ures_getKey(currentBundle), 245 idx, 246 locale); 247 continue; 248 } 249 } 250 if (localeStr[0] == (UChar)0x20) { 251 log_err("key \"%s\" at index %d in \"%s\" starts with a space in locale \"%s\"\n", 252 subBundleKey, 253 idx, 254 ures_getKey(currentBundle), 255 locale); 256 } 257 else if ((localeStr[localeStrLen - 1] == (UChar)0x20) && (strcmp(subBundleKey,"separator") != 0)) { 258 log_err("key \"%s\" at index %d in \"%s\" ends with a space in locale \"%s\"\n", 259 subBundleKey, 260 idx, 261 ures_getKey(currentBundle), 262 locale); 263 } 264 else if (subBundleKey != NULL 265 && strcmp(subBundleKey, "DateTimePatterns") == 0) 266 { 267 int32_t quoted = 0; 268 const UChar *localeStrItr = localeStr; 269 while (*localeStrItr) { 270 if (*localeStrItr == (UChar)0x27 /* ' */) { 271 quoted++; 272 } 273 else if ((quoted % 2) == 0) { 274 /* Search for unquoted characters */ 275 if (4 <= idx && idx <= 7 276 && (*localeStrItr == (UChar)0x6B /* k */ 277 || *localeStrItr == (UChar)0x48 /* H */ 278 || *localeStrItr == (UChar)0x6D /* m */ 279 || *localeStrItr == (UChar)0x73 /* s */ 280 || *localeStrItr == (UChar)0x53 /* S */ 281 || *localeStrItr == (UChar)0x61 /* a */ 282 || *localeStrItr == (UChar)0x68 /* h */ 283 || *localeStrItr == (UChar)0x7A /* z */)) 284 { 285 log_err("key \"%s\" at index %d has time pattern chars in date for locale \"%s\"\n", 286 subBundleKey, 287 idx, 288 locale); 289 } 290 else if (0 <= idx && idx <= 3 291 && (*localeStrItr == (UChar)0x47 /* G */ 292 || *localeStrItr == (UChar)0x79 /* y */ 293 || *localeStrItr == (UChar)0x4D /* M */ 294 || *localeStrItr == (UChar)0x64 /* d */ 295 || *localeStrItr == (UChar)0x45 /* E */ 296 || *localeStrItr == (UChar)0x44 /* D */ 297 || *localeStrItr == (UChar)0x46 /* F */ 298 || *localeStrItr == (UChar)0x77 /* w */ 299 || *localeStrItr == (UChar)0x57 /* W */)) 300 { 301 log_err("key \"%s\" at index %d has date pattern chars in time for locale \"%s\"\n", 302 subBundleKey, 303 idx, 304 locale); 305 } 306 } 307 localeStrItr++; 308 } 309 } 310 else if (idx == 4 && subBundleKey != NULL 311 && strcmp(subBundleKey, "NumberElements") == 0 312 && u_charDigitValue(localeStr[0]) != 0) 313 { 314 log_err("key \"%s\" at index %d has a non-zero based number for locale \"%s\"\n", 315 subBundleKey, 316 idx, 317 locale); 318 } 319 } 320 /* if (sameArray && strcmp(rootName, "root") == 0) { 321 log_err("Arrays are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n", 322 subBundleKey, 323 ures_getKey(currentBundle), 324 locale); 325 }*/ 326 } 327 ures_close(subSubBundle); 328 ures_close(subSubRootBundle); 329 } 330 else if (ures_getType(subBundle) == URES_STRING) { 331 int32_t len = 0; 332 const UChar *string = ures_getString(subBundle, &len, &errorCode); 333 if (U_FAILURE(errorCode) || string == NULL) { 334 log_err("Can't open a string with key \"%s\" in \"%s\" for locale \"%s\"\n", 335 subBundleKey, 336 ures_getKey(currentBundle), 337 locale); 338 } else if (string[0] == (UChar)0x20) { 339 log_err("key \"%s\" in \"%s\" starts with a space in locale \"%s\"\n", 340 subBundleKey, 341 ures_getKey(currentBundle), 342 locale); 343 /* localeDisplayPattern/separator can end with a space */ 344 } else if (string[len - 1] == (UChar)0x20 && (strcmp(subBundleKey,"separator"))) { 345 log_err("key \"%s\" in \"%s\" ends with a space in locale \"%s\"\n", 346 subBundleKey, 347 ures_getKey(currentBundle), 348 locale); 349 } else if (strcmp(subBundleKey, "localPatternChars") == 0) { 350 /* Note: We no longer import localPatternChars data starting 351 * ICU 3.8. So it never comes into this else if block. (ticket#5597) 352 */ 353 354 /* Check well-formedness of localPatternChars. First, the 355 * length must match the number of fields defined by 356 * DateFormat. Second, each character in the string must 357 * be in the set [A-Za-z]. Finally, each character must be 358 * unique. 359 */ 360 int32_t i,j; 361 #if !UCONFIG_NO_FORMATTING 362 if (len != UDAT_FIELD_COUNT) { 363 log_err("key \"%s\" has the wrong number of characters in locale \"%s\"\n", 364 subBundleKey, 365 locale); 366 } 367 #endif 368 /* Check char validity. */ 369 for (i=0; i<len; ++i) { 370 if (!((string[i] >= 65/*'A'*/ && string[i] <= 90/*'Z'*/) || 371 (string[i] >= 97/*'a'*/ && string[i] <= 122/*'z'*/))) { 372 log_err("key \"%s\" has illegal character '%c' in locale \"%s\"\n", 373 subBundleKey, 374 (char) string[i], 375 locale); 376 } 377 /* Do O(n^2) check for duplicate chars. */ 378 for (j=0; j<i; ++j) { 379 if (string[j] == string[i]) { 380 log_err("key \"%s\" has duplicate character '%c' in locale \"%s\"\n", 381 subBundleKey, 382 (char) string[i], 383 locale); 384 } 385 } 386 } 387 } 388 /* No fallback was done. Check for duplicate data */ 389 /* The ures_* API does not do fallback of sub-resource bundles, 390 So we can't do this now. */ 391 #if 0 392 else if (strcmp(locale, "root") != 0 && errorCode == U_ZERO_ERROR) { 393 394 const UChar *rootString = ures_getString(subRootBundle, &len, &errorCode); 395 if (U_FAILURE(errorCode) || rootString == NULL) { 396 log_err("Can't open a string with key \"%s\" in \"%s\" in root\n", 397 ures_getKey(subRootBundle), 398 ures_getKey(currentBundle)); 399 continue; 400 } else if (u_strcmp(string, rootString) == 0) { 401 if (strcmp(locale, "de_CH") != 0 && strcmp(subBundleKey, "Countries") != 0 && 402 strcmp(subBundleKey, "Version") != 0) { 403 log_err("Found duplicate data with key \"%s\" in \"%s\" in locale \"%s\"\n", 404 ures_getKey(subRootBundle), 405 ures_getKey(currentBundle), 406 locale); 407 } 408 else { 409 /* Ignore for now. */ 410 /* Can be fixed if fallback through de locale was done. */ 411 log_verbose("Skipping key %s in %s\n", subBundleKey, locale); 412 } 413 } 414 } 415 #endif 416 } 417 else if (ures_getType(subBundle) == URES_TABLE) { 418 if (strcmp(subBundleKey, "availableFormats")!=0) { 419 /* Here is one of the recursive parts */ 420 TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale); 421 } 422 else { 423 log_verbose("Skipping key %s in %s\n", subBundleKey, locale); 424 } 425 } 426 else if (ures_getType(subBundle) == URES_BINARY || ures_getType(subBundle) == URES_INT) { 427 /* Can't do anything to check it */ 428 /* We'll assume it's all correct */ 429 if (strcmp(subBundleKey, "MeasurementSystem") != 0) { 430 log_verbose("Skipping key \"%s\" in \"%s\" for locale \"%s\"\n", 431 subBundleKey, 432 ures_getKey(currentBundle), 433 locale); 434 } 435 /* Testing for MeasurementSystem is done in VerifyTranslation */ 436 } 437 else { 438 log_err("Type %d for key \"%s\" in \"%s\" is unknown for locale \"%s\"\n", 439 ures_getType(subBundle), 440 subBundleKey, 441 ures_getKey(currentBundle), 442 locale); 443 } 444 ures_close(subRootBundle); 445 ures_close(subBundle); 446 } 447 } 448 449 450 static void 451 testLCID(UResourceBundle *currentBundle, 452 const char *localeName) 453 { 454 UErrorCode status = U_ZERO_ERROR; 455 uint32_t expectedLCID; 456 char lcidStringC[64] = {0}; 457 458 expectedLCID = uloc_getLCID(localeName); 459 if (expectedLCID == 0) { 460 log_verbose("INFO: %-5s does not have any LCID mapping\n", 461 localeName); 462 return; 463 } 464 465 status = U_ZERO_ERROR; 466 uprv_strcpy(lcidStringC, uprv_convertToPosix(expectedLCID, &status)); 467 if (U_FAILURE(status)) { 468 log_err("ERROR: %.4x does not have a POSIX mapping due to %s\n", 469 expectedLCID, u_errorName(status)); 470 } 471 472 if(strcmp(localeName, lcidStringC) != 0) { 473 char langName[1024]; 474 char langLCID[1024]; 475 uloc_getLanguage(localeName, langName, sizeof(langName), &status); 476 uloc_getLanguage(lcidStringC, langLCID, sizeof(langLCID), &status); 477 478 if (strcmp(langName, langLCID) == 0) { 479 log_verbose("WARNING: %-5s resolves to %s (0x%.4x)\n", 480 localeName, lcidStringC, expectedLCID); 481 } 482 else { 483 log_err("ERROR: %-5s has 0x%.4x and the number resolves wrongfully to %s\n", 484 localeName, expectedLCID, lcidStringC); 485 } 486 } 487 } 488 489 static void 490 TestLocaleStructure(void) { 491 UResourceBundle *root, *currentLocale; 492 int32_t locCount = uloc_countAvailable(); 493 int32_t locIndex; 494 UErrorCode errorCode = U_ZERO_ERROR; 495 const char *currLoc, *resolvedLoc; 496 497 /* TODO: Compare against parent's data too. This code can't handle fallbacks that some tools do already. */ 498 /* char locName[ULOC_FULLNAME_CAPACITY]; 499 char *locNamePtr; 500 501 for (locIndex = 0; locIndex < locCount; locIndex++) { 502 errorCode=U_ZERO_ERROR; 503 strcpy(locName, uloc_getAvailable(locIndex)); 504 locNamePtr = strrchr(locName, '_'); 505 if (locNamePtr) { 506 *locNamePtr = 0; 507 } 508 else { 509 strcpy(locName, "root"); 510 } 511 512 root = ures_openDirect(NULL, locName, &errorCode); 513 if(U_FAILURE(errorCode)) { 514 log_err("Can't open %s\n", locName); 515 continue; 516 } 517 */ 518 if (locCount <= 1) { 519 log_data_err("At least root needs to be installed\n"); 520 } 521 522 root = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); 523 if(U_FAILURE(errorCode)) { 524 log_data_err("Can't open structLocale\n"); 525 return; 526 } 527 for (locIndex = 0; locIndex < locCount; locIndex++) { 528 errorCode=U_ZERO_ERROR; 529 currLoc = uloc_getAvailable(locIndex); 530 currentLocale = ures_open(NULL, currLoc, &errorCode); 531 if(errorCode != U_ZERO_ERROR) { 532 if(U_SUCCESS(errorCode)) { 533 /* It's installed, but there is no data. 534 It's installed for the g18n white paper [grhoten] */ 535 log_err("ERROR: Locale %-5s not installed, and it should be, err %s\n", 536 uloc_getAvailable(locIndex), u_errorName(errorCode)); 537 } else { 538 log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", 539 u_errorName(errorCode), 540 uloc_getAvailable(locIndex)); 541 } 542 ures_close(currentLocale); 543 continue; 544 } 545 ures_getStringByKey(currentLocale, "Version", NULL, &errorCode); 546 if(errorCode != U_ZERO_ERROR) { 547 log_err("No version information is available for locale %s, and it should be!\n", 548 currLoc); 549 } 550 else if (ures_getStringByKey(currentLocale, "Version", NULL, &errorCode)[0] == (UChar)(0x78)) { 551 log_verbose("WARNING: The locale %s is experimental! It shouldn't be listed as an installed locale.\n", 552 currLoc); 553 } 554 resolvedLoc = ures_getLocaleByType(currentLocale, ULOC_ACTUAL_LOCALE, &errorCode); 555 if (strcmp(resolvedLoc, currLoc) != 0) { 556 /* All locales have at least a Version resource. 557 If it's absolutely empty, then the previous test will fail too.*/ 558 log_err("Locale resolves to different locale. Is %s an alias of %s?\n", 559 currLoc, resolvedLoc); 560 } 561 TestKeyInRootRecursive(root, "root", currentLocale, currLoc); 562 563 testLCID(currentLocale, currLoc); 564 565 ures_close(currentLocale); 566 } 567 568 ures_close(root); 569 } 570 571 static void 572 compareArrays(const char *keyName, 573 UResourceBundle *fromArray, const char *fromLocale, 574 UResourceBundle *toArray, const char *toLocale, 575 int32_t start, int32_t end) 576 { 577 int32_t fromSize = ures_getSize(fromArray); 578 int32_t toSize = ures_getSize(fromArray); 579 int32_t idx; 580 UErrorCode errorCode = U_ZERO_ERROR; 581 582 if (fromSize > toSize) { 583 fromSize = toSize; 584 log_err("Arrays are different size from \"%s\" to \"%s\"\n", 585 fromLocale, 586 toLocale); 587 } 588 589 for (idx = start; idx <= end; idx++) { 590 const UChar *fromBundleStr = ures_getStringByIndex(fromArray, idx, NULL, &errorCode); 591 const UChar *toBundleStr = ures_getStringByIndex(toArray, idx, NULL, &errorCode); 592 if (fromBundleStr && toBundleStr && u_strcmp(fromBundleStr, toBundleStr) != 0) 593 { 594 log_err("Difference for %s at index %d from %s= \"%s\" to %s= \"%s\"\n", 595 keyName, 596 idx, 597 fromLocale, 598 austrdup(fromBundleStr), 599 toLocale, 600 austrdup(toBundleStr)); 601 } 602 } 603 } 604 605 static void 606 compareConsistentCountryInfo(const char *fromLocale, const char *toLocale) { 607 UErrorCode errorCode = U_ZERO_ERROR; 608 UResourceBundle *fromDateTimeElements, *toDateTimeElements, *fromWeekendData = NULL, *toWeekendData = NULL; 609 UResourceBundle *fromArray, *toArray; 610 UResourceBundle *fromLocaleBund = ures_open(NULL, fromLocale, &errorCode); 611 UResourceBundle *toLocaleBund = ures_open(NULL, toLocale, &errorCode); 612 UResourceBundle *toCalendar, *fromCalendar, *toGregorian, *fromGregorian; 613 614 if(U_FAILURE(errorCode)) { 615 log_err("Can't open resource bundle %s or %s - %s\n", fromLocale, toLocale, u_errorName(errorCode)); 616 return; 617 } 618 fromCalendar = ures_getByKey(fromLocaleBund, "calendar", NULL, &errorCode); 619 fromGregorian = ures_getByKeyWithFallback(fromCalendar, "gregorian", NULL, &errorCode); 620 fromDateTimeElements = ures_getByKeyWithFallback(fromGregorian, "DateTimeElements", NULL, &errorCode); 621 622 toCalendar = ures_getByKey(toLocaleBund, "calendar", NULL, &errorCode); 623 toGregorian = ures_getByKeyWithFallback(toCalendar, "gregorian", NULL, &errorCode); 624 toDateTimeElements = ures_getByKeyWithFallback(toGregorian, "DateTimeElements", NULL, &errorCode); 625 626 if(U_FAILURE(errorCode)){ 627 log_err("Did not get DateTimeElements from the bundle %s or %s\n", fromLocale, toLocale); 628 goto cleanup; 629 } 630 631 fromWeekendData = ures_getByKeyWithFallback(fromGregorian, "weekend", NULL, &errorCode); 632 if(U_FAILURE(errorCode)){ 633 log_err("Did not get weekend data from the bundle %s to compare against %s\n", fromLocale, toLocale); 634 goto cleanup; 635 } 636 toWeekendData = ures_getByKeyWithFallback(toGregorian, "weekend", NULL, &errorCode); 637 if(U_FAILURE(errorCode)){ 638 log_err("Did not get weekend data from the bundle %s to compare against %s\n", toLocale, fromLocale); 639 goto cleanup; 640 } 641 642 if (strcmp(fromLocale, "ar_IN") != 0) 643 { 644 int32_t fromSize; 645 int32_t toSize; 646 int32_t idx; 647 const int32_t *fromBundleArr = ures_getIntVector(fromDateTimeElements, &fromSize, &errorCode); 648 const int32_t *toBundleArr = ures_getIntVector(toDateTimeElements, &toSize, &errorCode); 649 650 if (fromSize > toSize) { 651 fromSize = toSize; 652 log_err("Arrays are different size with key \"DateTimeElements\" from \"%s\" to \"%s\"\n", 653 fromLocale, 654 toLocale); 655 } 656 657 for (idx = 0; idx < fromSize; idx++) { 658 if (fromBundleArr[idx] != toBundleArr[idx]) { 659 log_err("Difference with key \"DateTimeElements\" at index %d from \"%s\" to \"%s\"\n", 660 idx, 661 fromLocale, 662 toLocale); 663 } 664 } 665 } 666 667 /* test for weekend data */ 668 { 669 int32_t fromSize; 670 int32_t toSize; 671 int32_t idx; 672 const int32_t *fromBundleArr = ures_getIntVector(fromWeekendData, &fromSize, &errorCode); 673 const int32_t *toBundleArr = ures_getIntVector(toWeekendData, &toSize, &errorCode); 674 675 if (fromSize > toSize) { 676 fromSize = toSize; 677 log_err("Arrays are different size with key \"weekend\" data from \"%s\" to \"%s\"\n", 678 fromLocale, 679 toLocale); 680 } 681 682 for (idx = 0; idx < fromSize; idx++) { 683 if (fromBundleArr[idx] != toBundleArr[idx]) { 684 log_err("Difference with key \"weekend\" data at index %d from \"%s\" to \"%s\"\n", 685 idx, 686 fromLocale, 687 toLocale); 688 } 689 } 690 } 691 692 fromArray = ures_getByKey(fromLocaleBund, "CurrencyElements", NULL, &errorCode); 693 toArray = ures_getByKey(toLocaleBund, "CurrencyElements", NULL, &errorCode); 694 if (strcmp(fromLocale, "en_CA") != 0) 695 { 696 /* The first one is probably localized. */ 697 compareArrays("CurrencyElements", fromArray, fromLocale, toArray, toLocale, 1, 2); 698 } 699 ures_close(fromArray); 700 ures_close(toArray); 701 702 fromArray = ures_getByKey(fromLocaleBund, "NumberPatterns", NULL, &errorCode); 703 toArray = ures_getByKey(toLocaleBund, "NumberPatterns", NULL, &errorCode); 704 if (strcmp(fromLocale, "en_CA") != 0) 705 { 706 compareArrays("NumberPatterns", fromArray, fromLocale, toArray, toLocale, 0, 3); 707 } 708 ures_close(fromArray); 709 ures_close(toArray); 710 711 /* Difficult to test properly */ 712 /* 713 fromArray = ures_getByKey(fromLocaleBund, "DateTimePatterns", NULL, &errorCode); 714 toArray = ures_getByKey(toLocaleBund, "DateTimePatterns", NULL, &errorCode); 715 { 716 compareArrays("DateTimePatterns", fromArray, fromLocale, toArray, toLocale); 717 } 718 ures_close(fromArray); 719 ures_close(toArray);*/ 720 721 fromArray = ures_getByKey(fromLocaleBund, "NumberElements", NULL, &errorCode); 722 toArray = ures_getByKey(toLocaleBund, "NumberElements", NULL, &errorCode); 723 if (strcmp(fromLocale, "en_CA") != 0) 724 { 725 compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 0, 3); 726 /* Index 4 is a script based 0 */ 727 compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 5, 10); 728 } 729 ures_close(fromArray); 730 ures_close(toArray); 731 732 cleanup: 733 ures_close(fromDateTimeElements); 734 ures_close(toDateTimeElements); 735 ures_close(fromWeekendData); 736 ures_close(toWeekendData); 737 738 ures_close(fromCalendar); 739 ures_close(toCalendar); 740 ures_close(fromGregorian); 741 ures_close(toGregorian); 742 743 ures_close(fromLocaleBund); 744 ures_close(toLocaleBund); 745 } 746 747 static void 748 TestConsistentCountryInfo(void) { 749 /* UResourceBundle *fromLocale, *toLocale;*/ 750 int32_t locCount = uloc_countAvailable(); 751 int32_t fromLocIndex, toLocIndex; 752 753 int32_t fromCountryLen, toCountryLen; 754 char fromCountry[ULOC_FULLNAME_CAPACITY], toCountry[ULOC_FULLNAME_CAPACITY]; 755 756 int32_t fromVariantLen, toVariantLen; 757 char fromVariant[ULOC_FULLNAME_CAPACITY], toVariant[ULOC_FULLNAME_CAPACITY]; 758 759 UErrorCode errorCode = U_ZERO_ERROR; 760 761 for (fromLocIndex = 0; fromLocIndex < locCount; fromLocIndex++) { 762 const char *fromLocale = uloc_getAvailable(fromLocIndex); 763 764 errorCode=U_ZERO_ERROR; 765 fromCountryLen = uloc_getCountry(fromLocale, fromCountry, ULOC_FULLNAME_CAPACITY, &errorCode); 766 if (fromCountryLen <= 0) { 767 /* Ignore countryless locales */ 768 continue; 769 } 770 fromVariantLen = uloc_getVariant(fromLocale, fromVariant, ULOC_FULLNAME_CAPACITY, &errorCode); 771 if (fromVariantLen > 0) { 772 /* Most variants are ignorable like PREEURO, or collation variants. */ 773 continue; 774 } 775 /* Start comparing only after the current index. 776 Previous loop should have already compared fromLocIndex. 777 */ 778 for (toLocIndex = fromLocIndex + 1; toLocIndex < locCount; toLocIndex++) { 779 const char *toLocale = uloc_getAvailable(toLocIndex); 780 781 toCountryLen = uloc_getCountry(toLocale, toCountry, ULOC_FULLNAME_CAPACITY, &errorCode); 782 if(U_FAILURE(errorCode)) { 783 log_err("Unknown failure fromLocale=%s toLocale=%s errorCode=%s\n", 784 fromLocale, toLocale, u_errorName(errorCode)); 785 continue; 786 } 787 788 if (toCountryLen <= 0) { 789 /* Ignore countryless locales */ 790 continue; 791 } 792 toVariantLen = uloc_getVariant(toLocale, toVariant, ULOC_FULLNAME_CAPACITY, &errorCode); 793 if (toVariantLen > 0) { 794 /* Most variants are ignorable like PREEURO, or collation variants. */ 795 /* They're a variant for a reason. */ 796 continue; 797 } 798 if (strcmp(fromCountry, toCountry) == 0) { 799 log_verbose("comparing fromLocale=%s toLocale=%s\n", 800 fromLocale, toLocale); 801 compareConsistentCountryInfo(fromLocale, toLocale); 802 } 803 } 804 } 805 } 806 807 static int32_t 808 findStringSetMismatch(const char *currLoc, const UChar *string, int32_t langSize, 809 const UChar *exemplarCharacters, int32_t exemplarLen, 810 UBool ignoreNumbers) { 811 UErrorCode errorCode = U_ZERO_ERROR; 812 USet *origSet = uset_openPatternOptions(exemplarCharacters, exemplarLen, USET_CASE_INSENSITIVE, &errorCode); 813 USet *exemplarSet = createFlattenSet(origSet, &errorCode); 814 int32_t strIdx; 815 uset_close(origSet); 816 if (U_FAILURE(errorCode)) { 817 log_err("%s: error uset_openPattern returned %s\n", currLoc, u_errorName(errorCode)); 818 return -1; 819 } 820 821 for (strIdx = 0; strIdx < langSize; strIdx++) { 822 if (!uset_contains(exemplarSet, string[strIdx]) 823 && string[strIdx] != 0x0020 && string[strIdx] != 0x00A0 && string[strIdx] != 0x002e && string[strIdx] != 0x002c && string[strIdx] != 0x002d && string[strIdx] != 0x0027 && string[strIdx] != 0x2019 && string[strIdx] != 0x0f0b 824 && string[strIdx] != 0x200C && string[strIdx] != 0x200D) { 825 if (!ignoreNumbers || (ignoreNumbers && (string[strIdx] < 0x30 || string[strIdx] > 0x39))) { 826 uset_close(exemplarSet); 827 return strIdx; 828 } 829 } 830 } 831 uset_close(exemplarSet); 832 return -1; 833 } 834 /* include non-invariant chars */ 835 static int32_t 836 myUCharsToChars(const UChar* us, char* cs, int32_t len){ 837 int32_t i=0; 838 for(; i< len; i++){ 839 if(us[i] < 0x7f){ 840 cs[i] = (char)us[i]; 841 }else{ 842 return -1; 843 } 844 } 845 return i; 846 } 847 static void 848 findSetMatch( UScriptCode *scriptCodes, int32_t scriptsLen, 849 USet *exemplarSet, 850 const char *locale){ 851 USet *scripts[10]= {0}; 852 char pattern[256] = { '[', ':', 0x000 }; 853 int32_t patternLen; 854 UChar uPattern[256] = {0}; 855 UErrorCode status = U_ZERO_ERROR; 856 int32_t i; 857 858 /* create the sets with script codes */ 859 for(i = 0; i<scriptsLen; i++){ 860 strcat(pattern, uscript_getShortName(scriptCodes[i])); 861 strcat(pattern, ":]"); 862 patternLen = (int32_t)strlen(pattern); 863 u_charsToUChars(pattern, uPattern, patternLen); 864 scripts[i] = uset_openPattern(uPattern, patternLen, &status); 865 if(U_FAILURE(status)){ 866 log_err("Could not create set for pattern %s. Error: %s\n", pattern, u_errorName(status)); 867 return; 868 } 869 pattern[2] = 0; 870 } 871 if (strcmp(locale, "uk") == 0 || strcmp(locale, "uk_UA") == 0) { 872 /* Special addition. Add the modifying apostrophe, which isn't in Cyrillic. */ 873 uset_add(scripts[0], 0x2bc); 874 } 875 if(U_SUCCESS(status)){ 876 UBool existsInScript = FALSE; 877 /* iterate over the exemplarSet and ascertain if all 878 * UChars in exemplarSet belong to the scripts returned 879 * by getScript 880 */ 881 int32_t count = uset_getItemCount(exemplarSet); 882 883 for( i=0; i < count; i++){ 884 UChar32 start = 0; 885 UChar32 end = 0; 886 UChar *str = NULL; 887 int32_t strCapacity = 0; 888 889 strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); 890 if(U_SUCCESS(status)){ 891 int32_t j; 892 if(strCapacity == 0){ 893 /* ok the item is a range */ 894 for( j = 0; j < scriptsLen; j++){ 895 if(uset_containsRange(scripts[j], start, end) == TRUE){ 896 existsInScript = TRUE; 897 } 898 } 899 if(existsInScript == FALSE){ 900 for( j = 0; j < scriptsLen; j++){ 901 UChar toPattern[500]={'\0'}; 902 char pat[500]={'\0'}; 903 int32_t len = uset_toPattern(scripts[j], toPattern, 500, TRUE, &status); 904 len = myUCharsToChars(toPattern, pat, len); 905 log_err("uset_indexOf(\\u%04X)=%i uset_indexOf(\\u%04X)=%i\n", start, uset_indexOf(scripts[0], start), end, uset_indexOf(scripts[0], end)); 906 if(len!=-1){ 907 log_err("Pattern: %s\n",pat); 908 } 909 } 910 log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); 911 } 912 }else{ 913 strCapacity++; /* increment for NUL termination */ 914 /* allocate the str and call the api again */ 915 str = (UChar*) malloc(U_SIZEOF_UCHAR * strCapacity); 916 strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); 917 /* iterate over the scripts and figure out if the string contained is actually 918 * in the script set 919 */ 920 for( j = 0; j < scriptsLen; j++){ 921 if(uset_containsString(scripts[j],str, strCapacity) == TRUE){ 922 existsInScript = TRUE; 923 } 924 } 925 if(existsInScript == FALSE){ 926 log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); 927 } 928 } 929 } 930 } 931 932 } 933 934 /* close the sets */ 935 for(i = 0; i<scriptsLen; i++){ 936 uset_close(scripts[i]); 937 } 938 } 939 940 static void VerifyTranslation(void) { 941 UResourceBundle *root, *currentLocale; 942 int32_t locCount = uloc_countAvailable(); 943 int32_t locIndex; 944 UErrorCode errorCode = U_ZERO_ERROR; 945 int32_t exemplarLen; 946 const UChar *exemplarCharacters; 947 const char *currLoc; 948 UScriptCode scripts[USCRIPT_CODE_LIMIT]; 949 int32_t numScripts; 950 int32_t idx; 951 int32_t end; 952 UResourceBundle *resArray; 953 954 if (locCount <= 1) { 955 log_data_err("At least root needs to be installed\n"); 956 } 957 958 root = ures_openDirect(NULL, "root", &errorCode); 959 if(U_FAILURE(errorCode)) { 960 log_data_err("Can't open root\n"); 961 return; 962 } 963 for (locIndex = 0; locIndex < locCount; locIndex++) { 964 errorCode=U_ZERO_ERROR; 965 currLoc = uloc_getAvailable(locIndex); 966 currentLocale = ures_open(NULL, currLoc, &errorCode); 967 if(errorCode != U_ZERO_ERROR) { 968 if(U_SUCCESS(errorCode)) { 969 /* It's installed, but there is no data. 970 It's installed for the g18n white paper [grhoten] */ 971 log_err("ERROR: Locale %-5s not installed, and it should be!\n", 972 uloc_getAvailable(locIndex)); 973 } else { 974 log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", 975 u_errorName(errorCode), 976 uloc_getAvailable(locIndex)); 977 } 978 ures_close(currentLocale); 979 continue; 980 } 981 exemplarCharacters = ures_getStringByKey(currentLocale, "ExemplarCharacters", &exemplarLen, &errorCode); 982 if (U_FAILURE(errorCode)) { 983 log_err("error ures_getStringByKey returned %s\n", u_errorName(errorCode)); 984 } 985 else if (QUICK && exemplarLen > 2048) { 986 log_verbose("skipping test for %s\n", currLoc); 987 } 988 else if (uprv_strncmp(currLoc,"bem",3) == 0) { 989 log_verbose("skipping test for %s, some month and country names known to use aux exemplars\n", currLoc); 990 } 991 else { 992 UChar langBuffer[128]; 993 int32_t langSize; 994 int32_t strIdx; 995 langSize = uloc_getDisplayLanguage(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode); 996 if (U_FAILURE(errorCode)) { 997 log_err("error uloc_getDisplayLanguage returned %s\n", u_errorName(errorCode)); 998 } 999 else { 1000 strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE); 1001 if (strIdx >= 0) { 1002 log_err("getDisplayLanguage(%s) at index %d returned characters not in the exemplar characters.\n", 1003 currLoc, strIdx); 1004 } 1005 } 1006 langSize = uloc_getDisplayCountry(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode); 1007 if (U_FAILURE(errorCode)) { 1008 log_err("error uloc_getDisplayCountry returned %s\n", u_errorName(errorCode)); 1009 } 1010 else { 1011 strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE); 1012 if (strIdx >= 0) { 1013 log_err("getDisplayCountry(%s) at index %d returned characters not in the exemplar characters.\n", 1014 currLoc, strIdx); 1015 } 1016 } 1017 { 1018 UResourceBundle* cal = ures_getByKey(currentLocale, "calendar", NULL, &errorCode); 1019 UResourceBundle* greg = ures_getByKeyWithFallback(cal, "gregorian", NULL, &errorCode); 1020 UResourceBundle* names = ures_getByKeyWithFallback(greg, "dayNames", NULL, &errorCode); 1021 UResourceBundle* format = ures_getByKeyWithFallback(names, "format", NULL, &errorCode); 1022 resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); 1023 1024 if (U_FAILURE(errorCode)) { 1025 log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); 1026 } 1027 if (QUICK) { 1028 end = 1; 1029 } 1030 else { 1031 end = ures_getSize(resArray); 1032 } 1033 1034 1035 for (idx = 0; idx < end; idx++) { 1036 const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); 1037 if (U_FAILURE(errorCode)) { 1038 log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); 1039 continue; 1040 } 1041 strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE); 1042 if (strIdx >= 0) { 1043 log_err("getDayNames(%s, %d) at index %d returned characters not in the exemplar characters.\n", 1044 currLoc, idx, strIdx); 1045 } 1046 } 1047 ures_close(resArray); 1048 ures_close(format); 1049 ures_close(names); 1050 1051 names = ures_getByKeyWithFallback(greg, "monthNames", NULL, &errorCode); 1052 format = ures_getByKeyWithFallback(names,"format", NULL, &errorCode); 1053 resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); 1054 if (U_FAILURE(errorCode)) { 1055 log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); 1056 } 1057 if (QUICK) { 1058 end = 1; 1059 } 1060 else { 1061 end = ures_getSize(resArray); 1062 } 1063 1064 for (idx = 0; idx < end; idx++) { 1065 const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); 1066 if (U_FAILURE(errorCode)) { 1067 log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); 1068 continue; 1069 } 1070 strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE); 1071 if (strIdx >= 0) { 1072 log_err("getMonthNames(%s, %d) at index %d returned characters not in the exemplar characters.\n", 1073 currLoc, idx, strIdx); 1074 } 1075 } 1076 ures_close(resArray); 1077 ures_close(format); 1078 ures_close(names); 1079 ures_close(greg); 1080 ures_close(cal); 1081 } 1082 errorCode = U_ZERO_ERROR; 1083 numScripts = uscript_getCode(currLoc, scripts, sizeof(scripts)/sizeof(scripts[0]), &errorCode); 1084 if (numScripts == 0) { 1085 log_err("uscript_getCode(%s) doesn't work.\n", currLoc); 1086 }else if(scripts[0] == USCRIPT_COMMON){ 1087 log_err("uscript_getCode(%s) returned USCRIPT_COMMON.\n", currLoc); 1088 } 1089 1090 /* test that the scripts are a superset of exemplar characters. */ 1091 { 1092 ULocaleData *uld = ulocdata_open(currLoc,&errorCode); 1093 USet *exemplarSet = ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &errorCode); 1094 /* test if exemplar characters are part of script code */ 1095 findSetMatch(scripts, numScripts, exemplarSet, currLoc); 1096 uset_close(exemplarSet); 1097 ulocdata_close(uld); 1098 } 1099 1100 /* test that the paperSize API works */ 1101 { 1102 int32_t height=0, width=0; 1103 ulocdata_getPaperSize(currLoc, &height, &width, &errorCode); 1104 if(U_FAILURE(errorCode)){ 1105 log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); 1106 } 1107 if(strstr(currLoc, "_US")!=NULL && height != 279 && width != 216 ){ 1108 log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); 1109 } 1110 } 1111 /* test that the MeasurementSystem works API works */ 1112 { 1113 UMeasurementSystem measurementSystem = ulocdata_getMeasurementSystem(currLoc, &errorCode); 1114 if(U_FAILURE(errorCode)){ 1115 log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); 1116 } 1117 if(strstr(currLoc, "_US")!=NULL){ 1118 if(measurementSystem != UMS_US){ 1119 log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); 1120 } 1121 }else if(measurementSystem != UMS_SI){ 1122 log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); 1123 } 1124 } 1125 } 1126 ures_close(currentLocale); 1127 } 1128 1129 ures_close(root); 1130 } 1131 1132 /* adjust this limit as appropriate */ 1133 #define MAX_SCRIPTS_PER_LOCALE 8 1134 1135 static void TestExemplarSet(void){ 1136 int32_t i, j, k, m, n; 1137 int32_t equalCount = 0; 1138 UErrorCode ec = U_ZERO_ERROR; 1139 UEnumeration* avail; 1140 USet* exemplarSets[2]; 1141 USet* unassignedSet; 1142 UScriptCode code[MAX_SCRIPTS_PER_LOCALE]; 1143 USet* codeSets[MAX_SCRIPTS_PER_LOCALE]; 1144 int32_t codeLen; 1145 char cbuf[32]; /* 9 should be enough */ 1146 UChar ubuf[64]; /* adjust as needed */ 1147 UBool existsInScript; 1148 int32_t itemCount; 1149 int32_t strLen; 1150 UChar32 start, end; 1151 1152 unassignedSet = NULL; 1153 exemplarSets[0] = NULL; 1154 exemplarSets[1] = NULL; 1155 for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { 1156 codeSets[i] = NULL; 1157 } 1158 1159 avail = ures_openAvailableLocales(NULL, &ec); 1160 if (!assertSuccess("ures_openAvailableLocales", &ec)) goto END; 1161 n = uenum_count(avail, &ec); 1162 if (!assertSuccess("uenum_count", &ec)) goto END; 1163 1164 u_uastrcpy(ubuf, "[:unassigned:]"); 1165 unassignedSet = uset_openPattern(ubuf, -1, &ec); 1166 if (!assertSuccess("uset_openPattern", &ec)) goto END; 1167 1168 for(i=0; i<n; i++){ 1169 const char* locale = uenum_next(avail, NULL, &ec); 1170 if (!assertSuccess("uenum_next", &ec)) goto END; 1171 log_verbose("%s\n", locale); 1172 for (k=0; k<2; ++k) { 1173 uint32_t option = (k==0) ? 0 : USET_CASE_INSENSITIVE; 1174 ULocaleData *uld = ulocdata_open(locale,&ec); 1175 USet* exemplarSet = ulocdata_getExemplarSet(uld,NULL, option, ULOCDATA_ES_STANDARD, &ec); 1176 uset_close(exemplarSets[k]); 1177 ulocdata_close(uld); 1178 exemplarSets[k] = exemplarSet; 1179 if (!assertSuccess("ulocaledata_getExemplarSet", &ec)) goto END; 1180 1181 if (uset_containsSome(exemplarSet, unassignedSet)) { 1182 log_err("ExemplarSet contains unassigned characters for locale : %s\n", locale); 1183 } 1184 codeLen = uscript_getCode(locale, code, 8, &ec); 1185 if (!assertSuccess("uscript_getCode", &ec)) goto END; 1186 1187 for (j=0; j<MAX_SCRIPTS_PER_LOCALE; ++j) { 1188 uset_close(codeSets[j]); 1189 codeSets[j] = NULL; 1190 } 1191 for (j=0; j<codeLen; ++j) { 1192 uprv_strcpy(cbuf, "[:"); 1193 if(code[j]==-1){ 1194 log_err("USCRIPT_INVALID_CODE returned for locale: %s\n", locale); 1195 continue; 1196 } 1197 uprv_strcat(cbuf, uscript_getShortName(code[j])); 1198 uprv_strcat(cbuf, ":]"); 1199 u_uastrcpy(ubuf, cbuf); 1200 codeSets[j] = uset_openPattern(ubuf, -1, &ec); 1201 } 1202 if (!assertSuccess("uset_openPattern", &ec)) goto END; 1203 1204 existsInScript = FALSE; 1205 itemCount = uset_getItemCount(exemplarSet); 1206 for (m=0; m<itemCount && !existsInScript; ++m) { 1207 strLen = uset_getItem(exemplarSet, m, &start, &end, ubuf, 1208 sizeof(ubuf)/sizeof(ubuf[0]), &ec); 1209 /* failure here might mean str[] needs to be larger */ 1210 if (!assertSuccess("uset_getItem", &ec)) goto END; 1211 if (strLen == 0) { 1212 for (j=0; j<codeLen; ++j) { 1213 if (codeSets[j]!=NULL && uset_containsRange(codeSets[j], start, end)) { 1214 existsInScript = TRUE; 1215 break; 1216 } 1217 } 1218 } else { 1219 for (j=0; j<codeLen; ++j) { 1220 if (codeSets[j]!=NULL && uset_containsString(codeSets[j], ubuf, strLen)) { 1221 existsInScript = TRUE; 1222 break; 1223 } 1224 } 1225 } 1226 } 1227 1228 if (existsInScript == FALSE){ 1229 log_err("ExemplarSet containment failed for locale : %s\n", locale); 1230 } 1231 } 1232 assertTrue("case-folded is a superset", 1233 uset_containsAll(exemplarSets[1], exemplarSets[0])); 1234 if (uset_equals(exemplarSets[1], exemplarSets[0])) { 1235 ++equalCount; 1236 } 1237 } 1238 /* Note: The case-folded set should sometimes be a strict superset 1239 and sometimes be equal. */ 1240 assertTrue("case-folded is sometimes a strict superset, and sometimes equal", 1241 equalCount > 0 && equalCount < n); 1242 1243 END: 1244 uenum_close(avail); 1245 uset_close(exemplarSets[0]); 1246 uset_close(exemplarSets[1]); 1247 uset_close(unassignedSet); 1248 for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { 1249 uset_close(codeSets[i]); 1250 } 1251 } 1252 1253 static void TestLocaleDisplayPattern(void){ 1254 UErrorCode status = U_ZERO_ERROR; 1255 UChar pattern[32] = {0,}; 1256 UChar separator[32] = {0,}; 1257 ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status); 1258 1259 if(U_FAILURE(status)){ 1260 log_err("ulocdata_open error"); 1261 return; 1262 } 1263 ulocdata_getLocaleDisplayPattern(uld, pattern, 32, &status); 1264 if (U_FAILURE(status)){ 1265 log_err("ulocdata_getLocaleDisplayPattern error!"); 1266 } 1267 status = U_ZERO_ERROR; 1268 ulocdata_getLocaleSeparator(uld, separator, 32, &status); 1269 if (U_FAILURE(status)){ 1270 log_err("ulocdata_getLocaleSeparator error!"); 1271 } 1272 ulocdata_close(uld); 1273 } 1274 1275 static void TestCoverage(void){ 1276 ULocaleDataDelimiterType types[] = { 1277 ULOCDATA_QUOTATION_START, /* Quotation start */ 1278 ULOCDATA_QUOTATION_END, /* Quotation end */ 1279 ULOCDATA_ALT_QUOTATION_START, /* Alternate quotation start */ 1280 ULOCDATA_ALT_QUOTATION_END, /* Alternate quotation end */ 1281 ULOCDATA_DELIMITER_COUNT 1282 }; 1283 int i; 1284 UBool sub; 1285 UErrorCode status = U_ZERO_ERROR; 1286 ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status); 1287 1288 if(U_FAILURE(status)){ 1289 log_err("ulocdata_open error"); 1290 return; 1291 } 1292 1293 1294 for(i = 0; i < ULOCDATA_DELIMITER_COUNT; i++){ 1295 UChar result[32] = {0,}; 1296 status = U_ZERO_ERROR; 1297 ulocdata_getDelimiter(uld, types[i], result, 32, &status); 1298 if (U_FAILURE(status)){ 1299 log_err("ulocdata_getgetDelimiter error with type %d", types[i]); 1300 } 1301 } 1302 1303 sub = ulocdata_getNoSubstitute(uld); 1304 ulocdata_setNoSubstitute(uld,sub); 1305 ulocdata_close(uld); 1306 } 1307 1308 static void TestCurrencyList(void){ 1309 #if !UCONFIG_NO_FORMATTING 1310 UErrorCode errorCode = U_ZERO_ERROR; 1311 int32_t structLocaleCount, currencyCount; 1312 UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &errorCode); 1313 const char *isoCode, *structISOCode; 1314 UResourceBundle *subBundle; 1315 UResourceBundle *currencies = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); 1316 if(U_FAILURE(errorCode)) { 1317 log_data_err("Can't open structLocale\n"); 1318 return; 1319 } 1320 currencies = ures_getByKey(currencies, "Currencies", currencies, &errorCode); 1321 currencyCount = uenum_count(en, &errorCode); 1322 structLocaleCount = ures_getSize(currencies); 1323 if (currencyCount != structLocaleCount) { 1324 log_err("structLocale(%d) and ISO4217(%d) currency list are out of sync.\n", structLocaleCount, currencyCount); 1325 #if U_CHARSET_FAMILY == U_ASCII_FAMILY 1326 ures_resetIterator(currencies); 1327 while ((isoCode = uenum_next(en, NULL, &errorCode)) != NULL && ures_hasNext(currencies)) { 1328 subBundle = ures_getNextResource(currencies, NULL, &errorCode); 1329 structISOCode = ures_getKey(subBundle); 1330 ures_close(subBundle); 1331 if (strcmp(structISOCode, isoCode) != 0) { 1332 log_err("First difference found at structLocale(%s) and ISO4217(%s).\n", structISOCode, isoCode); 1333 break; 1334 } 1335 } 1336 #endif 1337 } 1338 ures_close(currencies); 1339 uenum_close(en); 1340 #endif 1341 } 1342 1343 #define TESTCASE(name) addTest(root, &name, "tsutil/cldrtest/" #name) 1344 1345 void addCLDRTest(TestNode** root); 1346 1347 void addCLDRTest(TestNode** root) 1348 { 1349 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION 1350 TESTCASE(TestLocaleStructure); 1351 TESTCASE(TestCurrencyList); 1352 #endif 1353 TESTCASE(TestConsistentCountryInfo); 1354 TESTCASE(VerifyTranslation); 1355 TESTCASE(TestExemplarSet); 1356 TESTCASE(TestLocaleDisplayPattern); 1357 TESTCASE(TestCoverage); 1358 } 1359