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