Home | History | Annotate | Download | only in format
      1 /*
      2  *******************************************************************************
      3  * Copyright (C) 2001-2015, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  *******************************************************************************
      6  */
      7 
      8 /**
      9  * Port From:   ICU4C v1.8.1 : format : NumberFormatTest
     10  * Source File: $ICU4CRoot/source/test/intltest/numfmtst.cpp
     11  **/
     12 
     13 package com.ibm.icu.dev.test.format;
     14 
     15 import java.io.IOException;
     16 import java.math.BigInteger;
     17 import java.text.AttributedCharacterIterator;
     18 import java.text.FieldPosition;
     19 import java.text.ParseException;
     20 import java.text.ParsePosition;
     21 import java.util.ArrayList;
     22 import java.util.Locale;
     23 import java.util.Set;
     24 
     25 import com.ibm.icu.dev.test.TestUtil;
     26 import com.ibm.icu.impl.ICUConfig;
     27 import com.ibm.icu.impl.LocaleUtility;
     28 import com.ibm.icu.impl.data.ResourceReader;
     29 import com.ibm.icu.impl.data.TokenIterator;
     30 import com.ibm.icu.math.BigDecimal;
     31 import com.ibm.icu.math.MathContext;
     32 import com.ibm.icu.text.DecimalFormat;
     33 import com.ibm.icu.text.DecimalFormatSymbols;
     34 import com.ibm.icu.text.DisplayContext;
     35 import com.ibm.icu.text.MeasureFormat;
     36 import com.ibm.icu.text.NumberFormat;
     37 import com.ibm.icu.text.NumberFormat.NumberFormatFactory;
     38 import com.ibm.icu.text.NumberFormat.SimpleNumberFormatFactory;
     39 import com.ibm.icu.util.Currency;
     40 import com.ibm.icu.util.CurrencyAmount;
     41 import com.ibm.icu.util.ULocale;
     42 
     43 public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
     44 
     45     public static void main(String[] args) throws Exception {
     46         new NumberFormatTest().run(args);
     47     }
     48 
     49     public void TestRoundingScientific10542() {
     50         DecimalFormat format =
     51                 new DecimalFormat("0.00E0");
     52 
     53         int[] roundingModes = {
     54               BigDecimal.ROUND_CEILING,
     55               BigDecimal.ROUND_DOWN,
     56               BigDecimal.ROUND_FLOOR,
     57               BigDecimal.ROUND_HALF_DOWN,
     58               BigDecimal.ROUND_HALF_EVEN,
     59               BigDecimal.ROUND_HALF_UP,
     60               BigDecimal.ROUND_UP};
     61         String[] descriptions = {
     62                 "Round Ceiling",
     63                 "Round Down",
     64                 "Round Floor",
     65                 "Round half down",
     66                 "Round half even",
     67                 "Round half up",
     68                 "Round up"};
     69 
     70         double[] values = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
     71         // The order of these expected values correspond to the order of roundingModes and the order of values.
     72         String[][] expected = {
     73                 {"-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3"},
     74                 {"-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3"},
     75                 {"-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3"},
     76                 {"-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3"},
     77                 {"-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3"},
     78                 {"-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3"},
     79                 {"-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"}};
     80         verifyRounding(format, values, expected, roundingModes, descriptions);
     81         values = new double[]{-3006.0, -3005, -3004, 3014, 3015, 3016};
     82         // The order of these expected values correspond to the order of roundingModes and the order of values.
     83         expected = new String[][]{
     84                 {"-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3"},
     85                 {"-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3"},
     86                 {"-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3"},
     87                 {"-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3"},
     88                 {"-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3"},
     89                 {"-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3"},
     90                 {"-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"}};
     91         verifyRounding(format, values, expected, roundingModes, descriptions);
     92         values = new double[]{0.0, -0.0};
     93         // The order of these expected values correspond to the order of roundingModes and the order of values.
     94         expected = new String[][]{
     95                 {"0.00E0", "-0.00E0"},
     96                 {"0.00E0", "-0.00E0"},
     97                 {"0.00E0", "-0.00E0"},
     98                 {"0.00E0", "-0.00E0"},
     99                 {"0.00E0", "-0.00E0"},
    100                 {"0.00E0", "-0.00E0"},
    101                 {"0.00E0", "-0.00E0"}};
    102         verifyRounding(format, values, expected, roundingModes, descriptions);
    103         values = new double[]{1e25, 1e25 + 1e15, 1e25 - 1e15};
    104         // The order of these expected values correspond to the order of roundingModes and the order of values.
    105         expected = new String[][]{
    106                 {"1.00E25", "1.01E25", "1.00E25"},
    107                 {"1.00E25", "1.00E25", "9.99E24"},
    108                 {"1.00E25", "1.00E25", "9.99E24"},
    109                 {"1.00E25", "1.00E25", "1.00E25"},
    110                 {"1.00E25", "1.00E25", "1.00E25"},
    111                 {"1.00E25", "1.00E25", "1.00E25"},
    112                 {"1.00E25", "1.01E25", "1.00E25"}};
    113         verifyRounding(format, values, expected, roundingModes, descriptions);
    114         values = new double[]{-1e25, -1e25 + 1e15, -1e25 - 1e15};
    115         // The order of these expected values correspond to the order of roundingModes and the order of values.
    116         expected = new String[][]{
    117                 {"-1.00E25", "-9.99E24", "-1.00E25"},
    118                 {"-1.00E25", "-9.99E24", "-1.00E25"},
    119                 {"-1.00E25", "-1.00E25", "-1.01E25"},
    120                 {"-1.00E25", "-1.00E25", "-1.00E25"},
    121                 {"-1.00E25", "-1.00E25", "-1.00E25"},
    122                 {"-1.00E25", "-1.00E25", "-1.00E25"},
    123                 {"-1.00E25", "-1.00E25", "-1.01E25"}};
    124         verifyRounding(format, values, expected, roundingModes, descriptions);
    125         values = new double[]{1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
    126         // The order of these expected values correspond to the order of roundingModes and the order of values.
    127         expected = new String[][]{
    128                 {"1.00E-25", "1.01E-25", "1.00E-25"},
    129                 {"1.00E-25", "1.00E-25", "9.99E-26"},
    130                 {"1.00E-25", "1.00E-25", "9.99E-26"},
    131                 {"1.00E-25", "1.00E-25", "1.00E-25"},
    132                 {"1.00E-25", "1.00E-25", "1.00E-25"},
    133                 {"1.00E-25", "1.00E-25", "1.00E-25"},
    134                 {"1.00E-25", "1.01E-25", "1.00E-25"}};
    135         verifyRounding(format, values, expected, roundingModes, descriptions);
    136         values = new double[]{-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
    137         // The order of these expected values correspond to the order of roundingModes and the order of values.
    138         expected = new String[][]{
    139                 {"-1.00E-25", "-9.99E-26", "-1.00E-25"},
    140                 {"-1.00E-25", "-9.99E-26", "-1.00E-25"},
    141                 {"-1.00E-25", "-1.00E-25", "-1.01E-25"},
    142                 {"-1.00E-25", "-1.00E-25", "-1.00E-25"},
    143                 {"-1.00E-25", "-1.00E-25", "-1.00E-25"},
    144                 {"-1.00E-25", "-1.00E-25", "-1.00E-25"},
    145                 {"-1.00E-25", "-1.00E-25", "-1.01E-25"}};
    146         verifyRounding(format, values, expected, roundingModes, descriptions);
    147     }
    148 
    149     private void verifyRounding(DecimalFormat format, double[] values, String[][] expected, int[] roundingModes,
    150             String[] descriptions) {
    151         for (int i = 0; i < roundingModes.length; i++) {
    152             format.setRoundingMode(roundingModes[i]);
    153             for (int j = 0; j < values.length; j++) {
    154                 assertEquals(descriptions[i]+" " +values[j], expected[i][j], format.format(values[j]));
    155             }
    156         }
    157     }
    158 
    159     public void Test10419RoundingWith0FractionDigits() {
    160         Object[][] data = new Object[][]{
    161                 {BigDecimal.ROUND_CEILING, 1.488, "2"},
    162                 {BigDecimal.ROUND_DOWN, 1.588, "1"},
    163                 {BigDecimal.ROUND_FLOOR, 1.588, "1"},
    164                 {BigDecimal.ROUND_HALF_DOWN, 1.5, "1"},
    165                 {BigDecimal.ROUND_HALF_EVEN, 2.5, "2"},
    166                 {BigDecimal.ROUND_HALF_UP, 2.5, "3"},
    167                 {BigDecimal.ROUND_UP, 1.5, "2"},
    168         };
    169         NumberFormat nff = NumberFormat.getNumberInstance(ULocale.ENGLISH);
    170         nff.setMaximumFractionDigits(0);
    171         for (Object[] item : data) {
    172           nff.setRoundingMode(((Integer) item[0]).intValue());
    173           assertEquals("Test10419", item[2], nff.format(item[1]));
    174         }
    175     }
    176 
    177     public void TestParseNegativeWithFaLocale() {
    178         DecimalFormat parser = (DecimalFormat) NumberFormat.getInstance(new ULocale("fa"));
    179         try {
    180             double value = parser.parse("-0,5").doubleValue();
    181             assertEquals("Expect -0.5", -0.5, value);
    182         } catch (ParseException e) {
    183             this.errln("Parsing -0.5 should have succeeded.");
    184         }
    185     }
    186 
    187     public void TestParseNegativeWithAlternativeMinusSign() {
    188         DecimalFormat parser = (DecimalFormat) NumberFormat.getInstance(new ULocale("en"));
    189         try {
    190             double value = parser.parse("\u208B0.5").doubleValue();
    191             assertEquals("Expect -0.5", -0.5, value);
    192         } catch (ParseException e) {
    193             this.errln("Parsing -0.5 should have succeeded.");
    194         }
    195     }
    196 
    197     // Test various patterns
    198     public void TestPatterns() {
    199 
    200         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
    201         final String pat[]    = { "#.#", "#.", ".#", "#" };
    202         int pat_length = pat.length;
    203         final String newpat[] = { "#0.#", "#0.", "#.0", "#" };
    204         final String num[]    = { "0",   "0.", ".0", "0" };
    205         for (int i=0; i<pat_length; ++i)
    206         {
    207             DecimalFormat fmt = new DecimalFormat(pat[i], sym);
    208             String newp = fmt.toPattern();
    209             if (!newp.equals(newpat[i]))
    210                 errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
    211                         "; " + newp + " seen instead");
    212 
    213             String s = ((NumberFormat)fmt).format(0);
    214             if (!s.equals(num[i]))
    215             {
    216                 errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
    217                         "; " + s + " seen instead");
    218                 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
    219             }
    220             // BigInteger 0 - ticket#4731
    221             s = ((NumberFormat)fmt).format(BigInteger.ZERO);
    222             if (!s.equals(num[i]))
    223             {
    224                 errln("FAIL: Pattern " + pat[i] + " should format BigInteger zero as " + num[i] +
    225                         "; " + s + " seen instead");
    226                 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
    227             }
    228         }
    229     }
    230 
    231     // Test exponential pattern
    232     public void TestExponential() {
    233 
    234         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
    235         final String pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
    236         int pat_length = pat.length;
    237 
    238         double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
    239         int val_length = val.length;
    240         final String valFormat[] = {
    241                 // 0.####E0
    242                 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
    243                 // 00.000E00
    244                 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
    245                 // ##0.######E000
    246                 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
    247                 // 0.###E0;[0.###E0]
    248                 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" };
    249         /*double valParse[] =
    250             {
    251                 0.01234, 123460000, 1.23E300, -3.1416E-271,
    252                 0.01234, 123460000, 1.23E300, -3.1416E-271,
    253                 0.01234, 123456800, 1.23E300, -3.141593E-271,
    254                 0.01234, 123500000, 1.23E300, -3.142E-271,
    255             };*/ //The variable is never used
    256 
    257         int lval[] = { 0, -1, 1, 123456789 };
    258         int lval_length = lval.length;
    259         final String lvalFormat[] = {
    260                 // 0.####E0
    261                 "0E0", "-1E0", "1E0", "1.2346E8",
    262                 // 00.000E00
    263                 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
    264                 // ##0.######E000
    265                 "0E000", "-1E000", "1E000", "123.4568E006",
    266                 // 0.###E0;[0.###E0]
    267                 "0E0", "[1E0]", "1E0", "1.235E8" };
    268         int lvalParse[] =
    269             {
    270                 0, -1, 1, 123460000,
    271                 0, -1, 1, 123460000,
    272                 0, -1, 1, 123456800,
    273                 0, -1, 1, 123500000,
    274             };
    275         int ival = 0, ilval = 0;
    276         for (int p = 0; p < pat_length; ++p) {
    277             DecimalFormat fmt = new DecimalFormat(pat[p], sym);
    278             logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" + fmt.toPattern() + "\"");
    279             int v;
    280             for (v = 0; v < val_length; ++v) {
    281                 String s;
    282                 s = ((NumberFormat) fmt).format(val[v]);
    283                 logln(" " + val[v] + " -format-> " + s);
    284                 if (!s.equals(valFormat[v + ival]))
    285                     errln("FAIL: Expected " + valFormat[v + ival]);
    286 
    287                 ParsePosition pos = new ParsePosition(0);
    288                 double a = fmt.parse(s, pos).doubleValue();
    289                 if (pos.getIndex() == s.length()) {
    290                     logln("  -parse-> " + Double.toString(a));
    291                     // Use epsilon comparison as necessary
    292                 } else
    293                     errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
    294             }
    295             for (v = 0; v < lval_length; ++v) {
    296                 String s;
    297                 s = ((NumberFormat) fmt).format(lval[v]);
    298                 logln(" " + lval[v] + "L -format-> " + s);
    299                 if (!s.equals(lvalFormat[v + ilval]))
    300                     errln("ERROR: Expected " + lvalFormat[v + ilval] + " Got: " + s);
    301 
    302                 ParsePosition pos = new ParsePosition(0);
    303                 long a = 0;
    304                 Number A = fmt.parse(s, pos);
    305                 if (A != null) {
    306                     a = A.longValue();
    307                     if (pos.getIndex() == s.length()) {
    308                         logln("  -parse-> " + a);
    309                         if (a != lvalParse[v + ilval])
    310                             errln("FAIL: Expected " + lvalParse[v + ilval]);
    311                     } else
    312                         errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + Long.toString(a));
    313                 } else {
    314                     errln("Fail to parse the string: " + s);
    315                 }
    316             }
    317             ival += val_length;
    318             ilval += lval_length;
    319         }
    320     }
    321 
    322     // Test the handling of quotes
    323     public void TestQuotes() {
    324 
    325         StringBuffer pat;
    326         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
    327         pat = new StringBuffer("a'fo''o'b#");
    328         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
    329         String s = ((NumberFormat)fmt).format(123);
    330         logln("Pattern \"" + pat + "\"");
    331         logln(" Format 123 . " + s);
    332         if (!s.equals("afo'ob123"))
    333             errln("FAIL: Expected afo'ob123");
    334 
    335         s ="";
    336         pat = new StringBuffer("a''b#");
    337         fmt = new DecimalFormat(pat.toString(), sym);
    338         s = ((NumberFormat)fmt).format(123);
    339         logln("Pattern \"" + pat + "\"");
    340         logln(" Format 123 . " + s);
    341         if (!s.equals("a'b123"))
    342             errln("FAIL: Expected a'b123");
    343     }
    344 
    345     public void TestParseCurrencyTrailingSymbol() {
    346         // see sun bug 4709840
    347         NumberFormat fmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);
    348         float val = 12345.67f;
    349         String str = fmt.format(val);
    350         logln("val: " + val + " str: " + str);
    351         try {
    352             Number num = fmt.parse(str);
    353             logln("num: " + num);
    354         } catch (ParseException e) {
    355             errln("parse of '" + str + "' threw exception: " + e);
    356         }
    357     }
    358 
    359     /**
    360      * Test the handling of the currency symbol in patterns.
    361      **/
    362     public void TestCurrencySign() {
    363         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
    364         StringBuffer pat = new StringBuffer("");
    365         char currency = 0x00A4;
    366         // "\xA4#,##0.00;-\xA4#,##0.00"
    367         pat.append(currency).append("#,##0.00;-").append(currency).append("#,##0.00");
    368         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
    369         String s = ((NumberFormat) fmt).format(1234.56);
    370         pat = new StringBuffer();
    371         logln("Pattern \"" + fmt.toPattern() + "\"");
    372         logln(" Format " + 1234.56 + " . " + s);
    373         assertEquals("symbol, pos", "$1,234.56", s);
    374 
    375         s = ((NumberFormat) fmt).format(-1234.56);
    376         logln(" Format " + Double.toString(-1234.56) + " . " + s);
    377         assertEquals("symbol, neg", "-$1,234.56", s);
    378 
    379         pat.setLength(0);
    380         // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
    381         pat.append(currency).append(currency).append(" #,##0.00;").append(currency).append(currency).append(" -#,##0.00");
    382         fmt = new DecimalFormat(pat.toString(), sym);
    383         s = ((NumberFormat) fmt).format(1234.56);
    384         logln("Pattern \"" + fmt.toPattern() + "\"");
    385         logln(" Format " + Double.toString(1234.56) + " . " + s);
    386         assertEquals("name, pos", "USD 1,234.56", s);
    387 
    388         s = ((NumberFormat) fmt).format(-1234.56);
    389         logln(" Format " + Double.toString(-1234.56) + " . " + s);
    390         assertEquals("name, neg", "USD -1,234.56", s);
    391     }
    392 
    393     public void TestSpaceParsing() {
    394         // the data are:
    395         // the string to be parsed, parsed position, parsed error index
    396         String[][] DATA = {
    397                 {"$124", "4", "-1"},
    398                 {"$124 $124", "4", "-1"},
    399                 {"$124 ", "4", "-1"},
    400                 {"$ 124 ", "5", "-1"},
    401                 {"$\u00A0124 ", "5", "-1"},
    402                 {" $ 124 ", "0", "0"}, // TODO: need to handle space correctly
    403                 {"124$", "0", "3"}, // TODO: need to handle space correctly
    404                 // {"124 $", "5", "-1"}, TODO: OK or NOT?
    405                 {"124 $", "0", "3"},
    406         };
    407         NumberFormat foo = NumberFormat.getCurrencyInstance();
    408         for (int i = 0; i < DATA.length; ++i) {
    409             ParsePosition parsePosition = new ParsePosition(0);
    410             String stringToBeParsed = DATA[i][0];
    411             int parsedPosition = Integer.parseInt(DATA[i][1]);
    412             int errorIndex = Integer.parseInt(DATA[i][2]);
    413             try {
    414                 Number result = foo.parse(stringToBeParsed, parsePosition);
    415                 if (parsePosition.getIndex() != parsedPosition ||
    416                         parsePosition.getErrorIndex() != errorIndex) {
    417                     errln("FAILED parse " + stringToBeParsed + "; parse position: " + parsePosition.getIndex() + "; error position: " + parsePosition.getErrorIndex());
    418                 }
    419                 if (parsePosition.getErrorIndex() == -1 &&
    420                         result.doubleValue() != 124) {
    421                     errln("FAILED parse " + stringToBeParsed + "; value " + result.doubleValue());
    422                 }
    423             } catch (Exception e) {
    424                 errln("FAILED " + e.toString());
    425             }
    426         }
    427     }
    428 
    429 
    430     public void TestMultiCurrencySign() {
    431         String[][] DATA = {
    432                 // the fields in the following test are:
    433                 // locale,
    434                 // currency pattern (with negative pattern),
    435                 // currency number to be formatted,
    436                 // currency format using currency symbol name, such as "$" for USD,
    437                 // currency format using currency ISO name, such as "USD",
    438                 // currency format using plural name, such as "US dollars".
    439                 // for US locale
    440                 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"},
    441                 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"},
    442                 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollars1.00"},
    443                 // for CHINA locale
    444                 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY1,234.56", "\u4EBA\u6C11\u5E011,234.56"},
    445                 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY1,234.56)", "(\u4EBA\u6C11\u5E011,234.56)"},
    446                 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY1.00", "\u4EBA\u6C11\u5E011.00"}
    447         };
    448 
    449         String doubleCurrencyStr = "\u00A4\u00A4";
    450         String tripleCurrencyStr = "\u00A4\u00A4\u00A4";
    451 
    452         for (int i=0; i<DATA.length; ++i) {
    453             String locale = DATA[i][0];
    454             String pat = DATA[i][1];
    455             Double numberToBeFormat = new Double(DATA[i][2]);
    456             DecimalFormatSymbols sym = new DecimalFormatSymbols(new ULocale(locale));
    457             for (int j=1; j<=3; ++j) {
    458                 // j represents the number of currency sign in the pattern.
    459                 if (j == 2) {
    460                     pat = pat.replaceAll("\u00A4", doubleCurrencyStr);
    461                 } else if (j == 3) {
    462                     pat = pat.replaceAll("\u00A4\u00A4", tripleCurrencyStr);
    463                 }
    464                 DecimalFormat fmt = new DecimalFormat(pat, sym);
    465                 String s = ((NumberFormat) fmt).format(numberToBeFormat);
    466                 // DATA[i][3] is the currency format result using a
    467                 // single currency sign.
    468                 // DATA[i][4] is the currency format result using
    469                 // double currency sign.
    470                 // DATA[i][5] is the currency format result using
    471                 // triple currency sign.
    472                 // DATA[i][j+2] is the currency format result using
    473                 // 'j' number of currency sign.
    474                 String currencyFormatResult = DATA[i][2+j];
    475                 if (!s.equals(currencyFormatResult)) {
    476                     errln("FAIL format: Expected " + currencyFormatResult);
    477                 }
    478                 try {
    479                     // mix style parsing
    480                     for (int k=3; k<=5; ++k) {
    481                         // DATA[i][3] is the currency format result using a
    482                         // single currency sign.
    483                         // DATA[i][4] is the currency format result using
    484                         // double currency sign.
    485                         // DATA[i][5] is the currency format result using
    486                         // triple currency sign.
    487                         String oneCurrencyFormat = DATA[i][k];
    488                         if (fmt.parse(oneCurrencyFormat).doubleValue() !=
    489                                 numberToBeFormat.doubleValue()) {
    490                             errln("FAILED parse " + oneCurrencyFormat);
    491                         }
    492                     }
    493                 } catch (ParseException e) {
    494                     errln("FAILED, DecimalFormat parse currency: " + e.toString());
    495                 }
    496             }
    497         }
    498     }
    499 
    500     public void TestCurrencyFormatForMixParsing() {
    501         MeasureFormat curFmt = MeasureFormat.getCurrencyFormat(new ULocale("en_US"));
    502         String[] formats = {
    503                 "$1,234.56",  // string to be parsed
    504                 "USD1,234.56",
    505                 "US dollars1,234.56",
    506                 "1,234.56 US dollars"
    507         };
    508         try {
    509             for (int i = 0; i < formats.length; ++i) {
    510                 String stringToBeParsed = formats[i];
    511                 CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(stringToBeParsed);
    512                 Number val = parsedVal.getNumber();
    513                 if (!val.equals(new BigDecimal("1234.56"))) {
    514                     errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val);
    515                 }
    516                 if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) {
    517                     errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency");
    518                 }
    519             }
    520         } catch (ParseException e) {
    521             errln("parse FAILED: " + e.toString());
    522         }
    523     }
    524 
    525     public void TestDecimalFormatCurrencyParse() {
    526         // Locale.US
    527         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
    528         StringBuffer pat = new StringBuffer("");
    529         char currency = 0x00A4;
    530         // "\xA4#,##0.00;-\xA4#,##0.00"
    531         pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
    532         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
    533         String[][] DATA = {
    534                 // the data are:
    535                 // string to be parsed, the parsed result (number)
    536                 {"$1.00", "1"},
    537                 {"USD1.00", "1"},
    538                 {"1.00 US dollar", "1"},
    539                 {"$1,234.56", "1234.56"},
    540                 {"USD1,234.56", "1234.56"},
    541                 {"1,234.56 US dollar", "1234.56"},
    542         };
    543         try {
    544             for (int i = 0; i < DATA.length; ++i) {
    545                 String stringToBeParsed = DATA[i][0];
    546                 double parsedResult = Double.parseDouble(DATA[i][1]);
    547                 Number num = fmt.parse(stringToBeParsed);
    548                 if (num.doubleValue() != parsedResult) {
    549                     errln("FAIL parse: Expected " + parsedResult);
    550                 }
    551             }
    552         } catch (ParseException e) {
    553             errln("FAILED, DecimalFormat parse currency: " + e.toString());
    554         }
    555     }
    556 
    557     /**
    558      * Test localized currency patterns.
    559      */
    560     public void TestCurrency() {
    561         String[] DATA = {
    562                 "fr", "CA", "", "1,50\u00a0$",
    563                 "de", "DE", "", "1,50\u00a0\u20AC",
    564                 "de", "DE", "PREEURO", "1,50\u00a0DM",
    565                 "fr", "FR", "", "1,50\u00a0\u20AC",
    566                 "fr", "FR", "PREEURO", "1,50\u00a0F",
    567         };
    568 
    569         for (int i=0; i<DATA.length; i+=4) {
    570             Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
    571             NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
    572             String s = fmt.format(1.50);
    573             if (s.equals(DATA[i+3])) {
    574                 logln("Ok: 1.50 x " + locale + " => " + s);
    575             } else {
    576                 logln("FAIL: 1.50 x " + locale + " => " + s +
    577                         ", expected " + DATA[i+3]);
    578             }
    579         }
    580 
    581         // format currency with CurrencyAmount
    582         for (int i=0; i<DATA.length; i+=4) {
    583             Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
    584 
    585             Currency curr = Currency.getInstance(locale);
    586             logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
    587             CurrencyAmount cAmt = new CurrencyAmount(1.5, curr);
    588             logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
    589 
    590             NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
    591             String sCurr = fmt.format(cAmt);
    592             if (sCurr.equals(DATA[i+3])) {
    593                 logln("Ok: 1.50 x " + locale + " => " + sCurr);
    594             } else {
    595                 errln("FAIL: 1.50 x " + locale + " => " + sCurr +
    596                         ", expected " + DATA[i+3]);
    597             }
    598         }
    599 
    600         //Cover MeasureFormat.getCurrencyFormat()
    601         ULocale save = ULocale.getDefault();
    602         ULocale.setDefault(ULocale.US);
    603         MeasureFormat curFmt = MeasureFormat.getCurrencyFormat();
    604         String strBuf = curFmt.format(new CurrencyAmount(new Float(1234.56), Currency.getInstance("USD")));
    605 
    606         try {
    607             CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(strBuf);
    608             Number val = parsedVal.getNumber();
    609             if (!val.equals(new BigDecimal("1234.56"))) {
    610                 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val);
    611             }
    612             if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) {
    613                 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency");
    614             }
    615         }
    616         catch (ParseException e) {
    617             errln("FAIL: " + e.getMessage());
    618         }
    619         ULocale.setDefault(save);
    620     }
    621 
    622     public void TestCurrencyIsoPluralFormat() {
    623         String[][] DATA = {
    624                 // the data are:
    625                 // locale,
    626                 // currency amount to be formatted,
    627                 // currency ISO code to be formatted,
    628                 // format result using CURRENCYSTYLE,
    629                 // format result using ISOCURRENCYSTYLE,
    630                 // format result using PLURALCURRENCYSTYLE,
    631                 {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"},
    632                 {"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
    633                 {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
    634                 {"zh_CN", "1", "USD", "US$\u00A01.00", "USD\u00A01.00", "1.00"},
    635                 {"zh_CN", "1234.56", "USD", "US$\u00A01,234.56", "USD\u00A01,234.56", "1,234.56"},
    636                 {"zh_CN", "1", "CNY", "\u00A01.00", "CNY\u00A01.00", "1.00"},
    637                 {"zh_CN", "1234.56", "CNY", "\u00A01,234.56", "CNY\u00A01,234.56", "1,234.56"},
    638                 {"ru_RU", "1", "RUB", "1,00.", "1,00RUB", "1,00  "},
    639                 {"ru_RU", "2", "RUB", "2,00.", "2,00RUB", "2,00  "},
    640                 {"ru_RU", "5", "RUB", "5,00.", "5,00RUB", "5,00  "},
    641                 // test locale without currency information
    642                 {"root", "-1.23", "USD", "-US$1.23", "-USD1.23", "-1.23 USD"},
    643                 {"root@numbers=latn", "-1.23", "USD", "-US$1.23", "-USD1.23", "-1.23 USD"}, // ensure that the root locale is still used with modifiers
    644                 {"root@numbers=arab", "-1.23", "USD", "\u200F-US$", "\u200F-USD", "\u200F- USD"}, // ensure that the root locale is still used with modifiers
    645                 {"es_AR", "1", "INR", "INR1,00", "INR1,00", "1,00 rupia india"},
    646                 {"ar_EG", "1", "USD", "US$", "USD", "  "},
    647         };
    648 
    649         for (int i=0; i<DATA.length; ++i) {
    650             for (int k = NumberFormat.CURRENCYSTYLE;
    651                     k <= NumberFormat.PLURALCURRENCYSTYLE;
    652                     ++k) {
    653                 // k represents currency format style.
    654                 if ( k != NumberFormat.CURRENCYSTYLE &&
    655                         k != NumberFormat.ISOCURRENCYSTYLE &&
    656                         k != NumberFormat.PLURALCURRENCYSTYLE ) {
    657                     continue;
    658                 }
    659                 String localeString = DATA[i][0];
    660                 Double numberToBeFormat = new Double(DATA[i][1]);
    661                 String currencyISOCode = DATA[i][2];
    662                 ULocale locale = new ULocale(localeString);
    663                 NumberFormat numFmt = NumberFormat.getInstance(locale, k);
    664                 numFmt.setCurrency(Currency.getInstance(currencyISOCode));
    665                 String strBuf = numFmt.format(numberToBeFormat);
    666                 int resultDataIndex = k-1;
    667                 if ( k == NumberFormat.CURRENCYSTYLE ) {
    668                     resultDataIndex = k+2;
    669                 }
    670                 // DATA[i][resultDataIndex] is the currency format result
    671                 // using 'k' currency style.
    672                 String formatResult = DATA[i][resultDataIndex];
    673                 if (!strBuf.equals(formatResult)) {
    674                     errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
    675                 }
    676                 try {
    677                     // test parsing, and test parsing for all currency formats.
    678                     for (int j = 3; j < 6; ++j) {
    679                         // DATA[i][3] is the currency format result using
    680                         // CURRENCYSTYLE formatter.
    681                         // DATA[i][4] is the currency format result using
    682                         // ISOCURRENCYSTYLE formatter.
    683                         // DATA[i][5] is the currency format result using
    684                         // PLURALCURRENCYSTYLE formatter.
    685                         String oneCurrencyFormatResult = DATA[i][j];
    686                         Number val = numFmt.parse(oneCurrencyFormatResult);
    687                         if (val.doubleValue() != numberToBeFormat.doubleValue()) {
    688                             errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat);
    689                         }
    690                     }
    691                 }
    692                 catch (ParseException e) {
    693                     errln("FAIL: " + e.getMessage());
    694                 }
    695             }
    696         }
    697     }
    698 
    699 
    700     public void TestMiscCurrencyParsing() {
    701         String[][] DATA = {
    702                 // each has: string to be parsed, parsed position, error position
    703                 {"1.00 ", "0", "4"},
    704                 {"1.00 UAE dirha", "0", "4"},
    705                 {"1.00 us dollar", "14", "-1"},
    706                 {"1.00 US DOLLAR", "14", "-1"},
    707                 {"1.00 usd", "0", "4"},
    708         };
    709         ULocale locale = new ULocale("en_US");
    710         for (int i=0; i<DATA.length; ++i) {
    711             String stringToBeParsed = DATA[i][0];
    712             int parsedPosition = Integer.parseInt(DATA[i][1]);
    713             int errorIndex = Integer.parseInt(DATA[i][2]);
    714             NumberFormat numFmt = NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
    715             ParsePosition parsePosition = new ParsePosition(0);
    716             Number val = numFmt.parse(stringToBeParsed, parsePosition);
    717             if (parsePosition.getIndex() != parsedPosition ||
    718                     parsePosition.getErrorIndex() != errorIndex) {
    719                 errln("FAIL: parse failed. expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex());
    720                 errln("FAIL: parse failed. expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex());
    721             }
    722             if (parsePosition.getErrorIndex() == -1 &&
    723                     val.doubleValue() != 1.00) {
    724                 errln("FAIL: parse failed. expected 1.00, actual:" + val);
    725             }
    726         }
    727     }
    728 
    729     public void TestParseCurrency() {
    730         class ParseCurrencyItem {
    731             private final String localeString;
    732             private final String descrip;
    733             private final String currStr;
    734             private final int    numExpectPos;
    735             private final int    numExpectVal;
    736             private final int    curExpectPos;
    737             private final int    curExpectVal;
    738             private final String curExpectCurr;
    739 
    740             ParseCurrencyItem(String locStr, String desc, String curr, int numExPos, int numExVal, int curExPos, int curExVal, String curExCurr) {
    741                 localeString  = locStr;
    742                 descrip       = desc;
    743                 currStr       = curr;
    744                 numExpectPos  = numExPos;
    745                 numExpectVal  = numExVal;
    746                 curExpectPos  = curExPos;
    747                 curExpectVal  = curExVal;
    748                 curExpectCurr = curExCurr;
    749             }
    750             public String getLocaleString()  { return localeString; }
    751             public String getDescrip()       { return descrip; }
    752             public String getCurrStr()       { return currStr; }
    753             public int    getNumExpectPos()  { return numExpectPos; }
    754             public int    getNumExpectVal()  { return numExpectVal; }
    755             public int    getCurExpectPos()  { return curExpectPos; }
    756             public int    getCurExpectVal()  { return curExpectVal; }
    757             public String getCurExpectCurr() { return curExpectCurr; }
    758         }
    759         final ParseCurrencyItem[] parseCurrencyItems = {
    760                 new ParseCurrencyItem( "en_US", "dollars2", "$2.00",            5,  2,  5,  2,  "USD" ),
    761                 new ParseCurrencyItem( "en_US", "dollars4", "$4",               2,  4,  2,  4,  "USD" ),
    762                 new ParseCurrencyItem( "en_US", "dollars9", "9\u00A0$",         0,  0,  0,  0,  ""    ),
    763                 new ParseCurrencyItem( "en_US", "pounds3",  "\u00A33.00",       0,  0,  5,  3,  "GBP" ),
    764                 new ParseCurrencyItem( "en_US", "pounds5",  "\u00A35",          0,  0,  2,  5,  "GBP" ),
    765                 new ParseCurrencyItem( "en_US", "pounds7",  "7\u00A0\u00A3",    0,  0,  0,  0,  ""    ),
    766                 new ParseCurrencyItem( "en_US", "euros8",   "\u20AC8",          0,  0,  2,  8,  "EUR" ),
    767 
    768                 new ParseCurrencyItem( "en_GB", "pounds3",  "\u00A33.00",       5,  3,  5,  3,  "GBP" ),
    769                 new ParseCurrencyItem( "en_GB", "pounds5",  "\u00A35",          2,  5,  2,  5,  "GBP" ),
    770                 new ParseCurrencyItem( "en_GB", "pounds7",  "7\u00A0\u00A3",    0,  0,  0,  0,  ""    ),
    771                 new ParseCurrencyItem( "en_GB", "euros4",   "4,00\u00A0\u20AC", 0,  0,  0,  0,  ""    ),
    772                 new ParseCurrencyItem( "en_GB", "euros6",   "6\u00A0\u20AC",    0,  0,  0,  0,  ""    ),
    773                 new ParseCurrencyItem( "en_GB", "euros8",   "\u20AC8",          0,  0,  2,  8,  "EUR" ),
    774                 new ParseCurrencyItem( "en_GB", "dollars4", "$4",               0,  0,  2,  4,  "USD" ),
    775 
    776                 new ParseCurrencyItem( "fr_FR", "euros4",   "4,00\u00A0\u20AC", 6,  4,  6,  4,  "EUR" ),
    777                 new ParseCurrencyItem( "fr_FR", "euros6",   "6\u00A0\u20AC",    3,  6,  3,  6,  "EUR" ),
    778                 new ParseCurrencyItem( "fr_FR", "euros8",   "\u20AC8",          0,  0,  0,  0,  ""    ),
    779                 new ParseCurrencyItem( "fr_FR", "dollars2", "$2.00",            0,  0,  0,  0,  ""    ),
    780                 new ParseCurrencyItem( "fr_FR", "dollars4", "$4",               0,  0,  0,  0,  ""    ),
    781         };
    782         for (ParseCurrencyItem item: parseCurrencyItems) {
    783             String localeString = item.getLocaleString();
    784             ULocale uloc = new ULocale(localeString);
    785             NumberFormat fmt = null;
    786             try {
    787                 fmt = NumberFormat.getCurrencyInstance(uloc);
    788             } catch (Exception e) {
    789                 errln("NumberFormat.getCurrencyInstance fails for locale " + localeString);
    790                 continue;
    791             }
    792             String currStr = item.getCurrStr();
    793             ParsePosition parsePos = new ParsePosition(0);
    794 
    795             Number numVal = fmt.parse(currStr, parsePos);
    796             if ( parsePos.getIndex() != item.getNumExpectPos() || (numVal != null && numVal.intValue() != item.getNumExpectVal()) ) {
    797                 if (numVal != null) {
    798                     errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() +
    799                             ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() +
    800                             ", get " + parsePos.getIndex() + "/" + numVal.intValue() );
    801                 } else {
    802                     errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() +
    803                             ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() +
    804                             ", get " + parsePos.getIndex() + "/(NULL)" );
    805                 }
    806             }
    807 
    808             parsePos.setIndex(0);
    809             CurrencyAmount currAmt = fmt.parseCurrency(currStr, parsePos);
    810             if ( parsePos.getIndex() != item.getCurExpectPos() || (currAmt != null && (currAmt.getNumber().intValue() != item.getCurExpectVal() ||
    811                     currAmt.getCurrency().getCurrencyCode().compareTo(item.getCurExpectCurr()) != 0)) ) {
    812                 if (currAmt != null) {
    813                     errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() +
    814                             ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() +
    815                             ", get " + parsePos.getIndex() + "/" + currAmt.getNumber().intValue() + "/" + currAmt.getCurrency().getCurrencyCode() );
    816                 } else {
    817                     errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() +
    818                             ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() +
    819                             ", get " + parsePos.getIndex() + "/(NULL)" );
    820                 }
    821             }
    822         }
    823     }
    824 
    825     /**
    826      * Test the Currency object handling, new as of ICU 2.2.
    827      */
    828     public void TestCurrencyObject() {
    829         NumberFormat fmt =
    830                 NumberFormat.getCurrencyInstance(Locale.US);
    831 
    832         expectCurrency(fmt, null, 1234.56, "$1,234.56");
    833 
    834         expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
    835                 1234.56, "\u20AC1,234.56"); // Euro
    836 
    837         expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
    838                 1234.56, "\u00A51,235"); // Yen
    839 
    840         expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
    841                 1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
    842 
    843         expectCurrency(fmt, Currency.getInstance(Locale.US),
    844                 1234.56, "$1,234.56");
    845 
    846         fmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);
    847 
    848         expectCurrency(fmt, null, 1234.56, "1 234,56 \u20AC");
    849 
    850         expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
    851                 1234.56, "1 235 JPY"); // Yen
    852 
    853         expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
    854                 1234.56, "1 234,56 CHF"); // no more rounding here, see cldrbug 5548
    855 
    856         expectCurrency(fmt, Currency.getInstance(Locale.US),
    857                 1234.56, "1 234,56 $US");
    858 
    859         expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
    860                 1234.56, "1 234,56 \u20AC"); // Euro
    861     }
    862 
    863     public void TestCompatibleCurrencies() {
    864         NumberFormat fmt =
    865                 NumberFormat.getCurrencyInstance(Locale.US);
    866         expectParseCurrency(fmt, Currency.getInstance(Locale.JAPAN), "\u00A51,235"); // Yen half-width
    867         expectParseCurrency(fmt, Currency.getInstance(Locale.JAPAN), "\uFFE51,235"); // Yen full-wdith
    868     }
    869 
    870     public void TestCurrencyPatterns() {
    871         int i;
    872         Locale[] locs = NumberFormat.getAvailableLocales();
    873         for (i=0; i<locs.length; ++i) {
    874             NumberFormat nf = NumberFormat.getCurrencyInstance(locs[i]);
    875             // Make sure currency formats do not have a variable number
    876             // of fraction digits
    877             int min = nf.getMinimumFractionDigits();
    878             int max = nf.getMaximumFractionDigits();
    879             if (min != max) {
    880                 String a = nf.format(1.0);
    881                 String b = nf.format(1.125);
    882                 errln("FAIL: " + locs[i] +
    883                         " min fraction digits != max fraction digits; "+
    884                         "x 1.0 => " + a +
    885                         "; x 1.125 => " + b);
    886             }
    887 
    888             // Make sure EURO currency formats have exactly 2 fraction digits
    889             if (nf instanceof DecimalFormat) {
    890                 Currency curr = ((DecimalFormat) nf).getCurrency();
    891                 if (curr != null && "EUR".equals(curr.getCurrencyCode())) {
    892                     if (min != 2 || max != 2) {
    893                         String a = nf.format(1.0);
    894                         errln("FAIL: " + locs[i] +
    895                                 " is a EURO format but it does not have 2 fraction digits; "+
    896                                 "x 1.0 => " +
    897                                 a);
    898                     }
    899                 }
    900             }
    901         }
    902     }
    903 
    904     /**
    905      * Do rudimentary testing of parsing.
    906      */
    907     public void TestParse() {
    908         String arg = "0.0";
    909         DecimalFormat format = new DecimalFormat("00");
    910         double aNumber = 0l;
    911         try {
    912             aNumber = format.parse(arg).doubleValue();
    913         } catch (ParseException e) {
    914             System.out.println(e);
    915         }
    916         logln("parse(" + arg + ") = " + aNumber);
    917     }
    918 
    919     /**
    920      * Test proper rounding by the format method.
    921      */
    922     public void TestRounding487() {
    923 
    924         NumberFormat nf = NumberFormat.getInstance();
    925         roundingTest(nf, 0.00159999, 4, "0.0016");
    926         roundingTest(nf, 0.00995, 4, "0.01");
    927 
    928         roundingTest(nf, 12.3995, 3, "12.4");
    929 
    930         roundingTest(nf, 12.4999, 0, "12");
    931         roundingTest(nf, - 19.5, 0, "-20");
    932 
    933     }
    934 
    935     /**
    936      * Test the functioning of the secondary grouping value.
    937      */
    938     public void TestSecondaryGrouping() {
    939 
    940         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
    941         DecimalFormat f = new DecimalFormat("#,##,###", US);
    942 
    943         expect(f, 123456789L, "12,34,56,789");
    944         expectPat(f, "#,##,###");
    945         f.applyPattern("#,###");
    946 
    947         f.setSecondaryGroupingSize(4);
    948         expect(f, 123456789L, "12,3456,789");
    949         expectPat(f, "#,####,###");
    950         NumberFormat g = NumberFormat.getInstance(new Locale("hi", "IN"));
    951 
    952         String out = "";
    953         long l = 1876543210L;
    954         out = g.format(l);
    955 
    956         // expect "1,87,65,43,210", but with Hindi digits
    957         //         01234567890123
    958         boolean ok = true;
    959         if (out.length() != 14) {
    960             ok = false;
    961         } else {
    962             for (int i = 0; i < out.length(); ++i) {
    963                 boolean expectGroup = false;
    964                 switch (i) {
    965                 case 1 :
    966                 case 4 :
    967                 case 7 :
    968                 case 10 :
    969                     expectGroup = true;
    970                     break;
    971                 }
    972                 // Later -- fix this to get the actual grouping
    973                 // character from the resource bundle.
    974                 boolean isGroup = (out.charAt(i) == 0x002C);
    975                 if (isGroup != expectGroup) {
    976                     ok = false;
    977                     break;
    978                 }
    979             }
    980         }
    981         if (!ok) {
    982             errln("FAIL  Expected "+ l + " x hi_IN . \"1,87,65,43,210\" (with Hindi digits), got \""
    983                     + out + "\"");
    984         } else {
    985             logln("Ok    " + l + " x hi_IN . \"" + out + "\"");
    986         }
    987     }
    988 
    989     public void roundingTest(NumberFormat nf, double x, int maxFractionDigits, final String expected) {
    990         nf.setMaximumFractionDigits(maxFractionDigits);
    991         String out = nf.format(x);
    992         logln(x + " formats with " + maxFractionDigits + " fractional digits to " + out);
    993         if (!out.equals(expected))
    994             errln("FAIL: Expected " + expected);
    995     }
    996 
    997     /**
    998      * Upgrade to alphaWorks
    999      */
   1000     public void TestExponent() {
   1001         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
   1002         DecimalFormat fmt1 = new DecimalFormat("0.###E0", US);
   1003         DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US);
   1004         int n = 1234;
   1005         expect2(fmt1, n, "1.234E3");
   1006         expect2(fmt2, n, "1.234E+3");
   1007         expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
   1008 
   1009     }
   1010 
   1011     /**
   1012      * Upgrade to alphaWorks
   1013      */
   1014     public void TestScientific() {
   1015 
   1016         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
   1017 
   1018         // Test pattern round-trip
   1019         final String PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };
   1020         int PAT_length = PAT.length;
   1021         int DIGITS[] = {
   1022                 // min int, max int, min frac, max frac
   1023                 0, 1, 0, 0, // "#E0"
   1024                 1, 1, 0, 4, // "0.####E0"
   1025                 2, 2, 3, 3, // "00.000E00"
   1026                 1, 3, 0, 4, // "##0.####E000"
   1027                 1, 1, 0, 3, // "0.###E0;[0.###E0]"
   1028         };
   1029         for (int i = 0; i < PAT_length; ++i) {
   1030             String pat = PAT[i];
   1031             DecimalFormat df = new DecimalFormat(pat, US);
   1032             String pat2 = df.toPattern();
   1033             if (pat.equals(pat2)) {
   1034                 logln("Ok   Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
   1035             } else {
   1036                 errln("FAIL Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
   1037             }
   1038             // Make sure digit counts match what we expect
   1039             if (df.getMinimumIntegerDigits() != DIGITS[4 * i]
   1040                     || df.getMaximumIntegerDigits() != DIGITS[4 * i + 1]
   1041                             || df.getMinimumFractionDigits() != DIGITS[4 * i + 2]
   1042                                     || df.getMaximumFractionDigits() != DIGITS[4 * i + 3]) {
   1043                 errln("FAIL \""+ pat+ "\" min/max int; min/max frac = "
   1044                         + df.getMinimumIntegerDigits() + "/"
   1045                         + df.getMaximumIntegerDigits() + ";"
   1046                         + df.getMinimumFractionDigits() + "/"
   1047                         + df.getMaximumFractionDigits() + ", expect "
   1048                         + DIGITS[4 * i] + "/"
   1049                         + DIGITS[4 * i + 1] + ";"
   1050                         + DIGITS[4 * i + 2] + "/"
   1051                         + DIGITS[4 * i + 3]);
   1052             }
   1053         }
   1054 
   1055         expect2(new DecimalFormat("#E0", US), 12345.0, "1.2345E4");
   1056         expect(new DecimalFormat("0E0", US), 12345.0, "1E4");
   1057 
   1058         // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
   1059         // so result = 1.234568E4 not 1.2345678901E4
   1060         //when the pattern problem is finalized, delete comment mark'//'
   1061         //of the following code
   1062         expect2(NumberFormat.getScientificInstance(Locale.US), 12345.678901, "1.2345678901E4");
   1063         logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
   1064         expect2(NumberFormat.getScientificInstance(ULocale.US), 12345.678901, "1.2345678901E4");
   1065 
   1066         expect(new DecimalFormat("##0.###E0", US), 12345.0, "12.34E3");
   1067         expect(new DecimalFormat("##0.###E0", US), 12345.00001, "12.35E3");
   1068         expect2(new DecimalFormat("##0.####E0", US), 12345, "12.345E3");
   1069 
   1070         // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
   1071         // so result = 1.234568E4 not 1.2345678901E4
   1072         expect2(NumberFormat.getScientificInstance(Locale.FRANCE), 12345.678901, "1,2345678901E4");
   1073         logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
   1074         expect2(NumberFormat.getScientificInstance(ULocale.FRANCE), 12345.678901, "1,2345678901E4");
   1075 
   1076         expect(new DecimalFormat("##0.####E0", US), 789.12345e-9, "789.12E-9");
   1077         expect2(new DecimalFormat("##0.####E0", US), 780.e-9, "780E-9");
   1078         expect(new DecimalFormat(".###E0", US), 45678.0, ".457E5");
   1079         expect2(new DecimalFormat(".###E0", US), 0, ".0E0");
   1080         /*
   1081         expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
   1082                                      new DecimalFormat("##E0", US),
   1083                                      new DecimalFormat("####E0", US),
   1084                                      new DecimalFormat("0E0", US),
   1085                                      new DecimalFormat("00E0", US),
   1086                                      new DecimalFormat("000E0", US),
   1087                                    },
   1088                new Long(45678000),
   1089                new String[] { "4.5678E7",
   1090                               "45.678E6",
   1091                               "4567.8E4",
   1092                               "5E7",
   1093                               "46E6",
   1094                               "457E5",
   1095                             }
   1096                );
   1097         !
   1098         ! Unroll this test into individual tests below...
   1099         !
   1100          */
   1101         expect2(new DecimalFormat("#E0", US), 45678000, "4.5678E7");
   1102         expect2(new DecimalFormat("##E0", US), 45678000, "45.678E6");
   1103         expect2(new DecimalFormat("####E0", US), 45678000, "4567.8E4");
   1104         expect(new DecimalFormat("0E0", US), 45678000, "5E7");
   1105         expect(new DecimalFormat("00E0", US), 45678000, "46E6");
   1106         expect(new DecimalFormat("000E0", US), 45678000, "457E5");
   1107         /*
   1108         expect(new DecimalFormat("###E0", US, status),
   1109                new Object[] { new Double(0.0000123), "12.3E-6",
   1110                               new Double(0.000123), "123E-6",
   1111                               new Double(0.00123), "1.23E-3",
   1112                               new Double(0.0123), "12.3E-3",
   1113                               new Double(0.123), "123E-3",
   1114                               new Double(1.23), "1.23E0",
   1115                               new Double(12.3), "12.3E0",
   1116                               new Double(123), "123E0",
   1117                               new Double(1230), "1.23E3",
   1118                              });
   1119         !
   1120         ! Unroll this test into individual tests below...
   1121         !
   1122          */
   1123         expect2(new DecimalFormat("###E0", US), 0.0000123, "12.3E-6");
   1124         expect2(new DecimalFormat("###E0", US), 0.000123, "123E-6");
   1125         expect2(new DecimalFormat("###E0", US), 0.00123, "1.23E-3");
   1126         expect2(new DecimalFormat("###E0", US), 0.0123, "12.3E-3");
   1127         expect2(new DecimalFormat("###E0", US), 0.123, "123E-3");
   1128         expect2(new DecimalFormat("###E0", US), 1.23, "1.23E0");
   1129         expect2(new DecimalFormat("###E0", US), 12.3, "12.3E0");
   1130         expect2(new DecimalFormat("###E0", US), 123.0, "123E0");
   1131         expect2(new DecimalFormat("###E0", US), 1230.0, "1.23E3");
   1132         /*
   1133         expect(new DecimalFormat("0.#E+00", US, status),
   1134                new Object[] { new Double(0.00012), "1.2E-04",
   1135                               new Long(12000),     "1.2E+04",
   1136                              });
   1137         !
   1138         ! Unroll this test into individual tests below...
   1139         !
   1140          */
   1141         expect2(new DecimalFormat("0.#E+00", US), 0.00012, "1.2E-04");
   1142         expect2(new DecimalFormat("0.#E+00", US), 12000, "1.2E+04");
   1143     }
   1144 
   1145     /**
   1146      * Upgrade to alphaWorks
   1147      */
   1148     public void TestPad() {
   1149 
   1150         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
   1151         expect2(new DecimalFormat("*^##.##", US), 0, "^^^^0");
   1152         expect2(new DecimalFormat("*^##.##", US), -1.3, "^-1.3");
   1153         expect2(
   1154                 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
   1155                 0,
   1156                 "0.0E0______ g-m/s^2");
   1157         expect(
   1158                 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
   1159                 1.0 / 3,
   1160                 "333.333E-3_ g-m/s^2");
   1161         expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US), 0, "0.0______ g-m/s^2");
   1162         expect(
   1163                 new DecimalFormat("##0.0####*_ 'g-m/s^2'", US),
   1164                 1.0 / 3,
   1165                 "0.33333__ g-m/s^2");
   1166 
   1167         // Test padding before a sign
   1168         final String formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
   1169         expect2(new DecimalFormat(formatStr, US), -10, "xxxxxxxxxx(10.0)");
   1170         expect2(new DecimalFormat(formatStr, US), -1000, "xxxxxxx(1,000.0)");
   1171         expect2(new DecimalFormat(formatStr, US), -1000000, "xxx(1,000,000.0)");
   1172         expect2(new DecimalFormat(formatStr, US), -100.37, "xxxxxxxx(100.37)");
   1173         expect2(new DecimalFormat(formatStr, US), -10456.37, "xxxxx(10,456.37)");
   1174         expect2(new DecimalFormat(formatStr, US), -1120456.37, "xx(1,120,456.37)");
   1175         expect2(new DecimalFormat(formatStr, US), -112045600.37, "(112,045,600.37)");
   1176         expect2(new DecimalFormat(formatStr, US), -1252045600.37, "(1,252,045,600.37)");
   1177 
   1178         expect2(new DecimalFormat(formatStr, US), 10, "xxxxxxxxxxxx10.0");
   1179         expect2(new DecimalFormat(formatStr, US), 1000, "xxxxxxxxx1,000.0");
   1180         expect2(new DecimalFormat(formatStr, US), 1000000, "xxxxx1,000,000.0");
   1181         expect2(new DecimalFormat(formatStr, US), 100.37, "xxxxxxxxxx100.37");
   1182         expect2(new DecimalFormat(formatStr, US), 10456.37, "xxxxxxx10,456.37");
   1183         expect2(new DecimalFormat(formatStr, US), 1120456.37, "xxxx1,120,456.37");
   1184         expect2(new DecimalFormat(formatStr, US), 112045600.37, "xx112,045,600.37");
   1185         expect2(new DecimalFormat(formatStr, US), 10252045600.37, "10,252,045,600.37");
   1186 
   1187         // Test padding between a sign and a number
   1188         final String formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
   1189         expect2(new DecimalFormat(formatStr2, US), -10, "(10.0xxxxxxxxxx)");
   1190         expect2(new DecimalFormat(formatStr2, US), -1000, "(1,000.0xxxxxxx)");
   1191         expect2(new DecimalFormat(formatStr2, US), -1000000, "(1,000,000.0xxx)");
   1192         expect2(new DecimalFormat(formatStr2, US), -100.37, "(100.37xxxxxxxx)");
   1193         expect2(new DecimalFormat(formatStr2, US), -10456.37, "(10,456.37xxxxx)");
   1194         expect2(new DecimalFormat(formatStr2, US), -1120456.37, "(1,120,456.37xx)");
   1195         expect2(new DecimalFormat(formatStr2, US), -112045600.37, "(112,045,600.37)");
   1196         expect2(new DecimalFormat(formatStr2, US), -1252045600.37, "(1,252,045,600.37)");
   1197 
   1198         expect2(new DecimalFormat(formatStr2, US), 10, "10.0xxxxxxxxxxxx");
   1199         expect2(new DecimalFormat(formatStr2, US), 1000, "1,000.0xxxxxxxxx");
   1200         expect2(new DecimalFormat(formatStr2, US), 1000000, "1,000,000.0xxxxx");
   1201         expect2(new DecimalFormat(formatStr2, US), 100.37, "100.37xxxxxxxxxx");
   1202         expect2(new DecimalFormat(formatStr2, US), 10456.37, "10,456.37xxxxxxx");
   1203         expect2(new DecimalFormat(formatStr2, US), 1120456.37, "1,120,456.37xxxx");
   1204         expect2(new DecimalFormat(formatStr2, US), 112045600.37, "112,045,600.37xx");
   1205         expect2(new DecimalFormat(formatStr2, US), 10252045600.37, "10,252,045,600.37");
   1206 
   1207         //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
   1208         DecimalFormat fmt = new DecimalFormat("#", US);
   1209         char padString = 'P';
   1210         fmt.setPadCharacter(padString);
   1211         expectPad(fmt, "*P##.##", DecimalFormat.PAD_BEFORE_PREFIX, 5, padString);
   1212         fmt.setPadCharacter('^');
   1213         expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, '^');
   1214         //commented untill implementation is complete
   1215         /*  fmt.setPadCharacter((UnicodeString)"^^^");
   1216           expectPad(fmt, "*^^^#", DecimalFormat.kPadBeforePrefix, 3, (UnicodeString)"^^^");
   1217           padString.remove();
   1218           padString.append((UChar)0x0061);
   1219           padString.append((UChar)0x0302);
   1220           fmt.setPadCharacter(padString);
   1221           UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
   1222           UnicodeString pattern(patternChars);
   1223           expectPad(fmt, pattern , DecimalFormat.kPadBeforePrefix, 4, padString);
   1224          */
   1225     }
   1226 
   1227     /**
   1228      * Upgrade to alphaWorks
   1229      */
   1230     public void TestPatterns2() {
   1231         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
   1232         DecimalFormat fmt = new DecimalFormat("#", US);
   1233 
   1234         char hat = 0x005E; /*^*/
   1235 
   1236         expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, hat);
   1237         expectPad(fmt, "$*^#", DecimalFormat.PAD_AFTER_PREFIX, 2, hat);
   1238         expectPad(fmt, "#*^", DecimalFormat.PAD_BEFORE_SUFFIX, 1, hat);
   1239         expectPad(fmt, "#$*^", DecimalFormat.PAD_AFTER_SUFFIX, 2, hat);
   1240         expectPad(fmt, "$*^$#", -1);
   1241         expectPad(fmt, "#$*^$", -1);
   1242         expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat.PAD_BEFORE_SUFFIX, 12, (char) 0x0078 /*x*/);
   1243         expectPad(fmt, "''#0*x", DecimalFormat.PAD_BEFORE_SUFFIX, 3, (char) 0x0078 /*x*/);
   1244         expectPad(fmt, "'I''ll'*a###.##", DecimalFormat.PAD_AFTER_PREFIX, 10, (char) 0x0061 /*a*/);
   1245 
   1246         fmt.applyPattern("AA#,##0.00ZZ");
   1247         fmt.setPadCharacter(hat);
   1248 
   1249         fmt.setFormatWidth(10);
   1250 
   1251         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_PREFIX);
   1252         expectPat(fmt, "*^AA#,##0.00ZZ");
   1253 
   1254         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_SUFFIX);
   1255         expectPat(fmt, "AA#,##0.00*^ZZ");
   1256 
   1257         fmt.setPadPosition(DecimalFormat.PAD_AFTER_SUFFIX);
   1258         expectPat(fmt, "AA#,##0.00ZZ*^");
   1259 
   1260         //            12  3456789012
   1261         String exp = "AA*^#,##0.00ZZ";
   1262         fmt.setFormatWidth(12);
   1263         fmt.setPadPosition(DecimalFormat.PAD_AFTER_PREFIX);
   1264         expectPat(fmt, exp);
   1265 
   1266         fmt.setFormatWidth(13);
   1267         //              12  34567890123
   1268         expectPat(fmt, "AA*^##,##0.00ZZ");
   1269 
   1270         fmt.setFormatWidth(14);
   1271         //              12  345678901234
   1272         expectPat(fmt, "AA*^###,##0.00ZZ");
   1273 
   1274         fmt.setFormatWidth(15);
   1275         //              12  3456789012345
   1276         expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
   1277 
   1278         fmt.setFormatWidth(16);
   1279         //              12  34567890123456
   1280         expectPat(fmt, "AA*^#,###,##0.00ZZ");
   1281     }
   1282 
   1283     public void TestRegistration() {
   1284         final ULocale SRC_LOC = ULocale.FRANCE;
   1285         final ULocale SWAP_LOC = ULocale.US;
   1286 
   1287         class TestFactory extends SimpleNumberFormatFactory {
   1288             NumberFormat currencyStyle;
   1289 
   1290             TestFactory() {
   1291                 super(SRC_LOC, true);
   1292                 currencyStyle = NumberFormat.getIntegerInstance(SWAP_LOC);
   1293             }
   1294 
   1295             @Override
   1296             public NumberFormat createFormat(ULocale loc, int formatType) {
   1297                 if (formatType == FORMAT_CURRENCY) {
   1298                     return currencyStyle;
   1299                 }
   1300                 return null;
   1301             }
   1302         }
   1303 
   1304         NumberFormat f0 = NumberFormat.getIntegerInstance(SWAP_LOC);
   1305         NumberFormat f1 = NumberFormat.getIntegerInstance(SRC_LOC);
   1306         NumberFormat f2 = NumberFormat.getCurrencyInstance(SRC_LOC);
   1307         Object key = NumberFormat.registerFactory(new TestFactory());
   1308         NumberFormat f3 = NumberFormat.getCurrencyInstance(SRC_LOC);
   1309         NumberFormat f4 = NumberFormat.getIntegerInstance(SRC_LOC);
   1310         NumberFormat.unregister(key); // restore for other tests
   1311         NumberFormat f5 = NumberFormat.getCurrencyInstance(SRC_LOC);
   1312 
   1313         float n = 1234.567f;
   1314         logln("f0 swap int: " + f0.format(n));
   1315         logln("f1 src int: " + f1.format(n));
   1316         logln("f2 src cur: " + f2.format(n));
   1317         logln("f3 reg cur: " + f3.format(n));
   1318         logln("f4 reg int: " + f4.format(n));
   1319         logln("f5 unreg cur: " + f5.format(n));
   1320 
   1321         if (!f3.format(n).equals(f0.format(n))) {
   1322             errln("registered service did not match");
   1323         }
   1324         if (!f4.format(n).equals(f1.format(n))) {
   1325             errln("registered service did not inherit");
   1326         }
   1327         if (!f5.format(n).equals(f2.format(n))) {
   1328             errln("unregistered service did not match original");
   1329         }
   1330     }
   1331 
   1332     public void TestScientific2() {
   1333         // jb 2552
   1334         DecimalFormat fmt = (DecimalFormat)NumberFormat.getCurrencyInstance();
   1335         Number num = new Double(12.34);
   1336         expect(fmt, num, "$12.34");
   1337         fmt.setScientificNotation(true);
   1338         expect(fmt, num, "$1.23E1");
   1339         fmt.setScientificNotation(false);
   1340         expect(fmt, num, "$12.34");
   1341     }
   1342 
   1343     public void TestScientificGrouping() {
   1344         // jb 2552
   1345         DecimalFormat fmt = new DecimalFormat("###.##E0");
   1346         expect(fmt, .01234, "12.3E-3");
   1347         expect(fmt, .1234, "123E-3");
   1348         expect(fmt, 1.234, "1.23E0");
   1349         expect(fmt, 12.34, "12.3E0");
   1350         expect(fmt, 123.4, "123E0");
   1351         expect(fmt, 1234, "1.23E3");
   1352     }
   1353 
   1354     // additional coverage tests
   1355 
   1356     // sigh, can't have static inner classes, why not?
   1357 
   1358     static final class PI extends Number {
   1359         /**
   1360          * For serialization
   1361          */
   1362         private static final long serialVersionUID = -305601227915602172L;
   1363 
   1364         private PI() {}
   1365         @Override
   1366         public int intValue() { return (int)Math.PI; }
   1367         @Override
   1368         public long longValue() { return (long)Math.PI; }
   1369         @Override
   1370         public float  floatValue() { return (float)Math.PI; }
   1371         @Override
   1372         public double doubleValue() { return Math.PI; }
   1373         @Override
   1374         public byte byteValue() { return (byte)Math.PI; }
   1375         @Override
   1376         public short shortValue() { return (short)Math.PI; }
   1377 
   1378         public static final Number INSTANCE = new PI();
   1379     }
   1380 
   1381     public void TestCoverage() {
   1382         NumberFormat fmt = NumberFormat.getNumberInstance(); // default locale
   1383         logln(fmt.format(new BigInteger("1234567890987654321234567890987654321", 10)));
   1384 
   1385         fmt = NumberFormat.getScientificInstance(); // default locale
   1386 
   1387         logln(fmt.format(PI.INSTANCE));
   1388 
   1389         try {
   1390             logln(fmt.format("12345"));
   1391             errln("numberformat of string did not throw exception");
   1392         }
   1393         catch (Exception e) {
   1394             logln("PASS: numberformat of string failed as expected");
   1395         }
   1396 
   1397         int hash = fmt.hashCode();
   1398         logln("hash code " + hash);
   1399 
   1400         logln("compare to string returns: " + fmt.equals(""));
   1401 
   1402         // For ICU 2.6 - alan
   1403         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
   1404         DecimalFormat df = new DecimalFormat("'*&'' '\u00A4' ''&*' #,##0.00", US);
   1405         df.setCurrency(Currency.getInstance("INR"));
   1406         expect2(df, 1.0, "*&' \u20B9 '&* 1.00");
   1407         expect2(df, -2.0, "-*&' \u20B9 '&* 2.00");
   1408         df.applyPattern("#,##0.00 '*&'' '\u00A4' ''&*'");
   1409         expect2(df, 2.0, "2.00 *&' \u20B9 '&*");
   1410         expect2(df, -1.0, "-1.00 *&' \u20B9 '&*");
   1411 
   1412         java.math.BigDecimal r;
   1413 
   1414         r = df.getRoundingIncrement();
   1415         if (r != null) {
   1416             errln("FAIL: rounding = " + r + ", expect null");
   1417         }
   1418 
   1419         if (df.isScientificNotation()) {
   1420             errln("FAIL: isScientificNotation = true, expect false");
   1421         }
   1422 
   1423         df.applyPattern("0.00000");
   1424         df.setScientificNotation(true);
   1425         if (!df.isScientificNotation()) {
   1426             errln("FAIL: isScientificNotation = false, expect true");
   1427         }
   1428         df.setMinimumExponentDigits((byte)2);
   1429         if (df.getMinimumExponentDigits() != 2) {
   1430             errln("FAIL: getMinimumExponentDigits = " +
   1431                     df.getMinimumExponentDigits() + ", expect 2");
   1432         }
   1433         df.setExponentSignAlwaysShown(true);
   1434         if (!df.isExponentSignAlwaysShown()) {
   1435             errln("FAIL: isExponentSignAlwaysShown = false, expect true");
   1436         }
   1437         df.setSecondaryGroupingSize(0);
   1438         if (df.getSecondaryGroupingSize() != 0) {
   1439             errln("FAIL: getSecondaryGroupingSize = " +
   1440                     df.getSecondaryGroupingSize() + ", expect 0");
   1441         }
   1442         expect2(df, 3.14159, "3.14159E+00");
   1443 
   1444         // DecimalFormatSymbols#getInstance
   1445         DecimalFormatSymbols decsym1 = DecimalFormatSymbols.getInstance();
   1446         DecimalFormatSymbols decsym2 = new DecimalFormatSymbols();
   1447         if (!decsym1.equals(decsym2)) {
   1448             errln("FAIL: DecimalFormatSymbols returned by getInstance()" +
   1449                     "does not match new DecimalFormatSymbols().");
   1450         }
   1451         decsym1 = DecimalFormatSymbols.getInstance(Locale.JAPAN);
   1452         decsym2 = DecimalFormatSymbols.getInstance(ULocale.JAPAN);
   1453         if (!decsym1.equals(decsym2)) {
   1454             errln("FAIL: DecimalFormatSymbols returned by getInstance(Locale.JAPAN)" +
   1455                     "does not match the one returned by getInstance(ULocale.JAPAN).");
   1456         }
   1457 
   1458         // DecimalFormatSymbols#getAvailableLocales/#getAvailableULocales
   1459         Locale[] allLocales = DecimalFormatSymbols.getAvailableLocales();
   1460         if (allLocales.length == 0) {
   1461             errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
   1462         } else {
   1463             logln("PASS: " + allLocales.length +
   1464                     " available locales returned by DecimalFormatSymbols.getAvailableLocales");
   1465         }
   1466         ULocale[] allULocales = DecimalFormatSymbols.getAvailableULocales();
   1467         if (allULocales.length == 0) {
   1468             errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
   1469         } else {
   1470             logln("PASS: " + allULocales.length +
   1471                     " available locales returned by DecimalFormatSymbols.getAvailableULocales");
   1472         }
   1473     }
   1474 
   1475     public void TestWhiteSpaceParsing() {
   1476         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
   1477         DecimalFormat fmt = new DecimalFormat("a  b#0c  ", US);
   1478         int n = 1234;
   1479         expect(fmt, "a b1234c ", n);
   1480         expect(fmt, "a   b1234c   ", n);
   1481     }
   1482 
   1483     /**
   1484      * Test currencies whose display name is a ChoiceFormat.
   1485      */
   1486     public void TestComplexCurrency() {
   1487         //  CLDR No Longer uses complex currency symbols.
   1488         //  Skipping this test.
   1489         //        Locale loc = new Locale("kn", "IN", "");
   1490         //        NumberFormat fmt = NumberFormat.getCurrencyInstance(loc);
   1491 
   1492         //        expect2(fmt, 1.0, "Re.\u00a01.00");
   1493         //        expect(fmt, 1.001, "Re.\u00a01.00"); // tricky
   1494         //        expect2(fmt, 12345678.0, "Rs.\u00a01,23,45,678.00");
   1495         //        expect2(fmt, 0.5, "Rs.\u00a00.50");
   1496         //        expect2(fmt, -1.0, "-Re.\u00a01.00");
   1497         //        expect2(fmt, -10.0, "-Rs.\u00a010.00");
   1498     }
   1499 
   1500     public void TestCurrencyKeyword() {
   1501         ULocale locale = new ULocale("th_TH@currency=QQQ");
   1502         NumberFormat format = NumberFormat.getCurrencyInstance(locale);
   1503         String result = format.format(12.34f);
   1504         if (!"QQQ12.34".equals(result)) {
   1505             errln("got unexpected currency: " + result);
   1506         }
   1507     }
   1508 
   1509     /**
   1510      * Test alternate numbering systems
   1511      */
   1512     public void TestNumberingSystems() {
   1513         class TestNumberingSystemItem {
   1514             private final String localeName;
   1515             private final double value;
   1516             private final boolean isRBNF;
   1517             private final String expectedResult;
   1518 
   1519             TestNumberingSystemItem(String loc, double val, boolean rbnf, String exp) {
   1520                 localeName  = loc;
   1521                 value = val;
   1522                 isRBNF = rbnf;
   1523                 expectedResult = exp;
   1524             }
   1525         }
   1526 
   1527         final TestNumberingSystemItem[] DATA = {
   1528                 new TestNumberingSystemItem( "en_US@numbers=thai",        1234.567, false, "\u0e51,\u0e52\u0e53\u0e54.\u0e55\u0e56\u0e57" ),
   1529                 new TestNumberingSystemItem( "en_US@numbers=thai",        1234.567, false, "\u0E51,\u0E52\u0E53\u0E54.\u0E55\u0E56\u0E57" ),
   1530                 new TestNumberingSystemItem( "en_US@numbers=hebr",        5678.0,   true,  "\u05D4\u05F3\u05EA\u05E8\u05E2\u05F4\u05D7" ),
   1531                 new TestNumberingSystemItem( "en_US@numbers=arabext",     1234.567, false, "\u06F1\u066c\u06F2\u06F3\u06F4\u066b\u06F5\u06F6\u06F7" ),
   1532                 new TestNumberingSystemItem( "de_DE@numbers=foobar",      1234.567, false, "1.234,567" ),
   1533                 new TestNumberingSystemItem( "ar_EG",                     1234.567, false, "\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666\u0667" ),
   1534                 new TestNumberingSystemItem( "th_TH@numbers=traditional", 1234.567, false, "\u0E51,\u0E52\u0E53\u0E54.\u0E55\u0E56\u0E57" ), // fall back to native per TR35
   1535                 new TestNumberingSystemItem( "ar_MA",                     1234.567, false, "1.234,567" ),
   1536                 new TestNumberingSystemItem( "en_US@numbers=hanidec",     1234.567, false, "\u4e00,\u4e8c\u4e09\u56db.\u4e94\u516d\u4e03" ),
   1537                 new TestNumberingSystemItem( "ta_IN@numbers=native",      1234.567, false, "\u0BE7,\u0BE8\u0BE9\u0BEA.\u0BEB\u0BEC\u0BED" ),
   1538                 new TestNumberingSystemItem( "ta_IN@numbers=traditional", 1235.0,   true,  "\u0BF2\u0BE8\u0BF1\u0BE9\u0BF0\u0BEB" ),
   1539                 new TestNumberingSystemItem( "ta_IN@numbers=finance",     1234.567, false, "1,234.567" ), // fall back to default per TR35
   1540                 new TestNumberingSystemItem( "zh_TW@numbers=native",      1234.567, false, "\u4e00,\u4e8c\u4e09\u56db.\u4e94\u516d\u4e03" ),
   1541                 new TestNumberingSystemItem( "zh_TW@numbers=traditional", 1234.567, true,  "\u4E00\u5343\u4E8C\u767E\u4E09\u5341\u56DB\u9EDE\u4E94\u516D\u4E03" ),
   1542                 new TestNumberingSystemItem( "zh_TW@numbers=finance",     1234.567, true,  "\u58F9\u4EDF\u8CB3\u4F70\u53C3\u62FE\u8086\u9EDE\u4F0D\u9678\u67D2" )
   1543         };
   1544 
   1545 
   1546         for (TestNumberingSystemItem item : DATA) {
   1547             ULocale loc = new ULocale(item.localeName);
   1548             NumberFormat fmt = NumberFormat.getInstance(loc);
   1549             if (item.isRBNF) {
   1550                 expect3(fmt,item.value,item.expectedResult);
   1551             } else {
   1552                 expect2(fmt,item.value,item.expectedResult);
   1553             }
   1554         }
   1555     }
   1556 
   1557     public void Test6816() {
   1558         Currency cur1 = Currency.getInstance(new Locale("und", "PH"));
   1559 
   1560         NumberFormat nfmt = NumberFormat.getCurrencyInstance(new Locale("und", "PH"));
   1561         DecimalFormatSymbols decsym = ((DecimalFormat)nfmt).getDecimalFormatSymbols();
   1562         Currency cur2 = decsym.getCurrency();
   1563 
   1564         if ( !cur1.getCurrencyCode().equals("PHP") || !cur2.getCurrencyCode().equals("PHP")) {
   1565             errln("FAIL: Currencies should match PHP: cur1 = "+cur1.getCurrencyCode()+"; cur2 = "+cur2.getCurrencyCode());
   1566         }
   1567 
   1568     }
   1569 
   1570     public void TestThreadedFormat() {
   1571 
   1572         class FormatTask implements Runnable {
   1573             DecimalFormat fmt;
   1574             StringBuffer buf;
   1575             boolean inc;
   1576             float num;
   1577 
   1578             FormatTask(DecimalFormat fmt, int index) {
   1579                 this.fmt = fmt;
   1580                 this.buf = new StringBuffer();
   1581                 this.inc = (index & 0x1) == 0;
   1582                 this.num = inc ? 0 : 10000;
   1583             }
   1584 
   1585             public void run() {
   1586                 if (inc) {
   1587                     while (num < 10000) {
   1588                         buf.append(fmt.format(num) + "\n");
   1589                         num += 3.14159;
   1590                     }
   1591                 } else {
   1592                     while (num > 0) {
   1593                         buf.append(fmt.format(num) + "\n");
   1594                         num -= 3.14159;
   1595                     }
   1596                 }
   1597             }
   1598 
   1599             String result() {
   1600                 return buf.toString();
   1601             }
   1602         }
   1603 
   1604         DecimalFormat fmt = new DecimalFormat("0.####");
   1605         FormatTask[] tasks = new FormatTask[8];
   1606         for (int i = 0; i < tasks.length; ++i) {
   1607             tasks[i] = new FormatTask(fmt, i);
   1608         }
   1609 
   1610         TestUtil.runUntilDone(tasks);
   1611 
   1612         for (int i = 2; i < tasks.length; i++) {
   1613             String str1 = tasks[i].result();
   1614             String str2 = tasks[i-2].result();
   1615             if (!str1.equals(str2)) {
   1616                 System.out.println("mismatch at " + i);
   1617                 System.out.println(str1);
   1618                 System.out.println(str2);
   1619                 errln("decimal format thread mismatch");
   1620 
   1621                 break;
   1622             }
   1623             str1 = str2;
   1624         }
   1625     }
   1626 
   1627     public void TestPerMill() {
   1628         DecimalFormat fmt = new DecimalFormat("###.###\u2030");
   1629         assertEquals("0.4857 x ###.###\u2030",
   1630                 "485.7\u2030", fmt.format(0.4857));
   1631 
   1632         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.ENGLISH);
   1633         sym.setPerMill('m');
   1634         DecimalFormat fmt2 = new DecimalFormat("", sym);
   1635         fmt2.applyLocalizedPattern("###.###m");
   1636         assertEquals("0.4857 x ###.###m",
   1637                 "485.7m", fmt2.format(0.4857));
   1638     }
   1639 
   1640     public void TestIllegalPatterns() {
   1641         // Test cases:
   1642         // Prefix with "-:" for illegal patterns
   1643         // Prefix with "+:" for legal patterns
   1644         String DATA[] = {
   1645                 // Unquoted special characters in the suffix are illegal
   1646                 "-:000.000|###",
   1647                 "+:000.000'|###'",
   1648         };
   1649         for (int i=0; i<DATA.length; ++i) {
   1650             String pat=DATA[i];
   1651             boolean valid = pat.charAt(0) == '+';
   1652             pat = pat.substring(2);
   1653             Exception e = null;
   1654             try {
   1655                 // locale doesn't matter here
   1656                 new DecimalFormat(pat);
   1657             } catch (IllegalArgumentException e1) {
   1658                 e = e1;
   1659             } catch (IndexOutOfBoundsException e1) {
   1660                 e = e1;
   1661             }
   1662             String msg = (e==null) ? "success" : e.getMessage();
   1663             if ((e==null) == valid) {
   1664                 logln("Ok: pattern \"" + pat + "\": " + msg);
   1665             } else {
   1666                 errln("FAIL: pattern \"" + pat + "\" should have " +
   1667                         (valid?"succeeded":"failed") + "; got " + msg);
   1668             }
   1669         }
   1670     }
   1671 
   1672     /**
   1673      * Parse a CurrencyAmount using the given NumberFormat, with
   1674      * the 'delim' character separating the number and the currency.
   1675      */
   1676     private static CurrencyAmount parseCurrencyAmount(String str, NumberFormat fmt,
   1677             char delim)
   1678                     throws ParseException {
   1679         int i = str.indexOf(delim);
   1680         return new CurrencyAmount(fmt.parse(str.substring(0,i)),
   1681                 Currency.getInstance(str.substring(i+1)));
   1682     }
   1683 
   1684     /**
   1685      * Return an integer representing the next token from this
   1686      * iterator.  The integer will be an index into the given list, or
   1687      * -1 if there are no more tokens, or -2 if the token is not on
   1688      * the list.
   1689      */
   1690     private static int keywordIndex(String tok) {
   1691         for (int i=0; i<KEYWORDS.length; ++i) {
   1692             if (tok.equals(KEYWORDS[i])) {
   1693                 return i;
   1694             }
   1695         }
   1696         return -1;
   1697     }
   1698 
   1699     private static final String KEYWORDS[] = {
   1700         /*0*/ "ref=", // <reference pattern to parse numbers>
   1701         /*1*/ "loc=", // <locale for formats>
   1702         /*2*/ "f:",   // <pattern or '-'> <number> <exp. string>
   1703         /*3*/ "fp:",  // <pattern or '-'> <number> <exp. string> <exp. number>
   1704         /*4*/ "rt:",  // <pattern or '-'> <(exp.) number> <(exp.) string>
   1705         /*5*/ "p:",   // <pattern or '-'> <string> <exp. number>
   1706         /*6*/ "perr:", // <pattern or '-'> <invalid string>
   1707         /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
   1708         /*8*/ "fpc:", // <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
   1709         /*9*/ "strict=", // true or false
   1710     };
   1711 
   1712     @SuppressWarnings("resource")  // InputStream is will be closed by the ResourceReader.
   1713     public void TestCases() {
   1714         String caseFileName = "NumberFormatTestCases.txt";
   1715         java.io.InputStream is = NumberFormatTest.class.getResourceAsStream(caseFileName);
   1716 
   1717         ResourceReader reader = new ResourceReader(is, caseFileName, "utf-8");
   1718         TokenIterator tokens = new TokenIterator(reader);
   1719 
   1720         Locale loc = new Locale("en", "US", "");
   1721         DecimalFormat ref = null, fmt = null;
   1722         MeasureFormat mfmt = null;
   1723         String pat = null, str = null, mloc = null;
   1724         boolean strict = false;
   1725 
   1726         try {
   1727             for (;;) {
   1728                 String tok = tokens.next();
   1729                 if (tok == null) {
   1730                     break;
   1731                 }
   1732                 String where = "(" + tokens.getLineNumber() + ") ";
   1733                 int cmd = keywordIndex(tok);
   1734                 switch (cmd) {
   1735                 case 0:
   1736                     // ref= <reference pattern>
   1737                     ref = new DecimalFormat(tokens.next(),
   1738                             new DecimalFormatSymbols(Locale.US));
   1739                     ref.setParseStrict(strict);
   1740                     logln("Setting reference pattern to:\t" + ref);
   1741                     break;
   1742                 case 1:
   1743                     // loc= <locale>
   1744                     loc = LocaleUtility.getLocaleFromName(tokens.next());
   1745                     pat = ((DecimalFormat) NumberFormat.getInstance(loc)).toPattern();
   1746                     logln("Setting locale to:\t" + loc + ", \tand pattern to:\t" + pat);
   1747                     break;
   1748                 case 2: // f:
   1749                 case 3: // fp:
   1750                 case 4: // rt:
   1751                 case 5: // p:
   1752                     tok = tokens.next();
   1753                     if (!tok.equals("-")) {
   1754                         pat = tok;
   1755                     }
   1756                     try {
   1757                         fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc));
   1758                         fmt.setParseStrict(strict);
   1759                     } catch (IllegalArgumentException iae) {
   1760                         errln(where + "Pattern \"" + pat + '"');
   1761                         iae.printStackTrace();
   1762                         tokens.next(); // consume remaining tokens
   1763                         //tokens.next();
   1764                         if (cmd == 3) tokens.next();
   1765                         continue;
   1766                     }
   1767                     str = null;
   1768                     try {
   1769                         if (cmd == 2 || cmd == 3 || cmd == 4) {
   1770                             // f: <pattern or '-'> <number> <exp. string>
   1771                             // fp: <pattern or '-'> <number> <exp. string> <exp. number>
   1772                             // rt: <pattern or '-'> <number> <string>
   1773                             String num = tokens.next();
   1774                             str = tokens.next();
   1775                             Number n = ref.parse(num);
   1776                             assertEquals(where + '"' + pat + "\".format(" + num + ")",
   1777                                     str, fmt.format(n));
   1778                             if (cmd == 3) { // fp:
   1779                                 n = ref.parse(tokens.next());
   1780                             }
   1781                             if (cmd != 2) { // != f:
   1782                                 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
   1783                                         n, fmt.parse(str));
   1784                             }
   1785                         }
   1786                         // p: <pattern or '-'> <string to parse> <exp. number>
   1787                         else {
   1788                             str = tokens.next();
   1789                             String expstr = tokens.next();
   1790                             Number parsed = fmt.parse(str);
   1791                             Number exp = ref.parse(expstr);
   1792                             assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
   1793                                     exp, parsed);
   1794                         }
   1795                     } catch (ParseException e) {
   1796                         errln(where + '"' + pat + "\".parse(\"" + str +
   1797                                 "\") threw an exception");
   1798                         e.printStackTrace();
   1799                     }
   1800                     break;
   1801                 case 6:
   1802                     // perr: <pattern or '-'> <invalid string>
   1803                     errln("Under construction");
   1804                     return;
   1805                 case 7:
   1806                     // pat: <pattern> <exp. toPattern, or '-' or 'err'>
   1807                     String testpat = tokens.next();
   1808                     String exppat  = tokens.next();
   1809                     boolean err    = exppat.equals("err");
   1810                     if (testpat.equals("-")) {
   1811                         if (err) {
   1812                             errln("Invalid command \"pat: - err\" at " +  tokens.describePosition());
   1813                             continue;
   1814                         }
   1815                         testpat = pat;
   1816                     }
   1817                     if (exppat.equals("-")) exppat = testpat;
   1818                     try {
   1819                         DecimalFormat f = null;
   1820                         if (testpat == pat) { // [sic]
   1821                             f = fmt;
   1822                         } else {
   1823                             f = new DecimalFormat(testpat);
   1824                             f.setParseStrict(strict);
   1825                         }
   1826                         if (err) {
   1827                             errln(where + "Invalid pattern \"" + testpat +
   1828                                     "\" was accepted");
   1829                         } else {
   1830                             assertEquals(where + '"' + testpat + "\".toPattern()",
   1831                                     exppat, f.toPattern());
   1832                         }
   1833                     } catch (IllegalArgumentException iae2) {
   1834                         if (err) {
   1835                             logln("Ok: " + where + "Invalid pattern \"" + testpat +
   1836                                     "\" threw an exception");
   1837                         } else {
   1838                             errln(where + "Valid pattern \"" + testpat +
   1839                                     "\" threw an exception");
   1840                             iae2.printStackTrace();
   1841                         }
   1842                     }
   1843                     break;
   1844                 case 8: // fpc:
   1845                     tok = tokens.next();
   1846                     if (!tok.equals("-")) {
   1847                         mloc = tok;
   1848                         ULocale l = new ULocale(mloc);
   1849                         try {
   1850                             mfmt = MeasureFormat.getCurrencyFormat(l);
   1851                         } catch (IllegalArgumentException iae) {
   1852                             errln(where + "Loc \"" + tok + '"');
   1853                             iae.printStackTrace();
   1854                             tokens.next(); // consume remaining tokens
   1855                             tokens.next();
   1856                             tokens.next();
   1857                             continue;
   1858                         }
   1859                     }
   1860                     str = null;
   1861                     try {
   1862                         // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
   1863                         String currAmt = tokens.next();
   1864                         str = tokens.next();
   1865                         CurrencyAmount target = parseCurrencyAmount(currAmt, ref, '/');
   1866                         String formatResult = mfmt.format(target);
   1867                         assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
   1868                                 str, formatResult);
   1869                         target = parseCurrencyAmount(tokens.next(), ref, '/');
   1870                         CurrencyAmount parseResult = (CurrencyAmount) mfmt.parseObject(str);
   1871                         assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
   1872                                 target, parseResult);
   1873                     } catch (ParseException e) {
   1874                         errln(where + '"' + pat + "\".parse(\"" + str +
   1875                                 "\") threw an exception");
   1876                         e.printStackTrace();
   1877                     }
   1878                     break;
   1879                 case 9: // strict= true or false
   1880                     strict = "true".equalsIgnoreCase(tokens.next());
   1881                     logln("Setting strict to:\t" + strict);
   1882                     break;
   1883                 case -1:
   1884                     errln("Unknown command \"" + tok + "\" at " + tokens.describePosition());
   1885                     return;
   1886                 }
   1887             }
   1888         } catch (java.io.IOException e) {
   1889             throw new RuntimeException(e);
   1890         } finally {
   1891             try {
   1892                 reader.close();
   1893             } catch (IOException ignored) {
   1894             }
   1895         }
   1896     }
   1897 
   1898     public void TestFieldPositionDecimal() {
   1899         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
   1900         nf.setPositivePrefix("FOO");
   1901         nf.setPositiveSuffix("BA");
   1902         StringBuffer buffer = new StringBuffer();
   1903         FieldPosition fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
   1904         nf.format(35.47, buffer, fp);
   1905         assertEquals("35.47", "FOO35.47BA", buffer.toString());
   1906         assertEquals("fp begin", 5, fp.getBeginIndex());
   1907         assertEquals("fp end", 6, fp.getEndIndex());
   1908     }
   1909 
   1910     public void TestFieldPositionInteger() {
   1911         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
   1912         nf.setPositivePrefix("FOO");
   1913         nf.setPositiveSuffix("BA");
   1914         StringBuffer buffer = new StringBuffer();
   1915         FieldPosition fp = new FieldPosition(NumberFormat.Field.INTEGER);
   1916         nf.format(35.47, buffer, fp);
   1917         assertEquals("35.47", "FOO35.47BA", buffer.toString());
   1918         assertEquals("fp begin", 3, fp.getBeginIndex());
   1919         assertEquals("fp end", 5, fp.getEndIndex());
   1920     }
   1921 
   1922     public void TestFieldPositionFractionButInteger() {
   1923         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
   1924         nf.setPositivePrefix("FOO");
   1925         nf.setPositiveSuffix("BA");
   1926         StringBuffer buffer = new StringBuffer();
   1927         FieldPosition fp = new FieldPosition(NumberFormat.Field.FRACTION);
   1928         nf.format(35, buffer, fp);
   1929         assertEquals("35", "FOO35BA", buffer.toString());
   1930         assertEquals("fp begin", 5, fp.getBeginIndex());
   1931         assertEquals("fp end", 5, fp.getEndIndex());
   1932     }
   1933 
   1934     public void TestFieldPositionFraction() {
   1935         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
   1936         nf.setPositivePrefix("FOO");
   1937         nf.setPositiveSuffix("BA");
   1938         StringBuffer buffer = new StringBuffer();
   1939         FieldPosition fp = new FieldPosition(NumberFormat.Field.FRACTION);
   1940         nf.format(35.47, buffer, fp);
   1941         assertEquals("35.47", "FOO35.47BA", buffer.toString());
   1942         assertEquals("fp begin", 6, fp.getBeginIndex());
   1943         assertEquals("fp end", 8, fp.getEndIndex());
   1944     }
   1945 
   1946     public void TestRounding() {
   1947         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
   1948         if (false) { // for debugging specific value
   1949             nf.setRoundingMode(BigDecimal.ROUND_HALF_UP);
   1950             checkRounding(nf, new BigDecimal("300.0300000000"), 0, new BigDecimal("0.020000000"));
   1951         }
   1952         // full tests
   1953         int[] roundingIncrements = {1, 2, 5, 20, 50, 100};
   1954         int[] testValues = {0, 300};
   1955         for (int j = 0; j < testValues.length; ++j) {
   1956             for (int mode = BigDecimal.ROUND_UP; mode < BigDecimal.ROUND_HALF_EVEN; ++mode) {
   1957                 nf.setRoundingMode(mode);
   1958                 for (int increment = 0; increment < roundingIncrements.length; ++increment) {
   1959                     BigDecimal base = new BigDecimal(testValues[j]);
   1960                     BigDecimal rInc = new BigDecimal(roundingIncrements[increment]);
   1961                     checkRounding(nf,  base, 20, rInc);
   1962                     rInc = new BigDecimal("1.000000000").divide(rInc);
   1963                     checkRounding(nf,  base, 20, rInc);
   1964                 }
   1965             }
   1966         }
   1967     }
   1968 
   1969     public void TestRoundingPattern() {
   1970         class TestRoundingPatternItem {
   1971             String     pattern;
   1972             double     roundingIncrement;
   1973             double     testCase;
   1974             String     expected;
   1975 
   1976             TestRoundingPatternItem(String pattern, double roundingIncrement, double testCase, String expected) {
   1977                 this.pattern = pattern;
   1978                 this.roundingIncrement = roundingIncrement;
   1979                 this.testCase = testCase;
   1980                 this.expected = expected;
   1981             }
   1982         };
   1983 
   1984         TestRoundingPatternItem []tests = {
   1985                 new TestRoundingPatternItem("##0.65", 0.65, 1.234, "1.30"),
   1986                 new TestRoundingPatternItem("#50", 50.0, 1230, "1250")
   1987         };
   1988 
   1989         DecimalFormat df = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
   1990         String result;
   1991         BigDecimal bd;
   1992         for (int i = 0; i < tests.length; i++) {
   1993             df.applyPattern(tests[i].pattern);
   1994 
   1995             result = df.format(tests[i].testCase);
   1996 
   1997             if (!tests[i].expected.equals(result)) {
   1998                 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
   1999             }
   2000 
   2001             bd = new BigDecimal(tests[i].roundingIncrement);
   2002 
   2003             df.setRoundingIncrement(bd);
   2004 
   2005             result = df.format(tests[i].testCase);
   2006 
   2007             if (!tests[i].expected.equals(result)) {
   2008                 errln("BigDecimal Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
   2009             }
   2010         }
   2011     }
   2012 
   2013     public void TestBigDecimalRounding() {
   2014         String figure = "50.000000004";
   2015         Double dbl = new Double(figure);
   2016         BigDecimal dec = new BigDecimal(figure);
   2017 
   2018         DecimalFormat f = (DecimalFormat) NumberFormat.getInstance();
   2019         f.applyPattern("00.00######");
   2020 
   2021         assertEquals("double format", "50.00", f.format(dbl));
   2022         assertEquals("bigdec format", "50.00", f.format(dec));
   2023 
   2024         int maxFracDigits = f.getMaximumFractionDigits();
   2025         BigDecimal roundingIncrement = new BigDecimal("1").movePointLeft(maxFracDigits);
   2026 
   2027         f.setRoundingIncrement(roundingIncrement);
   2028         f.setRoundingMode(BigDecimal.ROUND_DOWN);
   2029         assertEquals("Rounding down", f.format(dbl), f.format(dec));
   2030 
   2031         f.setRoundingIncrement(roundingIncrement);
   2032         f.setRoundingMode(BigDecimal.ROUND_HALF_UP);
   2033         assertEquals("Rounding half up", f.format(dbl), f.format(dec));
   2034     }
   2035 
   2036     void checkRounding(DecimalFormat nf, BigDecimal base, int iterations, BigDecimal increment) {
   2037         nf.setRoundingIncrement(increment.toBigDecimal());
   2038         BigDecimal lastParsed = new BigDecimal(Integer.MIN_VALUE); // used to make sure that rounding is monotonic
   2039         for (int i = -iterations; i <= iterations; ++i) {
   2040             BigDecimal iValue = base.add(increment.multiply(new BigDecimal(i)).movePointLeft(1));
   2041             BigDecimal smallIncrement = new BigDecimal("0.00000001");
   2042             if (iValue.signum() != 0) {
   2043                 smallIncrement.multiply(iValue); // scale unless zero
   2044             }
   2045             // we not only test the value, but some values in a small range around it.
   2046             lastParsed = checkRound(nf, iValue.subtract(smallIncrement), lastParsed);
   2047             lastParsed = checkRound(nf, iValue, lastParsed);
   2048             lastParsed = checkRound(nf, iValue.add(smallIncrement), lastParsed);
   2049         }
   2050     }
   2051 
   2052     private BigDecimal checkRound(DecimalFormat nf, BigDecimal iValue, BigDecimal lastParsed) {
   2053         String formatedBigDecimal = nf.format(iValue);
   2054         String formattedDouble = nf.format(iValue.doubleValue());
   2055         if (!equalButForTrailingZeros(formatedBigDecimal, formattedDouble)) {
   2056 
   2057             errln("Failure at: " + iValue + " (" + iValue.doubleValue() + ")"
   2058                     + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
   2059                             + ",\tRounding-increment: " + nf.getRoundingIncrement()
   2060                             + ",\tdouble: " + formattedDouble
   2061                             + ",\tBigDecimal: " + formatedBigDecimal);
   2062 
   2063         } else {
   2064             logln("Value: " + iValue
   2065                     + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
   2066                             + ",\tRounding-increment: " + nf.getRoundingIncrement()
   2067                             + ",\tdouble: " + formattedDouble
   2068                             + ",\tBigDecimal: " + formatedBigDecimal);
   2069         }
   2070         try {
   2071             // Number should have compareTo(...)
   2072             BigDecimal parsed = toBigDecimal(nf.parse(formatedBigDecimal));
   2073             if (lastParsed.compareTo(parsed) > 0) {
   2074                 errln("Rounding wrong direction!: " + lastParsed + " > " + parsed);
   2075             }
   2076             lastParsed = parsed;
   2077         } catch (ParseException e) {
   2078             errln("Parse Failure with: " + formatedBigDecimal);
   2079         }
   2080         return lastParsed;
   2081     }
   2082 
   2083     static BigDecimal toBigDecimal(Number number) {
   2084         return number instanceof BigDecimal ? (BigDecimal) number
   2085                 : number instanceof BigInteger ? new BigDecimal((BigInteger)number)
   2086         : number instanceof java.math.BigDecimal ? new BigDecimal((java.math.BigDecimal)number)
   2087                 : number instanceof Double ? new BigDecimal(number.doubleValue())
   2088         : number instanceof Float ? new BigDecimal(number.floatValue())
   2089                 : new BigDecimal(number.longValue());
   2090     }
   2091 
   2092     static String[] roundingModeNames = {
   2093         "ROUND_UP", "ROUND_DOWN", "ROUND_CEILING", "ROUND_FLOOR",
   2094         "ROUND_HALF_UP", "ROUND_HALF_DOWN", "ROUND_HALF_EVEN",
   2095         "ROUND_UNNECESSARY"
   2096     };
   2097 
   2098     private static boolean equalButForTrailingZeros(String formatted1, String formatted2) {
   2099         if (formatted1.length() == formatted2.length()) return formatted1.equals(formatted2);
   2100         return stripFinalZeros(formatted1).equals(stripFinalZeros(formatted2));
   2101     }
   2102 
   2103     private static String stripFinalZeros(String formatted) {
   2104         int len1 = formatted.length();
   2105         char ch;
   2106         while (len1 > 0 && ((ch = formatted.charAt(len1-1)) == '0' || ch == '.')) --len1;
   2107         if (len1==1 && ((ch = formatted.charAt(len1-1)) == '-')) --len1;
   2108         return formatted.substring(0,len1);
   2109     }
   2110 
   2111     //------------------------------------------------------------------
   2112     // Support methods
   2113     //------------------------------------------------------------------
   2114 
   2115     // Format-Parse test
   2116     public void expect2(NumberFormat fmt, Number n, String exp) {
   2117         // Don't round-trip format test, since we explicitly do it
   2118         expect(fmt, n, exp, false);
   2119         expect(fmt, exp, n);
   2120     }
   2121     // Format-Parse test
   2122     public void expect3(NumberFormat fmt, Number n, String exp) {
   2123         // Don't round-trip format test, since we explicitly do it
   2124         expect_rbnf(fmt, n, exp, false);
   2125         expect_rbnf(fmt, exp, n);
   2126     }
   2127 
   2128     // Format-Parse test (convenience)
   2129     public void expect2(NumberFormat fmt, double n, String exp) {
   2130         expect2(fmt, new Double(n), exp);
   2131     }
   2132     // Format-Parse test (convenience)
   2133     public void expect3(NumberFormat fmt, double n, String exp) {
   2134         expect3(fmt, new Double(n), exp);
   2135     }
   2136 
   2137     // Format-Parse test (convenience)
   2138     public void expect2(NumberFormat fmt, long n, String exp) {
   2139         expect2(fmt, new Long(n), exp);
   2140     }
   2141     // Format-Parse test (convenience)
   2142     public void expect3(NumberFormat fmt, long n, String exp) {
   2143         expect3(fmt, new Long(n), exp);
   2144     }
   2145 
   2146     // Format test
   2147     public void expect(NumberFormat fmt, Number n, String exp, boolean rt) {
   2148         StringBuffer saw = new StringBuffer();
   2149         FieldPosition pos = new FieldPosition(0);
   2150         fmt.format(n, saw, pos);
   2151         String pat = ((DecimalFormat)fmt).toPattern();
   2152         if (saw.toString().equals(exp)) {
   2153             logln("Ok   " + n + " x " +
   2154                     pat + " = \"" +
   2155                     saw + "\"");
   2156             // We should be able to round-trip the formatted string =>
   2157             // number => string (but not the other way around: number
   2158             // => string => number2, might have number2 != number):
   2159             if (rt) {
   2160                 try {
   2161                     Number n2 = fmt.parse(exp);
   2162                     StringBuffer saw2 = new StringBuffer();
   2163                     fmt.format(n2, saw2, pos);
   2164                     if (!saw2.toString().equals(exp)) {
   2165                         errln("expect() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2166                                 ", FAIL \"" + exp + "\" => " + n2 + " => \"" + saw2 + '"');
   2167                     }
   2168                 } catch (ParseException e) {
   2169                     errln("expect() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2170                             ", " + e.getMessage());
   2171                     return;
   2172                 }
   2173             }
   2174         } else {
   2175             errln("expect() format test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2176                     ", FAIL " + n + " x " + pat + " = \"" + saw + "\", expected \"" + exp + "\"");
   2177         }
   2178     }
   2179     // Format test
   2180     public void expect_rbnf(NumberFormat fmt, Number n, String exp, boolean rt) {
   2181         StringBuffer saw = new StringBuffer();
   2182         FieldPosition pos = new FieldPosition(0);
   2183         fmt.format(n, saw, pos);
   2184         if (saw.toString().equals(exp)) {
   2185             logln("Ok   " + n + " = \"" +
   2186                     saw + "\"");
   2187             // We should be able to round-trip the formatted string =>
   2188             // number => string (but not the other way around: number
   2189             // => string => number2, might have number2 != number):
   2190             if (rt) {
   2191                 try {
   2192                     Number n2 = fmt.parse(exp);
   2193                     StringBuffer saw2 = new StringBuffer();
   2194                     fmt.format(n2, saw2, pos);
   2195                     if (!saw2.toString().equals(exp)) {
   2196                         errln("expect_rbnf() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2197                                 ", FAIL \"" + exp + "\" => " + n2 + " => \"" + saw2 + '"');
   2198                     }
   2199                 } catch (ParseException e) {
   2200                     errln("expect_rbnf() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2201                             ", " + e.getMessage());
   2202                     return;
   2203                 }
   2204             }
   2205         } else {
   2206             errln("expect_rbnf() format test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2207                     ", FAIL " + n + " = \"" + saw + "\", expected \"" + exp + "\"");
   2208         }
   2209     }
   2210 
   2211     // Format test (convenience)
   2212     public void expect(NumberFormat fmt, Number n, String exp) {
   2213         expect(fmt, n, exp, true);
   2214     }
   2215 
   2216     // Format test (convenience)
   2217     public void expect(NumberFormat fmt, double n, String exp) {
   2218         expect(fmt, new Double(n), exp);
   2219     }
   2220 
   2221     // Format test (convenience)
   2222     public void expect(NumberFormat fmt, long n, String exp) {
   2223         expect(fmt, new Long(n), exp);
   2224     }
   2225 
   2226     // Parse test
   2227     public void expect(NumberFormat fmt, String str, Number n) {
   2228         Number num = null;
   2229         try {
   2230             num = fmt.parse(str);
   2231         } catch (ParseException e) {
   2232             errln(e.getMessage());
   2233             return;
   2234         }
   2235         String pat = ((DecimalFormat)fmt).toPattern();
   2236         // A little tricky here -- make sure Double(12345.0) and
   2237         // Long(12345) match.
   2238         if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
   2239             logln("Ok   \"" + str + "\" x " +
   2240                     pat + " = " +
   2241                     num);
   2242         } else {
   2243             errln("expect() parse test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2244                     ", FAIL \"" + str + "\" x " + pat + " = " + num + ", expected " + n);
   2245         }
   2246     }
   2247 
   2248     // Parse test
   2249     public void expect_rbnf(NumberFormat fmt, String str, Number n) {
   2250         Number num = null;
   2251         try {
   2252             num = fmt.parse(str);
   2253         } catch (ParseException e) {
   2254             errln(e.getMessage());
   2255             return;
   2256         }
   2257         // A little tricky here -- make sure Double(12345.0) and
   2258         // Long(12345) match.
   2259         if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
   2260             logln("Ok   \"" + str + " = " +
   2261                     num);
   2262         } else {
   2263             errln("expect_rbnf() parse test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) +
   2264                     ", FAIL \"" + str + " = " + num + ", expected " + n);
   2265         }
   2266     }
   2267 
   2268     // Parse test (convenience)
   2269     public void expect(NumberFormat fmt, String str, double n) {
   2270         expect(fmt, str, new Double(n));
   2271     }
   2272 
   2273     // Parse test (convenience)
   2274     public void expect(NumberFormat fmt, String str, long n) {
   2275         expect(fmt, str, new Long(n));
   2276     }
   2277 
   2278     private void expectCurrency(NumberFormat nf, Currency curr,
   2279             double value, String string) {
   2280         DecimalFormat fmt = (DecimalFormat) nf;
   2281         if (curr != null) {
   2282             fmt.setCurrency(curr);
   2283         }
   2284         String s = fmt.format(value).replace('\u00A0', ' ');
   2285 
   2286         if (s.equals(string)) {
   2287             logln("Ok: " + value + " x " + curr + " => " + s);
   2288         } else {
   2289             errln("FAIL: " + value + " x " + curr + " => " + s +
   2290                     ", expected " + string);
   2291         }
   2292     }
   2293 
   2294     public void expectPad(DecimalFormat fmt, String pat, int pos) {
   2295         expectPad(fmt, pat, pos, 0, (char)0);
   2296     }
   2297 
   2298     public void expectPad(DecimalFormat fmt, final String pat, int pos, int width, final char pad) {
   2299         int apos = 0, awidth = 0;
   2300         char apadStr;
   2301         try {
   2302             fmt.applyPattern(pat);
   2303             apos = fmt.getPadPosition();
   2304             awidth = fmt.getFormatWidth();
   2305             apadStr = fmt.getPadCharacter();
   2306         } catch (Exception e) {
   2307             apos = -1;
   2308             awidth = width;
   2309             apadStr = pad;
   2310         }
   2311 
   2312         if (apos == pos && awidth == width && apadStr == pad) {
   2313             logln("Ok   \"" + pat + "\" pos="
   2314                     + apos + ((pos == -1) ? "" : " width=" + awidth + " pad=" + apadStr));
   2315         } else {
   2316             errln("FAIL \"" + pat + "\" pos=" + apos + " width="
   2317                     + awidth + " pad=" + apadStr + ", expected "
   2318                     + pos + " " + width + " " + pad);
   2319         }
   2320     }
   2321 
   2322     public void expectPat(DecimalFormat fmt, final String exp) {
   2323         String pat = fmt.toPattern();
   2324         if (pat.equals(exp)) {
   2325             logln("Ok   \"" + pat + "\"");
   2326         } else {
   2327             errln("FAIL \"" + pat + "\", expected \"" + exp + "\"");
   2328         }
   2329     }
   2330 
   2331 
   2332     private void expectParseCurrency(NumberFormat fmt, Currency expected, String text) {
   2333         ParsePosition pos = new ParsePosition(0);
   2334         CurrencyAmount currencyAmount = fmt.parseCurrency(text, pos);
   2335         assertTrue("Parse of " + text + " should have succeeded.", pos.getIndex() > 0);
   2336         assertEquals("Currency should be correct.", expected, currencyAmount.getCurrency());
   2337     }
   2338 
   2339     public void TestJB3832(){
   2340         ULocale locale = new ULocale("pt_PT@currency=PTE");
   2341         NumberFormat format = NumberFormat.getCurrencyInstance(locale);
   2342         Currency curr = Currency.getInstance(locale);
   2343         logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
   2344         CurrencyAmount cAmt = new CurrencyAmount(1150.50, curr);
   2345         logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
   2346         String str = format.format(cAmt);
   2347         String expected = "1,150$50\u00a0\u200b";
   2348         if(!expected.equals(str)){
   2349             errln("Did not get the expected output Expected: "+expected+" Got: "+ str);
   2350         }
   2351     }
   2352 
   2353     public void TestStrictParse() {
   2354         String[] pass = {
   2355                 "0",           // single zero before end of text is not leading
   2356                 "0 ",          // single zero at end of number is not leading
   2357                 "0.",          // single zero before period (or decimal, it's ambiguous) is not leading
   2358                 "0,",          // single zero before comma (not group separator) is not leading
   2359                 "0.0",         // single zero before decimal followed by digit is not leading
   2360                 "0. ",         // same as above before period (or decimal) is not leading
   2361                 "0.100,5",     // comma stops parse of decimal (no grouping)
   2362                 ".00",         // leading decimal is ok, even with zeros
   2363                 "1234567",     // group separators are not required
   2364                 "12345, ",     // comma not followed by digit is not a group separator, but end of number
   2365                 "1,234, ",     // if group separator is present, group sizes must be appropriate
   2366                 "1,234,567",   // ...secondary too
   2367                 "0E",          // an exponent not followed by zero or digits is not an exponent
   2368                 "00",          // leading zero before zero - used to be error - see ticket #7913
   2369                 "012",         // leading zero before digit - used to be error - see ticket #7913
   2370                 "0,456",       // leading zero before group separator - used to be error - see ticket #7913
   2371         };
   2372         String[] fail = {
   2373                 "1,2",       // wrong number of digits after group separator
   2374                 ",0",        // leading group separator before zero
   2375                 ",1",        // leading group separator before digit
   2376                 ",.02",      // leading group separator before decimal
   2377                 "1,.02",     // group separator before decimal
   2378                 "1,,200",    // multiple group separators
   2379                 "1,45",      // wrong number of digits in primary group
   2380                 "1,45 that", // wrong number of digits in primary group
   2381                 "1,45.34",   // wrong number of digits in primary group
   2382                 "1234,567",  // wrong number of digits in secondary group
   2383                 "12,34,567", // wrong number of digits in secondary group
   2384                 "1,23,456,7890", // wrong number of digits in primary and secondary groups
   2385         };
   2386 
   2387         DecimalFormat nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
   2388         runStrictParseBatch(nf, pass, fail);
   2389 
   2390         String[] scientificPass = {
   2391                 "0E2",      // single zero before exponent is ok
   2392                 "1234E2",   // any number of digits before exponent is ok
   2393                 "1,234E",   // an exponent string not followed by zero or digits is not an exponent
   2394                 "00E2",     // leading zeroes now allowed in strict mode - see ticket #
   2395         };
   2396         String[] scientificFail = {
   2397                 "1,234E2",  // group separators with exponent fail
   2398         };
   2399 
   2400         nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
   2401         runStrictParseBatch(nf, scientificPass, scientificFail);
   2402 
   2403         String[] mixedPass = {
   2404                 "12,34,567",
   2405                 "12,34,567,",
   2406                 "12,34,567, that",
   2407                 "12,34,567 that",
   2408         };
   2409         String[] mixedFail = {
   2410                 "12,34,56",
   2411                 "12,34,56,",
   2412                 "12,34,56, that ",
   2413                 "12,34,56 that",
   2414         };
   2415 
   2416         nf = new DecimalFormat("#,##,##0.#");
   2417         runStrictParseBatch(nf, mixedPass, mixedFail);
   2418     }
   2419 
   2420     void runStrictParseBatch(DecimalFormat nf, String[] pass, String[] fail) {
   2421         nf.setParseStrict(false);
   2422         runStrictParseTests("should pass", nf, pass, true);
   2423         runStrictParseTests("should also pass", nf, fail, true);
   2424         nf.setParseStrict(true);
   2425         runStrictParseTests("should still pass", nf, pass, true);
   2426         runStrictParseTests("should fail", nf, fail, false);
   2427     }
   2428 
   2429     void runStrictParseTests(String msg, DecimalFormat nf, String[] tests, boolean pass) {
   2430         logln("");
   2431         logln("pattern: '" + nf.toPattern() + "'");
   2432         logln(msg);
   2433         for (int i = 0; i < tests.length; ++i) {
   2434             String str = tests[i];
   2435             ParsePosition pp = new ParsePosition(0);
   2436             Number n = nf.parse(str, pp);
   2437             String formatted = n != null ? nf.format(n) : "null";
   2438             String err = pp.getErrorIndex() == -1 ? "" : "(error at " + pp.getErrorIndex() + ")";
   2439             if ((err.length() == 0) != pass) {
   2440                 errln("'" + str + "' parsed '" +
   2441                         str.substring(0, pp.getIndex()) +
   2442                         "' returned " + n + " formats to '" +
   2443                         formatted + "' " + err);
   2444             } else {
   2445                 if (err.length() > 0) {
   2446                     err = "got expected " + err;
   2447                 }
   2448                 logln("'" + str + "' parsed '" +
   2449                         str.substring(0, pp.getIndex()) +
   2450                         "' returned " + n + " formats to '" +
   2451                         formatted + "' " + err);
   2452             }
   2453         }
   2454     }
   2455     public void TestJB5251(){
   2456         //save default locale
   2457         ULocale defaultLocale = ULocale.getDefault();
   2458         ULocale.setDefault(new ULocale("qr_QR"));
   2459         try {
   2460             NumberFormat.getInstance();
   2461         }
   2462         catch (Exception e) {
   2463             errln("Numberformat threw exception for non-existent locale. It should use the default.");
   2464         }
   2465         //reset default locale
   2466         ULocale.setDefault(defaultLocale);
   2467     }
   2468 
   2469     public void TestParseReturnType() {
   2470         String[] defaultNonBigDecimals = {
   2471                 "123",      // Long
   2472                 "123.0",    // Long
   2473                 "0.0",      // Long
   2474                 "12345678901234567890"      // BigInteger
   2475         };
   2476 
   2477         String[] doubles = {
   2478                 "-0.0",
   2479                 "NaN",
   2480                 "\u221E"    // Infinity
   2481         };
   2482 
   2483         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
   2484         DecimalFormat nf = new DecimalFormat("#.#", sym);
   2485 
   2486         if (nf.isParseBigDecimal()) {
   2487             errln("FAIL: isParseDecimal() must return false by default");
   2488         }
   2489 
   2490         // isParseBigDecimal() is false
   2491         for (int i = 0; i < defaultNonBigDecimals.length; i++) {
   2492             try {
   2493                 Number n = nf.parse(defaultNonBigDecimals[i]);
   2494                 if (n instanceof BigDecimal) {
   2495                     errln("FAIL: parse returns BigDecimal instance");
   2496                 }
   2497             } catch (ParseException e) {
   2498                 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
   2499             }
   2500         }
   2501         // parse results for doubls must be always Double
   2502         for (int i = 0; i < doubles.length; i++) {
   2503             try {
   2504                 Number n = nf.parse(doubles[i]);
   2505                 if (!(n instanceof Double)) {
   2506                     errln("FAIL: parse does not return Double instance");
   2507                 }
   2508             } catch (ParseException e) {
   2509                 errln("parse of '" + doubles[i] + "' threw exception: " + e);
   2510             }
   2511         }
   2512 
   2513         // force this DecimalFormat to return BigDecimal
   2514         nf.setParseBigDecimal(true);
   2515         if (!nf.isParseBigDecimal()) {
   2516             errln("FAIL: isParseBigDecimal() must return true");
   2517         }
   2518 
   2519         // isParseBigDecimal() is true
   2520         for (int i = 0; i < defaultNonBigDecimals.length; i++) {
   2521             try {
   2522                 Number n = nf.parse(defaultNonBigDecimals[i]);
   2523                 if (!(n instanceof BigDecimal)) {
   2524                     errln("FAIL: parse does not return BigDecimal instance");
   2525                 }
   2526             } catch (ParseException e) {
   2527                 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
   2528             }
   2529         }
   2530         // parse results for doubls must be always Double
   2531         for (int i = 0; i < doubles.length; i++) {
   2532             try {
   2533                 Number n = nf.parse(doubles[i]);
   2534                 if (!(n instanceof Double)) {
   2535                     errln("FAIL: parse does not return Double instance");
   2536                 }
   2537             } catch (ParseException e) {
   2538                 errln("parse of '" + doubles[i] + "' threw exception: " + e);
   2539             }
   2540         }
   2541     }
   2542 
   2543     public void TestNonpositiveMultiplier() {
   2544         DecimalFormat df = new DecimalFormat("0");
   2545 
   2546         // test zero multiplier
   2547 
   2548         try {
   2549             df.setMultiplier(0);
   2550 
   2551             // bad
   2552             errln("DecimalFormat.setMultiplier(0) did not throw an IllegalArgumentException");
   2553         } catch (IllegalArgumentException ex) {
   2554             // good
   2555         }
   2556 
   2557         // test negative multiplier
   2558 
   2559         try {
   2560             df.setMultiplier(-1);
   2561 
   2562             if (df.getMultiplier() != -1) {
   2563                 errln("DecimalFormat.setMultiplier(-1) did not change the multiplier to -1");
   2564                 return;
   2565             }
   2566 
   2567             // good
   2568         } catch (IllegalArgumentException ex) {
   2569             // bad
   2570             errln("DecimalFormat.setMultiplier(-1) threw an IllegalArgumentException");
   2571             return;
   2572         }
   2573 
   2574         expect(df, "1122.123", -1122.123);
   2575         expect(df, "-1122.123", 1122.123);
   2576         expect(df, "1.2", -1.2);
   2577         expect(df, "-1.2", 1.2);
   2578 
   2579         expect2(df, Long.MAX_VALUE, BigInteger.valueOf(Long.MAX_VALUE).negate().toString());
   2580         expect2(df, Long.MIN_VALUE, BigInteger.valueOf(Long.MIN_VALUE).negate().toString());
   2581         expect2(df, Long.MAX_VALUE / 2, BigInteger.valueOf(Long.MAX_VALUE / 2).negate().toString());
   2582         expect2(df, Long.MIN_VALUE / 2, BigInteger.valueOf(Long.MIN_VALUE / 2).negate().toString());
   2583 
   2584         expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
   2585         expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
   2586 
   2587         expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
   2588         expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
   2589     }
   2590 
   2591     public void TestJB5358() {
   2592         int numThreads = 10;
   2593         String numstr = "12345";
   2594         double expected = 12345;
   2595         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
   2596         DecimalFormat fmt = new DecimalFormat("#.#", sym);
   2597         ArrayList errors = new ArrayList();
   2598 
   2599         ParseThreadJB5358[] threads = new ParseThreadJB5358[numThreads];
   2600         for (int i = 0; i < numThreads; i++) {
   2601             threads[i] = new ParseThreadJB5358((DecimalFormat)fmt.clone(), numstr, expected, errors);
   2602             threads[i].start();
   2603         }
   2604         for (int i = 0; i < numThreads; i++) {
   2605             try {
   2606                 threads[i].join();
   2607             } catch (InterruptedException ie) {
   2608                 ie.printStackTrace();
   2609             }
   2610         }
   2611         if (errors.size() != 0) {
   2612             StringBuffer errBuf = new StringBuffer();
   2613             for (int i = 0; i < errors.size(); i++) {
   2614                 errBuf.append((String)errors.get(i));
   2615                 errBuf.append("\n");
   2616             }
   2617             errln("FAIL: " + errBuf);
   2618         }
   2619     }
   2620 
   2621     static private class ParseThreadJB5358 extends Thread {
   2622         private final DecimalFormat decfmt;
   2623         private final String numstr;
   2624         private final double expect;
   2625         private final ArrayList errors;
   2626 
   2627         public ParseThreadJB5358(DecimalFormat decfmt, String numstr, double expect, ArrayList errors) {
   2628             this.decfmt = decfmt;
   2629             this.numstr = numstr;
   2630             this.expect = expect;
   2631             this.errors = errors;
   2632         }
   2633 
   2634         @Override
   2635         public void run() {
   2636             for (int i = 0; i < 10000; i++) {
   2637                 try {
   2638                     Number n = decfmt.parse(numstr);
   2639                     if (n.doubleValue() != expect) {
   2640                         synchronized(errors) {
   2641                             errors.add(new String("Bad parse result - expected:" + expect + " actual:" + n.doubleValue()));
   2642                         }
   2643                     }
   2644                 } catch (Throwable t) {
   2645                     synchronized(errors) {
   2646                         errors.add(new String(t.getClass().getName() + " - " + t.getMessage()));
   2647                     }
   2648                 }
   2649             }
   2650         }
   2651     }
   2652 
   2653     public void TestSetCurrency() {
   2654         DecimalFormatSymbols decf1 = DecimalFormatSymbols.getInstance(ULocale.US);
   2655         DecimalFormatSymbols decf2 = DecimalFormatSymbols.getInstance(ULocale.US);
   2656         decf2.setCurrencySymbol("UKD");
   2657         DecimalFormat format1 = new DecimalFormat("000.000", decf1);
   2658         DecimalFormat format2 = new DecimalFormat("000.000", decf2);
   2659         Currency euro = Currency.getInstance("EUR");
   2660         format1.setCurrency(euro);
   2661         format2.setCurrency(euro);
   2662         assertEquals("Reset with currency symbol", format1, format2);
   2663     }
   2664 
   2665     /*
   2666      * Testing the method public StringBuffer format(Object number, ...)
   2667      */
   2668     public void TestFormat() {
   2669         NumberFormat nf = NumberFormat.getInstance();
   2670         StringBuffer sb = new StringBuffer("dummy");
   2671         FieldPosition fp = new FieldPosition(0);
   2672 
   2673         // Tests when "if (number instanceof Long)" is true
   2674         try {
   2675             nf.format(new Long("0"), sb, fp);
   2676         } catch (Exception e) {
   2677             errln("NumberFormat.format(Object number, ...) was not suppose to "
   2678                     + "return an exception for a Long object. Error: " + e);
   2679         }
   2680 
   2681         // Tests when "else if (number instanceof BigInteger)" is true
   2682         try {
   2683             nf.format((Object)new BigInteger("0"), sb, fp);
   2684         } catch (Exception e) {
   2685             errln("NumberFormat.format(Object number, ...) was not suppose to "
   2686                     + "return an exception for a BigInteger object. Error: " + e);
   2687         }
   2688 
   2689         // Tests when "else if (number instanceof java.math.BigDecimal)" is true
   2690         try {
   2691             nf.format((Object)new java.math.BigDecimal("0"), sb, fp);
   2692         } catch (Exception e) {
   2693             errln("NumberFormat.format(Object number, ...) was not suppose to "
   2694                     + "return an exception for a java.math.BigDecimal object. Error: " + e);
   2695         }
   2696 
   2697         // Tests when "else if (number instanceof com.ibm.icu.math.BigDecimal)" is true
   2698         try {
   2699             nf.format((Object)new com.ibm.icu.math.BigDecimal("0"), sb, fp);
   2700         } catch (Exception e) {
   2701             errln("NumberFormat.format(Object number, ...) was not suppose to "
   2702                     + "return an exception for a com.ibm.icu.math.BigDecimal object. Error: " + e);
   2703         }
   2704 
   2705         // Tests when "else if (number instanceof CurrencyAmount)" is true
   2706         try {
   2707             CurrencyAmount ca = new CurrencyAmount(0.0, Currency.getInstance(new ULocale("en_US")));
   2708             nf.format((Object)ca, sb, fp);
   2709         } catch (Exception e) {
   2710             errln("NumberFormat.format(Object number, ...) was not suppose to "
   2711                     + "return an exception for a CurrencyAmount object. Error: " + e);
   2712         }
   2713 
   2714         // Tests when "else if (number instanceof Number)" is true
   2715         try {
   2716             nf.format(0.0, sb, fp);
   2717         } catch (Exception e) {
   2718             errln("NumberFormat.format(Object number, ...) was not suppose to "
   2719                     + "to return an exception for a Number object. Error: " + e);
   2720         }
   2721 
   2722         // Tests when "else" is true
   2723         try {
   2724             nf.format(new Object(), sb, fp);
   2725             errln("NumberFormat.format(Object number, ...) was suppose to "
   2726                     + "return an exception for an invalid object.");
   2727         } catch (Exception e) {
   2728         }
   2729 
   2730         try {
   2731             nf.format(new String("dummy"), sb, fp);
   2732             errln("NumberFormat.format(Object number, ...) was suppose to "
   2733                     + "return an exception for an invalid object.");
   2734         } catch (Exception e) {
   2735         }
   2736     }
   2737 
   2738     /*
   2739      * Tests the method public final static NumberFormat getInstance(int style) public static NumberFormat
   2740      * getInstance(Locale inLocale, int style) public static NumberFormat getInstance(ULocale desiredLocale, int choice)
   2741      */
   2742     public void TestGetInstance() {
   2743         // Tests "public final static NumberFormat getInstance(int style)"
   2744         int maxStyle = NumberFormat.CASHCURRENCYSTYLE;
   2745 
   2746         int[] invalid_cases = { NumberFormat.NUMBERSTYLE - 1, NumberFormat.NUMBERSTYLE - 2,
   2747                 maxStyle + 1, maxStyle + 2 };
   2748 
   2749         for (int i = NumberFormat.NUMBERSTYLE; i < maxStyle; i++) {
   2750             try {
   2751                 NumberFormat.getInstance(i);
   2752             } catch (Exception e) {
   2753                 errln("NumberFormat.getInstance(int style) was not suppose to "
   2754                         + "return an exception for passing value of " + i);
   2755             }
   2756         }
   2757 
   2758         for (int i = 0; i < invalid_cases.length; i++) {
   2759             try {
   2760                 NumberFormat.getInstance(invalid_cases[i]);
   2761                 errln("NumberFormat.getInstance(int style) was suppose to "
   2762                         + "return an exception for passing value of " + invalid_cases[i]);
   2763             } catch (Exception e) {
   2764             }
   2765         }
   2766 
   2767         // Tests "public static NumberFormat getInstance(Locale inLocale, int style)"
   2768         String[] localeCases = { "en_US", "fr_FR", "de_DE", "jp_JP" };
   2769 
   2770         for (int i = NumberFormat.NUMBERSTYLE; i < maxStyle; i++) {
   2771             for (int j = 0; j < localeCases.length; j++) {
   2772                 try {
   2773                     NumberFormat.getInstance(new Locale(localeCases[j]), i);
   2774                 } catch (Exception e) {
   2775                     errln("NumberFormat.getInstance(Locale inLocale, int style) was not suppose to "
   2776                             + "return an exception for passing value of " + localeCases[j] + ", " + i);
   2777                 }
   2778             }
   2779         }
   2780 
   2781         // Tests "public static NumberFormat getInstance(ULocale desiredLocale, int choice)"
   2782         // Tests when "if (choice < NUMBERSTYLE || choice > PLURALCURRENCYSTYLE)" is true
   2783         for (int i = 0; i < invalid_cases.length; i++) {
   2784             try {
   2785                 NumberFormat.getInstance((ULocale) null, invalid_cases[i]);
   2786                 errln("NumberFormat.getInstance(ULocale inLocale, int choice) was not suppose to "
   2787                         + "return an exception for passing value of " + invalid_cases[i]);
   2788             } catch (Exception e) {
   2789             }
   2790         }
   2791     }
   2792 
   2793     /*
   2794      * Tests the class public static abstract class NumberFormatFactory
   2795      */
   2796     public void TestNumberFormatFactory() {
   2797         /*
   2798          * The following class allows the method public NumberFormat createFormat(Locale loc, int formatType) to be
   2799          * tested.
   2800          */
   2801         class TestFactory extends NumberFormatFactory {
   2802             @Override
   2803             public Set<String> getSupportedLocaleNames() {
   2804                 return null;
   2805             }
   2806 
   2807             @Override
   2808             public NumberFormat createFormat(ULocale loc, int formatType) {
   2809                 return null;
   2810             }
   2811         }
   2812 
   2813         /*
   2814          * The following class allows the method public NumberFormat createFormat(ULocale loc, int formatType) to be
   2815          * tested.
   2816          */
   2817         class TestFactory1 extends NumberFormatFactory {
   2818             @Override
   2819             public Set<String> getSupportedLocaleNames() {
   2820                 return null;
   2821             }
   2822 
   2823             @Override
   2824             public NumberFormat createFormat(Locale loc, int formatType) {
   2825                 return null;
   2826             }
   2827         }
   2828 
   2829         TestFactory tf = new TestFactory();
   2830         TestFactory1 tf1 = new TestFactory1();
   2831 
   2832         /*
   2833          * Tests the method public boolean visible()
   2834          */
   2835         if (tf.visible() != true) {
   2836             errln("NumberFormatFactor.visible() was suppose to return true.");
   2837         }
   2838 
   2839         /*
   2840          * Tests the method public NumberFormat createFormat(Locale loc, int formatType)
   2841          */
   2842         if (tf.createFormat(new Locale(""), 0) != null) {
   2843             errln("NumberFormatFactor.createFormat(Locale loc, int formatType) " + "was suppose to return null");
   2844         }
   2845 
   2846         /*
   2847          * Tests the method public NumberFormat createFormat(ULocale loc, int formatType)
   2848          */
   2849         if (tf1.createFormat(new ULocale(""), 0) != null) {
   2850             errln("NumberFormatFactor.createFormat(ULocale loc, int formatType) " + "was suppose to return null");
   2851         }
   2852     }
   2853 
   2854     /*
   2855      * Tests the class public static abstract class SimpleNumberFormatFactory extends NumberFormatFactory
   2856      */
   2857     public void TestSimpleNumberFormatFactory() {
   2858         class TestSimpleNumberFormatFactory extends SimpleNumberFormatFactory {
   2859             /*
   2860              * Tests the method public SimpleNumberFormatFactory(Locale locale)
   2861              */
   2862             TestSimpleNumberFormatFactory() {
   2863                 super(new Locale(""));
   2864             }
   2865         }
   2866         @SuppressWarnings("unused")
   2867         TestSimpleNumberFormatFactory tsnff = new TestSimpleNumberFormatFactory();
   2868     }
   2869 
   2870     /*
   2871      * Tests the method public static ULocale[] getAvailableLocales()
   2872      */
   2873     @SuppressWarnings("static-access")
   2874     public void TestGetAvailableLocales() {
   2875         // Tests when "if (shim == null)" is true
   2876         @SuppressWarnings("serial")
   2877         class TestGetAvailableLocales extends NumberFormat {
   2878             @Override
   2879             public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
   2880                 return null;
   2881             }
   2882 
   2883             @Override
   2884             public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
   2885                 return null;
   2886             }
   2887 
   2888             @Override
   2889             public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
   2890                 return null;
   2891             }
   2892 
   2893             @Override
   2894             public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
   2895                 return null;
   2896             }
   2897 
   2898             @Override
   2899             public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
   2900                 return null;
   2901             }
   2902 
   2903             @Override
   2904             public Number parse(String text, ParsePosition parsePosition) {
   2905                 return null;
   2906             }
   2907         }
   2908 
   2909         try {
   2910             TestGetAvailableLocales test = new TestGetAvailableLocales();
   2911             test.getAvailableLocales();
   2912         } catch (Exception e) {
   2913             errln("NumberFormat.getAvailableLocales() was not suppose to "
   2914                     + "return an exception when getting getting available locales.");
   2915         }
   2916     }
   2917 
   2918     /*
   2919      * Tests the method public void setMinimumIntegerDigits(int newValue)
   2920      */
   2921     public void TestSetMinimumIntegerDigits() {
   2922         NumberFormat nf = NumberFormat.getInstance();
   2923         // For valid array, it is displayed as {min value, max value}
   2924         // Tests when "if (minimumIntegerDigits > maximumIntegerDigits)" is true
   2925         int[][] cases = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 2, 0 }, { 2, 1 }, { 10, 0 } };
   2926         int[] expectedMax = { 0, 1, 1, 2, 2, 10 };
   2927         if (cases.length != expectedMax.length) {
   2928             errln("Can't continue test case method TestSetMinimumIntegerDigits "
   2929                     + "since the test case arrays are unequal.");
   2930         } else {
   2931             for (int i = 0; i < cases.length; i++) {
   2932                 nf.setMaximumIntegerDigits(cases[i][1]);
   2933                 nf.setMinimumIntegerDigits(cases[i][0]);
   2934                 if (nf.getMaximumIntegerDigits() != expectedMax[i]) {
   2935                     errln("NumberFormat.setMinimumIntegerDigits(int newValue "
   2936                             + "did not return an expected result for parameter " + cases[i][1] + " and " + cases[i][0]
   2937                                     + " and expected " + expectedMax[i] + " but got " + nf.getMaximumIntegerDigits());
   2938                 }
   2939             }
   2940         }
   2941     }
   2942 
   2943     /*
   2944      * Tests the method public int getRoundingMode() public void setRoundingMode(int roundingMode)
   2945      */
   2946     public void TestRoundingMode() {
   2947         @SuppressWarnings("serial")
   2948         class TestRoundingMode extends NumberFormat {
   2949             @Override
   2950             public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
   2951                 return null;
   2952             }
   2953 
   2954             @Override
   2955             public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
   2956                 return null;
   2957             }
   2958 
   2959             @Override
   2960             public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
   2961                 return null;
   2962             }
   2963 
   2964             @Override
   2965             public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
   2966                 return null;
   2967             }
   2968 
   2969             @Override
   2970             public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
   2971                 return null;
   2972             }
   2973 
   2974             @Override
   2975             public Number parse(String text, ParsePosition parsePosition) {
   2976                 return null;
   2977             }
   2978         }
   2979         TestRoundingMode tgrm = new TestRoundingMode();
   2980 
   2981         // Tests the function 'public void setRoundingMode(int roundingMode)'
   2982         try {
   2983             tgrm.setRoundingMode(0);
   2984             errln("NumberFormat.setRoundingMode(int) was suppose to return an exception");
   2985         } catch (Exception e) {
   2986         }
   2987 
   2988         // Tests the function 'public int getRoundingMode()'
   2989         try {
   2990             tgrm.getRoundingMode();
   2991             errln("NumberFormat.getRoundingMode() was suppose to return an exception");
   2992         } catch (Exception e) {
   2993         }
   2994     }
   2995 
   2996     /*
   2997      * Testing lenient decimal/grouping separator parsing
   2998      */
   2999     public void TestLenientSymbolParsing() {
   3000         DecimalFormat fmt = new DecimalFormat();
   3001         DecimalFormatSymbols sym = new DecimalFormatSymbols();
   3002 
   3003         expect(fmt, "12\u300234", 12.34);
   3004 
   3005         // Ticket#7345 - case 1
   3006         // Even strict parsing, the decimal separator set in the symbols
   3007         // should be successfully parsed.
   3008 
   3009         sym.setDecimalSeparator('\u3002');
   3010 
   3011         // non-strict
   3012         fmt.setDecimalFormatSymbols(sym);
   3013 
   3014         // strict - failed before the fix for #7345
   3015         fmt.setParseStrict(true);
   3016         expect(fmt, "23\u300245", 23.45);
   3017         fmt.setParseStrict(false);
   3018 
   3019 
   3020         // Ticket#7345 - case 2
   3021         // Decimal separator variants other than DecimalFormatSymbols.decimalSeparator
   3022         // should not hide the grouping separator DecimalFormatSymbols.groupingSeparator.
   3023         sym.setDecimalSeparator('.');
   3024         sym.setGroupingSeparator(',');
   3025         fmt.setDecimalFormatSymbols(sym);
   3026 
   3027         expect(fmt, "1,234.56", 1234.56);
   3028 
   3029         sym.setGroupingSeparator('\uFF61');
   3030         fmt.setDecimalFormatSymbols(sym);
   3031 
   3032         expect(fmt, "2\uFF61345.67", 2345.67);
   3033 
   3034         // Ticket#7128
   3035         //
   3036         sym.setGroupingSeparator(',');
   3037         fmt.setDecimalFormatSymbols(sym);
   3038 
   3039         String skipExtSepParse = ICUConfig.get("com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false");
   3040         if (skipExtSepParse.equals("true")) {
   3041             // When the property SkipExtendedSeparatorParsing is true,
   3042             // DecimalFormat does not use the extended equivalent separator
   3043             // data and only uses the one in DecimalFormatSymbols.
   3044             expect(fmt, "23 456", 23);
   3045         } else {
   3046             // Lenient separator parsing is enabled by default.
   3047             // A space character below is interpreted as a
   3048             // group separator, even ',' is used as grouping
   3049             // separator in the symbols.
   3050             expect(fmt, "12 345", 12345);
   3051         }
   3052     }
   3053 
   3054     /*
   3055      * Testing currency driven max/min fraction digits problem
   3056      * reported by ticket#7282
   3057      */
   3058     public void TestCurrencyFractionDigits() {
   3059         double value = 99.12345;
   3060 
   3061         // Create currency instance
   3062         NumberFormat cfmt  = NumberFormat.getCurrencyInstance(new ULocale("ja_JP"));
   3063         String text1 = cfmt.format(value);
   3064 
   3065         // Reset the same currency and format the test value again
   3066         cfmt.setCurrency(cfmt.getCurrency());
   3067         String text2 = cfmt.format(value);
   3068 
   3069         // output1 and output2 must be identical
   3070         if (!text1.equals(text2)) {
   3071             errln("NumberFormat.format() should return the same result - text1="
   3072                     + text1 + " text2=" + text2);
   3073         }
   3074     }
   3075 
   3076     /*
   3077      * Testing rounding to negative zero problem
   3078      * reported by ticket#7609
   3079      */
   3080     public void TestNegZeroRounding() {
   3081 
   3082         DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
   3083         df.setRoundingMode(MathContext.ROUND_HALF_UP);
   3084         df.setMinimumFractionDigits(1);
   3085         df.setMaximumFractionDigits(1);
   3086         String text1 = df.format(-0.01);
   3087 
   3088         df.setRoundingIncrement(0.1);
   3089         String text2 = df.format(-0.01);
   3090 
   3091         // output1 and output2 must be identical
   3092         if (!text1.equals(text2)) {
   3093             errln("NumberFormat.format() should return the same result - text1="
   3094                     + text1 + " text2=" + text2);
   3095         }
   3096 
   3097     }
   3098 
   3099     public void TestCurrencyAmountCoverage() {
   3100         CurrencyAmount ca, cb;
   3101 
   3102         try {
   3103             ca = new CurrencyAmount(null, null);
   3104             errln("NullPointerException should have been thrown.");
   3105         } catch (NullPointerException ex) {
   3106         }
   3107         try {
   3108             ca = new CurrencyAmount(new Integer(0), null);
   3109             errln("NullPointerException should have been thrown.");
   3110         } catch (NullPointerException ex) {
   3111         }
   3112 
   3113         ca = new CurrencyAmount(new Integer(0), Currency.getInstance(new ULocale("ja_JP")));
   3114         cb = new CurrencyAmount(new Integer(1), Currency.getInstance(new ULocale("ja_JP")));
   3115         if (ca.equals(null)) {
   3116             errln("Comparison should return false.");
   3117         }
   3118         if (!ca.equals(ca)) {
   3119             errln("Comparision should return true.");
   3120         }
   3121         if (ca.equals(cb)) {
   3122             errln("Comparison should return false.");
   3123         }
   3124     }
   3125 
   3126     public void TestExponentParse() {
   3127         ParsePosition parsePos = new ParsePosition(0);
   3128         DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
   3129         DecimalFormat fmt = new DecimalFormat("#####", symbols);
   3130         Number result = fmt.parse("5.06e-27", parsePos);
   3131         if ( result.doubleValue() != 5.06E-27 || parsePos.getIndex() != 8) {
   3132             errln("ERROR: ERROR: parse failed - expected 5.06E-27, 8; got " + result.doubleValue() + ", " + parsePos.getIndex());
   3133         }
   3134     }
   3135 
   3136     public void TestExplicitParents() {
   3137         // We use these for testing because decimal and grouping separators will be inherited from es_419
   3138         // starting with CLDR 2.0
   3139         String[] DATA = {
   3140                 "es", "CO", "", "1.250,75",
   3141                 "es", "CR", "", "1.250,75",
   3142                 "es", "ES", "", "1.250,75",
   3143                 "es", "GQ", "", "1.250,75",
   3144                 "es", "MX", "", "1,250.75",
   3145                 "es", "US", "", "1,250.75",
   3146                 "es", "VE", "", "1.250,75",
   3147 
   3148         };
   3149 
   3150         for (int i=0; i<DATA.length; i+=4) {
   3151             Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
   3152             NumberFormat fmt = NumberFormat.getInstance(locale);
   3153             String s = fmt.format(1250.75);
   3154             if (s.equals(DATA[i+3])) {
   3155                 logln("Ok: 1250.75 x " + locale + " => " + s);
   3156             } else {
   3157                 errln("FAIL: 1250.75 x " + locale + " => " + s +
   3158                         ", expected " + DATA[i+3]);
   3159             }
   3160         }
   3161     }
   3162 
   3163     /*
   3164      * Test case for #9240
   3165      * ICU4J 49.1 DecimalFormat did not clone the internal object holding
   3166      * formatted text attribute information properly. Therefore, DecimalFormat
   3167      * created by cloning may return incorrect results or may throw an exception
   3168      * when formatToCharacterIterator is invoked from multiple threads.
   3169      */
   3170     public void TestFormatToCharacterIteratorThread() {
   3171         final int COUNT = 10;
   3172 
   3173         DecimalFormat fmt1 = new DecimalFormat("#0");
   3174         DecimalFormat fmt2 = (DecimalFormat)fmt1.clone();
   3175 
   3176         int[] res1 = new int[COUNT];
   3177         int[] res2 = new int[COUNT];
   3178 
   3179         Thread t1 = new Thread(new FormatCharItrTestThread(fmt1, 1, res1));
   3180         Thread t2 = new Thread(new FormatCharItrTestThread(fmt2, 100, res2));
   3181 
   3182         t1.start();
   3183         t2.start();
   3184 
   3185         try {
   3186             t1.join();
   3187             t2.join();
   3188         } catch (InterruptedException e) {
   3189             //TODO
   3190         }
   3191 
   3192         int val1 = res1[0];
   3193         int val2 = res2[0];
   3194 
   3195         for (int i = 0; i < COUNT; i++) {
   3196             if (res1[i] != val1) {
   3197                 errln("Inconsistent first run limit in test thread 1");
   3198             }
   3199             if (res2[i] != val2) {
   3200                 errln("Inconsistent first run limit in test thread 2");
   3201             }
   3202         }
   3203     }
   3204 
   3205     public void TestParseMaxDigits() {
   3206         DecimalFormat fmt = new DecimalFormat();
   3207         String number = "100000000000";
   3208         int newParseMax = number.length() - 1;
   3209 
   3210         fmt.setParseMaxDigits(-1);
   3211 
   3212         /* Default value is 1000 */
   3213         if (fmt.getParseMaxDigits() != 1000) {
   3214             errln("Fail valid value checking in setParseMaxDigits.");
   3215         }
   3216 
   3217         try {
   3218             if (fmt.parse(number).doubleValue() == Float.POSITIVE_INFINITY) {
   3219                 errln("Got Infinity but should NOT when parsing number: " + number);
   3220             }
   3221 
   3222             fmt.setParseMaxDigits(newParseMax);
   3223 
   3224             if (fmt.parse(number).doubleValue() != Float.POSITIVE_INFINITY) {
   3225                 errln("Did not get Infinity but should when parsing number: " + number);
   3226             }
   3227         } catch (ParseException ex) {
   3228 
   3229         }
   3230     }
   3231 
   3232     private static class FormatCharItrTestThread implements Runnable {
   3233         private final NumberFormat fmt;
   3234         private final int num;
   3235         private final int[] result;
   3236 
   3237         FormatCharItrTestThread(NumberFormat fmt, int num, int[] result) {
   3238             this.fmt = fmt;
   3239             this.num = num;
   3240             this.result = result;
   3241         }
   3242 
   3243         public void run() {
   3244             for (int i = 0; i < result.length; i++) {
   3245                 AttributedCharacterIterator acitr = fmt.formatToCharacterIterator(num);
   3246                 acitr.first();
   3247                 result[i] = acitr.getRunLimit();
   3248             }
   3249         }
   3250     }
   3251 
   3252     public void TestRoundingBehavior() {
   3253         final Object[][] TEST_CASES = {
   3254                 {
   3255                     ULocale.US,                             // ULocale - null for default locale
   3256                     "#.##",                                 // Pattern
   3257                     Integer.valueOf(BigDecimal.ROUND_DOWN), // Rounding Mode or null (implicit)
   3258                     Double.valueOf(0.0d),                   // Rounding increment, Double or BigDecimal, or null (implicit)
   3259                     Double.valueOf(123.4567d),              // Input value, Long, Double, BigInteger or BigDecimal
   3260                     "123.45"                                // Expected result, null for exception
   3261                 },
   3262                 {
   3263                     ULocale.US,
   3264                     "#.##",
   3265                     null,
   3266                     Double.valueOf(0.1d),
   3267                     Double.valueOf(123.4567d),
   3268                     "123.5"
   3269                 },
   3270                 {
   3271                     ULocale.US,
   3272                     "#.##",
   3273                     Integer.valueOf(BigDecimal.ROUND_DOWN),
   3274                     Double.valueOf(0.1d),
   3275                     Double.valueOf(123.4567d),
   3276                     "123.4"
   3277                 },
   3278                 {
   3279                     ULocale.US,
   3280                     "#.##",
   3281                     Integer.valueOf(BigDecimal.ROUND_UNNECESSARY),
   3282                     null,
   3283                     Double.valueOf(123.4567d),
   3284                     null
   3285                 },
   3286                 {
   3287                     ULocale.US,
   3288                     "#.##",
   3289                     Integer.valueOf(BigDecimal.ROUND_DOWN),
   3290                     null,
   3291                     Long.valueOf(1234),
   3292                     "1234"
   3293                 },
   3294         };
   3295 
   3296         int testNum = 1;
   3297 
   3298         for (Object[] testCase : TEST_CASES) {
   3299             // 0: locale
   3300             // 1: pattern
   3301             ULocale locale = testCase[0] == null ? ULocale.getDefault() : (ULocale)testCase[0];
   3302             String pattern = (String)testCase[1];
   3303 
   3304             DecimalFormat fmt = new DecimalFormat(pattern, DecimalFormatSymbols.getInstance(locale));
   3305 
   3306             // 2: rounding mode
   3307             Integer roundingMode = null;
   3308             if (testCase[2] != null) {
   3309                 roundingMode = (Integer)testCase[2];
   3310                 fmt.setRoundingMode(roundingMode);
   3311             }
   3312 
   3313             // 3: rounding increment
   3314             if (testCase[3] != null) {
   3315                 if (testCase[3] instanceof Double) {
   3316                     fmt.setRoundingIncrement((Double)testCase[3]);
   3317                 } else if (testCase[3] instanceof BigDecimal) {
   3318                     fmt.setRoundingIncrement((BigDecimal)testCase[3]);
   3319                 } else if (testCase[3] instanceof java.math.BigDecimal) {
   3320                     fmt.setRoundingIncrement((java.math.BigDecimal)testCase[3]);
   3321                 }
   3322             }
   3323 
   3324             // 4: input number
   3325             String s = null;
   3326             boolean bException = false;
   3327             try {
   3328                 s = fmt.format(testCase[4]);
   3329             } catch (ArithmeticException e) {
   3330                 bException = true;
   3331             }
   3332 
   3333             if (bException) {
   3334                 if (testCase[5] != null) {
   3335                     errln("Test case #" + testNum + ": ArithmeticException was thrown.");
   3336                 }
   3337             } else {
   3338                 if (testCase[5] == null) {
   3339                     errln("Test case #" + testNum +
   3340                             ": ArithmeticException must be thrown, but got formatted result: " +
   3341                             s);
   3342                 } else {
   3343                     assertEquals("Test case #" + testNum, (String)testCase[5], s);
   3344                 }
   3345             }
   3346 
   3347             testNum++;
   3348         }
   3349     }
   3350 
   3351     public void TestSignificantDigits() {
   3352         double input[] = {
   3353                 0, 0,
   3354                 123, -123,
   3355                 12345, -12345,
   3356                 123.45, -123.45,
   3357                 123.44501, -123.44501,
   3358                 0.001234, -0.001234,
   3359                 0.00000000123, -0.00000000123,
   3360                 0.0000000000000000000123, -0.0000000000000000000123,
   3361                 1.2, -1.2,
   3362                 0.0000000012344501, -0.0000000012344501,
   3363                 123445.01, -123445.01,
   3364                 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
   3365         };
   3366         String[] expected = {
   3367                 "0.00", "0.00",
   3368                 "123", "-123",
   3369                 "12345", "-12345",
   3370                 "123.45", "-123.45",
   3371                 "123.45", "-123.45",
   3372                 "0.001234", "-0.001234",
   3373                 "0.00000000123", "-0.00000000123",
   3374                 "0.0000000000000000000123", "-0.0000000000000000000123",
   3375                 "1.20", "-1.20",
   3376                 "0.0000000012345", "-0.0000000012345",
   3377                 "123450", "-123450",
   3378                 "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
   3379         };
   3380         DecimalFormat numberFormat =
   3381                 (DecimalFormat) NumberFormat.getInstance(ULocale.US);
   3382         numberFormat.setSignificantDigitsUsed(true);
   3383         numberFormat.setMinimumSignificantDigits(3);
   3384         numberFormat.setMaximumSignificantDigits(5);
   3385         numberFormat.setGroupingUsed(false);
   3386         for (int i = 0; i < input.length; i++) {
   3387             assertEquals("TestSignificantDigits", expected[i], numberFormat.format(input[i]));
   3388         }
   3389     }
   3390 
   3391     public void TestBug9936() {
   3392         DecimalFormat numberFormat =
   3393                 (DecimalFormat) NumberFormat.getInstance(ULocale.US);
   3394         assertFalse("", numberFormat.areSignificantDigitsUsed());
   3395 
   3396         numberFormat.setSignificantDigitsUsed(true);
   3397         assertTrue("", numberFormat.areSignificantDigitsUsed());
   3398 
   3399         numberFormat.setSignificantDigitsUsed(false);
   3400         assertFalse("", numberFormat.areSignificantDigitsUsed());
   3401 
   3402         numberFormat.setMinimumSignificantDigits(3);
   3403         assertTrue("", numberFormat.areSignificantDigitsUsed());
   3404 
   3405         numberFormat.setSignificantDigitsUsed(false);
   3406         numberFormat.setMaximumSignificantDigits(6);
   3407         assertTrue("", numberFormat.areSignificantDigitsUsed());
   3408     }
   3409 
   3410     public void TestShowZero() {
   3411         DecimalFormat numberFormat =
   3412                 (DecimalFormat) NumberFormat.getInstance(ULocale.US);
   3413         numberFormat.setSignificantDigitsUsed(true);
   3414         numberFormat.setMaximumSignificantDigits(3);
   3415         assertEquals("TestShowZero", "0", numberFormat.format(0.0));
   3416     }
   3417 
   3418     public void TestCurrencyPlurals() {
   3419         String[][] tests = {
   3420                 {"en", "USD", "1", "1 US dollar"},
   3421                 {"en", "USD", "1.0", "1.0 US dollars"},
   3422                 {"en", "USD", "1.00", "1.00 US dollars"},
   3423                 {"en", "USD", "1.99", "1.99 US dollars"},
   3424                 {"en", "AUD", "1", "1 Australian dollar"},
   3425                 {"en", "AUD", "1.00", "1.00 Australian dollars"},
   3426                 {"sl", "USD", "1", "1 ameri\u0161ki dolar"},
   3427                 {"sl", "USD", "2", "2 ameri\u0161ka dolarja"},
   3428                 {"sl", "USD", "3", "3 ameri\u0161ki dolarji"},
   3429                 {"sl", "USD", "5", "5 amerikih dolarjev"},
   3430                 {"fr", "USD", "1.99", "1,99 dollar des tats-Unis"},
   3431                 {"ru", "RUB", "1", "1 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0439 \u0440\u0443\u0431\u043B\u044C"},
   3432                 {"ru", "RUB", "2", "2 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u044F"},
   3433                 {"ru", "RUB", "5", "5 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u0435\u0439"},
   3434         };
   3435         for (String test[] : tests) {
   3436             DecimalFormat numberFormat = (DecimalFormat) DecimalFormat.getInstance(new ULocale(test[0]), NumberFormat.PLURALCURRENCYSTYLE);
   3437             numberFormat.setCurrency(Currency.getInstance(test[1]));
   3438             double number = Double.parseDouble(test[2]);
   3439             int dotPos = test[2].indexOf('.');
   3440             int decimals = dotPos < 0 ? 0 : test[2].length() - dotPos - 1;
   3441             int digits = dotPos < 0 ? test[2].length() : test[2].length() - 1;
   3442             numberFormat.setMaximumFractionDigits(decimals);
   3443             numberFormat.setMinimumFractionDigits(decimals);
   3444             String actual = numberFormat.format(number);
   3445             assertEquals(test[0] + "\t" + test[1] + "\t" + test[2], test[3], actual);
   3446             numberFormat.setMaximumSignificantDigits(digits);
   3447             numberFormat.setMinimumSignificantDigits(digits);
   3448             actual = numberFormat.format(number);
   3449             assertEquals(test[0] + "\t" + test[1] + "\t" + test[2], test[3], actual);
   3450         }
   3451     }
   3452 
   3453     public void TestCustomCurrencySignAndSeparator() {
   3454         DecimalFormatSymbols custom = new DecimalFormatSymbols(ULocale.US);
   3455 
   3456         custom.setCurrencySymbol("*");
   3457         custom.setMonetaryGroupingSeparator('^');
   3458         custom.setMonetaryDecimalSeparator(':');
   3459 
   3460         DecimalFormat fmt = new DecimalFormat("\u00A4 #,##0.00", custom);
   3461 
   3462         final String numstr = "* 1^234:56";
   3463         expect2(fmt, 1234.56, numstr);
   3464     }
   3465 
   3466     public void TestParseSignsAndMarks() {
   3467         class SignsAndMarksItem {
   3468             public String locale;
   3469             public boolean lenient;
   3470             public String numString;
   3471             public double value;
   3472              // Simple constructor
   3473             public SignsAndMarksItem(String loc, boolean lnt, String numStr, double val) {
   3474                 locale = loc;
   3475                 lenient = lnt;
   3476                 numString = numStr;
   3477                 value = val;
   3478             }
   3479         };
   3480         final SignsAndMarksItem[] items = {
   3481             // *** Note, ICU4J lenient number parsing does not handle arbitrary whitespace, but can
   3482             // treat some whitespace as a grouping separator. The cases marked *** below depend
   3483             // on isGroupingUsed() being set for the locale, which in turn depends on grouping
   3484             // separators being present in the decimalFormat pattern for the locale (& num sys).
   3485             //
   3486             //                    locale                lenient numString                               value
   3487             new SignsAndMarksItem("en",                 false,  "12",                                    12 ),
   3488             new SignsAndMarksItem("en",                 true,   "12",                                    12 ),
   3489             new SignsAndMarksItem("en",                 false,  "-23",                                  -23 ),
   3490             new SignsAndMarksItem("en",                 true,   "-23",                                  -23 ),
   3491             new SignsAndMarksItem("en",                 true,   "- 23",                                 -23 ), // ***
   3492             new SignsAndMarksItem("en",                 false,  "\u200E-23",                            -23 ),
   3493             new SignsAndMarksItem("en",                 true,   "\u200E-23",                            -23 ),
   3494             new SignsAndMarksItem("en",                 true,   "\u200E- 23",                           -23 ), // ***
   3495 
   3496             new SignsAndMarksItem("en@numbers=arab",    false,  "\u0663\u0664",                          34 ),
   3497             new SignsAndMarksItem("en@numbers=arab",    true,   "\u0663\u0664",                          34 ),
   3498             new SignsAndMarksItem("en@numbers=arab",    false,  "-\u0664\u0665",                        -45 ),
   3499             new SignsAndMarksItem("en@numbers=arab",    true,   "-\u0664\u0665",                        -45 ),
   3500             new SignsAndMarksItem("en@numbers=arab",    true,   "- \u0664\u0665",                       -45 ), // ***
   3501             new SignsAndMarksItem("en@numbers=arab",    false,  "\u200F-\u0664\u0665",                  -45 ),
   3502             new SignsAndMarksItem("en@numbers=arab",    true,   "\u200F-\u0664\u0665",                  -45 ),
   3503             new SignsAndMarksItem("en@numbers=arab",    true,   "\u200F- \u0664\u0665",                 -45 ), // ***
   3504 
   3505             new SignsAndMarksItem("en@numbers=arabext", false,  "\u06F5\u06F6",                          56 ),
   3506             new SignsAndMarksItem("en@numbers=arabext", true,   "\u06F5\u06F6",                          56 ),
   3507             new SignsAndMarksItem("en@numbers=arabext", false,  "-\u06F6\u06F7",                        -67 ),
   3508             new SignsAndMarksItem("en@numbers=arabext", true,   "-\u06F6\u06F7",                        -67 ),
   3509             new SignsAndMarksItem("en@numbers=arabext", true,   "- \u06F6\u06F7",                       -67 ), // ***
   3510             new SignsAndMarksItem("en@numbers=arabext", false,  "\u200E-\u200E\u06F6\u06F7",            -67 ),
   3511             new SignsAndMarksItem("en@numbers=arabext", true,   "\u200E-\u200E\u06F6\u06F7",            -67 ),
   3512             new SignsAndMarksItem("en@numbers=arabext", true,   "\u200E-\u200E \u06F6\u06F7",           -67 ), // ***
   3513 
   3514             new SignsAndMarksItem("he",                 false,  "12",                                    12 ),
   3515             new SignsAndMarksItem("he",                 true,   "12",                                    12 ),
   3516             new SignsAndMarksItem("he",                 false,  "-23",                                  -23 ),
   3517             new SignsAndMarksItem("he",                 true,   "-23",                                  -23 ),
   3518             new SignsAndMarksItem("he",                 true,   "- 23",                                 -23 ), // ***
   3519             new SignsAndMarksItem("he",                 false,  "\u200E-23",                            -23 ),
   3520             new SignsAndMarksItem("he",                 true,   "\u200E-23",                            -23 ),
   3521             new SignsAndMarksItem("he",                 true,   "\u200E- 23",                           -23 ), // ***
   3522 
   3523             new SignsAndMarksItem("ar",                 false,  "\u0663\u0664",                          34 ),
   3524             new SignsAndMarksItem("ar",                 true,   "\u0663\u0664",                          34 ),
   3525             new SignsAndMarksItem("ar",                 false,  "-\u0664\u0665",                        -45 ),
   3526             new SignsAndMarksItem("ar",                 true,   "-\u0664\u0665",                        -45 ),
   3527             new SignsAndMarksItem("ar",                 true,   "- \u0664\u0665",                       -45 ), // ***
   3528             new SignsAndMarksItem("ar",                 false,  "\u200F-\u0664\u0665",                  -45 ),
   3529             new SignsAndMarksItem("ar",                 true,   "\u200F-\u0664\u0665",                  -45 ),
   3530             new SignsAndMarksItem("ar",                 true,   "\u200F- \u0664\u0665",                 -45 ), // ***
   3531 
   3532             new SignsAndMarksItem("ar_MA",              false,  "12",                                    12 ),
   3533             new SignsAndMarksItem("ar_MA",              true,   "12",                                    12 ),
   3534             new SignsAndMarksItem("ar_MA",              false,  "-23",                                  -23 ),
   3535             new SignsAndMarksItem("ar_MA",              true,   "-23",                                  -23 ),
   3536             new SignsAndMarksItem("ar_MA",              true,   "- 23",                                 -23 ), // ***
   3537             new SignsAndMarksItem("ar_MA",              false,  "\u200E-23",                            -23 ),
   3538             new SignsAndMarksItem("ar_MA",              true,   "\u200E-23",                            -23 ),
   3539             new SignsAndMarksItem("ar_MA",              true,   "\u200E- 23",                           -23 ), // ***
   3540 
   3541             new SignsAndMarksItem("fa",                 false,  "\u06F5\u06F6",                          56 ),
   3542             new SignsAndMarksItem("fa",                 true,   "\u06F5\u06F6",                          56 ),
   3543             new SignsAndMarksItem("fa",                 false,  "\u2212\u06F6\u06F7",                   -67 ),
   3544             new SignsAndMarksItem("fa",                 true,   "\u2212\u06F6\u06F7",                   -67 ),
   3545             new SignsAndMarksItem("fa",                 true,   "\u2212 \u06F6\u06F7",                  -67 ), // ***
   3546             new SignsAndMarksItem("fa",                 false,  "\u200E\u2212\u200E\u06F6\u06F7",       -67 ),
   3547             new SignsAndMarksItem("fa",                 true,   "\u200E\u2212\u200E\u06F6\u06F7",       -67 ),
   3548             new SignsAndMarksItem("fa",                 true,   "\u200E\u2212\u200E \u06F6\u06F7",      -67 ), // ***
   3549 
   3550             new SignsAndMarksItem("ps",                 false,  "\u06F5\u06F6",                          56 ),
   3551             new SignsAndMarksItem("ps",                 true,   "\u06F5\u06F6",                          56 ),
   3552             new SignsAndMarksItem("ps",                 false,  "-\u06F6\u06F7",                        -67 ),
   3553             new SignsAndMarksItem("ps",                 true,   "-\u06F6\u06F7",                        -67 ),
   3554             new SignsAndMarksItem("ps",                 true,   "- \u06F6\u06F7",                       -67 ), // ***
   3555             new SignsAndMarksItem("ps",                 false,  "\u200E-\u200E\u06F6\u06F7",            -67 ),
   3556             new SignsAndMarksItem("ps",                 true,   "\u200E-\u200E\u06F6\u06F7",            -67 ),
   3557             new SignsAndMarksItem("ps",                 true,   "\u200E-\u200E \u06F6\u06F7",           -67 ), // ***
   3558             new SignsAndMarksItem("ps",                 false,  "-\u200E\u06F6\u06F7",                  -67 ),
   3559             new SignsAndMarksItem("ps",                 true,   "-\u200E\u06F6\u06F7",                  -67 ),
   3560             new SignsAndMarksItem("ps",                 true,   "-\u200E \u06F6\u06F7",                 -67 ), // ***
   3561         };
   3562         for (SignsAndMarksItem item: items) {
   3563             ULocale locale = new ULocale(item.locale);
   3564             NumberFormat numfmt = NumberFormat.getInstance(locale);
   3565             if (numfmt != null) {
   3566                 numfmt.setParseStrict(!item.lenient);
   3567                 ParsePosition ppos = new ParsePosition(0);
   3568                 Number num = numfmt.parse(item.numString, ppos);
   3569                 if (num != null && ppos.getIndex() == item.numString.length()) {
   3570                     double parsedValue = num.doubleValue();
   3571                     if (parsedValue != item.value) {
   3572                         errln("FAIL: locale " + item.locale + ", lenient " + item.lenient + ", parse of \"" + item.numString + "\" gives value " + parsedValue);
   3573                     }
   3574                 } else {
   3575                     errln("FAIL: locale " + item.locale + ", lenient " + item.lenient + ", parse of \"" + item.numString + "\" gives position " + ppos.getIndex());
   3576                 }
   3577             } else {
   3578                 errln("FAIL: NumberFormat.getInstance for locale " + item.locale);
   3579             }
   3580         }
   3581     }
   3582 
   3583     public void TestContext() {
   3584         // just a minimal sanity check for now
   3585         NumberFormat nfmt = NumberFormat.getInstance();
   3586         DisplayContext context = nfmt.getContext(DisplayContext.Type.CAPITALIZATION);
   3587         if (context != DisplayContext.CAPITALIZATION_NONE) {
   3588             errln("FAIL: Initial NumberFormat.getContext() is not CAPITALIZATION_NONE");
   3589         }
   3590         nfmt.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE);
   3591         context = nfmt.getContext(DisplayContext.Type.CAPITALIZATION);
   3592         if (context != DisplayContext.CAPITALIZATION_FOR_STANDALONE) {
   3593             errln("FAIL: NumberFormat.getContext() does not return the value set, CAPITALIZATION_FOR_STANDALONE");
   3594         }
   3595     }
   3596 
   3597     public void TestAccountingCurrency() {
   3598         String[][] tests = {
   3599                 {"en_US", "1234.5", "$1,234.50", "true"},
   3600                 {"en_US", "-1234.5", "($1,234.50)", "true"},
   3601                 {"en_US", "0", "$0.00", "true"},
   3602                 {"en_US", "-0.2", "($0.20)", "true"},
   3603                 {"ja_JP", "10000", "10,000", "true"},
   3604                 {"ja_JP", "-1000.5", "(1,000)", "false"},
   3605                 {"de_DE", "-23456.7", "-23.456,70\u00A0", "true"},
   3606         };
   3607         for (String[] data : tests) {
   3608             ULocale loc = new ULocale(data[0]);
   3609             double num = Double.parseDouble(data[1]);
   3610             String fmt = data[2];
   3611             boolean rt = Boolean.parseBoolean(data[3]);
   3612 
   3613             NumberFormat acfmt = NumberFormat.getInstance(loc, NumberFormat.ACCOUNTINGCURRENCYSTYLE);
   3614             expect(acfmt, num, fmt, rt);
   3615         }
   3616     }
   3617 
   3618     public void TestCurrencyUsage() {
   3619         // the 1st one is checking setter/getter, while the 2nd one checks for getInstance
   3620         // compare the Currency and Currency Cash Digits
   3621         // Note that as of CLDR 26:
   3622         // * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that
   3623         // * CAD and all other currencies that rounded to .05 no longer do
   3624         for (int i = 0; i < 2; i++) {
   3625             String original_expected = "PKR124";
   3626             DecimalFormat custom = null;
   3627             if (i == 0) {
   3628                 custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=PKR"),
   3629                         DecimalFormat.CURRENCYSTYLE);
   3630 
   3631                 String original = custom.format(123.567);
   3632                 assertEquals("Test Currency Context", original_expected, original);
   3633 
   3634                 // test the getter
   3635                 assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(),
   3636                         Currency.CurrencyUsage.STANDARD);
   3637                 custom.setCurrencyUsage(Currency.CurrencyUsage.CASH);
   3638                 assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(), Currency.CurrencyUsage.CASH);
   3639             } else {
   3640                 custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=PKR"),
   3641                         DecimalFormat.CASHCURRENCYSTYLE);
   3642 
   3643                 // test the getter
   3644                 assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(), Currency.CurrencyUsage.CASH);
   3645             }
   3646 
   3647             String cash_currency = custom.format(123.567);
   3648             String cash_currency_expected = "PKR124";
   3649             assertEquals("Test Currency Context", cash_currency_expected, cash_currency);
   3650         }
   3651 
   3652         // the 1st one is checking setter/getter, while the 2nd one checks for getInstance
   3653         // compare the Currency and Currency Cash Rounding
   3654         for (int i = 0; i < 2; i++) {
   3655             String original_rounding_expected = "CA$123.57";
   3656             DecimalFormat fmt = null;
   3657             if (i == 0) {
   3658                 fmt = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=CAD"),
   3659                         DecimalFormat.CURRENCYSTYLE);
   3660 
   3661                 String original_rounding = fmt.format(123.566);
   3662                 assertEquals("Test Currency Context", original_rounding_expected, original_rounding);
   3663 
   3664                 fmt.setCurrencyUsage(Currency.CurrencyUsage.CASH);
   3665             } else {
   3666                 fmt = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=CAD"),
   3667                         DecimalFormat.CASHCURRENCYSTYLE);
   3668             }
   3669 
   3670             String cash_rounding_currency = fmt.format(123.567);
   3671             String cash__rounding_currency_expected = "CA$123.57";
   3672             assertEquals("Test Currency Context", cash__rounding_currency_expected, cash_rounding_currency);
   3673         }
   3674 
   3675         // the 1st one is checking setter/getter, while the 2nd one checks for getInstance
   3676         // Test the currency change
   3677         for (int i = 0; i < 2; i++) {
   3678             DecimalFormat fmt2 = null;
   3679             if (i == 1) {
   3680                 fmt2 = (DecimalFormat) NumberFormat.getInstance(new ULocale("en_US@currency=JPY"),
   3681                         NumberFormat.CURRENCYSTYLE);
   3682                 fmt2.setCurrencyUsage(Currency.CurrencyUsage.CASH);
   3683             } else {
   3684                 fmt2 = (DecimalFormat) NumberFormat.getInstance(new ULocale("en_US@currency=JPY"),
   3685                         NumberFormat.CASHCURRENCYSTYLE);
   3686             }
   3687 
   3688             fmt2.setCurrency(Currency.getInstance("PKR"));
   3689             String PKR_changed = fmt2.format(123.567);
   3690             String PKR_changed_expected = "PKR124";
   3691             assertEquals("Test Currency Context", PKR_changed_expected, PKR_changed);
   3692         }
   3693     }
   3694 
   3695     public void TestParseRequiredDecimalPoint() {
   3696 
   3697         String[] testPattern = { "00.####", "00.0", "00" };
   3698 
   3699         String value2Parse = "99";
   3700         double parseValue  =  99;
   3701         DecimalFormat parser = new DecimalFormat();
   3702         double result;
   3703         boolean hasDecimalPoint;
   3704         for (int i = 0; i < testPattern.length; i++) {
   3705             parser.applyPattern(testPattern[i]);
   3706             hasDecimalPoint = testPattern[i].contains(".");
   3707 
   3708             parser.setDecimalPatternMatchRequired(false);
   3709             try {
   3710                 result = parser.parse(value2Parse).doubleValue();
   3711                 assertEquals("wrong parsed value", parseValue, result);
   3712             } catch (ParseException e) {
   3713                this.errln("Parsing " + value2Parse + " should have succeeded with " + testPattern[i] +
   3714                             " and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired());
   3715             }
   3716 
   3717             parser.setDecimalPatternMatchRequired(true);
   3718             try {
   3719                 result = parser.parse(value2Parse).doubleValue();
   3720                 if(hasDecimalPoint){
   3721                     this.errln("Parsing " + value2Parse + " should NOT have succeeded with " + testPattern[i] +
   3722                             " and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired());
   3723                 }
   3724             } catch (ParseException e) {
   3725                     // OK, should fail
   3726             }
   3727         }
   3728 
   3729     }
   3730 
   3731     public void TestCurrFmtNegSameAsPositive() {
   3732         DecimalFormatSymbols decfmtsym = DecimalFormatSymbols.getInstance(Locale.US);
   3733         decfmtsym.setMinusSign('\u200B'); // ZERO WIDTH SPACE, in ICU4J cannot set to empty string
   3734         DecimalFormat decfmt = new DecimalFormat("\u00A4#,##0.00;\u00A4#,##0.00", decfmtsym);
   3735         String currFmtResult = decfmt.format(-100.0);
   3736         if (!currFmtResult.equals("\u200B$100.00")) {
   3737             errln("decfmt.toPattern results wrong, expected \u200B$100.00, got " + currFmtResult);
   3738         }
   3739     }
   3740 
   3741 }
   3742