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