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