cldrtest.c revision 85bf2e2fbc60a9f938064abc8127d61da7d19882
1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2009, 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 ---------------------------------------------------------------------*/
23static const UVersionInfo ICU_37 = {3,7,0,0};
24
25/*
26returns a new UnicodeSet that is a flattened form of the original
27UnicodeSet.
28*/
29static USet*
30createFlattenSet(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}
62static UBool
63isCurrencyPreEuro(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}
75static void
76TestKeyInRootRecursive(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
450static void
451testLCID(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
489static void
490TestLocaleStructure(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
571static void
572compareArrays(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
605static void
606compareConsistentCountryInfo(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
732cleanup:
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
747static void
748TestConsistentCountryInfo(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
807static int32_t
808findStringSetMismatch(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
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 */
835static int32_t
836myUCharsToChars(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}
847static void
848findSetMatch( 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
940static 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 {
989            UChar langBuffer[128];
990            int32_t langSize;
991            int32_t strIdx;
992            langSize = uloc_getDisplayLanguage(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode);
993            if (U_FAILURE(errorCode)) {
994                log_err("error uloc_getDisplayLanguage returned %s\n", u_errorName(errorCode));
995            }
996            else {
997                strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE);
998                if (strIdx >= 0) {
999                    log_err("getDisplayLanguage(%s) at index %d returned characters not in the exemplar characters.\n",
1000                        currLoc, strIdx);
1001                }
1002            }
1003            langSize = uloc_getDisplayCountry(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode);
1004            if (U_FAILURE(errorCode)) {
1005                log_err("error uloc_getDisplayCountry returned %s\n", u_errorName(errorCode));
1006            }
1007            else {
1008              strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE);
1009                if (strIdx >= 0) {
1010                    log_err("getDisplayCountry(%s) at index %d returned characters not in the exemplar characters.\n",
1011                        currLoc, strIdx);
1012                }
1013            }
1014            {
1015                UResourceBundle* cal = ures_getByKey(currentLocale, "calendar", NULL, &errorCode);
1016                UResourceBundle* greg = ures_getByKeyWithFallback(cal, "gregorian", NULL, &errorCode);
1017                UResourceBundle* names = ures_getByKeyWithFallback(greg,  "dayNames", NULL, &errorCode);
1018                UResourceBundle* format = ures_getByKeyWithFallback(names,  "format", NULL, &errorCode);
1019                resArray = ures_getByKeyWithFallback(format,  "wide", NULL, &errorCode);
1020
1021                if (U_FAILURE(errorCode)) {
1022                    log_err("error ures_getByKey returned %s\n", u_errorName(errorCode));
1023                }
1024                if (QUICK) {
1025                    end = 1;
1026                }
1027                else {
1028                    end = ures_getSize(resArray);
1029                }
1030
1031
1032                for (idx = 0; idx < end; idx++) {
1033                    const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode);
1034                    if (U_FAILURE(errorCode)) {
1035                        log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode));
1036                        continue;
1037                    }
1038                    strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE);
1039                    if (strIdx >= 0) {
1040                        log_err("getDayNames(%s, %d) at index %d returned characters not in the exemplar characters.\n",
1041                            currLoc, idx, strIdx);
1042                    }
1043                }
1044                ures_close(resArray);
1045                ures_close(format);
1046                ures_close(names);
1047
1048                names = ures_getByKeyWithFallback(greg, "monthNames", NULL, &errorCode);
1049                format = ures_getByKeyWithFallback(names,"format", NULL, &errorCode);
1050                resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode);
1051                if (U_FAILURE(errorCode)) {
1052                    log_err("error ures_getByKey returned %s\n", u_errorName(errorCode));
1053                }
1054                if (QUICK) {
1055                    end = 1;
1056                }
1057                else {
1058                    end = ures_getSize(resArray);
1059                }
1060
1061                for (idx = 0; idx < end; idx++) {
1062                    const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode);
1063                    if (U_FAILURE(errorCode)) {
1064                        log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode));
1065                        continue;
1066                    }
1067                    strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE);
1068                    if (strIdx >= 0) {
1069                        log_err("getMonthNames(%s, %d) at index %d returned characters not in the exemplar characters.\n",
1070                            currLoc, idx, strIdx);
1071                    }
1072                }
1073                ures_close(resArray);
1074                ures_close(format);
1075                ures_close(names);
1076                ures_close(greg);
1077                ures_close(cal);
1078            }
1079            errorCode = U_ZERO_ERROR;
1080            numScripts = uscript_getCode(currLoc, scripts, sizeof(scripts)/sizeof(scripts[0]), &errorCode);
1081            if (numScripts == 0) {
1082                log_err("uscript_getCode(%s) doesn't work.\n", currLoc);
1083            }else if(scripts[0] == USCRIPT_COMMON){
1084                log_err("uscript_getCode(%s) returned USCRIPT_COMMON.\n", currLoc);
1085            }
1086
1087            /* test that the scripts are a superset of exemplar characters. */
1088           {
1089                ULocaleData *uld = ulocdata_open(currLoc,&errorCode);
1090                USet *exemplarSet =  ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &errorCode);
1091                /* test if exemplar characters are part of script code */
1092                findSetMatch(scripts, numScripts, exemplarSet, currLoc);
1093                uset_close(exemplarSet);
1094                ulocdata_close(uld);
1095            }
1096
1097           /* test that the paperSize API works */
1098           {
1099               int32_t height=0, width=0;
1100               ulocdata_getPaperSize(currLoc, &height, &width, &errorCode);
1101               if(U_FAILURE(errorCode)){
1102                   log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode));
1103               }
1104               if(strstr(currLoc, "_US")!=NULL && height != 279 && width != 216 ){
1105                   log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc);
1106               }
1107           }
1108            /* test that the MeasurementSystem works API works */
1109           {
1110               UMeasurementSystem measurementSystem = ulocdata_getMeasurementSystem(currLoc, &errorCode);
1111               if(U_FAILURE(errorCode)){
1112                   log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode));
1113               }
1114               if(strstr(currLoc, "_US")!=NULL){
1115                   if(measurementSystem != UMS_US){
1116                        log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc);
1117                   }
1118               }else if(measurementSystem != UMS_SI){
1119                   log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc);
1120               }
1121           }
1122        }
1123        ures_close(currentLocale);
1124    }
1125
1126    ures_close(root);
1127}
1128
1129/* adjust this limit as appropriate */
1130#define MAX_SCRIPTS_PER_LOCALE 8
1131
1132static void TestExemplarSet(void){
1133    int32_t i, j, k, m, n;
1134    int32_t equalCount = 0;
1135    UErrorCode ec = U_ZERO_ERROR;
1136    UEnumeration* avail;
1137    USet* exemplarSets[2];
1138    USet* unassignedSet;
1139    UScriptCode code[MAX_SCRIPTS_PER_LOCALE];
1140    USet* codeSets[MAX_SCRIPTS_PER_LOCALE];
1141    int32_t codeLen;
1142    char cbuf[32]; /* 9 should be enough */
1143    UChar ubuf[64]; /* adjust as needed */
1144    UBool existsInScript;
1145    int32_t itemCount;
1146    int32_t strLen;
1147    UChar32 start, end;
1148
1149    unassignedSet = NULL;
1150    exemplarSets[0] = NULL;
1151    exemplarSets[1] = NULL;
1152    for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) {
1153        codeSets[i] = NULL;
1154    }
1155
1156    avail = ures_openAvailableLocales(NULL, &ec);
1157    if (!assertSuccess("ures_openAvailableLocales", &ec)) goto END;
1158    n = uenum_count(avail, &ec);
1159    if (!assertSuccess("uenum_count", &ec)) goto END;
1160
1161    u_uastrcpy(ubuf, "[:unassigned:]");
1162    unassignedSet = uset_openPattern(ubuf, -1, &ec);
1163    if (!assertSuccess("uset_openPattern", &ec)) goto END;
1164
1165    for(i=0; i<n; i++){
1166        const char* locale = uenum_next(avail, NULL, &ec);
1167        if (!assertSuccess("uenum_next", &ec)) goto END;
1168        log_verbose("%s\n", locale);
1169        for (k=0; k<2; ++k) {
1170            uint32_t option = (k==0) ? 0 : USET_CASE_INSENSITIVE;
1171            ULocaleData *uld = ulocdata_open(locale,&ec);
1172            USet* exemplarSet = ulocdata_getExemplarSet(uld,NULL, option, ULOCDATA_ES_STANDARD, &ec);
1173            uset_close(exemplarSets[k]);
1174            ulocdata_close(uld);
1175            exemplarSets[k] = exemplarSet;
1176            if (!assertSuccess("ulocaledata_getExemplarSet", &ec)) goto END;
1177
1178            if (uset_containsSome(exemplarSet, unassignedSet)) {
1179                log_err("ExemplarSet contains unassigned characters for locale : %s\n", locale);
1180            }
1181            codeLen = uscript_getCode(locale, code, 8, &ec);
1182            if (!assertSuccess("uscript_getCode", &ec)) goto END;
1183
1184            for (j=0; j<MAX_SCRIPTS_PER_LOCALE; ++j) {
1185                uset_close(codeSets[j]);
1186                codeSets[j] = NULL;
1187            }
1188            for (j=0; j<codeLen; ++j) {
1189                uprv_strcpy(cbuf, "[:");
1190                if(code[j]==-1){
1191                    log_err("USCRIPT_INVALID_CODE returned for locale: %s\n", locale);
1192                    continue;
1193                }
1194                uprv_strcat(cbuf, uscript_getShortName(code[j]));
1195                uprv_strcat(cbuf, ":]");
1196                u_uastrcpy(ubuf, cbuf);
1197                codeSets[j] = uset_openPattern(ubuf, -1, &ec);
1198            }
1199            if (!assertSuccess("uset_openPattern", &ec)) goto END;
1200
1201            existsInScript = FALSE;
1202            itemCount = uset_getItemCount(exemplarSet);
1203            for (m=0; m<itemCount && !existsInScript; ++m) {
1204                strLen = uset_getItem(exemplarSet, m, &start, &end, ubuf,
1205                                      sizeof(ubuf)/sizeof(ubuf[0]), &ec);
1206                /* failure here might mean str[] needs to be larger */
1207                if (!assertSuccess("uset_getItem", &ec)) goto END;
1208                if (strLen == 0) {
1209                    for (j=0; j<codeLen; ++j) {
1210                        if (codeSets[j]!=NULL && uset_containsRange(codeSets[j], start, end)) {
1211                            existsInScript = TRUE;
1212                            break;
1213                        }
1214                    }
1215                } else {
1216                    for (j=0; j<codeLen; ++j) {
1217                        if (codeSets[j]!=NULL && uset_containsString(codeSets[j], ubuf, strLen)) {
1218                            existsInScript = TRUE;
1219                            break;
1220                        }
1221                    }
1222                }
1223            }
1224
1225            if (existsInScript == FALSE){
1226                log_err("ExemplarSet containment failed for locale : %s\n", locale);
1227            }
1228        }
1229        assertTrue("case-folded is a superset",
1230                   uset_containsAll(exemplarSets[1], exemplarSets[0]));
1231        if (uset_equals(exemplarSets[1], exemplarSets[0])) {
1232            ++equalCount;
1233        }
1234    }
1235    /* Note: The case-folded set should sometimes be a strict superset
1236       and sometimes be equal. */
1237    assertTrue("case-folded is sometimes a strict superset, and sometimes equal",
1238               equalCount > 0 && equalCount < n);
1239
1240 END:
1241    uenum_close(avail);
1242    uset_close(exemplarSets[0]);
1243    uset_close(exemplarSets[1]);
1244    uset_close(unassignedSet);
1245    for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) {
1246        uset_close(codeSets[i]);
1247    }
1248}
1249
1250static void TestLocaleDisplayPattern(void){
1251    UErrorCode status = U_ZERO_ERROR;
1252    UChar pattern[32] = {0,};
1253    UChar separator[32] = {0,};
1254    ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status);
1255
1256    if(U_FAILURE(status)){
1257        log_err("ulocdata_open error");
1258        return;
1259    }
1260    ulocdata_getLocaleDisplayPattern(uld, pattern, 32, &status);
1261    if (U_FAILURE(status)){
1262        log_err("ulocdata_getLocaleDisplayPattern error!");
1263    }
1264    status = U_ZERO_ERROR;
1265    ulocdata_getLocaleSeparator(uld, separator, 32, &status);
1266    if (U_FAILURE(status)){
1267        log_err("ulocdata_getLocaleSeparator error!");
1268    }
1269    ulocdata_close(uld);
1270}
1271
1272static void TestCoverage(void){
1273    ULocaleDataDelimiterType types[] = {
1274     ULOCDATA_QUOTATION_START,     /* Quotation start */
1275     ULOCDATA_QUOTATION_END,       /* Quotation end */
1276     ULOCDATA_ALT_QUOTATION_START, /* Alternate quotation start */
1277     ULOCDATA_ALT_QUOTATION_END,   /* Alternate quotation end */
1278     ULOCDATA_DELIMITER_COUNT
1279    };
1280    int i;
1281    UBool sub;
1282    UErrorCode status = U_ZERO_ERROR;
1283    ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status);
1284
1285    if(U_FAILURE(status)){
1286        log_err("ulocdata_open error");
1287        return;
1288    }
1289
1290
1291    for(i = 0; i < ULOCDATA_DELIMITER_COUNT; i++){
1292        UChar result[32] = {0,};
1293        status = U_ZERO_ERROR;
1294        ulocdata_getDelimiter(uld, types[i], result, 32, &status);
1295        if (U_FAILURE(status)){
1296            log_err("ulocdata_getgetDelimiter error with type %d", types[i]);
1297        }
1298    }
1299
1300    sub = ulocdata_getNoSubstitute(uld);
1301    ulocdata_setNoSubstitute(uld,sub);
1302    ulocdata_close(uld);
1303}
1304
1305static void TestCurrencyList(void){
1306#if !UCONFIG_NO_FORMATTING
1307    UErrorCode errorCode = U_ZERO_ERROR;
1308    int32_t structLocaleCount, currencyCount;
1309    UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &errorCode);
1310    const char *isoCode, *structISOCode;
1311    UResourceBundle *subBundle;
1312    UResourceBundle *currencies = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode);
1313    if(U_FAILURE(errorCode)) {
1314        log_data_err("Can't open structLocale\n");
1315        return;
1316    }
1317    currencies = ures_getByKey(currencies, "Currencies", currencies, &errorCode);
1318    currencyCount = uenum_count(en, &errorCode);
1319    structLocaleCount = ures_getSize(currencies);
1320    if (currencyCount != structLocaleCount) {
1321        log_err("structLocale(%d) and ISO4217(%d) currency list are out of sync.\n", structLocaleCount, currencyCount);
1322#if U_CHARSET_FAMILY == U_ASCII_FAMILY
1323        ures_resetIterator(currencies);
1324        while ((isoCode = uenum_next(en, NULL, &errorCode)) != NULL && ures_hasNext(currencies)) {
1325            subBundle = ures_getNextResource(currencies, NULL, &errorCode);
1326            structISOCode = ures_getKey(subBundle);
1327            ures_close(subBundle);
1328            if (strcmp(structISOCode, isoCode) != 0) {
1329                log_err("First difference found at structLocale(%s) and ISO4217(%s).\n", structISOCode, isoCode);
1330                break;
1331            }
1332        }
1333#endif
1334    }
1335    ures_close(currencies);
1336    uenum_close(en);
1337#endif
1338}
1339
1340#define TESTCASE(name) addTest(root, &name, "tsutil/cldrtest/" #name)
1341
1342void addCLDRTest(TestNode** root);
1343
1344void addCLDRTest(TestNode** root)
1345{
1346    TESTCASE(TestLocaleStructure);
1347    TESTCASE(TestConsistentCountryInfo);
1348    TESTCASE(VerifyTranslation);
1349    TESTCASE(TestExemplarSet);
1350    TESTCASE(TestCurrencyList);
1351    TESTCASE(TestLocaleDisplayPattern);
1352    TESTCASE(TestCoverage);
1353}
1354