Home | History | Annotate | Download | only in intltest
      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* &name, 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 locale ");
     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, &message);
     84             numberFormatTest(plFmt[i], numFmt, 100, 112, NULL, NULL, FALSE, &message);
     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_errorName(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(status[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{The number {0, number, #.#0} is even.}"),
    166         UNICODE_STRING_SIMPLE("odd{The number {1, number, #} is odd.}other{The number {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.- exitting");
    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.- exitting");
    209             return;
    210         }
    211         plFmt.applyPattern(checkSyntaxtData[i], status);
    212         if (U_SUCCESS(status)) {
    213             errln("ERROR:  PluralFormat failed to detect syntax error with pattern: "+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 pattern ...");
    226     if (U_FAILURE(status)) {
    227         dataerrln("ERROR: Could not create NumberFormat instance with default locale ");
    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.- exitting");
    234             return;
    235         }
    236         plFmt.applyPattern(patternTestData[i], status);
    237         if (U_FAILURE(status)) {
    238             errln("ERROR:  PluralFormat failed to apply pattern- "+patternTestData[i]);
    239             continue;
    240         }
    241         numberFormatTest(&plFmt, numFmt, 1, 10, (UnicodeString *)&patternOddTestResult[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 locale ");
    270     }
    271     numberFormatTest(&pluralFmt, numFmt, 5, 5, NULL, NULL, FALSE, &message);
    272     pluralFmt.applyPattern(UNICODE_STRING_SIMPLE("odd__{odd} other{even}"), status);
    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}"), status);
    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+ UnicodeString("  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","ha",
    334                     "haw","hu","jgo","ka","kk","kl","ks","ku","lb","ml","mn","nah",
    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","xog"};
    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{other}");
    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{other}");
    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(status));
    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, errorCode);
    631     if (errorCode.logDataIfFailureAndReset("PluralFormat(en, UPLURAL_TYPE_ORDINAL, 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: ") + result);
    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: ") + result);
    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: ") + result);
    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, pattern) 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: ") + result);
    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: ") + result);
    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}", errorCode);
    673     assertEquals("simple format(1)", "one meter", pf.format((int32_t)1, errorCode), 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(), errorCode), 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 numberFormat.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 - exitting");
    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+ UnicodeString("  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(localeArray[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 with 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: "+UnicodeString(localeArray[i])+
    773                           UnicodeString(" for value: ")+n+
    774                           UnicodeString("  got:")+plResult+
    775                           UnicodeString("  expecting:")+ PLKeywordLookups[expResults[n]]);
    776                 }
    777             }
    778         }
    779     }
    780 }
    781 
    782 #endif /* #if !UCONFIG_NO_FORMATTING */
    783