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
31void 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 */
48void 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 */
158void 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 */
311void
312PluralFormatTest::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
498void
499PluralFormatTest::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
562void
563PluralFormatTest::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
583void
584PluralFormatTest::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
636void
637PluralFormatTest::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