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