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