OLD | NEW |
| (Empty) |
1 /******************************************************************** | |
2 * COPYRIGHT: | |
3 * Copyright (c) 2007-2013, International Business Machines Corporation and | |
4 * others. All Rights Reserved. | |
5 ********************************************************************/ | |
6 | |
7 #include "unicode/utypes.h" | |
8 | |
9 #if !UCONFIG_NO_FORMATTING | |
10 | |
11 #include "unicode/dcfmtsym.h" | |
12 #include "unicode/decimfmt.h" | |
13 #include "unicode/msgfmt.h" | |
14 #include "unicode/plurfmt.h" | |
15 #include "unicode/plurrule.h" | |
16 #include "cmemory.h" | |
17 #include "plurfmts.h" | |
18 #include "plurults.h" | |
19 | |
20 #define PLURAL_PATTERN_DATA 4 | |
21 #define PLURAL_TEST_ARRAY_SIZE 256 | |
22 | |
23 #define PLURAL_SYNTAX_DATA 8 | |
24 | |
25 // The value must be same as PLKeywordLookups[] order. | |
26 #define PFT_ZERO 0 | |
27 #define PFT_ONE 1 | |
28 #define PFT_TWO 2 | |
29 #define PFT_FEW 3 | |
30 #define PFT_MANY 4 | |
31 #define PFT_OTHER 5 | |
32 | |
33 void PluralFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
ame, char* /*par*/ ) | |
34 { | |
35 if (exec) logln("TestSuite PluralFormat"); | |
36 TESTCASE_AUTO_BEGIN; | |
37 TESTCASE_AUTO(pluralFormatBasicTest); | |
38 TESTCASE_AUTO(pluralFormatUnitTest); | |
39 TESTCASE_AUTO(pluralFormatLocaleTest); | |
40 TESTCASE_AUTO(pluralFormatExtendedTest); | |
41 TESTCASE_AUTO(pluralFormatExtendedParseTest); | |
42 TESTCASE_AUTO(ordinalFormatTest); | |
43 TESTCASE_AUTO(TestDecimals); | |
44 TESTCASE_AUTO_END; | |
45 } | |
46 | |
47 /** | |
48 * Test various generic API methods of PluralFormat for Basic usage. | |
49 */ | |
50 void PluralFormatTest::pluralFormatBasicTest(/*char *par*/) | |
51 { | |
52 UErrorCode status[8]; | |
53 PluralFormat* plFmt[8]; | |
54 Locale locale = Locale::getDefault(); | |
55 UnicodeString otherPattern = UnicodeString("other{#}"); | |
56 UnicodeString message=UnicodeString("ERROR: PluralFormat basic test"); | |
57 | |
58 // ========= Test constructors | |
59 logln(" Testing PluralFormat constructors ..."); | |
60 status[0] = U_ZERO_ERROR; | |
61 PluralRules* plRules = PluralRules::createDefaultRules(status[0]); | |
62 | |
63 status[0] = U_ZERO_ERROR; | |
64 NumberFormat *numFmt = NumberFormat::createInstance(status[0]); | |
65 if (U_FAILURE(status[0])) { | |
66 dataerrln("ERROR: Could not create NumberFormat instance with default lo
cale "); | |
67 } | |
68 | |
69 for (int32_t i=0; i< 8; ++i) { | |
70 status[i] = U_ZERO_ERROR; | |
71 } | |
72 plFmt[0] = new PluralFormat(status[0]); | |
73 plFmt[1] = new PluralFormat(*plRules, status[1]); | |
74 plFmt[2] = new PluralFormat(locale, status[2]); | |
75 plFmt[3] = new PluralFormat(locale, *plRules, status[3]); | |
76 plFmt[4] = new PluralFormat(otherPattern, status[4]); | |
77 plFmt[5] = new PluralFormat(*plRules, otherPattern, status[5]); | |
78 plFmt[6] = new PluralFormat(locale, otherPattern, status[6]); | |
79 plFmt[7] = new PluralFormat(locale, *plRules, otherPattern, status[7]); | |
80 | |
81 for (int32_t i=0; i< 8; ++i) { | |
82 if (U_SUCCESS(status[i])) { | |
83 numberFormatTest(plFmt[i], numFmt, 1, 12, NULL, NULL, FALSE, &messag
e); | |
84 numberFormatTest(plFmt[i], numFmt, 100, 112, NULL, NULL, FALSE, &mes
sage); | |
85 } | |
86 else { | |
87 dataerrln("ERROR: PluralFormat constructor failed!"); | |
88 } | |
89 delete plFmt[i]; | |
90 } | |
91 // ======= Test clone, assignment operator && == operator. | |
92 plFmt[0]= new PluralFormat(status[0]); | |
93 plFmt[0]->setNumberFormat(numFmt,status[0]); | |
94 UnicodeString us = UnicodeString(""); | |
95 plFmt[0]->toPattern(us); | |
96 plFmt[1]= new PluralFormat(locale, status[1]); | |
97 if ( U_SUCCESS(status[0]) && U_SUCCESS(status[1]) ) { | |
98 *plFmt[1] = *plFmt[0]; | |
99 if (plFmt[1]!=NULL) { | |
100 if ( *plFmt[1] != *plFmt[0] ) { | |
101 errln("ERROR: clone plural format test failed!"); | |
102 } | |
103 } | |
104 } | |
105 else { | |
106 dataerrln("ERROR: PluralFormat constructor failed! - [0]%s [1]%s", u_er
rorName(status[0]), u_errorName(status[1])); | |
107 } | |
108 delete plFmt[0]; | |
109 | |
110 status[0] = U_ZERO_ERROR; | |
111 plFmt[0]= new PluralFormat(locale, status[0]); | |
112 if ( U_SUCCESS(status[0]) ) { | |
113 *plFmt[1] = *plFmt[0]; | |
114 if (plFmt[1]!=NULL) { | |
115 if ( *plFmt[1] != *plFmt[0] ) { | |
116 errln("ERROR: assignment operator test failed!"); | |
117 } | |
118 } | |
119 } | |
120 else { | |
121 dataerrln("ERROR: PluralFormat constructor failed! - %s", u_errorName(s
tatus[1])); | |
122 } | |
123 | |
124 if ( U_SUCCESS(status[1]) ) { | |
125 plFmt[2] = (PluralFormat*) plFmt[1]->clone(); | |
126 | |
127 if (plFmt[1]!=NULL) { | |
128 if ( *plFmt[1] != *plFmt[2] ) { | |
129 errln("ERROR: clone function test failed!"); | |
130 } | |
131 } | |
132 delete plFmt[1]; | |
133 delete plFmt[2]; | |
134 } | |
135 else { | |
136 dataerrln("ERROR: PluralFormat clone failed! - %s", u_errorName(status[
1])); | |
137 } | |
138 | |
139 delete plFmt[0]; | |
140 delete numFmt; | |
141 delete plRules; | |
142 | |
143 // Tests parseObject | |
144 UErrorCode stat = U_ZERO_ERROR; | |
145 PluralFormat *pf = new PluralFormat(stat); | |
146 Formattable *f = new Formattable(); | |
147 ParsePosition *pp = new ParsePosition(); | |
148 pf->parseObject((UnicodeString)"",*f,*pp); | |
149 if(U_FAILURE(stat)) { | |
150 dataerrln("ERROR: PluralFormat::parseObject: %s", u_errorName(stat)); | |
151 } | |
152 delete pf; | |
153 delete f; | |
154 delete pp; | |
155 } | |
156 | |
157 /** | |
158 * Unit tests of PluralFormat class. | |
159 */ | |
160 void PluralFormatTest::pluralFormatUnitTest(/*char *par*/) | |
161 { | |
162 UnicodeString patternTestData[PLURAL_PATTERN_DATA] = { | |
163 UNICODE_STRING_SIMPLE("odd {# is odd.} other{# is even.}"), | |
164 UNICODE_STRING_SIMPLE("other{# is odd or even.}"), | |
165 UNICODE_STRING_SIMPLE("odd{The number {0, number, #.#0} is odd.}other{Th
e number {0, number, #.#0} is even.}"), | |
166 UNICODE_STRING_SIMPLE("odd{The number {1, number, #} is odd.}other{The n
umber {2, number, #} is even.}"), | |
167 }; | |
168 UnicodeString patternOddTestResult[PLURAL_PATTERN_DATA] = { | |
169 UNICODE_STRING_SIMPLE(" is odd."), | |
170 UNICODE_STRING_SIMPLE(" is odd or even."), | |
171 UNICODE_STRING_SIMPLE("The number {0, number, #.#0} is odd."), | |
172 UNICODE_STRING_SIMPLE("The number {1, number, #} is odd."), | |
173 }; | |
174 UnicodeString patternEvenTestResult[PLURAL_PATTERN_DATA] = { | |
175 UNICODE_STRING_SIMPLE(" is even."), | |
176 UNICODE_STRING_SIMPLE(" is odd or even."), | |
177 UNICODE_STRING_SIMPLE("The number {0, number, #.#0} is even."), | |
178 UNICODE_STRING_SIMPLE("The number {2, number, #} is even."), | |
179 }; | |
180 UnicodeString checkSyntaxtData[PLURAL_SYNTAX_DATA] = { | |
181 // ICU 4.8 does not check for duplicate keywords any more. | |
182 //UNICODE_STRING_SIMPLE("odd{foo} odd{bar} other{foobar}"), | |
183 //UNICODE_STRING_SIMPLE("odd{foo} other{bar} other{foobar}"), | |
184 UNICODE_STRING_SIMPLE("odd{foo}"), | |
185 // ICU 4.8 does not check for unknown keywords any more. | |
186 //UNICODE_STRING_SIMPLE("otto{foo} other{bar}"), | |
187 UNICODE_STRING_SIMPLE("*odd{foo} other{bar}"), | |
188 UNICODE_STRING_SIMPLE("odd{foo},other{bar}"), | |
189 UNICODE_STRING_SIMPLE("od d{foo} other{bar}"), | |
190 UNICODE_STRING_SIMPLE("odd{foo}{foobar}other{foo}"), | |
191 }; | |
192 | |
193 UErrorCode status = U_ZERO_ERROR; | |
194 UnicodeString oddAndEvenRule = UNICODE_STRING_SIMPLE("odd: n mod 2 is 1"); | |
195 PluralRules* plRules = PluralRules::createRules(oddAndEvenRule, status); | |
196 if (U_FAILURE(status)) { | |
197 dataerrln("ERROR: create PluralRules instance failed in unit tests.- ex
itting"); | |
198 return; | |
199 } | |
200 | |
201 // ======= Test PluralRules pattern syntax. | |
202 logln("Testing PluralRules pattern syntax."); | |
203 for (int32_t i=0; i<PLURAL_SYNTAX_DATA; ++i) { | |
204 status = U_ZERO_ERROR; | |
205 | |
206 PluralFormat plFmt=PluralFormat(*plRules, status); | |
207 if (U_FAILURE(status)) { | |
208 dataerrln("ERROR: PluralFormat constructor failed in unit tests.- e
xitting"); | |
209 return; | |
210 } | |
211 plFmt.applyPattern(checkSyntaxtData[i], status); | |
212 if (U_SUCCESS(status)) { | |
213 errln("ERROR: PluralFormat failed to detect syntax error with patte
rn: "+checkSyntaxtData[i]); | |
214 } | |
215 } | |
216 | |
217 | |
218 | |
219 // ======= Test applying various pattern | |
220 logln("Testing various patterns"); | |
221 status = U_ZERO_ERROR; | |
222 UBool overwrite[PLURAL_PATTERN_DATA] = {FALSE, FALSE, TRUE, TRUE}; | |
223 | |
224 NumberFormat *numFmt = NumberFormat::createInstance(status); | |
225 UnicodeString message=UnicodeString("ERROR: PluralFormat tests various patte
rn ..."); | |
226 if (U_FAILURE(status)) { | |
227 dataerrln("ERROR: Could not create NumberFormat instance with default lo
cale "); | |
228 } | |
229 for(int32_t i=0; i<PLURAL_PATTERN_DATA; ++i) { | |
230 status = U_ZERO_ERROR; | |
231 PluralFormat plFmt=PluralFormat(*plRules, status); | |
232 if (U_FAILURE(status)) { | |
233 dataerrln("ERROR: PluralFormat constructor failed in unit tests.- e
xitting"); | |
234 return; | |
235 } | |
236 plFmt.applyPattern(patternTestData[i], status); | |
237 if (U_FAILURE(status)) { | |
238 errln("ERROR: PluralFormat failed to apply pattern- "+patternTestDa
ta[i]); | |
239 continue; | |
240 } | |
241 numberFormatTest(&plFmt, numFmt, 1, 10, (UnicodeString *)&patternOddTest
Result[i], | |
242 (UnicodeString *)&patternEvenTestResult[i], overwrite[i
], &message); | |
243 } | |
244 delete plRules; | |
245 delete numFmt; | |
246 | |
247 // ======= Test set locale | |
248 status = U_ZERO_ERROR; | |
249 plRules = PluralRules::createRules(UNICODE_STRING_SIMPLE("odd: n mod 2 is 1"
), status); | |
250 PluralFormat pluralFmt = PluralFormat(*plRules, status); | |
251 if (U_FAILURE(status)) { | |
252 dataerrln("ERROR: Could not create PluralFormat instance in setLocale()
test - exitting. "); | |
253 delete plRules; | |
254 return; | |
255 } | |
256 pluralFmt.applyPattern(UNICODE_STRING_SIMPLE("odd{odd} other{even}"), status
); | |
257 pluralFmt.setLocale(Locale::getEnglish(), status); | |
258 if (U_FAILURE(status)) { | |
259 dataerrln("ERROR: Could not setLocale() with English locale "); | |
260 delete plRules; | |
261 return; | |
262 } | |
263 message = UNICODE_STRING_SIMPLE("Error set locale: pattern is not reset!"); | |
264 | |
265 // Check that pattern gets deleted. | |
266 logln("\n Test setLocale() ..\n"); | |
267 numFmt = NumberFormat::createInstance(Locale::getEnglish(), status); | |
268 if (U_FAILURE(status)) { | |
269 dataerrln("ERROR: Could not create NumberFormat instance with English lo
cale "); | |
270 } | |
271 numberFormatTest(&pluralFmt, numFmt, 5, 5, NULL, NULL, FALSE, &message); | |
272 pluralFmt.applyPattern(UNICODE_STRING_SIMPLE("odd__{odd} other{even}"), stat
us); | |
273 if (pluralFmt.format((int32_t)1, status) != UNICODE_STRING_SIMPLE("even")) { | |
274 errln("SetLocale should reset rules but did not."); | |
275 } | |
276 status = U_ZERO_ERROR; | |
277 pluralFmt.applyPattern(UNICODE_STRING_SIMPLE("one{one} other{not one}"), sta
tus); | |
278 if (U_FAILURE(status)) { | |
279 errln("SetLocale should reset rules but did not."); | |
280 } | |
281 UnicodeString one = UNICODE_STRING_SIMPLE("one"); | |
282 UnicodeString notOne = UNICODE_STRING_SIMPLE("not one"); | |
283 UnicodeString plResult, numResult; | |
284 for (int32_t i=0; i<20; ++i) { | |
285 plResult = pluralFmt.format(i, status); | |
286 if ( i==1 ) { | |
287 numResult = one; | |
288 } | |
289 else { | |
290 numResult = notOne; | |
291 } | |
292 if ( numResult != plResult ) { | |
293 errln("Wrong ruleset loaded by setLocale() - got:"+plResult+ Unicode
String(" expecting:")+numResult); | |
294 } | |
295 } | |
296 | |
297 // =========== Test copy constructor | |
298 logln("Test copy constructor and == operator of PluralFormat"); | |
299 PluralFormat dupPFmt = PluralFormat(pluralFmt); | |
300 if (pluralFmt != dupPFmt) { | |
301 errln("Failed in PluralFormat copy constructor or == operator"); | |
302 } | |
303 | |
304 delete plRules; | |
305 delete numFmt; | |
306 } | |
307 | |
308 | |
309 | |
310 /** | |
311 * Test locale data used in PluralFormat class. | |
312 */ | |
313 void | |
314 PluralFormatTest::pluralFormatLocaleTest(/*char *par*/) | |
315 { | |
316 int8_t pluralResults[PLURAL_TEST_ARRAY_SIZE]; // 0: is for default | |
317 | |
318 // ======= Test DefaultRule | |
319 logln("Testing PluralRules with no rule."); | |
320 // for CLDR 24, here delete tr, | |
321 // add id lo ms th zh | |
322 const char* oneRuleLocales[8] = {"id", "ja", "ko", "lo", "ms", "th", "vi", "
zh"}; | |
323 UnicodeString testPattern = UNICODE_STRING_SIMPLE("other{other}"); | |
324 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
325 pluralResults[0]= PFT_OTHER; // other | |
326 helperTestResults(oneRuleLocales, 8, testPattern, pluralResults); | |
327 | |
328 // ====== Test Singular1 locales. | |
329 logln("Testing singular1 locales."); | |
330 // for CLDR 24, here delete da de en et fi gl he it nl pt pt sv bn ca gu is
mr pa sw ur zu | |
331 // add hu tr others | |
332 const char* singular1Locales[56] = {"af","asa","az","bem","bez","bg","brx","
chr", | |
333 "ckb","dv","ee","el","eo","es","eu","fo","fur","fy","gsw","h
a", | |
334 "haw","hu","jgo","ka","kk","kl","ks","ku","lb","ml","mn","na
h", | |
335 "nb","ne","nn","no","nr","om","or","pap","ps","rm","rof","sn
", | |
336 "so", "sq","ta","te","tk","tn","tr","ts","vo","wae","xh","xo
g"}; | |
337 testPattern = UNICODE_STRING_SIMPLE("one{one} other{other}"); | |
338 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
339 pluralResults[0]= PFT_OTHER; | |
340 pluralResults[1]= PFT_ONE; | |
341 pluralResults[2]= PFT_OTHER; | |
342 helperTestResults(singular1Locales, 56, testPattern, pluralResults); | |
343 | |
344 // ======== Test Singular01 locales. | |
345 logln("Testing singular1 locales."); | |
346 // for CLDR 24, here add hy | |
347 const char* singular01Locales[4] = {"ff","fr","hy","kab"}; | |
348 testPattern = UNICODE_STRING_SIMPLE("one{one} other{other}"); | |
349 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
350 pluralResults[0]= PFT_ONE; | |
351 pluralResults[2]= PFT_OTHER; | |
352 helperTestResults(singular01Locales, 4, testPattern, pluralResults); | |
353 | |
354 // ======== Test ZeroSingular locales. | |
355 logln("Testing singular1 locales."); | |
356 const char* zeroSingularLocales[1] = {"lv"}; | |
357 testPattern = UNICODE_STRING_SIMPLE("zero{zero} one{one} other{other}"); | |
358 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
359 pluralResults[0]= PFT_ZERO; | |
360 pluralResults[1]= PFT_ONE; | |
361 for (int32_t i=2; i<20; ++i) { | |
362 pluralResults[i]= (i < 10)? PFT_OTHER: PFT_ZERO; | |
363 pluralResults[i*10] = PFT_ZERO; | |
364 pluralResults[i*10+1] = PFT_ONE; // note override after loop | |
365 pluralResults[i*10+2] = PFT_OTHER; // note override after loop | |
366 } | |
367 pluralResults[111]= PFT_ZERO; | |
368 pluralResults[112]= PFT_ZERO; | |
369 helperTestResults(zeroSingularLocales, 1, testPattern, pluralResults); | |
370 | |
371 // ======== Test singular dual locales. | |
372 logln("Testing singular1 locales."); | |
373 const char* singularDualLocales[1] = {"ga"}; | |
374 testPattern = UNICODE_STRING_SIMPLE("one{one} two{two} other{other}"); | |
375 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
376 pluralResults[0]= PFT_OTHER; | |
377 pluralResults[1]= PFT_ONE; | |
378 pluralResults[2]= PFT_TWO; | |
379 pluralResults[3]= PFT_OTHER; | |
380 helperTestResults(singularDualLocales, 1, testPattern, pluralResults); | |
381 | |
382 // ======== Test Singular Zero Some locales. | |
383 logln("Testing singular1 locales."); | |
384 const char* singularZeroSomeLocales[1] = {"ro"}; | |
385 testPattern = UNICODE_STRING_SIMPLE("few{few} one{one} other{other}"); | |
386 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
387 pluralResults[0]= PFT_FEW; | |
388 for (int32_t i=1; i<20; ++i) { | |
389 pluralResults[i] = PFT_FEW; // note override after loop | |
390 pluralResults[100+i] = PFT_FEW; | |
391 } | |
392 pluralResults[1]= PFT_ONE; | |
393 helperTestResults(singularZeroSomeLocales, 1, testPattern, pluralResults); | |
394 | |
395 // ======== Test Special 12/19. | |
396 logln("Testing special 12 and 19."); | |
397 const char* special12_19Locales[1] = {"lt"}; | |
398 testPattern = UNICODE_STRING_SIMPLE("one{one} few{few} other{other}"); | |
399 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
400 pluralResults[0]= PFT_OTHER; | |
401 pluralResults[1]= PFT_ONE; | |
402 for (int32_t i=2; i<20; ++i) { | |
403 pluralResults[i]= (i < 10)? PFT_FEW: PFT_OTHER; | |
404 pluralResults[i*10] = PFT_OTHER; | |
405 if (i==11) continue; | |
406 pluralResults[i*10+1] = PFT_ONE; | |
407 pluralResults[i*10+2] = PFT_FEW; | |
408 } | |
409 helperTestResults(special12_19Locales, 1, testPattern, pluralResults); | |
410 | |
411 // ======== Test Paucal Except 11 14. | |
412 logln("Testing Paucal Except 11 and 14, set A."); | |
413 const char* paucal01LocalesA[2] = {"hr","sr"}; | |
414 testPattern = UNICODE_STRING_SIMPLE("one{one} few{few} other{other}"); | |
415 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
416 pluralResults[0]= PFT_OTHER; | |
417 pluralResults[1]= PFT_ONE; | |
418 for (int32_t i=2; i<20; ++i) { | |
419 pluralResults[i]= (i < 5)? PFT_FEW: PFT_OTHER; | |
420 if (i==11) continue; | |
421 pluralResults[i*10+1] = PFT_ONE; | |
422 pluralResults[i*10+2] = PFT_FEW; | |
423 pluralResults[i*10+5] = PFT_OTHER; | |
424 pluralResults[i*10+6] = PFT_OTHER; | |
425 pluralResults[i*10+7] = PFT_OTHER; | |
426 pluralResults[i*10+8] = PFT_OTHER; | |
427 pluralResults[i*10+9] = PFT_OTHER; | |
428 } | |
429 helperTestResults(paucal01LocalesA, 2, testPattern, pluralResults); | |
430 | |
431 logln("Testing Paucal Except 11 and 14, set B."); | |
432 const char* paucal01LocalesB[1] = {"ru"}; | |
433 testPattern = UNICODE_STRING_SIMPLE("one{one} many{many} other{other}"); | |
434 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
435 pluralResults[0]= PFT_MANY; | |
436 pluralResults[1]= PFT_ONE; | |
437 for (int32_t i=2; i<20; ++i) { | |
438 pluralResults[i]= (i < 5)? PFT_OTHER: PFT_MANY; | |
439 if (i==11) continue; | |
440 pluralResults[i*10] = PFT_MANY; | |
441 pluralResults[i*10+1] = PFT_ONE; | |
442 pluralResults[i*10+2] = PFT_OTHER; | |
443 pluralResults[i*10+5] = PFT_MANY; | |
444 pluralResults[i*10+6] = PFT_MANY; | |
445 pluralResults[i*10+7] = PFT_MANY; | |
446 pluralResults[i*10+8] = PFT_MANY; | |
447 pluralResults[i*10+9] = PFT_MANY; | |
448 } | |
449 helperTestResults(paucal01LocalesB, 1, testPattern, pluralResults); | |
450 | |
451 logln("Testing Paucal Except 11 and 14, set C."); | |
452 const char* paucal01LocalesC[1] = {"uk"}; | |
453 testPattern = UNICODE_STRING_SIMPLE("one{one} many{many} few{few} other{othe
r}"); | |
454 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
455 pluralResults[0]= PFT_MANY; | |
456 pluralResults[1]= PFT_ONE; | |
457 for (int32_t i=2; i<20; ++i) { | |
458 pluralResults[i]= (i < 5)? PFT_FEW: PFT_MANY; | |
459 if (i==11) continue; | |
460 pluralResults[i*10] = PFT_MANY; | |
461 pluralResults[i*10+1] = PFT_ONE; | |
462 pluralResults[i*10+2] = PFT_FEW; | |
463 pluralResults[i*10+5] = PFT_MANY; | |
464 pluralResults[i*10+6] = PFT_MANY; | |
465 pluralResults[i*10+7] = PFT_MANY; | |
466 pluralResults[i*10+8] = PFT_MANY; | |
467 pluralResults[i*10+9] = PFT_MANY; | |
468 } | |
469 helperTestResults(paucal01LocalesC, 1, testPattern, pluralResults); | |
470 | |
471 // ======== Test Singular Paucal. | |
472 logln("Testing Singular Paucal."); | |
473 const char* singularPaucalLocales[2] = {"cs","sk"}; | |
474 testPattern = UNICODE_STRING_SIMPLE("one{one} few{few} other{other}"); | |
475 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
476 pluralResults[0]= PFT_OTHER; | |
477 pluralResults[1]= PFT_ONE; | |
478 pluralResults[2]= PFT_FEW; | |
479 pluralResults[5]= PFT_OTHER; | |
480 helperTestResults(singularPaucalLocales, 2, testPattern, pluralResults); | |
481 | |
482 // ======== Test Paucal (1), (2,3,4). | |
483 logln("Testing Paucal (1), (2,3,4)."); | |
484 const char* paucal02Locales[1] = {"pl"}; | |
485 testPattern = UNICODE_STRING_SIMPLE("one{one} many{many} few{few} other{othe
r}"); | |
486 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
487 for (int32_t i=0; i<20; ++i) { | |
488 pluralResults[i*10+0] = PFT_MANY; | |
489 pluralResults[i*10+1] = PFT_MANY; // note override after loop | |
490 if ((i==1)||(i==11)) { | |
491 pluralResults[i*10+2] = PFT_MANY; | |
492 pluralResults[i*10+3] = PFT_MANY; | |
493 pluralResults[i*10+4] = PFT_MANY; | |
494 } | |
495 else { | |
496 pluralResults[i*10+2] = PFT_FEW; | |
497 pluralResults[i*10+3] = PFT_FEW; | |
498 pluralResults[i*10+4] = PFT_FEW; | |
499 } | |
500 pluralResults[i*10+5] = PFT_MANY; | |
501 } | |
502 pluralResults[1]= PFT_ONE; | |
503 helperTestResults(paucal02Locales, 1, testPattern, pluralResults); | |
504 | |
505 // ======== Test Paucal (1), (2), (3,4). | |
506 logln("Testing Paucal (1), (2), (3,4)."); | |
507 const char* paucal03Locales[1] = {"sl"}; | |
508 testPattern = UNICODE_STRING_SIMPLE("one{one} two{two} few{few} other{other}
"); | |
509 uprv_memset(pluralResults, -1, sizeof(pluralResults)); | |
510 pluralResults[0]= PFT_OTHER; | |
511 pluralResults[1]= PFT_ONE; | |
512 pluralResults[2]= PFT_TWO; | |
513 pluralResults[3]= PFT_FEW; | |
514 pluralResults[5]= PFT_OTHER; | |
515 pluralResults[101]= PFT_ONE; | |
516 pluralResults[102]= PFT_TWO; | |
517 pluralResults[103]= PFT_FEW; | |
518 pluralResults[105]= PFT_OTHER; | |
519 helperTestResults(paucal03Locales, 1, testPattern, pluralResults); | |
520 | |
521 // TODO: move this test to Unit Test after CLDR 1.6 is final and we support
float | |
522 // ======= Test French "WITHIN rule | |
523 logln("Testing PluralRules with fr rule."); | |
524 testPattern = UNICODE_STRING_SIMPLE("one{one} other{other}"); | |
525 Locale ulocale((const char *)"fr"); | |
526 UErrorCode status = U_ZERO_ERROR; | |
527 PluralFormat plFmt(ulocale, testPattern, status); | |
528 if (U_FAILURE(status)) { | |
529 dataerrln("Failed to apply pattern to fr locale - %s", u_errorName(statu
s)); | |
530 } | |
531 else { | |
532 status = U_ZERO_ERROR; | |
533 UnicodeString plResult = plFmt.format(0.0, status); // retrun ONE | |
534 plResult = plFmt.format(0.5, status); // retrun ONE | |
535 plResult = plFmt.format(1.0, status); // retrun ONE | |
536 plResult = plFmt.format(1.9, status); // retrun ONE | |
537 plResult = plFmt.format(2.0, status); // retrun OTHER | |
538 } | |
539 } | |
540 | |
541 void | |
542 PluralFormatTest::pluralFormatExtendedTest(void) { | |
543 const char *targets[] = { | |
544 "There are no widgets.", | |
545 "There is one widget.", | |
546 "There is a bling widget and one other widget.", | |
547 "There is a bling widget and 2 other widgets.", | |
548 "There is a bling widget and 3 other widgets.", | |
549 "Widgets, five (5-1=4) there be.", | |
550 "There is a bling widget and 5 other widgets.", | |
551 "There is a bling widget and 6 other widgets.", | |
552 }; | |
553 | |
554 const char* fmt = | |
555 "offset:1.0 " | |
556 "=0 {There are no widgets.} " | |
557 "=1.0 {There is one widget.} " | |
558 "=5 {Widgets, five (5-1=#) there be.} " | |
559 "one {There is a bling widget and one other widget.} " | |
560 "other {There is a bling widget and # other widgets.}"; | |
561 | |
562 UErrorCode status = U_ZERO_ERROR; | |
563 UnicodeString fmtString(fmt, -1, US_INV); | |
564 PluralFormat pf(Locale::getEnglish(), fmtString, status); | |
565 MessageFormat mf(UNICODE_STRING_SIMPLE("{0,plural,").append(fmtString).append(
(UChar)0x7d /* '}' */), | |
566 Locale::getEnglish(), status); | |
567 Formattable args; | |
568 FieldPosition ignore; | |
569 if (U_FAILURE(status)) { | |
570 dataerrln("Failed to apply pattern - %s", u_errorName(status)); | |
571 return; | |
572 } | |
573 for (int32_t i = 0; i <= 7; ++i) { | |
574 UnicodeString result = pf.format(i, status); | |
575 if (U_FAILURE(status)) { | |
576 errln("PluralFormat.format(value %d) failed - %s", i, u_errorName(status))
; | |
577 return; | |
578 } | |
579 UnicodeString expected(targets[i], -1, US_INV); | |
580 if (expected != result) { | |
581 UnicodeString message("PluralFormat.format(): Expected '", -1, US_INV); | |
582 message.append(expected); | |
583 message.append(UnicodeString("' but got '", -1, US_INV)); | |
584 message.append(result); | |
585 message.append("'", -1, US_INV); | |
586 errln(message); | |
587 } | |
588 args.setLong(i); | |
589 mf.format(&args, 1, result.remove(), ignore, status); | |
590 if (U_FAILURE(status)) { | |
591 errln("MessageFormat.format(value %d) failed - %s", i, u_errorName(status)
); | |
592 return; | |
593 } | |
594 if (expected != result) { | |
595 UnicodeString message("MessageFormat.format(): Expected '", -1, US_INV); | |
596 message.append(expected); | |
597 message.append(UnicodeString("' but got '", -1, US_INV)); | |
598 message.append(result); | |
599 message.append("'", -1, US_INV); | |
600 errln(message); | |
601 } | |
602 } | |
603 } | |
604 | |
605 void | |
606 PluralFormatTest::pluralFormatExtendedParseTest(void) { | |
607 const char *failures[] = { | |
608 "offset:1..0 =0 {Foo}", | |
609 "offset:1.0 {Foo}", | |
610 "=0= {Foo}", | |
611 "=0 {Foo} =0.0 {Bar}", | |
612 " = {Foo}", | |
613 }; | |
614 int len = sizeof(failures)/sizeof(failures[0]); | |
615 | |
616 for (int i = 0; i < len; ++i) { | |
617 UErrorCode status = U_ZERO_ERROR; | |
618 UnicodeString fmt(failures[i], -1, US_INV); | |
619 PluralFormat pf(fmt, status); | |
620 if (U_SUCCESS(status)) { | |
621 errln("expected failure when parsing '" + fmt + "'"); | |
622 } | |
623 } | |
624 } | |
625 | |
626 void | |
627 PluralFormatTest::ordinalFormatTest(void) { | |
628 IcuTestErrorCode errorCode(*this, "ordinalFormatTest"); | |
629 UnicodeString pattern("one{#st file}two{#nd file}few{#rd file}other{#th file
}"); | |
630 PluralFormat pf(Locale::getEnglish(), UPLURAL_TYPE_ORDINAL, pattern, errorCo
de); | |
631 if (errorCode.logDataIfFailureAndReset("PluralFormat(en, UPLURAL_TYPE_ORDINA
L, pattern) failed")) { | |
632 return; | |
633 } | |
634 UnicodeString result = pf.format((int32_t)321, errorCode); | |
635 if (!errorCode.logIfFailureAndReset("PluralFormat.format(321) failed") && | |
636 result != UNICODE_STRING_SIMPLE("321st file")) { | |
637 errln(UnicodeString("PluralFormat.format(321) wrong result string: ") + re
sult); | |
638 } | |
639 result = pf.format((int32_t)22, errorCode); | |
640 if (!errorCode.logIfFailureAndReset("PluralFormat.format(22) failed") && | |
641 result != UNICODE_STRING_SIMPLE("22nd file")) { | |
642 errln(UnicodeString("PluralFormat.format(22) wrong result string: ") + res
ult); | |
643 } | |
644 result = pf.format((int32_t)3, errorCode); | |
645 if (!errorCode.logIfFailureAndReset("PluralFormat.format(3) failed") && | |
646 result != UNICODE_STRING_SIMPLE("3rd file")) { | |
647 errln(UnicodeString("PluralFormat.format(3) wrong result string: ") + resu
lt); | |
648 } | |
649 | |
650 // Code coverage: Use the other new-for-UPluralType constructor as well. | |
651 PluralFormat pf2(Locale::getEnglish(), UPLURAL_TYPE_ORDINAL, errorCode); | |
652 pf2.applyPattern(pattern, errorCode); | |
653 if (errorCode.logIfFailureAndReset("PluralFormat(en, UPLURAL_TYPE_ORDINAL, p
attern) failed")) { | |
654 return; | |
655 } | |
656 result = pf2.format((int32_t)456, errorCode); | |
657 if (!errorCode.logIfFailureAndReset("PluralFormat.format(456) failed") && | |
658 result != UNICODE_STRING_SIMPLE("456th file")) { | |
659 errln(UnicodeString("PluralFormat.format(456) wrong result string: ") + re
sult); | |
660 } | |
661 result = pf2.format((int32_t)111, errorCode); | |
662 if (!errorCode.logIfFailureAndReset("PluralFormat.format(111) failed") && | |
663 result != UNICODE_STRING_SIMPLE("111th file")) { | |
664 errln(UnicodeString("PluralFormat.format(111) wrong result string: ") + re
sult); | |
665 } | |
666 } | |
667 | |
668 void | |
669 PluralFormatTest::TestDecimals() { | |
670 IcuTestErrorCode errorCode(*this, "TestDecimals"); | |
671 // Simple number replacement. | |
672 PluralFormat pf(Locale::getEnglish(), "one{one meter}other{# meters}", error
Code); | |
673 assertEquals("simple format(1)", "one meter", pf.format((int32_t)1, errorCod
e), TRUE); | |
674 assertEquals("simple format(1.5)", "1.5 meters", pf.format(1.5, errorCode),
TRUE); | |
675 PluralFormat pf2(Locale::getEnglish(), | |
676 "offset:1 one{another meter}other{another # meters}", errorCode); | |
677 DecimalFormat df("0.0", new DecimalFormatSymbols(Locale::getEnglish(), error
Code), errorCode); | |
678 pf2.setNumberFormat(&df, errorCode); | |
679 assertEquals("offset-decimals format(1)", "another 0.0 meters", pf2.format((
int32_t)1, errorCode), TRUE); | |
680 assertEquals("offset-decimals format(2)", "another 1.0 meters", pf2.format((
int32_t)2, errorCode), TRUE); | |
681 assertEquals("offset-decimals format(2.5)", "another 1.5 meters", pf2.format
(2.5, errorCode), TRUE); | |
682 errorCode.reset(); | |
683 } | |
684 | |
685 void | |
686 PluralFormatTest::numberFormatTest(PluralFormat* plFmt, | |
687 NumberFormat *numFmt, | |
688 int32_t start, | |
689 int32_t end, | |
690 UnicodeString *numOddAppendStr, | |
691 UnicodeString *numEvenAppendStr, | |
692 UBool overwrite, // overwrite the numberForm
at.format result | |
693 UnicodeString *message) { | |
694 UErrorCode status = U_ZERO_ERROR; | |
695 | |
696 if ( (plFmt==NULL) || (numFmt==NULL) ) { | |
697 dataerrln("ERROR: Could not create PluralFormat or NumberFormat - exitti
ng"); | |
698 return; | |
699 } | |
700 UnicodeString plResult, numResult ; | |
701 | |
702 for (int32_t i=start; i<= end; ++i ) { | |
703 numResult.remove(); | |
704 numResult = numFmt->format(i, numResult); | |
705 plResult = plFmt->format(i, status); | |
706 if ((numOddAppendStr!= NULL)&&(numEvenAppendStr!=NULL)) { | |
707 if (overwrite) { | |
708 if (i&1) { | |
709 numResult = *numOddAppendStr; | |
710 } | |
711 else { | |
712 numResult = *numEvenAppendStr; | |
713 } | |
714 } | |
715 else { // Append the string | |
716 if (i&1) { | |
717 numResult += *numOddAppendStr; | |
718 } | |
719 else{ | |
720 numResult += *numEvenAppendStr; | |
721 } | |
722 } | |
723 } | |
724 if ( (numResult!=plResult) || U_FAILURE(status) ) { | |
725 if ( message == NULL ) { | |
726 errln("ERROR: Unexpected plural format - got:"+plResult+ Unicode
String(" expecting:")+numResult); | |
727 } | |
728 else { | |
729 errln( *message+UnicodeString(" got:")+plResult+UnicodeString("
expecting:")+numResult); | |
730 } | |
731 } | |
732 } | |
733 return; | |
734 } | |
735 | |
736 | |
737 void | |
738 PluralFormatTest::helperTestResults(const char** localeArray, | |
739 int32_t capacityOfArray, | |
740 UnicodeString& testPattern, | |
741 int8_t *expResults) { | |
742 UErrorCode status; | |
743 UnicodeString plResult; | |
744 const UnicodeString PLKeywordLookups[6] = { | |
745 UNICODE_STRING_SIMPLE("zero"), | |
746 UNICODE_STRING_SIMPLE("one"), | |
747 UNICODE_STRING_SIMPLE("two"), | |
748 UNICODE_STRING_SIMPLE("few"), | |
749 UNICODE_STRING_SIMPLE("many"), | |
750 UNICODE_STRING_SIMPLE("other"), | |
751 }; | |
752 | |
753 for (int32_t i=0; i<capacityOfArray; ++i) { | |
754 const char *locale = localeArray[i]; | |
755 Locale ulocale((const char *)locale); | |
756 status = U_ZERO_ERROR; | |
757 PluralFormat plFmt(ulocale, testPattern, status); | |
758 if (U_FAILURE(status)) { | |
759 dataerrln("Failed to apply pattern to locale:"+UnicodeString(localeA
rray[i]) + " - " + u_errorName(status)); | |
760 continue; | |
761 } | |
762 for (int32_t n=0; n<PLURAL_TEST_ARRAY_SIZE; ++n) { | |
763 if (expResults[n]!=-1) { | |
764 status = U_ZERO_ERROR; | |
765 plResult = plFmt.format(n, status); | |
766 if (U_FAILURE(status)) { | |
767 errln("ERROR: Failed to format number in locale data tests w
ith locale: "+ | |
768 UnicodeString(localeArray[i])); | |
769 } | |
770 if (plResult != PLKeywordLookups[expResults[n]]){ | |
771 plResult = plFmt.format(n, status); | |
772 errln("ERROR: Unexpected format result in locale: "+UnicodeS
tring(localeArray[i])+ | |
773 UnicodeString(" for value: ")+n+ | |
774 UnicodeString(" got:")+plResult+ | |
775 UnicodeString(" expecting:")+ PLKeywordLookups[expRes
ults[n]]); | |
776 } | |
777 } | |
778 } | |
779 } | |
780 } | |
781 | |
782 #endif /* #if !UCONFIG_NO_FORMATTING */ | |
OLD | NEW |