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