Home | History | Annotate | Download | only in cintltst
      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