]>
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 | { | |
457 | UErrorCode status = U_ZERO_ERROR; | |
458 | uint32_t expectedLCID; | |
459 | char lcidStringC[64] = {0}; | |
57a6839d | 460 | int32_t len; |
374ca955 A |
461 | |
462 | expectedLCID = uloc_getLCID(localeName); | |
463 | if (expectedLCID == 0) { | |
464 | log_verbose("INFO: %-5s does not have any LCID mapping\n", | |
465 | localeName); | |
466 | return; | |
467 | } | |
468 | ||
469 | status = U_ZERO_ERROR; | |
2ca993e8 | 470 | len = uprv_convertToPosix(expectedLCID, lcidStringC, UPRV_LENGTHOF(lcidStringC) - 1, &status); |
374ca955 A |
471 | if (U_FAILURE(status)) { |
472 | log_err("ERROR: %.4x does not have a POSIX mapping due to %s\n", | |
473 | expectedLCID, u_errorName(status)); | |
474 | } | |
57a6839d | 475 | lcidStringC[len] = 0; |
374ca955 A |
476 | |
477 | if(strcmp(localeName, lcidStringC) != 0) { | |
478 | char langName[1024]; | |
479 | char langLCID[1024]; | |
480 | uloc_getLanguage(localeName, langName, sizeof(langName), &status); | |
481 | uloc_getLanguage(lcidStringC, langLCID, sizeof(langLCID), &status); | |
482 | ||
483 | if (strcmp(langName, langLCID) == 0) { | |
484 | log_verbose("WARNING: %-5s resolves to %s (0x%.4x)\n", | |
485 | localeName, lcidStringC, expectedLCID); | |
486 | } | |
3d1f044b | 487 | else if (!(strcmp(localeName, "ku") == 0 && log_knownIssue("20181", "ICU-20181 Fix LCID mapping for ckb vs ku"))) { |
374ca955 A |
488 | log_err("ERROR: %-5s has 0x%.4x and the number resolves wrongfully to %s\n", |
489 | localeName, expectedLCID, lcidStringC); | |
490 | } | |
491 | } | |
492 | } | |
493 | ||
51004dcb | 494 | #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
374ca955 A |
495 | static void |
496 | TestLocaleStructure(void) { | |
57a6839d A |
497 | // This test checks the locale structure against a key file located |
498 | // at source/test/testdata/structLocale.txt. When adding new data to | |
b331163b | 499 | // a locale file such as en.txt, the structLocale.txt file must be changed |
57a6839d A |
500 | // too to include the the template of the new data. Otherwise this test |
501 | // will fail! | |
502 | ||
374ca955 A |
503 | UResourceBundle *root, *currentLocale; |
504 | int32_t locCount = uloc_countAvailable(); | |
505 | int32_t locIndex; | |
506 | UErrorCode errorCode = U_ZERO_ERROR; | |
73c04bcf | 507 | const char *currLoc, *resolvedLoc; |
374ca955 A |
508 | |
509 | /* TODO: Compare against parent's data too. This code can't handle fallbacks that some tools do already. */ | |
510 | /* char locName[ULOC_FULLNAME_CAPACITY]; | |
511 | char *locNamePtr; | |
512 | ||
513 | for (locIndex = 0; locIndex < locCount; locIndex++) { | |
514 | errorCode=U_ZERO_ERROR; | |
515 | strcpy(locName, uloc_getAvailable(locIndex)); | |
516 | locNamePtr = strrchr(locName, '_'); | |
517 | if (locNamePtr) { | |
518 | *locNamePtr = 0; | |
519 | } | |
520 | else { | |
521 | strcpy(locName, "root"); | |
522 | } | |
523 | ||
524 | root = ures_openDirect(NULL, locName, &errorCode); | |
525 | if(U_FAILURE(errorCode)) { | |
526 | log_err("Can't open %s\n", locName); | |
527 | continue; | |
528 | } | |
529 | */ | |
530 | if (locCount <= 1) { | |
531 | log_data_err("At least root needs to be installed\n"); | |
532 | } | |
533 | ||
534 | root = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); | |
535 | if(U_FAILURE(errorCode)) { | |
536 | log_data_err("Can't open structLocale\n"); | |
537 | return; | |
538 | } | |
539 | for (locIndex = 0; locIndex < locCount; locIndex++) { | |
540 | errorCode=U_ZERO_ERROR; | |
541 | currLoc = uloc_getAvailable(locIndex); | |
542 | currentLocale = ures_open(NULL, currLoc, &errorCode); | |
543 | if(errorCode != U_ZERO_ERROR) { | |
544 | if(U_SUCCESS(errorCode)) { | |
545 | /* It's installed, but there is no data. | |
546 | It's installed for the g18n white paper [grhoten] */ | |
729e4ab9 A |
547 | log_err("ERROR: Locale %-5s not installed, and it should be, err %s\n", |
548 | uloc_getAvailable(locIndex), u_errorName(errorCode)); | |
374ca955 A |
549 | } else { |
550 | log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", | |
551 | u_errorName(errorCode), | |
552 | uloc_getAvailable(locIndex)); | |
553 | } | |
554 | ures_close(currentLocale); | |
555 | continue; | |
556 | } | |
557 | ures_getStringByKey(currentLocale, "Version", NULL, &errorCode); | |
558 | if(errorCode != U_ZERO_ERROR) { | |
559 | log_err("No version information is available for locale %s, and it should be!\n", | |
560 | currLoc); | |
561 | } | |
562 | else if (ures_getStringByKey(currentLocale, "Version", NULL, &errorCode)[0] == (UChar)(0x78)) { | |
563 | log_verbose("WARNING: The locale %s is experimental! It shouldn't be listed as an installed locale.\n", | |
564 | currLoc); | |
565 | } | |
73c04bcf | 566 | resolvedLoc = ures_getLocaleByType(currentLocale, ULOC_ACTUAL_LOCALE, &errorCode); |
3d1f044b A |
567 | if (strcmp(resolvedLoc, currLoc) != 0 && strcmp(currLoc, "ars") != 0 && strcmp(currLoc, "wuu") != 0 // /* ars,wuu are aliased locales */ |
568 | && strcmp(currLoc, "ur_Arab_IN") != 0 && strcmp(currLoc, "ur_Aran_IN") != 0 /* so are ur_Ara?_IN <rdar://problem/47494884> */ | |
569 | && strcmp(currLoc, "pa_Aran") != 0) { /* and pa_Aran <rdar://problem/51418203> */ | |
73c04bcf A |
570 | /* All locales have at least a Version resource. |
571 | If it's absolutely empty, then the previous test will fail too.*/ | |
572 | log_err("Locale resolves to different locale. Is %s an alias of %s?\n", | |
573 | currLoc, resolvedLoc); | |
574 | } | |
374ca955 A |
575 | TestKeyInRootRecursive(root, "root", currentLocale, currLoc); |
576 | ||
577 | testLCID(currentLocale, currLoc); | |
578 | ||
579 | ures_close(currentLocale); | |
580 | } | |
581 | ||
582 | ures_close(root); | |
583 | } | |
51004dcb | 584 | #endif |
374ca955 A |
585 | |
586 | static void | |
587 | compareArrays(const char *keyName, | |
588 | UResourceBundle *fromArray, const char *fromLocale, | |
589 | UResourceBundle *toArray, const char *toLocale, | |
590 | int32_t start, int32_t end) | |
591 | { | |
592 | int32_t fromSize = ures_getSize(fromArray); | |
593 | int32_t toSize = ures_getSize(fromArray); | |
594 | int32_t idx; | |
595 | UErrorCode errorCode = U_ZERO_ERROR; | |
596 | ||
597 | if (fromSize > toSize) { | |
598 | fromSize = toSize; | |
599 | log_err("Arrays are different size from \"%s\" to \"%s\"\n", | |
600 | fromLocale, | |
601 | toLocale); | |
602 | } | |
603 | ||
604 | for (idx = start; idx <= end; idx++) { | |
605 | const UChar *fromBundleStr = ures_getStringByIndex(fromArray, idx, NULL, &errorCode); | |
606 | const UChar *toBundleStr = ures_getStringByIndex(toArray, idx, NULL, &errorCode); | |
607 | if (fromBundleStr && toBundleStr && u_strcmp(fromBundleStr, toBundleStr) != 0) | |
608 | { | |
609 | log_err("Difference for %s at index %d from %s= \"%s\" to %s= \"%s\"\n", | |
610 | keyName, | |
611 | idx, | |
612 | fromLocale, | |
613 | austrdup(fromBundleStr), | |
614 | toLocale, | |
615 | austrdup(toBundleStr)); | |
616 | } | |
617 | } | |
618 | } | |
619 | ||
620 | static void | |
621 | compareConsistentCountryInfo(const char *fromLocale, const char *toLocale) { | |
622 | UErrorCode errorCode = U_ZERO_ERROR; | |
374ca955 A |
623 | UResourceBundle *fromArray, *toArray; |
624 | UResourceBundle *fromLocaleBund = ures_open(NULL, fromLocale, &errorCode); | |
625 | UResourceBundle *toLocaleBund = ures_open(NULL, toLocale, &errorCode); | |
626 | UResourceBundle *toCalendar, *fromCalendar, *toGregorian, *fromGregorian; | |
627 | ||
628 | if(U_FAILURE(errorCode)) { | |
629 | log_err("Can't open resource bundle %s or %s - %s\n", fromLocale, toLocale, u_errorName(errorCode)); | |
630 | return; | |
631 | } | |
632 | fromCalendar = ures_getByKey(fromLocaleBund, "calendar", NULL, &errorCode); | |
633 | fromGregorian = ures_getByKeyWithFallback(fromCalendar, "gregorian", NULL, &errorCode); | |
729e4ab9 | 634 | |
374ca955 A |
635 | toCalendar = ures_getByKey(toLocaleBund, "calendar", NULL, &errorCode); |
636 | toGregorian = ures_getByKeyWithFallback(toCalendar, "gregorian", NULL, &errorCode); | |
374ca955 A |
637 | |
638 | fromArray = ures_getByKey(fromLocaleBund, "CurrencyElements", NULL, &errorCode); | |
639 | toArray = ures_getByKey(toLocaleBund, "CurrencyElements", NULL, &errorCode); | |
640 | if (strcmp(fromLocale, "en_CA") != 0) | |
641 | { | |
642 | /* The first one is probably localized. */ | |
643 | compareArrays("CurrencyElements", fromArray, fromLocale, toArray, toLocale, 1, 2); | |
644 | } | |
645 | ures_close(fromArray); | |
646 | ures_close(toArray); | |
647 | ||
648 | fromArray = ures_getByKey(fromLocaleBund, "NumberPatterns", NULL, &errorCode); | |
649 | toArray = ures_getByKey(toLocaleBund, "NumberPatterns", NULL, &errorCode); | |
650 | if (strcmp(fromLocale, "en_CA") != 0) | |
651 | { | |
652 | compareArrays("NumberPatterns", fromArray, fromLocale, toArray, toLocale, 0, 3); | |
653 | } | |
654 | ures_close(fromArray); | |
655 | ures_close(toArray); | |
656 | ||
657 | /* Difficult to test properly */ | |
658 | /* | |
659 | fromArray = ures_getByKey(fromLocaleBund, "DateTimePatterns", NULL, &errorCode); | |
660 | toArray = ures_getByKey(toLocaleBund, "DateTimePatterns", NULL, &errorCode); | |
661 | { | |
662 | compareArrays("DateTimePatterns", fromArray, fromLocale, toArray, toLocale); | |
663 | } | |
664 | ures_close(fromArray); | |
665 | ures_close(toArray);*/ | |
666 | ||
667 | fromArray = ures_getByKey(fromLocaleBund, "NumberElements", NULL, &errorCode); | |
668 | toArray = ures_getByKey(toLocaleBund, "NumberElements", NULL, &errorCode); | |
669 | if (strcmp(fromLocale, "en_CA") != 0) | |
670 | { | |
671 | compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 0, 3); | |
672 | /* Index 4 is a script based 0 */ | |
673 | compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 5, 10); | |
674 | } | |
675 | ures_close(fromArray); | |
676 | ures_close(toArray); | |
374ca955 A |
677 | ures_close(fromCalendar); |
678 | ures_close(toCalendar); | |
679 | ures_close(fromGregorian); | |
680 | ures_close(toGregorian); | |
681 | ||
682 | ures_close(fromLocaleBund); | |
683 | ures_close(toLocaleBund); | |
684 | } | |
685 | ||
686 | static void | |
687 | TestConsistentCountryInfo(void) { | |
688 | /* UResourceBundle *fromLocale, *toLocale;*/ | |
689 | int32_t locCount = uloc_countAvailable(); | |
690 | int32_t fromLocIndex, toLocIndex; | |
691 | ||
692 | int32_t fromCountryLen, toCountryLen; | |
693 | char fromCountry[ULOC_FULLNAME_CAPACITY], toCountry[ULOC_FULLNAME_CAPACITY]; | |
694 | ||
695 | int32_t fromVariantLen, toVariantLen; | |
696 | char fromVariant[ULOC_FULLNAME_CAPACITY], toVariant[ULOC_FULLNAME_CAPACITY]; | |
697 | ||
698 | UErrorCode errorCode = U_ZERO_ERROR; | |
699 | ||
700 | for (fromLocIndex = 0; fromLocIndex < locCount; fromLocIndex++) { | |
701 | const char *fromLocale = uloc_getAvailable(fromLocIndex); | |
702 | ||
703 | errorCode=U_ZERO_ERROR; | |
704 | fromCountryLen = uloc_getCountry(fromLocale, fromCountry, ULOC_FULLNAME_CAPACITY, &errorCode); | |
705 | if (fromCountryLen <= 0) { | |
706 | /* Ignore countryless locales */ | |
707 | continue; | |
708 | } | |
709 | fromVariantLen = uloc_getVariant(fromLocale, fromVariant, ULOC_FULLNAME_CAPACITY, &errorCode); | |
710 | if (fromVariantLen > 0) { | |
3d1f044b | 711 | /* Most variants are ignorable like collation variants. */ |
374ca955 A |
712 | continue; |
713 | } | |
714 | /* Start comparing only after the current index. | |
715 | Previous loop should have already compared fromLocIndex. | |
716 | */ | |
717 | for (toLocIndex = fromLocIndex + 1; toLocIndex < locCount; toLocIndex++) { | |
718 | const char *toLocale = uloc_getAvailable(toLocIndex); | |
719 | ||
720 | toCountryLen = uloc_getCountry(toLocale, toCountry, ULOC_FULLNAME_CAPACITY, &errorCode); | |
721 | if(U_FAILURE(errorCode)) { | |
722 | log_err("Unknown failure fromLocale=%s toLocale=%s errorCode=%s\n", | |
723 | fromLocale, toLocale, u_errorName(errorCode)); | |
724 | continue; | |
725 | } | |
726 | ||
727 | if (toCountryLen <= 0) { | |
728 | /* Ignore countryless locales */ | |
729 | continue; | |
730 | } | |
731 | toVariantLen = uloc_getVariant(toLocale, toVariant, ULOC_FULLNAME_CAPACITY, &errorCode); | |
732 | if (toVariantLen > 0) { | |
3d1f044b | 733 | /* Most variants are ignorable like collation variants. */ |
374ca955 A |
734 | /* They're a variant for a reason. */ |
735 | continue; | |
736 | } | |
737 | if (strcmp(fromCountry, toCountry) == 0) { | |
738 | log_verbose("comparing fromLocale=%s toLocale=%s\n", | |
739 | fromLocale, toLocale); | |
740 | compareConsistentCountryInfo(fromLocale, toLocale); | |
741 | } | |
742 | } | |
743 | } | |
744 | } | |
745 | ||
746 | static int32_t | |
747 | findStringSetMismatch(const char *currLoc, const UChar *string, int32_t langSize, | |
57a6839d | 748 | USet * mergedExemplarSet, |
0f5d89e8 | 749 | UBool ignoreNumbers, UChar32* badCharPtr) { |
374ca955 | 750 | UErrorCode errorCode = U_ZERO_ERROR; |
57a6839d | 751 | USet *exemplarSet; |
374ca955 | 752 | int32_t strIdx; |
57a6839d A |
753 | if (mergedExemplarSet == NULL) { |
754 | return -1; | |
755 | } | |
756 | exemplarSet = createFlattenSet(mergedExemplarSet, &errorCode); | |
374ca955 | 757 | if (U_FAILURE(errorCode)) { |
57a6839d | 758 | log_err("%s: error createFlattenSet returned %s\n", currLoc, u_errorName(errorCode)); |
374ca955 A |
759 | return -1; |
760 | } | |
761 | ||
0f5d89e8 A |
762 | for (strIdx = 0; strIdx < langSize;) { |
763 | UChar32 testChar; | |
764 | U16_NEXT(string, strIdx, langSize, testChar); | |
765 | if (!uset_contains(exemplarSet, testChar) | |
766 | && testChar != 0x0020 && testChar != 0x00A0 && testChar != 0x002e && testChar != 0x002c && testChar != 0x002d && testChar != 0x0027 | |
767 | && testChar != 0x005B && testChar != 0x005D && testChar != 0x2019 && testChar != 0x0f0b && testChar != 0x200C && testChar != 0x200D) { | |
768 | if (!ignoreNumbers || (ignoreNumbers && (testChar < 0x30 || testChar > 0x39))) { | |
73c04bcf | 769 | uset_close(exemplarSet); |
729e4ab9 | 770 | if (badCharPtr) { |
0f5d89e8 | 771 | *badCharPtr = testChar; |
729e4ab9 | 772 | } |
374ca955 A |
773 | return strIdx; |
774 | } | |
775 | } | |
776 | } | |
777 | uset_close(exemplarSet); | |
729e4ab9 A |
778 | if (badCharPtr) { |
779 | *badCharPtr = 0; | |
780 | } | |
374ca955 A |
781 | return -1; |
782 | } | |
73c04bcf A |
783 | /* include non-invariant chars */ |
784 | static int32_t | |
785 | myUCharsToChars(const UChar* us, char* cs, int32_t len){ | |
786 | int32_t i=0; | |
787 | for(; i< len; i++){ | |
788 | if(us[i] < 0x7f){ | |
789 | cs[i] = (char)us[i]; | |
790 | }else{ | |
791 | return -1; | |
792 | } | |
793 | } | |
794 | return i; | |
795 | } | |
729e4ab9 A |
796 | static void |
797 | findSetMatch( UScriptCode *scriptCodes, int32_t scriptsLen, | |
374ca955 A |
798 | USet *exemplarSet, |
799 | const char *locale){ | |
800 | USet *scripts[10]= {0}; | |
801 | char pattern[256] = { '[', ':', 0x000 }; | |
802 | int32_t patternLen; | |
803 | UChar uPattern[256] = {0}; | |
804 | UErrorCode status = U_ZERO_ERROR; | |
805 | int32_t i; | |
806 | ||
807 | /* create the sets with script codes */ | |
808 | for(i = 0; i<scriptsLen; i++){ | |
809 | strcat(pattern, uscript_getShortName(scriptCodes[i])); | |
810 | strcat(pattern, ":]"); | |
811 | patternLen = (int32_t)strlen(pattern); | |
812 | u_charsToUChars(pattern, uPattern, patternLen); | |
813 | scripts[i] = uset_openPattern(uPattern, patternLen, &status); | |
814 | if(U_FAILURE(status)){ | |
46f4442e A |
815 | log_err("Could not create set for pattern %s. Error: %s\n", pattern, u_errorName(status)); |
816 | return; | |
374ca955 | 817 | } |
729e4ab9 | 818 | pattern[2] = 0; |
374ca955 A |
819 | } |
820 | if (strcmp(locale, "uk") == 0 || strcmp(locale, "uk_UA") == 0) { | |
821 | /* Special addition. Add the modifying apostrophe, which isn't in Cyrillic. */ | |
822 | uset_add(scripts[0], 0x2bc); | |
823 | } | |
824 | if(U_SUCCESS(status)){ | |
825 | UBool existsInScript = FALSE; | |
826 | /* iterate over the exemplarSet and ascertain if all | |
827 | * UChars in exemplarSet belong to the scripts returned | |
828 | * by getScript | |
829 | */ | |
830 | int32_t count = uset_getItemCount(exemplarSet); | |
831 | ||
832 | for( i=0; i < count; i++){ | |
833 | UChar32 start = 0; | |
834 | UChar32 end = 0; | |
835 | UChar *str = NULL; | |
836 | int32_t strCapacity = 0; | |
729e4ab9 | 837 | |
374ca955 A |
838 | strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); |
839 | if(U_SUCCESS(status)){ | |
840 | int32_t j; | |
841 | if(strCapacity == 0){ | |
842 | /* ok the item is a range */ | |
843 | for( j = 0; j < scriptsLen; j++){ | |
844 | if(uset_containsRange(scripts[j], start, end) == TRUE){ | |
845 | existsInScript = TRUE; | |
846 | } | |
847 | } | |
848 | if(existsInScript == FALSE){ | |
73c04bcf A |
849 | for( j = 0; j < scriptsLen; j++){ |
850 | UChar toPattern[500]={'\0'}; | |
851 | char pat[500]={'\0'}; | |
852 | int32_t len = uset_toPattern(scripts[j], toPattern, 500, TRUE, &status); | |
853 | len = myUCharsToChars(toPattern, pat, len); | |
854 | 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)); | |
855 | if(len!=-1){ | |
856 | log_err("Pattern: %s\n",pat); | |
857 | } | |
858 | } | |
374ca955 A |
859 | log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); |
860 | } | |
861 | }else{ | |
862 | strCapacity++; /* increment for NUL termination */ | |
863 | /* allocate the str and call the api again */ | |
864 | str = (UChar*) malloc(U_SIZEOF_UCHAR * strCapacity); | |
865 | strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); | |
866 | /* iterate over the scripts and figure out if the string contained is actually | |
867 | * in the script set | |
868 | */ | |
869 | for( j = 0; j < scriptsLen; j++){ | |
870 | if(uset_containsString(scripts[j],str, strCapacity) == TRUE){ | |
871 | existsInScript = TRUE; | |
872 | } | |
873 | } | |
874 | if(existsInScript == FALSE){ | |
875 | log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); | |
876 | } | |
877 | } | |
878 | } | |
879 | } | |
880 | ||
881 | } | |
882 | ||
883 | /* close the sets */ | |
884 | for(i = 0; i<scriptsLen; i++){ | |
885 | uset_close(scripts[i]); | |
886 | } | |
887 | } | |
888 | ||
889 | static void VerifyTranslation(void) { | |
890 | UResourceBundle *root, *currentLocale; | |
891 | int32_t locCount = uloc_countAvailable(); | |
892 | int32_t locIndex; | |
893 | UErrorCode errorCode = U_ZERO_ERROR; | |
374ca955 A |
894 | const char *currLoc; |
895 | UScriptCode scripts[USCRIPT_CODE_LIMIT]; | |
896 | int32_t numScripts; | |
897 | int32_t idx; | |
898 | int32_t end; | |
899 | UResourceBundle *resArray; | |
900 | ||
901 | if (locCount <= 1) { | |
902 | log_data_err("At least root needs to be installed\n"); | |
903 | } | |
904 | ||
905 | root = ures_openDirect(NULL, "root", &errorCode); | |
906 | if(U_FAILURE(errorCode)) { | |
907 | log_data_err("Can't open root\n"); | |
908 | return; | |
909 | } | |
910 | for (locIndex = 0; locIndex < locCount; locIndex++) { | |
57a6839d | 911 | USet * mergedExemplarSet = NULL; |
374ca955 A |
912 | errorCode=U_ZERO_ERROR; |
913 | currLoc = uloc_getAvailable(locIndex); | |
914 | currentLocale = ures_open(NULL, currLoc, &errorCode); | |
915 | if(errorCode != U_ZERO_ERROR) { | |
916 | if(U_SUCCESS(errorCode)) { | |
917 | /* It's installed, but there is no data. | |
918 | It's installed for the g18n white paper [grhoten] */ | |
919 | log_err("ERROR: Locale %-5s not installed, and it should be!\n", | |
920 | uloc_getAvailable(locIndex)); | |
921 | } else { | |
922 | log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", | |
923 | u_errorName(errorCode), | |
924 | uloc_getAvailable(locIndex)); | |
925 | } | |
926 | ures_close(currentLocale); | |
927 | continue; | |
928 | } | |
57a6839d A |
929 | { |
930 | UErrorCode exemplarStatus = U_ZERO_ERROR; | |
931 | ULocaleData * uld = ulocdata_open(currLoc, &exemplarStatus); | |
932 | if (U_SUCCESS(exemplarStatus)) { | |
933 | USet * exemplarSet = ulocdata_getExemplarSet(uld, NULL, USET_ADD_CASE_MAPPINGS, ULOCDATA_ES_STANDARD, &exemplarStatus); | |
934 | if (U_SUCCESS(exemplarStatus)) { | |
935 | mergedExemplarSet = uset_cloneAsThawed(exemplarSet); | |
936 | uset_close(exemplarSet); | |
937 | exemplarSet = ulocdata_getExemplarSet(uld, NULL, USET_ADD_CASE_MAPPINGS, ULOCDATA_ES_AUXILIARY, &exemplarStatus); | |
938 | if (U_SUCCESS(exemplarStatus)) { | |
939 | uset_addAll(mergedExemplarSet, exemplarSet); | |
940 | uset_close(exemplarSet); | |
941 | } | |
942 | exemplarStatus = U_ZERO_ERROR; | |
943 | exemplarSet = ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_PUNCTUATION, &exemplarStatus); | |
944 | if (U_SUCCESS(exemplarStatus)) { | |
945 | uset_addAll(mergedExemplarSet, exemplarSet); | |
946 | uset_close(exemplarSet); | |
947 | } | |
948 | } else { | |
949 | log_err("error ulocdata_getExemplarSet (main) for locale %s returned %s\n", currLoc, u_errorName(errorCode)); | |
950 | } | |
951 | ulocdata_close(uld); | |
952 | } else { | |
953 | log_err("error ulocdata_open for locale %s returned %s\n", currLoc, u_errorName(errorCode)); | |
954 | } | |
374ca955 | 955 | } |
57a6839d | 956 | if (mergedExemplarSet == NULL /*|| (getTestOption(QUICK_OPTION) && uset_size() > 2048)*/) { |
374ca955 A |
957 | log_verbose("skipping test for %s\n", currLoc); |
958 | } | |
57a6839d A |
959 | //else if (uprv_strncmp(currLoc,"bem",3) == 0 || uprv_strncmp(currLoc,"mgo",3) == 0 || uprv_strncmp(currLoc,"nl",2) == 0) { |
960 | // log_verbose("skipping test for %s, some month and country names known to use aux exemplars\n", currLoc); | |
961 | //} | |
374ca955 A |
962 | else { |
963 | UChar langBuffer[128]; | |
964 | int32_t langSize; | |
965 | int32_t strIdx; | |
0f5d89e8 | 966 | UChar32 badChar; |
2ca993e8 | 967 | langSize = uloc_getDisplayLanguage(currLoc, currLoc, langBuffer, UPRV_LENGTHOF(langBuffer), &errorCode); |
374ca955 A |
968 | if (U_FAILURE(errorCode)) { |
969 | log_err("error uloc_getDisplayLanguage returned %s\n", u_errorName(errorCode)); | |
3d1f044b A |
970 | } else if (uprv_strncmp(currLoc,"gez",3) == 0 || uprv_strcmp(currLoc,"sa") == 0 || uprv_strncmp(currLoc,"sa_",3) == 0) { // Apple xtra locales |
971 | log_verbose("skipping DisplayLanguage test for %s, name or exemplars may need adjustment\n", currLoc); | |
972 | } else { | |
57a6839d | 973 | strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, mergedExemplarSet, FALSE, &badChar); |
374ca955 | 974 | if (strIdx >= 0) { |
2ca993e8 A |
975 | char bbuf[256]; |
976 | log_err("getDisplayLanguage(%s) at index %d returned characters not in the exemplar characters: %04X in \"%s\"\n", | |
977 | currLoc, strIdx, badChar, u_austrncpy(bbuf,langBuffer,langSize)); | |
374ca955 A |
978 | } |
979 | } | |
2ca993e8 | 980 | langSize = uloc_getDisplayCountry(currLoc, currLoc, langBuffer, UPRV_LENGTHOF(langBuffer), &errorCode); |
374ca955 A |
981 | if (U_FAILURE(errorCode)) { |
982 | log_err("error uloc_getDisplayCountry returned %s\n", u_errorName(errorCode)); | |
983 | } | |
3d1f044b A |
984 | if ( uprv_strcmp(currLoc,"ba") == 0 || uprv_strncmp(currLoc,"ba_",3) == 0 || |
985 | uprv_strcmp(currLoc,"cv") == 0 || uprv_strncmp(currLoc,"cv_",3) == 0 || | |
986 | uprv_strcmp(currLoc,"dv") == 0 || uprv_strncmp(currLoc,"dv_",3) == 0 || | |
987 | uprv_strcmp(currLoc,"sa") == 0 || uprv_strncmp(currLoc,"sa_",3) == 0 || | |
988 | uprv_strncmp(currLoc,"kaj",3) == 0 || uprv_strncmp(currLoc,"kpe",3) == 0 || | |
c5116b9f A |
989 | uprv_strncmp(currLoc,"nqo",3) == 0 || uprv_strncmp(currLoc,"sat",3) == 0 || |
990 | uprv_strncmp(currLoc,"syr",3) == 0 || | |
991 | uprv_strcmp(currLoc,"ks_Deva") == 0 || uprv_strncmp(currLoc,"mni_Mtei",8) == 0 || | |
992 | uprv_strcmp(currLoc,"sd_Deva") == 0 ) { // Apple xtra locales | |
3d1f044b A |
993 | log_verbose("skipping day/month tests for %s, missing some translated names\n", currLoc); |
994 | } else { | |
374ca955 A |
995 | UResourceBundle* cal = ures_getByKey(currentLocale, "calendar", NULL, &errorCode); |
996 | UResourceBundle* greg = ures_getByKeyWithFallback(cal, "gregorian", NULL, &errorCode); | |
997 | UResourceBundle* names = ures_getByKeyWithFallback(greg, "dayNames", NULL, &errorCode); | |
998 | UResourceBundle* format = ures_getByKeyWithFallback(names, "format", NULL, &errorCode); | |
999 | resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); | |
1000 | ||
1001 | if (U_FAILURE(errorCode)) { | |
1002 | log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); | |
1003 | } | |
729e4ab9 | 1004 | if (getTestOption(QUICK_OPTION)) { |
374ca955 A |
1005 | end = 1; |
1006 | } | |
1007 | else { | |
1008 | end = ures_getSize(resArray); | |
1009 | } | |
1010 | ||
2ca993e8 A |
1011 | if ((uprv_strncmp(currLoc,"lrc",3) == 0 || uprv_strncmp(currLoc,"mzn",3) == 0) && |
1012 | log_knownIssue("cldrbug:8899", "lrc and mzn locales don't have translated day names")) { | |
1013 | end = 0; | |
1014 | } | |
374ca955 A |
1015 | |
1016 | for (idx = 0; idx < end; idx++) { | |
1017 | const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); | |
1018 | if (U_FAILURE(errorCode)) { | |
1019 | log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); | |
1020 | continue; | |
1021 | } | |
57a6839d | 1022 | strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, mergedExemplarSet, TRUE, &badChar); |
2ca993e8 | 1023 | if ( strIdx >= 0 ) { |
57a6839d A |
1024 | log_err("getDayNames(%s, %d) at index %d returned characters not in the exemplar characters: %04X.\n", |
1025 | currLoc, idx, strIdx, badChar); | |
374ca955 A |
1026 | } |
1027 | } | |
1028 | ures_close(resArray); | |
1029 | ures_close(format); | |
1030 | ures_close(names); | |
1031 | ||
1032 | names = ures_getByKeyWithFallback(greg, "monthNames", NULL, &errorCode); | |
1033 | format = ures_getByKeyWithFallback(names,"format", NULL, &errorCode); | |
1034 | resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); | |
1035 | if (U_FAILURE(errorCode)) { | |
1036 | log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); | |
1037 | } | |
729e4ab9 | 1038 | if (getTestOption(QUICK_OPTION)) { |
374ca955 A |
1039 | end = 1; |
1040 | } | |
1041 | else { | |
1042 | end = ures_getSize(resArray); | |
1043 | } | |
1044 | ||
1045 | for (idx = 0; idx < end; idx++) { | |
1046 | const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); | |
1047 | if (U_FAILURE(errorCode)) { | |
1048 | log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); | |
1049 | continue; | |
1050 | } | |
57a6839d A |
1051 | strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, mergedExemplarSet, TRUE, &badChar); |
1052 | if (strIdx >= 0) { | |
1053 | log_err("getMonthNames(%s, %d) at index %d returned characters not in the exemplar characters: %04X.\n", | |
1054 | currLoc, idx, strIdx, badChar); | |
374ca955 A |
1055 | } |
1056 | } | |
1057 | ures_close(resArray); | |
1058 | ures_close(format); | |
1059 | ures_close(names); | |
1060 | ures_close(greg); | |
1061 | ures_close(cal); | |
1062 | } | |
1063 | errorCode = U_ZERO_ERROR; | |
2ca993e8 | 1064 | numScripts = uscript_getCode(currLoc, scripts, UPRV_LENGTHOF(scripts), &errorCode); |
b331163b A |
1065 | if (strcmp(currLoc, "yi") == 0 && numScripts > 0 && log_knownIssue("11217", "Fix result of uscript_getCode for yi: USCRIPT_YI -> USCRIPT_HEBREW")) { |
1066 | scripts[0] = USCRIPT_HEBREW; | |
1067 | } | |
374ca955 A |
1068 | if (numScripts == 0) { |
1069 | log_err("uscript_getCode(%s) doesn't work.\n", currLoc); | |
1070 | }else if(scripts[0] == USCRIPT_COMMON){ | |
729e4ab9 | 1071 | log_err("uscript_getCode(%s) returned USCRIPT_COMMON.\n", currLoc); |
374ca955 A |
1072 | } |
1073 | ||
1074 | /* test that the scripts are a superset of exemplar characters. */ | |
1075 | { | |
73c04bcf A |
1076 | ULocaleData *uld = ulocdata_open(currLoc,&errorCode); |
1077 | USet *exemplarSet = ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &errorCode); | |
374ca955 A |
1078 | /* test if exemplar characters are part of script code */ |
1079 | findSetMatch(scripts, numScripts, exemplarSet, currLoc); | |
1080 | uset_close(exemplarSet); | |
73c04bcf | 1081 | ulocdata_close(uld); |
374ca955 A |
1082 | } |
1083 | ||
1084 | /* test that the paperSize API works */ | |
1085 | { | |
1086 | int32_t height=0, width=0; | |
1087 | ulocdata_getPaperSize(currLoc, &height, &width, &errorCode); | |
1088 | if(U_FAILURE(errorCode)){ | |
1089 | log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); | |
1090 | } | |
1091 | if(strstr(currLoc, "_US")!=NULL && height != 279 && width != 216 ){ | |
1092 | log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); | |
1093 | } | |
1094 | } | |
57a6839d | 1095 | /* test that the MeasurementSystem API works */ |
374ca955 | 1096 | { |
51004dcb | 1097 | char fullLoc[ULOC_FULLNAME_CAPACITY]; |
57a6839d A |
1098 | UMeasurementSystem measurementSystem; |
1099 | int32_t height = 0, width = 0; | |
1100 | ||
1101 | uloc_addLikelySubtags(currLoc, fullLoc, ULOC_FULLNAME_CAPACITY, &errorCode); | |
1102 | ||
1103 | errorCode = U_ZERO_ERROR; | |
1104 | measurementSystem = ulocdata_getMeasurementSystem(currLoc, &errorCode); | |
1105 | if (U_FAILURE(errorCode)) { | |
374ca955 | 1106 | log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); |
57a6839d A |
1107 | } else { |
1108 | if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_MM")!=NULL || strstr(fullLoc, "_LR")!=NULL ) { | |
1109 | if(measurementSystem != UMS_US){ | |
1110 | log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); | |
1111 | } | |
b331163b A |
1112 | } else if ( strstr(fullLoc, "_GB")!=NULL ) { |
1113 | if(measurementSystem != UMS_UK){ | |
1114 | log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); | |
1115 | } | |
57a6839d A |
1116 | } else if (measurementSystem != UMS_SI) { |
1117 | log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); | |
1118 | } | |
374ca955 | 1119 | } |
57a6839d A |
1120 | |
1121 | errorCode = U_ZERO_ERROR; | |
1122 | ulocdata_getPaperSize(currLoc, &height, &width, &errorCode); | |
1123 | if (U_FAILURE(errorCode)) { | |
1124 | log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); | |
1125 | } else { | |
1126 | if ( strstr(fullLoc, "_US")!=NULL || strstr(fullLoc, "_BZ")!=NULL || strstr(fullLoc, "_CA")!=NULL || strstr(fullLoc, "_CL")!=NULL || | |
1127 | strstr(fullLoc, "_CO")!=NULL || strstr(fullLoc, "_CR")!=NULL || strstr(fullLoc, "_GT")!=NULL || strstr(fullLoc, "_MX")!=NULL || | |
1128 | strstr(fullLoc, "_NI")!=NULL || strstr(fullLoc, "_PA")!=NULL || strstr(fullLoc, "_PH")!=NULL || strstr(fullLoc, "_PR")!=NULL || | |
1129 | strstr(fullLoc, "_SV")!=NULL || strstr(fullLoc, "_VE")!=NULL ) { | |
1130 | if (height != 279 || width != 216) { | |
1131 | log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); | |
1132 | } | |
1133 | } else if (height != 297 || width != 210) { | |
1134 | log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); | |
374ca955 | 1135 | } |
374ca955 A |
1136 | } |
1137 | } | |
1138 | } | |
57a6839d A |
1139 | if (mergedExemplarSet != NULL) { |
1140 | uset_close(mergedExemplarSet); | |
1141 | } | |
374ca955 A |
1142 | ures_close(currentLocale); |
1143 | } | |
1144 | ||
1145 | ures_close(root); | |
1146 | } | |
1147 | ||
1148 | /* adjust this limit as appropriate */ | |
1149 | #define MAX_SCRIPTS_PER_LOCALE 8 | |
1150 | ||
1151 | static void TestExemplarSet(void){ | |
1152 | int32_t i, j, k, m, n; | |
1153 | int32_t equalCount = 0; | |
1154 | UErrorCode ec = U_ZERO_ERROR; | |
1155 | UEnumeration* avail; | |
1156 | USet* exemplarSets[2]; | |
73c04bcf | 1157 | USet* unassignedSet; |
374ca955 A |
1158 | UScriptCode code[MAX_SCRIPTS_PER_LOCALE]; |
1159 | USet* codeSets[MAX_SCRIPTS_PER_LOCALE]; | |
1160 | int32_t codeLen; | |
1161 | char cbuf[32]; /* 9 should be enough */ | |
1162 | UChar ubuf[64]; /* adjust as needed */ | |
1163 | UBool existsInScript; | |
1164 | int32_t itemCount; | |
1165 | int32_t strLen; | |
1166 | UChar32 start, end; | |
729e4ab9 | 1167 | |
73c04bcf A |
1168 | unassignedSet = NULL; |
1169 | exemplarSets[0] = NULL; | |
1170 | exemplarSets[1] = NULL; | |
374ca955 A |
1171 | for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { |
1172 | codeSets[i] = NULL; | |
1173 | } | |
1174 | ||
1175 | avail = ures_openAvailableLocales(NULL, &ec); | |
1176 | if (!assertSuccess("ures_openAvailableLocales", &ec)) goto END; | |
1177 | n = uenum_count(avail, &ec); | |
1178 | if (!assertSuccess("uenum_count", &ec)) goto END; | |
1179 | ||
73c04bcf A |
1180 | u_uastrcpy(ubuf, "[:unassigned:]"); |
1181 | unassignedSet = uset_openPattern(ubuf, -1, &ec); | |
1182 | if (!assertSuccess("uset_openPattern", &ec)) goto END; | |
1183 | ||
374ca955 A |
1184 | for(i=0; i<n; i++){ |
1185 | const char* locale = uenum_next(avail, NULL, &ec); | |
1186 | if (!assertSuccess("uenum_next", &ec)) goto END; | |
1187 | log_verbose("%s\n", locale); | |
1188 | for (k=0; k<2; ++k) { | |
1189 | uint32_t option = (k==0) ? 0 : USET_CASE_INSENSITIVE; | |
729e4ab9 | 1190 | ULocaleData *uld = ulocdata_open(locale,&ec); |
73c04bcf | 1191 | USet* exemplarSet = ulocdata_getExemplarSet(uld,NULL, option, ULOCDATA_ES_STANDARD, &ec); |
374ca955 | 1192 | uset_close(exemplarSets[k]); |
73c04bcf | 1193 | ulocdata_close(uld); |
374ca955 A |
1194 | exemplarSets[k] = exemplarSet; |
1195 | if (!assertSuccess("ulocaledata_getExemplarSet", &ec)) goto END; | |
1196 | ||
73c04bcf A |
1197 | if (uset_containsSome(exemplarSet, unassignedSet)) { |
1198 | log_err("ExemplarSet contains unassigned characters for locale : %s\n", locale); | |
1199 | } | |
374ca955 | 1200 | codeLen = uscript_getCode(locale, code, 8, &ec); |
b331163b A |
1201 | if (strcmp(locale, "yi") == 0 && codeLen > 0 && log_knownIssue("11217", "Fix result of uscript_getCode for yi: USCRIPT_YI -> USCRIPT_HEBREW")) { |
1202 | code[0] = USCRIPT_HEBREW; | |
1203 | } | |
374ca955 A |
1204 | if (!assertSuccess("uscript_getCode", &ec)) goto END; |
1205 | ||
1206 | for (j=0; j<MAX_SCRIPTS_PER_LOCALE; ++j) { | |
1207 | uset_close(codeSets[j]); | |
1208 | codeSets[j] = NULL; | |
1209 | } | |
1210 | for (j=0; j<codeLen; ++j) { | |
1211 | uprv_strcpy(cbuf, "[:"); | |
73c04bcf A |
1212 | if(code[j]==-1){ |
1213 | log_err("USCRIPT_INVALID_CODE returned for locale: %s\n", locale); | |
1214 | continue; | |
1215 | } | |
374ca955 A |
1216 | uprv_strcat(cbuf, uscript_getShortName(code[j])); |
1217 | uprv_strcat(cbuf, ":]"); | |
1218 | u_uastrcpy(ubuf, cbuf); | |
1219 | codeSets[j] = uset_openPattern(ubuf, -1, &ec); | |
1220 | } | |
1221 | if (!assertSuccess("uset_openPattern", &ec)) goto END; | |
1222 | ||
1223 | existsInScript = FALSE; | |
1224 | itemCount = uset_getItemCount(exemplarSet); | |
1225 | for (m=0; m<itemCount && !existsInScript; ++m) { | |
1226 | strLen = uset_getItem(exemplarSet, m, &start, &end, ubuf, | |
2ca993e8 | 1227 | UPRV_LENGTHOF(ubuf), &ec); |
374ca955 A |
1228 | /* failure here might mean str[] needs to be larger */ |
1229 | if (!assertSuccess("uset_getItem", &ec)) goto END; | |
1230 | if (strLen == 0) { | |
1231 | for (j=0; j<codeLen; ++j) { | |
73c04bcf | 1232 | if (codeSets[j]!=NULL && uset_containsRange(codeSets[j], start, end)) { |
374ca955 A |
1233 | existsInScript = TRUE; |
1234 | break; | |
1235 | } | |
1236 | } | |
1237 | } else { | |
1238 | for (j=0; j<codeLen; ++j) { | |
73c04bcf | 1239 | if (codeSets[j]!=NULL && uset_containsString(codeSets[j], ubuf, strLen)) { |
374ca955 A |
1240 | existsInScript = TRUE; |
1241 | break; | |
1242 | } | |
1243 | } | |
1244 | } | |
1245 | } | |
1246 | ||
1247 | if (existsInScript == FALSE){ | |
73c04bcf | 1248 | log_err("ExemplarSet containment failed for locale : %s\n", locale); |
374ca955 A |
1249 | } |
1250 | } | |
1251 | assertTrue("case-folded is a superset", | |
1252 | uset_containsAll(exemplarSets[1], exemplarSets[0])); | |
1253 | if (uset_equals(exemplarSets[1], exemplarSets[0])) { | |
1254 | ++equalCount; | |
1255 | } | |
1256 | } | |
1257 | /* Note: The case-folded set should sometimes be a strict superset | |
1258 | and sometimes be equal. */ | |
1259 | assertTrue("case-folded is sometimes a strict superset, and sometimes equal", | |
1260 | equalCount > 0 && equalCount < n); | |
729e4ab9 | 1261 | |
374ca955 A |
1262 | END: |
1263 | uenum_close(avail); | |
1264 | uset_close(exemplarSets[0]); | |
1265 | uset_close(exemplarSets[1]); | |
73c04bcf | 1266 | uset_close(unassignedSet); |
374ca955 A |
1267 | for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { |
1268 | uset_close(codeSets[i]); | |
1269 | } | |
1270 | } | |
1271 | ||
57a6839d | 1272 | enum { kUBufMax = 32 }; |
729e4ab9 | 1273 | static void TestLocaleDisplayPattern(void){ |
57a6839d A |
1274 | UErrorCode status; |
1275 | UChar pattern[kUBufMax] = {0,}; | |
1276 | UChar separator[kUBufMax] = {0,}; | |
1277 | ULocaleData *uld; | |
1278 | static const UChar enExpectPat[] = { 0x007B,0x0030,0x007D,0x0020,0x0028,0x007B,0x0031,0x007D,0x0029,0 }; /* "{0} ({1})" */ | |
1279 | static const UChar enExpectSep[] = { 0x002C,0x0020,0 }; /* ", " */ | |
1280 | static const UChar zhExpectPat[] = { 0x007B,0x0030,0x007D,0xFF08,0x007B,0x0031,0x007D,0xFF09,0 }; | |
f3c0d7a5 | 1281 | static const UChar zhExpectSep[] = { 0xFF0C,0 }; |
729e4ab9 | 1282 | |
57a6839d A |
1283 | status = U_ZERO_ERROR; |
1284 | uld = ulocdata_open("en", &status); | |
729e4ab9 | 1285 | if(U_FAILURE(status)){ |
57a6839d A |
1286 | log_data_err("ulocdata_open en error %s", u_errorName(status)); |
1287 | } else { | |
1288 | ulocdata_getLocaleDisplayPattern(uld, pattern, kUBufMax, &status); | |
1289 | if (U_FAILURE(status)){ | |
1290 | log_err("ulocdata_getLocaleDisplayPattern en error %s", u_errorName(status)); | |
1291 | } else if (u_strcmp(pattern, enExpectPat) != 0) { | |
1292 | log_err("ulocdata_getLocaleDisplayPattern en returns unexpected pattern"); | |
1293 | } | |
1294 | status = U_ZERO_ERROR; | |
1295 | ulocdata_getLocaleSeparator(uld, separator, kUBufMax, &status); | |
1296 | if (U_FAILURE(status)){ | |
1297 | log_err("ulocdata_getLocaleSeparator en error %s", u_errorName(status)); | |
1298 | } else if (u_strcmp(separator, enExpectSep) != 0) { | |
1299 | log_err("ulocdata_getLocaleSeparator en returns unexpected string "); | |
1300 | } | |
1301 | ulocdata_close(uld); | |
729e4ab9 | 1302 | } |
57a6839d | 1303 | |
729e4ab9 | 1304 | status = U_ZERO_ERROR; |
57a6839d A |
1305 | uld = ulocdata_open("zh", &status); |
1306 | if(U_FAILURE(status)){ | |
1307 | log_data_err("ulocdata_open zh error %s", u_errorName(status)); | |
1308 | } else { | |
1309 | ulocdata_getLocaleDisplayPattern(uld, pattern, kUBufMax, &status); | |
1310 | if (U_FAILURE(status)){ | |
1311 | log_err("ulocdata_getLocaleDisplayPattern zh error %s", u_errorName(status)); | |
1312 | } else if (u_strcmp(pattern, zhExpectPat) != 0) { | |
1313 | log_err("ulocdata_getLocaleDisplayPattern zh returns unexpected pattern"); | |
1314 | } | |
1315 | status = U_ZERO_ERROR; | |
1316 | ulocdata_getLocaleSeparator(uld, separator, kUBufMax, &status); | |
1317 | if (U_FAILURE(status)){ | |
1318 | log_err("ulocdata_getLocaleSeparator zh error %s", u_errorName(status)); | |
1319 | } else if (u_strcmp(separator, zhExpectSep) != 0) { | |
1320 | log_err("ulocdata_getLocaleSeparator zh returns unexpected string "); | |
1321 | } | |
1322 | ulocdata_close(uld); | |
729e4ab9 | 1323 | } |
729e4ab9 A |
1324 | } |
1325 | ||
73c04bcf A |
1326 | static void TestCoverage(void){ |
1327 | ULocaleDataDelimiterType types[] = { | |
1328 | ULOCDATA_QUOTATION_START, /* Quotation start */ | |
1329 | ULOCDATA_QUOTATION_END, /* Quotation end */ | |
1330 | ULOCDATA_ALT_QUOTATION_START, /* Alternate quotation start */ | |
1331 | ULOCDATA_ALT_QUOTATION_END, /* Alternate quotation end */ | |
1332 | ULOCDATA_DELIMITER_COUNT | |
1333 | }; | |
1334 | int i; | |
1335 | UBool sub; | |
1336 | UErrorCode status = U_ZERO_ERROR; | |
1337 | ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status); | |
1338 | ||
1339 | if(U_FAILURE(status)){ | |
729e4ab9 | 1340 | log_data_err("ulocdata_open error"); |
73c04bcf A |
1341 | return; |
1342 | } | |
1343 | ||
1344 | ||
1345 | for(i = 0; i < ULOCDATA_DELIMITER_COUNT; i++){ | |
1346 | UChar result[32] = {0,}; | |
1347 | status = U_ZERO_ERROR; | |
1348 | ulocdata_getDelimiter(uld, types[i], result, 32, &status); | |
1349 | if (U_FAILURE(status)){ | |
1350 | log_err("ulocdata_getgetDelimiter error with type %d", types[i]); | |
1351 | } | |
1352 | } | |
1353 | ||
1354 | sub = ulocdata_getNoSubstitute(uld); | |
1355 | ulocdata_setNoSubstitute(uld,sub); | |
1356 | ulocdata_close(uld); | |
1357 | } | |
1358 | ||
4388f060 A |
1359 | static void TestIndexChars(void) { |
1360 | /* Very basic test of ULOCDATA_ES_INDEX. | |
1361 | * No comprehensive test of data, just basic check that the code path is alive. | |
1362 | */ | |
1363 | UErrorCode status = U_ZERO_ERROR; | |
1364 | ULocaleData *uld; | |
1365 | USet *exemplarChars; | |
1366 | USet *indexChars; | |
1367 | ||
1368 | uld = ulocdata_open("en", &status); | |
1369 | exemplarChars = uset_openEmpty(); | |
1370 | indexChars = uset_openEmpty(); | |
1371 | ulocdata_getExemplarSet(uld, exemplarChars, 0, ULOCDATA_ES_STANDARD, &status); | |
1372 | ulocdata_getExemplarSet(uld, indexChars, 0, ULOCDATA_ES_INDEX, &status); | |
1373 | if (U_FAILURE(status)) { | |
1374 | log_data_err("File %s, line %d, Failure opening exemplar chars: %s", __FILE__, __LINE__, u_errorName(status)); | |
1375 | goto close_sets; | |
1376 | } | |
1377 | /* en data, standard exemplars are [a-z], lower case. */ | |
1378 | /* en data, index characters are [A-Z], upper case. */ | |
1379 | if ((uset_contains(exemplarChars, (UChar32)0x41) || uset_contains(indexChars, (UChar32)0x61))) { | |
1380 | log_err("File %s, line %d, Exemplar characters incorrect.", __FILE__, __LINE__ ); | |
1381 | goto close_sets; | |
1382 | } | |
1383 | if (!(uset_contains(exemplarChars, (UChar32)0x61) && uset_contains(indexChars, (UChar32)0x41) )) { | |
1384 | log_err("File %s, line %d, Exemplar characters incorrect.", __FILE__, __LINE__ ); | |
1385 | goto close_sets; | |
1386 | } | |
1387 | ||
1388 | close_sets: | |
1389 | uset_close(exemplarChars); | |
1390 | uset_close(indexChars); | |
1391 | ulocdata_close(uld); | |
1392 | } | |
1393 | ||
1394 | ||
1395 | ||
51004dcb | 1396 | #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
73c04bcf A |
1397 | static void TestCurrencyList(void){ |
1398 | #if !UCONFIG_NO_FORMATTING | |
1399 | UErrorCode errorCode = U_ZERO_ERROR; | |
1400 | int32_t structLocaleCount, currencyCount; | |
1401 | UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &errorCode); | |
1402 | const char *isoCode, *structISOCode; | |
1403 | UResourceBundle *subBundle; | |
1404 | UResourceBundle *currencies = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); | |
1405 | if(U_FAILURE(errorCode)) { | |
1406 | log_data_err("Can't open structLocale\n"); | |
1407 | return; | |
1408 | } | |
1409 | currencies = ures_getByKey(currencies, "Currencies", currencies, &errorCode); | |
1410 | currencyCount = uenum_count(en, &errorCode); | |
1411 | structLocaleCount = ures_getSize(currencies); | |
1412 | if (currencyCount != structLocaleCount) { | |
1413 | log_err("structLocale(%d) and ISO4217(%d) currency list are out of sync.\n", structLocaleCount, currencyCount); | |
1414 | #if U_CHARSET_FAMILY == U_ASCII_FAMILY | |
1415 | ures_resetIterator(currencies); | |
1416 | while ((isoCode = uenum_next(en, NULL, &errorCode)) != NULL && ures_hasNext(currencies)) { | |
1417 | subBundle = ures_getNextResource(currencies, NULL, &errorCode); | |
1418 | structISOCode = ures_getKey(subBundle); | |
1419 | ures_close(subBundle); | |
1420 | if (strcmp(structISOCode, isoCode) != 0) { | |
1421 | log_err("First difference found at structLocale(%s) and ISO4217(%s).\n", structISOCode, isoCode); | |
1422 | break; | |
1423 | } | |
1424 | } | |
1425 | #endif | |
1426 | } | |
1427 | ures_close(currencies); | |
1428 | uenum_close(en); | |
1429 | #endif | |
1430 | } | |
51004dcb | 1431 | #endif |
73c04bcf | 1432 | |
4388f060 A |
1433 | static void TestAvailableIsoCodes(void){ |
1434 | #if !UCONFIG_NO_FORMATTING | |
1435 | UErrorCode errorCode = U_ZERO_ERROR; | |
1436 | const char* eurCode = "EUR"; | |
1437 | const char* usdCode = "USD"; | |
1438 | const char* lastCode = "RHD"; | |
1439 | const char* zzzCode = "ZZZ"; | |
1440 | UDate date1950 = (UDate)-630720000000.0;/* year 1950 */ | |
1441 | UDate date1970 = (UDate)0.0; /* year 1970 */ | |
1442 | UDate date1975 = (UDate)173448000000.0; /* year 1975 */ | |
1443 | UDate date1978 = (UDate)260172000000.0; /* year 1978 */ | |
1444 | UDate date1981 = (UDate)346896000000.0; /* year 1981 */ | |
1445 | UDate date1992 = (UDate)693792000000.0; /* year 1992 */ | |
1446 | UChar* isoCode = (UChar*)malloc(sizeof(UChar) * (uprv_strlen(usdCode) + 1)); | |
1447 | ||
1448 | /* testing available codes with no time ranges */ | |
3d1f044b | 1449 | u_charsToUChars(eurCode, isoCode, (int32_t)uprv_strlen(usdCode) + 1); |
4388f060 A |
1450 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == FALSE) { |
1451 | log_data_err("FAIL: ISO code (%s) is not found.\n", eurCode); | |
1452 | } | |
1453 | ||
3d1f044b | 1454 | u_charsToUChars(usdCode, isoCode, (int32_t)uprv_strlen(zzzCode) + 1); |
4388f060 A |
1455 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == FALSE) { |
1456 | log_data_err("FAIL: ISO code (%s) is not found.\n", usdCode); | |
1457 | } | |
1458 | ||
3d1f044b | 1459 | u_charsToUChars(zzzCode, isoCode, (int32_t)uprv_strlen(zzzCode) + 1); |
4388f060 A |
1460 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == TRUE) { |
1461 | log_err("FAIL: ISO code (%s) is reported as available, but it doesn't exist.\n", zzzCode); | |
1462 | } | |
1463 | ||
3d1f044b | 1464 | u_charsToUChars(lastCode, isoCode, (int32_t)uprv_strlen(zzzCode) + 1); |
4388f060 A |
1465 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, U_DATE_MAX, &errorCode) == FALSE) { |
1466 | log_data_err("FAIL: ISO code (%s) is not found.\n", lastCode); | |
1467 | } | |
1468 | ||
1469 | /* RHD was used from 1970-02-17 to 1980-04-18*/ | |
1470 | ||
1471 | /* to = null */ | |
1472 | if (ucurr_isAvailable(isoCode, date1970, U_DATE_MAX, &errorCode) == FALSE) { | |
1473 | log_data_err("FAIL: ISO code (%s) was available in time range >1970-01-01.\n", lastCode); | |
1474 | } | |
1475 | ||
1476 | if (ucurr_isAvailable(isoCode, date1975, U_DATE_MAX, &errorCode) == FALSE) { | |
1477 | log_data_err("FAIL: ISO code (%s) was available in time range >1975.\n", lastCode); | |
1478 | } | |
1479 | ||
1480 | if (ucurr_isAvailable(isoCode, date1981, U_DATE_MAX, &errorCode) == TRUE) { | |
1481 | log_err("FAIL: ISO code (%s) was not available in time range >1981.\n", lastCode); | |
1482 | } | |
1483 | ||
1484 | /* from = null */ | |
1485 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, date1970, &errorCode) == TRUE) { | |
1486 | log_err("FAIL: ISO code (%s) was not available in time range <1970.\n", lastCode); | |
1487 | } | |
1488 | ||
1489 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, date1975, &errorCode) == FALSE) { | |
1490 | log_data_err("FAIL: ISO code (%s) was available in time range <1975.\n", lastCode); | |
1491 | } | |
1492 | ||
1493 | if (ucurr_isAvailable(isoCode, U_DATE_MIN, date1981, &errorCode) == FALSE) { | |
1494 | log_data_err("FAIL: ISO code (%s) was available in time range <1981.\n", lastCode); | |
1495 | } | |
1496 | ||
1497 | /* full ranges */ | |
1498 | if (ucurr_isAvailable(isoCode, date1975, date1978, &errorCode) == FALSE) { | |
1499 | log_data_err("FAIL: ISO code (%s) was available in time range 1975-1978.\n", lastCode); | |
1500 | } | |
1501 | ||
1502 | if (ucurr_isAvailable(isoCode, date1970, date1975, &errorCode) == FALSE) { | |
1503 | log_data_err("FAIL: ISO code (%s) was available in time range 1970-1975.\n", lastCode); | |
1504 | } | |
1505 | ||
1506 | if (ucurr_isAvailable(isoCode, date1975, date1981, &errorCode) == FALSE) { | |
1507 | log_data_err("FAIL: ISO code (%s) was available in time range 1975-1981.\n", lastCode); | |
1508 | } | |
1509 | ||
1510 | if (ucurr_isAvailable(isoCode, date1970, date1981, &errorCode) == FALSE) { | |
1511 | log_data_err("FAIL: ISO code (%s) was available in time range 1970-1981.\n", lastCode); | |
1512 | } | |
1513 | ||
1514 | if (ucurr_isAvailable(isoCode, date1981, date1992, &errorCode) == TRUE) { | |
1515 | log_err("FAIL: ISO code (%s) was not available in time range 1981-1992.\n", lastCode); | |
1516 | } | |
1517 | ||
1518 | if (ucurr_isAvailable(isoCode, date1950, date1970, &errorCode) == TRUE) { | |
1519 | log_err("FAIL: ISO code (%s) was not available in time range 1950-1970.\n", lastCode); | |
1520 | } | |
1521 | ||
1522 | /* wrong range - from > to*/ | |
1523 | if (ucurr_isAvailable(isoCode, date1975, date1970, &errorCode) == TRUE) { | |
1524 | log_err("FAIL: Wrong range 1975-1970 for ISO code (%s) was not reported.\n", lastCode); | |
1525 | } else if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) { | |
1526 | log_data_err("FAIL: Error code not reported for wrong range 1975-1970 for ISO code (%s).\n", lastCode); | |
1527 | } | |
1528 | ||
1529 | free(isoCode); | |
1530 | #endif | |
1531 | } | |
1532 | ||
0f5d89e8 A |
1533 | // Apple-specific |
1534 | typedef struct { | |
1535 | const char* locale; | |
1536 | const UChar* quoteStart; | |
1537 | const UChar* quoteEnd; | |
1538 | const UChar* altQuoteStart; | |
1539 | const UChar* altQuoteEnd; | |
1540 | } DelimItem; | |
1541 | static const DelimItem delimItems[] = { | |
1542 | { "en", u"“", u"”", u"‘", u"’"}, | |
1543 | { "es", u"«", u"»", u"“", u"”"}, | |
1544 | { "es_MX", u"“", u"”", u"‘", u"’"}, | |
1545 | { "ja", u"「", u"」", u"『", u"』"}, | |
1546 | { NULL,NULL,NULL,NULL,NULL } | |
1547 | }; | |
1548 | enum {kMaxDelimLen = 8}; | |
1549 | ||
1550 | static void TestDelimiters(void){ | |
1551 | const DelimItem* itemPtr; | |
1552 | for (itemPtr = delimItems; itemPtr->locale != NULL; itemPtr++) { | |
1553 | UErrorCode status = U_ZERO_ERROR; | |
1554 | ULocaleData* uldat = ulocdata_open(itemPtr->locale, &status); | |
1555 | if (U_FAILURE(status)) { | |
1556 | log_data_err("FAIL: ulocdata_open fails for locale %s: %s\n", itemPtr->locale, u_errorName(status)); | |
1557 | } else { | |
1558 | UChar quoteStart[kMaxDelimLen+1]; | |
1559 | UChar quoteEnd[kMaxDelimLen+1]; | |
1560 | UChar altQuoteStart[kMaxDelimLen+1]; | |
1561 | UChar altQuoteEnd[kMaxDelimLen+1]; | |
1562 | ||
1563 | ulocdata_getDelimiter(uldat, ULOCDATA_QUOTATION_START, quoteStart, kMaxDelimLen, &status); | |
1564 | quoteStart[kMaxDelimLen] = 0; | |
1565 | ulocdata_getDelimiter(uldat, ULOCDATA_QUOTATION_END, quoteEnd, kMaxDelimLen, &status); | |
1566 | quoteEnd[kMaxDelimLen] = 0; | |
1567 | ulocdata_getDelimiter(uldat, ULOCDATA_ALT_QUOTATION_START, altQuoteStart, kMaxDelimLen, &status); | |
1568 | altQuoteStart[kMaxDelimLen] = 0; | |
1569 | ulocdata_getDelimiter(uldat, ULOCDATA_ALT_QUOTATION_END, altQuoteEnd, kMaxDelimLen, &status); | |
1570 | altQuoteEnd[kMaxDelimLen] = 0; | |
1571 | if (U_FAILURE(status)) { | |
1572 | log_err("FAIL: ulocdata_getDelimiter fails for locale %s: %s\n", itemPtr->locale, u_errorName(status)); | |
1573 | } else if (u_strcmp(quoteStart, itemPtr->quoteStart) != 0 || u_strcmp(quoteEnd, itemPtr->quoteEnd) != 0 || | |
1574 | u_strcmp(altQuoteStart, itemPtr->altQuoteStart) != 0 || u_strcmp(altQuoteEnd, itemPtr->altQuoteEnd) != 0) { | |
1575 | log_err("FAIL: ulocdata_getDelimiter error for locale %s, one or more delimiters not as expected\n", itemPtr->locale); | |
1576 | } | |
1577 | ulocdata_close(uldat); | |
1578 | } | |
1579 | } | |
1580 | } | |
1581 | ||
1582 | ||
374ca955 A |
1583 | #define TESTCASE(name) addTest(root, &name, "tsutil/cldrtest/" #name) |
1584 | ||
1585 | void addCLDRTest(TestNode** root); | |
1586 | ||
1587 | void addCLDRTest(TestNode** root) | |
1588 | { | |
729e4ab9 | 1589 | #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION |
374ca955 | 1590 | TESTCASE(TestLocaleStructure); |
729e4ab9 A |
1591 | TESTCASE(TestCurrencyList); |
1592 | #endif | |
374ca955 A |
1593 | TESTCASE(TestConsistentCountryInfo); |
1594 | TESTCASE(VerifyTranslation); | |
1595 | TESTCASE(TestExemplarSet); | |
729e4ab9 | 1596 | TESTCASE(TestLocaleDisplayPattern); |
73c04bcf | 1597 | TESTCASE(TestCoverage); |
4388f060 A |
1598 | TESTCASE(TestIndexChars); |
1599 | TESTCASE(TestAvailableIsoCodes); | |
0f5d89e8 | 1600 | TESTCASE(TestDelimiters); |
374ca955 | 1601 | } |
4388f060 | 1602 |