]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
374ca955 A |
3 | /******************************************************************** |
4 | * COPYRIGHT: | |
2ca993e8 | 5 | * Copyright (c) 1997-2016, International Business Machines Corporation and |
374ca955 A |
6 | * others. All Rights Reserved. |
7 | ********************************************************************/ | |
8 | ||
9 | #include "cintltst.h" | |
10 | #include "unicode/ures.h" | |
73c04bcf | 11 | #include "unicode/ucurr.h" |
374ca955 A |
12 | #include "unicode/ustring.h" |
13 | #include "unicode/uset.h" | |
14 | #include "unicode/udat.h" | |
15 | #include "unicode/uscript.h" | |
16 | #include "unicode/ulocdata.h" | |
0f5d89e8 | 17 | #include "unicode/utf16.h" |
2ca993e8 | 18 | #include "cmemory.h" |
374ca955 A |
19 | #include "cstring.h" |
20 | #include "locmap.h" | |
21 | #include "uresimp.h" | |
22 | ||
73c04bcf A |
23 | /* |
24 | returns a new UnicodeSet that is a flattened form of the original | |
25 | UnicodeSet. | |
26 | */ | |
27 | static USet* | |
28 | createFlattenSet(USet *origSet, UErrorCode *status) { | |
29 | ||
30 | ||
31 | USet *newSet = NULL; | |
32 | int32_t origItemCount = 0; | |
33 | int32_t idx, graphmeSize; | |
34 | UChar32 start, end; | |
35 | UChar graphme[64]; | |
36 | if (U_FAILURE(*status)) { | |
37 | log_err("createFlattenSet called with %s\n", u_errorName(*status)); | |
38 | return NULL; | |
39 | } | |
40 | newSet = uset_open(1, 0); | |
41 | origItemCount = uset_getItemCount(origSet); | |
42 | for (idx = 0; idx < origItemCount; idx++) { | |
43 | graphmeSize = uset_getItem(origSet, idx, | |
729e4ab9 | 44 | &start, &end, |
2ca993e8 | 45 | graphme, UPRV_LENGTHOF(graphme), |
73c04bcf A |
46 | status); |
47 | if (U_FAILURE(*status)) { | |
48 | log_err("ERROR: uset_getItem returned %s\n", u_errorName(*status)); | |
49 | *status = U_ZERO_ERROR; | |
50 | } | |
51 | if (graphmeSize) { | |
52 | uset_addAllCodePoints(newSet, graphme, graphmeSize); | |
53 | } | |
54 | else { | |
55 | uset_addRange(newSet, start, end); | |
56 | } | |
57 | } | |
4388f060 | 58 | uset_closeOver(newSet,USET_CASE_INSENSITIVE); |
73c04bcf A |
59 | return newSet; |
60 | } | |
4388f060 | 61 | |
729e4ab9 | 62 | static UBool |
73c04bcf | 63 | isCurrencyPreEuro(const char* currencyKey){ |
374ca955 A |
64 | if( strcmp(currencyKey, "PTE") == 0 || |
65 | strcmp(currencyKey, "ESP") == 0 || | |
66 | strcmp(currencyKey, "LUF") == 0 || | |
67 | strcmp(currencyKey, "GRD") == 0 || | |
68 | strcmp(currencyKey, "BEF") == 0 || | |
73c04bcf A |
69 | strcmp(currencyKey, "ITL") == 0 || |
70 | strcmp(currencyKey, "EEK") == 0){ | |
374ca955 A |
71 | return TRUE; |
72 | } | |
73 | return FALSE; | |
74 | } | |
51004dcb | 75 | #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
374ca955 A |
76 | static void |
77 | TestKeyInRootRecursive(UResourceBundle *root, const char *rootName, | |
78 | UResourceBundle *currentBundle, const char *locale) { | |
79 | UErrorCode errorCode = U_ZERO_ERROR; | |
729e4ab9 | 80 | UResourceBundle *subRootBundle = NULL, *subBundle = NULL, *arr = NULL; |
374ca955 A |
81 | |
82 | ures_resetIterator(root); | |
83 | ures_resetIterator(currentBundle); | |
84 | while (ures_hasNext(currentBundle)) { | |
85 | const char *subBundleKey = NULL; | |
86 | const char *currentBundleKey = NULL; | |
87 | ||
88 | errorCode = U_ZERO_ERROR; | |
89 | currentBundleKey = ures_getKey(currentBundle); | |
57a6839d | 90 | (void)currentBundleKey; /* Suppress set but not used warning. */ |
374ca955 A |
91 | subBundle = ures_getNextResource(currentBundle, NULL, &errorCode); |
92 | if (U_FAILURE(errorCode)) { | |
729e4ab9 | 93 | log_err("Can't open a resource for lnocale %s. Error: %s\n", locale, u_errorName(errorCode)); |
374ca955 A |
94 | continue; |
95 | } | |
96 | subBundleKey = ures_getKey(subBundle); | |
729e4ab9 | 97 | |
374ca955 A |
98 | |
99 | subRootBundle = ures_getByKey(root, subBundleKey, NULL, &errorCode); | |
100 | if (U_FAILURE(errorCode)) { | |
101 | log_err("Can't open a resource with key \"%s\" in \"%s\" from %s for locale \"%s\"\n", | |
102 | subBundleKey, | |
103 | ures_getKey(currentBundle), | |
104 | rootName, | |
105 | locale); | |
106 | ures_close(subBundle); | |
107 | continue; | |
108 | } | |
109 | if (ures_getType(subRootBundle) != ures_getType(subBundle)) { | |
110 | log_err("key \"%s\" in \"%s\" has a different type from root for locale \"%s\"\n" | |
111 | "\troot=%d, locale=%d\n", | |
112 | subBundleKey, | |
113 | ures_getKey(currentBundle), | |
114 | locale, | |
115 | ures_getType(subRootBundle), | |
116 | ures_getType(subBundle)); | |
46f4442e | 117 | ures_close(subBundle); |
374ca955 A |
118 | continue; |
119 | } | |
120 | else if (ures_getType(subBundle) == URES_INT_VECTOR) { | |
121 | int32_t minSize; | |
122 | int32_t subBundleSize; | |
123 | int32_t idx; | |
124 | UBool sameArray = TRUE; | |
125 | const int32_t *subRootBundleArr = ures_getIntVector(subRootBundle, &minSize, &errorCode); | |
126 | const int32_t *subBundleArr = ures_getIntVector(subBundle, &subBundleSize, &errorCode); | |
127 | ||
128 | if (minSize > subBundleSize) { | |
129 | minSize = subBundleSize; | |
130 | log_err("Arrays are different size with key \"%s\" in \"%s\" from root for locale \"%s\"\n", | |
131 | subBundleKey, | |
132 | ures_getKey(currentBundle), | |
133 | locale); | |
134 | } | |
135 | ||
136 | for (idx = 0; idx < minSize && sameArray; idx++) { | |
137 | if (subRootBundleArr[idx] != subBundleArr[idx]) { | |
138 | sameArray = FALSE; | |
139 | } | |
140 | if (strcmp(subBundleKey, "DateTimeElements") == 0 | |
141 | && (subBundleArr[idx] < 1 || 7 < subBundleArr[idx])) | |
142 | { | |
143 | log_err("Value out of range with key \"%s\" at index %d in \"%s\" for locale \"%s\"\n", | |
144 | subBundleKey, | |
145 | idx, | |
146 | ures_getKey(currentBundle), | |
147 | locale); | |
148 | } | |
149 | } | |
150 | /* Special exception es_US and DateTimeElements */ | |
151 | if (sameArray | |
152 | && !(strcmp(locale, "es_US") == 0 && strcmp(subBundleKey, "DateTimeElements") == 0)) | |
153 | { | |
154 | log_err("Integer vectors are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n", | |
155 | subBundleKey, | |
156 | ures_getKey(currentBundle), | |
157 | locale); | |
158 | } | |
159 | } | |
160 | else if (ures_getType(subBundle) == URES_ARRAY) { | |
161 | UResourceBundle *subSubBundle = ures_getByIndex(subBundle, 0, NULL, &errorCode); | |
162 | UResourceBundle *subSubRootBundle = ures_getByIndex(subRootBundle, 0, NULL, &errorCode); | |
163 | ||
164 | if (U_SUCCESS(errorCode) | |
165 | && (ures_getType(subSubBundle) == URES_ARRAY || ures_getType(subSubRootBundle) == URES_ARRAY)) | |
166 | { | |
73c04bcf A |
167 | /* Here is one of the recursive parts */ |
168 | TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale); | |
374ca955 A |
169 | } |
170 | else { | |
171 | int32_t minSize = ures_getSize(subRootBundle); | |
172 | int32_t idx; | |
173 | UBool sameArray = TRUE; | |
174 | ||
175 | if (minSize > ures_getSize(subBundle)) { | |
176 | minSize = ures_getSize(subBundle); | |
177 | } | |
178 | ||
179 | if ((subBundleKey == NULL | |
180 | || (subBundleKey != NULL && strcmp(subBundleKey, "LocaleScript") != 0 && !isCurrencyPreEuro(subBundleKey))) | |
181 | && ures_getSize(subRootBundle) != ures_getSize(subBundle)) | |
182 | { | |
183 | log_err("Different size array with key \"%s\" in \"%s\" from root for locale \"%s\"\n" | |
184 | "\troot array size=%d, locale array size=%d\n", | |
185 | subBundleKey, | |
186 | ures_getKey(currentBundle), | |
187 | locale, | |
188 | ures_getSize(subRootBundle), | |
189 | ures_getSize(subBundle)); | |
190 | } | |
191 | /* | |
192 | if(isCurrencyPreEuro(subBundleKey) && ures_getSize(subBundle)!=3){ | |
193 | log_err("Different size array with key \"%s\" in \"%s\" for locale \"%s\" the expected size is 3 got size=%d\n", | |
194 | subBundleKey, | |
195 | ures_getKey(currentBundle), | |
196 | locale, | |
197 | ures_getSize(subBundle)); | |
198 | } | |
199 | */ | |
200 | for (idx = 0; idx < minSize; idx++) { | |
201 | int32_t rootStrLen, localeStrLen; | |
202 | const UChar *rootStr = ures_getStringByIndex(subRootBundle,idx,&rootStrLen,&errorCode); | |
203 | const UChar *localeStr = ures_getStringByIndex(subBundle,idx,&localeStrLen,&errorCode); | |
204 | if (rootStr && localeStr && U_SUCCESS(errorCode)) { | |
205 | if (u_strcmp(rootStr, localeStr) != 0) { | |
206 | sameArray = FALSE; | |
207 | } | |
208 | } | |
209 | else { | |
729e4ab9 A |
210 | if ( rootStrLen > 1 && rootStr[0] == 0x41 && rootStr[1] >= 0x30 && rootStr[1] <= 0x39 ) { |
211 | /* A2 or A4 in the root string indicates that the resource can optionally be an array instead of a */ | |
212 | /* string. Attempt to read it as an array. */ | |
213 | errorCode = U_ZERO_ERROR; | |
214 | arr = ures_getByIndex(subBundle,idx,NULL,&errorCode); | |
215 | if (U_FAILURE(errorCode)) { | |
216 | log_err("Got a NULL string with key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n", | |
217 | subBundleKey, | |
218 | ures_getKey(currentBundle), | |
219 | idx, | |
220 | locale); | |
221 | continue; | |
222 | } | |
223 | if (ures_getType(arr) != URES_ARRAY || ures_getSize(arr) != (int32_t)rootStr[1] - 0x30) { | |
224 | 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", | |
225 | rootStr[1] - 0x30, | |
226 | subBundleKey, | |
227 | ures_getKey(currentBundle), | |
228 | idx, | |
229 | locale); | |
230 | ures_close(arr); | |
231 | continue; | |
232 | } | |
233 | localeStr = ures_getStringByIndex(arr,0,&localeStrLen,&errorCode); | |
234 | ures_close(arr); | |
235 | if (U_FAILURE(errorCode)) { | |
236 | log_err("Got something other than a string or array for 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 | } else { | |
244 | log_err("Got a NULL string with key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n", | |
374ca955 A |
245 | subBundleKey, |
246 | ures_getKey(currentBundle), | |
247 | idx, | |
248 | locale); | |
729e4ab9 A |
249 | continue; |
250 | } | |
374ca955 A |
251 | } |
252 | if (localeStr[0] == (UChar)0x20) { | |
253 | log_err("key \"%s\" at index %d in \"%s\" starts with a space in locale \"%s\"\n", | |
254 | subBundleKey, | |
255 | idx, | |
256 | ures_getKey(currentBundle), | |
257 | locale); | |
258 | } | |
46f4442e | 259 | else if ((localeStr[localeStrLen - 1] == (UChar)0x20) && (strcmp(subBundleKey,"separator") != 0)) { |
374ca955 A |
260 | log_err("key \"%s\" at index %d in \"%s\" ends with a space in locale \"%s\"\n", |
261 | subBundleKey, | |
262 | idx, | |
263 | ures_getKey(currentBundle), | |
264 | locale); | |
265 | } | |
266 | else if (subBundleKey != NULL | |
267 | && strcmp(subBundleKey, "DateTimePatterns") == 0) | |
268 | { | |
269 | int32_t quoted = 0; | |
270 | const UChar *localeStrItr = localeStr; | |
271 | while (*localeStrItr) { | |
272 | if (*localeStrItr == (UChar)0x27 /* ' */) { | |
273 | quoted++; | |
274 | } | |
275 | else if ((quoted % 2) == 0) { | |
276 | /* Search for unquoted characters */ | |
277 | if (4 <= idx && idx <= 7 | |
278 | && (*localeStrItr == (UChar)0x6B /* k */ | |
279 | || *localeStrItr == (UChar)0x48 /* H */ | |
280 | || *localeStrItr == (UChar)0x6D /* m */ | |
281 | || *localeStrItr == (UChar)0x73 /* s */ | |
282 | || *localeStrItr == (UChar)0x53 /* S */ | |
283 | || *localeStrItr == (UChar)0x61 /* a */ | |
284 | || *localeStrItr == (UChar)0x68 /* h */ | |
285 | || *localeStrItr == (UChar)0x7A /* z */)) | |
286 | { | |
287 | log_err("key \"%s\" at index %d has time pattern chars in date for locale \"%s\"\n", | |
288 | subBundleKey, | |
289 | idx, | |
290 | locale); | |
291 | } | |
292 | else if (0 <= idx && idx <= 3 | |
293 | && (*localeStrItr == (UChar)0x47 /* G */ | |
294 | || *localeStrItr == (UChar)0x79 /* y */ | |
295 | || *localeStrItr == (UChar)0x4D /* M */ | |
296 | || *localeStrItr == (UChar)0x64 /* d */ | |
297 | || *localeStrItr == (UChar)0x45 /* E */ | |
298 | || *localeStrItr == (UChar)0x44 /* D */ | |
299 | || *localeStrItr == (UChar)0x46 /* F */ | |
300 | || *localeStrItr == (UChar)0x77 /* w */ | |
301 | || *localeStrItr == (UChar)0x57 /* W */)) | |
302 | { | |
303 | log_err("key \"%s\" at index %d has date pattern chars in time for locale \"%s\"\n", | |
304 | subBundleKey, | |
305 | idx, | |
306 | locale); | |
307 | } | |
308 | } | |
309 | localeStrItr++; | |
310 | } | |
311 | } | |
312 | else if (idx == 4 && subBundleKey != NULL | |
313 | && strcmp(subBundleKey, "NumberElements") == 0 | |
314 | && u_charDigitValue(localeStr[0]) != 0) | |
315 | { | |
316 | log_err("key \"%s\" at index %d has a non-zero based number for locale \"%s\"\n", | |
317 | subBundleKey, | |
318 | idx, | |
319 | locale); | |
320 | } | |
321 | } | |
57a6839d | 322 | (void)sameArray; /* Suppress set but not used warning. */ |
374ca955 A |
323 | /* if (sameArray && strcmp(rootName, "root") == 0) { |
324 | log_err("Arrays are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n", | |
325 | subBundleKey, | |
326 | ures_getKey(currentBundle), | |
327 | locale); | |
328 | }*/ | |
329 | } | |
330 | ures_close(subSubBundle); | |
331 | ures_close(subSubRootBundle); | |
332 | } | |
333 | else if (ures_getType(subBundle) == URES_STRING) { | |
334 | int32_t len = 0; | |
335 | const UChar *string = ures_getString(subBundle, &len, &errorCode); | |
336 | if (U_FAILURE(errorCode) || string == NULL) { | |
337 | log_err("Can't open a string with key \"%s\" in \"%s\" for locale \"%s\"\n", | |
338 | subBundleKey, | |
339 | ures_getKey(currentBundle), | |
340 | locale); | |
341 | } else if (string[0] == (UChar)0x20) { | |
342 | log_err("key \"%s\" in \"%s\" starts with a space in locale \"%s\"\n", | |
343 | subBundleKey, | |
344 | ures_getKey(currentBundle), | |
345 | locale); | |
46f4442e A |
346 | /* localeDisplayPattern/separator can end with a space */ |
347 | } else if (string[len - 1] == (UChar)0x20 && (strcmp(subBundleKey,"separator"))) { | |
374ca955 A |
348 | log_err("key \"%s\" in \"%s\" ends with a space in locale \"%s\"\n", |
349 | subBundleKey, | |
350 | ures_getKey(currentBundle), | |
351 | locale); | |
46f4442e A |
352 | } else if (strcmp(subBundleKey, "localPatternChars") == 0) { |
353 | /* Note: We no longer import localPatternChars data starting | |
354 | * ICU 3.8. So it never comes into this else if block. (ticket#5597) | |
355 | */ | |
356 | ||
374ca955 A |
357 | /* Check well-formedness of localPatternChars. First, the |
358 | * length must match the number of fields defined by | |
359 | * DateFormat. Second, each character in the string must | |
360 | * be in the set [A-Za-z]. Finally, each character must be | |
361 | * unique. | |
362 | */ | |
363 | int32_t i,j; | |
364 | #if !UCONFIG_NO_FORMATTING | |
365 | if (len != UDAT_FIELD_COUNT) { | |
366 | log_err("key \"%s\" has the wrong number of characters in locale \"%s\"\n", | |
367 | subBundleKey, | |
368 | locale); | |
369 | } | |
370 | #endif | |
371 | /* Check char validity. */ | |
372 | for (i=0; i<len; ++i) { | |
373 | if (!((string[i] >= 65/*'A'*/ && string[i] <= 90/*'Z'*/) || | |
374 | (string[i] >= 97/*'a'*/ && string[i] <= 122/*'z'*/))) { | |
375 | log_err("key \"%s\" has illegal character '%c' in locale \"%s\"\n", | |
376 | subBundleKey, | |
377 | (char) string[i], | |
378 | locale); | |
379 | } | |
380 | /* Do O(n^2) check for duplicate chars. */ | |
381 | for (j=0; j<i; ++j) { | |
382 | if (string[j] == string[i]) { | |
383 | log_err("key \"%s\" has duplicate character '%c' in locale \"%s\"\n", | |
384 | subBundleKey, | |
385 | (char) string[i], | |
386 | locale); | |
387 | } | |
388 | } | |
389 | } | |
390 | } | |
391 | /* No fallback was done. Check for duplicate data */ | |
392 | /* The ures_* API does not do fallback of sub-resource bundles, | |
393 | So we can't do this now. */ | |
394 | #if 0 | |
395 | else if (strcmp(locale, "root") != 0 && errorCode == U_ZERO_ERROR) { | |
396 | ||
397 | const UChar *rootString = ures_getString(subRootBundle, &len, &errorCode); | |
398 | if (U_FAILURE(errorCode) || rootString == NULL) { | |
399 | log_err("Can't open a string with key \"%s\" in \"%s\" in root\n", | |
400 | ures_getKey(subRootBundle), | |
401 | ures_getKey(currentBundle)); | |
402 | continue; | |
403 | } else if (u_strcmp(string, rootString) == 0) { | |
729e4ab9 | 404 | if (strcmp(locale, "de_CH") != 0 && strcmp(subBundleKey, "Countries") != 0 && |
374ca955 A |
405 | strcmp(subBundleKey, "Version") != 0) { |
406 | log_err("Found duplicate data with key \"%s\" in \"%s\" in locale \"%s\"\n", | |
407 | ures_getKey(subRootBundle), | |
408 | ures_getKey(currentBundle), | |
409 | locale); | |
410 | } | |
411 | else { | |
412 | /* Ignore for now. */ | |
413 | /* Can be fixed if fallback through de locale was done. */ | |
414 | log_verbose("Skipping key %s in %s\n", subBundleKey, locale); | |
415 | } | |
416 | } | |
417 | } | |
418 | #endif | |
419 | } | |
420 | else if (ures_getType(subBundle) == URES_TABLE) { | |
73c04bcf A |
421 | if (strcmp(subBundleKey, "availableFormats")!=0) { |
422 | /* Here is one of the recursive parts */ | |
423 | TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale); | |
424 | } | |
425 | else { | |
426 | log_verbose("Skipping key %s in %s\n", subBundleKey, locale); | |
427 | } | |
374ca955 A |
428 | } |
429 | else if (ures_getType(subBundle) == URES_BINARY || ures_getType(subBundle) == URES_INT) { | |
430 | /* Can't do anything to check it */ | |
431 | /* We'll assume it's all correct */ | |
432 | if (strcmp(subBundleKey, "MeasurementSystem") != 0) { | |
433 | log_verbose("Skipping key \"%s\" in \"%s\" for locale \"%s\"\n", | |
434 | subBundleKey, | |
435 | ures_getKey(currentBundle), | |
436 | locale); | |
437 | } | |
438 | /* Testing for MeasurementSystem is done in VerifyTranslation */ | |
439 | } | |
440 | else { | |
441 | log_err("Type %d for key \"%s\" in \"%s\" is unknown for locale \"%s\"\n", | |
442 | ures_getType(subBundle), | |
443 | subBundleKey, | |
444 | ures_getKey(currentBundle), | |
445 | locale); | |
446 | } | |
447 | ures_close(subRootBundle); | |
448 | ures_close(subBundle); | |
449 | } | |
450 | } | |
51004dcb | 451 | #endif |
374ca955 A |
452 | |
453 | static void | |
454 | testLCID(UResourceBundle *currentBundle, | |
455 | const char *localeName) | |
456 | { | |
340931cb | 457 | (void)currentBundle; // suppress compiler warnings about unused variables |
374ca955 A |
458 | UErrorCode status = U_ZERO_ERROR; |
459 | uint32_t expectedLCID; | |
460 | char lcidStringC[64] = {0}; | |
57a6839d | 461 | int32_t len; |
374ca955 A |
462 | |
463 | expectedLCID = uloc_getLCID(localeName); | |
464 | if (expectedLCID == 0) { | |
465 | log_verbose("INFO: %-5s does not have any LCID mapping\n", | |
466 | localeName); | |
467 | return; | |
468 | } | |
469 | ||
470 | status = U_ZERO_ERROR; | |
2ca993e8 | 471 | len = uprv_convertToPosix(expectedLCID, lcidStringC, UPRV_LENGTHOF(lcidStringC) - 1, &status); |
374ca955 A |
472 | if (U_FAILURE(status)) { |
473 | log_err("ERROR: %.4x does not have a POSIX mapping due to %s\n", | |
474 | expectedLCID, u_errorName(status)); | |
475 | } | |
57a6839d | 476 | lcidStringC[len] = 0; |
374ca955 A |
477 | |
478 | if(strcmp(localeName, lcidStringC) != 0) { | |
479 | char langName[1024]; | |
480 | char langLCID[1024]; | |
481 | uloc_getLanguage(localeName, langName, sizeof(langName), &status); | |
482 | uloc_getLanguage(lcidStringC, langLCID, sizeof(langLCID), &status); | |
483 | ||
484 | if (strcmp(langName, langLCID) == 0) { | |
485 | log_verbose("WARNING: %-5s resolves to %s (0x%.4x)\n", | |
486 | localeName, lcidStringC, expectedLCID); | |
487 | } | |
3d1f044b | 488 | else if (!(strcmp(localeName, "ku") == 0 && log_knownIssue("20181", "ICU-20181 Fix LCID mapping for ckb vs ku"))) { |
374ca955 A |
489 | log_err("ERROR: %-5s has 0x%.4x and the number resolves wrongfully to %s\n", |
490 | localeName, expectedLCID, lcidStringC); | |
491 | } | |
492 | } | |
493 | } | |
494 | ||
51004dcb | 495 | #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
374ca955 A |
496 | static void |
497 | TestLocaleStructure(void) { | |
57a6839d A |
498 | // This test checks the locale structure against a key file located |
499 | // at source/test/testdata/structLocale.txt. When adding new data to | |
b331163b | 500 | // a locale file such as en.txt, the structLocale.txt file must be changed |
57a6839d A |
501 | // too to include the the template of the new data. Otherwise this test |
502 | // will fail! | |
503 | ||
374ca955 A |
504 | UResourceBundle *root, *currentLocale; |
505 | int32_t locCount = uloc_countAvailable(); | |
506 | int32_t locIndex; | |
507 | UErrorCode errorCode = U_ZERO_ERROR; | |
73c04bcf | 508 | const char *currLoc, *resolvedLoc; |
374ca955 A |
509 | |
510 | /* TODO: Compare against parent's data too. This code can't handle fallbacks that some tools do already. */ | |
511 | /* char locName[ULOC_FULLNAME_CAPACITY]; | |
512 | char *locNamePtr; | |
513 | ||
514 | for (locIndex = 0; locIndex < locCount; locIndex++) { | |
515 | errorCode=U_ZERO_ERROR; | |
516 | strcpy(locName, uloc_getAvailable(locIndex)); | |
517 | locNamePtr = strrchr(locName, '_'); | |
518 | if (locNamePtr) { | |
519 | *locNamePtr = 0; | |
520 | } | |
521 | else { | |
522 | strcpy(locName, "root"); | |
523 | } | |
524 | ||
525 | root = ures_openDirect(NULL, locName, &errorCode); | |
526 | if(U_FAILURE(errorCode)) { | |
527 | log_err("Can't open %s\n", locName); | |
528 | continue; | |
529 | } | |
530 | */ | |
531 | if (locCount <= 1) { | |
532 | log_data_err("At least root needs to be installed\n"); | |
533 | } | |
534 | ||
535 | root = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); | |
536 | if(U_FAILURE(errorCode)) { | |
537 | log_data_err("Can't open structLocale\n"); | |
538 | return; | |
539 | } | |
540 | for (locIndex = 0; locIndex < locCount; locIndex++) { | |
541 | errorCode=U_ZERO_ERROR; | |
542 | currLoc = uloc_getAvailable(locIndex); | |
543 | currentLocale = ures_open(NULL, currLoc, &errorCode); | |
544 | if(errorCode != U_ZERO_ERROR) { | |
545 | if(U_SUCCESS(errorCode)) { | |
546 | /* It's installed, but there is no data. | |
547 | It's installed for the g18n white paper [grhoten] */ | |
729e4ab9 A |
548 | log_err("ERROR: Locale %-5s not installed, and it should be, err %s\n", |
549 | uloc_getAvailable(locIndex), u_errorName(errorCode)); | |
374ca955 A |
550 | } else { |
551 | log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", | |
552 | u_errorName(errorCode), | |
553 | uloc_getAvailable(locIndex)); | |
554 | } | |
555 | ures_close(currentLocale); | |
556 | continue; | |
557 | } | |
558 | ures_getStringByKey(currentLocale, "Version", NULL, &errorCode); | |
559 | if(errorCode != U_ZERO_ERROR) { | |
560 | log_err("No version information is available for locale %s, and it should be!\n", | |
561 | currLoc); | |
562 | } | |
563 | else if (ures_getStringByKey(currentLocale, "Version", NULL, &errorCode)[0] == (UChar)(0x78)) { | |
564 | log_verbose("WARNING: The locale %s is experimental! It shouldn't be listed as an installed locale.\n", | |
565 | currLoc); | |
566 | } | |
73c04bcf | 567 | resolvedLoc = ures_getLocaleByType(currentLocale, ULOC_ACTUAL_LOCALE, &errorCode); |
3d1f044b A |
568 | if (strcmp(resolvedLoc, currLoc) != 0 && strcmp(currLoc, "ars") != 0 && strcmp(currLoc, "wuu") != 0 // /* ars,wuu are aliased locales */ |
569 | && strcmp(currLoc, "ur_Arab_IN") != 0 && strcmp(currLoc, "ur_Aran_IN") != 0 /* so are ur_Ara?_IN <rdar://problem/47494884> */ | |
570 | && strcmp(currLoc, "pa_Aran") != 0) { /* and pa_Aran <rdar://problem/51418203> */ | |
73c04bcf A |
571 | /* All locales have at least a Version resource. |
572 | If it's absolutely empty, then the previous test will fail too.*/ | |
573 | log_err("Locale resolves to different locale. Is %s an alias of %s?\n", | |
574 | currLoc, resolvedLoc); | |
575 | } | |
374ca955 A |
576 | TestKeyInRootRecursive(root, "root", currentLocale, currLoc); |
577 | ||
578 | testLCID(currentLocale, currLoc); | |
579 | ||
580 | ures_close(currentLocale); | |
581 | } | |
582 | ||
583 | ures_close(root); | |
584 | } | |
51004dcb | 585 | #endif |
374ca955 A |
586 | |
587 | static void | |
588 | compareArrays(const char *keyName, | |
589 | UResourceBundle *fromArray, const char *fromLocale, | |
590 | UResourceBundle *toArray, const char *toLocale, | |
591 | int32_t start, int32_t end) | |
592 | { | |
593 | int32_t fromSize = ures_getSize(fromArray); | |
594 | int32_t toSize = ures_getSize(fromArray); | |
595 | int32_t idx; | |
596 | UErrorCode errorCode = U_ZERO_ERROR; | |
597 | ||
598 | if (fromSize > toSize) { | |
599 | fromSize = toSize; | |
600 | log_err("Arrays are different size from \"%s\" to \"%s\"\n", | |
601 | fromLocale, | |
602 | toLocale); | |
603 | } | |
604 | ||
605 | for (idx = start; idx <= end; idx++) { | |
606 | const UChar *fromBundleStr = ures_getStringByIndex(fromArray, idx, NULL, &errorCode); | |
607 | const UChar *toBundleStr = ures_getStringByIndex(toArray, idx, NULL, &errorCode); | |
608 | if (fromBundleStr && toBundleStr && u_strcmp(fromBundleStr, toBundleStr) != 0) | |
609 | { | |
610 | log_err("Difference for %s at index %d from %s= \"%s\" to %s= \"%s\"\n", | |
611 | keyName, | |
612 | idx, | |
613 | fromLocale, | |
614 | austrdup(fromBundleStr), | |
615 | toLocale, | |
616 | austrdup(toBundleStr)); | |
617 | } | |
618 | } | |
619 | } | |
620 | ||
621 | static void | |
622 | compareConsistentCountryInfo(const char *fromLocale, const char *toLocale) { | |
623 | UErrorCode errorCode = U_ZERO_ERROR; | |
374ca955 A |
624 | UResourceBundle *fromArray, *toArray; |
625 | UResourceBundle *fromLocaleBund = ures_open(NULL, fromLocale, &errorCode); | |
626 | UResourceBundle *toLocaleBund = ures_open(NULL, toLocale, &errorCode); | |
627 | UResourceBundle *toCalendar, *fromCalendar, *toGregorian, *fromGregorian; | |
628 | ||
629 | if(U_FAILURE(errorCode)) { | |
630 | log_err("Can't open resource bundle %s or %s - %s\n", fromLocale, toLocale, u_errorName(errorCode)); | |
631 | return; | |
632 | } | |
633 | fromCalendar = ures_getByKey(fromLocaleBund, "calendar", NULL, &errorCode); | |
634 | fromGregorian = ures_getByKeyWithFallback(fromCalendar, "gregorian", NULL, &errorCode); | |
729e4ab9 | 635 | |
374ca955 A |
636 | toCalendar = ures_getByKey(toLocaleBund, "calendar", NULL, &errorCode); |
637 | toGregorian = ures_getByKeyWithFallback(toCalendar, "gregorian", NULL, &errorCode); | |
374ca955 A |
638 | |
639 | fromArray = ures_getByKey(fromLocaleBund, "CurrencyElements", NULL, &errorCode); | |
640 | toArray = ures_getByKey(toLocaleBund, "CurrencyElements", NULL, &errorCode); | |
641 | if (strcmp(fromLocale, "en_CA") != 0) | |
642 | { | |
643 | /* The first one is probably localized. */ | |
644 | compareArrays("CurrencyElements", fromArray, fromLocale, toArray, toLocale, 1, 2); | |
645 | } | |
646 | ures_close(fromArray); | |
647 | ures_close(toArray); | |
648 | ||
649 | fromArray = ures_getByKey(fromLocaleBund, "NumberPatterns", NULL, &errorCode); | |
650 | toArray = ures_getByKey(toLocaleBund, "NumberPatterns", NULL, &errorCode); | |
651 | if (strcmp(fromLocale, "en_CA") != 0) | |
652 | { | |
653 | compareArrays("NumberPatterns", fromArray, fromLocale, toArray, toLocale, 0, 3); | |
654 | } | |
655 | ures_close(fromArray); | |
656 | ures_close(toArray); | |
657 | ||
658 | /* Difficult to test properly */ | |
659 | /* | |
660 | fromArray = ures_getByKey(fromLocaleBund, "DateTimePatterns", NULL, &errorCode); | |
661 | toArray = ures_getByKey(toLocaleBund, "DateTimePatterns", NULL, &errorCode); | |
662 | { | |
663 | compareArrays("DateTimePatterns", fromArray, fromLocale, toArray, toLocale); | |
664 | } | |
665 | ures_close(fromArray); | |
666 | ures_close(toArray);*/ | |
667 | ||
668 | fromArray = ures_getByKey(fromLocaleBund, "NumberElements", NULL, &errorCode); | |
669 | toArray = ures_getByKey(toLocaleBund, "NumberElements", NULL, &errorCode); | |
670 | if (strcmp(fromLocale, "en_CA") != 0) | |
671 | { | |
672 | compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 0, 3); | |
673 | /* Index 4 is a script based 0 */ | |
674 | compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 5, 10); | |
675 | } | |
676 | ures_close(fromArray); | |
677 | ures_close(toArray); | |
374ca955 A |
678 | ures_close(fromCalendar); |
679 | ures_close(toCalendar); | |
680 | ures_close(fromGregorian); | |
681 | ures_close(toGregorian); | |
682 | ||
683 | ures_close(fromLocaleBund); | |
684 | ures_close(toLocaleBund); | |
685 | } | |
686 | ||
687 | static void | |
688 | TestConsistentCountryInfo(void) { | |
689 | /* UResourceBundle *fromLocale, *toLocale;*/ | |
690 | int32_t locCount = uloc_countAvailable(); | |
691 | int32_t fromLocIndex, toLocIndex; | |
692 | ||
693 | int32_t fromCountryLen, toCountryLen; | |
694 | char fromCountry[ULOC_FULLNAME_CAPACITY], toCountry[ULOC_FULLNAME_CAPACITY]; | |
695 | ||
696 | int32_t fromVariantLen, toVariantLen; | |
697 | char fromVariant[ULOC_FULLNAME_CAPACITY], toVariant[ULOC_FULLNAME_CAPACITY]; | |
698 | ||
699 | UErrorCode errorCode = U_ZERO_ERROR; | |
700 | ||
701 | for (fromLocIndex = 0; fromLocIndex < locCount; fromLocIndex++) { | |
702 | const char *fromLocale = uloc_getAvailable(fromLocIndex); | |
703 | ||
704 | errorCode=U_ZERO_ERROR; | |
705 | fromCountryLen = uloc_getCountry(fromLocale, fromCountry, ULOC_FULLNAME_CAPACITY, &errorCode); | |
706 | if (fromCountryLen <= 0) { | |
707 | /* Ignore countryless locales */ | |
708 | continue; | |
709 | } | |
710 | fromVariantLen = uloc_getVariant(fromLocale, fromVariant, ULOC_FULLNAME_CAPACITY, &errorCode); | |
711 | if (fromVariantLen > 0) { | |
3d1f044b | 712 | /* Most variants are ignorable like collation variants. */ |
374ca955 A |
713 | continue; |
714 | } | |
715 | /* Start comparing only after the current index. | |
716 | Previous loop should have already compared fromLocIndex. | |
717 | */ | |
718 | for (toLocIndex = fromLocIndex + 1; toLocIndex < locCount; toLocIndex++) { | |
719 | const char *toLocale = uloc_getAvailable(toLocIndex); | |
720 | ||
721 | toCountryLen = uloc_getCountry(toLocale, toCountry, ULOC_FULLNAME_CAPACITY, &errorCode); | |
722 | if(U_FAILURE(errorCode)) { | |
723 | log_err("Unknown failure fromLocale=%s toLocale=%s errorCode=%s\n", | |
724 | fromLocale, toLocale, u_errorName(errorCode)); | |
725 | continue; | |
726 | } | |
727 | ||
728 | if (toCountryLen <= 0) { | |
729 | /* Ignore countryless locales */ | |
730 | continue; | |
731 | } | |
732 | toVariantLen = uloc_getVariant(toLocale, toVariant, ULOC_FULLNAME_CAPACITY, &errorCode); | |
733 | if (toVariantLen > 0) { | |
3d1f044b | 734 | /* Most variants are ignorable like collation variants. */ |
374ca955 A |
735 | /* They're a variant for a reason. */ |
736 | continue; | |
737 | } | |
738 | if (strcmp(fromCountry, toCountry) == 0) { | |
739 | log_verbose("comparing fromLocale=%s toLocale=%s\n", | |
740 | fromLocale, toLocale); | |
741 | compareConsistentCountryInfo(fromLocale, toLocale); | |
742 | } | |
743 | } | |
744 | } | |
745 | } | |
746 | ||
747 | static int32_t | |
748 | findStringSetMismatch(const char *currLoc, const UChar *string, int32_t langSize, | |
57a6839d | 749 | USet * mergedExemplarSet, |
0f5d89e8 | 750 | UBool ignoreNumbers, UChar32* badCharPtr) { |
374ca955 | 751 | UErrorCode errorCode = U_ZERO_ERROR; |
57a6839d | 752 | USet *exemplarSet; |
374ca955 | 753 | int32_t strIdx; |
57a6839d A |
754 | if (mergedExemplarSet == NULL) { |
755 | return -1; | |
756 | } | |
757 | exemplarSet = createFlattenSet(mergedExemplarSet, &errorCode); | |
374ca955 | 758 | if (U_FAILURE(errorCode)) { |
57a6839d | 759 | log_err("%s: error createFlattenSet returned %s\n", currLoc, u_errorName(errorCode)); |
374ca955 A |
760 | return -1; |
761 | } | |
762 | ||
0f5d89e8 A |
763 | for (strIdx = 0; strIdx < langSize;) { |
764 | UChar32 testChar; | |
765 | U16_NEXT(string, strIdx, langSize, testChar); | |
766 | if (!uset_contains(exemplarSet, testChar) | |
767 | && testChar != 0x0020 && testChar != 0x00A0 && testChar != 0x002e && testChar != 0x002c && testChar != 0x002d && testChar != 0x0027 | |
768 | && testChar != 0x005B && testChar != 0x005D && testChar != 0x2019 && testChar != 0x0f0b && testChar != 0x200C && testChar != 0x200D) { | |
769 | if (!ignoreNumbers || (ignoreNumbers && (testChar < 0x30 || testChar > 0x39))) { | |
73c04bcf | 770 | uset_close(exemplarSet); |
729e4ab9 | 771 | if (badCharPtr) { |
0f5d89e8 | 772 | *badCharPtr = testChar; |
729e4ab9 | 773 | } |
374ca955 A |
774 | return strIdx; |
775 | } | |
776 | } | |
777 | } | |
778 | uset_close(exemplarSet); | |
729e4ab9 A |
779 | if (badCharPtr) { |
780 | *badCharPtr = 0; | |
781 | } | |
374ca955 A |
782 | return -1; |
783 | } | |
73c04bcf A |
784 | /* include non-invariant chars */ |
785 | static int32_t | |
786 | myUCharsToChars(const UChar* us, char* cs, int32_t len){ | |
787 | int32_t i=0; | |
788 | for(; i< len; i++){ | |
789 | if(us[i] < 0x7f){ | |
790 | cs[i] = (char)us[i]; | |
791 | }else{ | |
792 | return -1; | |
793 | } | |
794 | } | |
795 | return i; | |
796 | } | |
729e4ab9 A |
797 | static void |
798 | findSetMatch( UScriptCode *scriptCodes, int32_t scriptsLen, | |
374ca955 A |
799 | USet *exemplarSet, |
800 | const char *locale){ | |
801 | USet *scripts[10]= {0}; | |
802 | char pattern[256] = { '[', ':', 0x000 }; | |
803 | int32_t patternLen; | |
804 | UChar uPattern[256] = {0}; | |
805 | UErrorCode status = U_ZERO_ERROR; | |
806 | int32_t i; | |
807 | ||
808 | /* create the sets with script codes */ | |
809 | for(i = 0; i<scriptsLen; i++){ | |
810 | strcat(pattern, uscript_getShortName(scriptCodes[i])); | |
811 | strcat(pattern, ":]"); | |
812 | patternLen = (int32_t)strlen(pattern); | |
813 | u_charsToUChars(pattern, uPattern, patternLen); | |
814 | scripts[i] = uset_openPattern(uPattern, patternLen, &status); | |
815 | if(U_FAILURE(status)){ | |
46f4442e A |
816 | log_err("Could not create set for pattern %s. Error: %s\n", pattern, u_errorName(status)); |
817 | return; | |
374ca955 | 818 | } |
729e4ab9 | 819 | pattern[2] = 0; |
374ca955 A |
820 | } |
821 | if (strcmp(locale, "uk") == 0 || strcmp(locale, "uk_UA") == 0) { | |
822 | /* Special addition. Add the modifying apostrophe, which isn't in Cyrillic. */ | |
823 | uset_add(scripts[0], 0x2bc); | |
824 | } | |
825 | if(U_SUCCESS(status)){ | |
826 | UBool existsInScript = FALSE; | |
827 | /* iterate over the exemplarSet and ascertain if all | |
828 | * UChars in exemplarSet belong to the scripts returned | |
829 | * by getScript | |
830 | */ | |
831 | int32_t count = uset_getItemCount(exemplarSet); | |
832 | ||
833 | for( i=0; i < count; i++){ | |
834 | UChar32 start = 0; | |
835 | UChar32 end = 0; | |
836 | UChar *str = NULL; | |
837 | int32_t strCapacity = 0; | |
729e4ab9 | 838 | |
374ca955 A |
839 | strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); |
840 | if(U_SUCCESS(status)){ | |
841 | int32_t j; | |
842 | if(strCapacity == 0){ | |
843 | /* ok the item is a range */ | |
844 | for( j = 0; j < scriptsLen; j++){ | |
845 | if(uset_containsRange(scripts[j], start, end) == TRUE){ | |
846 | existsInScript = TRUE; | |
847 | } | |
848 | } | |
849 | if(existsInScript == FALSE){ | |
73c04bcf A |
850 | for( j = 0; j < scriptsLen; j++){ |
851 | UChar toPattern[500]={'\0'}; | |
852 | char pat[500]={'\0'}; | |
853 | int32_t len = uset_toPattern(scripts[j], toPattern, 500, TRUE, &status); | |
854 | len = myUCharsToChars(toPattern, pat, len); | |
855 | 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)); | |
856 | if(len!=-1){ | |
857 | log_err("Pattern: %s\n",pat); | |
858 | } | |
859 | } | |
374ca955 A |
860 | log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); |
861 | } | |
862 | }else{ | |
863 | strCapacity++; /* increment for NUL termination */ | |
864 | /* allocate the str and call the api again */ | |
865 | str = (UChar*) malloc(U_SIZEOF_UCHAR * strCapacity); | |
866 | strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); | |
867 | /* iterate over the scripts and figure out if the string contained is actually | |
868 | * in the script set | |
869 | */ | |
870 | for( j = 0; j < scriptsLen; j++){ | |
871 | if(uset_containsString(scripts[j],str, strCapacity) == TRUE){ | |
872 | existsInScript = TRUE; | |
873 | } | |
874 | } | |
875 | if(existsInScript == FALSE){ | |
876 | log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); | |
877 | } | |
878 | } | |
879 | } | |
880 | } | |
881 | ||
882 | } | |
883 | ||
884 | /* close the sets */ | |
885 | for(i = 0; i<scriptsLen; i++){ | |
886 | uset_close(scripts[i]); | |
887 | } | |
888 | } | |
889 | ||
890 | static void VerifyTranslation(void) { | |
891 | UResourceBundle *root, *currentLocale; | |
892 | int32_t locCount = uloc_countAvailable(); | |
893 | int32_t locIndex; | |
894 | UErrorCode errorCode = U_ZERO_ERROR; | |
374ca955 A |
895 | const char *currLoc; |
896 | UScriptCode scripts[USCRIPT_CODE_LIMIT]; | |
897 | int32_t numScripts; | |
898 | int32_t idx; | |
899 | int32_t end; | |
900 | UResourceBundle *resArray; | |
901 | ||
902 | if (locCount <= 1) { | |
903 | log_data_err("At least root needs to be installed\n"); | |
904 | } | |
905 | ||
906 | root = ures_openDirect(NULL, "root", &errorCode); | |
907 | if(U_FAILURE(errorCode)) { | |
908 | log_data_err("Can't open root\n"); | |
909 | return; | |
910 | } | |
911 | for (locIndex = 0; locIndex < locCount; locIndex++) { | |
57a6839d | 912 | USet * mergedExemplarSet = NULL; |
374ca955 A |
913 | errorCode=U_ZERO_ERROR; |
914 | currLoc = uloc_getAvailable(locIndex); | |
915 | currentLocale = ures_open(NULL, currLoc, &errorCode); | |
916 | if(errorCode != U_ZERO_ERROR) { | |
917 | if(U_SUCCESS(errorCode)) { | |
918 | /* It's installed, but there is no data. | |
919 | It's installed for the g18n white paper [grhoten] */ | |
920 | log_err("ERROR: Locale %-5s not installed, and it should be!\n", | |
921 | uloc_getAvailable(locIndex)); | |
922 | } else { | |
923 | log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", | |
924 | u_errorName(errorCode), | |
925 | uloc_getAvailable(locIndex)); | |
926 | } | |
927 | ures_close(currentLocale); | |
928 | continue; | |
929 | } | |
57a6839d A |
930 | { |
931 | UErrorCode exemplarStatus = U_ZERO_ERROR; | |
932 | ULocaleData * uld = ulocdata_open(currLoc, &exemplarStatus); | |
933 | if (U_SUCCESS(exemplarStatus)) { | |
934 | USet * exemplarSet = ulocdata_getExemplarSet(uld, NULL, USET_ADD_CASE_MAPPINGS, ULOCDATA_ES_STANDARD, &exemplarStatus); | |
935 | if (U_SUCCESS(exemplarStatus)) { | |
936 | mergedExemplarSet = uset_cloneAsThawed(exemplarSet); | |
937 | uset_close(exemplarSet); | |
938 | exemplarSet = ulocdata_getExemplarSet(uld, NULL, USET_ADD_CASE_MAPPINGS, ULOCDATA_ES_AUXILIARY, &exemplarStatus); | |
939 | if (U_SUCCESS(exemplarStatus)) { | |
940 | uset_addAll(mergedExemplarSet, exemplarSet); | |
941 | uset_close(exemplarSet); | |
942 | } | |
943 | exemplarStatus = U_ZERO_ERROR; | |
944 | exemplarSet = ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_PUNCTUATION, &exemplarStatus); | |
945 | if (U_SUCCESS(exemplarStatus)) { | |
946 | uset_addAll(mergedExemplarSet, exemplarSet); | |
947 | uset_close(exemplarSet); | |
948 | } | |
949 | } else { | |
950 | log_err("error ulocdata_getExemplarSet (main) for locale %s returned %s\n", currLoc, u_errorName(errorCode)); | |
951 | } | |
952 | ulocdata_close(uld); | |
953 | } else { | |
954 | log_err("error ulocdata_open for locale %s returned %s\n", currLoc, u_errorName(errorCode)); | |
955 | } | |
374ca955 | 956 | } |
57a6839d | 957 | if (mergedExemplarSet == NULL /*|| (getTestOption(QUICK_OPTION) && uset_size() > 2048)*/) { |
374ca955 A |
958 | log_verbose("skipping test for %s\n", currLoc); |
959 | } | |
57a6839d A |
960 | //else if (uprv_strncmp(currLoc,"bem",3) == 0 || uprv_strncmp(currLoc,"mgo",3) == 0 || uprv_strncmp(currLoc,"nl",2) == 0) { |
961 | // log_verbose("skipping test for %s, some month and country names known to use aux exemplars\n", currLoc); | |
962 | //} | |
374ca955 A |
963 | else { |
964 | UChar langBuffer[128]; | |
965 | int32_t langSize; | |
966 | int32_t strIdx; | |
0f5d89e8 | 967 | UChar32 badChar; |
2ca993e8 | 968 | langSize = uloc_getDisplayLanguage(currLoc, currLoc, langBuffer, UPRV_LENGTHOF(langBuffer), &errorCode); |
374ca955 A |
969 | if (U_FAILURE(errorCode)) { |
970 | log_err("error uloc_getDisplayLanguage returned %s\n", u_errorName(errorCode)); | |
3d1f044b A |
971 | } else if (uprv_strncmp(currLoc,"gez",3) == 0 || uprv_strcmp(currLoc,"sa") == 0 || uprv_strncmp(currLoc,"sa_",3) == 0) { // Apple xtra locales |
972 | log_verbose("skipping DisplayLanguage test for %s, name or exemplars may need adjustment\n", currLoc); | |
973 | } else { | |
57a6839d | 974 | strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, mergedExemplarSet, FALSE, &badChar); |
374ca955 | 975 | if (strIdx >= 0) { |
2ca993e8 A |
976 | char bbuf[256]; |
977 | log_err("getDisplayLanguage(%s) at index %d returned characters not in the exemplar characters: %04X in \"%s\"\n", | |
978 | currLoc, strIdx, badChar, u_austrncpy(bbuf,langBuffer,langSize)); | |
374ca955 A |
979 | } |
980 | } | |
2ca993e8 | 981 | langSize = uloc_getDisplayCountry(currLoc, currLoc, langBuffer, UPRV_LENGTHOF(langBuffer), &errorCode); |
374ca955 A |
982 | if (U_FAILURE(errorCode)) { |
983 | log_err("error uloc_getDisplayCountry returned %s\n", u_errorName(errorCode)); | |
984 | } | |
3d1f044b A |
985 | if ( uprv_strcmp(currLoc,"ba") == 0 || uprv_strncmp(currLoc,"ba_",3) == 0 || |
986 | uprv_strcmp(currLoc,"cv") == 0 || uprv_strncmp(currLoc,"cv_",3) == 0 || | |
987 | uprv_strcmp(currLoc,"dv") == 0 || uprv_strncmp(currLoc,"dv_",3) == 0 || | |
988 | uprv_strcmp(currLoc,"sa") == 0 || uprv_strncmp(currLoc,"sa_",3) == 0 || | |
989 | uprv_strncmp(currLoc,"kaj",3) == 0 || uprv_strncmp(currLoc,"kpe",3) == 0 || | |
c5116b9f A |
990 | uprv_strncmp(currLoc,"nqo",3) == 0 || uprv_strncmp(currLoc,"sat",3) == 0 || |
991 | uprv_strncmp(currLoc,"syr",3) == 0 || | |
340931cb A |
992 | uprv_strncmp(currLoc,"ks_Deva",7) == 0 || uprv_strncmp(currLoc,"mni_Mtei",8) == 0 || |
993 | uprv_strncmp(currLoc,"sd_Deva",7) == 0 ) { | |
3d1f044b A |
994 | log_verbose("skipping day/month tests for %s, missing some translated names\n", currLoc); |
995 | } else { | |
374ca955 A |
996 | UResourceBundle* cal = ures_getByKey(currentLocale, "calendar", NULL, &errorCode); |
997 | UResourceBundle* greg = ures_getByKeyWithFallback(cal, "gregorian", NULL, &errorCode); | |
998 | UResourceBundle* names = ures_getByKeyWithFallback(greg, "dayNames", NULL, &errorCode); | |
999 | UResourceBundle* format = ures_getByKeyWithFallback(names, "format", NULL, &errorCode); | |
1000 | resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); | |
1001 | ||
1002 | if (U_FAILURE(errorCode)) { | |
1003 | log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); | |
1004 | } | |
729e4ab9 | 1005 | if (getTestOption(QUICK_OPTION)) { |
374ca955 A |
1006 | end = 1; |
1007 | } | |
1008 | else { | |
1009 | end = ures_getSize(resArray); | |
1010 | } | |
1011 | ||
2ca993e8 A |
1012 | if ((uprv_strncmp(currLoc,"lrc",3) == 0 || uprv_strncmp(currLoc,"mzn",3) == 0) && |
1013 | log_knownIssue("cldrbug:8899", "lrc and mzn locales don't have translated day names")) { | |
1014 | end = 0; | |
1015 | } | |
374ca955 A |
1016 | |
1017 | for (idx = 0; idx < end; idx++) { | |
1018 | const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); | |
1019 | if (U_FAILURE(errorCode)) { | |
1020 | log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); | |
1021 | continue; | |
1022 | } | |
57a6839d | 1023 | strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, mergedExemplarSet, TRUE, &badChar); |
2ca993e8 | 1024 | if ( strIdx >= 0 ) { |
57a6839d A |
1025 | log_err("getDayNames(%s, %d) at index %d returned characters not in the exemplar characters: %04X.\n", |
1026 | currLoc, idx, strIdx, badChar); | |
374ca955 A |
1027 | } |
1028 | } | |
1029 | ures_close(resArray); | |
1030 | ures_close(format); | |
1031 | ures_close(names); | |
1032 | ||
1033 | names = ures_getByKeyWithFallback(greg, "monthNames", NULL, &errorCode); | |
1034 | format = ures_getByKeyWithFallback(names,"format", NULL, &errorCode); | |
1035 | resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); | |
1036 | if (U_FAILURE(errorCode)) { | |
1037 | log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); | |
1038 | } | |
729e4ab9 | 1039 | if (getTestOption(QUICK_OPTION)) { |
374ca955 A |
1040 | end = 1; |
1041 | } | |
1042 | else { | |
1043 | end = ures_getSize(resArray); | |
1044 | } | |
1045 | ||
1046 | for (idx = 0; idx < end; idx++) { | |
1047 | const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); | |
1048 | if (U_FAILURE(errorCode)) { | |
1049 | log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); | |
1050 | continue; | |
1051 | } | |
57a6839d A |
1052 | strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, mergedExemplarSet, TRUE, &badChar); |
1053 | if (strIdx >= 0) { | |
1054 | log_err("getMonthNames(%s, %d) at index %d returned characters not in the exemplar characters: %04X.\n", | |
1055 | currLoc, idx, strIdx, badChar); | |
374ca955 A |
1056 | } |
1057 | } | |
1058 | ures_close(resArray); | |
1059 | ures_close(format); | |
1060 | ures_close(names); | |
1061 | ures_close(greg); | |
1062 | ures_close(cal); | |
1063 | } | |
1064 | errorCode = U_ZERO_ERROR; | |
2ca993e8 | 1065 | numScripts = uscript_getCode(currLoc, scripts, UPRV_LENGTHOF(scripts), &errorCode); |
b331163b A |
1066 | if (strcmp(currLoc, "yi") == 0 && numScripts > 0 && log_knownIssue("11217", "Fix result of uscript_getCode for yi: USCRIPT_YI -> USCRIPT_HEBREW")) { |
1067 | scripts[0] = USCRIPT_HEBREW; | |
1068 | } | |
374ca955 A |
1069 | if (numScripts == 0) { |
1070 | log_err("uscript_getCode(%s) doesn't work.\n", currLoc); | |
1071 | }else if(scripts[0] == USCRIPT_COMMON){ | |
729e4ab9 | 1072 | log_err("uscript_getCode(%s) returned USCRIPT_COMMON.\n", currLoc); |
374ca955 A |
1073 | } |
1074 | ||
1075 | /* test that the scripts are a superset of exemplar characters. */ | |
1076 | { | |
73c04bcf A |
1077 | ULocaleData *uld = ulocdata_open(currLoc,&errorCode); |
1078 | USet *exemplarSet = ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &errorCode); | |
374ca955 A |
1079 | /* test if exemplar characters are part of script code */ |
1080 | findSetMatch(scripts, numScripts, exemplarSet, currLoc); | |
1081 | uset_close(exemplarSet); | |
73c04bcf | 1082 | ulocdata_close(uld); |
374ca955 A |
1083 | } |
1084 | ||
1085 | /* test that the paperSize API works */ | |
1086 | { | |
1087 | int32_t height=0, width=0; | |
1088 | ulocdata_getPaperSize(currLoc, &height, &width, &errorCode); | |
1089 | if(U_FAILURE(errorCode)){ | |
1090 | log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); | |
1091 | } | |
1092 | if(strstr(currLoc, "_US")!=NULL && height != 279 && width != 216 ){ | |
1093 | log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); | |
1094 | } | |
1095 | } | |
57a6839d | 1096 | /* test that the MeasurementSystem API works */ |
374ca955 | 1097 | { |
51004dcb | 1098 | char fullLoc[ULOC_FULLNAME_CAPACITY]; |
57a6839d A |
1099 | UMeasurementSystem measurementSystem; |
1100 | int32_t height = 0, width = 0; | |
1101 | ||
1102 | uloc_addLikelySubtags(currLoc, fullLoc, ULOC_FULLNAME_CAPACITY, &errorCode); | |
1103 | ||
1104 | errorCode = U_ZERO_ERROR; | |
1105 | measurementSystem = ulocdata_getMeasurementSystem(currLoc, &errorCode); | |
1106 | if (U_FAILURE(errorCode)) { | |
374ca955 | 1107 | log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); |
57a6839d A |
1108 | } else { |
1109 | if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_MM")!=NULL || strstr(fullLoc, "_LR")!=NULL ) { | |
1110 | if(measurementSystem != UMS_US){ | |
1111 | log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); | |
1112 | } | |
b331163b A |
1113 | } else if ( strstr(fullLoc, "_GB")!=NULL ) { |
1114 | if(measurementSystem != UMS_UK){ | |
1115 | log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); | |
1116 | } | |
57a6839d A |
1117 | } else if (measurementSystem != UMS_SI) { |
1118 | log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); | |
1119 | } | |
374ca955 | 1120 | } |
57a6839d A |
1121 | |
1122 | errorCode = U_ZERO_ERROR; | |
1123 | ulocdata_getPaperSize(currLoc, &height, &width, &errorCode); | |
1124 | if (U_FAILURE(errorCode)) { | |
1125 | log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); | |
1126 | } else { | |
1127 | if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_BZ")!=NULL || strstr(fullLoc, "_CA")!=NULL || strstr(fullLoc, "_CL")!=NULL || | |
1128 | strstr(fullLoc, "_CO")!=NULL || strstr(fullLoc, "_CR")!=NULL || strstr(fullLoc, "_GT")!=NULL || strstr(fullLoc, "_MX")!=NULL || | |
1129 | strstr(fullLoc, "_NI")!=NULL || strstr(fullLoc, "_PA")!=NULL || strstr(fullLoc, "_PH")!=NULL || strstr(fullLoc, "_PR")!=NULL || | |
1130 | strstr(fullLoc, "_SV")!=NULL || strstr(fullLoc, "_VE")!=NULL ) { | |
1131 | if (height != 279 || width != 216) { | |
1132 | log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); | |
1133 | } | |
1134 | } else if (height != 297 || width != 210) { | |
1135 | log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); | |
374ca955 | 1136 | } |
374ca955 A |
1137 | } |
1138 | } | |
1139 | } | |
57a6839d A |
1140 | if (mergedExemplarSet != NULL) { |
1141 | uset_close(mergedExemplarSet); | |
1142 | } | |
374ca955 A |
1143 | ures_close(currentLocale); |
1144 | } | |
1145 | ||
1146 | ures_close(root); | |
1147 | } | |
1148 | ||
1149 | /* adjust this limit as appropriate */ | |
1150 | #define MAX_SCRIPTS_PER_LOCALE 8 | |
1151 | ||
1152 | static void TestExemplarSet(void){ | |
1153 | int32_t i, j, k, m, n; | |
1154 | int32_t equalCount = 0; | |
1155 | UErrorCode ec = U_ZERO_ERROR; | |
1156 | UEnumeration* avail; | |
1157 | USet* exemplarSets[2]; | |
73c04bcf | 1158 | USet* unassignedSet; |
374ca955 A |
1159 | UScriptCode code[MAX_SCRIPTS_PER_LOCALE]; |
1160 | USet* codeSets[MAX_SCRIPTS_PER_LOCALE]; | |
1161 | int32_t codeLen; | |
1162 | char cbuf[32]; /* 9 should be enough */ | |
1163 | UChar ubuf[64]; /* adjust as needed */ | |
1164 | UBool existsInScript; | |
1165 | int32_t itemCount; | |
1166 | int32_t strLen; | |
1167 | UChar32 start, end; | |
729e4ab9 | 1168 | |
73c04bcf A |
1169 | unassignedSet = NULL; |
1170 | exemplarSets[0] = NULL; | |
1171 | exemplarSets[1] = NULL; | |
374ca955 A |
1172 | for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { |
1173 | codeSets[i] = NULL; | |
1174 | } | |
1175 | ||
1176 | avail = ures_openAvailableLocales(NULL, &ec); | |
1177 | if (!assertSuccess("ures_openAvailableLocales", &ec)) goto END; | |
1178 | n = uenum_count(avail, &ec); | |
1179 | if (!assertSuccess("uenum_count", &ec)) goto END; | |
1180 | ||
73c04bcf A |
1181 | u_uastrcpy(ubuf, "[:unassigned:]"); |
1182 | unassignedSet = uset_openPattern(ubuf, -1, &ec); | |
1183 | if (!assertSuccess("uset_openPattern", &ec)) goto END; | |
1184 | ||
374ca955 A |
1185 | for(i=0; i<n; i++){ |
1186 | const char* locale = uenum_next(avail, NULL, &ec); | |
1187 | if (!assertSuccess("uenum_next", &ec)) goto END; | |
1188 | log_verbose("%s\n", locale); | |
1189 | for (k=0; k<2; ++k) { | |
1190 | uint32_t option = (k==0) ? 0 : USET_CASE_INSENSITIVE; | |
729e4ab9 | 1191 | ULocaleData *uld = ulocdata_open(locale,&ec); |
73c04bcf | 1192 | USet* exemplarSet = ulocdata_getExemplarSet(uld,NULL, option, ULOCDATA_ES_STANDARD, &ec); |
374ca955 | 1193 | uset_close(exemplarSets[k]); |
73c04bcf | 1194 | ulocdata_close(uld); |
374ca955 A |
1195 | exemplarSets[k] = exemplarSet; |
1196 | if (!assertSuccess("ulocaledata_getExemplarSet", &ec)) goto END; | |
1197 | ||
73c04bcf A |
1198 | if (uset_containsSome(exemplarSet, unassignedSet)) { |
1199 | log_err("ExemplarSet contains unassigned characters for locale : %s\n", locale); | |
1200 | } | |
374ca955 | 1201 | codeLen = uscript_getCode(locale, code, 8, &ec); |
b331163b A |
1202 | if (strcmp(locale, "yi") == 0 && codeLen > 0 && log_knownIssue("11217", "Fix result of uscript_getCode for yi: USCRIPT_YI -> USCRIPT_HEBREW")) { |
1203 | code[0] = USCRIPT_HEBREW; | |
1204 | } | |
374ca955 A |
1205 | if (!assertSuccess("uscript_getCode", &ec)) goto END; |
1206 | ||
1207 | for (j=0; j<MAX_SCRIPTS_PER_LOCALE; ++j) { | |
1208 | uset_close(codeSets[j]); | |
1209 | codeSets[j] = NULL; | |
1210 | } | |
1211 | for (j=0; j<codeLen; ++j) { | |
1212 | uprv_strcpy(cbuf, "[:"); | |
73c04bcf A |
1213 | if(code[j]==-1){ |
1214 | log_err("USCRIPT_INVALID_CODE returned for locale: %s\n", locale); | |
1215 | continue; | |
1216 | } | |
374ca955 A |
1217 | uprv_strcat(cbuf, uscript_getShortName(code[j])); |
1218 | uprv_strcat(cbuf, ":]"); | |
1219 | u_uastrcpy(ubuf, cbuf); | |
1220 | codeSets[j] = uset_openPattern(ubuf, -1, &ec); | |
1221 | } | |
1222 | if (!assertSuccess("uset_openPattern", &ec)) goto END; | |
1223 | ||
1224 | existsInScript = FALSE; | |
1225 | itemCount = uset_getItemCount(exemplarSet); | |
1226 | for (m=0; m<itemCount && !existsInScript; ++m) { | |
1227 | strLen = uset_getItem(exemplarSet, m, &start, &end, ubuf, | |
2ca993e8 | 1228 | UPRV_LENGTHOF(ubuf), &ec); |
374ca955 A |
1229 | /* failure here might mean str[] needs to be larger */ |
1230 | if (!assertSuccess("uset_getItem", &ec)) goto END; | |
1231 | if (strLen == 0) { | |
1232 | for (j=0; j<codeLen; ++j) { | |
73c04bcf | 1233 | if (codeSets[j]!=NULL && uset_containsRange(codeSets[j], start, end)) { |
374ca955 A |
1234 | existsInScript = TRUE; |
1235 | break; | |
1236 | } | |
1237 | } | |
1238 | } else { | |
1239 | for (j=0; j<codeLen; ++j) { | |
73c04bcf | 1240 | if (codeSets[j]!=NULL && uset_containsString(codeSets[j], ubuf, strLen)) { |
374ca955 A |
1241 | existsInScript = TRUE; |
1242 | break; | |
1243 | } | |
1244 | } | |
1245 | } | |
1246 | } | |
1247 | ||
1248 | if (existsInScript == FALSE){ | |
73c04bcf | 1249 | log_err("ExemplarSet containment failed for locale : %s\n", locale); |
374ca955 A |
1250 | } |
1251 | } | |
1252 | assertTrue("case-folded is a superset", | |
1253 | uset_containsAll(exemplarSets[1], exemplarSets[0])); | |
1254 | if (uset_equals(exemplarSets[1], exemplarSets[0])) { | |
1255 | ++equalCount; | |
1256 | } | |
1257 | } | |
1258 | /* Note: The case-folded set should sometimes be a strict superset | |
1259 | and sometimes be equal. */ | |
1260 | assertTrue("case-folded is sometimes a strict superset, and sometimes equal", | |
1261 | equalCount > 0 && equalCount < n); | |
729e4ab9 | 1262 | |
374ca955 A |
1263 | END: |
1264 | uenum_close(avail); | |
1265 | uset_close(exemplarSets[0]); | |
1266 | uset_close(exemplarSets[1]); | |
73c04bcf | 1267 | uset_close(unassignedSet); |
374ca955 A |
1268 | for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { |
1269 | uset_close(codeSets[i]); | |
1270 | } | |
1271 | } | |
1272 | ||
57a6839d | 1273 | enum { kUBufMax = 32 }; |
729e4ab9 | 1274 | static void TestLocaleDisplayPattern(void){ |
57a6839d A |
1275 | UErrorCode status; |
1276 | UChar pattern[kUBufMax] = {0,}; | |
1277 | UChar separator[kUBufMax] = {0,}; | |
1278 | ULocaleData *uld; | |
1279 | static const UChar enExpectPat[] = { 0x007B,0x0030,0x007D,0x0020,0x0028,0x007B,0x0031,0x007D,0x0029,0 }; /* "{0} ({1})" */ | |
1280 | static const UChar enExpectSep[] = { 0x002C,0x0020,0 }; /* ", " */ | |
1281 | static const UChar zhExpectPat[] = { 0x007B,0x0030,0x007D,0xFF08,0x007B,0x0031,0x007D,0xFF09,0 }; | |
f3c0d7a5 | 1282 | static const UChar zhExpectSep[] = { 0xFF0C,0 }; |
729e4ab9 | 1283 | |
57a6839d A |
1284 | status = U_ZERO_ERROR; |
1285 | uld = ulocdata_open("en", &status); | |
729e4ab9 | 1286 | if(U_FAILURE(status)){ |
57a6839d A |
1287 | log_data_err("ulocdata_open en error %s", u_errorName(status)); |
1288 | } else { | |
1289 | ulocdata_getLocaleDisplayPattern(uld, pattern, kUBufMax, &status); | |
1290 | if (U_FAILURE(status)){ | |
1291 | log_err("ulocdata_getLocaleDisplayPattern en error %s", u_errorName(status)); | |
1292 | } else if (u_strcmp(pattern, enExpectPat) != 0) { | |
1293 | log_err("ulocdata_getLocaleDisplayPattern en returns unexpected pattern"); | |
1294 | } | |
1295 | status = U_ZERO_ERROR; | |
1296 | ulocdata_getLocaleSeparator(uld, separator, kUBufMax, &status); | |
1297 | if (U_FAILURE(status)){ | |
1298 | log_err("ulocdata_getLocaleSeparator en error %s", u_errorName(status)); | |
1299 | } else if (u_strcmp(separator, enExpectSep) != 0) { | |
1300 | log_err("ulocdata_getLocaleSeparator en returns unexpected string "); | |
1301 | } | |
1302 | ulocdata_close(uld); | |
729e4ab9 | 1303 | } |
57a6839d | 1304 | |
729e4ab9 | 1305 | status = U_ZERO_ERROR; |
57a6839d A |
1306 | uld = ulocdata_open("zh", &status); |
1307 | if(U_FAILURE(status)){ | |
1308 | log_data_err("ulocdata_open zh error %s", u_errorName(status)); | |
1309 | } else { | |
1310 | ulocdata_getLocaleDisplayPattern(uld, pattern, kUBufMax, &status); | |
1311 | if (U_FAILURE(status)){ | |
1312 | log_err("ulocdata_getLocaleDisplayPattern zh error %s", u_errorName(status)); | |
1313 | } else if (u_strcmp(pattern, zhExpectPat) != 0) { | |
1314 | log_err("ulocdata_getLocaleDisplayPattern zh returns unexpected pattern"); | |
1315 | } | |
1316 | status = U_ZERO_ERROR; | |
1317 | ulocdata_getLocaleSeparator(uld, separator, kUBufMax, &status); | |
1318 | if (U_FAILURE(status)){ | |
1319 | log_err("ulocdata_getLocaleSeparator zh error %s", u_errorName(status)); | |
1320 | } else if (u_strcmp(separator, zhExpectSep) != 0) { | |
1321 | log_err("ulocdata_getLocaleSeparator zh returns unexpected string "); | |
1322 | } | |
1323 | ulocdata_close(uld); | |
729e4ab9 | 1324 | } |
729e4ab9 A |
1325 | } |
1326 | ||
73c04bcf A |
1327 | static void TestCoverage(void){ |
1328 | ULocaleDataDelimiterType types[] = { | |
1329 | ULOCDATA_QUOTATION_START, /* Quotation start */ | |
1330 | ULOCDATA_QUOTATION_END, /* Quotation end */ | |
1331 | ULOCDATA_ALT_QUOTATION_START, /* Alternate quotation start */ | |
1332 | ULOCDATA_ALT_QUOTATION_END, /* Alternate quotation end */ | |
1333 | ULOCDATA_DELIMITER_COUNT | |
1334 | }; | |
1335 | int i; | |
1336 | UBool sub; | |
1337 | UErrorCode status = U_ZERO_ERROR; | |
1338 | ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status); | |
1339 | ||
1340 | if(U_FAILURE(status)){ | |
729e4ab9 | 1341 | log_data_err("ulocdata_open error"); |
73c04bcf A |
1342 | return; |
1343 | } | |
1344 | ||
1345 | ||
1346 | for(i = 0; i < ULOCDATA_DELIMITER_COUNT; i++){ | |
1347 | UChar result[32] = {0,}; | |
1348 | status = U_ZERO_ERROR; | |
1349 | ulocdata_getDelimiter(uld, types[i], result, 32, &status); | |
1350 | if (U_FAILURE(status)){ | |
1351 | log_err("ulocdata_getgetDelimiter error with type %d", types[i]); | |
1352 | } | |
1353 | } | |
1354 | ||
1355 | sub = ulocdata_getNoSubstitute(uld); | |
1356 | ulocdata_setNoSubstitute(uld,sub); | |
1357 | ulocdata_close(uld); | |
1358 | } | |
1359 | ||
4388f060 A |
1360 | static void TestIndexChars(void) { |
1361 | /* Very basic test of ULOCDATA_ES_INDEX. | |
1362 | * No comprehensive test of data, just basic check that the code path is alive. | |
1363 | */ | |
1364 | UErrorCode status = U_ZERO_ERROR; | |
1365 | ULocaleData *uld; | |
1366 | USet *exemplarChars; | |
1367 | USet *indexChars; | |
1368 | ||
1369 | uld = ulocdata_open("en", &status); | |
1370 | exemplarChars = uset_openEmpty(); | |
1371 | indexChars = uset_openEmpty(); | |
1372 | ulocdata_getExemplarSet(uld, exemplarChars, 0, ULOCDATA_ES_STANDARD, &status); | |
1373 | ulocdata_getExemplarSet(uld, indexChars, 0, ULOCDATA_ES_INDEX, &status); | |
1374 | if (U_FAILURE(status)) { | |
1375 | log_data_err("File %s, line %d, Failure opening exemplar chars: %s", __FILE__, __LINE__, u_errorName(status)); | |
1376 | goto close_sets; | |
1377 | } | |
1378 | /* en data, standard exemplars are [a-z], lower case. */ | |
1379 | /* en data, index characters are [A-Z], upper case. */ | |
1380 | if ((uset_contains(exemplarChars, (UChar32)0x41) || uset_contains(indexChars, (UChar32)0x61))) { | |
1381 | log_err("File %s, line %d, Exemplar characters incorrect.", __FILE__, __LINE__ ); | |
1382 | goto close_sets; | |
1383 | } | |
1384 | if (!(uset_contains(exemplarChars, (UChar32)0x61) && uset_contains(indexChars, (UChar32)0x41) )) { | |
1385 | log_err("File %s, line %d, Exemplar characters incorrect.", __FILE__, __LINE__ ); | |
1386 | goto close_sets; | |
1387 | } | |
1388 | ||
1389 | close_sets: | |
1390 | uset_close(exemplarChars); | |
1391 | uset_close(indexChars); | |
1392 | ulocdata_close(uld); | |
1393 | } | |
1394 | ||
1395 | ||
1396 | ||
51004dcb | 1397 | #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
73c04bcf A |
1398 | static void TestCurrencyList(void){ |
1399 | #if !UCONFIG_NO_FORMATTING | |
1400 | UErrorCode errorCode = U_ZERO_ERROR; | |
1401 | int32_t structLocaleCount, currencyCount; | |
1402 | UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &errorCode); | |
1403 | const char *isoCode, *structISOCode; | |
1404 | UResourceBundle *subBundle; | |
1405 | UResourceBundle *currencies = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); | |
1406 | if(U_FAILURE(errorCode)) { | |
1407 | log_data_err("Can't open structLocale\n"); | |
1408 | return; | |
1409 | } | |
1410 | currencies = ures_getByKey(currencies, "Currencies", currencies, &errorCode); | |
1411 | currencyCount = uenum_count(en, &errorCode); | |
1412 | structLocaleCount = ures_getSize(currencies); | |
1413 | if (currencyCount != structLocaleCount) { | |
1414 | log_err("structLocale(%d) and ISO4217(%d) currency list are out of sync.\n", structLocaleCount, currencyCount); | |
1415 | #if U_CHARSET_FAMILY == U_ASCII_FAMILY | |
1416 | ures_resetIterator(currencies); | |
1417 | while ((isoCode = uenum_next(en, NULL, &errorCode)) != NULL && ures_hasNext(currencies)) { | |
1418 | subBundle = ures_getNextResource(currencies, NULL, &errorCode); | |
1419 | structISOCode = ures_getKey(subBundle); | |
1420 | ures_close(subBundle); | |
1421 | if (strcmp(structISOCode, isoCode) != 0) { | |
1422 | log_err("First difference found at structLocale(%s) and ISO4217(%s).\n", structISOCode, isoCode); | |
1423 | break; | |
1424 | } | |
1425 | } | |
1426 | #endif | |
1427 | } | |
1428 | ures_close(currencies); | |
1429 | uenum_close(en); | |
1430 | #endif | |
1431 | } | |
51004dcb | 1432 | #endif |
73c04bcf | 1433 | |
4388f060 A |
1434 | static void TestAvailableIsoCodes(void){ |
1435 | #if !UCONFIG_NO_FORMATTING | |
1436 | UErrorCode errorCode = U_ZERO_ERROR; | |
1437 | const char* eurCode = "EUR"; | |
1438 | const char* usdCode = "USD"; | |
1439 | const char* lastCode = "RHD"; | |
1440 | const char* zzzCode = "ZZZ"; | |
1441 | UDate date1950 = (UDate)-630720000000.0;/* year 1950 */ | |
1442 | UDate date1970 = (UDate)0.0; /* year 1970 */ | |
1443 | UDate date1975 = (UDate)173448000000.0; /* year 1975 */ | |
1444 | UDate date1978 = (UDate)260172000000.0; /* year 1978 */ | |
1445 | UDate date1981 = (UDate)346896000000.0; /* year 1981 */ | |
1446 | UDate date1992 = (UDate)693792000000.0; /* year 1992 */ | |
1447 | UChar* isoCode = (UChar*)malloc(sizeof(UChar) * (uprv_strlen(usdCode) + 1)); | |
1448 | ||
1449 | /* testing available codes with no time ranges */ | |
3d1f044b | 1450 | u_charsToUChars(eurCode, isoCode, (int32_t)uprv_strlen(usdCode) + 1); |
4388f060 A |
1451 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == FALSE) { |
1452 | log_data_err("FAIL: ISO code (%s) is not found.\n", eurCode); | |
1453 | } | |
1454 | ||
3d1f044b | 1455 | u_charsToUChars(usdCode, isoCode, (int32_t)uprv_strlen(zzzCode) + 1); |
4388f060 A |
1456 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == FALSE) { |
1457 | log_data_err("FAIL: ISO code (%s) is not found.\n", usdCode); | |
1458 | } | |
1459 | ||
3d1f044b | 1460 | u_charsToUChars(zzzCode, isoCode, (int32_t)uprv_strlen(zzzCode) + 1); |
4388f060 A |
1461 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == TRUE) { |
1462 | log_err("FAIL: ISO code (%s) is reported as available, but it doesn't exist.\n", zzzCode); | |
1463 | } | |
1464 | ||
3d1f044b | 1465 | u_charsToUChars(lastCode, isoCode, (int32_t)uprv_strlen(zzzCode) + 1); |
4388f060 A |
1466 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == FALSE) { |
1467 | log_data_err("FAIL: ISO code (%s) is not found.\n", lastCode); | |
1468 | } | |
1469 | ||
1470 | /* RHD was used from 1970-02-17 to 1980-04-18*/ | |
1471 | ||
1472 | /* to = null */ | |
1473 | if (ucurr_isAvailable(isoCode, date1970, U_DATE_MAX, &errorCode) == FALSE) { | |
1474 | log_data_err("FAIL: ISO code (%s) was available in time range >1970-01-01.\n", lastCode); | |
1475 | } | |
1476 | ||
1477 | if (ucurr_isAvailable(isoCode, date1975, U_DATE_MAX, &errorCode) == FALSE) { | |
1478 | log_data_err("FAIL: ISO code (%s) was available in time range >1975.\n", lastCode); | |
1479 | } | |
1480 | ||
1481 | if (ucurr_isAvailable(isoCode, date1981, U_DATE_MAX, &errorCode) == TRUE) { | |
1482 | log_err("FAIL: ISO code (%s) was not available in time range >1981.\n", lastCode); | |
1483 | } | |
1484 | ||
1485 | /* from = null */ | |
1486 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, date1970, &errorCode) == TRUE) { | |
1487 | log_err("FAIL: ISO code (%s) was not available in time range <1970.\n", lastCode); | |
1488 | } | |
1489 | ||
1490 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, date1975, &errorCode) == FALSE) { | |
1491 | log_data_err("FAIL: ISO code (%s) was available in time range <1975.\n", lastCode); | |
1492 | } | |
1493 | ||
1494 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, date1981, &errorCode) == FALSE) { | |
1495 | log_data_err("FAIL: ISO code (%s) was available in time range <1981.\n", lastCode); | |
1496 | } | |
1497 | ||
1498 | /* full ranges */ | |
1499 | if (ucurr_isAvailable(isoCode, date1975, date1978, &errorCode) == FALSE) { | |
1500 | log_data_err("FAIL: ISO code (%s) was available in time range 1975-1978.\n", lastCode); | |
1501 | } | |
1502 | ||
1503 | if (ucurr_isAvailable(isoCode, date1970, date1975, &errorCode) == FALSE) { | |
1504 | log_data_err("FAIL: ISO code (%s) was available in time range 1970-1975.\n", lastCode); | |
1505 | } | |
1506 | ||
1507 | if (ucurr_isAvailable(isoCode, date1975, date1981, &errorCode) == FALSE) { | |
1508 | log_data_err("FAIL: ISO code (%s) was available in time range 1975-1981.\n", lastCode); | |
1509 | } | |
1510 | ||
1511 | if (ucurr_isAvailable(isoCode, date1970, date1981, &errorCode) == FALSE) { | |
1512 | log_data_err("FAIL: ISO code (%s) was available in time range 1970-1981.\n", lastCode); | |
1513 | } | |
1514 | ||
1515 | if (ucurr_isAvailable(isoCode, date1981, date1992, &errorCode) == TRUE) { | |
1516 | log_err("FAIL: ISO code (%s) was not available in time range 1981-1992.\n", lastCode); | |
1517 | } | |
1518 | ||
1519 | if (ucurr_isAvailable(isoCode, date1950, date1970, &errorCode) == TRUE) { | |
1520 | log_err("FAIL: ISO code (%s) was not available in time range 1950-1970.\n", lastCode); | |
1521 | } | |
1522 | ||
1523 | /* wrong range - from > to*/ | |
1524 | if (ucurr_isAvailable(isoCode, date1975, date1970, &errorCode) == TRUE) { | |
1525 | log_err("FAIL: Wrong range 1975-1970 for ISO code (%s) was not reported.\n", lastCode); | |
1526 | } else if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) { | |
1527 | log_data_err("FAIL: Error code not reported for wrong range 1975-1970 for ISO code (%s).\n", lastCode); | |
1528 | } | |
1529 | ||
1530 | free(isoCode); | |
1531 | #endif | |
1532 | } | |
1533 | ||
0f5d89e8 A |
1534 | // Apple-specific |
1535 | typedef struct { | |
1536 | const char* locale; | |
1537 | const UChar* quoteStart; | |
1538 | const UChar* quoteEnd; | |
1539 | const UChar* altQuoteStart; | |
1540 | const UChar* altQuoteEnd; | |
1541 | } DelimItem; | |
1542 | static const DelimItem delimItems[] = { | |
1543 | { "en", u"“", u"”", u"‘", u"’"}, | |
1544 | { "es", u"«", u"»", u"“", u"”"}, | |
1545 | { "es_MX", u"“", u"”", u"‘", u"’"}, | |
1546 | { "ja", u"「", u"」", u"『", u"』"}, | |
1547 | { NULL,NULL,NULL,NULL,NULL } | |
1548 | }; | |
1549 | enum {kMaxDelimLen = 8}; | |
1550 | ||
1551 | static void TestDelimiters(void){ | |
1552 | const DelimItem* itemPtr; | |
1553 | for (itemPtr = delimItems; itemPtr->locale != NULL; itemPtr++) { | |
1554 | UErrorCode status = U_ZERO_ERROR; | |
1555 | ULocaleData* uldat = ulocdata_open(itemPtr->locale, &status); | |
1556 | if (U_FAILURE(status)) { | |
1557 | log_data_err("FAIL: ulocdata_open fails for locale %s: %s\n", itemPtr->locale, u_errorName(status)); | |
1558 | } else { | |
1559 | UChar quoteStart[kMaxDelimLen+1]; | |
1560 | UChar quoteEnd[kMaxDelimLen+1]; | |
1561 | UChar altQuoteStart[kMaxDelimLen+1]; | |
1562 | UChar altQuoteEnd[kMaxDelimLen+1]; | |
1563 | ||
1564 | ulocdata_getDelimiter(uldat, ULOCDATA_QUOTATION_START, quoteStart, kMaxDelimLen, &status); | |
1565 | quoteStart[kMaxDelimLen] = 0; | |
1566 | ulocdata_getDelimiter(uldat, ULOCDATA_QUOTATION_END, quoteEnd, kMaxDelimLen, &status); | |
1567 | quoteEnd[kMaxDelimLen] = 0; | |
1568 | ulocdata_getDelimiter(uldat, ULOCDATA_ALT_QUOTATION_START, altQuoteStart, kMaxDelimLen, &status); | |
1569 | altQuoteStart[kMaxDelimLen] = 0; | |
1570 | ulocdata_getDelimiter(uldat, ULOCDATA_ALT_QUOTATION_END, altQuoteEnd, kMaxDelimLen, &status); | |
1571 | altQuoteEnd[kMaxDelimLen] = 0; | |
1572 | if (U_FAILURE(status)) { | |
1573 | log_err("FAIL: ulocdata_getDelimiter fails for locale %s: %s\n", itemPtr->locale, u_errorName(status)); | |
1574 | } else if (u_strcmp(quoteStart, itemPtr->quoteStart) != 0 || u_strcmp(quoteEnd, itemPtr->quoteEnd) != 0 || | |
1575 | u_strcmp(altQuoteStart, itemPtr->altQuoteStart) != 0 || u_strcmp(altQuoteEnd, itemPtr->altQuoteEnd) != 0) { | |
1576 | log_err("FAIL: ulocdata_getDelimiter error for locale %s, one or more delimiters not as expected\n", itemPtr->locale); | |
1577 | } | |
1578 | ulocdata_close(uldat); | |
1579 | } | |
1580 | } | |
1581 | } | |
1582 | ||
1583 | ||
374ca955 A |
1584 | #define TESTCASE(name) addTest(root, &name, "tsutil/cldrtest/" #name) |
1585 | ||
1586 | void addCLDRTest(TestNode** root); | |
1587 | ||
1588 | void addCLDRTest(TestNode** root) | |
1589 | { | |
729e4ab9 | 1590 | #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
374ca955 | 1591 | TESTCASE(TestLocaleStructure); |
729e4ab9 A |
1592 | TESTCASE(TestCurrencyList); |
1593 | #endif | |
374ca955 A |
1594 | TESTCASE(TestConsistentCountryInfo); |
1595 | TESTCASE(VerifyTranslation); | |
1596 | TESTCASE(TestExemplarSet); | |
729e4ab9 | 1597 | TESTCASE(TestLocaleDisplayPattern); |
73c04bcf | 1598 | TESTCASE(TestCoverage); |
4388f060 A |
1599 | TESTCASE(TestIndexChars); |
1600 | TESTCASE(TestAvailableIsoCodes); | |
0f5d89e8 | 1601 | TESTCASE(TestDelimiters); |
374ca955 | 1602 | } |
4388f060 | 1603 |