Home | History | Annotate | Download | only in intltest
      1 /***********************************************************************
      2  * Copyright (c) 1997-2010, International Business Machines Corporation
      3  * and others. All Rights Reserved.
      4  ***********************************************************************/
      5 
      6 #include "unicode/utypes.h"
      7 
      8 #if !UCONFIG_NO_FORMATTING
      9 
     10 #include "numrgts.h"
     11 
     12 #include <float.h> // DBL_MIN, DBL_MAX
     13 #include <stdio.h>
     14 
     15 #include "unicode/dcfmtsym.h"
     16 #include "unicode/decimfmt.h"
     17 #include "unicode/locid.h"
     18 #include "unicode/resbund.h"
     19 #include "unicode/calendar.h"
     20 #include "unicode/datefmt.h"
     21 #include "unicode/ucurr.h"
     22 #include "putilimp.h"
     23 
     24 class MyNumberFormatTest : public NumberFormat
     25 {
     26 public:
     27 
     28     virtual UClassID getDynamicClassID(void) const;
     29 
     30     virtual UnicodeString& format(    double            number,
     31                     UnicodeString&        toAppendTo,
     32                     FieldPosition&        pos,
     33                     UErrorCode& status) const
     34     {
     35         return NumberFormat::format(number, toAppendTo, pos, status);
     36     }
     37 
     38     /* Just keep this here to make some of the compilers happy */
     39     virtual UnicodeString& format(const Formattable& obj,
     40                                   UnicodeString& toAppendTo,
     41                                   FieldPosition& pos,
     42                                   UErrorCode& status) const
     43     {
     44         return NumberFormat::format(obj, toAppendTo, pos, status);
     45     }
     46 
     47     /* Just use one of the format functions */
     48     virtual UnicodeString& format(    double            /* number */,
     49                     UnicodeString&        toAppendTo,
     50                     FieldPosition&        /* pos */) const
     51     {
     52         toAppendTo = "";
     53         return toAppendTo;
     54     }
     55 
     56     /*
     57     public Number parse(String text, ParsePosition parsePosition)
     58     { return new Integer(0); }
     59     */
     60 
     61     /* Just use one of the parse functions */
     62     virtual void parse(    const UnicodeString&    /* text */,
     63             Formattable&            result,
     64             ParsePosition&          /* parsePosition */) const
     65     {
     66         result.setLong((int32_t)0);
     67     }
     68 
     69     virtual void parse(    const UnicodeString&    text,
     70             Formattable&            result,
     71             UErrorCode&            status) const
     72     {
     73         NumberFormat::parse(text, result, status);
     74     }
     75     virtual Format* clone() const
     76     { return NULL; }
     77 
     78     virtual UnicodeString& format(int32_t,
     79                 UnicodeString& foo,
     80                 FieldPosition&) const
     81     { return foo.remove(); }
     82 
     83     virtual UnicodeString& format(int64_t,
     84                 UnicodeString& foo,
     85                 FieldPosition&) const
     86     { return foo.remove(); }
     87 
     88     virtual void applyPattern(const UnicodeString&, UParseError&, UErrorCode&){
     89     }
     90 };
     91 
     92 int32_t gMyNumberFormatTestClassID;
     93 UClassID MyNumberFormatTest::getDynamicClassID()  const
     94 {
     95     return (UClassID)&gMyNumberFormatTestClassID;
     96 }
     97 
     98 
     99 // *****************************************************************************
    100 // class NumberFormatRegressionTest
    101 // *****************************************************************************
    102 
    103 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
    104 
    105 void
    106 NumberFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
    107 {
    108     // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
    109     switch (index) {
    110         CASE(0,Test4075713);
    111         CASE(1,Test4074620);
    112         CASE(2,Test4088161);
    113         CASE(3,Test4087245);
    114         CASE(4,Test4087535);
    115         CASE(5,Test4088503);
    116         CASE(6,Test4066646);
    117         CASE(7,Test4059870);
    118         CASE(8,Test4083018);
    119         CASE(9,Test4071492);
    120         CASE(10,Test4086575);
    121         CASE(11,Test4068693);
    122         CASE(12,Test4069754);
    123         CASE(13,Test4087251);
    124         CASE(14,Test4090489);
    125         CASE(15,Test4090504);
    126         CASE(16,Test4095713);
    127         CASE(17,Test4092561);
    128         CASE(18,Test4092480);
    129         CASE(19,Test4087244);
    130         CASE(20,Test4070798);
    131         CASE(21,Test4071005);
    132         CASE(22,Test4071014);
    133         CASE(23,Test4071859);
    134         CASE(24,Test4093610);
    135         CASE(25,Test4098741);
    136         CASE(26,Test4074454);
    137         CASE(27,Test4099404);
    138         CASE(28,Test4101481);
    139         CASE(29,Test4052223);
    140         CASE(30,Test4061302);
    141         CASE(31,Test4062486);
    142         CASE(32,Test4108738);
    143         CASE(33,Test4106658);
    144         CASE(34,Test4106662);
    145         CASE(35,Test4114639);
    146         CASE(36,Test4106664);
    147         CASE(37,Test4106667);
    148         CASE(38,Test4110936);
    149         CASE(39,Test4122840);
    150         CASE(40,Test4125885);
    151         CASE(41,Test4134034);
    152         CASE(42,Test4134300);
    153         CASE(43,Test4140009);
    154         CASE(44,Test4141750);
    155         CASE(45,Test4145457);
    156         CASE(46,Test4147295);
    157         CASE(47,Test4147706);
    158         CASE(48,Test4162198);
    159         CASE(49,Test4162852);
    160         CASE(50,Test4167494);
    161         CASE(51,Test4170798);
    162         CASE(52,Test4176114);
    163         CASE(53,Test4179818);
    164         CASE(54,Test4212072);
    165         CASE(55,Test4216742);
    166         CASE(56,Test4217661);
    167         CASE(57,Test4161100);
    168         CASE(58,Test4243011);
    169         CASE(59,Test4243108);
    170         CASE(60,TestJ691);
    171 
    172         default: name = ""; break;
    173     }
    174 }
    175 
    176 UBool
    177 NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const Locale& l, UBool possibleDataError)
    178 {
    179     if(U_FAILURE(status)) {
    180         if (possibleDataError) {
    181             dataerrln(UnicodeString("FAIL: ", "") + msg
    182                   + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),""));
    183         } else {
    184             errcheckln(status, UnicodeString("FAIL: ", "") + msg
    185                   + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),""));
    186         }
    187         return TRUE;
    188     }
    189 
    190     return FALSE;
    191 }
    192 
    193 UBool
    194 NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const char *l, UBool possibleDataError)
    195 {
    196     if(U_FAILURE(status)) {
    197         if (possibleDataError) {
    198             dataerrln(UnicodeString("FAIL: ", "") + msg
    199                   + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, ""));
    200         } else {
    201             errcheckln(status, UnicodeString("FAIL: ", "") + msg
    202                   + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, ""));
    203         }
    204         return TRUE;
    205     }
    206 
    207     return FALSE;
    208 }
    209 
    210 UBool
    211 NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, UBool possibleDataError)
    212 {
    213     if(U_FAILURE(status)) {
    214         if (possibleDataError) {
    215             dataerrln(UnicodeString("FAIL: ", "") + msg
    216                   + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), ""));
    217         } else {
    218             errcheckln(status, UnicodeString("FAIL: ", "") + msg
    219                   + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), ""));
    220         }
    221         return TRUE;
    222     }
    223 
    224     return FALSE;
    225 }
    226 
    227 /**
    228  * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
    229  */
    230 inline UnicodeString str(const char *input)
    231 {
    232   return CharsToUnicodeString(input);
    233 }
    234 
    235 /* @bug 4075713
    236  * NumberFormat.equals comparing with null should always return false.
    237  */
    238 // {sfb} kind of silly in C++, just checking for new success
    239 void NumberFormatRegressionTest::Test4075713(void)
    240 {
    241     //try {
    242         MyNumberFormatTest *tmp = new MyNumberFormatTest();
    243         if(tmp != NULL)
    244             logln("NumberFormat.equals passed");
    245     /*} catch (NullPointerException e) {
    246         errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
    247     }*/
    248 
    249     delete tmp;
    250 }
    251 
    252 /* @bug 4074620
    253  * NumberFormat.equals comparing two obj equal even the setGroupingUsed
    254  * flag is different.
    255  */
    256 void NumberFormatRegressionTest::Test4074620(void)
    257 {
    258 
    259     MyNumberFormatTest *nf1 = new MyNumberFormatTest();
    260     MyNumberFormatTest *nf2 = new MyNumberFormatTest();
    261 
    262     nf1->setGroupingUsed(FALSE);
    263     nf2->setGroupingUsed(TRUE);
    264 
    265     if(nf1 == nf2)
    266         errln("Test for bug 4074620 failed");
    267     else
    268         logln("Test for bug 4074620 passed.");
    269 
    270     delete nf1;
    271     delete nf2;
    272 }
    273 
    274 
    275 /* @bug 4088161
    276  * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
    277  */
    278 
    279 void NumberFormatRegressionTest::Test4088161 (void)
    280 {
    281     UErrorCode status = U_ZERO_ERROR;
    282     DecimalFormat *df = new DecimalFormat(status);
    283     if (!failure(status, "new DecimalFormat", "")) {
    284         double d = 100;
    285         df->setMinimumFractionDigits(0);
    286         df->setMaximumFractionDigits(16);
    287         UnicodeString sBuf1;
    288         FieldPosition fp1(0);
    289         logln(UnicodeString("d = ") + d);
    290         logln("maxFractionDigits = " + df->getMaximumFractionDigits());
    291 
    292         logln(" format(d) = '" + df->format(d, sBuf1, fp1) + "'");
    293         df->setMaximumFractionDigits(17);
    294         UnicodeString sBuf2;
    295         FieldPosition fp2(0);
    296         logln("maxFractionDigits = " + df->getMaximumFractionDigits());
    297         sBuf2 = df->format(d, sBuf2, fp2);
    298         if(sBuf2 != "100")
    299             errln(" format(d) = '" + sBuf2 + "'");
    300     }
    301 
    302     delete df;
    303 }
    304 
    305 /* @bug 4087245
    306  * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
    307  * DecimalFormat(String, DecimalFormatSymbols).
    308  */
    309 void NumberFormatRegressionTest::Test4087245 (void)
    310 {
    311     UErrorCode status = U_ZERO_ERROR;
    312     DecimalFormatSymbols *symbols = new DecimalFormatSymbols(status);
    313     failure(status, "new DecimalFormatSymbols", "");
    314     // {sfb} One note about this test: if you pass in a pointer
    315     // to the symbols, they are adopted and this test will fail,
    316     // even though that is the correct behavior.  To test the cloning
    317     // of the symbols, it is necessary to pass in a reference to the symbols
    318     DecimalFormat *df = new DecimalFormat("#,##0.0", *symbols, status);
    319     failure(status, "new DecimalFormat with symbols", "");
    320     int32_t n = 123;
    321     UnicodeString buf1;
    322     UnicodeString buf2;
    323     FieldPosition pos(FieldPosition::DONT_CARE);
    324     logln(UnicodeString("format(") + n + ") = " +
    325         df->format(n, buf1, pos));
    326     symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, UnicodeString((UChar)0x70)); // change value of field
    327     logln(UnicodeString("format(") + n + ") = " +
    328         df->format(n, buf2, pos));
    329     if(buf1 != buf2)
    330         errln("Test for bug 4087245 failed");
    331 
    332     delete df;
    333     delete symbols;
    334 }
    335 
    336 /* @bug 4087535
    337  * DecimalFormat.format() incorrectly formats 0.0
    338  */
    339 void NumberFormatRegressionTest::Test4087535 (void)
    340 {
    341     UErrorCode status = U_ZERO_ERROR;
    342     DecimalFormat *df = new DecimalFormat(status);
    343     failure(status, "new DecimalFormat", "");
    344     df->setMinimumIntegerDigits(0);
    345 
    346     double n = 0;
    347     UnicodeString buffer;
    348     FieldPosition pos(FieldPosition::DONT_CARE);
    349     buffer = df->format(n, buffer, pos);
    350     if (buffer.length() == 0)
    351         errln(/*n + */": '" + buffer + "'");
    352     n = 0.1;
    353     buffer = df->format(n, buffer, pos);
    354     if (buffer.length() == 0)
    355         errln(/*n + */": '" + buffer + "'");
    356 
    357     delete df;
    358 }
    359 
    360 /* @bug 4088503
    361  * DecimalFormat.format fails when groupingSize is set to 0.
    362  */
    363 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
    364 void NumberFormatRegressionTest::Test4088503 (void)
    365 {
    366     UErrorCode status = U_ZERO_ERROR;
    367     DecimalFormat *df = new DecimalFormat(status);
    368     failure(status, "new DecimalFormat", "");
    369     df->setGroupingSize(0);
    370     UnicodeString sBuf;
    371     FieldPosition fp(FieldPosition::DONT_CARE);
    372     //try {
    373         logln(df->format((int32_t)123, sBuf, fp));
    374         //if(fp == FieldPosition(0))
    375         //    errln("Test for bug 4088503 failed.");
    376     /*} catch (Exception foo) {
    377         errln("Test for bug 4088503 failed.");
    378     }*/
    379     delete df;
    380 
    381 }
    382 /* @bug 4066646
    383  * NumberFormat.getCurrencyInstance is wrong.
    384  */
    385 void NumberFormatRegressionTest::Test4066646 (void)
    386 {
    387     assignFloatValue(2.04f);
    388     assignFloatValue(2.03f);
    389     assignFloatValue(2.02f);
    390     assignFloatValue(0.0f);
    391 }
    392 
    393 float
    394 NumberFormatRegressionTest::assignFloatValue(float returnfloat)
    395 {
    396     logln(UnicodeString(" VALUE ") + returnfloat);
    397     UErrorCode status = U_ZERO_ERROR;
    398     NumberFormat *nfcommon =  NumberFormat::createCurrencyInstance(Locale::getUS(), status);
    399     if (failure(status, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE)){
    400         delete nfcommon;
    401         return returnfloat;
    402     }
    403     nfcommon->setGroupingUsed(FALSE);
    404 
    405     UnicodeString stringValue;
    406     stringValue = nfcommon->format(returnfloat, stringValue);
    407     logln(" DISPLAYVALUE " + stringValue);
    408     Formattable result;
    409     nfcommon->parse(stringValue, result, status);
    410     failure(status, "nfcommon->parse", Locale::getUS());
    411     float floatResult = (float) (result.getType() == Formattable::kDouble
    412                                         ? result.getDouble() : result.getLong());
    413     if( uprv_fabs(floatResult - returnfloat) > 0.0001)
    414     //String stringValue = nfcommon.format(returnfloat).substring(1);
    415     //if (Float.valueOf(stringValue).floatValue() != returnfloat)
    416         errln(UnicodeString("FAIL: expected ") + returnfloat + ", got " + floatResult + " (" + stringValue+")");
    417 
    418     delete nfcommon;
    419     return returnfloat;
    420 } // End Of assignFloatValue()
    421 
    422 /* @bug 4059870
    423  * DecimalFormat throws exception when parsing "0"
    424  */
    425 void NumberFormatRegressionTest::Test4059870(void)
    426 {
    427     UErrorCode status = U_ZERO_ERROR;
    428     DecimalFormat *format = new DecimalFormat("00", status);
    429     failure(status, "new Decimalformat", Locale::getUS());
    430     //try {
    431         Formattable result;
    432         UnicodeString str;
    433         format->parse(UnicodeString("0"), result, status);
    434         failure(status, "format->parse", Locale::getUS());
    435 
    436     /*}
    437     catch (Exception e) {
    438         errln("Test for bug 4059870 failed : " + e);
    439     }*/
    440 
    441     delete format;
    442 }
    443 /* @bug 4083018
    444  * DecimalFormatSymbol.equals should always return false when
    445  * comparing with null.
    446  */
    447 // {sfb} this is silly in C++
    448 void NumberFormatRegressionTest::Test4083018 (void)
    449 {
    450     UErrorCode status = U_ZERO_ERROR;
    451     DecimalFormatSymbols *dfs = new DecimalFormatSymbols(status);
    452     failure(status, "new DecimalFormatSymbols", Locale::getUS());
    453     //try {
    454         if (dfs != NULL)
    455             logln("Test Passed!");
    456         else
    457             errln("Test for bug 4083018 failed");
    458     /*} catch (Exception foo) {
    459         errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
    460     }*/
    461 
    462     delete dfs;
    463 }
    464 
    465 /* @bug 4071492
    466  * DecimalFormat does not round up correctly.
    467  */
    468 void NumberFormatRegressionTest::Test4071492 (void)
    469 {
    470     double x = 0.00159999;
    471     UErrorCode status = U_ZERO_ERROR;
    472     NumberFormat *nf = NumberFormat::createInstance(status);
    473     if (failure(status, "NumberFormat::createInstance", Locale::getUS(), TRUE)) {
    474         delete nf;
    475         return;
    476     }
    477     nf->setMaximumFractionDigits(4);
    478     UnicodeString out;
    479     FieldPosition pos(FieldPosition::DONT_CARE);
    480     out = nf->format(x, out, pos);
    481     logln("0.00159999 formats with 4 fractional digits to " + out);
    482     UnicodeString expected("0.0016");
    483     if (out != expected)
    484         errln("FAIL: Expected " + expected);
    485 
    486     delete nf;
    487 }
    488 
    489 /* @bug 4086575
    490  * A space as a group separator for localized pattern causes
    491  * wrong format.  WorkAround : use non-breaking space.
    492  */
    493 void NumberFormatRegressionTest::Test4086575(void)
    494 {
    495     UErrorCode status = U_ZERO_ERROR;
    496     NumberFormat *nf1 = NumberFormat::createInstance(Locale::getFrance(), status);
    497 
    498     // TODO: There is not a good way to find out that the creation of this number format has
    499     // failed. Major rewiring of format construction proposed.
    500     if(U_FAILURE(status)) {
    501       dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status));
    502       delete nf1;
    503       return;
    504     }
    505     failure(status, "NumberFormat::createInstance", Locale::getFrance());
    506 
    507     // C++ workaround to make sure cast works
    508     DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nf1);
    509     if(nf == NULL) {
    510         errln("NumberFormat::createInstance returned incorrect type.");
    511         return;
    512     }
    513 
    514     UnicodeString temp;
    515     logln("nf toPattern1: " + nf->toPattern(temp));
    516     logln("nf toLocPattern1: " + nf->toLocalizedPattern(temp));
    517 
    518     // No group separator
    519     logln("...applyLocalizedPattern ###,00;(###,00) ");
    520     nf->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status);
    521     failure(status, "nf->applyLocalizedPattern", Locale::getFrance());
    522     logln("nf toPattern2: " + nf->toPattern(temp));
    523     logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp));
    524 
    525     FieldPosition pos(FieldPosition::DONT_CARE);
    526     logln("nf: " + nf->format((int32_t)1234, temp, pos)); // 1234,00
    527     logln("nf: " + nf->format((int32_t)-1234, temp, pos)); // (1234,00)
    528 
    529     // Space as group separator
    530 
    531     logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
    532     // nbsp = \u00a0
    533     //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
    534     UChar patChars[] = {
    535              0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
    536         0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
    537     };
    538     UnicodeString pat(patChars, 19, 19);
    539     nf->applyLocalizedPattern(pat, status);
    540     failure(status, "nf->applyLocalizedPattern", Locale::getFrance());
    541     logln("nf toPattern2: " + nf->toPattern(temp));
    542     logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp));
    543     UnicodeString buffer;
    544     buffer = nf->format((int32_t)1234, buffer, pos);
    545     //if (buffer != UnicodeString("1\u00a0234,00"))
    546     UChar c[] = {
    547         0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
    548     };
    549     UnicodeString cc(c, 8, 8);
    550     if (buffer != cc)
    551         errln("nf : " + buffer); // Expect 1 234,00
    552 
    553     buffer.remove();
    554     buffer = nf->format((int32_t)-1234, buffer, pos);
    555     UChar c1[] = {
    556         0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
    557     };
    558     UnicodeString cc1(c1, 10, 10);
    559     if (buffer != cc1)
    560         errln("nf : " + buffer); // Expect (1 234,00)
    561 
    562     // Erroneously prints:
    563     // 1234,00 ,
    564     // (1234,00 ,)
    565 
    566     delete nf1;
    567 }
    568 /* @bug 4068693
    569  * DecimalFormat.parse returns wrong value
    570  */
    571 // {sfb} slightly converted into a round-trip test, since in C++
    572 // there is no Double.toString()
    573 void NumberFormatRegressionTest::Test4068693(void)
    574 {
    575     logln("----- Test Application -----");
    576     ParsePosition pos(0);
    577     UErrorCode status = U_ZERO_ERROR;
    578     DecimalFormat *df = new DecimalFormat(status);
    579     if(U_FAILURE(status)) {
    580       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
    581       delete df;
    582       return;
    583     }
    584     failure(status, "new DecimalFormat");
    585     Formattable d;
    586     //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
    587     df->parse(UnicodeString("123.55456"), d, pos);
    588     //if (!d.toString().equals("123.55456")) {
    589     UnicodeString dstr;
    590     df->setMaximumFractionDigits(999);
    591     df->setMaximumIntegerDigits(999);
    592     FieldPosition fp(FieldPosition::DONT_CARE);
    593     dstr = df->format(d.getDouble(), dstr, fp);
    594     if (dstr != UnicodeString("123.55456")) {
    595         errln(UnicodeString("Result -> ") + d.getDouble());
    596     }
    597 
    598     delete df;
    599 }
    600 
    601 /* @bug 4069754, 4067878
    602  * null pointer thrown when accessing a deserialized DecimalFormat
    603  * object.
    604  */
    605 // {sfb} doesn't apply in C++
    606 void NumberFormatRegressionTest::Test4069754(void)
    607 {
    608 /*    try {
    609         myformat it = new myformat();
    610         logln(it.Now());
    611         FileOutputStream ostream = new FileOutputStream("t.tmp");
    612         ObjectOutputStream p = new ObjectOutputStream(ostream);
    613         p.writeObject(it);
    614         ostream.close();
    615         logln("Saved ok.");
    616 
    617         FileInputStream istream = new FileInputStream("t.tmp");
    618         ObjectInputStream p2 = new ObjectInputStream(istream);
    619         myformat it2 = (myformat)p2.readObject();
    620         logln(it2.Now());
    621         istream.close();
    622         logln("Loaded ok.");
    623     } catch (Exception foo) {
    624         errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
    625     }
    626 */}
    627 
    628 /* @bug 4087251
    629  * DecimalFormat.applyPattern(String) allows illegal patterns
    630  */
    631 void NumberFormatRegressionTest::Test4087251 (void)
    632 {
    633     UErrorCode status = U_ZERO_ERROR;
    634     DecimalFormat *df = new DecimalFormat(status);
    635     if(U_FAILURE(status)) {
    636       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
    637       delete df;
    638       return;
    639     }
    640     failure(status, "new DecimalFormat");
    641     //try {
    642         df->applyPattern(UnicodeString("#.#.#"), status);
    643         if( ! U_FAILURE(status))
    644             errln("df->applyPattern with illegal pattern didn't fail");
    645         UnicodeString temp;
    646         logln("toPattern() returns \"" + df->toPattern(temp) + "\"");
    647         //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
    648     /*} catch (IllegalArgumentException e) {
    649         logln("Caught Illegal Argument Error !");
    650     }*/
    651     // Second test; added 5/11/98 when reported to fail on 1.2b3
    652     //try {
    653         df->applyPattern("#0.0#0#0", status);
    654         if( ! U_FAILURE(status))
    655             errln("df->applyPattern with illegal pattern didn't fail");
    656         logln("toPattern() returns \"" + df->toPattern(temp) + "\"");
    657         //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
    658     /*} catch (IllegalArgumentException e) {
    659         logln("Ok - IllegalArgumentException for #0.0#0#0");
    660     }*/
    661 
    662     delete df;
    663 }
    664 
    665 /* @bug 4090489
    666  * DecimalFormat.format() loses precision
    667  */
    668 void NumberFormatRegressionTest::Test4090489 (void)
    669 {
    670 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
    671 // that NumberFormat can do.  For some reason, it does not format the last 1.
    672 
    673 /*    UErrorCode status = U_ZERO_ERROR;
    674     DecimalFormat *df = new DecimalFormat(status);
    675     failure(status, "new DecimalFormat");
    676     df->setMinimumFractionDigits(10);
    677     df->setMaximumFractionDigits(999);
    678     df->setGroupingUsed(FALSE);
    679     double d = 1.000000000000001E7;
    680     //BigDecimal bd = new BigDecimal(d);
    681     UnicodeString sb;
    682     FieldPosition fp(0);
    683     logln(UnicodeString("d = ") + d);
    684     //logln("BigDecimal.toString():  " + bd.toString());
    685     df->format(d, sb, fp);
    686     if (sb != "10000000.0000000100") {
    687         errln("DecimalFormat.format(): " + sb);
    688     }
    689 */
    690 }
    691 
    692 /* @bug 4090504
    693  * DecimalFormat.format() loses precision
    694  */
    695 void NumberFormatRegressionTest::Test4090504 (void)
    696 {
    697     double d = 1;
    698     logln(UnicodeString("d = ") + d);
    699     UErrorCode status = U_ZERO_ERROR;
    700     DecimalFormat *df = new DecimalFormat(status);
    701     if(U_FAILURE(status)) {
    702       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
    703       delete df;
    704       return;
    705     }
    706     failure(status, "new DecimalFormat");
    707     UnicodeString sb;
    708     FieldPosition fp(FieldPosition::DONT_CARE);
    709     //try {
    710         for (int i = 17; i <= 20; i++) {
    711             df->setMaximumFractionDigits(i);
    712             //sb = new StringBuffer("");
    713             fp.setField(0);
    714             logln("  getMaximumFractionDigits() = " + i);
    715             logln("  formated: " + df->format(d, sb, fp));
    716         }
    717     /*} catch (Exception foo) {
    718         errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
    719     }*/
    720 
    721     delete df;
    722 }
    723 /* @bug 4095713
    724  * DecimalFormat.parse(String str, ParsePosition pp) loses precision
    725  */
    726 void NumberFormatRegressionTest::Test4095713 (void)
    727 {
    728     UErrorCode status = U_ZERO_ERROR;
    729     DecimalFormat *df = new DecimalFormat(status);
    730     if(U_FAILURE(status)) {
    731       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
    732       delete df;
    733       return;
    734     }
    735     failure(status, "new DecimalFormat");
    736     UnicodeString str("0.1234");
    737     double d1 = 0.1234;
    738     //Double d1 = new Double(str);
    739     //Double d2 = (Double) df.parse(str, new ParsePosition(0));
    740     Formattable d2;
    741     ParsePosition pp(0);
    742     df->parse(str, d2, pp);
    743     logln(UnicodeString("") + d1);
    744     if (d2.getDouble() != d1)
    745         errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2.getDouble());
    746     delete df;
    747 }
    748 
    749 /* @bug 4092561
    750  * DecimalFormat.parse() fails when multiplier is not set to 1
    751  */
    752 // {sfb} not sure what to do with this one
    753 void NumberFormatRegressionTest::Test4092561 (void)
    754 {
    755     UErrorCode status = U_ZERO_ERROR;
    756     DecimalFormat *df = new DecimalFormat(status);
    757     if(U_FAILURE(status)) {
    758       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
    759       delete df;
    760       return;
    761     }
    762     failure(status, "new DecimalFormat");
    763 
    764     // {sfb} going to cheat here and use sprintf ??
    765 
    766     /*UnicodeString str = Long.toString(Long.MIN_VALUE);
    767     logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
    768     df.setMultiplier(100);
    769     Number num = df.parse(str, new ParsePosition(0));
    770     if (num.doubleValue() != -9.223372036854776E16)
    771         errln("Bug 4092561 test failed when multiplier is set to not 1.");
    772 */
    773     delete df;
    774 }
    775 
    776 /* @bug 4092480
    777  * DecimalFormat: Negative format ignored.
    778  */
    779 void NumberFormatRegressionTest::Test4092480 (void)
    780 {
    781     UErrorCode status = U_ZERO_ERROR;
    782     DecimalFormat *dfFoo = new DecimalFormat(UnicodeString("000"), status);
    783     if(U_FAILURE(status)) {
    784       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
    785       delete dfFoo;
    786       return;
    787     }
    788     failure(status, "new DecimalFormat");
    789 
    790     //try {
    791         dfFoo->applyPattern("0000;-000", status);
    792         failure(status, "dfFoo->applyPattern");
    793         UnicodeString temp;
    794         if (dfFoo->toPattern(temp) != UnicodeString("#0000"))
    795             errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
    796         FieldPosition pos(FieldPosition::DONT_CARE);
    797         logln(dfFoo->format((int32_t)42, temp, pos));
    798         logln(dfFoo->format((int32_t)-42, temp, pos));
    799         dfFoo->applyPattern("000;-000", status);
    800         failure(status, "dfFoo->applyPattern");
    801         if (dfFoo->toPattern(temp) != UnicodeString("#000"))
    802             errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
    803         logln(dfFoo->format((int32_t)42,temp, pos));
    804         logln(dfFoo->format((int32_t)-42, temp, pos));
    805 
    806         dfFoo->applyPattern("000;-0000", status);
    807         failure(status, "dfFoo->applyPattern");
    808         if (dfFoo->toPattern(temp) != UnicodeString("#000"))
    809             errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
    810         logln(dfFoo->format((int32_t)42, temp, pos));
    811         logln(dfFoo->format((int32_t)-42, temp, pos));
    812 
    813         dfFoo->applyPattern("0000;-000", status);
    814         failure(status, "dfFoo->applyPattern");
    815         if (dfFoo->toPattern(temp) != UnicodeString("#0000"))
    816             errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
    817         logln(dfFoo->format((int32_t)42, temp, pos));
    818         logln(dfFoo->format((int32_t)-42, temp, pos));
    819     /*} catch (Exception foo) {
    820         errln("Message " + foo.getMessage());
    821     }*/
    822 
    823     delete dfFoo;
    824 }
    825 /* @bug 4087244
    826  * NumberFormat.getCurrencyInstance() produces format that uses
    827  * decimal separator instead of monetary decimal separator.
    828  *
    829  * Rewrote this test not to depend on the actual pattern.  Pattern should
    830  * never contain the monetary separator!  Decimal separator in pattern is
    831  * interpreted as monetary separator if currency symbol is seen!
    832  */
    833 void NumberFormatRegressionTest::Test4087244 (void) {
    834     UErrorCode status = U_ZERO_ERROR;
    835     char loc[256] = {0};
    836     uloc_canonicalize("pt_PT_PREEURO", loc, 256, &status);
    837     Locale *de = new Locale(loc);
    838     NumberFormat *nf = NumberFormat::createCurrencyInstance(*de, status);
    839     if(U_FAILURE(status)) {
    840       dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
    841       delete nf;
    842       return;
    843     }
    844     DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
    845     if(df == NULL) {
    846         errln("expected DecimalFormat!");
    847         return;
    848     }
    849     const DecimalFormatSymbols *sym = df->getDecimalFormatSymbols();
    850     UnicodeString decSep = sym->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
    851     UnicodeString monSep = sym->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
    852     if (decSep == monSep) {
    853         errln("ERROR in test: want decimal sep != monetary sep");
    854         return;
    855     }
    856     df->setMinimumIntegerDigits(1);
    857     df->setMinimumFractionDigits(2);
    858     UnicodeString str;
    859     FieldPosition pos;
    860     df->format(1.23, str, pos);
    861     UnicodeString monStr("1x23");
    862     monStr.replace((int32_t)1, 1, monSep);
    863     UnicodeString decStr("1x23");
    864     decStr.replace((int32_t)1, 1, decSep);
    865     if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) {
    866         logln(UnicodeString("OK: 1.23 -> \"") + str + "\" contains \"" +
    867               monStr + "\" and not \"" + decStr + '"');
    868     } else {
    869         errln(UnicodeString("FAIL: 1.23 -> \"") + str + "\", should contain \"" +
    870               monStr +
    871               "\" and not \"" + decStr + '"');
    872     }
    873     delete de;
    874     delete nf;
    875 }
    876 /* @bug 4070798
    877  * Number format data rounding errors for locale FR
    878  */
    879 void NumberFormatRegressionTest::Test4070798 (void)
    880 {
    881     NumberFormat *formatter;
    882     UnicodeString tempString;
    883 
    884     /* User error :
    885     String expectedDefault = "-5\u00a0789,987";
    886     String expectedCurrency = "5\u00a0789,98\u00a0F";
    887     String expectedPercent = "-578\u00a0998%";
    888     */
    889     UChar chars1 [] = {
    890         0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
    891     };
    892     UChar chars2 [] = {
    893         0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
    894     };
    895     UChar chars3 [] = {
    896         0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
    897     };
    898     UnicodeString expectedDefault(chars1, 10, 10);
    899     UnicodeString expectedCurrency(chars2, 10, 10);
    900     UnicodeString expectedPercent(chars3, 10, 10);
    901 
    902     UErrorCode status = U_ZERO_ERROR;
    903     char loc[256]={0};
    904     int len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
    905     formatter = NumberFormat::createInstance(Locale(loc), status);
    906     if(U_FAILURE(status)) {
    907       dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
    908       delete formatter;
    909       return;
    910     }
    911     failure(status, "NumberFormat::createNumberInstance", loc);
    912     tempString = formatter->format (-5789.9876, tempString);
    913 
    914     if (tempString == expectedDefault) {
    915         logln ("Bug 4070798 default test passed.");
    916     } else {
    917         errln(UnicodeString("Failed:") +
    918         " Expected " + expectedDefault +
    919         " Received " + tempString );
    920     }
    921     delete formatter;
    922     len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
    923     formatter = NumberFormat::createCurrencyInstance(loc, status);
    924     failure(status, "NumberFormat::createCurrencyInstance", loc);
    925     tempString.remove();
    926     tempString = formatter->format( 5789.9876, tempString );
    927 
    928     if (tempString == expectedCurrency) {
    929         logln ("Bug 4070798 currency test passed.");
    930     } else {
    931         errln(UnicodeString("Failed:") +
    932         " Expected " + expectedCurrency +
    933         " Received " + tempString );
    934     }
    935     delete formatter;
    936 
    937     uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
    938     formatter = NumberFormat::createPercentInstance(Locale(loc), status);
    939     failure(status, "NumberFormat::createPercentInstance", loc);
    940     tempString.remove();
    941     tempString = formatter->format (-5789.9876, tempString);
    942 
    943     if (tempString == expectedPercent) {
    944         logln ("Bug 4070798 percentage test passed.");
    945     } else {
    946         errln(UnicodeString("Failed:") +
    947         " Expected " + expectedPercent +
    948         " Received " + tempString );
    949     }
    950 
    951     delete formatter;
    952 }
    953 /* @bug 4071005
    954  * Data rounding errors for French (Canada) locale
    955  */
    956 void NumberFormatRegressionTest::Test4071005 (void)
    957 {
    958     NumberFormat *formatter;
    959     UnicodeString tempString;
    960     /* User error :
    961     String expectedDefault = "-5\u00a0789,987";
    962     String expectedCurrency = "5\u00a0789,98\u00a0$";
    963     String expectedPercent = "-578\u00a0998%";
    964     */
    965     UChar chars1 [] = {
    966         0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
    967     };
    968     UChar chars2 [] = {
    969         0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
    970     };
    971     UChar chars3 [] = {
    972         0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
    973     };
    974     UnicodeString expectedDefault(chars1, 10, 10);
    975     UnicodeString expectedCurrency(chars2, 10, 10);
    976     UnicodeString expectedPercent(chars3, 10, 10);
    977 
    978     UErrorCode status = U_ZERO_ERROR;
    979     formatter = NumberFormat::createInstance(Locale::getCanadaFrench(), status);
    980     if (failure(status, "NumberFormat::createNumberInstance", Locale::getCanadaFrench(), TRUE)){
    981         delete formatter;
    982         return;
    983     };
    984     tempString = formatter->format (-5789.9876, tempString);
    985 
    986     if (tempString == expectedDefault) {
    987         logln ("Bug 4071005 default test passed.");
    988     } else {
    989         errln(UnicodeString("Failed:") +
    990         " Expected " + expectedDefault +
    991         " Received " + tempString );
    992     }
    993     delete formatter;
    994 
    995     formatter = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
    996     failure(status, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
    997     tempString.remove();
    998     tempString = formatter->format( 5789.9876, tempString );
    999 
   1000     if (tempString == expectedCurrency) {
   1001         logln ("Bug 4071005 currency test assed.");
   1002     } else {
   1003         errln(UnicodeString("Failed:") +
   1004         " Expected " + expectedCurrency +
   1005         " Received " + tempString );
   1006     }
   1007     delete formatter;
   1008 
   1009     formatter = NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status);
   1010     failure(status, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
   1011     tempString.remove();
   1012     tempString = formatter->format (-5789.9876, tempString);
   1013 
   1014     if (tempString == expectedPercent) {
   1015         logln ("Bug 4071005 percentage test passed.");
   1016     } else {
   1017         errln(UnicodeString("Failed:") +
   1018         " Expected " + expectedPercent +
   1019         " Received " + tempString );
   1020     }
   1021 
   1022     delete formatter;
   1023 }
   1024 
   1025 /* @bug 4071014
   1026  * Data rounding errors for German (Germany) locale
   1027  */
   1028 void NumberFormatRegressionTest::Test4071014 (void)
   1029 {
   1030     NumberFormat *formatter;
   1031     UnicodeString tempString;
   1032     /* user error :
   1033     String expectedDefault = "-5.789,987";
   1034     String expectedCurrency = "5.789,98 DM";
   1035     String expectedPercent = "-578.998%";
   1036     */
   1037     UnicodeString expectedDefault("-5.789,988");
   1038     UnicodeString expectedCurrency("5.789,99\\u00A0DM");
   1039     UnicodeString expectedPercent("-578.999\\u00A0%");
   1040 
   1041     expectedCurrency = expectedCurrency.unescape();
   1042     expectedPercent = expectedPercent.unescape();
   1043 
   1044     UErrorCode status = U_ZERO_ERROR;
   1045     char loc[256]={0};
   1046     uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
   1047     formatter = NumberFormat::createInstance(Locale(loc), status);
   1048     if (failure(status, "NumberFormat::createNumberInstance", loc, TRUE)){
   1049         delete formatter;
   1050         return;
   1051     }
   1052     tempString.remove();
   1053     tempString = formatter->format (-5789.9876, tempString);
   1054 
   1055     if (tempString == expectedDefault) {
   1056         logln ("Bug 4071014 default test passed.");
   1057     } else {
   1058         errln(UnicodeString("Failed:") +
   1059         " Expected " + expectedDefault +
   1060         " Received " + tempString );
   1061     }
   1062     delete formatter;
   1063     uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
   1064     formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
   1065     failure(status, "NumberFormat::createCurrencyInstance", loc);
   1066     tempString.remove();
   1067     tempString = formatter->format( 5789.9876, tempString );
   1068 
   1069     if (tempString == expectedCurrency) {
   1070         logln ("Bug 4071014 currency test assed.");
   1071     } else {
   1072         errln(UnicodeString("Failed:") +
   1073         " Expected " + expectedCurrency +
   1074         " Received " + tempString );
   1075     }
   1076     delete formatter;
   1077 
   1078     formatter = NumberFormat::createPercentInstance(Locale::getGermany(), status);
   1079     failure(status, "NumberFormat::createPercentInstance", Locale::getGermany());
   1080     tempString.remove();
   1081     tempString = formatter->format (-5789.9876, tempString);
   1082 
   1083     if (tempString == expectedPercent) {
   1084         logln ("Bug 4071014 percentage test passed.");
   1085     } else {
   1086         errln(UnicodeString("Failed:") +
   1087         " Expected " + expectedPercent +
   1088         " Received " + tempString );
   1089     }
   1090 
   1091     delete formatter;
   1092 }
   1093 /* @bug 4071859
   1094  * Data rounding errors for Italian locale number formats
   1095  */
   1096 void NumberFormatRegressionTest::Test4071859 (void)
   1097 {
   1098     NumberFormat *formatter;
   1099     UnicodeString tempString;
   1100     /* user error :
   1101     String expectedDefault = "-5.789,987";
   1102     String expectedCurrency = "-L.\\u00A05.789,98";
   1103     String expectedPercent = "-578.998%";
   1104     */
   1105     UnicodeString expectedDefault("-5.789,988");
   1106     UnicodeString expectedCurrency("-IT\\u20A4\\u00A05.790", -1, US_INV);
   1107     UnicodeString expectedPercent("-578.999%");
   1108     expectedCurrency = expectedCurrency.unescape();
   1109 
   1110     UErrorCode status = U_ZERO_ERROR;
   1111     char loc[256]={0};
   1112     uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
   1113     formatter = NumberFormat::createInstance(Locale(loc), status);
   1114     if (failure(status, "NumberFormat::createNumberInstance", TRUE)){
   1115         delete formatter;
   1116         return;
   1117     };
   1118     tempString = formatter->format (-5789.9876, tempString);
   1119 
   1120     if (tempString == expectedDefault) {
   1121         logln ("Bug 4071859 default test passed.");
   1122     } else {
   1123         errln(UnicodeString("Failed:") +
   1124         " Expected " + expectedDefault +
   1125         " Received " + tempString );
   1126     }
   1127     delete formatter;
   1128     uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
   1129     formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
   1130     failure(status, "NumberFormat::createCurrencyInstance");
   1131     tempString.remove();
   1132     tempString = formatter->format( -5789.9876, tempString );
   1133 
   1134     if (tempString == expectedCurrency) {
   1135         logln ("Bug 4071859 currency test assed.");
   1136     } else {
   1137         errln(UnicodeString("Failed:") +
   1138         " Expected " + expectedCurrency +
   1139         " Received " + tempString );
   1140     }
   1141     delete formatter;
   1142     uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
   1143     formatter = NumberFormat::createPercentInstance(Locale(loc), status);
   1144     failure(status, "NumberFormat::createPercentInstance");
   1145     tempString.remove();
   1146     tempString = formatter->format (-5789.9876, tempString);
   1147 
   1148     if (tempString == expectedPercent) {
   1149         logln ("Bug 4071859 percentage test passed.");
   1150     } else {
   1151         errln(UnicodeString("Failed:") +
   1152         " Expected " + expectedPercent +
   1153         " Received " + tempString );
   1154     }
   1155 
   1156     delete formatter;
   1157 }
   1158 /* @bug 4071859
   1159  * Test rounding for nearest even.
   1160  */
   1161 void NumberFormatRegressionTest::Test4093610(void)
   1162 {
   1163     UErrorCode status = U_ZERO_ERROR;
   1164     DecimalFormat *df = new DecimalFormat("#0.#", status);
   1165     if (!failure(status, "new DecimalFormat")) {
   1166         UnicodeString s("12.4");
   1167         roundingTest(df, 12.35, s);
   1168         roundingTest(df, 12.45, s);
   1169         s = "12.5";
   1170         roundingTest(df, 12.452,s);
   1171         s = "12.6";
   1172         roundingTest(df, 12.55, s);
   1173         roundingTest(df, 12.65, s);
   1174         s = "12.7";
   1175         roundingTest(df, 12.652,s);
   1176         s = "12.8";
   1177         roundingTest(df, 12.75, s);
   1178         roundingTest(df, 12.752,s);
   1179         roundingTest(df, 12.85, s);
   1180         s = "12.9";
   1181         roundingTest(df, 12.852,s);
   1182         s = "13";
   1183         roundingTest(df, 12.95, s);
   1184         roundingTest(df, 12.952,s);
   1185     }
   1186 
   1187     delete df;
   1188 }
   1189 
   1190 void NumberFormatRegressionTest::roundingTest(DecimalFormat *df, double x, UnicodeString& expected)
   1191 {
   1192     UnicodeString out;
   1193     FieldPosition pos(FieldPosition::DONT_CARE);
   1194     out = df->format(x, out, pos);
   1195     logln(UnicodeString("") + x + " formats with 1 fractional digits to " + out);
   1196     if (out != expected)
   1197         errln("FAIL: Expected " + expected);
   1198 }
   1199 /* @bug 4098741
   1200  * Tests the setMaximumFractionDigits limit.
   1201  */
   1202 void NumberFormatRegressionTest::Test4098741(void)
   1203 {
   1204     //try {
   1205     UErrorCode status = U_ZERO_ERROR;
   1206     NumberFormat *fmt = NumberFormat::createPercentInstance(status);
   1207     if (U_FAILURE(status)) {
   1208         dataerrln("Error calling NumberFormat::createPercentInstance");
   1209         delete fmt;
   1210         return;
   1211     }
   1212 
   1213         fmt->setMaximumFractionDigits(20);
   1214         UnicodeString temp;
   1215         logln(fmt->format(.001, temp));
   1216     /*} catch (Exception foo) {
   1217         errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
   1218     }*/
   1219     delete fmt;
   1220 }
   1221 /* @bug 4074454
   1222  * Tests illegal pattern exception.
   1223  * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
   1224  * Part2 has been fixed.
   1225  */
   1226 void NumberFormatRegressionTest::Test4074454(void)
   1227 {
   1228     //try {
   1229     UErrorCode status = U_ZERO_ERROR;
   1230     DecimalFormat *fmt = new DecimalFormat("#,#00.00;-#.#", status);
   1231     if(U_FAILURE(status)) {
   1232       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1233       delete fmt;
   1234       return;
   1235     }
   1236     failure(status, "new DecimalFormat");
   1237       logln("Inconsistent negative pattern is fine.");
   1238         DecimalFormat *newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status);
   1239         failure(status, "new DecimalFormat");
   1240         UnicodeString tempString;
   1241         FieldPosition pos(FieldPosition::DONT_CARE);
   1242         tempString = newFmt->format(3456.78, tempString, pos);
   1243         if (tempString != UnicodeString("3,456.78 p'ieces"))
   1244             dataerrln("Failed!  3456.78 p'ieces expected, but got : " + tempString);
   1245     /*} catch (Exception foo) {
   1246         errln("An exception was thrown for any inconsistent negative pattern.");
   1247     }*/
   1248 
   1249     delete fmt;
   1250     delete newFmt;
   1251 }
   1252 /* @bug 4099404
   1253  * Tests all different comments.
   1254  * Response to some comments :
   1255  * [1] DecimalFormat.parse API documentation is more than just one line.
   1256  * This is not a reproducable doc error in 116 source code.
   1257  * [2] See updated javadoc.
   1258  * [3] Fixed.
   1259  * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
   1260  * a null object will be returned.  The unchanged parse position also
   1261  * reflects an error.
   1262  * NumberFormat.parse(String) : If parsing fails, an ParseException
   1263  * will be thrown.
   1264  * See updated javadoc for more details.
   1265  * [5] See updated javadoc.
   1266  * [6] See updated javadoc.
   1267  * [7] This is a correct behavior if the DateFormat object is linient.
   1268  * Otherwise, an IllegalArgumentException will be thrown when formatting
   1269  * "January 35".  See GregorianCalendar class javadoc for more details.
   1270  */
   1271 void NumberFormatRegressionTest::Test4099404(void)
   1272 {
   1273     //try {
   1274         UErrorCode status = U_ZERO_ERROR;
   1275         DecimalFormat *fmt = new DecimalFormat(UnicodeString("000.0#0"), status);
   1276         if(! U_FAILURE(status))
   1277             errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
   1278     /*} catch (Exception foo) {
   1279         logln("Bug 4099404 pattern \"000.0#0\" passed");
   1280     }*/
   1281     delete fmt;
   1282     fmt = 0;
   1283         //try {
   1284         fmt = new DecimalFormat(UnicodeString("0#0.000"), status);
   1285         if( !U_FAILURE(status))
   1286            errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
   1287     /*} catch (Exception foo) {
   1288         logln("Bug 4099404 pattern \"0#0.000\" passed");
   1289     }*/
   1290 
   1291     delete fmt;
   1292 }
   1293 /* @bug 4101481
   1294  * DecimalFormat.applyPattern doesn't set minimum integer digits
   1295  */
   1296 void NumberFormatRegressionTest::Test4101481(void)
   1297 {
   1298     UErrorCode status = U_ZERO_ERROR;
   1299     DecimalFormat *sdf = new DecimalFormat(UnicodeString("#,##0"), status);
   1300     if(U_FAILURE(status)) {
   1301       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1302       delete sdf;
   1303       return;
   1304     }
   1305     failure(status, "new DecimalFormat");
   1306     if (sdf->getMinimumIntegerDigits() != 1)
   1307         errln("Minimum integer digits : " + sdf->getMinimumIntegerDigits());
   1308     delete sdf;
   1309 }
   1310 /* @bug 4052223 (API addition request A27)
   1311  * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
   1312  */
   1313 void NumberFormatRegressionTest::Test4052223(void)
   1314 {
   1315     //try {
   1316     UErrorCode status = U_ZERO_ERROR;
   1317         DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,#00.00"), status);
   1318         if(U_FAILURE(status)) {
   1319           errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1320           delete fmt;
   1321           return;
   1322         }
   1323         failure(status, "new DecimalFormat");
   1324         Formattable num;
   1325         fmt->parse(UnicodeString("abc3"), num, status);
   1326         if(! U_FAILURE(status))
   1327             errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\".  Got ") /*+ num*/);
   1328     /*} catch (ParseException foo) {
   1329         logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
   1330     }*/
   1331     delete fmt;
   1332 }
   1333 /* @bug 4061302
   1334  * API tests for API addition request A9.
   1335  */
   1336 void NumberFormatRegressionTest::Test4061302(void)
   1337 {
   1338     UErrorCode status = U_ZERO_ERROR;
   1339     DecimalFormatSymbols *fmt = new DecimalFormatSymbols(status);
   1340     failure(status, "new DecimalFormatSymbols");
   1341     UnicodeString currency(fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
   1342     UnicodeString intlCurrency(fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
   1343     UnicodeString monDecSeparator(fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
   1344     if (currency == UnicodeString("") ||
   1345         intlCurrency == UnicodeString("") ||
   1346         monDecSeparator == UnicodeString(""))
   1347     {
   1348         errln("getCurrencySymbols failed, got empty string.");
   1349     }
   1350     UnicodeString monDecSeparatorStr;
   1351     monDecSeparatorStr.append(monDecSeparator);
   1352     logln((UnicodeString)"Before set ==> Currency : " + currency +(UnicodeString)" Intl Currency : " + intlCurrency + (UnicodeString)" Monetary Decimal Separator : " + monDecSeparatorStr);
   1353     fmt->setSymbol(DecimalFormatSymbols::kCurrencySymbol, UnicodeString("XYZ"));
   1354     fmt->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, UnicodeString("ABC"));
   1355     fmt->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, UnicodeString((UChar)0x002A/*'*'*/));
   1356     currency = fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol);
   1357     intlCurrency = fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
   1358     monDecSeparator = fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
   1359     if (currency != UnicodeString("XYZ") ||
   1360         intlCurrency != UnicodeString("ABC") ||
   1361         monDecSeparator != UnicodeString((UChar)0x002A/*'*'*/)) {
   1362         errln("setCurrencySymbols failed.");
   1363     }
   1364     monDecSeparatorStr.remove();
   1365     monDecSeparatorStr.append(monDecSeparator);
   1366     logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparatorStr);
   1367 
   1368     delete fmt;
   1369 }
   1370 /* @bug 4062486
   1371  * API tests for API addition request A23. FieldPosition.getBeginIndex and
   1372  * FieldPosition.getEndIndex.
   1373  */
   1374 void NumberFormatRegressionTest::Test4062486(void)
   1375 {
   1376     UErrorCode status = U_ZERO_ERROR;
   1377     DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,##0.00"), status);
   1378     failure(status, "new DecimalFormat");
   1379     UnicodeString formatted;
   1380     FieldPosition field(0);
   1381     double num = 1234.5;
   1382     fmt->format(num, formatted, field);
   1383     if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
   1384         errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
   1385     field.setBeginIndex(7);
   1386     field.setEndIndex(4);
   1387     if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
   1388         errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
   1389 
   1390     delete fmt;
   1391 }
   1392 
   1393 /* @bug 4108738
   1394  * DecimalFormat.parse incorrectly works with a group separator.
   1395  */
   1396 void NumberFormatRegressionTest::Test4108738(void)
   1397 {
   1398     UErrorCode status = U_ZERO_ERROR;
   1399     DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getUS(), status);
   1400     failure(status, "new DecimalFormatSymbols");
   1401     DecimalFormat *df = new DecimalFormat("#,##0.###", syms, status);
   1402     if(U_FAILURE(status)) {
   1403       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1404       delete df;
   1405       return;
   1406     }
   1407     failure(status, "new DecimalFormat");
   1408     UnicodeString text("1.222,111");
   1409     Formattable num;
   1410     ParsePosition pp(0);
   1411     df->parse(text, num, pp);
   1412 
   1413     // {sfb} how to do this (again) ?
   1414     // shouldn't just be another round-trip test, should it?
   1415     UnicodeString temp;
   1416     FieldPosition pos(FieldPosition::DONT_CARE);
   1417     temp = df->format(num.getDouble(), temp, pos);
   1418     //if (!num.toString().equals("1.222"))
   1419     if (temp != UnicodeString("1.222"))
   1420         //errln("\"" + text + "\"  is parsed as " + num);
   1421         errln("\"" + text + "\"  is parsed as " + temp);
   1422     text = UnicodeString("1.222x111");
   1423     pp = ParsePosition(0);
   1424     df->parse(text, num, pp);
   1425     temp.remove();
   1426     temp = df->format(num.getDouble(), temp, pos);
   1427     //if (!num.toString().equals("1.222"))
   1428     if (temp != UnicodeString("1.222"))
   1429         errln("\"" + text + "\"  is parsed as " + temp);
   1430 
   1431     delete df;
   1432 }
   1433 
   1434 /* @bug 4106658
   1435  * DecimalFormat.format() incorrectly formats negative doubles.
   1436  */
   1437 void NumberFormatRegressionTest::Test4106658(void)
   1438 {
   1439     UErrorCode status = U_ZERO_ERROR;
   1440     DecimalFormat *df = new DecimalFormat(status); // Corrected; see 4147706
   1441     if(U_FAILURE(status)) {
   1442       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1443       delete df;
   1444       return;
   1445     }
   1446     failure(status, "new DecimalFormat");
   1447     volatile double d1 = 0.0;   // volatile to prevent code optimization
   1448     double d2 = -0.0001;
   1449     UnicodeString buffer;
   1450     UnicodeString temp;
   1451     FieldPosition pos(FieldPosition::DONT_CARE);
   1452 
   1453 #if defined(U_HPUX)
   1454     d1 = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
   1455 #else
   1456     d1 *= -1.0; // Some compilers have a problem with defining -0.0
   1457 #endif
   1458     logln("pattern: \"" + df->toPattern(temp) + "\"");
   1459     df->format(d1, buffer, pos);
   1460     if (buffer != UnicodeString("-0")) // Corrected; see 4147706
   1461         errln(UnicodeString("") + d1 + "      is formatted as " + buffer);
   1462     buffer.remove();
   1463     df->format(d2, buffer, pos);
   1464     if (buffer != UnicodeString("-0")) // Corrected; see 4147706
   1465         errln(UnicodeString("") + d2 + "      is formatted as " + buffer);
   1466 
   1467     delete df;
   1468 }
   1469 
   1470 /* @bug 4106662
   1471  * DecimalFormat.parse returns 0 if string parameter is incorrect.
   1472  */
   1473 void NumberFormatRegressionTest::Test4106662(void)
   1474 {
   1475     UErrorCode status = U_ZERO_ERROR;
   1476     DecimalFormat *df = new DecimalFormat(status);
   1477     if(U_FAILURE(status)) {
   1478       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1479       delete df;
   1480       return;
   1481     }
   1482     failure(status, "new DecimalFormat");
   1483     UnicodeString text("x");
   1484     ParsePosition pos1(0), pos2(0);
   1485 
   1486     UnicodeString temp;
   1487     logln("pattern: \"" + df->toPattern(temp) + "\"");
   1488     Formattable num;
   1489     df->parse(text, num, pos1);
   1490     if (pos1 == ParsePosition(0)/*num != null*/) {
   1491         errln(UnicodeString("Test Failed: \"") + text + "\" is parsed as " /*+ num*/);
   1492     }
   1493     delete df;
   1494     df = new DecimalFormat(UnicodeString("$###.00"), status);
   1495     failure(status, "new DecimalFormat");
   1496     df->parse(UnicodeString("$"), num, pos2);
   1497     if (pos2 == ParsePosition(0) /*num != null*/){
   1498         errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
   1499     }
   1500 
   1501     delete df;
   1502 }
   1503 
   1504 /* @bug 4114639 (duplicate of 4106662)
   1505  * NumberFormat.parse doesn't return null
   1506  */
   1507 void NumberFormatRegressionTest::Test4114639(void)
   1508 {
   1509     UErrorCode status = U_ZERO_ERROR;
   1510     NumberFormat *format = NumberFormat::createInstance(status);
   1511     if(U_FAILURE(status)) {
   1512       dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
   1513       delete format;
   1514       return;
   1515     }
   1516     failure(status, "NumberFormat::createInstance");
   1517     UnicodeString text("time 10:x");
   1518     ParsePosition pos(8);
   1519     Formattable result;
   1520     format->parse(text, result, pos);
   1521     if (/*result != null*/pos.getErrorIndex() != 8)
   1522         errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
   1523 
   1524     delete format;
   1525 }
   1526 
   1527 /* @bug 4106664
   1528  * TODO: this test does not work because we need to use a 64 bit number and a
   1529  * a double only MAY only have 52 bits of precision.
   1530  * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
   1531  */
   1532 void NumberFormatRegressionTest::Test4106664(void)
   1533 {
   1534     UErrorCode status = U_ZERO_ERROR;
   1535     DecimalFormat *df = new DecimalFormat(status);
   1536     if(U_FAILURE(status)) {
   1537       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1538       delete df;
   1539       return;
   1540     }
   1541     failure(status, "new DecimalFormat");
   1542     // {sfb} long in java is 64 bits
   1543     /*long*/double n = 1234567890123456.0;
   1544     /*int*/int32_t m = 12345678;
   1545     // {sfb} will this work?
   1546     //BigInteger bigN = BigInteger.valueOf(n);
   1547     //bigN = bigN.multiply(BigInteger.valueOf(m));
   1548     double bigN = n * m;
   1549     df->setMultiplier(m);
   1550     df->setGroupingUsed(FALSE);
   1551     UnicodeString temp;
   1552     FieldPosition pos(FieldPosition::DONT_CARE);
   1553     logln("formated: " +
   1554         df->format(n, temp, pos));
   1555 
   1556     char buf [128];
   1557     sprintf(buf, "%g", bigN);
   1558     //logln("expected: " + bigN.toString());
   1559     logln(UnicodeString("expected: ") + buf);
   1560 
   1561     delete df;
   1562 }
   1563 /* @bug 4106667 (duplicate of 4106658)
   1564  * DecimalFormat.format incorrectly formats -0.0.
   1565  */
   1566 void NumberFormatRegressionTest::Test4106667(void)
   1567 {
   1568     UErrorCode status = U_ZERO_ERROR;
   1569     DecimalFormat *df = new DecimalFormat(status);
   1570     if(U_FAILURE(status)) {
   1571       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1572       delete df;
   1573       return;
   1574     }
   1575     failure(status, "new DecimalFormat");
   1576     UChar foo [] = { 0x002B };
   1577     UnicodeString bar(foo, 1, 1);
   1578     volatile double d = 0.0;   // volatile to prevent code optimization
   1579     UnicodeString temp;
   1580     UnicodeString buffer;
   1581     FieldPosition pos(FieldPosition::DONT_CARE);
   1582 
   1583     logln("pattern: \"" + df->toPattern(temp) + "\"");
   1584 #if defined(U_HPUX)
   1585     d = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
   1586 #else
   1587     d *= -1.0; // Some compilers have a problem with defining -0.0
   1588 #endif
   1589     df->setPositivePrefix(/*"+"*/bar);
   1590     df->format(d, buffer, pos);
   1591     if (buffer != UnicodeString("-0")) // Corrected; see 4147706
   1592         errln(/*d + */UnicodeString("  is formatted as ") + buffer);
   1593 
   1594     delete df;
   1595 }
   1596 
   1597 /* @bug 4110936
   1598  * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
   1599  */
   1600 #ifdef OS390
   1601 #   define MAX_INT_DIGITS 70
   1602 #else
   1603 #   define MAX_INT_DIGITS 128
   1604 #endif
   1605 
   1606 void NumberFormatRegressionTest::Test4110936(void)
   1607 {
   1608     UErrorCode status = U_ZERO_ERROR;
   1609     NumberFormat *nf = NumberFormat::createInstance(status);
   1610     if(U_FAILURE(status)) {
   1611       dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
   1612       delete nf;
   1613       return;
   1614     }
   1615     failure(status, "NumberFormat::createInstance");
   1616     nf->setMaximumIntegerDigits(MAX_INT_DIGITS);
   1617     logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
   1618     if (nf->getMaximumIntegerDigits() != MAX_INT_DIGITS)
   1619         errln("getMaximumIntegerDigits() returns " +
   1620             nf->getMaximumIntegerDigits());
   1621 
   1622     delete nf;
   1623 }
   1624 
   1625 /* @bug 4122840
   1626  * Locale data should use generic currency symbol
   1627  *
   1628  * 1) Make sure that all currency formats use the generic currency symbol.
   1629  * 2) Make sure we get the same results using the generic symbol or a
   1630  *    hard-coded one.
   1631  */
   1632 void NumberFormatRegressionTest::Test4122840(void)
   1633 {
   1634     int32_t count = 0;
   1635     const Locale *locales = Locale::getAvailableLocales(count);
   1636 
   1637     for (int i = 0; i < count; i++) {
   1638         UErrorCode status = U_ZERO_ERROR;
   1639         ResourceBundle *rb = new ResourceBundle(
   1640             NULL/*"java.text.resources.LocaleElements"*/,
   1641             locales[i], status);
   1642         failure(status, "new ResourceBundle");
   1643         ResourceBundle numPat = rb->getWithFallback("NumberElements", status);
   1644         failure(status, "rb.get(NumberElements)");
   1645         numPat = numPat.getWithFallback("latn",status);
   1646         failure(status, "rb.get(latn)");
   1647         numPat = numPat.getWithFallback("patterns",status);
   1648         failure(status, "rb.get(patterns)");
   1649         numPat = numPat.getWithFallback("currencyFormat",status);
   1650         failure(status, "rb.get(currencyFormat)");
   1651        //
   1652         // Get the currency pattern for this locale.  We have to fish it
   1653         // out of the ResourceBundle directly, since DecimalFormat.toPattern
   1654         // will return the localized symbol, not \00a4
   1655         //
   1656         UnicodeString pattern = numPat.getString(status);
   1657         failure(status, "rb->getString()");
   1658 
   1659         UChar fo[] = { 0x00A4 };
   1660         UnicodeString foo(fo, 1, 1);
   1661 
   1662         //if (pattern.indexOf("\u00A4") == -1 ) {
   1663         if (pattern.indexOf(foo) == -1 ) {
   1664             errln(UnicodeString("Currency format for ") + UnicodeString(locales[i].getName()) +
   1665                     " does not contain generic currency symbol:" +
   1666                     pattern );
   1667         }
   1668 
   1669         // Create a DecimalFormat using the pattern we got and format a number
   1670         DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status);
   1671         failure(status, "new DecimalFormatSymbols");
   1672         DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status);
   1673         failure(status, "new DecimalFormat");
   1674 
   1675         UnicodeString result1;
   1676         FieldPosition pos(FieldPosition::DONT_CARE);
   1677         result1 = fmt1->format(1.111, result1, pos);
   1678 
   1679         //
   1680         // Now substitute in the locale's currency symbol and create another
   1681         // pattern.  We have to skip locales where the currency symbol
   1682         // contains decimal separators, because that confuses things
   1683         //
   1684         UChar ba[] = { 0x002E/*'.'*/ };
   1685         UnicodeString bar(ba, 1, 1);
   1686 
   1687         if (symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).indexOf(bar) == -1) {
   1688             // {sfb} Also, switch the decimal separator to the monetary decimal
   1689             // separator to mimic the behavior of a currency format
   1690             symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol,
   1691                 symbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
   1692 
   1693             UnicodeString buf(pattern);
   1694             for (int j = 0; j < buf.length(); j++) {
   1695                 if (buf[j] == 0x00a4 ) {
   1696                     if(buf[j + 1] == 0x00a4) {
   1697                         // {sfb} added to support double currency marker (intl currency sign)
   1698                         buf.replace(j, /*j+*/2, symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
   1699                         j += symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol).length();
   1700                     }
   1701                     else {
   1702                         buf.replace(j, /*j+*/1, symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
   1703                         j += symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).length() - 1;
   1704                     }
   1705                 }
   1706             }
   1707 
   1708             DecimalFormat *fmt2 = new DecimalFormat(buf, *symbols, status);
   1709             failure(status, "new DecimalFormat");
   1710 
   1711             // Get the currency (if there is one) so we can set the rounding and fraction
   1712             const UChar *currency = fmt1->getCurrency();
   1713             if (*currency != 0) {
   1714                 double rounding = ucurr_getRoundingIncrement(currency, &status);
   1715                 int32_t frac = ucurr_getDefaultFractionDigits(currency, &status);
   1716                 if (U_SUCCESS(status)) {
   1717                     fmt2->setRoundingIncrement(rounding);
   1718                     fmt2->setMinimumFractionDigits(frac);
   1719                     fmt2->setMaximumFractionDigits(frac);
   1720                 }
   1721                 else {
   1722                     failure(status, "Fetching currency rounding/fractions");
   1723                 }
   1724             }
   1725 
   1726             UnicodeString result2;
   1727             fmt2->format(1.111, result2, pos);
   1728 
   1729             if (result1 != result2) {
   1730                 errln("Results for " + (UnicodeString)(locales[i].getName()) + " differ: " +
   1731                         result1 + " vs " + result2);
   1732             }
   1733 
   1734             delete fmt2;
   1735         }
   1736 
   1737         delete rb;
   1738         delete fmt1;
   1739         delete symbols;
   1740     }
   1741 }
   1742 
   1743 /* @bug 4125885
   1744  * DecimalFormat.format() delivers wrong string.
   1745  */
   1746 void NumberFormatRegressionTest::Test4125885(void)
   1747 {
   1748     UErrorCode status = U_ZERO_ERROR;
   1749     double rate = 12.34;
   1750     DecimalFormat *formatDec = new DecimalFormat ("000.00", status);
   1751     if(U_FAILURE(status)) {
   1752       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
   1753       delete formatDec;
   1754       return;
   1755     }
   1756     failure(status, "new DecimalFormat");
   1757     UnicodeString temp;
   1758     logln("toPattern: " + formatDec->toPattern(temp));
   1759     UnicodeString rateString;
   1760     FieldPosition pos(FieldPosition::DONT_CARE);
   1761     rateString = formatDec->format(rate, rateString, pos);
   1762     if (rateString != UnicodeString("012.34"))
   1763         errln("result : " + rateString + " expected : 012.34");
   1764     rate = 0.1234;
   1765     delete formatDec;// = null;
   1766     formatDec = new DecimalFormat ("+000.00%;-000.00%", status);
   1767     failure(status, "new DecimalFormat");
   1768     logln("toPattern: " + formatDec->toPattern(temp));
   1769     rateString.remove();
   1770     rateString = formatDec->format(rate, rateString, pos);
   1771     if (rateString != UnicodeString("+012.34%"))
   1772         errln("result : " + rateString + " expected : +012.34%");
   1773 
   1774     delete formatDec;
   1775 }
   1776 
   1777 /**
   1778  * @bug 4134034
   1779  * DecimalFormat produces extra zeros when formatting numbers.
   1780  */
   1781 void NumberFormatRegressionTest::Test4134034(void)
   1782 {
   1783     UErrorCode status = U_ZERO_ERROR;
   1784     DecimalFormat *nf = new DecimalFormat("##,###,###.00", status);
   1785     if (!failure(status, "new DecimalFormat")) {
   1786         UnicodeString f;
   1787         FieldPosition pos(FieldPosition::DONT_CARE);
   1788         f = nf->format(9.02, f, pos);
   1789         if (f == UnicodeString("9.02"))
   1790             logln(f + " ok");
   1791         else
   1792             errln("9.02 -> " + f + "; want 9.02");
   1793 
   1794         f.remove();
   1795         f = nf->format((int32_t)0, f, pos);
   1796         if (f == UnicodeString(".00"))
   1797             logln(f + " ok");
   1798         else
   1799             errln("0 -> " + f + "; want .00");
   1800     }
   1801 
   1802     delete nf;
   1803 }
   1804 
   1805 /**
   1806  * @bug 4134300
   1807  * CANNOT REPRODUCE - This bug could not be reproduced.  It may be
   1808  * a duplicate of 4134034.
   1809  *
   1810  * JDK 1.1.6 Bug, did NOT occur in 1.1.5
   1811  * Possibly related to bug 4125885.
   1812  *
   1813  * This class demonstrates a regression in version 1.1.6
   1814  * of DecimalFormat class.
   1815  *
   1816  * 1.1.6 Results
   1817  * Value 1.2 Format #.00 Result '01.20' !!!wrong
   1818  * Value 1.2 Format 0.00 Result '001.20' !!!wrong
   1819  * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
   1820  * Value 1.2 Format #0.0# Result '1.2'
   1821  * Value 1.2 Format #0.00 Result '001.20' !!!wrong
   1822  *
   1823  * 1.1.5 Results
   1824  * Value 1.2 Format #.00 Result '1.20'
   1825  * Value 1.2 Format 0.00 Result '1.20'
   1826  * Value 1.2 Format 00.00 Result '01.20'
   1827  * Value 1.2 Format #0.0# Result '1.2'
   1828  * Value 1.2 Format #0.00 Result '1.20'
   1829  */
   1830 void NumberFormatRegressionTest::Test4134300(void) {
   1831     UnicodeString DATA [] = {
   1832      // Pattern      Expected string
   1833         UnicodeString("#.00"),      UnicodeString("1.20"),
   1834         UnicodeString("0.00"),      UnicodeString("1.20"),
   1835         UnicodeString("00.00"),     UnicodeString("01.20"),
   1836         UnicodeString("#0.0#"),     UnicodeString("1.2"),
   1837         UnicodeString("#0.00"),     UnicodeString("1.20")
   1838     };
   1839 
   1840     for (int i=0; i< 10; i+=2) {
   1841         UnicodeString result;
   1842         UErrorCode status = U_ZERO_ERROR;
   1843         DecimalFormat *df = new DecimalFormat(DATA[i], status);
   1844         if (!failure(status, "new DecimalFormat")) {
   1845             FieldPosition pos(FieldPosition::DONT_CARE);
   1846             result = df->format(1.2, result, pos);
   1847             if (result != DATA[i+1]) {
   1848                 errln("Fail: 1.2 x " + DATA[i] + " = " + result +
   1849                       "; want " + DATA[i+1]);
   1850             }
   1851             else {
   1852                 logln("Ok: 1.2 x " + DATA[i] + " = " + result);
   1853             }
   1854         }
   1855 
   1856         delete df;
   1857     }
   1858 }
   1859 
   1860 /**
   1861  * @bug 4140009
   1862  * Empty pattern produces double negative prefix.
   1863  */
   1864 void NumberFormatRegressionTest::Test4140009(void)
   1865 {
   1866     UErrorCode status = U_ZERO_ERROR;
   1867     DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status);
   1868     failure(status, "new DecimalFormatSymbols");
   1869     DecimalFormat *f = new DecimalFormat(UnicodeString(""), syms, status);
   1870     if (!failure(status, "new DecimalFormat")) {
   1871         UnicodeString s;
   1872         FieldPosition pos(FieldPosition::DONT_CARE);
   1873         s = f->format(123.456, s, pos);
   1874         if (s != UnicodeString("123.456"))
   1875             errln("Fail: Format empty pattern x 123.456 => " + s);
   1876         s.remove();
   1877         s = f->format(-123.456, s, pos);
   1878         if (s != UnicodeString("-123.456"))
   1879             errln("Fail: Format empty pattern x -123.456 => " + s);
   1880     }
   1881     delete f;
   1882 }
   1883 
   1884 /**
   1885  * @bug 4141750
   1886  * BigDecimal numbers get their fractions truncated by NumberFormat.
   1887  */
   1888 // {sfb} not pertinent in C++ ??
   1889 void NumberFormatRegressionTest::Test4141750(void) {
   1890     /*try {
   1891         UnicodeString str("12345.67");
   1892         BigDecimal bd = new BigDecimal(str);
   1893         String sd = NumberFormat.getInstance(Locale.US).format(bd);
   1894         if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
   1895     }
   1896     catch (Exception e) {
   1897         errln(e.toString());
   1898         e.printStackTrace();
   1899     }*/
   1900 }
   1901 
   1902 /**
   1903  * @bug 4145457
   1904  * DecimalFormat toPattern() doesn't quote special characters or handle
   1905  * single quotes.
   1906  */
   1907 void NumberFormatRegressionTest::Test4145457() {
   1908     //try {
   1909     UErrorCode status = U_ZERO_ERROR;
   1910     NumberFormat *nff = NumberFormat::createInstance(status);
   1911     if (failure(status, "NumberFormat::createInstance", TRUE)){
   1912         delete nff;
   1913         return;
   1914     };
   1915     DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nff);
   1916     if(nf == NULL) {
   1917         errln("DecimalFormat needed to continue");
   1918         return;
   1919     }
   1920 
   1921     DecimalFormatSymbols *sym = (DecimalFormatSymbols*) nf->getDecimalFormatSymbols();
   1922     sym->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, (UChar)/*'\''*/0x0027);
   1923     nf->setDecimalFormatSymbols(*sym);
   1924     double pi = 3.14159;
   1925 
   1926     UnicodeString PATS [] = {
   1927         UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
   1928     };
   1929 
   1930     for (int32_t i=0; i<2; ++i) {
   1931         nf->applyPattern(PATS[i], status);
   1932         failure(status, "nf->applyPattern");
   1933         UnicodeString out;
   1934         FieldPosition pos(FieldPosition::DONT_CARE);
   1935         out = nf->format(pi, out, pos);
   1936         UnicodeString pat;
   1937         pat = nf->toPattern(pat);
   1938         Formattable num;
   1939         ParsePosition pp(0);
   1940         nf->parse(out, num, pp);
   1941         double val = num.getDouble();
   1942 
   1943         nf->applyPattern(pat, status);
   1944         failure(status, "nf->applyPattern");
   1945         UnicodeString out2;
   1946         out2 = nf->format(pi, out2, pos);
   1947         UnicodeString pat2;
   1948         pat2 = nf->toPattern(pat2);
   1949         pp.setIndex(0);
   1950         nf->parse(out2, num, pp);
   1951         double val2 = num.getDouble();
   1952 
   1953         if (pat != pat2)
   1954             errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
   1955                 pat + "\" vs. \"" + pat2 + "\"");
   1956         else
   1957             logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
   1958 
   1959         if (val == val2 && out == out2) {
   1960             logln(UnicodeString("Ok ") + pi + " x \"" + PATS[i] + "\" -> \"" +
   1961                 out + "\" -> " + val + " -> \"" +
   1962                 out2 + "\" -> " + val2);
   1963         }
   1964         else {
   1965             errln(UnicodeString("Fail ") + pi + " x \"" + PATS[i] + "\" -> \"" +
   1966                 out + "\" -> " + val + " -> \"" +
   1967                 out2 + "\" -> " + val2);
   1968         }
   1969     }
   1970     /*}
   1971     catch (ParseException e) {
   1972         errln("Fail: " + e);
   1973         e.printStackTrace();
   1974     }*/
   1975 
   1976     delete nff;
   1977 }
   1978 
   1979 /**
   1980  * @bug 4147295
   1981  * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
   1982  * CANNOT REPRODUCE
   1983  * This bug is a duplicate of 4139344, which is a duplicate of 4134300
   1984  */
   1985 void NumberFormatRegressionTest::Test4147295(void)
   1986 {
   1987     UErrorCode status = U_ZERO_ERROR;
   1988     DecimalFormat *sdf = new DecimalFormat(status);
   1989     UnicodeString pattern("#,###");
   1990     logln("Applying pattern \"" + pattern + "\"");
   1991     sdf->applyPattern(pattern, status);
   1992     if (!failure(status, "sdf->applyPattern")) {
   1993         int minIntDig = sdf->getMinimumIntegerDigits();
   1994         if (minIntDig != 0) {
   1995             errln("Test failed");
   1996             errln(" Minimum integer digits : " + minIntDig);
   1997             UnicodeString temp;
   1998             errln(" new pattern: " + sdf->toPattern(temp));
   1999         } else {
   2000             logln("Test passed");
   2001             logln(" Minimum integer digits : " + minIntDig);
   2002         }
   2003     }
   2004     delete sdf;
   2005 }
   2006 
   2007 /**
   2008  * @bug 4147706
   2009  * DecimalFormat formats -0.0 as +0.0
   2010  * See also older related bug 4106658, 4106667
   2011  */
   2012 void NumberFormatRegressionTest::Test4147706(void)
   2013 {
   2014     UErrorCode status = U_ZERO_ERROR;
   2015     DecimalFormat *df = new DecimalFormat("#,##0.0##", status);
   2016     failure(status, "new DecimalFormat");
   2017     DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status);
   2018     if (!failure(status, "new DecimalFormatSymbols")) {
   2019         UnicodeString f1;
   2020         UnicodeString f2, temp;
   2021         FieldPosition pos(FieldPosition::DONT_CARE);
   2022         volatile double d1 = 0.0;   // volatile to prevent code optimization
   2023         double d2 = -0.0001;
   2024 
   2025 #if defined(U_HPUX)
   2026         d1 = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
   2027 #else
   2028         d1 *= -1.0; // Some compilers have a problem with defining -0.0
   2029 #endif
   2030         df->adoptDecimalFormatSymbols(syms);
   2031         f1 = df->format(d1, f1, pos);
   2032         f2 = df->format(d2, f2, pos);
   2033         if (f1 != UnicodeString("-0.0")) {
   2034             errln(UnicodeString("") + d1 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f1 + '"');
   2035         }
   2036         if (f2 != UnicodeString("-0.0")) {
   2037             errln(UnicodeString("") + d2 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f2 + '"');
   2038         }
   2039     }
   2040 
   2041     delete df;
   2042 }
   2043 
   2044 
   2045 // Not applicable, since no serialization in C++
   2046 /*class myformat implements Serializable
   2047 {
   2048 DateFormat _dateFormat = DateFormat.getDateInstance();
   2049 
   2050 public String Now()
   2051 {
   2052     GregorianCalendar calendar = new GregorianCalendar();
   2053     Date t = calendar.getTime();
   2054     String nowStr = _dateFormat.format(t);
   2055     return nowStr;
   2056 }
   2057 }*/
   2058 
   2059 /**
   2060  * @bug 4162198
   2061  * NumberFormat cannot format Double.MAX_VALUE
   2062  */
   2063 // TODO: make this test actually test something
   2064 void
   2065 NumberFormatRegressionTest::Test4162198(void)
   2066 {
   2067     // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
   2068     double dbl = INT32_MAX * 1000.0;
   2069     UErrorCode status = U_ZERO_ERROR;
   2070     NumberFormat *f = NumberFormat::createInstance(status);
   2071     if(U_FAILURE(status)) {
   2072         dataerrln("Couldn't create number format - %s", u_errorName(status));
   2073         return;
   2074     }
   2075     f->setMaximumFractionDigits(INT32_MAX);
   2076     f->setMaximumIntegerDigits(INT32_MAX);
   2077     UnicodeString s;
   2078     f->format(dbl,s);
   2079     logln(UnicodeString("The number ") + dbl + " formatted to " + s);
   2080     Formattable n;
   2081     //try {
   2082     f->parse(s, n, status);
   2083     if(U_FAILURE(status))
   2084         errln("Couldn't parse!");
   2085     //} catch (java.text.ParseException e) {
   2086     //    errln("Caught a ParseException:");
   2087     //    e.printStackTrace();
   2088     //}
   2089 
   2090     //logln("The string " + s + " parsed as " + n);
   2091 
   2092     // {dlf} The old code assumes n is a double, but it isn't any more...
   2093     // Formattable apparently does not and never did interconvert... too bad.
   2094     //if(n.getDouble() != dbl) {
   2095     //    errln("Round trip failure");
   2096     //}
   2097     if (n.getInt64() != dbl) {
   2098         errln("Round trip failure");
   2099     }
   2100 
   2101     delete f;
   2102 }
   2103 
   2104 /**
   2105  * @bug 4162852
   2106  * NumberFormat does not parse negative zero.
   2107  */
   2108 void
   2109 NumberFormatRegressionTest::Test4162852(void)
   2110 {
   2111     UErrorCode status = U_ZERO_ERROR;
   2112     for(int32_t i=0; i < 2; ++i) {
   2113         NumberFormat *f = (i == 0) ? NumberFormat::createInstance(status)
   2114             : NumberFormat::createPercentInstance(status);
   2115         if(U_FAILURE(status)) {
   2116             dataerrln("Couldn't create number format - %s", u_errorName(status));
   2117             return;
   2118         }
   2119         double d = 0.0;
   2120         d *= -1.0;
   2121         UnicodeString s;
   2122         f->format(d, s);
   2123         Formattable n;
   2124         f->parse(s, n, status);
   2125         if(U_FAILURE(status))
   2126             errln("Couldn't parse!");
   2127         double e = n.getDouble();
   2128         logln(UnicodeString("") +
   2129               d + " -> " +
   2130               '"' + s + '"' + " -> " + e);
   2131 #if (defined(OS390) && !defined(IEEE_754)) || defined(OS400)
   2132         if (e != 0.0) {
   2133 #else
   2134         if (e != 0.0 || 1.0/e > 0.0) {
   2135 #endif
   2136             logln("Failed to parse negative zero");
   2137         }
   2138         delete f;
   2139     }
   2140 }
   2141 
   2142 static double _u_abs(double a) { return a<0?-a:a; }
   2143 
   2144 /**
   2145  * May 17 1999 sync up - liu
   2146  * @bug 4167494
   2147  * NumberFormat truncates data
   2148  */
   2149 void NumberFormatRegressionTest::Test4167494(void) {
   2150     UErrorCode status = U_ZERO_ERROR;
   2151     NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
   2152     if (failure(status, "NumberFormat::createInstance", TRUE)){
   2153         delete fmt;
   2154         return;
   2155     };
   2156 
   2157     double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf
   2158     UnicodeString s;
   2159     fmt->format(a, s);
   2160     Formattable num;
   2161     fmt->parse(s, num, status);
   2162     failure(status, "Parse");
   2163     if (num.getType() == Formattable::kDouble &&
   2164         _u_abs(num.getDouble() - a) / a < 0.01) { // RT within 1%
   2165         logln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
   2166               toString(num) + " ok");
   2167     } else {
   2168         errln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
   2169               toString(num) + " FAIL");
   2170     }
   2171 
   2172     // We don't test Double.MIN_VALUE because the locale data for the US
   2173     // currently doesn't specify enough digits to display Double.MIN_VALUE.
   2174     // This is correct for now; however, we leave this here as a reminder
   2175     // in case we want to address this later.
   2176 
   2177     delete fmt;
   2178 }
   2179 
   2180 /**
   2181  * May 17 1999 sync up - liu
   2182  * @bug 4170798
   2183  * DecimalFormat.parse() fails when ParseIntegerOnly set to true
   2184  */
   2185 void NumberFormatRegressionTest::Test4170798(void) {
   2186     UErrorCode status = U_ZERO_ERROR;
   2187     NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
   2188     if (failure(status, "NumberFormat::createInstance", TRUE)){
   2189         delete nf;
   2190         return;
   2191     };
   2192     DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
   2193     if(df == NULL) {
   2194         errln("DecimalFormat needed to continue");
   2195         return;
   2196     }
   2197     df->setParseIntegerOnly(TRUE);
   2198     Formattable n;
   2199     ParsePosition pos(0);
   2200     df->parse("-0.0", n, pos);
   2201     if (n.getType() != Formattable::kLong
   2202         || n.getLong() != 0) {
   2203         errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n));
   2204     }
   2205     delete nf;
   2206 }
   2207 
   2208 /**
   2209  * May 17 1999 sync up - liu
   2210  * toPattern only puts the first grouping separator in.
   2211  */
   2212 void NumberFormatRegressionTest::Test4176114(void) {
   2213     const char* DATA[] = {
   2214         "00", "#00",
   2215         "000", "#000", // No grouping
   2216         "#000", "#000", // No grouping
   2217         "#,##0", "#,##0",
   2218         "#,000", "#,000",
   2219         "0,000", "#0,000",
   2220         "00,000", "#00,000",
   2221         "000,000", "#,000,000",
   2222         "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
   2223     };
   2224     int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0]));
   2225     UErrorCode status = U_ZERO_ERROR;
   2226     UnicodeString s;
   2227     for (int i=0; i<DATA_length; i+=2) {
   2228         DecimalFormat df(DATA[i], status);
   2229         if (!failure(status, "DecimalFormat constructor")) {
   2230             df.toPattern(s);
   2231             UnicodeString exp(DATA[i+1]);
   2232             if (s != exp) {
   2233                 errln(UnicodeString("FAIL: ") + DATA[i] + " -> " +
   2234                       s + ", want " + exp);
   2235             }
   2236         }
   2237     }
   2238 }
   2239 
   2240 /**
   2241  * May 17 1999 sync up - liu
   2242  * @bug 4179818
   2243  * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
   2244  */
   2245 void NumberFormatRegressionTest::Test4179818(void) {
   2246     const char* DATA[] = {
   2247         // Input  Pattern  Expected output
   2248         "1.2511", "#.#",   "1.3",
   2249         "1.2501", "#.#",   "1.3",
   2250         "0.9999", "#",     "1",
   2251     };
   2252     int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0]));
   2253     double DOUBLE[] = {
   2254         1.2511,
   2255         1.2501,
   2256         0.9999,
   2257     };
   2258     UErrorCode status = U_ZERO_ERROR;
   2259     DecimalFormatSymbols sym(Locale::getUS(), status);
   2260     failure(status, "Construct DecimalFormatSymbols");
   2261     DecimalFormat fmt("#", sym, status);
   2262     if (!failure(status, "Construct DecimalFormat")) {
   2263         for (int i=0; i<DATA_length; i+=3) {
   2264             double in = DOUBLE[i/3];
   2265             UnicodeString pat(DATA[i+1]);
   2266             UnicodeString exp(DATA[i+2]);
   2267             fmt.applyPattern(pat, status);
   2268             failure(status, "applyPattern");
   2269             UnicodeString out;
   2270             FieldPosition pos;
   2271             fmt.format(in, out, pos);
   2272             if (out == exp) {
   2273                 logln(UnicodeString("Ok: ") + in + " x " + pat + " = " + out);
   2274             } else {
   2275                 errln(UnicodeString("FAIL: ") + in + " x  " + pat + " = " + out +
   2276                       ", expected " + exp);
   2277             }
   2278         }
   2279     }
   2280 }
   2281 
   2282 /**
   2283  * May 17 1999 sync up - liu
   2284  * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
   2285  * This includes the minus sign, currency symbol, international currency
   2286  * symbol, percent, and permille.  This is filed as bugs 4212072 and
   2287  * 4212073.
   2288  */
   2289 void NumberFormatRegressionTest::Test4212072(void) {
   2290     UErrorCode status = U_ZERO_ERROR;
   2291     DecimalFormatSymbols sym(Locale::getUS(), status);
   2292 
   2293     failure(status, "DecimalFormatSymbols ct", Locale::getUS());
   2294     DecimalFormat fmt(UnicodeString("#"), sym, status);
   2295     if(failure(status, "DecimalFormat ct", Locale::getUS())) {
   2296         return;
   2297     }
   2298 
   2299     UnicodeString s;
   2300     FieldPosition pos;
   2301 
   2302     sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x5e);
   2303     fmt.setDecimalFormatSymbols(sym);
   2304     s.remove();
   2305     if (fmt.format((int32_t)-1, s, pos) != UNICODE_STRING("^1", 2)) {
   2306         errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s +
   2307               ", exp ^1");
   2308     }
   2309     s.remove();
   2310     if (fmt.getNegativePrefix(s) != UnicodeString((UChar)0x5e)) {
   2311         errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
   2312               s + ", exp ^");
   2313     }
   2314     sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x2d);
   2315 
   2316     fmt.applyPattern(UnicodeString("#%"), status);
   2317     failure(status, "applyPattern percent");
   2318     sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x5e);
   2319     fmt.setDecimalFormatSymbols(sym);
   2320     s.remove();
   2321     if (fmt.format(0.25, s, pos) != UNICODE_STRING("25^", 3)) {
   2322         errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s +
   2323               ", exp 25^");
   2324     }
   2325     s.remove();
   2326     if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
   2327         errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
   2328               s + ", exp ^");
   2329     }
   2330     sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x25);
   2331 
   2332     fmt.applyPattern(str("#\\u2030"), status);
   2333     failure(status, "applyPattern permill");
   2334     sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x5e);
   2335     fmt.setDecimalFormatSymbols(sym);
   2336     s.remove();
   2337     if (fmt.format(0.25, s, pos) != UNICODE_STRING("250^", 4)) {
   2338         errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s +
   2339               ", exp 250^");
   2340     }
   2341     s.remove();
   2342     if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
   2343         errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
   2344               s + ", exp ^");
   2345     }
   2346     sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x2030);
   2347 
   2348     fmt.applyPattern(str("\\u00A4#.00"), status);
   2349     failure(status, "applyPattern currency");
   2350     sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "usd");
   2351     fmt.setDecimalFormatSymbols(sym);
   2352     s.remove();
   2353     if (fmt.format(12.5, s, pos) != UnicodeString("usd12.50")) {
   2354         errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s +
   2355               ", exp usd12.50");
   2356     }
   2357     s.remove();
   2358     if (fmt.getPositivePrefix(s) != UnicodeString("usd")) {
   2359         errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
   2360               s + ", exp usd");
   2361     }
   2362     sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "$");
   2363 
   2364     fmt.applyPattern(str("\\u00A4\\u00A4#.00"), status);
   2365     failure(status, "applyPattern intl currency");
   2366     sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL");
   2367     fmt.setDecimalFormatSymbols(sym);
   2368     s.remove();
   2369     if (fmt.format(12.5, s, pos) != UnicodeString("DOL12.50")) {
   2370         errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s +
   2371               ", exp DOL12.50");
   2372     }
   2373     s.remove();
   2374     if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) {
   2375         errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
   2376               s + ", exp DOL");
   2377     }
   2378     sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "USD");
   2379 
   2380     // Since the pattern logic has changed, make sure that patterns round
   2381     // trip properly.  Test stream in/out integrity too.
   2382     int32_t n;
   2383     const Locale* avail = NumberFormat::getAvailableLocales(n);
   2384     static const char* type[] = {
   2385         "",
   2386         "$ ",
   2387         "% ",
   2388     };
   2389     for (int i=0; i<n; ++i) {
   2390         for (int j=0; j<3; ++j) {
   2391             status = U_ZERO_ERROR;
   2392             NumberFormat *nf;
   2393             switch (j) {
   2394             case 0:
   2395                 nf = NumberFormat::createInstance(avail[i], status);
   2396                 failure(status, "createInstance", avail[i]);
   2397                 break;
   2398             case 1:
   2399                 nf = NumberFormat::createCurrencyInstance(avail[i], status);
   2400                 failure(status, "createCurrencyInstance", avail[i]);
   2401                 break;
   2402             default:
   2403                 nf = NumberFormat::createPercentInstance(avail[i], status);
   2404                 failure(status, "createPercentInstance", avail[i]);
   2405                 break;
   2406             }
   2407             if (U_FAILURE(status)) {
   2408                 continue;
   2409             }
   2410             DecimalFormat *df = (DecimalFormat*) nf;
   2411 
   2412             // Test toPattern/applyPattern round trip
   2413             UnicodeString pat;
   2414             df->toPattern(pat);
   2415             DecimalFormatSymbols symb(avail[i], status);
   2416             failure(status, "Construct DecimalFormatSymbols", avail[i]);
   2417             DecimalFormat f2(pat, symb, status);
   2418             if (failure(status,
   2419                         UnicodeString("Construct DecimalFormat(") + pat + ")")) {
   2420                 continue;
   2421             }
   2422             if (*df != f2) {
   2423                 UnicodeString l, p;
   2424                 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
   2425                       " -> \"" + pat +
   2426                       "\" -> \"" + f2.toPattern(p) + "\"");
   2427             } else {
   2428                 UnicodeString l, p;
   2429                 logln(UnicodeString("PASS: ") + type[j] + avail[i].getDisplayName(l) +
   2430                       " -> \"" + pat +
   2431                       "\"");
   2432             }
   2433 
   2434             // Test toLocalizedPattern/applyLocalizedPattern round trip
   2435             df->toLocalizedPattern(pat);
   2436             f2.applyLocalizedPattern(pat, status);
   2437             failure(status,
   2438                     UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]);
   2439             if (U_FAILURE(status)) {
   2440                 continue;
   2441             }
   2442 
   2443             // Make sure we set the currency attributes appropriately
   2444             if (j == 1) {   // Currency format
   2445                 f2.setCurrency(f2.getCurrency(), status);
   2446             }
   2447             failure(status,
   2448                     UnicodeString("setCurrency() for (") + pat + ")", avail[i]);
   2449             if (U_FAILURE(status)) {
   2450                 continue;
   2451             }
   2452 
   2453             if (*df != f2) {
   2454                 UnicodeString l, p;
   2455                 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
   2456                       " -> localized \"" + pat +
   2457                       "\" -> \"" + f2.toPattern(p) + "\"");
   2458             }
   2459 
   2460             delete nf;
   2461 
   2462             // Test writeObject/readObject round trip
   2463             // NOT ON ICU -- Java only
   2464         }
   2465     }
   2466 }
   2467 
   2468 /**
   2469  * May 17 1999 sync up - liu
   2470  * DecimalFormat.parse() fails for mulipliers 2^n.
   2471  */
   2472 void NumberFormatRegressionTest::Test4216742(void) {
   2473     UErrorCode status = U_ZERO_ERROR;
   2474     DecimalFormat *fmt = (DecimalFormat*) NumberFormat::createInstance(Locale::getUS(), status);
   2475     if (failure(status, "createInstance", Locale::getUS(), TRUE)){
   2476         delete fmt;
   2477         return;
   2478     };
   2479     int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 };
   2480     int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0]));
   2481     for (int i=0; i<DATA_length; ++i) {
   2482         UnicodeString str((UnicodeString)"" + DATA[i]);
   2483         for (int m = 1; m <= 100; m++) {
   2484             fmt->setMultiplier(m);
   2485             Formattable num;
   2486             fmt->parse(str, num, status);
   2487             failure(status, "parse", Locale::getUS());
   2488             if (num.getType() != Formattable::kLong &&
   2489                 num.getType() != Formattable::kDouble) {
   2490                 errln(UnicodeString("FAIL: Wanted number, got ") +
   2491                       toString(num));
   2492             } else {
   2493                 double d = num.getType() == Formattable::kDouble ?
   2494                     num.getDouble() : (double) num.getLong();
   2495                 if ((d > 0) != (DATA[i] > 0)) {
   2496                     errln(UnicodeString("\"") + str + "\" parse(x " +
   2497                           fmt->getMultiplier() +
   2498                           ") => " + toString(num));
   2499                 }
   2500             }
   2501         }
   2502     }
   2503     delete fmt;
   2504 }
   2505 
   2506 /**
   2507  * May 17 1999 sync up - liu
   2508  * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
   2509  * digits.
   2510  */
   2511 void NumberFormatRegressionTest::Test4217661(void) {
   2512     const double D[] = {  0.001, 1.001, 0.006,  1.006 };
   2513     const char*  S[] = { "0",   "1",   "0.01", "1.01" };
   2514     int D_length = (int)(sizeof(D) / sizeof(D[0]));
   2515     UErrorCode status = U_ZERO_ERROR;
   2516     NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
   2517     if (failure(status, "createInstance", Locale::getUS(), TRUE)){
   2518         delete fmt;
   2519         return;
   2520     };
   2521     fmt->setMaximumFractionDigits(2);
   2522     for (int i=0; i<D_length; i++) {
   2523         UnicodeString s;
   2524         fmt->format(D[i], s);
   2525         if (s != UnicodeString(S[i])) {
   2526             errln(UnicodeString("FAIL: Got ") + s + ", exp " + S[i]);
   2527         }
   2528     }
   2529     delete fmt;
   2530 }
   2531 
   2532 /**
   2533  * alphaWorks upgrade
   2534  */
   2535 void NumberFormatRegressionTest::Test4161100(void) {
   2536     UErrorCode status = U_ZERO_ERROR;
   2537     NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
   2538     if (failure(status, "createInstance", Locale::getUS(), TRUE)){
   2539         delete nf;
   2540         return;
   2541     };
   2542     nf->setMinimumFractionDigits(1);
   2543     nf->setMaximumFractionDigits(1);
   2544     double a = -0.09;
   2545     UnicodeString s;
   2546     nf->format(a, s);
   2547     UnicodeString pat;
   2548     logln(UnicodeString() + a + " x " +
   2549           ((DecimalFormat*) nf)->toPattern(pat) + " = " + s);
   2550     if (s != UnicodeString("-0.1")) {
   2551         errln("FAIL");
   2552     }
   2553     delete nf;
   2554 }
   2555 
   2556 /**
   2557  * June 16 1999 sync up - liu
   2558  * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
   2559  */
   2560 void NumberFormatRegressionTest::Test4243011(void) {
   2561     UErrorCode status = U_ZERO_ERROR;
   2562     DecimalFormatSymbols sym(Locale::getUS(), status);
   2563     failure(status, "DecimalFormatSymbols ct", Locale::getUS());
   2564     DecimalFormat fmt(UnicodeString("0."), sym, status);
   2565 
   2566     if (!failure(status, "DecimalFormat ct", Locale::getUS())) {
   2567         const double NUM[] = {  -2.5,  -1.5,  -0.5,  0.5,  1.5,  2.5,  3.5,  4.5 };
   2568         const char*  STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
   2569         int32_t N = (int32_t)(sizeof(NUM) / sizeof(NUM[0]));
   2570 
   2571         for (int32_t i=0; i<N; ++i) {
   2572             UnicodeString str;
   2573             UnicodeString exp(STR[i]);
   2574             FieldPosition pos;
   2575             fmt.format(NUM[i], str, pos);
   2576             if (str == exp) {
   2577                 logln(UnicodeString("Ok   ") + NUM[i] + " x 0. = " + str);
   2578             } else {
   2579                 errln(UnicodeString("FAIL ") + NUM[i] + " x 0. = " + str +
   2580                       ", want " + exp);
   2581             }
   2582         }
   2583     }
   2584 }
   2585 
   2586 /**
   2587  * June 16 1999 sync up - liu
   2588  * format(0.0) gives "0.1" if preceded by parse("99.99").
   2589  * (Regression in 1.2.2 RC1)
   2590  */
   2591 void NumberFormatRegressionTest::Test4243108(void) {
   2592     UErrorCode status = U_ZERO_ERROR;
   2593     DecimalFormatSymbols sym(Locale::getUS(), status);
   2594     failure(status, "DecimalFormatSymbols ct", Locale::getUS());
   2595     DecimalFormat fmt(UnicodeString("#.#"), sym, status);
   2596     if (failure(status, "DecimalFormat ct", Locale::getUS())) {
   2597         return;
   2598     }
   2599 
   2600     UnicodeString str;
   2601     FieldPosition pos;
   2602 
   2603     fmt.format(0.0, str, pos);
   2604     UnicodeString exp("0");
   2605     if (str == exp) {
   2606         logln(UnicodeString("Ok   0.0 x #.# = ") + str);
   2607     } else {
   2608         errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
   2609               ", want " + exp);
   2610     }
   2611 
   2612     str = "99.99";
   2613     Formattable val;
   2614     fmt.parse(str, val, status);
   2615     failure(status, "DecimalFormat.parse(99.99)", Locale::getUS());
   2616     if (val.getType() == Formattable::kDouble &&
   2617         val.getDouble() == 99.99) {
   2618         logln(UnicodeString("Ok   99.99 / #.# = ") + toString(val));
   2619     } else {
   2620         errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val) +
   2621               ", want " + 99.99);
   2622     }
   2623 
   2624     str.remove();
   2625     fmt.format(0.0, str, pos);
   2626     if (str == exp) {
   2627         logln(UnicodeString("Ok   0.0 x #.# = ") + str);
   2628     } else {
   2629         errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
   2630               ", want " + exp);
   2631     }
   2632 }
   2633 
   2634 
   2635 /**
   2636  * DateFormat should call setIntegerParseOnly(TRUE) on adopted
   2637  * NumberFormat objects.
   2638  */
   2639 void NumberFormatRegressionTest::TestJ691(void) {
   2640     UErrorCode status = U_ZERO_ERROR;
   2641     Locale loc("fr", "CH");
   2642 
   2643     // set up the input date string & expected output
   2644     UnicodeString udt("11.10.2000", "");
   2645     UnicodeString exp("11.10.00", "");
   2646 
   2647     // create a Calendar for this locale
   2648     Calendar *cal = Calendar::createInstance(loc, status);
   2649     if (U_FAILURE(status)) {
   2650         dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status));
   2651         return;
   2652     }
   2653 
   2654     // create a NumberFormat for this locale
   2655     NumberFormat *nf = NumberFormat::createInstance(loc, status);
   2656     if (U_FAILURE(status)) {
   2657         dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
   2658         return;
   2659     }
   2660 
   2661     // *** Here's the key: We don't want to have to do THIS:
   2662     // nf->setParseIntegerOnly(TRUE);
   2663 
   2664     // create the DateFormat
   2665     DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc);
   2666     if (U_FAILURE(status)) {
   2667         errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
   2668         return;
   2669     }
   2670 
   2671     df->adoptCalendar(cal);
   2672     df->adoptNumberFormat(nf);
   2673 
   2674     // set parsing to lenient & parse
   2675     df->setLenient(TRUE);
   2676     UDate ulocdat = df->parse(udt, status);
   2677 
   2678     // format back to a string
   2679     UnicodeString outString;
   2680     df->format(ulocdat, outString);
   2681 
   2682     if (outString != exp) {
   2683         errln("FAIL: " + udt + " => " + outString);
   2684     }
   2685 
   2686     delete df;
   2687 }
   2688 
   2689 #endif /* #if !UCONFIG_NO_FORMATTING */
   2690