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