Home | History | Annotate | Download | only in intltest
      1 /***********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2009, International Business Machines Corporation
      4  * and others. All Rights Reserved.
      5  ***********************************************************************/
      6 
      7 #include "unicode/utypes.h"
      8 
      9 #if !UCONFIG_NO_FORMATTING
     10 
     11 #include "msfmrgts.h"
     12 
     13 #include "unicode/format.h"
     14 #include "unicode/decimfmt.h"
     15 #include "unicode/locid.h"
     16 #include "unicode/msgfmt.h"
     17 #include "unicode/numfmt.h"
     18 #include "unicode/choicfmt.h"
     19 #include "unicode/gregocal.h"
     20 #include "putilimp.h"
     21 
     22 // *****************************************************************************
     23 // class MessageFormatRegressionTest
     24 // *****************************************************************************
     25 
     26 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break;
     27 
     28 void
     29 MessageFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
     30 {
     31     // if (exec) logln((UnicodeString)"TestSuite MessageFormatRegressionTest");
     32     switch (index) {
     33         CASE(0,Test4074764)
     34         CASE(1,Test4058973)
     35         CASE(2,Test4031438)
     36         CASE(3,Test4052223)
     37         CASE(4,Test4104976)
     38         CASE(5,Test4106659)
     39         CASE(6,Test4106660)
     40         CASE(7,Test4111739)
     41         CASE(8,Test4114743)
     42         CASE(9,Test4116444)
     43         CASE(10,Test4114739)
     44         CASE(11,Test4113018)
     45         CASE(12,Test4106661)
     46         CASE(13,Test4094906)
     47         CASE(14,Test4118592)
     48         CASE(15,Test4118594)
     49         CASE(16,Test4105380)
     50         CASE(17,Test4120552)
     51         CASE(18,Test4142938)
     52         CASE(19,TestChoicePatternQuote)
     53         CASE(20,Test4112104)
     54 
     55         default: name = ""; break;
     56     }
     57 }
     58 
     59 UBool
     60 MessageFormatRegressionTest::failure(UErrorCode status, const char* msg, UBool possibleDataError)
     61 {
     62     if(U_FAILURE(status)) {
     63         if (possibleDataError) {
     64             dataerrln(UnicodeString("FAIL: ") + msg + " failed, error " + u_errorName(status));
     65         } else {
     66             errln(UnicodeString("FAIL: ") + msg + " failed, error " + u_errorName(status));
     67         }
     68         return TRUE;
     69     }
     70 
     71     return FALSE;
     72 }
     73 
     74 /* @bug 4074764
     75  * Null exception when formatting pattern with MessageFormat
     76  * with no parameters.
     77  */
     78 void MessageFormatRegressionTest::Test4074764() {
     79     UnicodeString pattern [] = {
     80         "Message without param",
     81         "Message with param:{0}",
     82         "Longer Message with param {0}"
     83     };
     84     //difference between the two param strings are that
     85     //in the first one, the param position is within the
     86     //length of the string without param while it is not so
     87     //in the other case.
     88 
     89     UErrorCode status = U_ZERO_ERROR;
     90     MessageFormat *messageFormatter = new MessageFormat("", status);
     91 
     92     failure(status, "couldn't create MessageFormat");
     93 
     94     //try {
     95         //Apply pattern with param and print the result
     96         messageFormatter->applyPattern(pattern[1], status);
     97         failure(status, "messageFormat->applyPattern");
     98         //Object[] params = {new UnicodeString("BUG"), new Date()};
     99         Formattable params [] = {
    100             Formattable(UnicodeString("BUG")),
    101             Formattable(0, Formattable::kIsDate)
    102         };
    103         UnicodeString tempBuffer;
    104         FieldPosition pos(FieldPosition::DONT_CARE);
    105         tempBuffer = messageFormatter->format(params, 2, tempBuffer, pos, status);
    106         if( tempBuffer != "Message with param:BUG" || failure(status, "messageFormat->format"))
    107             errln("MessageFormat with one param test failed.");
    108         logln("Formatted with one extra param : " + tempBuffer);
    109 
    110         //Apply pattern without param and print the result
    111         messageFormatter->applyPattern(pattern[0], status);
    112         failure(status, "messageFormatter->applyPattern");
    113 
    114         // {sfb} how much does this apply in C++?
    115         // do we want to verify that the Formattable* array is not NULL,
    116         // or is that the user's responsibility?
    117         // additionally, what should be the item count?
    118         // for bug testing purposes, assume that something was set to
    119         // NULL by mistake, and that the length should be non-zero
    120 
    121         //tempBuffer = messageFormatter->format(NULL, 1, tempBuffer, FieldPosition(FieldPosition::DONT_CARE), status);
    122         tempBuffer.remove();
    123         tempBuffer = messageFormatter->format(NULL, 0, tempBuffer, pos, status);
    124 
    125         if( tempBuffer != "Message without param" || failure(status, "messageFormat->format"))
    126             errln("MessageFormat with no param test failed.");
    127         logln("Formatted with no params : " + tempBuffer);
    128 
    129         tempBuffer.remove();
    130         tempBuffer = messageFormatter->format(params, 2, tempBuffer, pos, status);
    131          if (tempBuffer != "Message without param" || failure(status, "messageFormat->format"))
    132             errln("Formatted with arguments > subsitution failed. result = " + tempBuffer);
    133          logln("Formatted with extra params : " + tempBuffer);
    134         //This statement gives an exception while formatting...
    135         //If we use pattern[1] for the message with param,
    136         //we get an NullPointerException in MessageFormat.java(617)
    137         //If we use pattern[2] for the message with param,
    138         //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614)
    139         //Both are due to maxOffset not being reset to -1
    140         //in applyPattern() when the pattern does not
    141         //contain any param.
    142     /*} catch (Exception foo) {
    143         errln("Exception when formatting with no params.");
    144     }*/
    145 
    146     delete messageFormatter;
    147 }
    148 
    149 /* @bug 4058973
    150  * MessageFormat.toPattern has weird rounding behavior.
    151  */
    152 void MessageFormatRegressionTest::Test4058973()
    153 {
    154     UErrorCode status = U_ZERO_ERROR;
    155     MessageFormat *fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}", status);
    156     failure(status, "new MessageFormat");
    157 
    158     UnicodeString pat;
    159     pat = fmt->toPattern(pat);
    160     UnicodeString exp("{0,choice,0#no files|1#one file|1< {0,number,integer} files}");
    161     if (pat != exp) {
    162         errln("MessageFormat.toPattern failed");
    163         errln("Exp: " + exp);
    164         errln("Got: " + pat);
    165     }
    166 
    167     delete fmt;
    168 }
    169 /* @bug 4031438
    170  * More robust message formats.
    171  */
    172 void MessageFormatRegressionTest::Test4031438()
    173 {
    174     UErrorCode status = U_ZERO_ERROR;
    175 
    176     UnicodeString pattern1("Impossible {1} has occurred -- status code is {0} and message is {2}.");
    177     UnicodeString pattern2("Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'.");
    178 
    179     MessageFormat *messageFormatter = new MessageFormat("", status);
    180     failure(status, "new MessageFormat");
    181 
    182     const UBool possibleDataError = TRUE;
    183 
    184     //try {
    185         logln("Apply with pattern : " + pattern1);
    186         messageFormatter->applyPattern(pattern1, status);
    187         failure(status, "messageFormat->applyPattern");
    188         //Object[] params = {new Integer(7)};
    189         Formattable params []= {
    190             Formattable((int32_t)7)
    191         };
    192         UnicodeString tempBuffer;
    193         FieldPosition pos(FieldPosition::DONT_CARE);
    194         tempBuffer = messageFormatter->format(params, 1, tempBuffer, pos, status);
    195         if(tempBuffer != "Impossible {1} has occurred -- status code is 7 and message is {2}." || failure(status, "MessageFormat::format"))
    196             dataerrln("Tests arguments < substitution failed");
    197         logln("Formatted with 7 : " + tempBuffer);
    198         ParsePosition pp(0);
    199         int32_t count = 0;
    200         Formattable *objs = messageFormatter->parse(tempBuffer, pp, count);
    201         //if(objs[7/*params.length*/] != NULL)
    202         //    errln("Parse failed with more than expected arguments");
    203 
    204         NumberFormat *fmt = 0;
    205         UnicodeString temp, temp1;
    206 
    207         for (int i = 0; i < count; i++) {
    208 
    209             // convert to string if not already
    210             Formattable obj = objs[i];
    211             temp.remove();
    212             if(obj.getType() == Formattable::kString)
    213                 temp = obj.getString(temp);
    214             else {
    215                 fmt = NumberFormat::createInstance(status);
    216                 switch (obj.getType()) {
    217                 case Formattable::kLong: fmt->format(obj.getLong(), temp); break;
    218                 case Formattable::kInt64: fmt->format(obj.getInt64(), temp); break;
    219                 case Formattable::kDouble: fmt->format(obj.getDouble(), temp); break;
    220                 default: break;
    221                 }
    222             }
    223 
    224             // convert to string if not already
    225             Formattable obj1 = params[i];
    226             temp1.remove();
    227             if(obj1.getType() == Formattable::kString)
    228                 temp1 = obj1.getString(temp1);
    229             else {
    230                 fmt = NumberFormat::createInstance(status);
    231                 switch (obj1.getType()) {
    232                 case Formattable::kLong: fmt->format(obj1.getLong(), temp1); break;
    233                 case Formattable::kInt64: fmt->format(obj1.getInt64(), temp1); break;
    234                 case Formattable::kDouble: fmt->format(obj1.getDouble(), temp1); break;
    235                 default: break;
    236                 }
    237             }
    238 
    239             //if (objs[i] != NULL && objs[i].getString(temp1) != params[i].getString(temp2)) {
    240             if (temp != temp1) {
    241                 errln("Parse failed on object " + objs[i].getString(temp1) + " at index : " + i);
    242             }
    243         }
    244 
    245         delete fmt;
    246         delete [] objs;
    247 
    248         // {sfb} does this apply?  no way to really pass a null Formattable,
    249         // only a null array
    250 
    251         /*tempBuffer = messageFormatter->format(null, tempBuffer, FieldPosition(FieldPosition::DONT_CARE), status);
    252         if (tempBuffer != "Impossible {1} has occurred -- status code is {0} and message is {2}." || failure(status, "messageFormat->format"))
    253             errln("Tests with no arguments failed");
    254         logln("Formatted with null : " + tempBuffer);*/
    255         logln("Apply with pattern : " + pattern2);
    256         messageFormatter->applyPattern(pattern2, status);
    257         failure(status, "messageFormatter->applyPattern", possibleDataError);
    258         tempBuffer.remove();
    259         tempBuffer = messageFormatter->format(params, 1, tempBuffer, pos, status);
    260         if (tempBuffer != "Double ' Quotes 7 test and quoted {1} test plus other {2} stuff.")
    261             dataerrln("quote format test (w/ params) failed. - %s", u_errorName(status));
    262         logln("Formatted with params : " + tempBuffer);
    263 
    264         /*tempBuffer = messageFormatter->format(null);
    265         if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff."))
    266             errln("quote format test (w/ null) failed.");
    267         logln("Formatted with null : " + tempBuffer);
    268         logln("toPattern : " + messageFormatter.toPattern());*/
    269     /*} catch (Exception foo) {
    270         errln("Exception when formatting in bug 4031438. "+foo.getMessage());
    271     }*/
    272         delete messageFormatter;
    273 }
    274 
    275 void MessageFormatRegressionTest::Test4052223()
    276 {
    277 
    278     ParsePosition pos(0);
    279     if (pos.getErrorIndex() != -1) {
    280         errln("ParsePosition.getErrorIndex initialization failed.");
    281     }
    282 
    283     UErrorCode status = U_ZERO_ERROR;
    284     MessageFormat *fmt = new MessageFormat("There are {0} apples growing on the {1} tree.", status);
    285     failure(status, "new MessageFormat");
    286     UnicodeString str("There is one apple growing on the peach tree.");
    287 
    288     int32_t count = 0;
    289     fmt->parse(str, pos, count);
    290 
    291     logln(UnicodeString("unparsable string , should fail at ") + pos.getErrorIndex());
    292     if (pos.getErrorIndex() == -1)
    293         errln("Bug 4052223 failed : parsing string " + str);
    294     pos.setErrorIndex(4);
    295     if (pos.getErrorIndex() != 4)
    296         errln(UnicodeString("setErrorIndex failed, got ") + pos.getErrorIndex() + " instead of 4");
    297 
    298     ChoiceFormat *f = new ChoiceFormat(
    299         "-1#are negative|0#are no or fraction|1#is one|1.0<is 1+|2#are two|2<are more than 2.", status);
    300     failure(status, "new ChoiceFormat");
    301     pos.setIndex(0);
    302     pos.setErrorIndex(-1);
    303     Formattable obj;
    304     f->parse("are negative", obj, pos);
    305     if (pos.getErrorIndex() != -1 && obj.getDouble() == -1.0)
    306         errln(UnicodeString("Parse with \"are negative\" failed, at ") + pos.getErrorIndex());
    307     pos.setIndex(0);
    308     pos.setErrorIndex(-1);
    309     f->parse("are no or fraction ", obj, pos);
    310     if (pos.getErrorIndex() != -1 && obj.getDouble() == 0.0)
    311         errln(UnicodeString("Parse with \"are no or fraction\" failed, at ") + pos.getErrorIndex());
    312     pos.setIndex(0);
    313     pos.setErrorIndex(-1);
    314     f->parse("go postal", obj, pos);
    315     if (pos.getErrorIndex() == -1 && ! uprv_isNaN(obj.getDouble()))
    316         errln(UnicodeString("Parse with \"go postal\" failed, at ") + pos.getErrorIndex());
    317 
    318     delete fmt;
    319     delete f;
    320 }
    321 /* @bug 4104976
    322  * ChoiceFormat.equals(null) throws NullPointerException
    323  */
    324 
    325 // {sfb} not really applicable in C++?? (kind of silly)
    326 
    327 void MessageFormatRegressionTest::Test4104976()
    328 {
    329     double limits [] = {1, 20};
    330     UnicodeString formats [] = {
    331         UnicodeString("xyz"),
    332         UnicodeString("abc")
    333     };
    334     int32_t formats_length = (int32_t)(sizeof(formats)/sizeof(formats[0]));
    335     UErrorCode status = U_ZERO_ERROR;
    336     ChoiceFormat *cf = new ChoiceFormat(limits, formats, formats_length);
    337     failure(status, "new ChoiceFormat");
    338     //try {
    339         log("Compares to null is always false, returned : ");
    340         logln(cf == NULL ? "TRUE" : "FALSE");
    341     /*} catch (Exception foo) {
    342         errln("ChoiceFormat.equals(null) throws exception.");
    343     }*/
    344 
    345     delete cf;
    346 }
    347 
    348 /* @bug 4106659
    349  * ChoiceFormat.ctor(double[], String[]) doesn't check
    350  * whether lengths of input arrays are equal.
    351  */
    352 
    353 // {sfb} again, not really applicable in C++
    354 
    355 void MessageFormatRegressionTest::Test4106659()
    356 {
    357     /*
    358     double limits [] = {
    359         1, 2, 3
    360     };
    361     UnicodeString formats [] = {
    362         "one", "two"
    363     };
    364     ChoiceFormat *cf = NULL;
    365     //try {
    366     //    cf = new ChoiceFormat(limits, formats, 3);
    367     //} catch (Exception foo) {
    368     //    logln("ChoiceFormat constructor should check for the array lengths");
    369     //    cf = null;
    370     //}
    371     //if (cf != null)
    372     //    errln(cf->format(5));
    373     //
    374     delete cf;
    375     */
    376 }
    377 
    378 /* @bug 4106660
    379  * ChoiceFormat.ctor(double[], String[]) allows unordered double array.
    380  * This is not a bug, added javadoc to emphasize the use of limit
    381  * array must be in ascending order.
    382  */
    383 void MessageFormatRegressionTest::Test4106660()
    384 {
    385     double limits [] = {3, 1, 2};
    386     UnicodeString formats [] = {
    387         UnicodeString("Three"),
    388             UnicodeString("One"),
    389             UnicodeString("Two")
    390     };
    391     ChoiceFormat *cf = new ChoiceFormat(limits, formats, 3);
    392     double d = 5.0;
    393     UnicodeString str;
    394     FieldPosition pos(FieldPosition::DONT_CARE);
    395     str = cf->format(d, str, pos);
    396     if (str != "Two")
    397         errln( (UnicodeString) "format(" + d + ") = " + str);
    398 
    399     delete cf;
    400 }
    401 
    402 /* @bug 4111739
    403  * MessageFormat is incorrectly serialized/deserialized.
    404  */
    405 
    406 // {sfb} doesn't apply in C++
    407 
    408 void MessageFormatRegressionTest::Test4111739()
    409 {
    410     /*MessageFormat format1 = null;
    411     MessageFormat format2 = null;
    412     ObjectOutputStream ostream = null;
    413     ByteArrayOutputStream baos = null;
    414     ObjectInputStream istream = null;
    415 
    416     try {
    417         baos = new ByteArrayOutputStream();
    418         ostream = new ObjectOutputStream(baos);
    419     } catch(IOException e) {
    420         errln("Unexpected exception : " + e.getMessage());
    421         return;
    422     }
    423 
    424     try {
    425         format1 = new MessageFormat("pattern{0}");
    426         ostream.writeObject(format1);
    427         ostream.flush();
    428 
    429         byte bytes[] = baos.toByteArray();
    430 
    431         istream = new ObjectInputStream(new ByteArrayInputStream(bytes));
    432         format2 = (MessageFormat)istream.readObject();
    433     } catch(Exception e) {
    434         errln("Unexpected exception : " + e.getMessage());
    435     }
    436 
    437     if (!format1.equals(format2)) {
    438         errln("MessageFormats before and after serialization are not" +
    439             " equal\nformat1 = " + format1 + "(" + format1.toPattern() + ")\nformat2 = " +
    440             format2 + "(" + format2.toPattern() + ")");
    441     } else {
    442         logln("Serialization for MessageFormat is OK.");
    443     }*/
    444 }
    445 /* @bug 4114743
    446  * MessageFormat.applyPattern allows illegal patterns.
    447  */
    448 void MessageFormatRegressionTest::Test4114743()
    449 {
    450     UnicodeString originalPattern("initial pattern");
    451     UErrorCode status = U_ZERO_ERROR;
    452     MessageFormat *mf = new MessageFormat(originalPattern, status);
    453     failure(status, "new MessageFormat");
    454     //try {
    455         UnicodeString illegalPattern("ab { '}' de");
    456         mf->applyPattern(illegalPattern, status);
    457         if( ! U_FAILURE(status))
    458             errln("illegal pattern: \"" + illegalPattern + "\"");
    459     /*} catch (IllegalArgumentException foo) {
    460         if (!originalPattern.equals(mf.toPattern()))
    461             errln("pattern after: \"" + mf.toPattern() + "\"");
    462     }*/
    463     delete mf;
    464 }
    465 
    466 /* @bug 4116444
    467  * MessageFormat.parse has different behavior in case of null.
    468  */
    469 void MessageFormatRegressionTest::Test4116444()
    470 {
    471     UnicodeString patterns [] = {
    472         (UnicodeString)"",
    473         (UnicodeString)"one",
    474         (UnicodeString) "{0,date,short}"
    475     };
    476 
    477     UErrorCode status = U_ZERO_ERROR;
    478     MessageFormat *mf = new MessageFormat("", status);
    479     failure(status, "new MessageFormat");
    480 
    481     for (int i = 0; i < 3; i++) {
    482         UnicodeString pattern = patterns[i];
    483         mf->applyPattern(pattern, status);
    484         failure(status, "mf->applyPattern", TRUE);
    485 
    486         //try {
    487         int32_t count = 0;
    488         ParsePosition pp(0);
    489         Formattable *array = mf->parse(UnicodeString(""), pp, count);
    490             logln("pattern: \"" + pattern + "\"");
    491             log(" parsedObjects: ");
    492             if (array != NULL) {
    493                 log("{");
    494                 for (int j = 0; j < count; j++) {
    495                     //if (array[j] != null)
    496                     UnicodeString dummy;
    497                     err("\"" + array[j].getString(dummy) + "\"");
    498                     //else
    499                      //   log("null");
    500                     if (j < count- 1)
    501                         log(",");
    502                 }
    503                 log("}") ;
    504                 delete[] array;
    505             } else {
    506                 log("null");
    507             }
    508             logln("");
    509         /*} catch (Exception e) {
    510             errln("pattern: \"" + pattern + "\"");
    511             errln("  Exception: " + e.getMessage());
    512         }*/
    513     }
    514 
    515     delete mf;
    516 }
    517 /* @bug 4114739 (FIX and add javadoc)
    518  * MessageFormat.format has undocumented behavior about empty format objects.
    519  */
    520 
    521 // {sfb} doesn't apply in C++?
    522 void MessageFormatRegressionTest::Test4114739()
    523 {
    524 
    525     UErrorCode status = U_ZERO_ERROR;
    526     MessageFormat *mf = new MessageFormat("<{0}>", status);
    527     failure(status, "new MessageFormat");
    528 
    529     Formattable *objs1 = NULL;
    530     //Formattable objs2 [] = {};
    531     //Formattable *objs3 [] = {NULL};
    532     //try {
    533     UnicodeString pat;
    534     UnicodeString res;
    535         logln("pattern: \"" + mf->toPattern(pat) + "\"");
    536         log("format(null) : ");
    537         FieldPosition pos(FieldPosition::DONT_CARE);
    538         logln("\"" + mf->format(objs1, 0, res, pos, status) + "\"");
    539         failure(status, "mf->format");
    540         /*log("format({})   : ");
    541         logln("\"" + mf->format(objs2, 0, res, FieldPosition(FieldPosition::DONT_CARE), status) + "\"");
    542         failure(status, "mf->format");
    543         log("format({null}) :");
    544         logln("\"" + mf->format(objs3, 0, res, FieldPosition(FieldPosition::DONT_CARE), status) + "\"");
    545         failure(status, "mf->format");*/
    546     /*} catch (Exception e) {
    547         errln("Exception thrown for null argument tests.");
    548     }*/
    549 
    550     delete mf;
    551 }
    552 
    553 /* @bug 4113018
    554  * MessageFormat.applyPattern works wrong with illegal patterns.
    555  */
    556 void MessageFormatRegressionTest::Test4113018()
    557 {
    558     UnicodeString originalPattern("initial pattern");
    559     UErrorCode status = U_ZERO_ERROR;
    560     MessageFormat *mf = new MessageFormat(originalPattern, status);
    561     failure(status, "new messageFormat");
    562     UnicodeString illegalPattern("format: {0, xxxYYY}");
    563     UnicodeString pat;
    564     logln("pattern before: \"" + mf->toPattern(pat) + "\"");
    565     logln("illegal pattern: \"" + illegalPattern + "\"");
    566     //try {
    567         mf->applyPattern(illegalPattern, status);
    568         if( ! U_FAILURE(status))
    569             errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern);
    570     /*} catch (IllegalArgumentException e) {
    571         if (!originalPattern.equals(mf.toPattern()))
    572             errln("pattern after: \"" + mf.toPattern() + "\"");
    573     }*/
    574     delete mf;
    575 }
    576 
    577 /* @bug 4106661
    578  * ChoiceFormat is silent about the pattern usage in javadoc.
    579  */
    580 void MessageFormatRegressionTest::Test4106661()
    581 {
    582     UErrorCode status = U_ZERO_ERROR;
    583     ChoiceFormat *fmt = new ChoiceFormat(
    584       "-1#are negative| 0#are no or fraction | 1#is one |1.0<is 1+ |2#are two |2<are more than 2.", status);
    585     failure(status, "new ChoiceFormat");
    586     UnicodeString pat;
    587     logln("Formatter Pattern : " + fmt->toPattern(pat));
    588 
    589     FieldPosition bogus(FieldPosition::DONT_CARE);
    590     UnicodeString str;
    591 
    592     // Will this work for -inf?
    593     logln("Format with -INF : " + fmt->format(Formattable(-uprv_getInfinity()), str, bogus, status));
    594     failure(status, "fmt->format");
    595     str.remove();
    596     logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, status));
    597     failure(status, "fmt->format");
    598     str.remove();
    599     logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, status));
    600     failure(status, "fmt->format");
    601     str.remove();
    602     logln("Format with 0 : " + fmt->format(Formattable((int32_t)0), str, bogus, status));
    603     failure(status, "fmt->format");
    604     str.remove();
    605     logln("Format with 0.9 : " + fmt->format(Formattable(0.9), str, bogus, status));
    606     failure(status, "fmt->format");
    607     str.remove();
    608     logln("Format with 1.0 : " + fmt->format(Formattable(1.0), str, bogus, status));
    609     failure(status, "fmt->format");
    610     str.remove();
    611     logln("Format with 1.5 : " + fmt->format(Formattable(1.5), str, bogus, status));
    612     failure(status, "fmt->format");
    613     str.remove();
    614     logln("Format with 2 : " + fmt->format(Formattable((int32_t)2), str, bogus, status));
    615     failure(status, "fmt->format");
    616     str.remove();
    617     logln("Format with 2.1 : " + fmt->format(Formattable(2.1), str, bogus, status));
    618     failure(status, "fmt->format");
    619     str.remove();
    620     logln("Format with NaN : " + fmt->format(Formattable(uprv_getNaN()), str, bogus, status));
    621     failure(status, "fmt->format");
    622     str.remove();
    623     logln("Format with +INF : " + fmt->format(Formattable(uprv_getInfinity()), str, bogus, status));
    624     failure(status, "fmt->format");
    625 
    626     delete fmt;
    627 }
    628 
    629 /* @bug 4094906
    630  * ChoiceFormat should accept \u221E as eq. to INF.
    631  */
    632 void MessageFormatRegressionTest::Test4094906()
    633 {
    634     UErrorCode status = U_ZERO_ERROR;
    635     UnicodeString pattern("-");
    636     pattern += (UChar) 0x221E;
    637     pattern += "<are negative|0<are no or fraction|1#is one|1<is 1+|";
    638     pattern += (UChar) 0x221E;
    639     pattern += "<are many.";
    640 
    641     ChoiceFormat *fmt = new ChoiceFormat(pattern, status);
    642     failure(status, "new ChoiceFormat");
    643     UnicodeString pat;
    644     if (fmt->toPattern(pat) != pattern) {
    645         errln( (UnicodeString) "Formatter Pattern : " + pat);
    646         errln( (UnicodeString) "Expected Pattern  : " + pattern);
    647     }
    648     FieldPosition bogus(FieldPosition::DONT_CARE);
    649     UnicodeString str;
    650 
    651     // Will this work for -inf?
    652     logln("Format with -INF : " + fmt->format(Formattable(-uprv_getInfinity()), str, bogus, status));
    653     failure(status, "fmt->format");
    654     str.remove();
    655     logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, status));
    656     failure(status, "fmt->format");
    657     str.remove();
    658     logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, status));
    659     failure(status, "fmt->format");
    660     str.remove();
    661     logln("Format with 0 : " + fmt->format(Formattable((int32_t)0), str, bogus, status));
    662     failure(status, "fmt->format");
    663     str.remove();
    664     logln("Format with 0.9 : " + fmt->format(Formattable(0.9), str, bogus, status));
    665     failure(status, "fmt->format");
    666     str.remove();
    667     logln("Format with 1.0 : " + fmt->format(Formattable(1.0), str, bogus, status));
    668     failure(status, "fmt->format");
    669     str.remove();
    670     logln("Format with 1.5 : " + fmt->format(Formattable(1.5), str, bogus, status));
    671     failure(status, "fmt->format");
    672     str.remove();
    673     logln("Format with 2 : " + fmt->format(Formattable((int32_t)2), str, bogus, status));
    674     failure(status, "fmt->format");
    675     str.remove();
    676     logln("Format with 2.1 : " + fmt->format(Formattable(2.1), str, bogus, status));
    677     failure(status, "fmt->format");
    678     str.remove();
    679     logln("Format with NaN : " + fmt->format(Formattable(uprv_getNaN()), str, bogus, status));
    680     failure(status, "fmt->format");
    681     str.remove();
    682     logln("Format with +INF : " + fmt->format(Formattable(uprv_getInfinity()), str, bogus, status));
    683     failure(status, "fmt->format");
    684 
    685     delete fmt;
    686 }
    687 
    688 /* @bug 4118592
    689  * MessageFormat.parse fails with ChoiceFormat.
    690  */
    691 void MessageFormatRegressionTest::Test4118592()
    692 {
    693     UErrorCode status = U_ZERO_ERROR;
    694     MessageFormat *mf = new MessageFormat("", status);
    695     failure(status, "new messageFormat");
    696     UnicodeString pattern("{0,choice,1#YES|2#NO}");
    697     UnicodeString prefix("");
    698     Formattable *objs = 0;
    699 
    700     for (int i = 0; i < 5; i++) {
    701         UnicodeString formatted;
    702         formatted = prefix + "YES";
    703         mf->applyPattern(prefix + pattern, status);
    704         failure(status, "mf->applyPattern");
    705         prefix += "x";
    706         //Object[] objs = mf.parse(formatted, new ParsePosition(0));
    707         int32_t count = 0;
    708         ParsePosition pp(0);
    709         objs = mf->parse(formatted, pp, count);
    710         UnicodeString pat;
    711         logln(UnicodeString("") + i + ". pattern :\"" + mf->toPattern(pat) + "\"");
    712         log(" \"" + formatted + "\" parsed as ");
    713         if (objs == NULL)
    714             logln("  null");
    715         else {
    716             UnicodeString temp;
    717             if(objs[0].getType() == Formattable::kString)
    718                 logln((UnicodeString)"  " + objs[0].getString(temp));
    719             else
    720                 logln((UnicodeString)"  " + (objs[0].getType() == Formattable::kLong ? objs[0].getLong() : objs[0].getDouble()));
    721             delete[] objs;
    722 
    723         }
    724     }
    725 
    726     delete mf;
    727 }
    728 /* @bug 4118594
    729  * MessageFormat.parse fails for some patterns.
    730  */
    731 void MessageFormatRegressionTest::Test4118594()
    732 {
    733     UErrorCode status = U_ZERO_ERROR;
    734     const UBool possibleDataError = TRUE;
    735     MessageFormat *mf = new MessageFormat("{0}, {0}, {0}", status);
    736     failure(status, "new MessageFormat");
    737     UnicodeString forParsing("x, y, z");
    738     //Object[] objs = mf.parse(forParsing, new ParsePosition(0));
    739     int32_t count = 0;
    740     ParsePosition pp(0);
    741     Formattable *objs = mf->parse(forParsing, pp, count);
    742     UnicodeString pat;
    743     logln("pattern: \"" + mf->toPattern(pat) + "\"");
    744     logln("text for parsing: \"" + forParsing + "\"");
    745     UnicodeString str;
    746     if (objs[0].getString(str) != "z")
    747         errln("argument0: \"" + objs[0].getString(str) + "\"");
    748     mf->applyPattern("{0,number,#.##}, {0,number,#.#}", status);
    749     failure(status, "mf->applyPattern", possibleDataError);
    750     //Object[] oldobjs = {new Double(3.1415)};
    751     Formattable oldobjs [] = {Formattable(3.1415)};
    752     UnicodeString result;
    753     FieldPosition pos(FieldPosition::DONT_CARE);
    754     result = mf->format( oldobjs, 1, result, pos, status );
    755     failure(status, "mf->format", possibleDataError);
    756     pat.remove();
    757     logln("pattern: \"" + mf->toPattern(pat) + "\"");
    758     logln("text for parsing: \"" + result + "\"");
    759     // result now equals "3.14, 3.1"
    760     if (result != "3.14, 3.1")
    761         dataerrln("result = " + result + " - " + u_errorName(status));
    762     //Object[] newobjs = mf.parse(result, new ParsePosition(0));
    763     int32_t count1 = 0;
    764     pp.setIndex(0);
    765     Formattable *newobjs = mf->parse(result, pp, count1);
    766     // newobjs now equals {new Double(3.1)}
    767     if (newobjs == NULL) {
    768         dataerrln("Error calling MessageFormat::parse");
    769     } else {
    770         if (newobjs[0].getDouble() != 3.1)
    771             errln( UnicodeString("newobjs[0] = ") + newobjs[0].getDouble());
    772     }
    773 
    774     delete [] objs;
    775     delete [] newobjs;
    776     delete mf;
    777 }
    778 /* @bug 4105380
    779  * When using ChoiceFormat, MessageFormat is not good for I18n.
    780  */
    781 void MessageFormatRegressionTest::Test4105380()
    782 {
    783     UnicodeString patternText1("The disk \"{1}\" contains {0}.");
    784     UnicodeString patternText2("There are {0} on the disk \"{1}\"");
    785     UErrorCode status = U_ZERO_ERROR;
    786     const UBool possibleDataError = TRUE;
    787     MessageFormat *form1 = new MessageFormat(patternText1, status);
    788     failure(status, "new MessageFormat");
    789     MessageFormat *form2 = new MessageFormat(patternText2, status);
    790     failure(status, "new MessageFormat");
    791     double filelimits [] = {0,1,2};
    792     UnicodeString filepart [] = {
    793         (UnicodeString)"no files",
    794             (UnicodeString)"one file",
    795             (UnicodeString)"{0,number} files"
    796     };
    797     ChoiceFormat *fileform = new ChoiceFormat(filelimits, filepart, 3);
    798     form1->setFormat(1, *fileform);
    799     form2->setFormat(0, *fileform);
    800     //Object[] testArgs = {new Long(12373), "MyDisk"};
    801     Formattable testArgs [] = {
    802         Formattable((int32_t)12373),
    803             Formattable((UnicodeString)"MyDisk")
    804     };
    805 
    806     FieldPosition bogus(FieldPosition::DONT_CARE);
    807 
    808     UnicodeString result;
    809     logln(form1->format(testArgs, 2, result, bogus, status));
    810     failure(status, "form1->format", possibleDataError);
    811     result.remove();
    812     logln(form2->format(testArgs, 2, result, bogus, status));
    813     failure(status, "form1->format", possibleDataError);
    814 
    815     delete form1;
    816     delete form2;
    817     delete fileform;
    818 }
    819 /* @bug 4120552
    820  * MessageFormat.parse incorrectly sets errorIndex.
    821  */
    822 void MessageFormatRegressionTest::Test4120552()
    823 {
    824     UErrorCode status = U_ZERO_ERROR;
    825     MessageFormat *mf = new MessageFormat("pattern", status);
    826     failure(status, "new MessageFormat");
    827     UnicodeString texts[] = {
    828         (UnicodeString)"pattern",
    829             (UnicodeString)"pat",
    830             (UnicodeString)"1234"
    831     };
    832     UnicodeString pat;
    833     logln("pattern: \"" + mf->toPattern(pat) + "\"");
    834     for (int i = 0; i < 3; i++) {
    835         ParsePosition pp(0);
    836         //Object[] objs = mf.parse(texts[i], pp);
    837         int32_t count = 0;
    838         Formattable *objs = mf->parse(texts[i], pp, count);
    839         log("  text for parsing: \"" + texts[i] + "\"");
    840         if (objs == NULL) {
    841             logln("  (incorrectly formatted string)");
    842             if (pp.getErrorIndex() == -1)
    843                 errln(UnicodeString("Incorrect error index: ") + pp.getErrorIndex());
    844         } else {
    845             logln("  (correctly formatted string)");
    846             delete[] objs;
    847         }
    848     }
    849     delete mf;
    850 }
    851 
    852 /**
    853  * @bug 4142938
    854  * MessageFormat handles single quotes in pattern wrong.
    855  * This is actually a problem in ChoiceFormat; it doesn't
    856  * understand single quotes.
    857  */
    858 void MessageFormatRegressionTest::Test4142938()
    859 {
    860     UnicodeString pat = CharsToUnicodeString("''Vous'' {0,choice,0#n''|1#}avez s\\u00E9lectionn\\u00E9 "
    861         "{0,choice,0#aucun|1#{0}} client{0,choice,0#s|1#|2#s} "
    862         "personnel{0,choice,0#s|1#|2#s}.");
    863     UErrorCode status = U_ZERO_ERROR;
    864     MessageFormat *mf = new MessageFormat(pat, status);
    865     failure(status, "new MessageFormat");
    866 
    867     UnicodeString PREFIX [] = {
    868         CharsToUnicodeString("'Vous' n'avez s\\u00E9lectionn\\u00E9 aucun clients personnels."),
    869         CharsToUnicodeString("'Vous' avez s\\u00E9lectionn\\u00E9 "),
    870         CharsToUnicodeString("'Vous' avez s\\u00E9lectionn\\u00E9 ")
    871     };
    872     UnicodeString SUFFIX [] = {
    873         UnicodeString(),
    874         UNICODE_STRING(" client personnel.", 18),
    875         UNICODE_STRING(" clients personnels.", 20)
    876     };
    877 
    878     for (int i=0; i<3; i++) {
    879         UnicodeString out;
    880         //out = mf->format(new Object[]{new Integer(i)});
    881         Formattable objs [] = {
    882             Formattable((int32_t)i)
    883         };
    884         FieldPosition pos(FieldPosition::DONT_CARE);
    885         out = mf->format(objs, 1, out, pos, status);
    886         if (!failure(status, "mf->format", TRUE)) {
    887             if (SUFFIX[i] == "") {
    888                 if (out != PREFIX[i])
    889                     errln((UnicodeString)"" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"");
    890             }
    891             else {
    892                 if (!out.startsWith(PREFIX[i]) ||
    893                     !out.endsWith(SUFFIX[i]))
    894                     errln((UnicodeString)"" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"...\"" +
    895                           SUFFIX[i] + "\"");
    896             }
    897         }
    898     }
    899 
    900     delete mf;
    901 }
    902 
    903 /**
    904  * @bug 4142938
    905  * Test the applyPattern and toPattern handling of single quotes
    906  * by ChoiceFormat.  (This is in here because this was a bug reported
    907  * against MessageFormat.)  The single quote is used to quote the
    908  * pattern characters '|', '#', '<', and '\u2264'.  Two quotes in a row
    909  * is a quote literal.
    910  */
    911 void MessageFormatRegressionTest::TestChoicePatternQuote()
    912 {
    913     UnicodeString DATA [] = {
    914         // Pattern                  0 value           1 value
    915         // {sfb} hacked - changed \u2264 to = (copied from Character Map)
    916         (UnicodeString)"0#can''t|1#can",           (UnicodeString)"can't",          (UnicodeString)"can",
    917         (UnicodeString)"0#'pound(#)=''#'''|1#xyz", (UnicodeString)"pound(#)='#'",   (UnicodeString)"xyz",
    918         (UnicodeString)"0#'1<2 | 1=1'|1#''",  (UnicodeString)"1<2 | 1=1", (UnicodeString)"'",
    919     };
    920     for (int i=0; i<9; i+=3) {
    921         //try {
    922             UErrorCode status = U_ZERO_ERROR;
    923             ChoiceFormat *cf = new ChoiceFormat(DATA[i], status);
    924             failure(status, "new ChoiceFormat");
    925             for (int j=0; j<=1; ++j) {
    926                 UnicodeString out;
    927                 FieldPosition pos(FieldPosition::DONT_CARE);
    928                 out = cf->format((double)j, out, pos);
    929                 if (out != DATA[i+1+j])
    930                     errln("Fail: Pattern \"" + DATA[i] + "\" x "+j+" -> " +
    931                           out + "; want \"" + DATA[i+1+j] + '"');
    932             }
    933             UnicodeString pat;
    934             pat = cf->toPattern(pat);
    935             UnicodeString pat2;
    936             ChoiceFormat *cf2 = new ChoiceFormat(pat, status);
    937             pat2 = cf2->toPattern(pat2);
    938             if (pat != pat2)
    939                 errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
    940             else
    941                 logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
    942         /*}
    943         catch (IllegalArgumentException e) {
    944             errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e);
    945         }*/
    946 
    947         delete cf;
    948         delete cf2;
    949     }
    950 }
    951 
    952 /**
    953  * @bug 4112104
    954  * MessageFormat.equals(null) throws a NullPointerException.  The JLS states
    955  * that it should return false.
    956  */
    957 void MessageFormatRegressionTest::Test4112104()
    958 {
    959     UErrorCode status = U_ZERO_ERROR;
    960     MessageFormat *format = new MessageFormat("", status);
    961     failure(status, "new MessageFormat");
    962     //try {
    963         // This should NOT throw an exception
    964         if (format == NULL) {
    965             // It also should return false
    966             errln("MessageFormat.equals(null) returns false");
    967         }
    968     /*}
    969     catch (NullPointerException e) {
    970         errln("MessageFormat.equals(null) throws " + e);
    971     }*/
    972     delete format;
    973 }
    974 
    975 #endif /* #if !UCONFIG_NO_FORMATTING */
    976