]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
46f4442e A |
3 | /* |
4 | ******************************************************************************* | |
5 | * | |
2ca993e8 | 6 | * Copyright (C) 2007-2016, International Business Machines |
46f4442e A |
7 | * Corporation and others. All Rights Reserved. |
8 | * | |
9 | ******************************************************************************* | |
10 | * file name: udatpg_test.c | |
f3c0d7a5 | 11 | * encoding: UTF-8 |
46f4442e A |
12 | * tab size: 8 (not used) |
13 | * indentation:4 | |
14 | * | |
15 | * created on: 2007aug01 | |
16 | * created by: Markus W. Scherer | |
17 | * | |
18 | * Test of the C wrapper for the DateTimePatternGenerator. | |
19 | * Calls each C API function and exercises code paths in the wrapper, | |
20 | * but the full functionality is tested in the C++ intltest. | |
21 | * | |
22 | * One item to note: C API functions which return a const UChar * | |
23 | * should return a NUL-terminated string. | |
24 | * (The C++ implementation needs to use getTerminatedBuffer() | |
25 | * on UnicodeString objects which end up being returned this way.) | |
26 | */ | |
27 | ||
28 | #include "unicode/utypes.h" | |
29 | ||
30 | #if !UCONFIG_NO_FORMATTING | |
31 | #include "unicode/udat.h" | |
32 | #include "unicode/udatpg.h" | |
33 | #include "unicode/ustring.h" | |
34 | #include "cintltst.h" | |
2ca993e8 | 35 | #include "cmemory.h" |
46f4442e | 36 | |
340931cb A |
37 | #include <stdio.h> // for sprintf() |
38 | ||
46f4442e A |
39 | void addDateTimePatternGeneratorTest(TestNode** root); |
40 | ||
41 | #define TESTCASE(x) addTest(root, &x, "tsformat/udatpg_test/" #x) | |
42 | ||
43 | static void TestOpenClose(void); | |
44 | static void TestUsage(void); | |
45 | static void TestBuilder(void); | |
729e4ab9 | 46 | static void TestOptions(void); |
0f5d89e8 | 47 | static void TestGetFieldDisplayNames(void); |
3d1f044b | 48 | static void TestJapaneseCalendarItems(void); // rdar://52042600 |
340931cb A |
49 | static void TestCountryFallback(void); // rdar://problem/26911014 |
50 | static void TestEras(void); | |
46f4442e A |
51 | |
52 | void addDateTimePatternGeneratorTest(TestNode** root) { | |
53 | TESTCASE(TestOpenClose); | |
54 | TESTCASE(TestUsage); | |
55 | TESTCASE(TestBuilder); | |
729e4ab9 | 56 | TESTCASE(TestOptions); |
0f5d89e8 | 57 | TESTCASE(TestGetFieldDisplayNames); |
3d1f044b | 58 | TESTCASE(TestJapaneseCalendarItems); |
340931cb A |
59 | TESTCASE(TestCountryFallback); |
60 | TESTCASE(TestEras); | |
46f4442e A |
61 | } |
62 | ||
63 | /* | |
64 | * Pipe symbol '|'. We pass only the first UChar without NUL-termination. | |
65 | * The second UChar is just to verify that the API does not pick that up. | |
66 | */ | |
67 | static const UChar pipeString[]={ 0x7c, 0x0a }; | |
68 | ||
69 | static const UChar testSkeleton1[]={ 0x48, 0x48, 0x6d, 0x6d, 0 }; /* HHmm */ | |
729e4ab9 | 70 | static const UChar expectingBestPattern[]={ 0x48, 0x2e, 0x6d, 0x6d, 0 }; /* H.mm */ |
46f4442e A |
71 | static const UChar testPattern[]={ 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0 }; /* HH:mm */ |
72 | static const UChar expectingSkeleton[]= { 0x48, 0x48, 0x6d, 0x6d, 0 }; /* HHmm */ | |
73 | static const UChar expectingBaseSkeleton[]= { 0x48, 0x6d, 0 }; /* HHmm */ | |
74 | static const UChar redundantPattern[]={ 0x79, 0x79, 0x4d, 0x4d, 0x4d, 0 }; /* yyMMM */ | |
75 | static const UChar testFormat[]= {0x7B, 0x31, 0x7D, 0x20, 0x7B, 0x30, 0x7D, 0}; /* {1} {0} */ | |
76 | static const UChar appendItemName[]= {0x68, 0x72, 0}; /* hr */ | |
77 | static const UChar testPattern2[]={ 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x76, 0 }; /* HH:mm v */ | |
78 | static const UChar replacedStr[]={ 0x76, 0x76, 0x76, 0x76, 0 }; /* vvvv */ | |
79 | /* results for getBaseSkeletons() - {Hmv}, {yMMM} */ | |
80 | static const UChar resultBaseSkeletons[2][10] = {{0x48,0x6d, 0x76, 0}, {0x79, 0x4d, 0x4d, 0x4d, 0 } }; | |
81 | static const UChar sampleFormatted[] = {0x31, 0x30, 0x20, 0x6A, 0x75, 0x69, 0x6C, 0x2E, 0}; /* 10 juil. */ | |
82 | static const UChar skeleton[]= {0x4d, 0x4d, 0x4d, 0x64, 0}; /* MMMd */ | |
83 | static const UChar timeZoneGMT[] = { 0x0047, 0x004d, 0x0054, 0x0000 }; /* "GMT" */ | |
84 | ||
85 | static void TestOpenClose() { | |
86 | UErrorCode errorCode=U_ZERO_ERROR; | |
87 | UDateTimePatternGenerator *dtpg, *dtpg2; | |
88 | const UChar *s; | |
89 | int32_t length; | |
90 | ||
91 | /* Open a DateTimePatternGenerator for the default locale. */ | |
92 | dtpg=udatpg_open(NULL, &errorCode); | |
93 | if(U_FAILURE(errorCode)) { | |
729e4ab9 | 94 | log_err_status(errorCode, "udatpg_open(NULL) failed - %s\n", u_errorName(errorCode)); |
46f4442e A |
95 | return; |
96 | } | |
97 | udatpg_close(dtpg); | |
98 | ||
99 | /* Now one for German. */ | |
100 | dtpg=udatpg_open("de", &errorCode); | |
101 | if(U_FAILURE(errorCode)) { | |
102 | log_err("udatpg_open(de) failed - %s\n", u_errorName(errorCode)); | |
103 | return; | |
104 | } | |
105 | ||
106 | /* Make some modification which we verify gets passed on to the clone. */ | |
107 | udatpg_setDecimal(dtpg, pipeString, 1); | |
108 | ||
109 | /* Clone the generator. */ | |
110 | dtpg2=udatpg_clone(dtpg, &errorCode); | |
111 | if(U_FAILURE(errorCode) || dtpg2==NULL) { | |
112 | log_err("udatpg_clone() failed - %s\n", u_errorName(errorCode)); | |
113 | return; | |
114 | } | |
115 | ||
116 | /* Verify that the clone has the custom decimal symbol. */ | |
117 | s=udatpg_getDecimal(dtpg2, &length); | |
118 | if(s==pipeString || length!=1 || 0!=u_memcmp(s, pipeString, length) || s[length]!=0) { | |
119 | log_err("udatpg_getDecimal(cloned object) did not return the expected string\n"); | |
120 | return; | |
121 | } | |
122 | ||
123 | udatpg_close(dtpg); | |
124 | udatpg_close(dtpg2); | |
125 | } | |
126 | ||
57a6839d A |
127 | typedef struct { |
128 | UDateTimePatternField field; | |
129 | UChar name[12]; | |
130 | } AppendItemNameData; | |
131 | ||
132 | static const AppendItemNameData appendItemNameData[] = { /* for Finnish */ | |
133 | { UDATPG_YEAR_FIELD, {0x0076,0x0075,0x006F,0x0073,0x0069,0} }, /* "vuosi" */ | |
134 | { UDATPG_MONTH_FIELD, {0x006B,0x0075,0x0075,0x006B,0x0061,0x0075,0x0073,0x0069,0} }, /* "kuukausi" */ | |
135 | { UDATPG_WEEKDAY_FIELD, {0x0076,0x0069,0x0069,0x006B,0x006F,0x006E,0x0070,0x00E4,0x0069,0x0076,0x00E4,0} }, | |
136 | { UDATPG_DAY_FIELD, {0x0070,0x00E4,0x0069,0x0076,0x00E4,0} }, | |
137 | { UDATPG_HOUR_FIELD, {0x0074,0x0075,0x006E,0x0074,0x0069,0} }, /* "tunti" */ | |
138 | { UDATPG_FIELD_COUNT, {0} } /* terminator */ | |
139 | }; | |
140 | ||
46f4442e A |
141 | static void TestUsage() { |
142 | UErrorCode errorCode=U_ZERO_ERROR; | |
143 | UDateTimePatternGenerator *dtpg; | |
57a6839d | 144 | const AppendItemNameData * appItemNameDataPtr; |
46f4442e A |
145 | UChar bestPattern[20]; |
146 | UChar result[20]; | |
147 | int32_t length; | |
148 | UChar *s; | |
149 | const UChar *r; | |
150 | ||
151 | dtpg=udatpg_open("fi", &errorCode); | |
152 | if(U_FAILURE(errorCode)) { | |
729e4ab9 | 153 | log_err_status(errorCode, "udatpg_open(fi) failed - %s\n", u_errorName(errorCode)); |
46f4442e A |
154 | return; |
155 | } | |
156 | length = udatpg_getBestPattern(dtpg, testSkeleton1, 4, | |
157 | bestPattern, 20, &errorCode); | |
158 | if(U_FAILURE(errorCode)) { | |
159 | log_err("udatpg_getBestPattern failed - %s\n", u_errorName(errorCode)); | |
160 | return; | |
161 | } | |
162 | if((u_memcmp(bestPattern, expectingBestPattern, length)!=0) || bestPattern[length]!=0) { | |
163 | log_err("udatpg_getBestPattern did not return the expected string\n"); | |
164 | return; | |
165 | } | |
166 | ||
167 | ||
168 | /* Test skeleton == NULL */ | |
169 | s=NULL; | |
170 | length = udatpg_getBestPattern(dtpg, s, 0, bestPattern, 20, &errorCode); | |
171 | if(!U_FAILURE(errorCode)&&(length!=0) ) { | |
172 | log_err("udatpg_getBestPattern failed in illegal argument - skeleton is NULL.\n"); | |
173 | return; | |
174 | } | |
175 | ||
176 | /* Test udatpg_getSkeleton */ | |
177 | length = udatpg_getSkeleton(dtpg, testPattern, 5, result, 20, &errorCode); | |
178 | if(U_FAILURE(errorCode)) { | |
179 | log_err("udatpg_getSkeleton failed - %s\n", u_errorName(errorCode)); | |
180 | return; | |
181 | } | |
182 | if((u_memcmp(result, expectingSkeleton, length)!=0) || result[length]!=0) { | |
183 | log_err("udatpg_getSkeleton did not return the expected string\n"); | |
184 | return; | |
185 | } | |
186 | ||
187 | /* Test pattern == NULL */ | |
188 | s=NULL; | |
189 | length = udatpg_getSkeleton(dtpg, s, 0, result, 20, &errorCode); | |
190 | if(!U_FAILURE(errorCode)&&(length!=0) ) { | |
191 | log_err("udatpg_getSkeleton failed in illegal argument - pattern is NULL.\n"); | |
192 | return; | |
193 | } | |
194 | ||
195 | /* Test udatpg_getBaseSkeleton */ | |
196 | length = udatpg_getBaseSkeleton(dtpg, testPattern, 5, result, 20, &errorCode); | |
197 | if(U_FAILURE(errorCode)) { | |
198 | log_err("udatpg_getBaseSkeleton failed - %s\n", u_errorName(errorCode)); | |
199 | return; | |
200 | } | |
201 | if((u_memcmp(result, expectingBaseSkeleton, length)!=0) || result[length]!=0) { | |
202 | log_err("udatpg_getBaseSkeleton did not return the expected string\n"); | |
203 | return; | |
204 | } | |
205 | ||
206 | /* Test pattern == NULL */ | |
207 | s=NULL; | |
208 | length = udatpg_getBaseSkeleton(dtpg, s, 0, result, 20, &errorCode); | |
209 | if(!U_FAILURE(errorCode)&&(length!=0) ) { | |
210 | log_err("udatpg_getBaseSkeleton failed in illegal argument - pattern is NULL.\n"); | |
211 | return; | |
212 | } | |
213 | ||
214 | /* set append format to {1}{0} */ | |
215 | udatpg_setAppendItemFormat( dtpg, UDATPG_MONTH_FIELD, testFormat, 7 ); | |
216 | r = udatpg_getAppendItemFormat(dtpg, UDATPG_MONTH_FIELD, &length); | |
217 | ||
218 | ||
219 | if(length!=7 || 0!=u_memcmp(r, testFormat, length) || r[length]!=0) { | |
220 | log_err("udatpg_setAppendItemFormat did not return the expected string\n"); | |
221 | return; | |
222 | } | |
223 | ||
57a6839d A |
224 | for (appItemNameDataPtr = appendItemNameData; appItemNameDataPtr->field < UDATPG_FIELD_COUNT; appItemNameDataPtr++) { |
225 | int32_t nameLength; | |
226 | const UChar * namePtr = udatpg_getAppendItemName(dtpg, appItemNameDataPtr->field, &nameLength); | |
227 | if ( namePtr == NULL || u_strncmp(appItemNameDataPtr->name, namePtr, nameLength) != 0 ) { | |
228 | log_err("udatpg_getAppendItemName returns invalid name for field %d\n", (int)appItemNameDataPtr->field); | |
229 | } | |
230 | } | |
231 | ||
46f4442e | 232 | /* set append name to hr */ |
2ca993e8 | 233 | udatpg_setAppendItemName(dtpg, UDATPG_HOUR_FIELD, appendItemName, 2); |
46f4442e A |
234 | r = udatpg_getAppendItemName(dtpg, UDATPG_HOUR_FIELD, &length); |
235 | ||
2ca993e8 | 236 | if(length!=2 || 0!=u_memcmp(r, appendItemName, length) || r[length]!=0) { |
46f4442e A |
237 | log_err("udatpg_setAppendItemName did not return the expected string\n"); |
238 | return; | |
239 | } | |
240 | ||
241 | /* set date time format to {1}{0} */ | |
242 | udatpg_setDateTimeFormat( dtpg, testFormat, 7 ); | |
243 | r = udatpg_getDateTimeFormat(dtpg, &length); | |
244 | ||
245 | if(length!=7 || 0!=u_memcmp(r, testFormat, length) || r[length]!=0) { | |
246 | log_err("udatpg_setDateTimeFormat did not return the expected string\n"); | |
247 | return; | |
248 | } | |
249 | udatpg_close(dtpg); | |
250 | } | |
251 | ||
252 | static void TestBuilder() { | |
253 | UErrorCode errorCode=U_ZERO_ERROR; | |
254 | UDateTimePatternGenerator *dtpg; | |
255 | UDateTimePatternConflict conflict; | |
256 | UEnumeration *en; | |
257 | UChar result[20]; | |
258 | int32_t length, pLength; | |
259 | const UChar *s, *p; | |
260 | const UChar* ptrResult[2]; | |
261 | int32_t count=0; | |
262 | UDateTimePatternGenerator *generator; | |
263 | int32_t formattedCapacity, resultLen,patternCapacity ; | |
264 | UChar pattern[40], formatted[40]; | |
265 | UDateFormat *formatter; | |
266 | UDate sampleDate = 837039928046.0; | |
729e4ab9 | 267 | static const char locale[]= "fr"; |
46f4442e A |
268 | UErrorCode status=U_ZERO_ERROR; |
269 | ||
270 | /* test create an empty DateTimePatternGenerator */ | |
271 | dtpg=udatpg_openEmpty(&errorCode); | |
272 | if(U_FAILURE(errorCode)) { | |
273 | log_err("udatpg_openEmpty() failed - %s\n", u_errorName(errorCode)); | |
274 | return; | |
275 | } | |
276 | ||
277 | /* Add a pattern */ | |
278 | conflict = udatpg_addPattern(dtpg, redundantPattern, 5, FALSE, result, 20, | |
279 | &length, &errorCode); | |
280 | if(U_FAILURE(errorCode)) { | |
281 | log_err("udatpg_addPattern() failed - %s\n", u_errorName(errorCode)); | |
282 | return; | |
283 | } | |
284 | /* Add a redundant pattern */ | |
285 | conflict = udatpg_addPattern(dtpg, redundantPattern, 5, FALSE, result, 20, | |
286 | &length, &errorCode); | |
287 | if(conflict == UDATPG_NO_CONFLICT) { | |
288 | log_err("udatpg_addPattern() failed to find the duplicate pattern.\n"); | |
289 | return; | |
290 | } | |
291 | /* Test pattern == NULL */ | |
292 | s=NULL; | |
293 | length = udatpg_addPattern(dtpg, s, 0, FALSE, result, 20, | |
294 | &length, &errorCode); | |
295 | if(!U_FAILURE(errorCode)&&(length!=0) ) { | |
296 | log_err("udatpg_addPattern failed in illegal argument - pattern is NULL.\n"); | |
297 | return; | |
298 | } | |
299 | ||
300 | /* replace field type */ | |
301 | errorCode=U_ZERO_ERROR; | |
302 | conflict = udatpg_addPattern(dtpg, testPattern2, 7, FALSE, result, 20, | |
303 | &length, &errorCode); | |
304 | if((conflict != UDATPG_NO_CONFLICT)||U_FAILURE(errorCode)) { | |
305 | log_err("udatpg_addPattern() failed to add HH:mm v. - %s\n", u_errorName(errorCode)); | |
306 | return; | |
307 | } | |
308 | length = udatpg_replaceFieldTypes(dtpg, testPattern2, 7, replacedStr, 4, | |
309 | result, 20, &errorCode); | |
310 | if (U_FAILURE(errorCode) || (length==0) ) { | |
311 | log_err("udatpg_replaceFieldTypes failed!\n"); | |
312 | return; | |
313 | } | |
314 | ||
315 | /* Get all skeletons and the crroespong pattern for each skeleton. */ | |
316 | ptrResult[0] = testPattern2; | |
317 | ptrResult[1] = redundantPattern; | |
318 | count=0; | |
319 | en = udatpg_openSkeletons(dtpg, &errorCode); | |
320 | if (U_FAILURE(errorCode) || (length==0) ) { | |
321 | log_err("udatpg_openSkeletons failed!\n"); | |
322 | return; | |
323 | } | |
324 | while ( (s=uenum_unext(en, &length, &errorCode))!= NULL) { | |
325 | p = udatpg_getPatternForSkeleton(dtpg, s, length, &pLength); | |
326 | if (U_FAILURE(errorCode) || p==NULL || u_memcmp(p, ptrResult[count], pLength)!=0 ) { | |
327 | log_err("udatpg_getPatternForSkeleton failed!\n"); | |
328 | return; | |
329 | } | |
330 | count++; | |
331 | } | |
332 | uenum_close(en); | |
333 | ||
334 | /* Get all baseSkeletons */ | |
335 | en = udatpg_openBaseSkeletons(dtpg, &errorCode); | |
336 | count=0; | |
337 | while ( (s=uenum_unext(en, &length, &errorCode))!= NULL) { | |
338 | p = udatpg_getPatternForSkeleton(dtpg, s, length, &pLength); | |
339 | if (U_FAILURE(errorCode) || p==NULL || u_memcmp(p, resultBaseSkeletons[count], pLength)!=0 ) { | |
340 | log_err("udatpg_getPatternForSkeleton failed!\n"); | |
341 | return; | |
342 | } | |
343 | count++; | |
344 | } | |
345 | if (U_FAILURE(errorCode) || (length==0) ) { | |
346 | log_err("udatpg_openSkeletons failed!\n"); | |
347 | return; | |
348 | } | |
349 | uenum_close(en); | |
350 | ||
351 | udatpg_close(dtpg); | |
352 | ||
353 | /* sample code in Userguide */ | |
2ca993e8 | 354 | patternCapacity = UPRV_LENGTHOF(pattern); |
46f4442e A |
355 | status=U_ZERO_ERROR; |
356 | generator=udatpg_open(locale, &status); | |
357 | if(U_FAILURE(status)) { | |
358 | return; | |
359 | } | |
360 | ||
361 | /* get a pattern for an abbreviated month and day */ | |
362 | length = udatpg_getBestPattern(generator, skeleton, 4, | |
363 | pattern, patternCapacity, &status); | |
51004dcb | 364 | formatter = udat_open(UDAT_PATTERN, UDAT_PATTERN, locale, timeZoneGMT, -1, |
46f4442e A |
365 | pattern, length, &status); |
366 | if (formatter==NULL) { | |
367 | log_err("Failed to initialize the UDateFormat of the sample code in Userguide.\n"); | |
368 | udatpg_close(generator); | |
369 | return; | |
370 | } | |
371 | ||
372 | /* use it to format (or parse) */ | |
2ca993e8 | 373 | formattedCapacity = UPRV_LENGTHOF(formatted); |
46f4442e A |
374 | resultLen=udat_format(formatter, ucal_getNow(), formatted, formattedCapacity, |
375 | NULL, &status); | |
376 | /* for French, the result is "13 sept." */ | |
377 | ||
378 | /* cannot use the result from ucal_getNow() because the value change evreyday. */ | |
379 | resultLen=udat_format(formatter, sampleDate, formatted, formattedCapacity, | |
380 | NULL, &status); | |
381 | if ( u_memcmp(sampleFormatted, formatted, resultLen) != 0 ) { | |
382 | log_err("Failed udat_format() of sample code in Userguide.\n"); | |
383 | } | |
384 | udatpg_close(generator); | |
385 | udat_close(formatter); | |
386 | } | |
387 | ||
729e4ab9 A |
388 | typedef struct DTPtnGenOptionsData { |
389 | const char * locale; | |
390 | const UChar * skel; | |
391 | UDateTimePatternMatchOptions options; | |
392 | const UChar * expectedPattern; | |
393 | } DTPtnGenOptionsData; | |
394 | enum { kTestOptionsPatLenMax = 32 }; | |
395 | ||
396 | static const UChar skel_Hmm[] = { 0x0048, 0x006D, 0x006D, 0 }; | |
397 | static const UChar skel_HHmm[] = { 0x0048, 0x0048, 0x006D, 0x006D, 0 }; | |
398 | static const UChar skel_hhmm[] = { 0x0068, 0x0068, 0x006D, 0x006D, 0 }; | |
3bb97ae2 A |
399 | static const UChar skel_mmss[] = { 0x006D, 0x006D, 0x0073, 0x0073, 0 }; |
400 | static const UChar skel_mmssSS[] = { 0x006D, 0x006D, 0x0073, 0x0073, 0x0053, 0x0053, 0 }; | |
729e4ab9 A |
401 | static const UChar patn_hcmm_a[] = { 0x0068, 0x003A, 0x006D, 0x006D, 0x0020, 0x0061, 0 }; /* h:mm a */ |
402 | static const UChar patn_HHcmm[] = { 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0 }; /* HH:mm */ | |
403 | static const UChar patn_hhcmm_a[] = { 0x0068, 0x0068, 0x003A, 0x006D, 0x006D, 0x0020, 0x0061, 0 }; /* hh:mm a */ | |
404 | static const UChar patn_HHpmm[] = { 0x0048, 0x0048, 0x002E, 0x006D, 0x006D, 0 }; /* HH.mm */ | |
405 | static const UChar patn_hpmm_a[] = { 0x0068, 0x002E, 0x006D, 0x006D, 0x0020, 0x0061, 0 }; /* h.mm a */ | |
406 | static const UChar patn_Hpmm[] = { 0x0048, 0x002E, 0x006D, 0x006D, 0 }; /* H.mm */ | |
407 | static const UChar patn_hhpmm_a[] = { 0x0068, 0x0068, 0x002E, 0x006D, 0x006D, 0x0020, 0x0061, 0 }; /* hh.mm a */ | |
3bb97ae2 A |
408 | static const UChar patn_mmcss[] = { 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0 }; /* mm:ss */ |
409 | static const UChar patn_mmcsspSS[]= { 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x002E, 0x0053, 0x0053, 0 }; /* mm:ss.SS */ | |
729e4ab9 A |
410 | |
411 | static void TestOptions() { | |
412 | const DTPtnGenOptionsData testData[] = { | |
413 | /*loc skel options expectedPattern */ | |
414 | { "en", skel_Hmm, UDATPG_MATCH_NO_OPTIONS, patn_HHcmm }, | |
415 | { "en", skel_HHmm, UDATPG_MATCH_NO_OPTIONS, patn_HHcmm }, | |
416 | { "en", skel_hhmm, UDATPG_MATCH_NO_OPTIONS, patn_hcmm_a }, | |
417 | { "en", skel_Hmm, UDATPG_MATCH_HOUR_FIELD_LENGTH, patn_HHcmm }, | |
418 | { "en", skel_HHmm, UDATPG_MATCH_HOUR_FIELD_LENGTH, patn_HHcmm }, | |
419 | { "en", skel_hhmm, UDATPG_MATCH_HOUR_FIELD_LENGTH, patn_hhcmm_a }, | |
2ca993e8 A |
420 | { "da", skel_Hmm, UDATPG_MATCH_NO_OPTIONS, patn_HHpmm }, |
421 | { "da", skel_HHmm, UDATPG_MATCH_NO_OPTIONS, patn_HHpmm }, | |
422 | { "da", skel_hhmm, UDATPG_MATCH_NO_OPTIONS, patn_hpmm_a }, | |
423 | { "da", skel_Hmm, UDATPG_MATCH_HOUR_FIELD_LENGTH, patn_Hpmm }, | |
424 | { "da", skel_HHmm, UDATPG_MATCH_HOUR_FIELD_LENGTH, patn_HHpmm }, | |
425 | { "da", skel_hhmm, UDATPG_MATCH_HOUR_FIELD_LENGTH, patn_hhpmm_a }, | |
3bb97ae2 A |
426 | { "en_JP@calendar=japanese", skel_mmss, UDATPG_MATCH_NO_OPTIONS, patn_mmcss }, |
427 | { "en_JP@calendar=japanese", skel_mmssSS, UDATPG_MATCH_NO_OPTIONS, patn_mmcsspSS }, | |
729e4ab9 A |
428 | }; |
429 | ||
2ca993e8 | 430 | int count = UPRV_LENGTHOF(testData); |
729e4ab9 A |
431 | const DTPtnGenOptionsData * testDataPtr = testData; |
432 | ||
433 | for (; count-- > 0; ++testDataPtr) { | |
434 | UErrorCode status = U_ZERO_ERROR; | |
435 | UDateTimePatternGenerator * dtpgen = udatpg_open(testDataPtr->locale, &status); | |
436 | if ( U_SUCCESS(status) ) { | |
437 | UChar pattern[kTestOptionsPatLenMax]; | |
438 | int32_t patLen = udatpg_getBestPatternWithOptions(dtpgen, testDataPtr->skel, -1, | |
439 | testDataPtr->options, pattern, | |
440 | kTestOptionsPatLenMax, &status); | |
441 | if ( U_FAILURE(status) || u_strncmp(pattern, testDataPtr->expectedPattern, patLen+1) != 0 ) { | |
442 | char skelBytes[kTestOptionsPatLenMax]; | |
443 | char expectedPatternBytes[kTestOptionsPatLenMax]; | |
444 | char patternBytes[kTestOptionsPatLenMax]; | |
445 | log_err("ERROR udatpg_getBestPatternWithOptions, locale %s, skeleton %s, options 0x%04X, expected pattern %s, got %s, status %d\n", | |
446 | testDataPtr->locale, u_austrncpy(skelBytes,testDataPtr->skel,kTestOptionsPatLenMax), testDataPtr->options, | |
447 | u_austrncpy(expectedPatternBytes,testDataPtr->expectedPattern,kTestOptionsPatLenMax), | |
448 | u_austrncpy(patternBytes,pattern,kTestOptionsPatLenMax), status ); | |
449 | } | |
450 | udatpg_close(dtpgen); | |
451 | } else { | |
452 | log_data_err("ERROR udatpg_open failed for locale %s : %s - (Are you missing data?)\n", testDataPtr->locale, myErrorName(status)); | |
453 | } | |
454 | } | |
455 | } | |
456 | ||
0f5d89e8 A |
457 | typedef struct FieldDisplayNameData { |
458 | const char * locale; | |
459 | UDateTimePatternField field; | |
460 | UDateTimePGDisplayWidth width; | |
461 | const char * expected; | |
462 | } FieldDisplayNameData; | |
463 | enum { kFieldDisplayNameMax = 32, kFieldDisplayNameBytesMax = 64}; | |
464 | ||
465 | static void TestGetFieldDisplayNames() { | |
466 | const FieldDisplayNameData testData[] = { | |
467 | /*loc field width expectedName */ | |
468 | { "de", UDATPG_QUARTER_FIELD, UDATPG_WIDE, "Quartal" }, | |
469 | { "de", UDATPG_QUARTER_FIELD, UDATPG_ABBREVIATED, "Quart." }, | |
470 | { "de", UDATPG_QUARTER_FIELD, UDATPG_NARROW, "Q" }, | |
471 | { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_WIDE, "weekday of the month" }, | |
472 | { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_ABBREVIATED, "wkday. of mo." }, | |
473 | { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_NARROW, "wkday. of mo." }, // fallback | |
474 | { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_WIDE, "weekday of the month" }, | |
475 | { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_ABBREVIATED, "wkday of mo" }, // override | |
476 | { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_NARROW, "wkday of mo" }, | |
477 | { "it", UDATPG_SECOND_FIELD, UDATPG_WIDE, "secondo" }, | |
478 | { "it", UDATPG_SECOND_FIELD, UDATPG_ABBREVIATED, "s" }, | |
479 | { "it", UDATPG_SECOND_FIELD, UDATPG_NARROW, "s" }, | |
480 | }; | |
481 | ||
482 | int count = UPRV_LENGTHOF(testData); | |
483 | const FieldDisplayNameData * testDataPtr = testData; | |
484 | for (; count-- > 0; ++testDataPtr) { | |
485 | UErrorCode status = U_ZERO_ERROR; | |
486 | UDateTimePatternGenerator * dtpgen = udatpg_open(testDataPtr->locale, &status); | |
487 | if ( U_FAILURE(status) ) { | |
488 | log_data_err("ERROR udatpg_open failed for locale %s : %s - (Are you missing data?)\n", testDataPtr->locale, myErrorName(status)); | |
489 | } else { | |
490 | UChar expName[kFieldDisplayNameMax]; | |
491 | UChar getName[kFieldDisplayNameMax]; | |
492 | u_unescape(testDataPtr->expected, expName, kFieldDisplayNameMax); | |
493 | ||
494 | int32_t getLen = udatpg_getFieldDisplayName(dtpgen, testDataPtr->field, testDataPtr->width, | |
495 | getName, kFieldDisplayNameMax, &status); | |
496 | if ( U_FAILURE(status) ) { | |
497 | log_err("ERROR udatpg_getFieldDisplayName locale %s field %d width %d, got status %s, len %d\n", | |
498 | testDataPtr->locale, testDataPtr->field, testDataPtr->width, u_errorName(status), getLen); | |
499 | } else if ( u_strncmp(expName, getName, kFieldDisplayNameMax) != 0 ) { | |
500 | char expNameB[kFieldDisplayNameBytesMax]; | |
501 | char getNameB[kFieldDisplayNameBytesMax]; | |
502 | log_err("ERROR udatpg_getFieldDisplayName locale %s field %d width %d, expected %s, got %s, status %s\n", | |
503 | testDataPtr->locale, testDataPtr->field, testDataPtr->width, | |
504 | u_austrncpy(expNameB,expName,kFieldDisplayNameBytesMax), | |
505 | u_austrncpy(getNameB,getName,kFieldDisplayNameBytesMax), u_errorName(status) ); | |
506 | } else if (testDataPtr->width == UDATPG_WIDE && getLen > 1) { | |
507 | // test preflight & inadequate buffer | |
508 | int32_t getNewLen; | |
509 | status = U_ZERO_ERROR; | |
510 | getNewLen = udatpg_getFieldDisplayName(dtpgen, testDataPtr->field, UDATPG_WIDE, NULL, 0, &status); | |
511 | if (U_FAILURE(status) || getNewLen != getLen) { | |
512 | log_err("ERROR udatpg_getFieldDisplayName locale %s field %d width %d, preflight expected len %d, got %d, status %s\n", | |
513 | testDataPtr->locale, testDataPtr->field, testDataPtr->width, getLen, getNewLen, u_errorName(status) ); | |
514 | } | |
515 | status = U_ZERO_ERROR; | |
516 | getNewLen = udatpg_getFieldDisplayName(dtpgen, testDataPtr->field, UDATPG_WIDE, getName, getLen-1, &status); | |
517 | if (status!=U_BUFFER_OVERFLOW_ERROR || getNewLen != getLen) { | |
518 | log_err("ERROR udatpg_getFieldDisplayName locale %s field %d width %d, overflow expected len %d & BUFFER_OVERFLOW_ERROR, got %d & status %s\n", | |
519 | testDataPtr->locale, testDataPtr->field, testDataPtr->width, getLen, getNewLen, u_errorName(status) ); | |
520 | } | |
521 | } | |
522 | udatpg_close(dtpgen); | |
523 | } | |
524 | } | |
525 | } | |
526 | ||
3d1f044b A |
527 | enum { kUFmtMax = 64, kBFmtMax = 128 }; |
528 | static void TestJapaneseCalendarItems(void) { // rdar://52042600 | |
529 | static const UChar* jaJpnCalSkelAndFmt[][2] = { | |
530 | { u"yMd", u"GGGGGy/MM/dd" }, | |
531 | { u"GGGGGyMd", u"GGGGGy/MM/dd" }, | |
532 | { u"GyMd", u"GGGGGy/MM/dd" }, | |
533 | { u"yyMMdd", u"GGGGGy/MM/dd" }, | |
534 | //{ u"GGGGGyyMMdd", u"GGGGGy/MM/dd" }, | |
535 | { u"GyyMMdd", u"GGGGGy/MM/dd" }, | |
536 | { u"yyMMEdd", u"GGGGGy/MM/dd(EEE)" }, | |
537 | { u"GGGGGyyMMEdd", u"GGGGGy/MM/dd(EEE)" }, | |
538 | { u"yyMEdjmma", u"GGGGGy/MM/dd(EEE) H:mm" }, | |
539 | { NULL, NULL } | |
540 | }; | |
541 | UErrorCode status = U_ZERO_ERROR; | |
542 | UDateTimePatternGenerator* udatpg = udatpg_open("ja@calendar=japanese", &status); | |
543 | if ( U_FAILURE(status) ) { | |
544 | log_data_err("FAIL udatpg_open failed for locale ja@calendar=japanese : %s\n", myErrorName(status)); | |
545 | } else { | |
546 | int32_t idx; | |
547 | for (idx = 0; jaJpnCalSkelAndFmt[idx][0] != NULL; idx++) { | |
548 | UChar uget[kUFmtMax]; | |
549 | char bskel[kBFmtMax]; | |
550 | status = U_ZERO_ERROR; | |
551 | u_strToUTF8(bskel, kBFmtMax, NULL, jaJpnCalSkelAndFmt[idx][0], -1, &status); | |
552 | int32_t ulen = udatpg_getBestPattern(udatpg, jaJpnCalSkelAndFmt[idx][0], -1, uget, kUFmtMax, &status); | |
553 | if ( U_FAILURE(status) ) { | |
554 | log_data_err("FAIL udatpg_getBestPattern status for skeleton %s : %s\n", bskel); | |
555 | } else if (u_strcmp(uget,jaJpnCalSkelAndFmt[idx][1]) != 0) { | |
556 | char bexp[kBFmtMax]; | |
557 | char bget[kBFmtMax]; | |
558 | u_strToUTF8(bexp, kBFmtMax, NULL, jaJpnCalSkelAndFmt[idx][1], -1, &status); | |
559 | u_strToUTF8(bget, kBFmtMax, NULL, uget, ulen, &status); | |
560 | log_data_err("ERROR udatpg_getBestPattern for skeleton %s, expect %s, get %s\n", bskel, bexp, bget); | |
561 | } | |
562 | } | |
563 | udatpg_close(udatpg); | |
564 | } | |
565 | } | |
566 | ||
340931cb A |
567 | static void TestCountryFallback(void) { |
568 | // (The list of test locales here is derived from the one in TestCountryFallback() in cnumtst.c) | |
569 | // column 1 is the locale, column 2 is the input skeleton, column 3 is the expected pattern | |
570 | UChar* testData[] = { | |
571 | // The following locales are specifically mentioned in Radars: | |
572 | u"fr_US", u"GyMMMM", u"MMMM y G", // rdar://problem/54886964 | |
573 | u"en_TH", u"GyMMMM", u"MMMM y G", // rdar://problem/29299919 | |
574 | u"en_BG", u"GyMMMM", u"MMMM y G", // rdar://problem/29299919 | |
575 | u"en_LI", u"GyMMMM", u"MMMM y G", // rdar://problem/29299919 | |
576 | u"en_MC", u"GyMMMM", u"MMMM y G", // rdar://problem/29299919 | |
577 | u"en_MD", u"GyMMMM", u"MMMM y G", // rdar://problem/29299919 | |
578 | u"en_VA", u"GyMMMM", u"MMMM y G", // rdar://problem/29299919 | |
579 | u"fr_GB", u"GyMMMM", u"MMMM y G", // rdar://problem/36020946 | |
580 | u"fr_CN", u"GyMMMM", u"MMMM y G", // rdar://problem/50083902 | |
581 | u"es_IE", u"GyMMMM", u"MMMM 'de' y G", // rdar://problem/58733843 | |
582 | // Special for en_SA, date formats should match en_001, other items should match en | |
583 | u"en_SA", u"GyMMMM", u"MMMM y G", | |
584 | // Tests for situations where the default calendar is different depending on whether you | |
585 | // fall back by language or by country: | |
586 | u"ar_US", u"GyMMMM", u"MMMM y G", | |
587 | // Tests for situations where the original locale ID specifies a script: | |
588 | u"sr_Cyrl_SA", u"GyMMMM", u"MMMM y. G", | |
589 | u"ru_Cyrl_BA", u"GyMMMM", u"LLLL y G", | |
590 | // And these are just a few additional arbitrary combinations: | |
591 | u"ja_US", u"GyMMMM", u"Gy年M月", | |
592 | u"fr_DE", u"GyMMMM", u"MMMM y G", | |
593 | u"es_TW", u"GyMMMM", u"MMMM 'de' y G", | |
594 | // Test to make sure that nothing goes wrong if language and country fallback both lead to the same resource | |
595 | // (This won't happen for any "real" locales, because ICU has resources for all of them, but we can fake it with | |
596 | // a nonexistent country code such as QQ.) | |
597 | u"en_QQ", u"GyMMMM", u"MMMM y G", | |
598 | ||
599 | // The following locales are specifically mentioned in Radars: | |
600 | u"fr_US", u"yMEd", u"EEE, M/d/y", // rdar://problem/54886964 | |
601 | u"en_TH", u"yMEd", u"EEE, dd/MM/y GGGGG", // rdar://problem/29299919 | |
602 | u"en_BG", u"yMEd", u"EEE, d.MM.y", // rdar://problem/29299919 | |
603 | u"en_LI", u"yMEd", u"EEE d.M.y", // rdar://problem/29299919 | |
604 | u"en_MC", u"yMEd", u"EEE dd/MM/y", // rdar://problem/29299919 | |
605 | u"en_MD", u"yMEd", u"EEE, dd.MM.y", // rdar://problem/29299919 | |
606 | u"en_VA", u"yMEd", u"EEE d/M/y", // rdar://problem/29299919 | |
607 | u"fr_GB", u"yMEd", u"EEE, dd/MM/y", // rdar://problem/36020946 | |
608 | u"fr_CN", u"yMEd", u"y/M/dEEE", // rdar://problem/50083902 | |
609 | u"es_IE", u"yMEd", u"EEE, d/M/y", // rdar://problem/58733843 | |
610 | // Special for en_SA, date formats should match en_001, other items should match en | |
611 | u"en_SA", u"yMEd", u"EEE, dd/MM/y GGGGG", | |
612 | // Tests for situations where the default calendar is different depending on whether you | |
613 | // fall back by language or by country: | |
614 | u"ar_US", u"yMEd", u"EEE, M/d/y", | |
615 | // Tests for situations where the original locale ID specifies a script: | |
616 | u"sr_Cyrl_SA", u"yMEd", u"EEE, d.M.y. GGGGG", | |
617 | u"ru_Cyrl_BA", u"yMEd", u"EEE, dd.MM.y.", | |
618 | // And these are just a few additional arbitrary combinations: | |
619 | u"ja_US", u"yMEd", u"EEE, M/d/y", | |
620 | u"fr_DE", u"yMEd", u"EEE d.M.y", | |
621 | u"es_TW", u"yMEd", u"y/M/d(EEE)", | |
622 | // Test to make sure that nothing goes wrong if language and country fallback both lead to the same resource | |
623 | // (This won't happen for any "real" locales, because ICU has resources for all of them, but we can fake it with | |
624 | // a nonexistent country code such as QQ.) | |
625 | u"en_QQ", u"yMEd", u"EEE, M/d/y", | |
626 | ||
627 | // The following locales are specifically mentioned in Radars: | |
628 | u"fr_US", u"Ejm", u"EEE h:mm a", // rdar://problem/54886964 | |
629 | u"en_TH", u"Ejm", u"EEE, HH:mm", // rdar://problem/29299919 | |
630 | u"en_BG", u"Ejm", u"EEE HH:mm", // rdar://problem/29299919 | |
631 | u"en_LI", u"Ejm", u"EEE HH:mm", // rdar://problem/29299919 | |
632 | u"en_MC", u"Ejm", u"EEE HH:mm", // rdar://problem/29299919 | |
633 | u"en_MD", u"Ejm", u"EEE HH:mm", // rdar://problem/29299919 | |
634 | u"en_VA", u"Ejm", u"EEE HH:mm", // rdar://problem/29299919 | |
635 | u"fr_GB", u"Ejm", u"EEE HH:mm", // rdar://problem/36020946 | |
636 | u"fr_CN", u"Ejm", u"EEE h:mm a", // rdar://problem/50083902 | |
637 | u"es_IE", u"Ejm", u"EEE, H:mm", // rdar://problem/58733843 | |
638 | // Special for en_SA, date formats should match en_001, other items should match en | |
639 | u"en_SA", u"Ejm", u"EEE, h:mm a", | |
640 | // Tests for situations where the default calendar is different depending on whether you | |
641 | // fall back by language or by country: | |
642 | u"ar_US", u"Ejm", u"EEE h:mm\u00a0a", | |
643 | // Tests for situations where the original locale ID specifies a script: | |
644 | u"sr_Cyrl_SA", u"Ejm", u"EEE hh:mm a", | |
645 | u"ru_Cyrl_BA", u"Ejm", u"EEE HH:mm", | |
646 | // And these are just a few additional arbitrary combinations: | |
647 | u"ja_US", u"Ejm", u"EEE aK:mm", | |
648 | u"fr_DE", u"Ejm", u"EEE HH:mm", | |
649 | u"es_TW", u"Ejm", u"EEE, h:mm a", | |
650 | // Test to make sure that nothing goes wrong if language and country fallback both lead to the same resource | |
651 | // (This won't happen for any "real" locales, because ICU has resources for all of them, but we can fake it with | |
652 | // a nonexistent country code such as QQ.) | |
653 | u"en_QQ", u"Ejm", u"EEE HH:mm", | |
654 | ||
655 | // Tests for rdar://64948924 (D431/18A314: Incorrect date format in description: th_US) | |
656 | u"th_TH", u"Gy", u"G y", | |
657 | u"th_TH", u"y", u"G y", | |
658 | u"th_TH@calendar=gregorian", u"Gy", u"G y", | |
659 | u"th_TH@calendar=gregorian", u"y", u"y", | |
660 | u"th_US", u"Gy", u"G y", | |
661 | u"th_US", u"y", u"y" | |
662 | }; | |
663 | ||
664 | for (int32_t i = 0; i < (sizeof(testData) / sizeof(UChar*)); i += 3) { | |
665 | UChar* localeU = testData[i]; | |
666 | char locale[30]; | |
667 | UChar* skeleton = testData[i + 1]; | |
668 | UChar* expectedPattern = testData[i + 2]; | |
669 | ||
670 | u_austrcpy(locale, localeU); | |
671 | ||
672 | UErrorCode err = U_ZERO_ERROR; | |
673 | UDateTimePatternGenerator* dtpg = udatpg_open(locale, &err); | |
674 | if (assertSuccess("Failed to open UDateTimePatternGenerator", &err)) { | |
675 | UChar actualPattern[200]; | |
676 | ||
677 | udatpg_getBestPattern(dtpg, skeleton, -1, actualPattern, 200, &err); | |
678 | ||
679 | if (assertSuccess("Error getting pattern with skeleton", &err)) { | |
680 | char errorMessage[200]; | |
681 | sprintf(errorMessage, "In %s, pattern for skeleton %s doesn't match\n", locale, austrdup(skeleton)); | |
682 | assertUEquals(errorMessage, expectedPattern, actualPattern); | |
683 | } | |
684 | udatpg_close(dtpg); | |
685 | } | |
686 | } | |
687 | } | |
688 | ||
689 | // Test for rdar://65281358: Make sure DateTimePatternGenerator supplies an era field for year formats using the | |
690 | // Buddhist and Japanese calendars for all English-speaking locales. | |
691 | static void TestEras(void) { | |
692 | char* localeIDs[] = { | |
693 | "en_US@calendar=japanese", | |
694 | "en_GB@calendar=japanese", | |
695 | "en_150@calendar=japanese", | |
696 | "en_001@calendar=japanese", | |
697 | "en@calendar=japanese", | |
698 | "en_US@calendar=buddhist", | |
699 | "en_GB@calendar=buddhist", | |
700 | "en_150@calendar=buddhist", | |
701 | "en_001@calendar=buddhist", | |
702 | "en@calendar=buddhist", | |
703 | }; | |
704 | ||
705 | UErrorCode err = U_ZERO_ERROR; | |
706 | for (int32_t i = 0; i < UPRV_LENGTHOF(localeIDs); i++) { | |
707 | char* locale = localeIDs[i]; | |
708 | UDateTimePatternGenerator* dtpg = udatpg_open(locale, &err); | |
709 | if (U_SUCCESS(err)) { | |
710 | UChar pattern[200]; | |
711 | udatpg_getBestPattern(dtpg, u"y", 1, pattern, 200, &err); | |
712 | ||
713 | if (u_strchr(pattern, u'G') == NULL) { | |
714 | log_err("missing era field for locale %s\n", locale); | |
715 | } | |
716 | } | |
717 | udatpg_close(dtpg); | |
718 | } | |
719 | } | |
720 | ||
46f4442e | 721 | #endif |