]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / tests / core / src / com / ibm / icu / dev / test / format / NumberFormatTest.java
1 //##header
2 /*
3  *******************************************************************************
4  * Copyright (C) 2001-2011, International Business Machines Corporation and    *
5  * others. All Rights Reserved.                                                *
6  *******************************************************************************
7  */
8
9 /**
10  * Port From:   ICU4C v1.8.1 : format : NumberFormatTest
11  * Source File: $ICU4CRoot/source/test/intltest/numfmtst.cpp
12  **/
13
14 package com.ibm.icu.dev.test.format;
15
16 import java.math.BigInteger;
17 import java.text.FieldPosition;
18 import java.text.ParseException;
19 import java.text.ParsePosition;
20 import java.util.ArrayList;
21 import java.util.Locale;
22 import java.util.Set;
23
24 import com.ibm.icu.dev.test.TestUtil;
25 import com.ibm.icu.impl.LocaleUtility;
26 import com.ibm.icu.impl.Utility;
27 import com.ibm.icu.impl.data.ResourceReader;
28 import com.ibm.icu.impl.data.TokenIterator;
29 import com.ibm.icu.math.BigDecimal;
30 import com.ibm.icu.math.MathContext;
31 import com.ibm.icu.text.DecimalFormat;
32 import com.ibm.icu.text.DecimalFormatSymbols;
33 import com.ibm.icu.text.MeasureFormat;
34 import com.ibm.icu.text.NumberFormat;
35 import com.ibm.icu.text.NumberFormat.NumberFormatFactory;
36 import com.ibm.icu.text.NumberFormat.SimpleNumberFormatFactory;
37 import com.ibm.icu.util.Currency;
38 import com.ibm.icu.util.CurrencyAmount;
39 import com.ibm.icu.util.ULocale;
40
41 public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
42
43     public static void main(String[] args) throws Exception {
44         new NumberFormatTest().run(args);
45     }
46
47     // Test various patterns
48     public void TestPatterns() {
49
50         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
51         final String pat[]    = { "#.#", "#.", ".#", "#" };
52         int pat_length = pat.length;
53         final String newpat[] = { "#0.#", "#0.", "#.0", "#" };
54         final String num[]    = { "0",   "0.", ".0", "0" };
55         for (int i=0; i<pat_length; ++i)
56         {
57             DecimalFormat fmt = new DecimalFormat(pat[i], sym);
58             String newp = fmt.toPattern();
59             if (!newp.equals(newpat[i]))
60                 errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
61                       "; " + newp + " seen instead");
62
63             String s = ((NumberFormat)fmt).format(0);
64             if (!s.equals(num[i]))
65             {
66                 errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
67                       "; " + s + " seen instead");
68                 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
69             }
70             // BigInteger 0 - ticket#4731
71             s = ((NumberFormat)fmt).format(BigInteger.ZERO);
72             if (!s.equals(num[i]))
73             {
74                 errln("FAIL: Pattern " + pat[i] + " should format BigInteger zero as " + num[i] +
75                       "; " + s + " seen instead");
76                 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
77             }
78         }
79     }
80
81     // Test exponential pattern
82     public void TestExponential() {
83
84         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
85         final String pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
86         int pat_length = pat.length;
87
88         double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
89         int val_length = val.length;
90         final String valFormat[] = {
91             // 0.####E0
92             "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
93             // 00.000E00
94             "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
95             // ##0.######E000
96             "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
97             // 0.###E0;[0.###E0]
98             "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" };
99         /*double valParse[] =
100             {
101                 0.01234, 123460000, 1.23E300, -3.1416E-271,
102                 0.01234, 123460000, 1.23E300, -3.1416E-271,
103                 0.01234, 123456800, 1.23E300, -3.141593E-271,
104                 0.01234, 123500000, 1.23E300, -3.142E-271,
105             };*/ //The variable is never used
106
107         int lval[] = { 0, -1, 1, 123456789 };
108         int lval_length = lval.length;
109         final String lvalFormat[] = {
110             // 0.####E0
111             "0E0", "-1E0", "1E0", "1.2346E8",
112             // 00.000E00
113             "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
114             // ##0.######E000
115             "0E000", "-1E000", "1E000", "123.4568E006",
116             // 0.###E0;[0.###E0]
117             "0E0", "[1E0]", "1E0", "1.235E8" };
118         int lvalParse[] =
119             {
120                 0, -1, 1, 123460000,
121                 0, -1, 1, 123460000,
122                 0, -1, 1, 123456800,
123                 0, -1, 1, 123500000,
124             };
125         int ival = 0, ilval = 0;
126         for (int p = 0; p < pat_length; ++p) {
127             DecimalFormat fmt = new DecimalFormat(pat[p], sym);
128             logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" + fmt.toPattern() + "\"");
129             int v;
130             for (v = 0; v < val_length; ++v) {
131                 String s;
132                 s = ((NumberFormat) fmt).format(val[v]);
133                 logln(" " + val[v] + " -format-> " + s);
134                 if (!s.equals(valFormat[v + ival]))
135                     errln("FAIL: Expected " + valFormat[v + ival]);
136
137                 ParsePosition pos = new ParsePosition(0);
138                 double a = fmt.parse(s, pos).doubleValue();
139                 if (pos.getIndex() == s.length()) {
140                     logln("  -parse-> " + Double.toString(a));
141                     // Use epsilon comparison as necessary
142                 } else
143                     errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
144             }
145             for (v = 0; v < lval_length; ++v) {
146                 String s;
147                 s = ((NumberFormat) fmt).format(lval[v]);
148                 logln(" " + lval[v] + "L -format-> " + s);
149                 if (!s.equals(lvalFormat[v + ilval]))
150                     errln("ERROR: Expected " + lvalFormat[v + ilval] + " Got: " + s);
151
152                 ParsePosition pos = new ParsePosition(0);
153                 long a = 0;
154                 Number A = fmt.parse(s, pos);
155                 if (A != null) {
156                     a = A.longValue();
157                     if (pos.getIndex() == s.length()) {
158                         logln("  -parse-> " + a);
159                         if (a != lvalParse[v + ilval])
160                             errln("FAIL: Expected " + lvalParse[v + ilval]);
161                     } else
162                         errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + Long.toString(a));
163                 } else {
164                     errln("Fail to parse the string: " + s);
165                 }
166             }
167             ival += val_length;
168             ilval += lval_length;
169         }
170     }
171
172     // Test the handling of quotes
173     public void TestQuotes() {
174
175         StringBuffer pat;
176         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
177         pat = new StringBuffer("a'fo''o'b#");
178         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
179         String s = ((NumberFormat)fmt).format(123);
180         logln("Pattern \"" + pat + "\"");
181         logln(" Format 123 . " + s);
182         if (!s.equals("afo'ob123"))
183             errln("FAIL: Expected afo'ob123");
184
185         s ="";
186         pat = new StringBuffer("a''b#");
187         fmt = new DecimalFormat(pat.toString(), sym);
188         s = ((NumberFormat)fmt).format(123);
189         logln("Pattern \"" + pat + "\"");
190         logln(" Format 123 . " + s);
191         if (!s.equals("a'b123"))
192             errln("FAIL: Expected a'b123");
193     }
194
195     public void TestParseCurrencyTrailingSymbol() {
196         // see sun bug 4709840
197         NumberFormat fmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);
198         float val = 12345.67f;
199         String str = fmt.format(val);
200         logln("val: " + val + " str: " + str);
201         try {
202             Number num = fmt.parse(str);
203             logln("num: " + num);
204         } catch (ParseException e) {
205             errln("parse of '" + str + "' threw exception: " + e);
206         }
207     }
208
209     /**
210      * Test the handling of the currency symbol in patterns.
211      **/
212     public void TestCurrencySign() {
213         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
214         StringBuffer pat = new StringBuffer("");
215         char currency = 0x00A4;
216         // "\xA4#,##0.00;-\xA4#,##0.00"
217         pat.append(currency).append("#,##0.00;-").append(currency).append("#,##0.00");
218         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
219         String s = ((NumberFormat) fmt).format(1234.56);
220         pat = new StringBuffer();
221         logln("Pattern \"" + fmt.toPattern() + "\"");
222         logln(" Format " + 1234.56 + " . " + s);
223         assertEquals("symbol, pos", "$1,234.56", s);
224         
225         s = ((NumberFormat) fmt).format(-1234.56);
226         logln(" Format " + Double.toString(-1234.56) + " . " + s);
227         assertEquals("symbol, neg", "-$1,234.56", s);
228
229         pat.setLength(0);
230         // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
231         pat.append(currency).append(currency).append(" #,##0.00;").append(currency).append(currency).append(" -#,##0.00");
232         fmt = new DecimalFormat(pat.toString(), sym);
233         s = ((NumberFormat) fmt).format(1234.56);
234         logln("Pattern \"" + fmt.toPattern() + "\"");
235         logln(" Format " + Double.toString(1234.56) + " . " + s);
236         assertEquals("name, pos", "USD 1,234.56", s);
237         
238         s = ((NumberFormat) fmt).format(-1234.56);
239         logln(" Format " + Double.toString(-1234.56) + " . " + s);
240         assertEquals("name, neg", "USD -1,234.56", s);
241     }
242
243     public void TestSpaceParsing() {
244         // the data are:
245         // the string to be parsed, parsed position, parsed error index
246         String[][] DATA = {
247             {"$124", "4", "-1"},
248             {"$124 $124", "4", "-1"},
249             {"$124 ", "4", "-1"},
250             {"$ 124 ", "5", "-1"},
251             {"$\u00A0124 ", "5", "-1"},
252             {" $ 124 ", "0", "0"}, // TODO: need to handle space correctly
253             {"124$", "0", "3"}, // TODO: need to handle space correctly
254             // {"124 $", "5", "-1"}, TODO: OK or NOT?
255             {"124 $", "0", "3"}, 
256         };
257         NumberFormat foo = NumberFormat.getCurrencyInstance();
258         for (int i = 0; i < DATA.length; ++i) {
259           ParsePosition parsePosition = new ParsePosition(0);
260           String stringToBeParsed = DATA[i][0];
261           int parsedPosition = Integer.parseInt(DATA[i][1]);
262           int errorIndex = Integer.parseInt(DATA[i][2]);
263           try {
264             Number result = foo.parse(stringToBeParsed, parsePosition);
265             if (parsePosition.getIndex() != parsedPosition ||
266                 parsePosition.getErrorIndex() != errorIndex) {
267                 errln("FAILED parse " + stringToBeParsed + "; parse position: " + parsePosition.getIndex() + "; error position: " + parsePosition.getErrorIndex());
268             }
269             if (parsePosition.getErrorIndex() == -1 &&
270                 result.doubleValue() != 124) {
271                 errln("FAILED parse " + stringToBeParsed + "; value " + result.doubleValue());
272             }
273           } catch (Exception e) {
274               errln("FAILED " + e.toString());
275           }
276         }
277     }
278
279
280     public void TestMultiCurrencySign() {
281         String[][] DATA = {
282             // the fields in the following test are:
283             // locale, 
284             // currency pattern (with negative pattern), 
285             // currency number to be formatted,
286             // currency format using currency symbol name, such as "$" for USD,
287             // currency format using currency ISO name, such as "USD",
288             // currency format using plural name, such as "US dollars".
289             // for US locale
290             {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"}, 
291             {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"}, 
292             {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollar1.00"}, 
293             // for CHINA locale
294             {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY1,234.56", "\u4EBA\u6C11\u5E011,234.56"},
295             {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY1,234.56)", "(\u4EBA\u6C11\u5E011,234.56)"},
296             {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY1.00", "\u4EBA\u6C11\u5E011.00"}
297         };
298
299         String doubleCurrencyStr = "\u00A4\u00A4";
300         String tripleCurrencyStr = "\u00A4\u00A4\u00A4";
301
302         for (int i=0; i<DATA.length; ++i) {
303             String locale = DATA[i][0];
304             String pat = DATA[i][1];
305             Double numberToBeFormat = new Double(DATA[i][2]);
306             DecimalFormatSymbols sym = new DecimalFormatSymbols(new ULocale(locale));
307             for (int j=1; j<=3; ++j) {
308                 // j represents the number of currency sign in the pattern.
309                 if (j == 2) {
310                     pat = pat.replaceAll("\u00A4", doubleCurrencyStr);
311                 } else if (j == 3) {
312                     pat = pat.replaceAll("\u00A4\u00A4", tripleCurrencyStr);
313                 }
314                 DecimalFormat fmt = new DecimalFormat(pat, sym);
315                 String s = ((NumberFormat) fmt).format(numberToBeFormat);
316                 // DATA[i][3] is the currency format result using a
317                 // single currency sign.
318                 // DATA[i][4] is the currency format result using
319                 // double currency sign.
320                 // DATA[i][5] is the currency format result using
321                 // triple currency sign.
322                 // DATA[i][j+2] is the currency format result using
323                 // 'j' number of currency sign.
324                 String currencyFormatResult = DATA[i][2+j];
325                 if (!s.equals(currencyFormatResult)) {
326                     errln("FAIL format: Expected " + currencyFormatResult);
327                 }
328                 try {
329                     // mix style parsing
330                     for (int k=3; k<=5; ++k) {
331                       // DATA[i][3] is the currency format result using a
332                       // single currency sign.
333                       // DATA[i][4] is the currency format result using
334                       // double currency sign.
335                       // DATA[i][5] is the currency format result using
336                       // triple currency sign.
337                       String oneCurrencyFormat = DATA[i][k];
338                       if (fmt.parse(oneCurrencyFormat).doubleValue() != 
339                           numberToBeFormat.doubleValue()) {
340                         errln("FAILED parse " + oneCurrencyFormat);
341                       }
342                     }
343                 } catch (ParseException e) {
344                     errln("FAILED, DecimalFormat parse currency: " + e.toString());
345                 }
346             }
347         }
348     }
349
350     public void TestCurrencyFormatForMixParsing() {
351         MeasureFormat curFmt = MeasureFormat.getCurrencyFormat(new ULocale("en_US"));
352         String[] formats = {
353             "$1,234.56",  // string to be parsed
354             "USD1,234.56",
355             "US dollars1,234.56",
356             "1,234.56 US dollars"
357         };
358         try {
359           for (int i = 0; i < formats.length; ++i) {
360             String stringToBeParsed = formats[i];
361             CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(stringToBeParsed);
362             Number val = parsedVal.getNumber();
363             if (!val.equals(new BigDecimal("1234.56"))) {
364                 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val);
365             }
366             if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) {
367                 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency");
368             }
369           }
370         } catch (ParseException e) {
371             errln("parse FAILED: " + e.toString());
372         }
373     }
374
375     public void TestDecimalFormatCurrencyParse() {
376         // Locale.US
377         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
378         StringBuffer pat = new StringBuffer("");
379         char currency = 0x00A4;
380         // "\xA4#,##0.00;-\xA4#,##0.00"
381         pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
382         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
383         String[][] DATA = {
384             // the data are:
385             // string to be parsed, the parsed result (number)
386             {"$1.00", "1"},    
387             {"USD1.00", "1"},    
388             {"1.00 US dollar", "1"},    
389             {"$1,234.56", "1234.56"},    
390             {"USD1,234.56", "1234.56"},    
391             {"1,234.56 US dollar", "1234.56"},    
392         };
393         try {
394             for (int i = 0; i < DATA.length; ++i) {
395                 String stringToBeParsed = DATA[i][0];
396                 double parsedResult = Double.parseDouble(DATA[i][1]);
397                 Number num = fmt.parse(stringToBeParsed);
398                 if (num.doubleValue() != parsedResult) {
399                     errln("FAIL parse: Expected " + parsedResult);
400                 }
401             }
402         } catch (ParseException e) {
403             errln("FAILED, DecimalFormat parse currency: " + e.toString());
404         }
405     } 
406
407     /**
408      * Test localized currency patterns.
409      */
410     public void TestCurrency() {
411         String[] DATA = {
412             "fr", "CA", "", "1,50\u00a0$",
413             "de", "DE", "", "1,50\u00a0\u20AC",
414             "de", "DE", "PREEURO", "1,50\u00a0DEM",
415             "fr", "FR", "", "1,50\u00a0\u20AC",
416             "fr", "FR", "PREEURO", "1,50\u00a0F",
417         };
418
419         for (int i=0; i<DATA.length; i+=4) {
420             Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
421             NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
422             String s = fmt.format(1.50);
423             if (s.equals(DATA[i+3])) {
424                 logln("Ok: 1.50 x " + locale + " => " + s);
425             } else {
426                 logln("FAIL: 1.50 x " + locale + " => " + s +
427                       ", expected " + DATA[i+3]);
428             }
429         }
430
431         // format currency with CurrencyAmount
432         for (int i=0; i<DATA.length; i+=4) {
433             Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
434
435             Currency curr = Currency.getInstance(locale);
436             logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
437             CurrencyAmount cAmt = new CurrencyAmount(1.5, curr);
438             logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
439
440             NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
441             String sCurr = fmt.format(cAmt);
442             if (sCurr.equals(DATA[i+3])) {
443                 logln("Ok: 1.50 x " + locale + " => " + sCurr);
444             } else {
445                 errln("FAIL: 1.50 x " + locale + " => " + sCurr +
446                       ", expected " + DATA[i+3]);
447             }
448         }
449
450         //Cover MeasureFormat.getCurrencyFormat()
451         ULocale save = ULocale.getDefault();
452         ULocale.setDefault(ULocale.US);
453         MeasureFormat curFmt = MeasureFormat.getCurrencyFormat();
454         String strBuf = curFmt.format(new CurrencyAmount(new Float(1234.56), Currency.getInstance("USD")));
455
456         try {
457             CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(strBuf);
458             Number val = parsedVal.getNumber();
459             if (!val.equals(new BigDecimal("1234.56"))) {
460                 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val);
461             }
462             if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) {
463                 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency");
464             }
465         }
466         catch (ParseException e) {
467             errln("FAIL: " + e.getMessage());
468         }
469         ULocale.setDefault(save);
470     }
471
472     public void TestCurrencyIsoPluralFormat() {
473         String[][] DATA = {
474             // the data are:
475             // locale, 
476             // currency amount to be formatted,
477             // currency ISO code to be formatted,
478             // format result using CURRENCYSTYLE,
479             // format result using ISOCURRENCYSTYLE,
480             // format result using PLURALCURRENCYSTYLE,
481             {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
482             {"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
483             {"en_US", "-1234.56", "USD", "($1,234.56)", "(USD1,234.56)", "-1,234.56 US dollars"},
484             {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00 \u7F8E\u5143"}, 
485             {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56 \u7F8E\u5143"},
486             //{"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "1.00 CHY"},
487             //{"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"},
488             {"zh_CN", "1", "CNY", "\uFFE51.00", "CNY1.00", "1.00 \u4EBA\u6C11\u5E01"},
489             {"zh_CN", "1234.56", "CNY", "\uFFE51,234.56", "CNY1,234.56", "1,234.56 \u4EBA\u6C11\u5E01"}, 
490             {"ru_RU", "1", "RUB", "1,00\u00A0\u0440\u0443\u0431.", "1,00\u00A0RUB", "1,00 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0439 \u0440\u0443\u0431\u043B\u044C"},
491             {"ru_RU", "2", "RUB", "2,00\u00A0\u0440\u0443\u0431.", "2,00\u00A0RUB", "2,00 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u044F"},
492             {"ru_RU", "5", "RUB", "5,00\u00A0\u0440\u0443\u0431.", "5,00\u00A0RUB", "5,00 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u0435\u0439"},
493             // test locale without currency information
494             {"root", "-1.23", "USD", "-US$\u00a01.23", "-USD\u00a01.23", "-1.23 USD"},
495             {"root@numbers=latn", "-1.23", "USD", "-US$\u00a01.23", "-USD\u00a01.23", "-1.23 USD"}, // ensure that the root locale is still used with modifiers
496             {"root@numbers=arab", "-1.23", "USD", "-US$\u00a0\u0661\u066B\u0662\u0663", "-USD\u00a0\u0661\u066B\u0662\u0663", "-\u0661\u066B\u0662\u0663 USD"}, // ensure that the root locale is still used with modifiers
497             // test choice format
498             {"es_AR", "1", "INR", "\u20B91,00", "INR1,00", "1,00 rupia india"},
499             {"ar_EG", "1", "USD", "US$\u00A0\u0661\u066B\u0660\u0660", "USD\u00a0\u0661\u066b\u0660\u0660", "\u0661\u066b\u0660\u0660 \u062f\u0648\u0644\u0627\u0631 \u0623\u0645\u0631\u064a\u0643\u064a"},
500         };
501         
502         for (int i=0; i<DATA.length; ++i) {
503           for (int k = NumberFormat.CURRENCYSTYLE;
504                k <= NumberFormat.PLURALCURRENCYSTYLE;
505                ++k) {
506             // k represents currency format style.
507             if ( k != NumberFormat.CURRENCYSTYLE &&
508                  k != NumberFormat.ISOCURRENCYSTYLE &&
509                  k != NumberFormat.PLURALCURRENCYSTYLE ) {
510                 continue;
511             }
512             String localeString = DATA[i][0];
513             Double numberToBeFormat = new Double(DATA[i][1]);
514             String currencyISOCode = DATA[i][2];
515             ULocale locale = new ULocale(localeString);
516             NumberFormat numFmt = NumberFormat.getInstance(locale, k);
517             numFmt.setCurrency(Currency.getInstance(currencyISOCode));
518             String strBuf = numFmt.format(numberToBeFormat);
519             int resultDataIndex = k-1;
520             if ( k == NumberFormat.CURRENCYSTYLE ) {
521                 resultDataIndex = k+2;
522             }
523             // DATA[i][resultDataIndex] is the currency format result
524             // using 'k' currency style.
525             String formatResult = DATA[i][resultDataIndex];
526             if (!strBuf.equals(formatResult)) {
527                 errln("FAIL: Expected " + formatResult + " actual: " + Utility.escape(strBuf));
528             }
529             try {
530                 // test parsing, and test parsing for all currency formats.
531                 for (int j = 3; j < 6; ++j) {
532                     // DATA[i][3] is the currency format result using 
533                     // CURRENCYSTYLE formatter.
534                     // DATA[i][4] is the currency format result using
535                     // ISOCURRENCYSTYLE formatter.
536                     // DATA[i][5] is the currency format result using
537                     // PLURALCURRENCYSTYLE formatter.
538                     String oneCurrencyFormatResult = DATA[i][j];
539                     Number val = numFmt.parse(oneCurrencyFormatResult);
540                     if (val.doubleValue() != numberToBeFormat.doubleValue()) {
541                         errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat);
542                     }
543                 }
544             }
545             catch (ParseException e) {
546                 errln("FAIL: " + e.getMessage());
547             }
548           }  
549         }
550     }
551
552
553     public void TestMiscCurrencyParsing() {
554         String[][] DATA = {
555             // each has: string to be parsed, parsed position, error position
556             {"1.00 ", "0", "4"},
557             {"1.00 UAE dirha", "0", "4"},
558             {"1.00 us dollar", "14", "-1"},
559             {"1.00 US DOLLAR", "14", "-1"},
560             {"1.00 usd", "0", "4"},
561         };
562         ULocale locale = new ULocale("en_US");
563         for (int i=0; i<DATA.length; ++i) {
564             String stringToBeParsed = DATA[i][0];
565             int parsedPosition = Integer.parseInt(DATA[i][1]);
566             int errorIndex = Integer.parseInt(DATA[i][2]);
567             NumberFormat numFmt = NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
568             ParsePosition parsePosition = new ParsePosition(0);
569             Number val = numFmt.parse(stringToBeParsed, parsePosition);
570             if (parsePosition.getIndex() != parsedPosition ||
571                 parsePosition.getErrorIndex() != errorIndex) {
572                 errln("FAIL: parse failed. expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex());
573                 errln("FAIL: parse failed. expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex());
574             }
575             if (parsePosition.getErrorIndex() == -1 &&
576                 val.doubleValue() != 1.00) {
577                 errln("FAIL: parse failed. expected 1.00, actual:" + val);
578             }
579         }
580     }
581
582     public void TestParseCurrency() {
583         class ParseCurrencyItem {
584             private String localeString;
585             private String descrip;
586             private String currStr;
587             private int    numExpectPos;
588             private int    numExpectVal;
589             private int    curExpectPos;
590             private int    curExpectVal;
591             private String curExpectCurr;
592
593             ParseCurrencyItem(String locStr, String desc, String curr, int numExPos, int numExVal, int curExPos, int curExVal, String curExCurr) {
594                 localeString  = locStr;
595                 descrip       = desc;
596                 currStr       = curr;
597                 numExpectPos  = numExPos;
598                 numExpectVal  = numExVal;
599                 curExpectPos  = curExPos;
600                 curExpectVal  = curExVal;
601                 curExpectCurr = curExCurr;
602             }
603             public String getLocaleString()  { return localeString; }
604             public String getDescrip()       { return descrip; }
605             public String getCurrStr()       { return currStr; }
606             public int    getNumExpectPos()  { return numExpectPos; }
607             public int    getNumExpectVal()  { return numExpectVal; }
608             public int    getCurExpectPos()  { return curExpectPos; }
609             public int    getCurExpectVal()  { return curExpectVal; }
610             public String getCurExpectCurr() { return curExpectCurr; }
611         }
612         final ParseCurrencyItem[] parseCurrencyItems = { 
613             new ParseCurrencyItem( "en_US", "dollars2", "$2.00",            5,  2,  5,  2,  "USD" ),
614             new ParseCurrencyItem( "en_US", "dollars4", "$4",               2,  4,  2,  4,  "USD" ),
615             new ParseCurrencyItem( "en_US", "dollars9", "9\u00A0$",         0,  0,  0,  0,  ""    ),
616             new ParseCurrencyItem( "en_US", "pounds3",  "\u00A33.00",       0,  0,  5,  3,  "GBP" ),
617             new ParseCurrencyItem( "en_US", "pounds5",  "\u00A35",          0,  0,  2,  5,  "GBP" ),
618             new ParseCurrencyItem( "en_US", "pounds7",  "7\u00A0\u00A3",    0,  0,  0,  0,  ""    ),
619             new ParseCurrencyItem( "en_US", "euros8",   "\u20AC8",          0,  0,  2,  8,  "EUR" ),
620
621             new ParseCurrencyItem( "en_GB", "pounds3",  "\u00A33.00",       5,  3,  5,  3,  "GBP" ),
622             new ParseCurrencyItem( "en_GB", "pounds5",  "\u00A35",          2,  5,  2,  5,  "GBP" ),
623             new ParseCurrencyItem( "en_GB", "pounds7",  "7\u00A0\u00A3",    0,  0,  0,  0,  ""    ),
624             new ParseCurrencyItem( "en_GB", "euros4",   "4,00\u00A0\u20AC", 0,  0,  0,  0,  ""    ),
625             new ParseCurrencyItem( "en_GB", "euros6",   "6\u00A0\u20AC",    0,  0,  0,  0,  ""    ),
626             new ParseCurrencyItem( "en_GB", "euros8",   "\u20AC8",          0,  0,  2,  8,  "EUR" ),
627             new ParseCurrencyItem( "en_GB", "dollars4", "$4",               0,  0,  2,  4,  "USD" ),
628
629             new ParseCurrencyItem( "fr_FR", "euros4",   "4,00\u00A0\u20AC", 6,  4,  6,  4,  "EUR" ),
630             new ParseCurrencyItem( "fr_FR", "euros6",   "6\u00A0\u20AC",    3,  6,  3,  6,  "EUR" ),
631             new ParseCurrencyItem( "fr_FR", "euros8",   "\u20AC8",          0,  0,  0,  0,  ""    ),
632             new ParseCurrencyItem( "fr_FR", "dollars2", "$2.00",            0,  0,  0,  0,  ""    ),
633             new ParseCurrencyItem( "fr_FR", "dollars4", "$4",               0,  0,  0,  0,  ""    ),
634         };
635         for (ParseCurrencyItem item: parseCurrencyItems) {
636             String localeString = item.getLocaleString();
637             ULocale uloc = new ULocale(localeString);
638             NumberFormat fmt = null;
639             try {
640                 fmt = NumberFormat.getCurrencyInstance(uloc);
641             } catch (Exception e) {
642                 errln("NumberFormat.getCurrencyInstance fails for locale " + localeString);
643                 continue;
644             }
645             String currStr = item.getCurrStr();
646             ParsePosition parsePos = new ParsePosition(0);
647
648             Number numVal = fmt.parse(currStr, parsePos);
649             if ( parsePos.getIndex() != item.getNumExpectPos() || (numVal != null && numVal.intValue() != item.getNumExpectVal()) ) {
650                 if (numVal != null) {
651                     errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() + 
652                             ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() +
653                             ", get " + parsePos.getIndex() + "/" + numVal.intValue() );
654                 } else {
655                     errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() + 
656                             ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() +
657                             ", get " + parsePos.getIndex() + "/(NULL)" );
658                 }
659             }
660             
661             parsePos.setIndex(0);
662             CurrencyAmount currAmt = fmt.parseCurrency(currStr, parsePos);
663             if ( parsePos.getIndex() != item.getCurExpectPos() || (currAmt != null && (currAmt.getNumber().intValue() != item.getCurExpectVal() ||
664                     currAmt.getCurrency().getCurrencyCode().compareTo(item.getCurExpectCurr()) != 0)) ) {
665                 if (currAmt != null) {
666                     errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() + 
667                             ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() +
668                             ", get " + parsePos.getIndex() + "/" + currAmt.getNumber().intValue() + "/" + currAmt.getCurrency().getCurrencyCode() );
669                 } else {
670                     errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() + 
671                             ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() +
672                             ", get " + parsePos.getIndex() + "/(NULL)" );
673                 }
674             }
675         }
676     }
677
678     /**
679      * Test the Currency object handling, new as of ICU 2.2.
680      */
681     public void TestCurrencyObject() {
682         NumberFormat fmt =
683             NumberFormat.getCurrencyInstance(Locale.US);
684
685         expectCurrency(fmt, null, 1234.56, "$1,234.56");
686
687         expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
688                        1234.56, "\u20AC1,234.56"); // Euro
689
690         expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
691                        1234.56, "\u00A51,235"); // Yen
692
693         expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
694                        1234.56, "CHF1,234.55"); // 0.05 rounding
695
696         expectCurrency(fmt, Currency.getInstance(Locale.US),
697                        1234.56, "$1,234.56");
698
699         fmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);
700
701         expectCurrency(fmt, null, 1234.56, "1 234,56 \u20AC");
702
703         expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
704                        1234.56, "1 235 \u00A5JP"); // Yen
705
706         expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
707                        1234.56, "1 234,55 CHF"); // 0.25 rounding
708
709         expectCurrency(fmt, Currency.getInstance(Locale.US),
710                        1234.56, "1 234,56 $US");
711
712         expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
713                        1234.56, "1 234,56 \u20AC"); // Euro
714     }
715
716     public void TestCurrencyPatterns() {
717         int i;
718         Locale[] locs = NumberFormat.getAvailableLocales();
719         for (i=0; i<locs.length; ++i) {
720             NumberFormat nf = NumberFormat.getCurrencyInstance(locs[i]);
721             // Make sure currency formats do not have a variable number
722             // of fraction digits
723             int min = nf.getMinimumFractionDigits();
724             int max = nf.getMaximumFractionDigits();
725             if (min != max) {
726                 String a = nf.format(1.0);
727                 String b = nf.format(1.125);
728                 errln("FAIL: " + locs[i] +
729                       " min fraction digits != max fraction digits; "+
730                       "x 1.0 => " + a +
731                       "; x 1.125 => " + b);
732             }
733
734             // Make sure EURO currency formats have exactly 2 fraction digits
735             if (nf instanceof DecimalFormat) {
736                 Currency curr = ((DecimalFormat) nf).getCurrency();
737                 if (curr != null && "EUR".equals(curr.getCurrencyCode())) {
738                     if (min != 2 || max != 2) {
739                         String a = nf.format(1.0);
740                         errln("FAIL: " + locs[i] +
741                               " is a EURO format but it does not have 2 fraction digits; "+
742                               "x 1.0 => " +
743                               a);
744                     }
745                 }
746             }
747         }
748     }
749
750     /**
751      * Do rudimentary testing of parsing.
752      */
753     public void TestParse() {
754         String arg = "0.0";
755         DecimalFormat format = new DecimalFormat("00");
756         double aNumber = 0l;
757         try {
758             aNumber = format.parse(arg).doubleValue();
759         } catch (ParseException e) {
760             System.out.println(e);
761         }
762         logln("parse(" + arg + ") = " + aNumber);
763     }
764
765     /**
766      * Test proper rounding by the format method.
767      */
768     public void TestRounding487() {
769
770         NumberFormat nf = NumberFormat.getInstance();
771         roundingTest(nf, 0.00159999, 4, "0.0016");
772         roundingTest(nf, 0.00995, 4, "0.01");
773
774         roundingTest(nf, 12.3995, 3, "12.4");
775
776         roundingTest(nf, 12.4999, 0, "12");
777         roundingTest(nf, - 19.5, 0, "-20");
778
779     }
780
781     /**
782      * Test the functioning of the secondary grouping value.
783      */
784     public void TestSecondaryGrouping() {
785
786         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
787         DecimalFormat f = new DecimalFormat("#,##,###", US);
788
789         expect(f, 123456789L, "12,34,56,789");
790         expectPat(f, "#,##,###");
791         f.applyPattern("#,###");
792
793         f.setSecondaryGroupingSize(4);
794         expect(f, 123456789L, "12,3456,789");
795         expectPat(f, "#,####,###");
796         NumberFormat g = NumberFormat.getInstance(new Locale("hi", "IN"));
797
798         String out = "";
799         long l = 1876543210L;
800         out = g.format(l);
801
802         // expect "1,87,65,43,210", but with Hindi digits
803         //         01234567890123
804         boolean ok = true;
805         if (out.length() != 14) {
806             ok = false;
807         } else {
808             for (int i = 0; i < out.length(); ++i) {
809                 boolean expectGroup = false;
810                 switch (i) {
811                     case 1 :
812                     case 4 :
813                     case 7 :
814                     case 10 :
815                         expectGroup = true;
816                         break;
817                 }
818                 // Later -- fix this to get the actual grouping
819                 // character from the resource bundle.
820                 boolean isGroup = (out.charAt(i) == 0x002C);
821                 if (isGroup != expectGroup) {
822                     ok = false;
823                     break;
824                 }
825             }
826         }
827         if (!ok) {
828             errln("FAIL  Expected "+ l + " x hi_IN . \"1,87,65,43,210\" (with Hindi digits), got \""
829                     + out + "\"");
830         } else {
831             logln("Ok    " + l + " x hi_IN . \"" + out + "\"");
832         }
833     }
834
835     public void roundingTest(NumberFormat nf, double x, int maxFractionDigits, final String expected) {
836         nf.setMaximumFractionDigits(maxFractionDigits);
837         String out = nf.format(x);
838         logln(x + " formats with " + maxFractionDigits + " fractional digits to " + out);
839         if (!out.equals(expected))
840             errln("FAIL: Expected " + expected);
841     }
842
843     /**
844      * Upgrade to alphaWorks
845      */
846     public void TestExponent() {
847         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
848         DecimalFormat fmt1 = new DecimalFormat("0.###E0", US);
849         DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US);
850         int n = 1234;
851         expect2(fmt1, n, "1.234E3");
852         expect2(fmt2, n, "1.234E+3");
853         expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
854
855     }
856
857     /**
858      * Upgrade to alphaWorks
859      */
860     public void TestScientific() {
861
862         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
863
864         // Test pattern round-trip
865         final String PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };
866         int PAT_length = PAT.length;
867         int DIGITS[] = {
868             // min int, max int, min frac, max frac
869             0, 1, 0, 0, // "#E0"
870             1, 1, 0, 4, // "0.####E0"
871             2, 2, 3, 3, // "00.000E00"
872             1, 3, 0, 4, // "##0.####E000"
873             1, 1, 0, 3, // "0.###E0;[0.###E0]"
874         };
875         for (int i = 0; i < PAT_length; ++i) {
876             String pat = PAT[i];
877             DecimalFormat df = new DecimalFormat(pat, US);
878             String pat2 = df.toPattern();
879             if (pat.equals(pat2)) {
880                 logln("Ok   Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
881             } else {
882                 errln("FAIL Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
883             }
884             // Make sure digit counts match what we expect
885             if (df.getMinimumIntegerDigits() != DIGITS[4 * i]
886                 || df.getMaximumIntegerDigits() != DIGITS[4 * i + 1]
887                 || df.getMinimumFractionDigits() != DIGITS[4 * i + 2]
888                 || df.getMaximumFractionDigits() != DIGITS[4 * i + 3]) {
889                 errln("FAIL \""+ pat+ "\" min/max int; min/max frac = "
890                         + df.getMinimumIntegerDigits() + "/"
891                         + df.getMaximumIntegerDigits() + ";"
892                         + df.getMinimumFractionDigits() + "/"
893                         + df.getMaximumFractionDigits() + ", expect "
894                         + DIGITS[4 * i] + "/"
895                         + DIGITS[4 * i + 1] + ";"
896                         + DIGITS[4 * i + 2] + "/"
897                         + DIGITS[4 * i + 3]);
898             }
899         }
900
901         expect2(new DecimalFormat("#E0", US), 12345.0, "1.2345E4");
902         expect(new DecimalFormat("0E0", US), 12345.0, "1E4");
903
904         // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
905         // so result = 1.234568E4 not 1.2345678901E4
906         //when the pattern problem is finalized, delete comment mark'//'
907         //of the following code
908         expect2(NumberFormat.getScientificInstance(Locale.US), 12345.678901, "1.2345678901E4");
909         logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
910         expect2(NumberFormat.getScientificInstance(ULocale.US), 12345.678901, "1.2345678901E4");
911
912         expect(new DecimalFormat("##0.###E0", US), 12345.0, "12.34E3");
913         expect(new DecimalFormat("##0.###E0", US), 12345.00001, "12.35E3");
914         expect2(new DecimalFormat("##0.####E0", US), 12345, "12.345E3");
915
916         // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
917         // so result = 1.234568E4 not 1.2345678901E4
918         expect2(NumberFormat.getScientificInstance(Locale.FRANCE), 12345.678901, "1,2345678901E4");
919         logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
920         expect2(NumberFormat.getScientificInstance(ULocale.FRANCE), 12345.678901, "1,2345678901E4");
921
922         expect(new DecimalFormat("##0.####E0", US), 789.12345e-9, "789.12E-9");
923         expect2(new DecimalFormat("##0.####E0", US), 780.e-9, "780E-9");
924         expect(new DecimalFormat(".###E0", US), 45678.0, ".457E5");
925         expect2(new DecimalFormat(".###E0", US), 0, ".0E0");
926         /*
927         expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
928                                      new DecimalFormat("##E0", US),
929                                      new DecimalFormat("####E0", US),
930                                      new DecimalFormat("0E0", US),
931                                      new DecimalFormat("00E0", US),
932                                      new DecimalFormat("000E0", US),
933                                    },
934                new Long(45678000),
935                new String[] { "4.5678E7",
936                               "45.678E6",
937                               "4567.8E4",
938                               "5E7",
939                               "46E6",
940                               "457E5",
941                             }
942                );
943         !
944         ! Unroll this test into individual tests below...
945         !
946         */
947         expect2(new DecimalFormat("#E0", US), 45678000, "4.5678E7");
948         expect2(new DecimalFormat("##E0", US), 45678000, "45.678E6");
949         expect2(new DecimalFormat("####E0", US), 45678000, "4567.8E4");
950         expect(new DecimalFormat("0E0", US), 45678000, "5E7");
951         expect(new DecimalFormat("00E0", US), 45678000, "46E6");
952         expect(new DecimalFormat("000E0", US), 45678000, "457E5");
953         /*
954         expect(new DecimalFormat("###E0", US, status),
955                new Object[] { new Double(0.0000123), "12.3E-6",
956                               new Double(0.000123), "123E-6",
957                               new Double(0.00123), "1.23E-3",
958                               new Double(0.0123), "12.3E-3",
959                               new Double(0.123), "123E-3",
960                               new Double(1.23), "1.23E0",
961                               new Double(12.3), "12.3E0",
962                               new Double(123), "123E0",
963                               new Double(1230), "1.23E3",
964                              });
965         !
966         ! Unroll this test into individual tests below...
967         !
968         */
969         expect2(new DecimalFormat("###E0", US), 0.0000123, "12.3E-6");
970         expect2(new DecimalFormat("###E0", US), 0.000123, "123E-6");
971         expect2(new DecimalFormat("###E0", US), 0.00123, "1.23E-3");
972         expect2(new DecimalFormat("###E0", US), 0.0123, "12.3E-3");
973         expect2(new DecimalFormat("###E0", US), 0.123, "123E-3");
974         expect2(new DecimalFormat("###E0", US), 1.23, "1.23E0");
975         expect2(new DecimalFormat("###E0", US), 12.3, "12.3E0");
976         expect2(new DecimalFormat("###E0", US), 123.0, "123E0");
977         expect2(new DecimalFormat("###E0", US), 1230.0, "1.23E3");
978         /*
979         expect(new DecimalFormat("0.#E+00", US, status),
980                new Object[] { new Double(0.00012), "1.2E-04",
981                               new Long(12000),     "1.2E+04",
982                              });
983         !
984         ! Unroll this test into individual tests below...
985         !
986         */
987         expect2(new DecimalFormat("0.#E+00", US), 0.00012, "1.2E-04");
988         expect2(new DecimalFormat("0.#E+00", US), 12000, "1.2E+04");
989     }
990
991     /**
992      * Upgrade to alphaWorks
993      */
994     public void TestPad() {
995
996         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
997         expect2(new DecimalFormat("*^##.##", US), 0, "^^^^0");
998         expect2(new DecimalFormat("*^##.##", US), -1.3, "^-1.3");
999         expect2(
1000             new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
1001             0,
1002             "0.0E0______ g-m/s^2");
1003         expect(
1004             new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
1005             1.0 / 3,
1006             "333.333E-3_ g-m/s^2");
1007         expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US), 0, "0.0______ g-m/s^2");
1008         expect(
1009             new DecimalFormat("##0.0####*_ 'g-m/s^2'", US),
1010             1.0 / 3,
1011             "0.33333__ g-m/s^2");
1012
1013         // Test padding before a sign
1014         final String formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1015         expect2(new DecimalFormat(formatStr, US), -10, "xxxxxxxxxx(10.0)");
1016         expect2(new DecimalFormat(formatStr, US), -1000, "xxxxxxx(1,000.0)");
1017         expect2(new DecimalFormat(formatStr, US), -1000000, "xxx(1,000,000.0)");
1018         expect2(new DecimalFormat(formatStr, US), -100.37, "xxxxxxxx(100.37)");
1019         expect2(new DecimalFormat(formatStr, US), -10456.37, "xxxxx(10,456.37)");
1020         expect2(new DecimalFormat(formatStr, US), -1120456.37, "xx(1,120,456.37)");
1021         expect2(new DecimalFormat(formatStr, US), -112045600.37, "(112,045,600.37)");
1022         expect2(new DecimalFormat(formatStr, US), -1252045600.37, "(1,252,045,600.37)");
1023
1024         expect2(new DecimalFormat(formatStr, US), 10, "xxxxxxxxxxxx10.0");
1025         expect2(new DecimalFormat(formatStr, US), 1000, "xxxxxxxxx1,000.0");
1026         expect2(new DecimalFormat(formatStr, US), 1000000, "xxxxx1,000,000.0");
1027         expect2(new DecimalFormat(formatStr, US), 100.37, "xxxxxxxxxx100.37");
1028         expect2(new DecimalFormat(formatStr, US), 10456.37, "xxxxxxx10,456.37");
1029         expect2(new DecimalFormat(formatStr, US), 1120456.37, "xxxx1,120,456.37");
1030         expect2(new DecimalFormat(formatStr, US), 112045600.37, "xx112,045,600.37");
1031         expect2(new DecimalFormat(formatStr, US), 10252045600.37, "10,252,045,600.37");
1032
1033         // Test padding between a sign and a number
1034         final String formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1035         expect2(new DecimalFormat(formatStr2, US), -10, "(10.0xxxxxxxxxx)");
1036         expect2(new DecimalFormat(formatStr2, US), -1000, "(1,000.0xxxxxxx)");
1037         expect2(new DecimalFormat(formatStr2, US), -1000000, "(1,000,000.0xxx)");
1038         expect2(new DecimalFormat(formatStr2, US), -100.37, "(100.37xxxxxxxx)");
1039         expect2(new DecimalFormat(formatStr2, US), -10456.37, "(10,456.37xxxxx)");
1040         expect2(new DecimalFormat(formatStr2, US), -1120456.37, "(1,120,456.37xx)");
1041         expect2(new DecimalFormat(formatStr2, US), -112045600.37, "(112,045,600.37)");
1042         expect2(new DecimalFormat(formatStr2, US), -1252045600.37, "(1,252,045,600.37)");
1043
1044         expect2(new DecimalFormat(formatStr2, US), 10, "10.0xxxxxxxxxxxx");
1045         expect2(new DecimalFormat(formatStr2, US), 1000, "1,000.0xxxxxxxxx");
1046         expect2(new DecimalFormat(formatStr2, US), 1000000, "1,000,000.0xxxxx");
1047         expect2(new DecimalFormat(formatStr2, US), 100.37, "100.37xxxxxxxxxx");
1048         expect2(new DecimalFormat(formatStr2, US), 10456.37, "10,456.37xxxxxxx");
1049         expect2(new DecimalFormat(formatStr2, US), 1120456.37, "1,120,456.37xxxx");
1050         expect2(new DecimalFormat(formatStr2, US), 112045600.37, "112,045,600.37xx");
1051         expect2(new DecimalFormat(formatStr2, US), 10252045600.37, "10,252,045,600.37");
1052
1053         //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1054         DecimalFormat fmt = new DecimalFormat("#", US);
1055         char padString = 'P';
1056         fmt.setPadCharacter(padString);
1057         expectPad(fmt, "*P##.##", DecimalFormat.PAD_BEFORE_PREFIX, 5, padString);
1058         fmt.setPadCharacter('^');
1059         expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, '^');
1060         //commented untill implementation is complete
1061         /*  fmt.setPadCharacter((UnicodeString)"^^^");
1062           expectPad(fmt, "*^^^#", DecimalFormat.kPadBeforePrefix, 3, (UnicodeString)"^^^");
1063           padString.remove();
1064           padString.append((UChar)0x0061);
1065           padString.append((UChar)0x0302);
1066           fmt.setPadCharacter(padString);
1067           UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1068           UnicodeString pattern(patternChars);
1069           expectPad(fmt, pattern , DecimalFormat.kPadBeforePrefix, 4, padString);
1070           */
1071     }
1072
1073     /**
1074      * Upgrade to alphaWorks
1075      */
1076     public void TestPatterns2() {
1077         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1078         DecimalFormat fmt = new DecimalFormat("#", US);
1079
1080         char hat = 0x005E; /*^*/
1081
1082         expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, hat);
1083         expectPad(fmt, "$*^#", DecimalFormat.PAD_AFTER_PREFIX, 2, hat);
1084         expectPad(fmt, "#*^", DecimalFormat.PAD_BEFORE_SUFFIX, 1, hat);
1085         expectPad(fmt, "#$*^", DecimalFormat.PAD_AFTER_SUFFIX, 2, hat);
1086         expectPad(fmt, "$*^$#", -1);
1087         expectPad(fmt, "#$*^$", -1);
1088         expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat.PAD_BEFORE_SUFFIX, 12, (char) 0x0078 /*x*/);
1089         expectPad(fmt, "''#0*x", DecimalFormat.PAD_BEFORE_SUFFIX, 3, (char) 0x0078 /*x*/);
1090         expectPad(fmt, "'I''ll'*a###.##", DecimalFormat.PAD_AFTER_PREFIX, 10, (char) 0x0061 /*a*/);
1091
1092         fmt.applyPattern("AA#,##0.00ZZ");
1093         fmt.setPadCharacter(hat);
1094
1095         fmt.setFormatWidth(10);
1096
1097         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_PREFIX);
1098         expectPat(fmt, "*^AA#,##0.00ZZ");
1099
1100         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_SUFFIX);
1101         expectPat(fmt, "AA#,##0.00*^ZZ");
1102
1103         fmt.setPadPosition(DecimalFormat.PAD_AFTER_SUFFIX);
1104         expectPat(fmt, "AA#,##0.00ZZ*^");
1105
1106         //            12  3456789012
1107         String exp = "AA*^#,##0.00ZZ";
1108         fmt.setFormatWidth(12);
1109         fmt.setPadPosition(DecimalFormat.PAD_AFTER_PREFIX);
1110         expectPat(fmt, exp);
1111
1112         fmt.setFormatWidth(13);
1113         //              12  34567890123
1114         expectPat(fmt, "AA*^##,##0.00ZZ");
1115
1116         fmt.setFormatWidth(14);
1117         //              12  345678901234
1118         expectPat(fmt, "AA*^###,##0.00ZZ");
1119
1120         fmt.setFormatWidth(15);
1121         //              12  3456789012345
1122         expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1123
1124         fmt.setFormatWidth(16);
1125         //              12  34567890123456
1126         expectPat(fmt, "AA*^#,###,##0.00ZZ");
1127     }
1128
1129     public void TestRegistration() {
1130         final ULocale SRC_LOC = ULocale.FRANCE;
1131         final ULocale SWAP_LOC = ULocale.US;
1132
1133         class TestFactory extends SimpleNumberFormatFactory {
1134             NumberFormat currencyStyle;
1135
1136             TestFactory() {
1137                 super(SRC_LOC, true);
1138                 currencyStyle = NumberFormat.getIntegerInstance(SWAP_LOC);
1139             }
1140
1141             public NumberFormat createFormat(ULocale loc, int formatType) {
1142                 if (formatType == FORMAT_CURRENCY) {
1143                     return currencyStyle;
1144                 }
1145                 return null;
1146             }
1147         }
1148
1149         NumberFormat f0 = NumberFormat.getIntegerInstance(SWAP_LOC);
1150         NumberFormat f1 = NumberFormat.getIntegerInstance(SRC_LOC);
1151         NumberFormat f2 = NumberFormat.getCurrencyInstance(SRC_LOC);
1152         Object key = NumberFormat.registerFactory(new TestFactory());
1153         NumberFormat f3 = NumberFormat.getCurrencyInstance(SRC_LOC);
1154         NumberFormat f4 = NumberFormat.getIntegerInstance(SRC_LOC);
1155         NumberFormat.unregister(key); // restore for other tests
1156         NumberFormat f5 = NumberFormat.getCurrencyInstance(SRC_LOC);
1157
1158         float n = 1234.567f;
1159         logln("f0 swap int: " + f0.format(n));
1160         logln("f1 src int: " + f1.format(n));
1161         logln("f2 src cur: " + f2.format(n));
1162         logln("f3 reg cur: " + f3.format(n));
1163         logln("f4 reg int: " + f4.format(n));
1164         logln("f5 unreg cur: " + f5.format(n));
1165
1166         if (!f3.format(n).equals(f0.format(n))) {
1167             errln("registered service did not match");
1168         }
1169         if (!f4.format(n).equals(f1.format(n))) {
1170             errln("registered service did not inherit");
1171         }
1172         if (!f5.format(n).equals(f2.format(n))) {
1173             errln("unregistered service did not match original");
1174         }
1175     }
1176
1177     public void TestScientific2() {
1178         // jb 2552
1179         DecimalFormat fmt = (DecimalFormat)NumberFormat.getCurrencyInstance();
1180         Number num = new Double(12.34);
1181         expect(fmt, num, "$12.34");
1182         fmt.setScientificNotation(true);
1183         expect(fmt, num, "$1.23E1");
1184         fmt.setScientificNotation(false);
1185         expect(fmt, num, "$12.34");
1186     }
1187
1188     public void TestScientificGrouping() {
1189         // jb 2552
1190         DecimalFormat fmt = new DecimalFormat("###.##E0");
1191         expect(fmt, .01234, "12.3E-3");
1192         expect(fmt, .1234, "123E-3");
1193         expect(fmt, 1.234, "1.23E0");
1194         expect(fmt, 12.34, "12.3E0");
1195         expect(fmt, 123.4, "123E0");
1196         expect(fmt, 1234, "1.23E3");
1197     }
1198
1199     // additional coverage tests
1200
1201     // sigh, can't have static inner classes, why not?
1202
1203     static final class PI extends Number {
1204         /**
1205          * For serialization
1206          */
1207         private static final long serialVersionUID = -305601227915602172L;
1208
1209         private PI() {}
1210         public int intValue() { return (int)Math.PI; }
1211         public long longValue() { return (long)Math.PI; }
1212         public float  floatValue() { return (float)Math.PI; }
1213         public double doubleValue() { return (double)Math.PI; }
1214         public byte byteValue() { return (byte)Math.PI; }
1215         public short shortValue() { return (short)Math.PI; }
1216
1217         public static final Number INSTANCE = new PI();
1218     }
1219
1220     public void TestCoverage() {
1221         NumberFormat fmt = NumberFormat.getNumberInstance(); // default locale
1222         logln(fmt.format(new BigInteger("1234567890987654321234567890987654321", 10)));
1223
1224         fmt = NumberFormat.getScientificInstance(); // default locale
1225
1226         logln(fmt.format(PI.INSTANCE));
1227
1228         try {
1229             logln(fmt.format("12345"));
1230             errln("numberformat of string did not throw exception");
1231         }
1232         catch (Exception e) {
1233             logln("PASS: numberformat of string failed as expected");
1234         }
1235
1236         int hash = fmt.hashCode();
1237         logln("hash code " + hash);
1238
1239         logln("compare to string returns: " + fmt.equals(""));
1240
1241         // For ICU 2.6 - alan
1242         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1243         DecimalFormat df = new DecimalFormat("'*&'' '\u00A4' ''&*' #,##0.00", US);
1244         df.setCurrency(Currency.getInstance("INR"));
1245         expect2(df, 1.0, "*&' \u20B9 '&* 1.00");
1246         expect2(df, -2.0, "-*&' \u20B9 '&* 2.00");
1247         df.applyPattern("#,##0.00 '*&'' '\u00A4' ''&*'");
1248         expect2(df, 2.0, "2.00 *&' \u20B9 '&*");
1249         expect2(df, -1.0, "-1.00 *&' \u20B9 '&*");
1250
1251 //#if defined(ECLIPSE)
1252 //##        BigDecimal r;
1253 //#else
1254         java.math.BigDecimal r;
1255 //#endif
1256         r = df.getRoundingIncrement();
1257         if (r != null) {
1258             errln("FAIL: rounding = " + r + ", expect null");
1259         }
1260
1261         if (df.isScientificNotation()) {
1262             errln("FAIL: isScientificNotation = true, expect false");
1263         }
1264
1265         df.applyPattern("0.00000");
1266         df.setScientificNotation(true);
1267         if (!df.isScientificNotation()) {
1268             errln("FAIL: isScientificNotation = false, expect true");
1269         }
1270         df.setMinimumExponentDigits((byte)2);
1271         if (df.getMinimumExponentDigits() != 2) {
1272             errln("FAIL: getMinimumExponentDigits = " +
1273                   df.getMinimumExponentDigits() + ", expect 2");
1274         }
1275         df.setExponentSignAlwaysShown(true);
1276         if (!df.isExponentSignAlwaysShown()) {
1277             errln("FAIL: isExponentSignAlwaysShown = false, expect true");
1278         }
1279         df.setSecondaryGroupingSize(0);
1280         if (df.getSecondaryGroupingSize() != 0) {
1281             errln("FAIL: getSecondaryGroupingSize = " +
1282                   df.getSecondaryGroupingSize() + ", expect 0");
1283         }
1284         expect2(df, 3.14159, "3.14159E+00");
1285
1286         // DecimalFormatSymbols#getInstance
1287         DecimalFormatSymbols decsym1 = DecimalFormatSymbols.getInstance();
1288         DecimalFormatSymbols decsym2 = new DecimalFormatSymbols();
1289         if (!decsym1.equals(decsym2)) {
1290             errln("FAIL: DecimalFormatSymbols returned by getInstance()" +
1291             "does not match new DecimalFormatSymbols().");
1292         }
1293         decsym1 = DecimalFormatSymbols.getInstance(Locale.JAPAN);
1294         decsym2 = DecimalFormatSymbols.getInstance(ULocale.JAPAN);
1295         if (!decsym1.equals(decsym2)) {
1296             errln("FAIL: DecimalFormatSymbols returned by getInstance(Locale.JAPAN)" +
1297             "does not match the one returned by getInstance(ULocale.JAPAN).");
1298         }
1299
1300         // DecimalFormatSymbols#getAvailableLocales/#getAvailableULocales
1301         Locale[] allLocales = DecimalFormatSymbols.getAvailableLocales();
1302         if (allLocales.length == 0) {
1303             errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1304         } else {
1305             logln("PASS: " + allLocales.length +
1306                     " available locales returned by DecimalFormatSymbols.getAvailableLocales");
1307         }
1308         ULocale[] allULocales = DecimalFormatSymbols.getAvailableULocales();
1309         if (allULocales.length == 0) {
1310             errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1311         } else {
1312             logln("PASS: " + allULocales.length +
1313                     " available locales returned by DecimalFormatSymbols.getAvailableULocales");
1314         }
1315     }
1316
1317     public void TestWhiteSpaceParsing() {
1318         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1319         DecimalFormat fmt = new DecimalFormat("a  b#0c  ", US);
1320         int n = 1234;
1321         expect(fmt, "a b1234c ", n);
1322         expect(fmt, "a   b1234c   ", n);
1323     }
1324
1325     /**
1326      * Test currencies whose display name is a ChoiceFormat.
1327      */
1328     public void TestComplexCurrency() {
1329 //  CLDR No Longer uses complex currency symbols.
1330 //  Skipping this test.
1331 //        Locale loc = new Locale("kn", "IN", "");
1332 //        NumberFormat fmt = NumberFormat.getCurrencyInstance(loc);
1333
1334 //        expect2(fmt, 1.0, "Re.\u00a01.00");
1335 //        expect(fmt, 1.001, "Re.\u00a01.00"); // tricky
1336 //        expect2(fmt, 12345678.0, "Rs.\u00a01,23,45,678.00");
1337 //        expect2(fmt, 0.5, "Rs.\u00a00.50");
1338 //        expect2(fmt, -1.0, "-Re.\u00a01.00");
1339 //        expect2(fmt, -10.0, "-Rs.\u00a010.00");
1340     }
1341
1342     public void TestCurrencyKeyword() {
1343     ULocale locale = new ULocale("th_TH@currency=QQQ");
1344     NumberFormat format = NumberFormat.getCurrencyInstance(locale);
1345     String result = format.format(12.34f);
1346     if (!"QQQ12.34".equals(result)) {
1347         errln("got unexpected currency: " + result);
1348     }
1349     }
1350
1351     /**
1352      * Test alternate numbering systems
1353      */
1354     public void TestNumberingSystems() {
1355
1356         ULocale loc1 = new ULocale("en_US@numbers=thai");
1357         ULocale loc2 = new ULocale("en_US@numbers=hebr");
1358         ULocale loc3 = new ULocale("en_US@numbers=arabext");
1359         ULocale loc4 = new ULocale("hi_IN@numbers=foobar");
1360         ULocale loc5 = new ULocale("ar_EG"); // ar_EG uses arab numbering system
1361         ULocale loc6 = new ULocale("ar_MA"); // ar_MA users latn numbering system
1362         ULocale loc7 = new ULocale("en_US@numbers=hanidec"); // hanidec is a non-contiguous ns
1363         
1364         NumberFormat fmt1 = NumberFormat.getInstance(loc1);
1365         NumberFormat fmt2 = NumberFormat.getInstance(loc2);
1366         NumberFormat fmt3 = NumberFormat.getInstance(loc3);
1367         NumberFormat fmt4 = NumberFormat.getInstance(loc4);
1368         NumberFormat fmt5 = NumberFormat.getInstance(loc5);
1369         NumberFormat fmt6 = NumberFormat.getInstance(loc6);
1370         NumberFormat fmt7 = NumberFormat.getInstance(loc7);
1371         
1372         expect2(fmt1,1234.567,"\u0e51,\u0e52\u0e53\u0e54.\u0e55\u0e56\u0e57");
1373         expect3(fmt2,5678.0,"\u05d4\u05f3\u05ea\u05e8\u05e2\u05f4\u05d7");
1374         expect2(fmt3,1234.567,"\u06f1\u066c\u06f2\u06f3\u06f4\u066b\u06f5\u06f6\u06f7");
1375         expect2(fmt4,1234.567,"\u0967,\u0968\u0969\u096a.\u096b\u096c\u096d");
1376         expect2(fmt5,1234.567,"\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666\u0667");
1377         expect2(fmt6,1234.567,"1.234,567");
1378         expect2(fmt7,1234.567, "\u4e00,\u4e8c\u4e09\u56db.\u4e94\u516d\u4e03");
1379
1380     }
1381
1382     public void Test6816() {
1383         Currency cur1 = Currency.getInstance(new Locale("und", "PH"));
1384
1385         NumberFormat nfmt = NumberFormat.getCurrencyInstance(new Locale("und", "PH"));
1386         DecimalFormatSymbols decsym = ((DecimalFormat)nfmt).getDecimalFormatSymbols();
1387         Currency cur2 = decsym.getCurrency();
1388         
1389         if ( !cur1.getCurrencyCode().equals("PHP") || !cur2.getCurrencyCode().equals("PHP")) {
1390             errln("FAIL: Currencies should match PHP: cur1 = "+cur1.getCurrencyCode()+"; cur2 = "+cur2.getCurrencyCode());
1391         }
1392
1393     }
1394     
1395     public void TestThreadedFormat() {
1396
1397         class FormatTask implements Runnable {
1398             DecimalFormat fmt;
1399             StringBuffer buf;
1400             boolean inc;
1401             float num;
1402
1403             FormatTask(DecimalFormat fmt, int index) {
1404                 this.fmt = fmt;
1405                 this.buf = new StringBuffer();
1406                 this.inc = (index & 0x1) == 0;
1407                 this.num = inc ? 0 : 10000;
1408             }
1409
1410             public void run() {
1411         if (inc) {
1412             while (num < 10000) {
1413             buf.append(fmt.format(num) + "\n");
1414             num += 3.14159;
1415             }
1416         } else {
1417             while (num > 0) {
1418             buf.append(fmt.format(num) + "\n");
1419             num -= 3.14159;
1420             }
1421         }
1422         }
1423
1424         String result() {
1425         return buf.toString();
1426         }
1427     }
1428
1429         DecimalFormat fmt = new DecimalFormat("0.####");
1430         FormatTask[] tasks = new FormatTask[8];
1431         for (int i = 0; i < tasks.length; ++i) {
1432         tasks[i] = new FormatTask(fmt, i);
1433     }
1434
1435     TestUtil.runUntilDone(tasks);
1436
1437         for (int i = 2; i < tasks.length; i++) {
1438         String str1 = tasks[i].result();
1439         String str2 = tasks[i-2].result();
1440             if (!str1.equals(str2)) {
1441                 System.out.println("mismatch at " + i);
1442                 System.out.println(str1);
1443                 System.out.println(str2);
1444                 errln("decimal format thread mismatch");
1445
1446                 break;
1447             }
1448             str1 = str2;
1449         }
1450     }
1451
1452     public void TestPerMill() {
1453         DecimalFormat fmt = new DecimalFormat("###.###\u2030");
1454         assertEquals("0.4857 x ###.###\u2030",
1455                      "485.7\u2030", fmt.format(0.4857));
1456
1457         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.ENGLISH);
1458         sym.setPerMill('m');
1459         DecimalFormat fmt2 = new DecimalFormat("", sym);
1460         fmt2.applyLocalizedPattern("###.###m");
1461         assertEquals("0.4857 x ###.###m",
1462                      "485.7m", fmt2.format(0.4857));
1463     }
1464
1465     public void TestIllegalPatterns() {
1466         // Test cases:
1467         // Prefix with "-:" for illegal patterns
1468         // Prefix with "+:" for legal patterns
1469         String DATA[] = {
1470             // Unquoted special characters in the suffix are illegal
1471             "-:000.000|###",
1472             "+:000.000'|###'",
1473         };
1474         for (int i=0; i<DATA.length; ++i) {
1475             String pat=DATA[i];
1476             boolean valid = pat.charAt(0) == '+';
1477             pat = pat.substring(2);
1478             Exception e = null;
1479             try {
1480                 // locale doesn't matter here
1481                 new DecimalFormat(pat);
1482             } catch (IllegalArgumentException e1) {
1483                 e = e1;
1484             } catch (IndexOutOfBoundsException e1) {
1485                 e = e1;
1486             }
1487             String msg = (e==null) ? "success" : e.getMessage();
1488             if ((e==null) == valid) {
1489                 logln("Ok: pattern \"" + pat + "\": " + msg);
1490             } else {
1491                 errln("FAIL: pattern \"" + pat + "\" should have " +
1492                       (valid?"succeeded":"failed") + "; got " + msg);
1493             }
1494         }
1495     }
1496
1497     /**
1498      * Parse a CurrencyAmount using the given NumberFormat, with
1499      * the 'delim' character separating the number and the currency.
1500      */
1501     private static CurrencyAmount parseCurrencyAmount(String str, NumberFormat fmt,
1502                                                       char delim)
1503         throws ParseException {
1504         int i = str.indexOf(delim);
1505         return new CurrencyAmount(fmt.parse(str.substring(0,i)),
1506                                   Currency.getInstance(str.substring(i+1)));
1507     }
1508
1509     /**
1510      * Return an integer representing the next token from this
1511      * iterator.  The integer will be an index into the given list, or
1512      * -1 if there are no more tokens, or -2 if the token is not on
1513      * the list.
1514      */
1515     private static int keywordIndex(String tok) {
1516         for (int i=0; i<KEYWORDS.length; ++i) {
1517             if (tok.equals(KEYWORDS[i])) {
1518                 return i;
1519             }
1520         }
1521         return -1;
1522     }
1523
1524     private static final String KEYWORDS[] = {
1525         /*0*/ "ref=", // <reference pattern to parse numbers>
1526         /*1*/ "loc=", // <locale for formats>
1527         /*2*/ "f:",   // <pattern or '-'> <number> <exp. string>
1528         /*3*/ "fp:",  // <pattern or '-'> <number> <exp. string> <exp. number>
1529         /*4*/ "rt:",  // <pattern or '-'> <(exp.) number> <(exp.) string>
1530         /*5*/ "p:",   // <pattern or '-'> <string> <exp. number>
1531         /*6*/ "perr:", // <pattern or '-'> <invalid string>
1532         /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1533         /*8*/ "fpc:", // <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1534         /*9*/ "strict=", // true or false
1535     };
1536
1537     public void TestCases() {
1538         String caseFileName = "NumberFormatTestCases.txt";
1539         java.io.InputStream is = NumberFormatTest.class.getResourceAsStream(caseFileName);
1540
1541         ResourceReader reader = new ResourceReader(is, caseFileName, "utf-8");
1542         TokenIterator tokens = new TokenIterator(reader);
1543
1544         Locale loc = new Locale("en", "US", "");
1545         DecimalFormat ref = null, fmt = null;
1546         MeasureFormat mfmt = null;
1547         String pat = null, str = null, mloc = null;
1548         boolean strict = false;
1549
1550         try {
1551             for (;;) {
1552                 String tok = tokens.next();
1553                 if (tok == null) {
1554                     break;
1555                 }
1556                 String where = "(" + tokens.getLineNumber() + ") ";
1557                 int cmd = keywordIndex(tok);
1558                 switch (cmd) {
1559                 case 0:
1560                     // ref= <reference pattern>
1561                     ref = new DecimalFormat(tokens.next(),
1562                                             new DecimalFormatSymbols(Locale.US));
1563                     ref.setParseStrict(strict);
1564                     logln("Setting reference pattern to:\t" + ref);
1565                     break;
1566                 case 1:
1567                     // loc= <locale>
1568                     loc = LocaleUtility.getLocaleFromName(tokens.next());
1569                     pat = ((DecimalFormat) NumberFormat.getInstance(loc)).toPattern();
1570                     logln("Setting locale to:\t" + loc + ", \tand pattern to:\t" + pat);
1571                     break;
1572                 case 2: // f:
1573                 case 3: // fp:
1574                 case 4: // rt:
1575                 case 5: // p:
1576                     tok = tokens.next();
1577                     if (!tok.equals("-")) {
1578                         pat = tok;
1579                     }
1580                     try {
1581                         fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc));
1582                         fmt.setParseStrict(strict);
1583                     } catch (IllegalArgumentException iae) {
1584                         errln(where + "Pattern \"" + pat + '"');
1585                         iae.printStackTrace();
1586                         tokens.next(); // consume remaining tokens
1587                         //tokens.next();
1588                         if (cmd == 3) tokens.next();
1589                         continue;
1590                     }
1591                    str = null;
1592                     try {
1593                         if (cmd == 2 || cmd == 3 || cmd == 4) {
1594                             // f: <pattern or '-'> <number> <exp. string>
1595                             // fp: <pattern or '-'> <number> <exp. string> <exp. number>
1596                             // rt: <pattern or '-'> <number> <string>
1597                             String num = tokens.next();
1598                             str = tokens.next();
1599                             Number n = (Number) ref.parse(num);
1600                             assertEquals(where + '"' + pat + "\".format(" + num + ")",
1601                                          str, fmt.format(n));
1602                             if (cmd == 3) { // fp:
1603                                 n = (Number) ref.parse(tokens.next());
1604                             }
1605                             if (cmd != 2) { // != f:
1606                                 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1607                                              n, fmt.parse(str));
1608                             }
1609                         }
1610                         // p: <pattern or '-'> <string to parse> <exp. number>
1611                         else {
1612                             str = tokens.next();
1613                             String expstr = tokens.next();
1614                             Number parsed = fmt.parse(str);
1615                             Number exp = (Number) ref.parse(expstr);
1616                             assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1617                                          exp, parsed);
1618                         }
1619                     } catch (ParseException e) {
1620                         errln(where + '"' + pat + "\".parse(\"" + str +
1621                               "\") threw an exception");
1622                         e.printStackTrace();
1623                     }
1624                     break;
1625                 case 6:
1626                     // perr: <pattern or '-'> <invalid string>
1627                     errln("Under construction");
1628                     return;
1629                 case 7:
1630                     // pat: <pattern> <exp. toPattern, or '-' or 'err'>
1631                     String testpat = tokens.next();
1632                     String exppat  = tokens.next();
1633                     boolean err    = exppat.equals("err");
1634                     if (testpat.equals("-")) {
1635                         if (err) {
1636                             errln("Invalid command \"pat: - err\" at " +  tokens.describePosition());
1637                             continue;
1638                         }
1639                         testpat = pat;
1640                     }
1641                     if (exppat.equals("-")) exppat = testpat;
1642                     try {
1643                         DecimalFormat f = null;
1644                         if (testpat == pat) { // [sic]
1645                             f = fmt;
1646                         } else {
1647                             f = new DecimalFormat(testpat);
1648                             f.setParseStrict(strict);
1649                         }
1650                         if (err) {
1651                             errln(where + "Invalid pattern \"" + testpat +
1652                                   "\" was accepted");
1653                         } else {
1654                             assertEquals(where + '"' + testpat + "\".toPattern()",
1655                                          exppat, f.toPattern());
1656                         }
1657                     } catch (IllegalArgumentException iae2) {
1658                         if (err) {
1659                             logln("Ok: " + where + "Invalid pattern \"" + testpat +
1660                                   "\" threw an exception");
1661                         } else {
1662                             errln(where + "Valid pattern \"" + testpat +
1663                                   "\" threw an exception");
1664                             iae2.printStackTrace();
1665                         }
1666                     }
1667                     break;
1668                 case 8: // fpc:
1669                     tok = tokens.next();
1670                     if (!tok.equals("-")) {
1671                         mloc = tok;
1672                         ULocale l = new ULocale(mloc);
1673                         try {
1674                             mfmt = MeasureFormat.getCurrencyFormat(l);
1675                         } catch (IllegalArgumentException iae) {
1676                             errln(where + "Loc \"" + tok + '"');
1677                             iae.printStackTrace();
1678                             tokens.next(); // consume remaining tokens
1679                             tokens.next();
1680                             tokens.next();
1681                             continue;
1682                         }
1683                     }
1684                     str = null;
1685                     try {
1686                         // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1687                         String currAmt = tokens.next();
1688                         str = tokens.next();
1689                         CurrencyAmount target = parseCurrencyAmount(currAmt, ref, '/');
1690                         String formatResult = mfmt.format(target);
1691                         assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
1692                                      str, formatResult);
1693                         target = parseCurrencyAmount(tokens.next(), ref, '/');
1694                         CurrencyAmount parseResult = (CurrencyAmount) mfmt.parseObject(str);
1695                         assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
1696                                      target, parseResult);
1697                     } catch (ParseException e) {
1698                         errln(where + '"' + pat + "\".parse(\"" + str +
1699                               "\") threw an exception");
1700                         e.printStackTrace();
1701                     }
1702                     break;
1703                 case 9: // strict= true or false
1704                     strict = "true".equalsIgnoreCase(tokens.next());
1705                     logln("Setting strict to:\t" + strict);
1706                     break;
1707                 case -1:
1708                     errln("Unknown command \"" + tok + "\" at " + tokens.describePosition());
1709                     return;
1710                 }
1711             }
1712         } catch (java.io.IOException e) {
1713             throw new RuntimeException(e);
1714         }
1715     }
1716
1717     public void TestRounding() {
1718         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
1719         if (false) { // for debugging specific value
1720             nf.setRoundingMode(BigDecimal.ROUND_HALF_UP);
1721             checkRounding(nf, new BigDecimal("300.0300000000"), 0, new BigDecimal("0.020000000"));
1722         }
1723         // full tests
1724         int[] roundingIncrements = {1, 2, 5, 20, 50, 100};
1725         int[] testValues = {0, 300};
1726         for (int j = 0; j < testValues.length; ++j) {
1727             for (int mode = BigDecimal.ROUND_UP; mode < BigDecimal.ROUND_HALF_EVEN; ++mode) {
1728                 nf.setRoundingMode(mode);
1729                 for (int increment = 0; increment < roundingIncrements.length; ++increment) {
1730                     BigDecimal base = new BigDecimal(testValues[j]);
1731                     BigDecimal rInc = new BigDecimal(roundingIncrements[increment]);
1732                     checkRounding(nf,  base, 20, rInc);
1733                     rInc = new BigDecimal("1.000000000").divide(rInc);
1734                     checkRounding(nf,  base, 20, rInc);
1735                 }
1736             }
1737         }
1738     }
1739
1740     public void TestBigDecimalRounding() {
1741         String figure = "50.000000004"; 
1742         Double dbl = new Double(figure); 
1743         BigDecimal dec = new BigDecimal(figure);
1744
1745         DecimalFormat f = (DecimalFormat) NumberFormat.getInstance(); 
1746         f.applyPattern("00.00######");
1747
1748         assertEquals("double format", "50.00", f.format(dbl));
1749         assertEquals("bigdec format", "50.00", f.format(dec));
1750
1751         int maxFracDigits = f.getMaximumFractionDigits();
1752         BigDecimal roundingIncrement = new BigDecimal("1").movePointLeft(maxFracDigits);
1753
1754         f.setRoundingIncrement(roundingIncrement);
1755         f.setRoundingMode(BigDecimal.ROUND_DOWN); 
1756         assertEquals("Rounding down", f.format(dbl), f.format(dec));
1757
1758         f.setRoundingIncrement(roundingIncrement);
1759         f.setRoundingMode(BigDecimal.ROUND_HALF_UP); 
1760         assertEquals("Rounding half up", f.format(dbl), f.format(dec));
1761     }
1762
1763     void checkRounding(DecimalFormat nf, BigDecimal base, int iterations, BigDecimal increment) {
1764         nf.setRoundingIncrement(increment.toBigDecimal());
1765         BigDecimal lastParsed = new BigDecimal(Integer.MIN_VALUE); // used to make sure that rounding is monotonic
1766         for (int i = -iterations; i <= iterations; ++i) {
1767             BigDecimal iValue = base.add(increment.multiply(new BigDecimal(i)).movePointLeft(1));
1768             BigDecimal smallIncrement = new BigDecimal("0.00000001");
1769             if (iValue.signum() != 0) {
1770                 smallIncrement.multiply(iValue); // scale unless zero
1771             }
1772             // we not only test the value, but some values in a small range around it.
1773             lastParsed = checkRound(nf, iValue.subtract(smallIncrement), lastParsed);
1774             lastParsed = checkRound(nf, iValue, lastParsed);
1775             lastParsed = checkRound(nf, iValue.add(smallIncrement), lastParsed);
1776         }
1777     }
1778
1779     private BigDecimal checkRound(DecimalFormat nf, BigDecimal iValue, BigDecimal lastParsed) {
1780         String formatedBigDecimal = nf.format(iValue);
1781         String formattedDouble = nf.format(iValue.doubleValue());
1782         if (!equalButForTrailingZeros(formatedBigDecimal, formattedDouble)) {
1783
1784             errln("Failure at: " + iValue + " (" + iValue.doubleValue() + ")"
1785                   + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1786                   + ",\tRounding-increment: " + nf.getRoundingIncrement()
1787                   + ",\tdouble: " + formattedDouble
1788                   + ",\tBigDecimal: " + formatedBigDecimal);
1789                   
1790         } else {
1791             logln("Value: " + iValue
1792                   + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1793                   + ",\tRounding-increment: " + nf.getRoundingIncrement()
1794                   + ",\tdouble: " + formattedDouble
1795                   + ",\tBigDecimal: " + formatedBigDecimal);
1796         }
1797         try {
1798             // Number should have compareTo(...)
1799             BigDecimal parsed = toBigDecimal(nf.parse(formatedBigDecimal));
1800             if (lastParsed.compareTo(parsed) > 0) {
1801                 errln("Rounding wrong direction!: " + lastParsed + " > " + parsed);
1802             }
1803             lastParsed = parsed;
1804         } catch (ParseException e) {
1805             errln("Parse Failure with: " + formatedBigDecimal);
1806         }
1807         return lastParsed;
1808     }
1809
1810     static BigDecimal toBigDecimal(Number number) {
1811         return number instanceof BigDecimal ? (BigDecimal) number
1812             : number instanceof BigInteger ? new BigDecimal((BigInteger)number)
1813             : number instanceof java.math.BigDecimal ? new BigDecimal((java.math.BigDecimal)number)
1814             : number instanceof Double ? new BigDecimal(number.doubleValue())
1815             : number instanceof Float ? new BigDecimal(number.floatValue())
1816             : new BigDecimal(number.longValue());
1817     }
1818
1819     static String[] roundingModeNames = {
1820         "ROUND_UP", "ROUND_DOWN", "ROUND_CEILING", "ROUND_FLOOR",
1821         "ROUND_HALF_UP", "ROUND_HALF_DOWN", "ROUND_HALF_EVEN",
1822         "ROUND_UNNECESSARY"
1823     };
1824
1825     private static boolean equalButForTrailingZeros(String formatted1, String formatted2) {
1826         if (formatted1.length() == formatted2.length()) return formatted1.equals(formatted2);
1827         return stripFinalZeros(formatted1).equals(stripFinalZeros(formatted2));
1828     }
1829
1830     private static String stripFinalZeros(String formatted) {
1831         int len1 = formatted.length();
1832         char ch;
1833         while (len1 > 0 && ((ch = formatted.charAt(len1-1)) == '0' || ch == '.')) --len1;
1834         if (len1==1 && ((ch = formatted.charAt(len1-1)) == '-')) --len1;
1835         return formatted.substring(0,len1);
1836     }
1837
1838     //------------------------------------------------------------------
1839     // Support methods
1840     //------------------------------------------------------------------
1841
1842     // Format-Parse test
1843     public void expect2(NumberFormat fmt, Number n, String exp) {
1844         // Don't round-trip format test, since we explicitly do it
1845         expect(fmt, n, exp, false);
1846         expect(fmt, exp, n);
1847     }
1848     // Format-Parse test
1849     public void expect3(NumberFormat fmt, Number n, String exp) {
1850         // Don't round-trip format test, since we explicitly do it
1851         expect_rbnf(fmt, n, exp, false);
1852         expect_rbnf(fmt, exp, n);
1853     }
1854
1855     // Format-Parse test (convenience)
1856     public void expect2(NumberFormat fmt, double n, String exp) {
1857         expect2(fmt, new Double(n), exp);
1858     }
1859     // Format-Parse test (convenience)
1860     public void expect3(NumberFormat fmt, double n, String exp) {
1861         expect3(fmt, new Double(n), exp);
1862     }
1863
1864     // Format-Parse test (convenience)
1865     public void expect2(NumberFormat fmt, long n, String exp) {
1866         expect2(fmt, new Long(n), exp);
1867     }
1868     // Format-Parse test (convenience)
1869     public void expect3(NumberFormat fmt, long n, String exp) {
1870         expect3(fmt, new Long(n), exp);
1871     }
1872
1873     // Format test
1874     public void expect(NumberFormat fmt, Number n, String exp, boolean rt) {
1875         StringBuffer saw = new StringBuffer();
1876         FieldPosition pos = new FieldPosition(0);
1877         fmt.format(n, saw, pos);
1878         String pat = ((DecimalFormat)fmt).toPattern();
1879         if (saw.toString().equals(exp)) {
1880             logln("Ok   " + n + " x " +
1881                   pat + " = \"" +
1882                   saw + "\"");
1883             // We should be able to round-trip the formatted string =>
1884             // number => string (but not the other way around: number
1885             // => string => number2, might have number2 != number):
1886             if (rt) {
1887                 try {
1888                     Number n2 = fmt.parse(exp);
1889                     StringBuffer saw2 = new StringBuffer();
1890                     fmt.format(n2, saw2, pos);
1891                     if (!saw2.toString().equals(exp)) {
1892                         errln("FAIL \"" + exp + "\" => " + n2 +
1893                               " => \"" + saw2 + '"');
1894                     }
1895                 } catch (ParseException e) {
1896                     errln(e.getMessage());
1897                     return;
1898                 }
1899             }
1900         } else {
1901             errln("FAIL " + n + " x " +
1902                   pat + " = \"" +
1903                   saw + "\", expected \"" + exp + "\"");
1904         }
1905     }
1906     // Format test
1907     public void expect_rbnf(NumberFormat fmt, Number n, String exp, boolean rt) {
1908         StringBuffer saw = new StringBuffer();
1909         FieldPosition pos = new FieldPosition(0);
1910         fmt.format(n, saw, pos);
1911         if (saw.toString().equals(exp)) {
1912             logln("Ok   " + n + " = \"" +
1913                   saw + "\"");
1914             // We should be able to round-trip the formatted string =>
1915             // number => string (but not the other way around: number
1916             // => string => number2, might have number2 != number):
1917             if (rt) {
1918                 try {
1919                     Number n2 = fmt.parse(exp);
1920                     StringBuffer saw2 = new StringBuffer();
1921                     fmt.format(n2, saw2, pos);
1922                     if (!saw2.toString().equals(exp)) {
1923                         errln("FAIL \"" + exp + "\" => " + n2 +
1924                               " => \"" + saw2 + '"');
1925                     }
1926                 } catch (ParseException e) {
1927                     errln(e.getMessage());
1928                     return;
1929                 }
1930             }
1931         } else {
1932             errln("FAIL " + n + " = \"" +
1933                   saw + "\", expected \"" + exp + "\"");
1934         }
1935     }
1936
1937     // Format test (convenience)
1938     public void expect(NumberFormat fmt, Number n, String exp) {
1939         expect(fmt, n, exp, true);
1940     }
1941
1942     // Format test (convenience)
1943     public void expect(NumberFormat fmt, double n, String exp) {
1944         expect(fmt, new Double(n), exp);
1945     }
1946
1947     // Format test (convenience)
1948     public void expect(NumberFormat fmt, long n, String exp) {
1949         expect(fmt, new Long(n), exp);
1950     }
1951
1952     // Parse test
1953     public void expect(NumberFormat fmt, String str, Number n) {
1954         Number num = null;
1955         try {
1956             num = (Number) fmt.parse(str);
1957         } catch (ParseException e) {
1958             errln(e.getMessage());
1959             return;
1960         }
1961         String pat = ((DecimalFormat)fmt).toPattern();
1962         // A little tricky here -- make sure Double(12345.0) and
1963         // Long(12345) match.
1964         if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1965             logln("Ok   \"" + str + "\" x " +
1966                   pat + " = " +
1967                   num);
1968         } else {
1969             errln("FAIL \"" + str + "\" x " +
1970                   pat + " = " +
1971                   num + ", expected " + n);
1972         }
1973     }
1974
1975     // Parse test
1976     public void expect_rbnf(NumberFormat fmt, String str, Number n) {
1977         Number num = null;
1978         try {
1979             num = (Number) fmt.parse(str);
1980         } catch (ParseException e) {
1981             errln(e.getMessage());
1982             return;
1983         }
1984         // A little tricky here -- make sure Double(12345.0) and
1985         // Long(12345) match.
1986         if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1987             logln("Ok   \"" + str + " = " +
1988                   num);
1989         } else {
1990             errln("FAIL \"" + str + " = " +
1991                   num + ", expected " + n);
1992         }
1993     }
1994
1995     // Parse test (convenience)
1996     public void expect(NumberFormat fmt, String str, double n) {
1997         expect(fmt, str, new Double(n));
1998     }
1999
2000     // Parse test (convenience)
2001     public void expect(NumberFormat fmt, String str, long n) {
2002         expect(fmt, str, new Long(n));
2003     }
2004
2005     private void expectCurrency(NumberFormat nf, Currency curr,
2006                                 double value, String string) {
2007         DecimalFormat fmt = (DecimalFormat) nf;
2008         if (curr != null) {
2009             fmt.setCurrency(curr);
2010         }
2011         String s = fmt.format(value).replace('\u00A0', ' ');
2012
2013         if (s.equals(string)) {
2014             logln("Ok: " + value + " x " + curr + " => " + s);
2015         } else {
2016             errln("FAIL: " + value + " x " + curr + " => " + s +
2017                   ", expected " + string);
2018         }
2019     }
2020
2021     public void expectPad(DecimalFormat fmt, String pat, int pos) {
2022         expectPad(fmt, pat, pos, 0, (char)0);
2023     }
2024
2025     public void expectPad(DecimalFormat fmt, final String pat, int pos, int width, final char pad) {
2026         int apos = 0, awidth = 0;
2027         char apadStr;
2028         try {
2029             fmt.applyPattern(pat);
2030             apos = fmt.getPadPosition();
2031             awidth = fmt.getFormatWidth();
2032             apadStr = fmt.getPadCharacter();
2033         } catch (Exception e) {
2034             apos = -1;
2035             awidth = width;
2036             apadStr = pad;
2037         }
2038
2039         if (apos == pos && awidth == width && apadStr == pad) {
2040             logln("Ok   \"" + pat + "\" pos="
2041                     + apos + ((pos == -1) ? "" : " width=" + awidth + " pad=" + apadStr));
2042         } else {
2043             errln("FAIL \"" + pat + "\" pos=" + apos + " width="
2044                     + awidth + " pad=" + apadStr + ", expected "
2045                     + pos + " " + width + " " + pad);
2046         }
2047     }
2048
2049     public void expectPat(DecimalFormat fmt, final String exp) {
2050         String pat = fmt.toPattern();
2051         if (pat.equals(exp)) {
2052             logln("Ok   \"" + pat + "\"");
2053         } else {
2054             errln("FAIL \"" + pat + "\", expected \"" + exp + "\"");
2055         }
2056     }
2057
2058     public void TestJB3832(){
2059         ULocale locale = new ULocale("pt_PT@currency=PTE");
2060         NumberFormat format = NumberFormat.getCurrencyInstance(locale);
2061         Currency curr = Currency.getInstance(locale);
2062         logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
2063         CurrencyAmount cAmt = new CurrencyAmount(1150.50, curr);
2064         logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
2065         String str = format.format(cAmt);
2066         String expected = "1,150$50\u00a0Esc.";
2067         if(!expected.equals(str)){
2068             errln("Did not get the expected output Expected: "+expected+" Got: "+ str);
2069         }
2070     }
2071
2072     public void TestStrictParse() {
2073         String[] pass = {
2074             "0",           // single zero before end of text is not leading
2075             "0 ",          // single zero at end of number is not leading
2076             "0.",          // single zero before period (or decimal, it's ambiguous) is not leading
2077             "0,",          // single zero before comma (not group separator) is not leading
2078             "0.0",         // single zero before decimal followed by digit is not leading
2079             "0. ",         // same as above before period (or decimal) is not leading
2080             "0.100,5",     // comma stops parse of decimal (no grouping)
2081             ".00",         // leading decimal is ok, even with zeros
2082             "1234567",     // group separators are not required
2083             "12345, ",     // comma not followed by digit is not a group separator, but end of number
2084             "1,234, ",     // if group separator is present, group sizes must be appropriate
2085             "1,234,567",   // ...secondary too
2086             "0E",          // an exponent not followed by zero or digits is not an exponent
2087             "00",          // leading zero before zero - used to be error - see ticket #7913
2088             "012",         // leading zero before digit - used to be error - see ticket #7913
2089             "0,456",       // leading zero before group separator - used to be error - see ticket #7913
2090         };
2091         String[] fail = {
2092             "1,2",       // wrong number of digits after group separator
2093             ",0",        // leading group separator before zero
2094             ",1",        // leading group separator before digit
2095             ",.02",      // leading group separator before decimal
2096             "1,.02",     // group separator before decimal
2097             "1,,200",    // multiple group separators
2098             "1,45",      // wrong number of digits in primary group
2099             "1,45 that", // wrong number of digits in primary group
2100             "1,45.34",   // wrong number of digits in primary group
2101             "1234,567",  // wrong number of digits in secondary group
2102             "12,34,567", // wrong number of digits in secondary group
2103             "1,23,456,7890", // wrong number of digits in primary and secondary groups
2104         };
2105
2106         DecimalFormat nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
2107         runStrictParseBatch(nf, pass, fail);
2108
2109         String[] scientificPass = {
2110             "0E2",      // single zero before exponent is ok
2111             "1234E2",   // any number of digits before exponent is ok
2112             "1,234E",   // an exponent string not followed by zero or digits is not an exponent
2113             "00E2",     // leading zeroes now allowed in strict mode - see ticket #
2114         };
2115         String[] scientificFail = {
2116             "1,234E2",  // group separators with exponent fail
2117         };
2118
2119         nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
2120         runStrictParseBatch(nf, scientificPass, scientificFail);
2121
2122         String[] mixedPass = {
2123             "12,34,567",
2124             "12,34,567,",
2125             "12,34,567, that",
2126             "12,34,567 that",
2127         };
2128         String[] mixedFail = {
2129             "12,34,56",
2130             "12,34,56,",
2131             "12,34,56, that ",
2132             "12,34,56 that",
2133         };
2134
2135         nf = new DecimalFormat("#,##,##0.#");
2136         runStrictParseBatch(nf, mixedPass, mixedFail);
2137     }
2138
2139     void runStrictParseBatch(DecimalFormat nf, String[] pass, String[] fail) {
2140         nf.setParseStrict(false);
2141         runStrictParseTests("should pass", nf, pass, true);
2142         runStrictParseTests("should also pass", nf, fail, true);
2143         nf.setParseStrict(true);
2144         runStrictParseTests("should still pass", nf, pass, true);
2145         runStrictParseTests("should fail", nf, fail, false);
2146     }
2147
2148     void runStrictParseTests(String msg, DecimalFormat nf, String[] tests, boolean pass) {
2149         logln("");
2150         logln("pattern: '" + nf.toPattern() + "'");
2151         logln(msg);
2152         for (int i = 0; i < tests.length; ++i) {
2153             String str = tests[i];
2154             ParsePosition pp = new ParsePosition(0);
2155             Number n = nf.parse(str, pp);
2156             String formatted = n != null ? nf.format(n) : "null";
2157             String err = pp.getErrorIndex() == -1 ? "" : "(error at " + pp.getErrorIndex() + ")";
2158             if ((err.length() == 0) != pass) {
2159                 errln("'" + str + "' parsed '" +
2160                       str.substring(0, pp.getIndex()) +
2161                       "' returned " + n + " formats to '" +
2162                       formatted + "' " + err);
2163             } else {
2164                 if (err.length() > 0) {
2165                     err = "got expected " + err;
2166                 }
2167                 logln("'" + str + "' parsed '" +
2168                       str.substring(0, pp.getIndex()) +
2169                       "' returned " + n + " formats to '" +
2170                       formatted + "' " + err);
2171             }
2172         }
2173     }
2174     public void TestJB5251(){
2175         //save default locale
2176         ULocale defaultLocale = ULocale.getDefault();
2177         ULocale.setDefault(new ULocale("qr_QR"));
2178         try {
2179             NumberFormat.getInstance();
2180         }
2181         catch (Exception e) {
2182             errln("Numberformat threw exception for non-existent locale. It should use the default.");
2183         }
2184         //reset default locale
2185         ULocale.setDefault(defaultLocale);
2186     }
2187
2188     public void TestParseReturnType() {
2189         String[] defaultNonBigDecimals = {
2190             "123",      // Long
2191             "123.0",    // Long
2192             "0.0",      // Long
2193             "12345678901234567890"      // BigInteger
2194         };
2195
2196         String[] doubles = {
2197             "-0.0",
2198             "NaN",
2199             "\u221E"    // Infinity
2200         };
2201
2202         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2203         DecimalFormat nf = new DecimalFormat("#.#", sym);
2204
2205         if (nf.isParseBigDecimal()) {
2206             errln("FAIL: isParseDecimal() must return false by default");
2207         }
2208
2209         // isParseBigDecimal() is false
2210         for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2211             try {
2212                 Number n = nf.parse(defaultNonBigDecimals[i]);
2213                 if (n instanceof BigDecimal) {
2214                     errln("FAIL: parse returns BigDecimal instance");
2215                 }
2216             } catch (ParseException e) {
2217                 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2218             }
2219         }
2220         // parse results for doubls must be always Double
2221         for (int i = 0; i < doubles.length; i++) {
2222             try {
2223                 Number n = nf.parse(doubles[i]);
2224                 if (!(n instanceof Double)) {
2225                     errln("FAIL: parse does not return Double instance");
2226                 }
2227             } catch (ParseException e) {
2228                 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2229             }
2230         }
2231
2232         // force this DecimalFormat to return BigDecimal
2233         nf.setParseBigDecimal(true);
2234         if (!nf.isParseBigDecimal()) {
2235             errln("FAIL: isParseBigDecimal() must return true");
2236         }
2237
2238         // isParseBigDecimal() is true
2239         for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2240             try {
2241                 Number n = nf.parse(defaultNonBigDecimals[i]);
2242                 if (!(n instanceof BigDecimal)) {
2243                     errln("FAIL: parse does not return BigDecimal instance");
2244                 }
2245             } catch (ParseException e) {
2246                 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2247             }
2248         }
2249         // parse results for doubls must be always Double
2250         for (int i = 0; i < doubles.length; i++) {
2251             try {
2252                 Number n = nf.parse(doubles[i]);
2253                 if (!(n instanceof Double)) {
2254                     errln("FAIL: parse does not return Double instance");
2255                 }
2256             } catch (ParseException e) {
2257                 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2258             }
2259         }
2260     }
2261
2262     public void TestNonpositiveMultiplier() {
2263         DecimalFormat df = new DecimalFormat("0");
2264
2265         // test zero multiplier
2266
2267         try {
2268             df.setMultiplier(0);
2269
2270             // bad
2271             errln("DecimalFormat.setMultiplier(0) did not throw an IllegalArgumentException");
2272         } catch (IllegalArgumentException ex) {
2273             // good
2274         }
2275
2276         // test negative multiplier
2277
2278         try {
2279             df.setMultiplier(-1);
2280
2281             if (df.getMultiplier() != -1) {
2282                 errln("DecimalFormat.setMultiplier(-1) did not change the multiplier to -1");
2283                 return;
2284             }
2285
2286             // good
2287         } catch (IllegalArgumentException ex) {
2288             // bad
2289             errln("DecimalFormat.setMultiplier(-1) threw an IllegalArgumentException");
2290             return;
2291         }
2292
2293         expect(df, "1122.123", -1122.123);
2294         expect(df, "-1122.123", 1122.123);
2295         expect(df, "1.2", -1.2);
2296         expect(df, "-1.2", 1.2);
2297
2298         expect2(df, Long.MAX_VALUE, BigInteger.valueOf(Long.MAX_VALUE).negate().toString());
2299         expect2(df, Long.MIN_VALUE, BigInteger.valueOf(Long.MIN_VALUE).negate().toString());
2300         expect2(df, Long.MAX_VALUE / 2, BigInteger.valueOf(Long.MAX_VALUE / 2).negate().toString());
2301         expect2(df, Long.MIN_VALUE / 2, BigInteger.valueOf(Long.MIN_VALUE / 2).negate().toString());
2302
2303         expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2304         expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2305
2306         expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2307         expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2308     }
2309
2310     public void TestJB5358() {
2311         int numThreads = 10;
2312         String numstr = "12345";
2313         double expected = 12345;
2314         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2315         DecimalFormat fmt = new DecimalFormat("#.#", sym);
2316         ArrayList errors = new ArrayList();
2317
2318         ParseThreadJB5358[] threads = new ParseThreadJB5358[numThreads];
2319         for (int i = 0; i < numThreads; i++) {
2320             threads[i] = new ParseThreadJB5358((DecimalFormat)fmt.clone(), numstr, expected, errors);
2321             threads[i].start();
2322         }
2323         for (int i = 0; i < numThreads; i++) {
2324             try {
2325                 threads[i].join();
2326             } catch (InterruptedException ie) {
2327                 ie.printStackTrace();
2328             }
2329         }
2330         if (errors.size() != 0) {
2331             StringBuffer errBuf = new StringBuffer();
2332             for (int i = 0; i < errors.size(); i++) {
2333                 errBuf.append((String)errors.get(i));
2334                 errBuf.append("\n");
2335             }
2336             errln("FAIL: " + errBuf);
2337         }
2338     }
2339
2340     static private class ParseThreadJB5358 extends Thread {
2341         private DecimalFormat decfmt;
2342         private String numstr;
2343         private double expect;
2344         private ArrayList errors;
2345
2346         public ParseThreadJB5358(DecimalFormat decfmt, String numstr, double expect, ArrayList errors) {
2347             this.decfmt = decfmt;
2348             this.numstr = numstr;
2349             this.expect = expect;
2350             this.errors = errors;
2351         }
2352
2353         public void run() {
2354             for (int i = 0; i < 10000; i++) {
2355                 try {
2356                     Number n = decfmt.parse(numstr);
2357                     if (n.doubleValue() != expect) {
2358                         synchronized(errors) {
2359                             errors.add(new String("Bad parse result - expected:" + expect + " actual:" + n.doubleValue()));
2360                         }
2361                     }
2362                 } catch (Throwable t) {
2363                     synchronized(errors) {
2364                         errors.add(new String(t.getClass().getName() + " - " + t.getMessage()));
2365                     }
2366                 }
2367             }
2368         }
2369     }
2370     
2371     public void TestSetCurrency() {
2372         DecimalFormatSymbols decf1 = DecimalFormatSymbols.getInstance(ULocale.US);
2373         DecimalFormatSymbols decf2 = DecimalFormatSymbols.getInstance(ULocale.US);
2374         decf2.setCurrencySymbol("UKD");
2375         DecimalFormat format1 = new DecimalFormat("000.000", decf1);
2376         DecimalFormat format2 = new DecimalFormat("000.000", decf2);
2377         Currency euro = Currency.getInstance("EUR");
2378         format1.setCurrency(euro);
2379         format2.setCurrency(euro);
2380         assertEquals("Reset with currency symbol", format1, format2);
2381     }
2382     
2383     /*
2384      * Testing the method public StringBuffer format(Object number, ...)
2385      */
2386     public void TestFormat() {
2387         NumberFormat nf = NumberFormat.getInstance();
2388         StringBuffer sb = new StringBuffer("dummy");
2389         FieldPosition fp = new FieldPosition(0);
2390
2391         // Tests when "if (number instanceof Long)" is true
2392         try {
2393             nf.format((Object)new Long("0"), sb, fp);
2394         } catch (Exception e) {
2395             errln("NumberFormat.format(Object number, ...) was not suppose to "
2396                     + "return an exception for a Long object. Error: " + e);
2397         }
2398
2399         // Tests when "else if (number instanceof BigInteger)" is true
2400         try {
2401             nf.format((Object)new BigInteger("0"), sb, fp);
2402         } catch (Exception e) {
2403             errln("NumberFormat.format(Object number, ...) was not suppose to "
2404                     + "return an exception for a BigInteger object. Error: " + e);
2405         }
2406
2407         // Tests when "else if (number instanceof java.math.BigDecimal)" is true
2408         try {
2409             nf.format((Object)new java.math.BigDecimal("0"), sb, fp);
2410         } catch (Exception e) {
2411             errln("NumberFormat.format(Object number, ...) was not suppose to "
2412                     + "return an exception for a java.math.BigDecimal object. Error: " + e);
2413         }
2414
2415         // Tests when "else if (number instanceof com.ibm.icu.math.BigDecimal)" is true
2416         try {
2417             nf.format((Object)new com.ibm.icu.math.BigDecimal("0"), sb, fp);
2418         } catch (Exception e) {
2419             errln("NumberFormat.format(Object number, ...) was not suppose to "
2420                     + "return an exception for a com.ibm.icu.math.BigDecimal object. Error: " + e);
2421         }
2422
2423         // Tests when "else if (number instanceof CurrencyAmount)" is true
2424         try {
2425             CurrencyAmount ca = new CurrencyAmount(0.0, Currency.getInstance(new ULocale("en_US")));
2426             nf.format((Object)ca, sb, fp);
2427         } catch (Exception e) {
2428             errln("NumberFormat.format(Object number, ...) was not suppose to "
2429                     + "return an exception for a CurrencyAmount object. Error: " + e);
2430         }
2431
2432         // Tests when "else if (number instanceof Number)" is true
2433         try {
2434             nf.format((Object)(Number) 0.0, sb, fp);
2435         } catch (Exception e) {
2436             errln("NumberFormat.format(Object number, ...) was not suppose to "
2437                     + "to return an exception for a Number object. Error: " + e);
2438         }
2439
2440         // Tests when "else" is true
2441         try {
2442             nf.format(new Object(), sb, fp);
2443             errln("NumberFormat.format(Object number, ...) was suppose to "
2444                     + "return an exception for an invalid object.");
2445         } catch (Exception e) {
2446         }
2447
2448         try {
2449             nf.format(new String("dummy"), sb, fp);
2450             errln("NumberFormat.format(Object number, ...) was suppose to "
2451                     + "return an exception for an invalid object.");
2452         } catch (Exception e) {
2453         }
2454     }
2455
2456     /*
2457      * Tests the method public final static NumberFormat getInstance(int style) public static NumberFormat
2458      * getInstance(Locale inLocale, int style) public static NumberFormat getInstance(ULocale desiredLocale, int choice)
2459      */
2460     public void TestGetInstance() {
2461         // Tests "public final static NumberFormat getInstance(int style)"
2462
2463         int[] invalid_cases = { NumberFormat.NUMBERSTYLE - 1, NumberFormat.NUMBERSTYLE - 2,
2464                 NumberFormat.PLURALCURRENCYSTYLE + 1, NumberFormat.PLURALCURRENCYSTYLE + 2 };
2465
2466         for (int i = NumberFormat.NUMBERSTYLE; i < NumberFormat.PLURALCURRENCYSTYLE; i++) {
2467             try {
2468                 NumberFormat.getInstance(i);
2469             } catch (Exception e) {
2470                 errln("NumberFormat.getInstance(int style) was not suppose to "
2471                         + "return an exception for passing value of " + i);
2472             }
2473         }
2474
2475         for (int i = 0; i < invalid_cases.length; i++) {
2476             try {
2477                 NumberFormat.getInstance(invalid_cases[i]);
2478                 errln("NumberFormat.getInstance(int style) was suppose to "
2479                         + "return an exception for passing value of " + invalid_cases[i]);
2480             } catch (Exception e) {
2481             }
2482         }
2483
2484         // Tests "public static NumberFormat getInstance(Locale inLocale, int style)"
2485         String[] localeCases = { "en_US", "fr_FR", "de_DE", "jp_JP" };
2486
2487         for (int i = NumberFormat.NUMBERSTYLE; i < NumberFormat.PLURALCURRENCYSTYLE; i++) {
2488             for (int j = 0; j < localeCases.length; j++) {
2489                 try {
2490                     NumberFormat.getInstance(new Locale(localeCases[j]), i);
2491                 } catch (Exception e) {
2492                     errln("NumberFormat.getInstance(Locale inLocale, int style) was not suppose to "
2493                             + "return an exception for passing value of " + localeCases[j] + ", " + i);
2494                 }
2495             }
2496         }
2497
2498         // Tests "public static NumberFormat getInstance(ULocale desiredLocale, int choice)"
2499         // Tests when "if (choice < NUMBERSTYLE || choice > PLURALCURRENCYSTYLE)" is true
2500         for (int i = 0; i < invalid_cases.length; i++) {
2501             try {
2502                 NumberFormat.getInstance((ULocale) null, invalid_cases[i]);
2503                 errln("NumberFormat.getInstance(ULocale inLocale, int choice) was not suppose to "
2504                         + "return an exception for passing value of " + invalid_cases[i]);
2505             } catch (Exception e) {
2506             }
2507         }
2508     }
2509
2510     /*
2511      * Tests the class public static abstract class NumberFormatFactory
2512      */
2513     public void TestNumberFormatFactory() {
2514         /*
2515          * The following class allows the method public NumberFormat createFormat(Locale loc, int formatType) to be
2516          * tested.
2517          */
2518         class TestFactory extends NumberFormatFactory {
2519             public Set<String> getSupportedLocaleNames() {
2520                 return null;
2521             }
2522
2523             public NumberFormat createFormat(ULocale loc, int formatType) {
2524                 return null;
2525             }
2526         }
2527
2528         /*
2529          * The following class allows the method public NumberFormat createFormat(ULocale loc, int formatType) to be
2530          * tested.
2531          */
2532         class TestFactory1 extends NumberFormatFactory {
2533             public Set<String> getSupportedLocaleNames() {
2534                 return null;
2535             }
2536
2537             public NumberFormat createFormat(Locale loc, int formatType) {
2538                 return null;
2539             }
2540         }
2541
2542         TestFactory tf = new TestFactory();
2543         TestFactory1 tf1 = new TestFactory1();
2544
2545         /*
2546          * Tests the method public boolean visible()
2547          */
2548         if (tf.visible() != true) {
2549             errln("NumberFormatFactor.visible() was suppose to return true.");
2550         }
2551
2552         /*
2553          * Tests the method public NumberFormat createFormat(Locale loc, int formatType)
2554          */
2555         if (tf.createFormat(new Locale(""), 0) != null) {
2556             errln("NumberFormatFactor.createFormat(Locale loc, int formatType) " + "was suppose to return null");
2557         }
2558
2559         /*
2560          * Tests the method public NumberFormat createFormat(ULocale loc, int formatType)
2561          */
2562         if (tf1.createFormat(new ULocale(""), 0) != null) {
2563             errln("NumberFormatFactor.createFormat(ULocale loc, int formatType) " + "was suppose to return null");
2564         }
2565     }
2566
2567     /*
2568      * Tests the class public static abstract class SimpleNumberFormatFactory extends NumberFormatFactory
2569      */
2570     public void TestSimpleNumberFormatFactory() {
2571         class TestSimpleNumberFormatFactory extends SimpleNumberFormatFactory {
2572             /*
2573              * Tests the method public SimpleNumberFormatFactory(Locale locale)
2574              */
2575             TestSimpleNumberFormatFactory() {
2576                 super(new Locale(""));
2577             }
2578         }
2579         @SuppressWarnings("unused")
2580         TestSimpleNumberFormatFactory tsnff = new TestSimpleNumberFormatFactory();
2581     }
2582
2583     /*
2584      * Tests the method public static ULocale[] getAvailableLocales()
2585      */
2586     @SuppressWarnings("static-access")
2587     public void TestGetAvailableLocales() {
2588         // Tests when "if (shim == null)" is true
2589         @SuppressWarnings("serial")
2590         class TestGetAvailableLocales extends NumberFormat {
2591             public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
2592                 return null;
2593             }
2594
2595             public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
2596                 return null;
2597             }
2598
2599             public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
2600                 return null;
2601             }
2602
2603             public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2604                 return null;
2605             }
2606
2607             public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2608                 return null;
2609             }
2610
2611             public Number parse(String text, ParsePosition parsePosition) {
2612                 return null;
2613             }
2614         }
2615
2616         try {
2617             TestGetAvailableLocales test = new TestGetAvailableLocales();
2618             test.getAvailableLocales();
2619         } catch (Exception e) {
2620             errln("NumberFormat.getAvailableLocales() was not suppose to "
2621                     + "return an exception when getting getting available locales.");
2622         }
2623     }
2624
2625     /*
2626      * Tests the method public void setMinimumIntegerDigits(int newValue)
2627      */
2628     public void TestSetMinimumIntegerDigits() {
2629         NumberFormat nf = NumberFormat.getInstance();
2630         // For valid array, it is displayed as {min value, max value}
2631         // Tests when "if (minimumIntegerDigits > maximumIntegerDigits)" is true
2632         int[][] cases = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 2, 0 }, { 2, 1 }, { 10, 0 } };
2633         int[] expectedMax = { 0, 1, 1, 2, 2, 10 };
2634         if (cases.length != expectedMax.length) {
2635             errln("Can't continue test case method TestSetMinimumIntegerDigits "
2636                     + "since the test case arrays are unequal.");
2637         } else {
2638             for (int i = 0; i < cases.length; i++) {
2639                 nf.setMaximumIntegerDigits(cases[i][1]);
2640                 nf.setMinimumIntegerDigits(cases[i][0]);
2641                 if (nf.getMaximumIntegerDigits() != expectedMax[i]) {
2642                     errln("NumberFormat.setMinimumIntegerDigits(int newValue "
2643                             + "did not return an expected result for parameter " + cases[i][1] + " and " + cases[i][0]
2644                             + " and expected " + expectedMax[i] + " but got " + nf.getMaximumIntegerDigits());
2645                 }
2646             }
2647         }
2648     }
2649
2650     /*
2651      * Tests the method protected Currency getEffectiveCurrency()
2652      */
2653     public void TestGetEffectiveCurrency() {
2654         // TODO: Tests the method
2655     }
2656
2657     /*
2658      * Tests the method public int getRoundingMode() public void setRoundingMode(int roundingMode)
2659      */
2660     public void TestRoundingMode() {
2661         @SuppressWarnings("serial")
2662         class TestRoundingMode extends NumberFormat {
2663             public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
2664                 return null;
2665             }
2666
2667             public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
2668                 return null;
2669             }
2670
2671             public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
2672                 return null;
2673             }
2674
2675             public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2676                 return null;
2677             }
2678
2679             public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2680                 return null;
2681             }
2682
2683             public Number parse(String text, ParsePosition parsePosition) {
2684                 return null;
2685             }
2686         }
2687         TestRoundingMode tgrm = new TestRoundingMode();
2688
2689         // Tests the function 'public void setRoundingMode(int roundingMode)'
2690         try {
2691             tgrm.setRoundingMode(0);
2692             errln("NumberFormat.setRoundingMode(int) was suppose to return an exception");
2693         } catch (Exception e) {
2694         }
2695
2696         // Tests the function 'public int getRoundingMode()'
2697         try {
2698             tgrm.getRoundingMode();
2699             errln("NumberFormat.getRoundingMode() was suppose to return an exception");
2700         } catch (Exception e) {
2701         }
2702     }
2703
2704     /*
2705      * Testing lenient decimal/grouping separator parsing
2706      */
2707     public void TestLenientSymbolParsing() {
2708         DecimalFormat fmt = new DecimalFormat();
2709         DecimalFormatSymbols sym = new DecimalFormatSymbols();
2710
2711         expect(fmt, "12\u300234", 12.34);
2712
2713         // Ticket#7345 - case 1
2714         // Even strict parsing, the decimal separator set in the symbols
2715         // should be successfully parsed.
2716
2717         sym.setDecimalSeparator('\u3002');
2718
2719         // non-strict
2720         fmt.setDecimalFormatSymbols(sym);
2721
2722         // strict - failed before the fix for #7345
2723         fmt.setParseStrict(true);
2724         expect(fmt, "23\u300245", 23.45);
2725         fmt.setParseStrict(false);
2726
2727
2728         // Ticket#7345 - case 2
2729         // Decimal separator variants other than DecimalFormatSymbols.decimalSeparator
2730         // should not hide the grouping separator DecimalFormatSymbols.groupingSeparator.
2731         sym.setDecimalSeparator('.');
2732         sym.setGroupingSeparator(',');
2733         fmt.setDecimalFormatSymbols(sym);
2734
2735         expect(fmt, "1,234.56", 1234.56);
2736
2737         sym.setGroupingSeparator('\uFF61');
2738         fmt.setDecimalFormatSymbols(sym);
2739
2740         expect(fmt, "2\uFF61345.67", 2345.67);
2741
2742         // Ticket#7218
2743         //
2744         // Lenient separator parsing is enabled by default.
2745         // A space character below is interpreted as a
2746         // group separator, even ',' is used as grouping
2747         // separator in the symbols.
2748         sym.setGroupingSeparator(',');
2749         fmt.setDecimalFormatSymbols(sym);
2750
2751         expect(fmt, "12 345", 12345);
2752
2753         // When the property SkipExtendedSeparatorParsing is true,
2754         // DecimalFormat does not use the extended equivalent separator
2755         // data and only uses the one in DecimalFormatSymbols.
2756         System.setProperty("com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "true");
2757
2758         expect(fmt, "23 456", 23);
2759
2760         // Set the configuration back to the default
2761         System.setProperty("com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false");
2762     }
2763
2764     /*
2765      * Testing currency driven max/min fraction digits problem
2766      * reported by ticket#7282
2767      */
2768     public void TestCurrencyFractionDigits() {
2769         double value = 99.12345;
2770
2771         // Create currency instance
2772         NumberFormat cfmt  = NumberFormat.getCurrencyInstance(new ULocale("ja_JP"));
2773         String text1 = cfmt.format(value);
2774
2775         // Reset the same currency and format the test value again
2776         cfmt.setCurrency(cfmt.getCurrency());
2777         String text2 = cfmt.format(value);
2778
2779         // output1 and output2 must be identical
2780         if (!text1.equals(text2)) {
2781             errln("NumberFormat.format() should return the same result - text1="
2782                     + text1 + " text2=" + text2);
2783         }
2784     }
2785     
2786     /*
2787      * Testing rounding to negative zero problem
2788      * reported by ticket#7609
2789      */
2790     public void TestNegZeroRounding() {    
2791   
2792         DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); 
2793         df.setRoundingMode(MathContext.ROUND_HALF_UP); 
2794         df.setMinimumFractionDigits(1); 
2795         df.setMaximumFractionDigits(1); 
2796         String text1 = df.format(-0.01);
2797         
2798         df.setRoundingIncrement(0.1);         
2799         String text2 = df.format(-0.01);
2800         
2801         // output1 and output2 must be identical
2802         if (!text1.equals(text2)) {
2803             errln("NumberFormat.format() should return the same result - text1="
2804                     + text1 + " text2=" + text2);
2805         }
2806   
2807     }
2808     
2809     public void TestCurrencyAmountCoverage() {
2810         CurrencyAmount ca, cb;
2811         
2812         try {
2813             ca = new CurrencyAmount(null, null);
2814             errln("NullPointerException should have been thrown.");
2815         } catch (NullPointerException ex) {
2816         }
2817         try {
2818             ca = new CurrencyAmount(new Integer(0), null);
2819             errln("NullPointerException should have been thrown.");
2820         } catch (NullPointerException ex) {
2821         }
2822         
2823         ca = new CurrencyAmount(new Integer(0), Currency.getInstance(new ULocale("ja_JP")));
2824         cb = new CurrencyAmount(new Integer(1), Currency.getInstance(new ULocale("ja_JP")));
2825         if (ca.equals(null)) {
2826             errln("Comparison should return false.");
2827         }
2828         if (!ca.equals(ca)) {
2829             errln("Comparision should return true.");
2830         }
2831         if (ca.equals(cb)) {
2832             errln("Comparison should return false.");
2833         }
2834     }
2835
2836     public void TestExponentParse() {
2837         ParsePosition parsePos = new ParsePosition(0);
2838         DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
2839         DecimalFormat fmt = new DecimalFormat("#####", symbols);
2840         Number result = fmt.parse("5.06e-27", parsePos);
2841         if ( result.doubleValue() != 5.06E-27 || parsePos.getIndex() != 8) {
2842             errln("ERROR: ERROR: parse failed - expected 5.06E-27, 8; got " + result.doubleValue() + ", " + parsePos.getIndex());
2843         }
2844     }
2845
2846     public void TestExplicitParents() {
2847         // We use these for testing because decimal and grouping separators will be inherited from es_419
2848         // starting with CLDR 2.0
2849         String[] DATA = {
2850                 "es", "CO", "", "1.250,75",
2851                 "es", "CR", "", "1.250,75",
2852                 "es", "ES", "", "1.250,75",
2853                 "es", "GQ", "", "1.250,75",
2854                 "es", "MX", "", "1,250.75",
2855                 "es", "US", "", "1,250.75",
2856                 "es", "VE", "", "1.250,75",
2857
2858         };
2859
2860         for (int i=0; i<DATA.length; i+=4) {
2861             Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
2862             NumberFormat fmt = NumberFormat.getInstance(locale);
2863             String s = fmt.format(1250.75);
2864             if (s.equals(DATA[i+3])) {
2865                 logln("Ok: 1250.75 x " + locale + " => " + s);
2866             } else {
2867                 errln("FAIL: 1250.75 x " + locale + " => " + s +
2868                       ", expected " + DATA[i+3]);
2869             }
2870         }
2871     }
2872 }