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