Home | History | Annotate | Download | only in intltest
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2010, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************
      6  * File TMSGFMT.CPP
      7  *
      8  * Modification History:
      9  *
     10  *   Date        Name        Description
     11  *   03/24/97    helena      Converted from Java.
     12  *   07/11/97    helena      Updated to work on AIX.
     13  *   08/04/97    jfitz       Updated to intltest
     14  *******************************************************************/
     15 
     16 #include "unicode/utypes.h"
     17 
     18 #if !UCONFIG_NO_FORMATTING
     19 
     20 #include "tmsgfmt.h"
     21 
     22 #include "unicode/format.h"
     23 #include "unicode/decimfmt.h"
     24 #include "unicode/locid.h"
     25 #include "unicode/msgfmt.h"
     26 #include "unicode/numfmt.h"
     27 #include "unicode/choicfmt.h"
     28 #include "unicode/selfmt.h"
     29 #include "unicode/gregocal.h"
     30 #include <stdio.h>
     31 
     32 #define E_WITH_ACUTE ((char)0x00E9)
     33 static const char E_ACCENTED[]={E_WITH_ACUTE,0};
     34 
     35 void
     36 TestMessageFormat::runIndexedTest(int32_t index, UBool exec,
     37                                   const char* &name, char* /*par*/) {
     38     switch (index) {
     39         TESTCASE(0,testBug1);
     40         TESTCASE(1,testBug2);
     41         TESTCASE(2,sample);
     42         TESTCASE(3,PatternTest);
     43         TESTCASE(4,testStaticFormat);
     44         TESTCASE(5,testSimpleFormat);
     45         TESTCASE(6,testMsgFormatChoice);
     46         TESTCASE(7,testCopyConstructor);
     47         TESTCASE(8,testAssignment);
     48         TESTCASE(9,testClone);
     49         TESTCASE(10,testEquals);
     50         TESTCASE(11,testNotEquals);
     51         TESTCASE(12,testSetLocale);
     52         TESTCASE(13,testFormat);
     53         TESTCASE(14,testParse);
     54         TESTCASE(15,testAdopt);
     55         TESTCASE(16,testCopyConstructor2);
     56         TESTCASE(17,TestUnlimitedArgsAndSubformats);
     57         TESTCASE(18,TestRBNF);
     58         TESTCASE(19,TestTurkishCasing);
     59         TESTCASE(20,testAutoQuoteApostrophe);
     60         TESTCASE(21,testMsgFormatPlural);
     61         TESTCASE(22,testCoverage);
     62         TESTCASE(23,testMsgFormatSelect);
     63         default: name = ""; break;
     64     }
     65 }
     66 
     67 void TestMessageFormat::testBug3()
     68 {
     69     double myNumber = -123456;
     70     DecimalFormat *form = 0;
     71     Locale locale[] = {
     72         Locale("ar", "", ""),
     73         Locale("be", "", ""),
     74         Locale("bg", "", ""),
     75         Locale("ca", "", ""),
     76         Locale("cs", "", ""),
     77         Locale("da", "", ""),
     78         Locale("de", "", ""),
     79         Locale("de", "AT", ""),
     80         Locale("de", "CH", ""),
     81         Locale("el", "", ""),       // 10
     82         Locale("en", "CA", ""),
     83         Locale("en", "GB", ""),
     84         Locale("en", "IE", ""),
     85         Locale("en", "US", ""),
     86         Locale("es", "", ""),
     87         Locale("et", "", ""),
     88         Locale("fi", "", ""),
     89         Locale("fr", "", ""),
     90         Locale("fr", "BE", ""),
     91         Locale("fr", "CA", ""),     // 20
     92         Locale("fr", "CH", ""),
     93         Locale("he", "", ""),
     94         Locale("hr", "", ""),
     95         Locale("hu", "", ""),
     96         Locale("is", "", ""),
     97         Locale("it", "", ""),
     98         Locale("it", "CH", ""),
     99         Locale("ja", "", ""),
    100         Locale("ko", "", ""),
    101         Locale("lt", "", ""),       // 30
    102         Locale("lv", "", ""),
    103         Locale("mk", "", ""),
    104         Locale("nl", "", ""),
    105         Locale("nl", "BE", ""),
    106         Locale("no", "", ""),
    107         Locale("pl", "", ""),
    108         Locale("pt", "", ""),
    109         Locale("ro", "", ""),
    110         Locale("ru", "", ""),
    111         Locale("sh", "", ""),       // 40
    112         Locale("sk", "", ""),
    113         Locale("sl", "", ""),
    114         Locale("sq", "", ""),
    115         Locale("sr", "", ""),
    116         Locale("sv", "", ""),
    117         Locale("tr", "", ""),
    118         Locale("uk", "", ""),
    119         Locale("zh", "", ""),
    120         Locale("zh", "TW", "")      // 49
    121     };
    122     int32_t i;
    123     for (i= 0; i < 49; i++) {
    124         UnicodeString buffer;
    125         logln(locale[i].getDisplayName(buffer));
    126         UErrorCode success = U_ZERO_ERROR;
    127 //        form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
    128         form = (DecimalFormat*)NumberFormat::createInstance(locale[i], success);
    129         if (U_FAILURE(success)) {
    130             errln("Err: Number Format ");
    131             logln("Number format creation failed.");
    132             continue;
    133         }
    134         Formattable result;
    135         FieldPosition pos(0);
    136         buffer.remove();
    137         form->format(myNumber, buffer, pos);
    138         success = U_ZERO_ERROR;
    139         ParsePosition parsePos;
    140         form->parse(buffer, result, parsePos);
    141         logln(UnicodeString(" -> ") /* + << dec*/ + toString(result) + UnicodeString("[supposed output for result]"));
    142         if (U_FAILURE(success)) {
    143             errln("Err: Number Format parse");
    144             logln("Number format parse failed.");
    145         }
    146         delete form;
    147     }
    148 }
    149 
    150 void TestMessageFormat::testBug1()
    151 {
    152     const double limit[] = {0.0, 1.0, 2.0};
    153     const UnicodeString formats[] = {"0.0<=Arg<1.0",
    154                                "1.0<=Arg<2.0",
    155                                "2.0<-Arg"};
    156     ChoiceFormat *cf = new ChoiceFormat(limit, formats, 3);
    157     FieldPosition status(0);
    158     UnicodeString toAppendTo;
    159     cf->format((int32_t)1, toAppendTo, status);
    160     if (toAppendTo != "1.0<=Arg<2.0") {
    161         errln("ChoiceFormat cmp in testBug1");
    162     }
    163     logln(toAppendTo);
    164     delete cf;
    165 }
    166 
    167 void TestMessageFormat::testBug2()
    168 {
    169     UErrorCode status = U_ZERO_ERROR;
    170     UnicodeString result;
    171     // {sfb} use double format in pattern, so result will match (not strictly necessary)
    172     const UnicodeString pattern = "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
    173     logln("The input pattern : " + pattern);
    174     MessageFormat *fmt = new MessageFormat(pattern, status);
    175     if (U_FAILURE(status)) {
    176         errln("MessageFormat pattern creation failed.");
    177         return;
    178     }
    179     logln("The output pattern is : " + fmt->toPattern(result));
    180     if (pattern != result) {
    181         errln("MessageFormat::toPattern() failed.");
    182     }
    183     delete fmt;
    184 }
    185 
    186 #if 0
    187 #if defined(_DEBUG) && U_IOSTREAM_SOURCE!=0
    188 //----------------------------------------------------
    189 // console I/O
    190 //----------------------------------------------------
    191 
    192 #if U_IOSTREAM_SOURCE >= 199711
    193 #   include <iostream>
    194     std::ostream& operator<<(std::ostream& stream,  const Formattable&   obj);
    195 #elif U_IOSTREAM_SOURCE >= 198506
    196 #   include <iostream.h>
    197     ostream& operator<<(ostream& stream,  const Formattable&   obj);
    198 #endif
    199 
    200 #include "unicode/datefmt.h"
    201 #include <stdlib.h>
    202 #include <string.h>
    203 
    204 IntlTest&
    205 operator<<( IntlTest&           stream,
    206             const Formattable&  obj)
    207 {
    208     static DateFormat *defDateFormat = 0;
    209 
    210     UnicodeString buffer;
    211     switch(obj.getType()) {
    212         case Formattable::kDate :
    213             if (defDateFormat == 0) {
    214                 defDateFormat = DateFormat::createInstance();
    215             }
    216             defDateFormat->format(obj.getDate(), buffer);
    217             stream << buffer;
    218             break;
    219         case Formattable::kDouble :
    220             char convert[20];
    221             sprintf( convert, "%lf", obj.getDouble() );
    222             stream << convert << "D";
    223             break;
    224         case Formattable::kLong :
    225             stream << obj.getLong() << "L";
    226             break;
    227         case Formattable::kString:
    228             stream << "\"" << obj.getString(buffer) << "\"";
    229             break;
    230         case Formattable::kArray:
    231             int32_t i, count;
    232             const Formattable* array;
    233             array = obj.getArray(count);
    234             stream << "[";
    235             for (i=0; i<count; ++i) stream << array[i] << ( (i==(count-1)) ? "" : ", " );
    236             stream << "]";
    237             break;
    238         default:
    239             stream << "INVALID_Formattable";
    240     }
    241     return stream;
    242 }
    243 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE!=0 */
    244 #endif
    245 
    246 void TestMessageFormat::PatternTest()
    247 {
    248     Formattable testArgs[] = {
    249         Formattable(double(1)), Formattable(double(3456)),
    250             Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate)
    251     };
    252     UnicodeString testCases[] = {
    253        "Quotes '', '{', 'a' {0} '{0}'",
    254        "Quotes '', '{', 'a' {0,number} '{0}'",
    255        "'{'1,number,'#',##} {1,number,'#',##}",
    256        "There are {1} files on {2} at {3}.",
    257        "On {2}, there are {1} files, with {0,number,currency}.",
    258        "'{1,number,percent}', {1,number,percent},",
    259        "'{1,date,full}', {1,date,full},",
    260        "'{3,date,full}', {3,date,full},",
    261        "'{1,number,#,##}' {1,number,#,##}",
    262     };
    263 
    264     UnicodeString testResultPatterns[] = {
    265         "Quotes '', '{', a {0} '{'0}",
    266         "Quotes '', '{', a {0,number} '{'0}",
    267         "'{'1,number,#,##} {1,number,'#'#,##}",
    268         "There are {1} files on {2} at {3}.",
    269         "On {2}, there are {1} files, with {0,number,currency}.",
    270         "'{'1,number,percent}, {1,number,percent},",
    271         "'{'1,date,full}, {1,date,full},",
    272         "'{'3,date,full}, {3,date,full},",
    273         "'{'1,number,#,##} {1,number,#,##}"
    274     };
    275 
    276     UnicodeString testResultStrings[] = {
    277         "Quotes ', {, a 1 {0}",
    278         "Quotes ', {, a 1 {0}",
    279         "{1,number,#,##} #34,56",
    280         "There are 3,456 files on Disk at 1/12/70 5:46 AM.",
    281         "On Disk, there are 3,456 files, with $1.00.",
    282         "{1,number,percent}, 345,600%,",
    283         "{1,date,full}, Wednesday, December 31, 1969,",
    284         "{3,date,full}, Monday, January 12, 1970,",
    285         "{1,number,#,##} 34,56"
    286     };
    287 
    288 
    289     for (int32_t i = 0; i < 9; ++i) {
    290         //it_out << "\nPat in:  " << testCases[i]);
    291 
    292         MessageFormat *form = 0;
    293         UErrorCode success = U_ZERO_ERROR;
    294         UnicodeString buffer;
    295         form = new MessageFormat(testCases[i], Locale::getUS(), success);
    296         if (U_FAILURE(success)) {
    297             dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success));
    298             logln(((UnicodeString)"MessageFormat for ") + testCases[i] + " creation failed.\n");
    299             continue;
    300         }
    301         if (form->toPattern(buffer) != testResultPatterns[i]) {
    302             errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i);
    303             //form->toPattern(buffer);
    304             errln(((UnicodeString)" Orig: ") + testCases[i]);
    305             errln(((UnicodeString)" Exp:  ") + testResultPatterns[i]);
    306             errln(((UnicodeString)" Got:  ") + buffer);
    307         }
    308 
    309         //it_out << "Pat out: " << form->toPattern(buffer));
    310         UnicodeString result;
    311         int32_t count = 4;
    312         FieldPosition fieldpos(0);
    313         form->format(testArgs, count, result, fieldpos, success);
    314         if (U_FAILURE(success)) {
    315             dataerrln("MessageFormat failed test #3 - %s", u_errorName(success));
    316             logln("TestMessageFormat::PatternTest failed test #3");
    317             continue;
    318         }
    319         if (result != testResultStrings[i]) {
    320             errln("TestMessageFormat::PatternTest failed test #4");
    321             logln("TestMessageFormat::PatternTest failed #4.");
    322             logln(UnicodeString("    Result: ") + result );
    323             logln(UnicodeString("  Expected: ") + testResultStrings[i] );
    324         }
    325 
    326 
    327         //it_out << "Result:  " << result);
    328 #if 0
    329         /* TODO: Look at this test and see if this is still a valid test */
    330         logln("---------------- test parse ----------------");
    331 
    332         form->toPattern(buffer);
    333         logln("MSG pattern for parse: " + buffer);
    334 
    335         int32_t parseCount = 0;
    336         Formattable* values = form->parse(result, parseCount, success);
    337         if (U_FAILURE(success)) {
    338             errln("MessageFormat failed test #5");
    339             logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success);
    340         } else if (parseCount != count) {
    341             errln("MSG count not %d as expected. Got %d", count, parseCount);
    342         }
    343         UBool failed = FALSE;
    344         for (int32_t j = 0; j < parseCount; ++j) {
    345              if (values == 0 || testArgs[j] != values[j]) {
    346                 errln(((UnicodeString)"MSG testargs[") + j + "]: " + toString(testArgs[j]));
    347                 errln(((UnicodeString)"MSG values[") + j + "]  : " + toString(values[j]));
    348                 failed = TRUE;
    349              }
    350         }
    351         if (failed)
    352             errln("MessageFormat failed test #6");
    353 #endif
    354         delete form;
    355     }
    356 }
    357 
    358 void TestMessageFormat::sample()
    359 {
    360     MessageFormat *form = 0;
    361     UnicodeString buffer1, buffer2;
    362     UErrorCode success = U_ZERO_ERROR;
    363     form = new MessageFormat("There are {0} files on {1}", success);
    364     if (U_FAILURE(success)) {
    365         errln("Err: Message format creation failed");
    366         logln("Sample message format creation failed.");
    367         return;
    368     }
    369     UnicodeString abc("abc");
    370     UnicodeString def("def");
    371     Formattable testArgs1[] = { abc, def };
    372     FieldPosition fieldpos(0);
    373     assertEquals("format",
    374                  "There are abc files on def",
    375                  form->format(testArgs1, 2, buffer2, fieldpos, success));
    376     assertSuccess("format", success);
    377     delete form;
    378 }
    379 
    380 void TestMessageFormat::testStaticFormat()
    381 {
    382     UErrorCode err = U_ZERO_ERROR;
    383     Formattable arguments[] = {
    384         (int32_t)7,
    385         Formattable(UDate(8.71068e+011), Formattable::kIsDate),
    386         "a disturbance in the Force"
    387         };
    388 
    389     UnicodeString result;
    390     result = MessageFormat::format(
    391         "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
    392         arguments,
    393         3,
    394         result,
    395         err);
    396 
    397     if (U_FAILURE(err)) {
    398         dataerrln("TestMessageFormat::testStaticFormat #1 - %s", u_errorName(err));
    399         logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err);
    400         return;
    401     }
    402 
    403     const UnicodeString expected(
    404             "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
    405     if (result != expected) {
    406         errln("TestMessageFormat::testStaticFormat failed on test");
    407         logln( UnicodeString("     Result: ") + result );
    408         logln( UnicodeString("   Expected: ") + expected );
    409     }
    410 }
    411 
    412 /* When the default locale is tr, make sure that the pattern can still be parsed. */
    413 void TestMessageFormat::TestTurkishCasing()
    414 {
    415     UErrorCode err = U_ZERO_ERROR;
    416     Locale  saveDefaultLocale;
    417     Locale::setDefault( Locale("tr"), err );
    418 
    419     Formattable arguments[] = {
    420         (int32_t)7,
    421         Formattable(UDate(8.71068e+011), Formattable::kIsDate),
    422         "a disturbance in the Force"
    423         };
    424 
    425     UnicodeString result;
    426     result = MessageFormat::format(
    427         "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
    428         arguments,
    429         3,
    430         result,
    431         err);
    432 
    433     if (U_FAILURE(err)) {
    434         dataerrln("TestTurkishCasing #1 with error code %s", u_errorName(err));
    435         return;
    436     }
    437 
    438     const UnicodeString expected(
    439             "At 12:20:00 on 08.08.1997, there was a disturbance in the Force on planet 7.", "");
    440     if (result != expected) {
    441         errln("TestTurkishCasing failed on test");
    442         errln( UnicodeString("     Result: ") + result );
    443         errln( UnicodeString("   Expected: ") + expected );
    444     }
    445     Locale::setDefault( saveDefaultLocale, err );
    446 }
    447 
    448 void TestMessageFormat::testSimpleFormat(/* char* par */)
    449 {
    450     logln("running TestMessageFormat::testSimpleFormat");
    451 
    452     UErrorCode err = U_ZERO_ERROR;
    453 
    454     Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
    455     Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
    456     Formattable testArgs3[] = {(int32_t)12, "MyDisk"};
    457 
    458     MessageFormat* form = new MessageFormat(
    459         "The disk \"{1}\" contains {0} file(s).", err);
    460 
    461     UnicodeString string;
    462     FieldPosition ignore(FieldPosition::DONT_CARE);
    463     form->format(testArgs1, 2, string, ignore, err);
    464     if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 0 file(s).") {
    465         dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1 - ") + u_errorName(err));
    466     }
    467 
    468     ignore.setField(FieldPosition::DONT_CARE);
    469     string.remove();
    470     form->format(testArgs2, 2, string, ignore, err);
    471     if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 1 file(s).") {
    472         logln(string);
    473         dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string + " - " + u_errorName(err));
    474     }
    475 
    476     ignore.setField(FieldPosition::DONT_CARE);
    477     string.remove();
    478     form->format(testArgs3, 2, string, ignore, err);
    479     if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 12 file(s).") {
    480         dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string + " - " + u_errorName(err));
    481     }
    482 
    483     delete form;
    484  }
    485 
    486 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
    487 {
    488     logln("running TestMessageFormat::testMsgFormatChoice");
    489 
    490     UErrorCode err = U_ZERO_ERROR;
    491 
    492     MessageFormat* form = new MessageFormat("The disk \"{1}\" contains {0}.", err);
    493     double filelimits[] = {0,1,2};
    494     UnicodeString filepart[] = {"no files","one file","{0,number} files"};
    495     ChoiceFormat* fileform = new ChoiceFormat(filelimits, filepart, 3);
    496     form->setFormat(1,*fileform); // NOT zero, see below
    497         //is the format adopted?
    498 
    499     FieldPosition ignore(FieldPosition::DONT_CARE);
    500     UnicodeString string;
    501     Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
    502     form->format(testArgs1, 2, string, ignore, err);
    503     if (string != "The disk \"MyDisk\" contains no files.") {
    504         errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
    505     }
    506 
    507     ignore.setField(FieldPosition::DONT_CARE);
    508     string.remove();
    509     Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
    510     form->format(testArgs2, 2, string, ignore, err);
    511     if (string != "The disk \"MyDisk\" contains one file.") {
    512         errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
    513     }
    514 
    515     ignore.setField(FieldPosition::DONT_CARE);
    516     string.remove();
    517     Formattable testArgs3[] = {(int32_t)1273, "MyDisk"};
    518     form->format(testArgs3, 2, string, ignore, err);
    519     if (string != "The disk \"MyDisk\" contains 1,273 files.") {
    520         dataerrln("TestMessageFormat::testMsgFormatChoice failed on test #3 - %s", u_errorName(err));
    521     }
    522 
    523     delete form;
    524     delete fileform;
    525 }
    526 
    527 
    528 void TestMessageFormat::testMsgFormatPlural(/* char* par */)
    529 {
    530     logln("running TestMessageFormat::testMsgFormatPlural");
    531 
    532     UErrorCode err = U_ZERO_ERROR;
    533     UnicodeString t1("{0, plural, one{C''est # fichier} other{Ce sont # fichiers}} dans la liste.");
    534     UnicodeString t2("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
    535     UnicodeString t3("There {0, plural, one{is # zavod}few{are {0, number,###.0} zavoda} other{are # zavodov}} in the directory.");
    536     UnicodeString t4("There {argument, plural, one{is # zavod}few{are {argument, number,###.0} zavoda} other{are #zavodov}} in the directory.");
    537     UnicodeString t5("{0, plural, one {{0, number,C''''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.");
    538     MessageFormat* mfNum = new MessageFormat(t1, Locale("fr"), err);
    539     if (U_FAILURE(err)) {
    540         dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex - %s", u_errorName(err));
    541         logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
    542         return;
    543     }
    544     Formattable testArgs1((int32_t)0);
    545     FieldPosition ignore(FieldPosition::DONT_CARE);
    546     UnicodeString numResult1;
    547     mfNum->format(&testArgs1, 1, numResult1, ignore, err);
    548 
    549     MessageFormat* mfAlpha = new MessageFormat(t2, Locale("fr"), err);
    550     UnicodeString argName[] = {UnicodeString("argument")};
    551     UnicodeString argNameResult;
    552     mfAlpha->format(argName, &testArgs1, 1, argNameResult, err);
    553     if (U_FAILURE(err)) {
    554         errln("TestMessageFormat::testMsgFormatPlural #1 - argumentName");
    555         logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
    556         delete mfNum;
    557         return;
    558     }
    559     if ( numResult1 != argNameResult){
    560         errln("TestMessageFormat::testMsgFormatPlural #1");
    561         logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
    562     }
    563     if ( numResult1 != UnicodeString("C\'est 0 fichier dans la liste.")) {
    564         errln("TestMessageFormat::testMsgFormatPlural #1");
    565         logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
    566     }
    567     err = U_ZERO_ERROR;
    568 
    569     delete mfNum;
    570     delete mfAlpha;
    571 
    572     MessageFormat* mfNum2 = new MessageFormat(t3, Locale("ru"), err);
    573     numResult1.remove();
    574     Formattable testArgs2((int32_t)4);
    575     mfNum2->format(&testArgs2, 1, numResult1, ignore, err);
    576     MessageFormat* mfAlpha2 = new MessageFormat(t4, Locale("ru"), err);
    577     argNameResult.remove();
    578     mfAlpha2->format(argName, &testArgs2, 1, argNameResult, err);
    579 
    580     if (U_FAILURE(err)) {
    581         errln("TestMessageFormat::testMsgFormatPlural #2 - argumentName");
    582         logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #2 with error code ")+(int32_t)err);
    583         delete mfNum2;
    584         return;
    585     }
    586     if ( numResult1 != argNameResult){
    587         errln("TestMessageFormat::testMsgFormatPlural #2");
    588         logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
    589     }
    590     if ( numResult1 != UnicodeString("There are 4,0 zavoda in the directory.")) {
    591         errln("TestMessageFormat::testMsgFormatPlural #2");
    592         logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
    593     }
    594 
    595     delete mfNum2;
    596     delete mfAlpha2;
    597 
    598     // nested formats
    599     err = U_ZERO_ERROR;
    600     MessageFormat* msgFmt = new MessageFormat(t5, Locale("fr"), err);
    601     if (U_FAILURE(err)) {
    602         errln("TestMessageFormat::test nested PluralFormat with argumentName");
    603         logln(UnicodeString("TestMessageFormat::test nested PluralFormat with error code ")+(int32_t)err);
    604         delete msgFmt;
    605         return;
    606     }
    607     Formattable testArgs3((int32_t)0);
    608     argNameResult.remove();
    609     msgFmt->format(&testArgs3, 1, argNameResult, ignore, err);
    610     if (U_FAILURE(err)) {
    611         errln("TestMessageFormat::test nested PluralFormat with argumentName");
    612     }
    613     if ( argNameResult!= UnicodeString("C'est 0,0 fichier dans la liste.")) {
    614         errln(UnicodeString("TestMessageFormat::test nested named PluralFormat."));
    615         logln(UnicodeString("The unexpected nested named PluralFormat."));
    616     }
    617     delete msgFmt;
    618 }
    619 
    620 void TestMessageFormat::internalFormat(MessageFormat* msgFmt ,
    621         Formattable* args , int32_t numOfArgs ,
    622         UnicodeString expected ,char* errMsg)
    623 {
    624         UnicodeString result;
    625         FieldPosition ignore(FieldPosition::DONT_CARE);
    626         UErrorCode status = U_ZERO_ERROR;
    627 
    628         //Format with passed arguments
    629         msgFmt->format( args , numOfArgs , result, ignore, status);
    630         if (U_FAILURE(status)) {
    631             dataerrln( "%serror while formatting with ErrorCode as %s" ,errMsg, u_errorName(status) );
    632         }
    633         //Compare expected with obtained result
    634         if ( result!= expected ) {
    635             UnicodeString err = UnicodeString(errMsg);
    636             err+= UnicodeString(":Unexpected Result \n Expected: " + expected + "\n Obtained: " + result + "\n");
    637             dataerrln(err);
    638         }
    639 }
    640 
    641 MessageFormat* TestMessageFormat::internalCreate(
    642         UnicodeString pattern ,Locale locale ,UErrorCode &status ,  char* errMsg)
    643 {
    644     //Create the MessageFormat with simple SelectFormat
    645     MessageFormat* msgFmt = new MessageFormat(pattern, locale, status);
    646     if (U_FAILURE(status)) {
    647         dataerrln( "%serror while constructing with ErrorCode as %s" ,errMsg, u_errorName(status) );
    648         logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error code ")+(int32_t)status);
    649         return NULL;
    650     }
    651     return msgFmt;
    652 }
    653 
    654 void TestMessageFormat::testMsgFormatSelect(/* char* par */)
    655 {
    656     logln("running TestMessageFormat::testMsgFormatSelect");
    657 
    658     UErrorCode err = U_ZERO_ERROR;
    659     //French Pattern
    660     UnicodeString t1("{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
    661 
    662     err = U_ZERO_ERROR;
    663     //Create the MessageFormat with simple French pattern
    664     MessageFormat* msgFmt1 = internalCreate(t1.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t1");
    665     if (!U_FAILURE(err)) {
    666         //Arguments
    667         Formattable testArgs10[] = {"Kirti","female"};
    668         Formattable testArgs11[] = {"Victor","other"};
    669         Formattable testArgs12[] = {"Ash","unknown"};
    670         Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
    671         UnicodeString exp[] = {
    672             "Kirti est all\\u00E9e \\u00E0 Paris." ,
    673             "Victor est all\\u00E9 \\u00E0 Paris.",
    674             "Ash est all\\u00E9 \\u00E0 Paris."};
    675         //Format
    676         for( int i=0; i< 3; i++){
    677             internalFormat( msgFmt1 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t1");
    678         }
    679     }
    680     delete msgFmt1;
    681 
    682     //Quoted French Pattern
    683     UnicodeString t2("{0} est {1, select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris.");
    684     err = U_ZERO_ERROR;
    685     //Create the MessageFormat with Quoted French pattern
    686     MessageFormat* msgFmt2 = internalCreate(t2.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t2");
    687     if (!U_FAILURE(err)) {
    688         //Arguments
    689         Formattable testArgs10[] = {"Kirti","female"};
    690         Formattable testArgs11[] = {"Victor","other"};
    691         Formattable testArgs12[] = {"Ash","male"};
    692         Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
    693         UnicodeString exp[] = {
    694             "Kirti est all\\u00E9e c'est \\u00E0 Paris." ,
    695             "Victor est all\\u00E9 c'est \\u00E0 Paris.",
    696             "Ash est all\\u00E9 c'est \\u00E0 Paris."};
    697         //Format
    698         for( int i=0; i< 3; i++){
    699             internalFormat( msgFmt2 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t2");
    700         }
    701     }
    702     delete msgFmt2;
    703 
    704     //English Pattern
    705     UnicodeString t3("{0, select , male {MALE FR company} female {FEMALE FR company} other {FR otherValue}} published new books.");
    706     err = U_ZERO_ERROR;
    707     //Create the MessageFormat with English pattern
    708     MessageFormat* msgFmt3 = internalCreate(t3, Locale("en"),err,(char*)"From TestMessageFormat::TestSelectFormat create t3");
    709     if (!U_FAILURE(err)) {
    710         //Arguments
    711         Formattable testArgs10[] = {"female"};
    712         Formattable testArgs11[] = {"other"};
    713         Formattable testArgs12[] = {"male"};
    714         Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
    715         UnicodeString exp[] = {
    716             "FEMALE FR company published new books." ,
    717             "FR otherValue published new books.",
    718             "MALE FR company published new books."};
    719         //Format
    720         for( int i=0; i< 3; i++){
    721             internalFormat( msgFmt3 , testArgs[i], 1, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t3");
    722         }
    723     }
    724     delete msgFmt3;
    725 
    726     //Nested patterns with plural, number ,choice ,select format etc.
    727     //Select Format with embedded number format
    728     UnicodeString t4("{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
    729     //Create the MessageFormat with Select Format with embedded number format (nested pattern)
    730     MessageFormat* msgFmt4 = internalCreate(t4.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t4");
    731     if (!U_FAILURE(err)) {
    732         //Arguments
    733         Formattable testArgs10[] = {"Kirti","female",(int32_t)6};
    734         Formattable testArgs11[] = {"Kirti","female",100.100};
    735         Formattable testArgs12[] = {"Kirti","other",(int32_t)6};
    736         Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
    737         UnicodeString exp[] = {
    738             "Kirti est 6 all\\u00E9e \\u00E0 Paris." ,
    739             "Kirti est 100 all\\u00E9e \\u00E0 Paris.",
    740             "Kirti est all\\u00E9 \\u00E0 Paris."};
    741         //Format
    742         for( int i=0; i< 3; i++){
    743             internalFormat( msgFmt4 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t4");
    744         }
    745     }
    746     delete msgFmt4;
    747 
    748     err = U_ZERO_ERROR;
    749     //Plural format with embedded select format
    750     UnicodeString t5("{0} {1, plural, one {est {2, select, female {all\\u00E9e} other {all\\u00E9}}} other {sont {2, select, female {all\\u00E9es} other {all\\u00E9s}}}} \\u00E0 Paris.");
    751     err = U_ZERO_ERROR;
    752     //Create the MessageFormat with Plural format with embedded select format(nested pattern)
    753     MessageFormat* msgFmt5 = internalCreate(t5.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t5");
    754     if (!U_FAILURE(err)) {
    755         //Arguments
    756         Formattable testArgs10[] = {"Kirti",(int32_t)6,"female"};
    757         Formattable testArgs11[] = {"Kirti",(int32_t)1,"female"};
    758         Formattable testArgs12[] = {"Ash",(int32_t)1,"other"};
    759         Formattable testArgs13[] = {"Ash",(int32_t)5,"other"};
    760         Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13};
    761         UnicodeString exp[] = {
    762             "Kirti sont all\\u00E9es \\u00E0 Paris." ,
    763             "Kirti est all\\u00E9e \\u00E0 Paris.",
    764             "Ash est all\\u00E9 \\u00E0 Paris.",
    765             "Ash sont all\\u00E9s \\u00E0 Paris."};
    766         //Format
    767         for( int i=0; i< 4; i++){
    768             internalFormat( msgFmt5 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t5");
    769         }
    770     }
    771     delete msgFmt5;
    772 
    773     err = U_ZERO_ERROR;
    774     //Select, plural, and number formats heavily nested
    775     UnicodeString t6("{0} und {1, select, female {{2, plural, one {{3, select, female {ihre Freundin} other {ihr Freund}} } other {ihre {2, number, integer} {3, select, female {Freundinnen} other {Freunde}} } }} other{{2, plural, one {{3, select, female {seine Freundin} other {sein Freund}}} other {seine {2, number, integer} {3, select, female {Freundinnen} other {Freunde}}}}} } gingen nach Paris.");
    776     //Create the MessageFormat with Select, plural, and number formats heavily nested
    777     MessageFormat* msgFmt6 = internalCreate(t6, Locale("de"),err,(char*)"From TestMessageFormat::TestSelectFormat create t6");
    778     if (!U_FAILURE(err)) {
    779         //Arguments
    780         Formattable testArgs10[] = {"Kirti","other",(int32_t)1,"other"};
    781         Formattable testArgs11[] = {"Kirti","other",(int32_t)6,"other"};
    782         Formattable testArgs12[] = {"Kirti","other",(int32_t)1,"female"};
    783         Formattable testArgs13[] = {"Kirti","other",(int32_t)3,"female"};
    784         Formattable testArgs14[] = {"Kirti","female",(int32_t)1,"female"};
    785         Formattable testArgs15[] = {"Kirti","female",(int32_t)5,"female"};
    786         Formattable testArgs16[] = {"Kirti","female",(int32_t)1,"other"};
    787         Formattable testArgs17[] = {"Kirti","female",(int32_t)5,"other"};
    788         Formattable testArgs18[] = {"Kirti","mixed",(int32_t)1,"mixed"};
    789         Formattable testArgs19[] = {"Kirti","mixed",(int32_t)1,"other"};
    790         Formattable testArgs20[] = {"Kirti","female",(int32_t)1,"mixed"};
    791         Formattable testArgs21[] = {"Kirti","mixed",(int32_t)5,"mixed"};
    792         Formattable testArgs22[] = {"Kirti","mixed",(int32_t)5,"other"};
    793         Formattable testArgs23[] = {"Kirti","female",(int32_t)5,"mixed"};
    794         Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13,
    795                                    testArgs14,testArgs15,testArgs16,testArgs17,
    796                                    testArgs18,testArgs19,testArgs20,testArgs21,
    797                                    testArgs22,testArgs23 };
    798         UnicodeString exp[] = {
    799             "Kirti und sein Freund gingen nach Paris." ,
    800             "Kirti und seine 6 Freunde gingen nach Paris." ,
    801             "Kirti und seine Freundin gingen nach Paris.",
    802             "Kirti und seine 3 Freundinnen gingen nach Paris.",
    803             "Kirti und ihre Freundin  gingen nach Paris.",
    804             "Kirti und ihre 5 Freundinnen  gingen nach Paris.",
    805             "Kirti und ihr Freund  gingen nach Paris.",
    806             "Kirti und ihre 5 Freunde  gingen nach Paris.",
    807             "Kirti und sein Freund gingen nach Paris.",
    808             "Kirti und sein Freund gingen nach Paris.",
    809             "Kirti und ihr Freund  gingen nach Paris.",
    810             "Kirti und seine 5 Freunde gingen nach Paris." ,
    811             "Kirti und seine 5 Freunde gingen nach Paris." ,
    812             "Kirti und ihre 5 Freunde  gingen nach Paris."
    813         };
    814         //Format
    815         for( int i=0; i< 14; i++){
    816             internalFormat( msgFmt6 , testArgs[i], 4, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t6");
    817         }
    818     }
    819     delete msgFmt6;
    820 }
    821 
    822 //---------------------------------
    823 //  API Tests
    824 //---------------------------------
    825 
    826 void TestMessageFormat::testCopyConstructor()
    827 {
    828     UErrorCode success = U_ZERO_ERROR;
    829     MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
    830     MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
    831     MessageFormat *y = 0;
    832     y = new MessageFormat(*x);
    833     if ( (*x == *y) &&
    834          (*x != *z) &&
    835          (*y != *z) )
    836          logln("First test (operator ==): Passed!");
    837     else {
    838         errln("TestMessageFormat::testCopyConstructor failed #1");
    839         logln("First test (operator ==): Failed!");
    840     }
    841     if ( ((*x == *y) && (*y == *x)) &&
    842          ((*x != *z) && (*z != *x)) &&
    843          ((*y != *z) && (*z != *y)) )
    844         logln("Second test (equals): Passed!");
    845     else {
    846         errln("TestMessageFormat::testCopyConstructor failed #2");
    847         logln("Second test (equals): Failed!");
    848     }
    849 
    850     delete x;
    851     delete y;
    852     delete z;
    853 }
    854 
    855 
    856 void TestMessageFormat::testAssignment()
    857 {
    858     UErrorCode success = U_ZERO_ERROR;
    859     MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
    860     MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
    861     MessageFormat *y = new MessageFormat("There are {0} files on {1} created", success);
    862     *y = *x;
    863     if ( (*x == *y) &&
    864          (*x != *z) &&
    865          (*y != *z) )
    866         logln("First test (operator ==): Passed!");
    867     else {
    868         errln( "TestMessageFormat::testAssignment failed #1");
    869         logln("First test (operator ==): Failed!");
    870     }
    871     if ( ((*x == *y) && (*y == *x)) &&
    872          ((*x != *z) && (*z != *x)) &&
    873          ((*y != *z) && (*z != *y)) )
    874         logln("Second test (equals): Passed!");
    875     else {
    876         errln("TestMessageFormat::testAssignment failed #2");
    877         logln("Second test (equals): Failed!");
    878     }
    879 
    880     delete x;
    881     delete y;
    882     delete z;
    883 }
    884 
    885 void TestMessageFormat::testClone()
    886 {
    887     UErrorCode success = U_ZERO_ERROR;
    888     MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
    889     MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
    890     MessageFormat *y = 0;
    891     y = (MessageFormat*)x->clone();
    892     if ( (*x == *y) &&
    893          (*x != *z) &&
    894          (*y != *z) )
    895         logln("First test (operator ==): Passed!");
    896     else {
    897         errln("TestMessageFormat::testClone failed #1");
    898         logln("First test (operator ==): Failed!");
    899     }
    900     if ( ((*x == *y) && (*y == *x)) &&
    901          ((*x != *z) && (*z != *x)) &&
    902          ((*y != *z) && (*z != *y)) )
    903         logln("Second test (equals): Passed!");
    904     else {
    905         errln("TestMessageFormat::testClone failed #2");
    906         logln("Second test (equals): Failed!");
    907     }
    908 
    909     delete x;
    910     delete y;
    911     delete z;
    912 }
    913 
    914 void TestMessageFormat::testEquals()
    915 {
    916     UErrorCode success = U_ZERO_ERROR;
    917     MessageFormat x("There are {0} files on {1}", success);
    918     MessageFormat y("There are {0} files on {1}", success);
    919     if (!(x == y)) {
    920         errln( "TestMessageFormat::testEquals failed #1");
    921         logln("First test (operator ==): Failed!");
    922     }
    923 
    924 }
    925 
    926 void TestMessageFormat::testNotEquals()
    927 {
    928     UErrorCode success = U_ZERO_ERROR;
    929     MessageFormat x("There are {0} files on {1}", success);
    930     MessageFormat y(x);
    931     y.setLocale(Locale("fr"));
    932     if (!(x != y)) {
    933         errln( "TestMessageFormat::testEquals failed #1");
    934         logln("First test (operator !=): Failed!");
    935     }
    936     y = x;
    937     y.applyPattern("There are {0} files on {1} the disk", success);
    938     if (!(x != y)) {
    939         errln( "TestMessageFormat::testEquals failed #1");
    940         logln("Second test (operator !=): Failed!");
    941     }
    942 }
    943 
    944 
    945 void TestMessageFormat::testSetLocale()
    946 {
    947     UErrorCode err = U_ZERO_ERROR;
    948     GregorianCalendar cal(err);
    949     Formattable arguments[] = {
    950         456.83,
    951         Formattable(UDate(8.71068e+011), Formattable::kIsDate),
    952         "deposit"
    953         };
    954 
    955     UnicodeString result;
    956 
    957     //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
    958     UnicodeString formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
    959     // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
    960     // Just use unlocalized currency symbol.
    961     //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
    962     UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of ";
    963     compareStrEng += (UChar) 0x00a4;
    964     compareStrEng += "456.83.";
    965     // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
    966     // Just use unlocalized currency symbol.
    967     //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
    968     UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of ";
    969     compareStrGer += "456,83";
    970     compareStrGer += (UChar) 0x00a0;
    971     compareStrGer += (UChar) 0x00a4;
    972     compareStrGer += ".";
    973 
    974     MessageFormat msg( formatStr, err);
    975     result = "";
    976     FieldPosition pos(0);
    977     result = msg.format(
    978         arguments,
    979         3,
    980         result,
    981         pos,
    982         err);
    983 
    984     logln(result);
    985     if (result != compareStrEng) {
    986         dataerrln("***  MSG format err. - %s", u_errorName(err));
    987     }
    988 
    989     msg.setLocale(Locale::getEnglish());
    990     UBool getLocale_ok = TRUE;
    991     if (msg.getLocale() != Locale::getEnglish()) {
    992         errln("*** MSG getLocal err.");
    993         getLocale_ok = FALSE;
    994     }
    995 
    996     msg.setLocale(Locale::getGerman());
    997 
    998     if (msg.getLocale() != Locale::getGerman()) {
    999         errln("*** MSG getLocal err.");
   1000         getLocale_ok = FALSE;
   1001     }
   1002 
   1003     msg.applyPattern( formatStr, err);
   1004 
   1005     pos.setField(0);
   1006     result = "";
   1007     result = msg.format(
   1008         arguments,
   1009         3,
   1010         result,
   1011         pos,
   1012         err);
   1013 
   1014     logln(result);
   1015     if (result == compareStrGer) {
   1016         logln("MSG setLocale tested.");
   1017     }else{
   1018         dataerrln( "*** MSG setLocale err. - %s", u_errorName(err));
   1019     }
   1020 
   1021     if (getLocale_ok) {
   1022         logln("MSG getLocale tested.");
   1023     }
   1024 }
   1025 
   1026 void TestMessageFormat::testFormat()
   1027 {
   1028     UErrorCode err = U_ZERO_ERROR;
   1029     GregorianCalendar cal(err);
   1030 
   1031     const Formattable ftarray[] =
   1032     {
   1033         Formattable( UDate(8.71068e+011), Formattable::kIsDate )
   1034     };
   1035     const int32_t ft_cnt = sizeof(ftarray) / sizeof(Formattable);
   1036     Formattable ft_arr( ftarray, ft_cnt );
   1037 
   1038     Formattable* fmt = new Formattable(UDate(8.71068e+011), Formattable::kIsDate);
   1039 
   1040     UnicodeString result;
   1041 
   1042     //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
   1043     UnicodeString formatStr = "On {0,date}, it began.";
   1044     UnicodeString compareStr = "On Aug 8, 1997, it began.";
   1045 
   1046     err = U_ZERO_ERROR;
   1047     MessageFormat msg( formatStr, err);
   1048     FieldPosition fp(0);
   1049 
   1050     result = "";
   1051     fp = 0;
   1052     result = msg.format(
   1053         *fmt,
   1054         result,
   1055         //FieldPosition(0),
   1056         fp,
   1057         err);
   1058 
   1059     if (err != U_ILLEGAL_ARGUMENT_ERROR) {
   1060         dataerrln("*** MSG format without expected error code. - %s", u_errorName(err));
   1061     }
   1062     err = U_ZERO_ERROR;
   1063 
   1064     result = "";
   1065     fp = 0;
   1066     result = msg.format(
   1067         ft_arr,
   1068         result,
   1069         //FieldPosition(0),
   1070         fp,
   1071         err);
   1072 
   1073     logln("MSG format( Formattable&, ... ) expected:" + compareStr);
   1074     logln("MSG format( Formattable&, ... )   result:" + result);
   1075     if (result != compareStr) {
   1076         dataerrln("***  MSG format( Formattable&, .... ) err. - %s", u_errorName(err));
   1077     }else{
   1078         logln("MSG format( Formattable&, ... ) tested.");
   1079     }
   1080 
   1081     delete fmt;
   1082 
   1083 }
   1084 
   1085 void TestMessageFormat::testParse()
   1086 {
   1087     UErrorCode err = U_ZERO_ERROR;
   1088     int32_t count;
   1089     UnicodeString msgFormatString = "{0} =sep= {1}";
   1090     MessageFormat msg( msgFormatString, err);
   1091     UnicodeString source = "abc =sep= def";
   1092     UnicodeString tmp1, tmp2;
   1093 
   1094     Formattable* fmt_arr = msg.parse( source, count, err );
   1095     if (U_FAILURE(err) || (!fmt_arr)) {
   1096         errln("*** MSG parse (ustring, count, err) error.");
   1097     }else{
   1098         logln("MSG parse -- count: %d", count);
   1099         if (count != 2) {
   1100             errln("*** MSG parse (ustring, count, err) count err.");
   1101         }else{
   1102             if ((fmt_arr[0].getType() == Formattable::kString)
   1103              && (fmt_arr[1].getType() == Formattable::kString)
   1104              && (fmt_arr[0].getString(tmp1) == "abc")
   1105              && (fmt_arr[1].getString(tmp2) == "def")) {
   1106                 logln("MSG parse (ustring, count, err) tested.");
   1107             }else{
   1108                 errln("*** MSG parse (ustring, count, err) result err.");
   1109             }
   1110         }
   1111     }
   1112     delete[] fmt_arr;
   1113 
   1114     ParsePosition pp(0);
   1115 
   1116     fmt_arr = msg.parse( source, pp, count );
   1117     if ((pp == 0) || (!fmt_arr)) {
   1118         errln("*** MSG parse (ustring, parsepos., count) error.");
   1119     }else{
   1120         logln("MSG parse -- count: %d", count);
   1121         if (count != 2) {
   1122             errln("*** MSG parse (ustring, parsepos., count) count err.");
   1123         }else{
   1124             if ((fmt_arr[0].getType() == Formattable::kString)
   1125              && (fmt_arr[1].getType() == Formattable::kString)
   1126              && (fmt_arr[0].getString(tmp1) == "abc")
   1127              && (fmt_arr[1].getString(tmp2) == "def")) {
   1128                 logln("MSG parse (ustring, parsepos., count) tested.");
   1129             }else{
   1130                 errln("*** MSG parse (ustring, parsepos., count) result err.");
   1131             }
   1132         }
   1133     }
   1134     delete[] fmt_arr;
   1135 
   1136     pp = 0;
   1137     Formattable fmta;
   1138 
   1139     msg.parseObject( source, fmta, pp );
   1140     if (pp == 0) {
   1141         errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
   1142     }else{
   1143         logln("MSG parse -- count: %d", count);
   1144         fmta.getArray(count);
   1145         if (count != 2) {
   1146             errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
   1147         }else{
   1148             if ((fmta[0].getType() == Formattable::kString)
   1149              && (fmta[1].getType() == Formattable::kString)
   1150              && (fmta[0].getString(tmp1) == "abc")
   1151              && (fmta[1].getString(tmp2) == "def")) {
   1152                 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
   1153             }else{
   1154                 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
   1155             }
   1156         }
   1157     }
   1158 }
   1159 
   1160 
   1161 void TestMessageFormat::testAdopt()
   1162 {
   1163     UErrorCode err = U_ZERO_ERROR;
   1164 
   1165     UnicodeString formatStr("{0,date},{1},{2,number}", "");
   1166     UnicodeString formatStrChange("{0,number},{1,number},{2,date}", "");
   1167     err = U_ZERO_ERROR;
   1168     MessageFormat msg( formatStr, err);
   1169     MessageFormat msgCmp( formatStr, err);
   1170     int32_t count, countCmp;
   1171     const Format** formats = msg.getFormats(count);
   1172     const Format** formatsCmp = msgCmp.getFormats(countCmp);
   1173     const Format** formatsChg = 0;
   1174     const Format** formatsAct = 0;
   1175     int32_t countAct;
   1176     const Format* a;
   1177     const Format* b;
   1178     UnicodeString patCmp;
   1179     UnicodeString patAct;
   1180     Format** formatsToAdopt;
   1181 
   1182     if (!formats || !formatsCmp || (count <= 0) || (count != countCmp)) {
   1183         dataerrln("Error getting Formats");
   1184         return;
   1185     }
   1186 
   1187     int32_t i;
   1188 
   1189     for (i = 0; i < count; i++) {
   1190         a = formats[i];
   1191         b = formatsCmp[i];
   1192         if ((a != NULL) && (b != NULL)) {
   1193             if (*a != *b) {
   1194                 errln("a != b");
   1195                 return;
   1196             }
   1197         }else if ((a != NULL) || (b != NULL)) {
   1198             errln("(a != NULL) || (b != NULL)");
   1199             return;
   1200         }
   1201     }
   1202 
   1203     msg.applyPattern( formatStrChange, err ); //set msg formats to something different
   1204     int32_t countChg;
   1205     formatsChg = msg.getFormats(countChg); // tested function
   1206     if (!formatsChg || (countChg != count)) {
   1207         errln("Error getting Formats");
   1208         return;
   1209     }
   1210 
   1211     UBool diff;
   1212     diff = TRUE;
   1213     for (i = 0; i < count; i++) {
   1214         a = formatsChg[i];
   1215         b = formatsCmp[i];
   1216         if ((a != NULL) && (b != NULL)) {
   1217             if (*a == *b) {
   1218                 logln("formatsChg == formatsCmp at index %d", i);
   1219                 diff = FALSE;
   1220             }
   1221         }
   1222     }
   1223     if (!diff) {
   1224         errln("*** MSG getFormats diff err.");
   1225         return;
   1226     }
   1227 
   1228     logln("MSG getFormats tested.");
   1229 
   1230     msg.setFormats( formatsCmp, countCmp ); //tested function
   1231 
   1232     formatsAct = msg.getFormats(countAct);
   1233     if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
   1234         errln("Error getting Formats");
   1235         return;
   1236     }
   1237 
   1238     assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
   1239     assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
   1240 
   1241     for (i = 0; i < countAct; i++) {
   1242         a = formatsAct[i];
   1243         b = formatsCmp[i];
   1244         if ((a != NULL) && (b != NULL)) {
   1245             if (*a != *b) {
   1246                 logln("formatsAct != formatsCmp at index %d", i);
   1247                 errln("a != b");
   1248                 return;
   1249             }
   1250         }else if ((a != NULL) || (b != NULL)) {
   1251             errln("(a != NULL) || (b != NULL)");
   1252             return;
   1253         }
   1254     }
   1255     logln("MSG setFormats tested.");
   1256 
   1257     //----
   1258 
   1259     msg.applyPattern( formatStrChange, err ); //set msg formats to something different
   1260 
   1261     formatsToAdopt = new Format* [countCmp];
   1262     if (!formatsToAdopt) {
   1263         errln("memory allocation error");
   1264         return;
   1265     }
   1266 
   1267     for (i = 0; i < countCmp; i++) {
   1268         if (formatsCmp[i] == NULL) {
   1269             formatsToAdopt[i] = NULL;
   1270         }else{
   1271             formatsToAdopt[i] = formatsCmp[i]->clone();
   1272             if (!formatsToAdopt[i]) {
   1273                 errln("Can't clone format at index %d", i);
   1274                 return;
   1275             }
   1276         }
   1277     }
   1278     msg.adoptFormats( formatsToAdopt, countCmp ); // function to test
   1279     delete[] formatsToAdopt;
   1280 
   1281     assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
   1282     assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
   1283 
   1284     formatsAct = msg.getFormats(countAct);
   1285     if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
   1286         errln("Error getting Formats");
   1287         return;
   1288     }
   1289 
   1290     for (i = 0; i < countAct; i++) {
   1291         a = formatsAct[i];
   1292         b = formatsCmp[i];
   1293         if ((a != NULL) && (b != NULL)) {
   1294             if (*a != *b) {
   1295                 errln("a != b");
   1296                 return;
   1297             }
   1298         }else if ((a != NULL) || (b != NULL)) {
   1299             errln("(a != NULL) || (b != NULL)");
   1300             return;
   1301         }
   1302     }
   1303     logln("MSG adoptFormats tested.");
   1304 
   1305     //---- adoptFormat
   1306 
   1307     msg.applyPattern( formatStrChange, err ); //set msg formats to something different
   1308 
   1309     formatsToAdopt = new Format* [countCmp];
   1310     if (!formatsToAdopt) {
   1311         errln("memory allocation error");
   1312         return;
   1313     }
   1314 
   1315     for (i = 0; i < countCmp; i++) {
   1316         if (formatsCmp[i] == NULL) {
   1317             formatsToAdopt[i] = NULL;
   1318         }else{
   1319             formatsToAdopt[i] = formatsCmp[i]->clone();
   1320             if (!formatsToAdopt[i]) {
   1321                 errln("Can't clone format at index %d", i);
   1322                 return;
   1323             }
   1324         }
   1325     }
   1326 
   1327     for ( i = 0; i < countCmp; i++ ) {
   1328         msg.adoptFormat( i, formatsToAdopt[i] ); // function to test
   1329     }
   1330     delete[] formatsToAdopt; // array itself not needed in this case;
   1331 
   1332     assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
   1333     assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
   1334 
   1335     formatsAct = msg.getFormats(countAct);
   1336     if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
   1337         errln("Error getting Formats");
   1338         return;
   1339     }
   1340 
   1341     for (i = 0; i < countAct; i++) {
   1342         a = formatsAct[i];
   1343         b = formatsCmp[i];
   1344         if ((a != NULL) && (b != NULL)) {
   1345             if (*a != *b) {
   1346                 errln("a != b");
   1347                 return;
   1348             }
   1349         }else if ((a != NULL) || (b != NULL)) {
   1350             errln("(a != NULL) || (b != NULL)");
   1351             return;
   1352         }
   1353     }
   1354     logln("MSG adoptFormat tested.");
   1355 }
   1356 
   1357 // This test is a regression test for a fixed bug in the copy constructor.
   1358 // It is kept as a global function rather than as a method since the test depends on memory values.
   1359 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
   1360 // which is probably why it didn't show up in the regular test for the copy constructor.)
   1361 // For this reason, the test isn't changed even though it contains function calls whose results are
   1362 // not tested and had no problems. Actually, the test failed by *crashing*.
   1363 static void _testCopyConstructor2()
   1364 {
   1365     UErrorCode status = U_ZERO_ERROR;
   1366     UnicodeString formatStr("Hello World on {0,date,full}", "");
   1367     UnicodeString resultStr(" ", "");
   1368     UnicodeString result;
   1369     FieldPosition fp(0);
   1370     UDate d = Calendar::getNow();
   1371     const Formattable fargs( d, Formattable::kIsDate );
   1372 
   1373     MessageFormat* fmt1 = new MessageFormat( formatStr, status );
   1374     MessageFormat* fmt2 = new MessageFormat( *fmt1 );
   1375     MessageFormat* fmt3;
   1376     MessageFormat* fmt4;
   1377 
   1378     if (fmt1 == NULL) it_err("testCopyConstructor2: (fmt1 != NULL)");
   1379 
   1380     result = fmt1->format( &fargs, 1, resultStr, fp, status );
   1381 
   1382     if (fmt2 == NULL) it_err("testCopyConstructor2: (fmt2 != NULL)");
   1383 
   1384     fmt3 = (MessageFormat*) fmt1->clone();
   1385     fmt4 = (MessageFormat*) fmt2->clone();
   1386 
   1387     if (fmt3 == NULL) it_err("testCopyConstructor2: (fmt3 != NULL)");
   1388     if (fmt4 == NULL) it_err("testCopyConstructor2: (fmt4 != NULL)");
   1389 
   1390     result = fmt1->format( &fargs, 1, resultStr, fp, status );
   1391     result = fmt2->format( &fargs, 1, resultStr, fp, status );
   1392     result = fmt3->format( &fargs, 1, resultStr, fp, status );
   1393     result = fmt4->format( &fargs, 1, resultStr, fp, status );
   1394     delete fmt1;
   1395     delete fmt2;
   1396     delete fmt3;
   1397     delete fmt4;
   1398 }
   1399 
   1400 void TestMessageFormat::testCopyConstructor2() {
   1401     _testCopyConstructor2();
   1402 }
   1403 
   1404 /**
   1405  * Verify that MessageFormat accomodates more than 10 arguments and
   1406  * more than 10 subformats.
   1407  */
   1408 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
   1409     UErrorCode ec = U_ZERO_ERROR;
   1410     const UnicodeString pattern =
   1411         "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
   1412         "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
   1413         "there were {1,number} werjes "
   1414         "(a {3,number,percent} increase over {2,number}) "
   1415         "despite the {4}''s efforts "
   1416         "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
   1417     MessageFormat msg(pattern, ec);
   1418     if (U_FAILURE(ec)) {
   1419         dataerrln("FAIL: constructor failed - %s", u_errorName(ec));
   1420         return;
   1421     }
   1422 
   1423     const Formattable ARGS[] = {
   1424         Formattable(UDate(1e13), Formattable::kIsDate),
   1425         Formattable((int32_t)1303),
   1426         Formattable((int32_t)1202),
   1427         Formattable(1303.0/1202 - 1),
   1428         Formattable("Glimmung"),
   1429         Formattable("the printers"),
   1430         Formattable("Nick"),
   1431         Formattable("his father"),
   1432         Formattable("his mother"),
   1433         Formattable("the spiddles"),
   1434         Formattable("of course"),
   1435         Formattable("Horace"),
   1436     };
   1437     const int32_t ARGS_LENGTH = sizeof(ARGS) / sizeof(ARGS[0]);
   1438     Formattable ARGS_OBJ(ARGS, ARGS_LENGTH);
   1439 
   1440     UnicodeString expected =
   1441         "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
   1442         "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
   1443         "there were 1,303 werjes "
   1444         "(a 8% increase over 1,202) "
   1445         "despite the Glimmung's efforts "
   1446         "and to delight of the printers, Nick, his father, "
   1447         "his mother, the spiddles, and of course Horace.";
   1448     UnicodeString result;
   1449     msg.format(ARGS_OBJ, result, ec);
   1450     if (result == expected) {
   1451         logln(result);
   1452     } else {
   1453         errln((UnicodeString)"FAIL: Got " + result +
   1454               ", expected " + expected);
   1455     }
   1456 }
   1457 
   1458 // test RBNF extensions to message format
   1459 void TestMessageFormat::TestRBNF(void) {
   1460     // WARNING: this depends on the RBNF formats for en_US
   1461     Locale locale("en", "US", "");
   1462 
   1463     UErrorCode ec = U_ZERO_ERROR;
   1464 
   1465     UnicodeString values[] = {
   1466         // decimal values do not format completely for ordinal or duration, and
   1467         // do not always parse, so do not include them
   1468         "0", "1", "12", "100", "123", "1001", "123,456", "-17",
   1469     };
   1470     int32_t values_count = sizeof(values)/sizeof(values[0]);
   1471 
   1472     UnicodeString formats[] = {
   1473         "There are {0,spellout} files to search.",
   1474         "There are {0,spellout,%simplified} files to search.",
   1475         "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
   1476         "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
   1477         "Searching this file will take {0,duration} to complete.",
   1478         "Searching this file will take {0,duration,%with-words} to complete.",
   1479     };
   1480     int32_t formats_count = sizeof(formats)/sizeof(formats[0]);
   1481 
   1482     Formattable args[1];
   1483 
   1484     NumberFormat* numFmt = NumberFormat::createInstance(locale, ec);
   1485     if (U_FAILURE(ec)) {
   1486         dataerrln("Error calling NumberFormat::createInstance()");
   1487         return;
   1488     }
   1489 
   1490     for (int i = 0; i < formats_count; ++i) {
   1491         MessageFormat* fmt = new MessageFormat(formats[i], locale, ec);
   1492         logln((UnicodeString)"Testing format pattern: '" + formats[i] + "'");
   1493 
   1494         for (int j = 0; j < values_count; ++j) {
   1495             ec = U_ZERO_ERROR;
   1496             numFmt->parse(values[j], args[0], ec);
   1497             if (U_FAILURE(ec)) {
   1498                 errln((UnicodeString)"Failed to parse test argument " + values[j]);
   1499             } else {
   1500                 FieldPosition fp(0);
   1501                 UnicodeString result;
   1502                 fmt->format(args, 1, result, fp, ec);
   1503                 logln((UnicodeString)"value: " + toString(args[0]) + " --> " + result + UnicodeString(" ec: ") + u_errorName(ec));
   1504 
   1505                 if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
   1506                     int32_t count = 0;
   1507                     Formattable* parseResult = fmt->parse(result, count, ec);
   1508                     if (count != 1) {
   1509                         errln((UnicodeString)"parse returned " + count + " args");
   1510                     } else if (parseResult[0] != args[0]) {
   1511                         errln((UnicodeString)"parsed argument " + toString(parseResult[0]) + " != " + toString(args[0]));
   1512                     }
   1513                     delete []parseResult;
   1514                 }
   1515             }
   1516         }
   1517         delete fmt;
   1518     }
   1519     delete numFmt;
   1520 }
   1521 
   1522 void TestMessageFormat::testAutoQuoteApostrophe(void) {
   1523     const char* patterns[] = { // pattern, expected pattern
   1524         "'", "''",
   1525         "''", "''",
   1526         "'{", "'{'",
   1527         "' {", "'' {",
   1528         "'a", "''a",
   1529         "'{'a", "'{'a",
   1530         "'{a'", "'{a'",
   1531         "'{}", "'{}'",
   1532         "{'", "{'",
   1533         "{'a", "{'a",
   1534         "{'a{}'a}'a", "{'a{}'a}''a",
   1535         "'}'", "'}'",
   1536         "'} '{'}'", "'} '{'}''",
   1537         "'} {{{''", "'} {{{'''",
   1538     };
   1539     int32_t pattern_count = sizeof(patterns)/sizeof(patterns[0]);
   1540 
   1541     for (int i = 0; i < pattern_count; i += 2) {
   1542         UErrorCode status = U_ZERO_ERROR;
   1543         UnicodeString result = MessageFormat::autoQuoteApostrophe(patterns[i], status);
   1544         UnicodeString target(patterns[i+1]);
   1545         if (target != result) {
   1546             const int BUF2_LEN = 64;
   1547             char buf[256];
   1548             char buf2[BUF2_LEN];
   1549             int32_t len = result.extract(0, result.length(), buf2, BUF2_LEN);
   1550             if (len >= BUF2_LEN) {
   1551                 buf2[BUF2_LEN-1] = 0;
   1552             }
   1553             sprintf(buf, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i/2, patterns[i], patterns[i+1], buf2);
   1554             errln(buf);
   1555         }
   1556     }
   1557 }
   1558 
   1559 void TestMessageFormat::testCoverage(void) {
   1560     UErrorCode status = U_ZERO_ERROR;
   1561     UnicodeString testformat("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
   1562     MessageFormat *msgfmt = new MessageFormat(testformat, Locale("fr"), status);
   1563     if (msgfmt == NULL || U_FAILURE(status)) {
   1564         dataerrln("FAIL: Unable to create MessageFormat.: %s", u_errorName(status));
   1565         return;
   1566     }
   1567     if (!msgfmt->usesNamedArguments()) {
   1568         errln("FAIL: Unable to detect usage of named arguments.");
   1569     }
   1570     const double limit[] = {0.0, 1.0, 2.0};
   1571     const UnicodeString formats[] = {"0.0<=Arg<1.0",
   1572                                    "1.0<=Arg<2.0",
   1573                                    "2.0<-Arg"};
   1574     ChoiceFormat cf(limit, formats, 3);
   1575 
   1576     msgfmt->setFormat("set", cf, status);
   1577 
   1578     StringEnumeration *en = msgfmt->getFormatNames(status);
   1579     if (en == NULL || U_FAILURE(status)) {
   1580         errln("FAIL: Unable to get format names enumeration.");
   1581     } else {
   1582         int32_t count = 0;
   1583         en->reset(status);
   1584         count = en->count(status);
   1585         if (U_FAILURE(status)) {
   1586             errln("FAIL: Unable to get format name enumeration count.");
   1587         } else {
   1588             for (int32_t i = 0; i < count; i++) {
   1589                 en->snext(status);
   1590                 if (U_FAILURE(status)) {
   1591                     errln("FAIL: Error enumerating through names.");
   1592                     break;
   1593                 }
   1594             }
   1595         }
   1596     }
   1597 
   1598     msgfmt->adoptFormat("adopt", &cf, status);
   1599 
   1600     delete en;
   1601     delete msgfmt;
   1602 
   1603     msgfmt = new MessageFormat("'", status);
   1604     if (msgfmt == NULL || U_FAILURE(status)) {
   1605         errln("FAIL: Unable to create MessageFormat.");
   1606         return;
   1607     }
   1608     if (msgfmt->usesNamedArguments()) {
   1609         errln("FAIL: Unable to detect usage of named arguments.");
   1610     }
   1611 
   1612     msgfmt->setFormat("formatName", cf, status);
   1613     if (!U_FAILURE(status)) {
   1614         errln("FAIL: Should fail to setFormat instead of passing.");
   1615     }
   1616     status = U_ZERO_ERROR;
   1617     en = msgfmt->getFormatNames(status);
   1618     if (!U_FAILURE(status)) {
   1619         errln("FAIL: Should fail to get format names enumeration instead of passing.");
   1620     }
   1621 
   1622     delete en;
   1623     delete msgfmt;
   1624 }
   1625 
   1626 #endif /* #if !UCONFIG_NO_FORMATTING */
   1627