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