]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/format/NumberFormatTest.java
go
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / dev / test / format / NumberFormatTest.java
1 //##header J2SE15
2 /*
3  *******************************************************************************
4  * Copyright (C) 2001-2009, 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 com.ibm.icu.dev.test.TestUtil;
17 import com.ibm.icu.text.*;
18 import com.ibm.icu.text.NumberFormat.*;
19 import com.ibm.icu.util.*;
20 import com.ibm.icu.impl.LocaleUtility;
21 import com.ibm.icu.impl.data.ResourceReader;
22 import com.ibm.icu.impl.data.TokenIterator;
23 import com.ibm.icu.impl.Utility;
24 import com.ibm.icu.math.BigDecimal;
25
26 import java.lang.Double;
27 import java.math.BigInteger;
28 import java.text.FieldPosition;
29 import java.text.ParsePosition;
30 import java.text.ParseException;
31 import java.util.Locale;
32 import java.util.ArrayList;
33
34 public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
35
36     public static void main(String[] args) throws Exception {
37         new NumberFormatTest().run(args);
38     }
39
40     // Test various patterns
41     public void TestPatterns() {
42
43         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
44         final String pat[]    = { "#.#", "#.", ".#", "#" };
45         int pat_length = pat.length;
46         final String newpat[] = { "#0.#", "#0.", "#.0", "#" };
47         final String num[]    = { "0",   "0.", ".0", "0" };
48         for (int i=0; i<pat_length; ++i)
49         {
50             DecimalFormat fmt = new DecimalFormat(pat[i], sym);
51             String newp = fmt.toPattern();
52             if (!newp.equals(newpat[i]))
53                 errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
54                       "; " + newp + " seen instead");
55
56             String s = ((NumberFormat)fmt).format(0);
57             if (!s.equals(num[i]))
58             {
59                 errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
60                       "; " + s + " seen instead");
61                 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
62             }
63             // BigInteger 0 - ticket#4731
64             s = ((NumberFormat)fmt).format(BigInteger.ZERO);
65             if (!s.equals(num[i]))
66             {
67                 errln("FAIL: Pattern " + pat[i] + " should format BigInteger zero as " + num[i] +
68                       "; " + s + " seen instead");
69                 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
70             }
71         }
72     }
73
74     // Test exponential pattern
75     public void TestExponential() {
76
77         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
78         final String pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
79         int pat_length = pat.length;
80
81         double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
82         int val_length = val.length;
83         final String valFormat[] = {
84             // 0.####E0
85             "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
86             // 00.000E00
87             "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
88             // ##0.######E000
89             "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
90             // 0.###E0;[0.###E0]
91             "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" };
92         /*double valParse[] =
93             {
94                 0.01234, 123460000, 1.23E300, -3.1416E-271,
95                 0.01234, 123460000, 1.23E300, -3.1416E-271,
96                 0.01234, 123456800, 1.23E300, -3.141593E-271,
97                 0.01234, 123500000, 1.23E300, -3.142E-271,
98             };*/ //The variable is never used
99
100         int lval[] = { 0, -1, 1, 123456789 };
101         int lval_length = lval.length;
102         final String lvalFormat[] = {
103             // 0.####E0
104             "0E0", "-1E0", "1E0", "1.2346E8",
105             // 00.000E00
106             "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
107             // ##0.######E000
108             "0E000", "-1E000", "1E000", "123.4568E006",
109             // 0.###E0;[0.###E0]
110             "0E0", "[1E0]", "1E0", "1.235E8" };
111         int lvalParse[] =
112             {
113                 0, -1, 1, 123460000,
114                 0, -1, 1, 123460000,
115                 0, -1, 1, 123456800,
116                 0, -1, 1, 123500000,
117             };
118         int ival = 0, ilval = 0;
119         for (int p = 0; p < pat_length; ++p) {
120             DecimalFormat fmt = new DecimalFormat(pat[p], sym);
121             logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" + fmt.toPattern() + "\"");
122             int v;
123             for (v = 0; v < val_length; ++v) {
124                 String s;
125                 s = ((NumberFormat) fmt).format(val[v]);
126                 logln(" " + val[v] + " -format-> " + s);
127                 if (!s.equals(valFormat[v + ival]))
128                     errln("FAIL: Expected " + valFormat[v + ival]);
129
130                 ParsePosition pos = new ParsePosition(0);
131                 double a = fmt.parse(s, pos).doubleValue();
132                 if (pos.getIndex() == s.length()) {
133                     logln("  -parse-> " + Double.toString(a));
134                     // Use epsilon comparison as necessary
135                 } else
136                     errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
137             }
138             for (v = 0; v < lval_length; ++v) {
139                 String s;
140                 s = ((NumberFormat) fmt).format(lval[v]);
141                 logln(" " + lval[v] + "L -format-> " + s);
142                 if (!s.equals(lvalFormat[v + ilval]))
143                     errln("ERROR: Expected " + lvalFormat[v + ilval] + " Got: " + s);
144
145                 ParsePosition pos = new ParsePosition(0);
146                 long a = 0;
147                 Number A = fmt.parse(s, pos);
148                 if (A != null) {
149                     a = A.longValue();
150                     if (pos.getIndex() == s.length()) {
151                         logln("  -parse-> " + a);
152                         if (a != lvalParse[v + ilval])
153                             errln("FAIL: Expected " + lvalParse[v + ilval]);
154                     } else
155                         errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + Long.toString(a));
156                 } else {
157                     errln("Fail to parse the string: " + s);
158                 }
159             }
160             ival += val_length;
161             ilval += lval_length;
162         }
163     }
164
165     // Test the handling of quotes
166     public void TestQuotes() {
167
168         StringBuffer pat;
169         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
170         pat = new StringBuffer("a'fo''o'b#");
171         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
172         String s = ((NumberFormat)fmt).format(123);
173         logln("Pattern \"" + pat + "\"");
174         logln(" Format 123 . " + s);
175         if (!s.equals("afo'ob123"))
176             errln("FAIL: Expected afo'ob123");
177
178         s ="";
179         pat = new StringBuffer("a''b#");
180         fmt = new DecimalFormat(pat.toString(), sym);
181         s = ((NumberFormat)fmt).format(123);
182         logln("Pattern \"" + pat + "\"");
183         logln(" Format 123 . " + s);
184         if (!s.equals("a'b123"))
185             errln("FAIL: Expected a'b123");
186     }
187
188     public void TestParseCurrencyTrailingSymbol() {
189         // see sun bug 4709840
190         NumberFormat fmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);
191         float val = 12345.67f;
192         String str = fmt.format(val);
193         logln("val: " + val + " str: " + str);
194         try {
195             Number num = fmt.parse(str);
196             logln("num: " + num);
197         } catch (ParseException e) {
198             errln("parse of '" + str + "' threw exception: " + e);
199         }
200     }
201
202     /**
203      * Test the handling of the currency symbol in patterns.
204      **/
205     public void TestCurrencySign() {
206         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
207         StringBuffer pat = new StringBuffer("");
208         char currency = 0x00A4;
209         // "\xA4#,##0.00;-\xA4#,##0.00"
210         pat.append(currency).append("#,##0.00;-").append(currency).append("#,##0.00");
211         DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
212         String s = ((NumberFormat) fmt).format(1234.56);
213         pat = new StringBuffer("");
214         logln("Pattern \"" + fmt.toPattern() + "\"");
215         logln(" Format " + 1234.56 + " . " + s);
216         if (!s.equals("$1,234.56"))
217             errln("FAIL: Expected $1,234.56");
218         s = "";
219         s = ((NumberFormat) fmt).format(-1234.56);
220         logln(" Format " + Double.toString(-1234.56) + " . " + s);
221         if (!s.equals("-$1,234.56"))
222             errln("FAIL: Expected -$1,234.56");
223
224         pat = new StringBuffer("");
225         // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
226         pat.append(currency).append(currency).append(" #,##0.00;").append(currency).append(currency).append(" -#,##0.00");
227         fmt = new DecimalFormat(pat.toString(), sym);
228         s = "";
229         s = ((NumberFormat) fmt).format(1234.56);
230         logln("Pattern \"" + fmt.toPattern() + "\"");
231         logln(" Format " + Double.toString(1234.56) + " . " + s);
232
233         if (!s.equals("USD 1,234.56"))
234             errln("FAIL: Expected USD 1,234.56");
235         s = "";
236         s = ((NumberFormat) fmt).format(-1234.56);
237         logln(" Format " + Double.toString(-1234.56) + " . " + s);
238         if (!s.equals("USD -1,234.56"))
239             errln("FAIL: Expected USD -1,234.56");
240
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 = Utility.replaceAll(pat, "\u00A4", doubleCurrencyStr);
311                 } else if (j == 3) {
312                     pat = Utility.replaceAll(pat, "\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\u00a0DM",
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 \u0420\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 \u0420\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 \u0420\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u0435\u0439"},
493             // test locale without currency information
494             {"ti_ET", "-1.23", "USD", "-US$1.23", "-USD1.23", "-1.23 USD"},
495             // test choice format
496             {"es_AR", "1", "INR", "Rs\u00A01,00", "INR\u00A01,00", "1,00 rupia india"},
497             {"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"},
498         };
499         
500         for (int i=0; i<DATA.length; ++i) {
501           for (int k = NumberFormat.CURRENCYSTYLE;
502                k <= NumberFormat.PLURALCURRENCYSTYLE;
503                ++k) {
504             // k represents currency format style.
505             if ( k != NumberFormat.CURRENCYSTYLE &&
506                  k != NumberFormat.ISOCURRENCYSTYLE &&
507                  k != NumberFormat.PLURALCURRENCYSTYLE ) {
508                 continue;
509             }
510             String localeString = DATA[i][0];
511             Double numberToBeFormat = new Double(DATA[i][1]);
512             String currencyISOCode = DATA[i][2];
513             ULocale locale = new ULocale(localeString);
514             NumberFormat numFmt = NumberFormat.getInstance(locale, k);
515             numFmt.setCurrency(Currency.getInstance(currencyISOCode));
516             String strBuf = numFmt.format(numberToBeFormat);
517             int resultDataIndex = k-1;
518             if ( k == NumberFormat.CURRENCYSTYLE ) {
519                 resultDataIndex = k+2;
520             }
521             // DATA[i][resultDataIndex] is the currency format result
522             // using 'k' currency style.
523             String formatResult = DATA[i][resultDataIndex];
524             if (!strBuf.equals(formatResult)) {
525                 errln("FAIL: Expected " + formatResult + " actual: " + Utility.escape(strBuf));
526             }
527             try {
528                 // test parsing, and test parsing for all currency formats.
529                 for (int j = 3; j < 6; ++j) {
530                     // DATA[i][3] is the currency format result using 
531                     // CURRENCYSTYLE formatter.
532                     // DATA[i][4] is the currency format result using
533                     // ISOCURRENCYSTYLE formatter.
534                     // DATA[i][5] is the currency format result using
535                     // PLURALCURRENCYSTYLE formatter.
536                     String oneCurrencyFormatResult = DATA[i][j];
537                     Number val = numFmt.parse(oneCurrencyFormatResult);
538                     if (val.doubleValue() != numberToBeFormat.doubleValue()) {
539                         errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat);
540                     }
541                 }
542             }
543             catch (ParseException e) {
544                 errln("FAIL: " + e.getMessage());
545             }
546           }  
547         }
548     }
549
550
551     public void TestMiscCurrencyParsing() {
552         String[][] DATA = {
553             // each has: string to be parsed, parsed position, error position
554             {"1.00 ", "0", "4"},
555             {"1.00 UAE dirha", "0", "4"},
556             {"1.00 us dollar", "14", "-1"},
557             {"1.00 US DOLLAR", "14", "-1"},
558             {"1.00 usd", "0", "4"},
559         };
560         ULocale locale = new ULocale("en_US");
561         for (int i=0; i<DATA.length; ++i) {
562             String stringToBeParsed = DATA[i][0];
563             int parsedPosition = Integer.parseInt(DATA[i][1]);
564             int errorIndex = Integer.parseInt(DATA[i][2]);
565             NumberFormat numFmt = NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
566             ParsePosition parsePosition = new ParsePosition(0);
567             Number val = numFmt.parse(stringToBeParsed, parsePosition);
568             if (parsePosition.getIndex() != parsedPosition ||
569                 parsePosition.getErrorIndex() != errorIndex) {
570                 errln("FAIL: parse failed. expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex());
571                 errln("FAIL: parse failed. expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex());
572             }
573             if (parsePosition.getErrorIndex() == -1 &&
574                 val.doubleValue() != 1.00) {
575                 errln("FAIL: parse failed. expected 1.00, actual:" + val);
576             }
577         }
578     }
579
580
581     /**
582      * Test the Currency object handling, new as of ICU 2.2.
583      */
584     public void TestCurrencyObject() {
585         NumberFormat fmt =
586             NumberFormat.getCurrencyInstance(Locale.US);
587
588         expectCurrency(fmt, null, 1234.56, "$1,234.56");
589
590         expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
591                        1234.56, "\u20AC1,234.56"); // Euro
592
593         expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
594                        1234.56, "\u00A51,235"); // Yen
595
596         expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
597                        1234.56, "Fr.1,234.55"); // 0.05 rounding
598
599         expectCurrency(fmt, Currency.getInstance(Locale.US),
600                        1234.56, "$1,234.56");
601
602         fmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);
603
604         expectCurrency(fmt, null, 1234.56, "1 234,56 \u20AC");
605
606         expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
607                        1234.56, "1 235 \u00A5JP"); // Yen
608
609         expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
610                        1234.56, "1 234,55 CHF"); // 0.25 rounding
611
612         expectCurrency(fmt, Currency.getInstance(Locale.US),
613                        1234.56, "1 234,56 $US");
614
615         expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
616                        1234.56, "1 234,56 \u20AC"); // Euro
617     }
618
619     public void TestCurrencyPatterns() {
620         int i;
621         Locale[] locs = NumberFormat.getAvailableLocales();
622         for (i=0; i<locs.length; ++i) {
623             NumberFormat nf = NumberFormat.getCurrencyInstance(locs[i]);
624             // Make sure currency formats do not have a variable number
625             // of fraction digits
626             int min = nf.getMinimumFractionDigits();
627             int max = nf.getMaximumFractionDigits();
628             if (min != max) {
629                 String a = nf.format(1.0);
630                 String b = nf.format(1.125);
631                 errln("FAIL: " + locs[i] +
632                       " min fraction digits != max fraction digits; "+
633                       "x 1.0 => " + a +
634                       "; x 1.125 => " + b);
635             }
636
637             // Make sure EURO currency formats have exactly 2 fraction digits
638             if (nf instanceof DecimalFormat) {
639                 Currency curr = ((DecimalFormat) nf).getCurrency();
640                 if (curr != null && "EUR".equals(curr.getCurrencyCode())) {
641                     if (min != 2 || max != 2) {
642                         String a = nf.format(1.0);
643                         errln("FAIL: " + locs[i] +
644                               " is a EURO format but it does not have 2 fraction digits; "+
645                               "x 1.0 => " +
646                               a);
647                     }
648                 }
649             }
650         }
651     }
652
653     /**
654      * Do rudimentary testing of parsing.
655      */
656     public void TestParse() {
657         String arg = "0.0";
658         DecimalFormat format = new DecimalFormat("00");
659         double aNumber = 0l;
660         try {
661             aNumber = format.parse(arg).doubleValue();
662         } catch (ParseException e) {
663             System.out.println(e);
664         }
665         logln("parse(" + arg + ") = " + aNumber);
666     }
667
668     /**
669      * Test proper rounding by the format method.
670      */
671     public void TestRounding487() {
672
673         NumberFormat nf = NumberFormat.getInstance();
674         roundingTest(nf, 0.00159999, 4, "0.0016");
675         roundingTest(nf, 0.00995, 4, "0.01");
676
677         roundingTest(nf, 12.3995, 3, "12.4");
678
679         roundingTest(nf, 12.4999, 0, "12");
680         roundingTest(nf, - 19.5, 0, "-20");
681
682     }
683
684     /**
685      * Test the functioning of the secondary grouping value.
686      */
687     public void TestSecondaryGrouping() {
688
689         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
690         DecimalFormat f = new DecimalFormat("#,##,###", US);
691
692         expect(f, 123456789L, "12,34,56,789");
693         expectPat(f, "#,##,###");
694         f.applyPattern("#,###");
695
696         f.setSecondaryGroupingSize(4);
697         expect(f, 123456789L, "12,3456,789");
698         expectPat(f, "#,####,###");
699         NumberFormat g = NumberFormat.getInstance(new Locale("hi", "IN"));
700
701         String out = "";
702         long l = 1876543210L;
703         out = g.format(l);
704
705         // expect "1,87,65,43,210", but with Hindi digits
706         //         01234567890123
707         boolean ok = true;
708         if (out.length() != 14) {
709             ok = false;
710         } else {
711             for (int i = 0; i < out.length(); ++i) {
712                 boolean expectGroup = false;
713                 switch (i) {
714                     case 1 :
715                     case 4 :
716                     case 7 :
717                     case 10 :
718                         expectGroup = true;
719                         break;
720                 }
721                 // Later -- fix this to get the actual grouping
722                 // character from the resource bundle.
723                 boolean isGroup = (out.charAt(i) == 0x002C);
724                 if (isGroup != expectGroup) {
725                     ok = false;
726                     break;
727                 }
728             }
729         }
730         if (!ok) {
731             errln("FAIL  Expected "+ l + " x hi_IN . \"1,87,65,43,210\" (with Hindi digits), got \""
732                     + out + "\"");
733         } else {
734             logln("Ok    " + l + " x hi_IN . \"" + out + "\"");
735         }
736     }
737
738     public void roundingTest(NumberFormat nf, double x, int maxFractionDigits, final String expected) {
739         nf.setMaximumFractionDigits(maxFractionDigits);
740         String out = nf.format(x);
741         logln(x + " formats with " + maxFractionDigits + " fractional digits to " + out);
742         if (!out.equals(expected))
743             errln("FAIL: Expected " + expected);
744     }
745
746     /**
747      * Upgrade to alphaWorks
748      */
749     public void TestExponent() {
750         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
751         DecimalFormat fmt1 = new DecimalFormat("0.###E0", US);
752         DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US);
753         int n = 1234;
754         expect2(fmt1, n, "1.234E3");
755         expect2(fmt2, n, "1.234E+3");
756         expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
757
758     }
759
760     /**
761      * Upgrade to alphaWorks
762      */
763     public void TestScientific() {
764
765         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
766
767         // Test pattern round-trip
768         final String PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };
769         int PAT_length = PAT.length;
770         int DIGITS[] = {
771             // min int, max int, min frac, max frac
772             0, 1, 0, 0, // "#E0"
773             1, 1, 0, 4, // "0.####E0"
774             2, 2, 3, 3, // "00.000E00"
775             1, 3, 0, 4, // "##0.####E000"
776             1, 1, 0, 3, // "0.###E0;[0.###E0]"
777         };
778         for (int i = 0; i < PAT_length; ++i) {
779             String pat = PAT[i];
780             DecimalFormat df = new DecimalFormat(pat, US);
781             String pat2 = df.toPattern();
782             if (pat.equals(pat2)) {
783                 logln("Ok   Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
784             } else {
785                 errln("FAIL Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
786             }
787             // Make sure digit counts match what we expect
788             if (df.getMinimumIntegerDigits() != DIGITS[4 * i]
789                 || df.getMaximumIntegerDigits() != DIGITS[4 * i + 1]
790                 || df.getMinimumFractionDigits() != DIGITS[4 * i + 2]
791                 || df.getMaximumFractionDigits() != DIGITS[4 * i + 3]) {
792                 errln("FAIL \""+ pat+ "\" min/max int; min/max frac = "
793                         + df.getMinimumIntegerDigits() + "/"
794                         + df.getMaximumIntegerDigits() + ";"
795                         + df.getMinimumFractionDigits() + "/"
796                         + df.getMaximumFractionDigits() + ", expect "
797                         + DIGITS[4 * i] + "/"
798                         + DIGITS[4 * i + 1] + ";"
799                         + DIGITS[4 * i + 2] + "/"
800                         + DIGITS[4 * i + 3]);
801             }
802         }
803
804         expect2(new DecimalFormat("#E0", US), 12345.0, "1.2345E4");
805         expect(new DecimalFormat("0E0", US), 12345.0, "1E4");
806
807         // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
808         // so result = 1.234568E4 not 1.2345678901E4
809         //when the pattern problem is finalized, delete comment mark'//'
810         //of the following code
811         expect2(NumberFormat.getScientificInstance(Locale.US), 12345.678901, "1.2345678901E4");
812         logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
813         expect2(NumberFormat.getScientificInstance(ULocale.US), 12345.678901, "1.2345678901E4");
814
815         expect(new DecimalFormat("##0.###E0", US), 12345.0, "12.34E3");
816         expect(new DecimalFormat("##0.###E0", US), 12345.00001, "12.35E3");
817         expect2(new DecimalFormat("##0.####E0", US), 12345, "12.345E3");
818
819         // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
820         // so result = 1.234568E4 not 1.2345678901E4
821         expect2(NumberFormat.getScientificInstance(Locale.FRANCE), 12345.678901, "1,2345678901E4");
822         logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
823         expect2(NumberFormat.getScientificInstance(ULocale.FRANCE), 12345.678901, "1,2345678901E4");
824
825         expect(new DecimalFormat("##0.####E0", US), 789.12345e-9, "789.12E-9");
826         expect2(new DecimalFormat("##0.####E0", US), 780.e-9, "780E-9");
827         expect(new DecimalFormat(".###E0", US), 45678.0, ".457E5");
828         expect2(new DecimalFormat(".###E0", US), 0, ".0E0");
829         /*
830         expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
831                                      new DecimalFormat("##E0", US),
832                                      new DecimalFormat("####E0", US),
833                                      new DecimalFormat("0E0", US),
834                                      new DecimalFormat("00E0", US),
835                                      new DecimalFormat("000E0", US),
836                                    },
837                new Long(45678000),
838                new String[] { "4.5678E7",
839                               "45.678E6",
840                               "4567.8E4",
841                               "5E7",
842                               "46E6",
843                               "457E5",
844                             }
845                );
846         !
847         ! Unroll this test into individual tests below...
848         !
849         */
850         expect2(new DecimalFormat("#E0", US), 45678000, "4.5678E7");
851         expect2(new DecimalFormat("##E0", US), 45678000, "45.678E6");
852         expect2(new DecimalFormat("####E0", US), 45678000, "4567.8E4");
853         expect(new DecimalFormat("0E0", US), 45678000, "5E7");
854         expect(new DecimalFormat("00E0", US), 45678000, "46E6");
855         expect(new DecimalFormat("000E0", US), 45678000, "457E5");
856         /*
857         expect(new DecimalFormat("###E0", US, status),
858                new Object[] { new Double(0.0000123), "12.3E-6",
859                               new Double(0.000123), "123E-6",
860                               new Double(0.00123), "1.23E-3",
861                               new Double(0.0123), "12.3E-3",
862                               new Double(0.123), "123E-3",
863                               new Double(1.23), "1.23E0",
864                               new Double(12.3), "12.3E0",
865                               new Double(123), "123E0",
866                               new Double(1230), "1.23E3",
867                              });
868         !
869         ! Unroll this test into individual tests below...
870         !
871         */
872         expect2(new DecimalFormat("###E0", US), 0.0000123, "12.3E-6");
873         expect2(new DecimalFormat("###E0", US), 0.000123, "123E-6");
874         expect2(new DecimalFormat("###E0", US), 0.00123, "1.23E-3");
875         expect2(new DecimalFormat("###E0", US), 0.0123, "12.3E-3");
876         expect2(new DecimalFormat("###E0", US), 0.123, "123E-3");
877         expect2(new DecimalFormat("###E0", US), 1.23, "1.23E0");
878         expect2(new DecimalFormat("###E0", US), 12.3, "12.3E0");
879         expect2(new DecimalFormat("###E0", US), 123.0, "123E0");
880         expect2(new DecimalFormat("###E0", US), 1230.0, "1.23E3");
881         /*
882         expect(new DecimalFormat("0.#E+00", US, status),
883                new Object[] { new Double(0.00012), "1.2E-04",
884                               new Long(12000),     "1.2E+04",
885                              });
886         !
887         ! Unroll this test into individual tests below...
888         !
889         */
890         expect2(new DecimalFormat("0.#E+00", US), 0.00012, "1.2E-04");
891         expect2(new DecimalFormat("0.#E+00", US), 12000, "1.2E+04");
892     }
893
894     /**
895      * Upgrade to alphaWorks
896      */
897     public void TestPad() {
898
899         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
900         expect2(new DecimalFormat("*^##.##", US), 0, "^^^^0");
901         expect2(new DecimalFormat("*^##.##", US), -1.3, "^-1.3");
902         expect2(
903             new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
904             0,
905             "0.0E0______ g-m/s^2");
906         expect(
907             new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
908             1.0 / 3,
909             "333.333E-3_ g-m/s^2");
910         expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US), 0, "0.0______ g-m/s^2");
911         expect(
912             new DecimalFormat("##0.0####*_ 'g-m/s^2'", US),
913             1.0 / 3,
914             "0.33333__ g-m/s^2");
915
916         // Test padding before a sign
917         final String formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
918         expect2(new DecimalFormat(formatStr, US), -10, "xxxxxxxxxx(10.0)");
919         expect2(new DecimalFormat(formatStr, US), -1000, "xxxxxxx(1,000.0)");
920         expect2(new DecimalFormat(formatStr, US), -1000000, "xxx(1,000,000.0)");
921         expect2(new DecimalFormat(formatStr, US), -100.37, "xxxxxxxx(100.37)");
922         expect2(new DecimalFormat(formatStr, US), -10456.37, "xxxxx(10,456.37)");
923         expect2(new DecimalFormat(formatStr, US), -1120456.37, "xx(1,120,456.37)");
924         expect2(new DecimalFormat(formatStr, US), -112045600.37, "(112,045,600.37)");
925         expect2(new DecimalFormat(formatStr, US), -1252045600.37, "(1,252,045,600.37)");
926
927         expect2(new DecimalFormat(formatStr, US), 10, "xxxxxxxxxxxx10.0");
928         expect2(new DecimalFormat(formatStr, US), 1000, "xxxxxxxxx1,000.0");
929         expect2(new DecimalFormat(formatStr, US), 1000000, "xxxxx1,000,000.0");
930         expect2(new DecimalFormat(formatStr, US), 100.37, "xxxxxxxxxx100.37");
931         expect2(new DecimalFormat(formatStr, US), 10456.37, "xxxxxxx10,456.37");
932         expect2(new DecimalFormat(formatStr, US), 1120456.37, "xxxx1,120,456.37");
933         expect2(new DecimalFormat(formatStr, US), 112045600.37, "xx112,045,600.37");
934         expect2(new DecimalFormat(formatStr, US), 10252045600.37, "10,252,045,600.37");
935
936         // Test padding between a sign and a number
937         final String formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
938         expect2(new DecimalFormat(formatStr2, US), -10, "(10.0xxxxxxxxxx)");
939         expect2(new DecimalFormat(formatStr2, US), -1000, "(1,000.0xxxxxxx)");
940         expect2(new DecimalFormat(formatStr2, US), -1000000, "(1,000,000.0xxx)");
941         expect2(new DecimalFormat(formatStr2, US), -100.37, "(100.37xxxxxxxx)");
942         expect2(new DecimalFormat(formatStr2, US), -10456.37, "(10,456.37xxxxx)");
943         expect2(new DecimalFormat(formatStr2, US), -1120456.37, "(1,120,456.37xx)");
944         expect2(new DecimalFormat(formatStr2, US), -112045600.37, "(112,045,600.37)");
945         expect2(new DecimalFormat(formatStr2, US), -1252045600.37, "(1,252,045,600.37)");
946
947         expect2(new DecimalFormat(formatStr2, US), 10, "10.0xxxxxxxxxxxx");
948         expect2(new DecimalFormat(formatStr2, US), 1000, "1,000.0xxxxxxxxx");
949         expect2(new DecimalFormat(formatStr2, US), 1000000, "1,000,000.0xxxxx");
950         expect2(new DecimalFormat(formatStr2, US), 100.37, "100.37xxxxxxxxxx");
951         expect2(new DecimalFormat(formatStr2, US), 10456.37, "10,456.37xxxxxxx");
952         expect2(new DecimalFormat(formatStr2, US), 1120456.37, "1,120,456.37xxxx");
953         expect2(new DecimalFormat(formatStr2, US), 112045600.37, "112,045,600.37xx");
954         expect2(new DecimalFormat(formatStr2, US), 10252045600.37, "10,252,045,600.37");
955
956         //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
957         DecimalFormat fmt = new DecimalFormat("#", US);
958         char padString = 'P';
959         fmt.setPadCharacter(padString);
960         expectPad(fmt, "*P##.##", DecimalFormat.PAD_BEFORE_PREFIX, 5, padString);
961         fmt.setPadCharacter('^');
962         expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, '^');
963         //commented untill implementation is complete
964         /*  fmt.setPadCharacter((UnicodeString)"^^^");
965           expectPad(fmt, "*^^^#", DecimalFormat.kPadBeforePrefix, 3, (UnicodeString)"^^^");
966           padString.remove();
967           padString.append((UChar)0x0061);
968           padString.append((UChar)0x0302);
969           fmt.setPadCharacter(padString);
970           UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
971           UnicodeString pattern(patternChars);
972           expectPad(fmt, pattern , DecimalFormat.kPadBeforePrefix, 4, padString);
973           */
974     }
975
976     /**
977      * Upgrade to alphaWorks
978      */
979     public void TestPatterns2() {
980         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
981         DecimalFormat fmt = new DecimalFormat("#", US);
982
983         char hat = 0x005E; /*^*/
984
985         expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, hat);
986         expectPad(fmt, "$*^#", DecimalFormat.PAD_AFTER_PREFIX, 2, hat);
987         expectPad(fmt, "#*^", DecimalFormat.PAD_BEFORE_SUFFIX, 1, hat);
988         expectPad(fmt, "#$*^", DecimalFormat.PAD_AFTER_SUFFIX, 2, hat);
989         expectPad(fmt, "$*^$#", -1);
990         expectPad(fmt, "#$*^$", -1);
991         expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat.PAD_BEFORE_SUFFIX, 12, (char) 0x0078 /*x*/);
992         expectPad(fmt, "''#0*x", DecimalFormat.PAD_BEFORE_SUFFIX, 3, (char) 0x0078 /*x*/);
993         expectPad(fmt, "'I''ll'*a###.##", DecimalFormat.PAD_AFTER_PREFIX, 10, (char) 0x0061 /*a*/);
994
995         fmt.applyPattern("AA#,##0.00ZZ");
996         fmt.setPadCharacter(hat);
997
998         fmt.setFormatWidth(10);
999
1000         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_PREFIX);
1001         expectPat(fmt, "*^AA#,##0.00ZZ");
1002
1003         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_SUFFIX);
1004         expectPat(fmt, "AA#,##0.00*^ZZ");
1005
1006         fmt.setPadPosition(DecimalFormat.PAD_AFTER_SUFFIX);
1007         expectPat(fmt, "AA#,##0.00ZZ*^");
1008
1009         //            12  3456789012
1010         String exp = "AA*^#,##0.00ZZ";
1011         fmt.setFormatWidth(12);
1012         fmt.setPadPosition(DecimalFormat.PAD_AFTER_PREFIX);
1013         expectPat(fmt, exp);
1014
1015         fmt.setFormatWidth(13);
1016         //              12  34567890123
1017         expectPat(fmt, "AA*^##,##0.00ZZ");
1018
1019         fmt.setFormatWidth(14);
1020         //              12  345678901234
1021         expectPat(fmt, "AA*^###,##0.00ZZ");
1022
1023         fmt.setFormatWidth(15);
1024         //              12  3456789012345
1025         expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1026
1027         fmt.setFormatWidth(16);
1028         //              12  34567890123456
1029         expectPat(fmt, "AA*^#,###,##0.00ZZ");
1030     }
1031
1032     public void TestRegistration() {
1033         final ULocale SRC_LOC = ULocale.FRANCE;
1034         final ULocale SWAP_LOC = ULocale.US;
1035
1036         class TestFactory extends SimpleNumberFormatFactory {
1037             NumberFormat currencyStyle;
1038
1039             TestFactory() {
1040                 super(SRC_LOC, true);
1041                 currencyStyle = NumberFormat.getIntegerInstance(SWAP_LOC);
1042             }
1043
1044             public NumberFormat createFormat(ULocale loc, int formatType) {
1045                 if (formatType == FORMAT_CURRENCY) {
1046                     return currencyStyle;
1047                 }
1048                 return null;
1049             }
1050         }
1051
1052         NumberFormat f0 = NumberFormat.getIntegerInstance(SWAP_LOC);
1053         NumberFormat f1 = NumberFormat.getIntegerInstance(SRC_LOC);
1054         NumberFormat f2 = NumberFormat.getCurrencyInstance(SRC_LOC);
1055         Object key = NumberFormat.registerFactory(new TestFactory());
1056         NumberFormat f3 = NumberFormat.getCurrencyInstance(SRC_LOC);
1057         NumberFormat f4 = NumberFormat.getIntegerInstance(SRC_LOC);
1058         NumberFormat.unregister(key); // restore for other tests
1059         NumberFormat f5 = NumberFormat.getCurrencyInstance(SRC_LOC);
1060
1061         float n = 1234.567f;
1062         logln("f0 swap int: " + f0.format(n));
1063         logln("f1 src int: " + f1.format(n));
1064         logln("f2 src cur: " + f2.format(n));
1065         logln("f3 reg cur: " + f3.format(n));
1066         logln("f4 reg int: " + f4.format(n));
1067         logln("f5 unreg cur: " + f5.format(n));
1068
1069         if (!f3.format(n).equals(f0.format(n))) {
1070             errln("registered service did not match");
1071         }
1072         if (!f4.format(n).equals(f1.format(n))) {
1073             errln("registered service did not inherit");
1074         }
1075         if (!f5.format(n).equals(f2.format(n))) {
1076             errln("unregistered service did not match original");
1077         }
1078     }
1079
1080     public void TestScientific2() {
1081         // jb 2552
1082         DecimalFormat fmt = (DecimalFormat)NumberFormat.getCurrencyInstance();
1083         Number num = new Double(12.34);
1084         expect(fmt, num, "$12.34");
1085         fmt.setScientificNotation(true);
1086         expect(fmt, num, "$1.23E1");
1087         fmt.setScientificNotation(false);
1088         expect(fmt, num, "$12.34");
1089     }
1090
1091     public void TestScientificGrouping() {
1092         // jb 2552
1093         DecimalFormat fmt = new DecimalFormat("###.##E0");
1094         expect(fmt, .01234, "12.3E-3");
1095         expect(fmt, .1234, "123E-3");
1096         expect(fmt, 1.234, "1.23E0");
1097         expect(fmt, 12.34, "12.3E0");
1098         expect(fmt, 123.4, "123E0");
1099         expect(fmt, 1234, "1.23E3");
1100     }
1101
1102     // additional coverage tests
1103
1104     // sigh, can't have static inner classes, why not?
1105
1106     static final class PI extends Number {
1107         /**
1108          * For serialization
1109          */
1110         private static final long serialVersionUID = -305601227915602172L;
1111
1112         private PI() {}
1113         public int intValue() { return (int)Math.PI; }
1114         public long longValue() { return (long)Math.PI; }
1115         public float  floatValue() { return (float)Math.PI; }
1116         public double doubleValue() { return (double)Math.PI; }
1117         public byte byteValue() { return (byte)Math.PI; }
1118         public short shortValue() { return (short)Math.PI; }
1119
1120         public static final Number INSTANCE = new PI();
1121     }
1122
1123     public void TestCoverage() {
1124         NumberFormat fmt = NumberFormat.getNumberInstance(); // default locale
1125         logln(fmt.format(new BigInteger("1234567890987654321234567890987654321", 10)));
1126
1127         fmt = NumberFormat.getScientificInstance(); // default locale
1128
1129         logln(fmt.format(PI.INSTANCE));
1130
1131         try {
1132             logln(fmt.format("12345"));
1133             errln("numberformat of string did not throw exception");
1134         }
1135         catch (Exception e) {
1136             logln("PASS: numberformat of string failed as expected");
1137         }
1138
1139         int hash = fmt.hashCode();
1140         logln("hash code " + hash);
1141
1142         logln("compare to string returns: " + fmt.equals(""));
1143
1144         // For ICU 2.6 - alan
1145         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1146         DecimalFormat df = new DecimalFormat("'*&'' '\u00A4' ''&*' #,##0.00", US);
1147         df.setCurrency(Currency.getInstance("INR"));
1148         expect2(df, 1.0, "*&' Rs '&* 1.00");
1149         expect2(df, -2.0, "-*&' Rs '&* 2.00");
1150         df.applyPattern("#,##0.00 '*&'' '\u00A4' ''&*'");
1151         expect2(df, 2.0, "2.00 *&' Rs '&*");
1152         expect2(df, -1.0, "-1.00 *&' Rs '&*");
1153
1154 //#if defined(FOUNDATION10)
1155 //##        com.ibm.icu.math.BigDecimal r = df.getRoundingIncrement();
1156 //#else
1157         java.math.BigDecimal r = df.getRoundingIncrement();
1158 //#endif
1159         if (r != null) {
1160             errln("FAIL: rounding = " + r + ", expect null");
1161         }
1162
1163         if (df.isScientificNotation()) {
1164             errln("FAIL: isScientificNotation = true, expect false");
1165         }
1166
1167         df.applyPattern("0.00000");
1168         df.setScientificNotation(true);
1169         if (!df.isScientificNotation()) {
1170             errln("FAIL: isScientificNotation = false, expect true");
1171         }
1172         df.setMinimumExponentDigits((byte)2);
1173         if (df.getMinimumExponentDigits() != 2) {
1174             errln("FAIL: getMinimumExponentDigits = " +
1175                   df.getMinimumExponentDigits() + ", expect 2");
1176         }
1177         df.setExponentSignAlwaysShown(true);
1178         if (!df.isExponentSignAlwaysShown()) {
1179             errln("FAIL: isExponentSignAlwaysShown = false, expect true");
1180         }
1181         df.setSecondaryGroupingSize(0);
1182         if (df.getSecondaryGroupingSize() != 0) {
1183             errln("FAIL: getSecondaryGroupingSize = " +
1184                   df.getSecondaryGroupingSize() + ", expect 0");
1185         }
1186         expect2(df, 3.14159, "3.14159E+00");
1187
1188         // DecimalFormatSymbols#getInstance
1189         DecimalFormatSymbols decsym1 = DecimalFormatSymbols.getInstance();
1190         DecimalFormatSymbols decsym2 = new DecimalFormatSymbols();
1191         if (!decsym1.equals(decsym2)) {
1192             errln("FAIL: DecimalFormatSymbols returned by getInstance()" +
1193             "does not match new DecimalFormatSymbols().");
1194         }
1195         decsym1 = DecimalFormatSymbols.getInstance(Locale.JAPAN);
1196         decsym2 = DecimalFormatSymbols.getInstance(ULocale.JAPAN);
1197         if (!decsym1.equals(decsym2)) {
1198             errln("FAIL: DecimalFormatSymbols returned by getInstance(Locale.JAPAN)" +
1199             "does not match the one returned by getInstance(ULocale.JAPAN).");
1200         }
1201
1202         // DecimalFormatSymbols#getAvailableLocales/#getAvailableULocales
1203         Locale[] allLocales = DecimalFormatSymbols.getAvailableLocales();
1204         if (allLocales.length == 0) {
1205             errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1206         } else {
1207             logln("PASS: " + allLocales.length +
1208                     " available locales returned by DecimalFormatSymbols.getAvailableLocales");
1209         }
1210         ULocale[] allULocales = DecimalFormatSymbols.getAvailableULocales();
1211         if (allULocales.length == 0) {
1212             errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1213         } else {
1214             logln("PASS: " + allULocales.length +
1215                     " available locales returned by DecimalFormatSymbols.getAvailableULocales");
1216         }
1217     }
1218
1219     public void TestWhiteSpaceParsing() {
1220         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1221         DecimalFormat fmt = new DecimalFormat("a  b#0c  ", US);
1222         int n = 1234;
1223         expect(fmt, "a b1234c ", n);
1224         expect(fmt, "a   b1234c   ", n);
1225     }
1226
1227     /**
1228      * Test currencies whose display name is a ChoiceFormat.
1229      */
1230     public void TestComplexCurrency() {
1231 //  CLDR No Longer uses complex currency symbols.
1232 //  Skipping this test.
1233 //        Locale loc = new Locale("kn", "IN", "");
1234 //        NumberFormat fmt = NumberFormat.getCurrencyInstance(loc);
1235
1236 //        expect2(fmt, 1.0, "Re.\u00a01.00");
1237 //        expect(fmt, 1.001, "Re.\u00a01.00"); // tricky
1238 //        expect2(fmt, 12345678.0, "Rs.\u00a01,23,45,678.00");
1239 //        expect2(fmt, 0.5, "Rs.\u00a00.50");
1240 //        expect2(fmt, -1.0, "-Re.\u00a01.00");
1241 //        expect2(fmt, -10.0, "-Rs.\u00a010.00");
1242     }
1243
1244     public void TestCurrencyKeyword() {
1245     ULocale locale = new ULocale("th_TH@currency=QQQ");
1246     NumberFormat format = NumberFormat.getCurrencyInstance(locale);
1247     String result = format.format(12.34f);
1248     if (!"QQQ12.34".equals(result)) {
1249         errln("got unexpected currency: " + result);
1250     }
1251     }
1252
1253     /**
1254      * Test alternate numbering systems
1255      */
1256     public void TestNumberingSystems() {
1257
1258         ULocale loc1 = new ULocale("en_US@numbers=thai");
1259         ULocale loc2 = new ULocale("en_US@numbers=hebr");
1260         ULocale loc3 = new ULocale("en_US@numbers=arabext");
1261         ULocale loc4 = new ULocale("hi_IN@numbers=foobar");
1262         
1263         NumberFormat fmt1 = NumberFormat.getInstance(loc1);
1264         NumberFormat fmt2 = NumberFormat.getInstance(loc2);
1265         NumberFormat fmt3 = NumberFormat.getInstance(loc3);
1266         NumberFormat fmt4 = NumberFormat.getInstance(loc4);
1267
1268         expect2(fmt1,1234.567,"\u0e51,\u0e52\u0e53\u0e54.\u0e55\u0e56\u0e57");
1269         expect3(fmt2,5678.0,"\u05d4\u05f3\u05ea\u05e8\u05e2\u05f4\u05d7");
1270         expect2(fmt3,1234.567,"\u06f1,\u06f2\u06f3\u06f4.\u06f5\u06f6\u06f7");
1271         expect2(fmt4,1234.567,"\u0967,\u0968\u0969\u096a.\u096b\u096c\u096d");
1272
1273     }
1274
1275     public void TestThreadedFormat() {
1276
1277         class FormatTask implements Runnable {
1278             DecimalFormat fmt;
1279             StringBuffer buf;
1280             boolean inc;
1281             float num;
1282
1283             FormatTask(DecimalFormat fmt, int index) {
1284                 this.fmt = fmt;
1285                 this.buf = new StringBuffer();
1286                 this.inc = (index & 0x1) == 0;
1287                 this.num = inc ? 0 : 10000;
1288             }
1289
1290             public void run() {
1291         if (inc) {
1292             while (num < 10000) {
1293             buf.append(fmt.format(num) + "\n");
1294             num += 3.14159;
1295             }
1296         } else {
1297             while (num > 0) {
1298             buf.append(fmt.format(num) + "\n");
1299             num -= 3.14159;
1300             }
1301         }
1302         }
1303
1304         String result() {
1305         return buf.toString();
1306         }
1307     }
1308
1309         DecimalFormat fmt = new DecimalFormat("0.####");
1310         FormatTask[] tasks = new FormatTask[8];
1311         for (int i = 0; i < tasks.length; ++i) {
1312         tasks[i] = new FormatTask(fmt, i);
1313     }
1314
1315     TestUtil.runUntilDone(tasks);
1316
1317         for (int i = 2; i < tasks.length; i++) {
1318         String str1 = tasks[i].result();
1319         String str2 = tasks[i-2].result();
1320             if (!str1.equals(str2)) {
1321                 System.out.println("mismatch at " + i);
1322                 System.out.println(str1);
1323                 System.out.println(str2);
1324                 errln("decimal format thread mismatch");
1325
1326                 break;
1327             }
1328             str1 = str2;
1329         }
1330     }
1331
1332     public void TestPerMill() {
1333         DecimalFormat fmt = new DecimalFormat("###.###\u2030");
1334         assertEquals("0.4857 x ###.###\u2030",
1335                      "485.7\u2030", fmt.format(0.4857));
1336
1337         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.ENGLISH);
1338         sym.setPerMill('m');
1339         DecimalFormat fmt2 = new DecimalFormat("", sym);
1340         fmt2.applyLocalizedPattern("###.###m");
1341         assertEquals("0.4857 x ###.###m",
1342                      "485.7m", fmt2.format(0.4857));
1343     }
1344
1345     public void TestIllegalPatterns() {
1346         // Test cases:
1347         // Prefix with "-:" for illegal patterns
1348         // Prefix with "+:" for legal patterns
1349         String DATA[] = {
1350             // Unquoted special characters in the suffix are illegal
1351             "-:000.000|###",
1352             "+:000.000'|###'",
1353         };
1354         for (int i=0; i<DATA.length; ++i) {
1355             String pat=DATA[i];
1356             boolean valid = pat.charAt(0) == '+';
1357             pat = pat.substring(2);
1358             Exception e = null;
1359             try {
1360                 // locale doesn't matter here
1361                 new DecimalFormat(pat);
1362             } catch (IllegalArgumentException e1) {
1363                 e = e1;
1364             } catch (IndexOutOfBoundsException e1) {
1365                 e = e1;
1366             }
1367             String msg = (e==null) ? "success" : e.getMessage();
1368             if ((e==null) == valid) {
1369                 logln("Ok: pattern \"" + pat + "\": " + msg);
1370             } else {
1371                 errln("FAIL: pattern \"" + pat + "\" should have " +
1372                       (valid?"succeeded":"failed") + "; got " + msg);
1373             }
1374         }
1375     }
1376
1377     /**
1378      * Parse a CurrencyAmount using the given NumberFormat, with
1379      * the 'delim' character separating the number and the currency.
1380      */
1381     private static CurrencyAmount parseCurrencyAmount(String str, NumberFormat fmt,
1382                                                       char delim)
1383         throws ParseException {
1384         int i = str.indexOf(delim);
1385         return new CurrencyAmount(fmt.parse(str.substring(0,i)),
1386                                   Currency.getInstance(str.substring(i+1)));
1387     }
1388
1389     /**
1390      * Return an integer representing the next token from this
1391      * iterator.  The integer will be an index into the given list, or
1392      * -1 if there are no more tokens, or -2 if the token is not on
1393      * the list.
1394      */
1395     private static int keywordIndex(String tok) {
1396         for (int i=0; i<KEYWORDS.length; ++i) {
1397             if (tok.equals(KEYWORDS[i])) {
1398                 return i;
1399             }
1400         }
1401         return -1;
1402     }
1403
1404     private static final String KEYWORDS[] = {
1405         /*0*/ "ref=", // <reference pattern to parse numbers>
1406         /*1*/ "loc=", // <locale for formats>
1407         /*2*/ "f:",   // <pattern or '-'> <number> <exp. string>
1408         /*3*/ "fp:",  // <pattern or '-'> <number> <exp. string> <exp. number>
1409         /*4*/ "rt:",  // <pattern or '-'> <(exp.) number> <(exp.) string>
1410         /*5*/ "p:",   // <pattern or '-'> <string> <exp. number>
1411         /*6*/ "perr:", // <pattern or '-'> <invalid string>
1412         /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1413         /*8*/ "fpc:", // <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1414         /*9*/ "strict=", // true or false
1415     };
1416
1417     public void TestCases() {
1418         String caseFileName = "NumberFormatTestCases.txt";
1419         java.io.InputStream is = NumberFormatTest.class.getResourceAsStream(caseFileName);
1420
1421         ResourceReader reader = new ResourceReader(is, caseFileName, "utf-8");
1422         TokenIterator tokens = new TokenIterator(reader);
1423
1424         Locale loc = new Locale("en", "US", "");
1425         DecimalFormat ref = null, fmt = null;
1426         MeasureFormat mfmt = null;
1427         String pat = null, str = null, mloc = null;
1428         boolean strict = false;
1429
1430         try {
1431             for (;;) {
1432                 String tok = tokens.next();
1433                 if (tok == null) {
1434                     break;
1435                 }
1436                 String where = "(" + tokens.getLineNumber() + ") ";
1437                 int cmd = keywordIndex(tok);
1438                 switch (cmd) {
1439                 case 0:
1440                     // ref= <reference pattern>
1441                     ref = new DecimalFormat(tokens.next(),
1442                                             new DecimalFormatSymbols(Locale.US));
1443                     ref.setParseStrict(strict);
1444                     logln("Setting reference pattern to:\t" + ref);
1445                     break;
1446                 case 1:
1447                     // loc= <locale>
1448                     loc = LocaleUtility.getLocaleFromName(tokens.next());
1449                     pat = ((DecimalFormat) NumberFormat.getInstance(loc)).toPattern();
1450                     logln("Setting locale to:\t" + loc + ", \tand pattern to:\t" + pat);
1451                     break;
1452                 case 2: // f:
1453                 case 3: // fp:
1454                 case 4: // rt:
1455                 case 5: // p:
1456                     tok = tokens.next();
1457                     if (!tok.equals("-")) {
1458                         pat = tok;
1459                     }
1460                     try {
1461                         fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc));
1462                         fmt.setParseStrict(strict);
1463                     } catch (IllegalArgumentException iae) {
1464                         errln(where + "Pattern \"" + pat + '"');
1465                         iae.printStackTrace();
1466                         tokens.next(); // consume remaining tokens
1467                         //tokens.next();
1468                         if (cmd == 3) tokens.next();
1469                         continue;
1470                     }
1471                    str = null;
1472                     try {
1473                         if (cmd == 2 || cmd == 3 || cmd == 4) {
1474                             // f: <pattern or '-'> <number> <exp. string>
1475                             // fp: <pattern or '-'> <number> <exp. string> <exp. number>
1476                             // rt: <pattern or '-'> <number> <string>
1477                             String num = tokens.next();
1478                             str = tokens.next();
1479                             Number n = (Number) ref.parse(num);
1480                             assertEquals(where + '"' + pat + "\".format(" + num + ")",
1481                                          str, fmt.format(n));
1482                             if (cmd == 3) { // fp:
1483                                 n = (Number) ref.parse(tokens.next());
1484                             }
1485                             if (cmd != 2) { // != f:
1486                                 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1487                                              n, fmt.parse(str));
1488                             }
1489                         }
1490                         // p: <pattern or '-'> <string to parse> <exp. number>
1491                         else {
1492                             str = tokens.next();
1493                             String expstr = tokens.next();
1494                             Number parsed = fmt.parse(str);
1495                             Number exp = (Number) ref.parse(expstr);
1496                             assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1497                                          exp, parsed);
1498                         }
1499                     } catch (ParseException e) {
1500                         errln(where + '"' + pat + "\".parse(\"" + str +
1501                               "\") threw an exception");
1502                         e.printStackTrace();
1503                     }
1504                     break;
1505                 case 6:
1506                     // perr: <pattern or '-'> <invalid string>
1507                     errln("Under construction");
1508                     return;
1509                 case 7:
1510                     // pat: <pattern> <exp. toPattern, or '-' or 'err'>
1511                     String testpat = tokens.next();
1512                     String exppat  = tokens.next();
1513                     boolean err    = exppat.equals("err");
1514                     if (testpat.equals("-")) {
1515                         if (err) {
1516                             errln("Invalid command \"pat: - err\" at " +  tokens.describePosition());
1517                             continue;
1518                         }
1519                         testpat = pat;
1520                     }
1521                     if (exppat.equals("-")) exppat = testpat;
1522                     try {
1523                         DecimalFormat f = null;
1524                         if (testpat == pat) { // [sic]
1525                             f = fmt;
1526                         } else {
1527                             f = new DecimalFormat(testpat);
1528                             f.setParseStrict(strict);
1529                         }
1530                         if (err) {
1531                             errln(where + "Invalid pattern \"" + testpat +
1532                                   "\" was accepted");
1533                         } else {
1534                             assertEquals(where + '"' + testpat + "\".toPattern()",
1535                                          exppat, f.toPattern());
1536                         }
1537                     } catch (IllegalArgumentException iae2) {
1538                         if (err) {
1539                             logln("Ok: " + where + "Invalid pattern \"" + testpat +
1540                                   "\" threw an exception");
1541                         } else {
1542                             errln(where + "Valid pattern \"" + testpat +
1543                                   "\" threw an exception");
1544                             iae2.printStackTrace();
1545                         }
1546                     }
1547                     break;
1548                 case 8: // fpc:
1549                     tok = tokens.next();
1550                     if (!tok.equals("-")) {
1551                         mloc = tok;
1552                         ULocale l = new ULocale(mloc);
1553                         try {
1554                             mfmt = MeasureFormat.getCurrencyFormat(l);
1555                         } catch (IllegalArgumentException iae) {
1556                             errln(where + "Loc \"" + tok + '"');
1557                             iae.printStackTrace();
1558                             tokens.next(); // consume remaining tokens
1559                             tokens.next();
1560                             tokens.next();
1561                             continue;
1562                         }
1563                     }
1564                     str = null;
1565                     try {
1566                         // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1567                         String currAmt = tokens.next();
1568                         str = tokens.next();
1569                         CurrencyAmount n = parseCurrencyAmount(currAmt, ref, '/');
1570                         assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
1571                                      str, mfmt.format(n));
1572                         n = parseCurrencyAmount(tokens.next(), ref, '/');
1573                         assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
1574                                      n, (CurrencyAmount) mfmt.parseObject(str));
1575                     } catch (ParseException e) {
1576                         errln(where + '"' + pat + "\".parse(\"" + str +
1577                               "\") threw an exception");
1578                         e.printStackTrace();
1579                     }
1580                     break;
1581                 case 9: // strict= true or false
1582                     strict = "true".equalsIgnoreCase(tokens.next());
1583                     logln("Setting strict to:\t" + strict);
1584                     break;
1585                 case -1:
1586                     errln("Unknown command \"" + tok + "\" at " + tokens.describePosition());
1587                     return;
1588                 }
1589             }
1590         } catch (java.io.IOException e) {
1591 //#if defined(FOUNDATION10) || defined(J2SE13)
1592 //##        throw new RuntimeException(e.getMessage());
1593 //#else
1594             throw new RuntimeException(e);
1595 //#endif
1596         }
1597     }
1598
1599     public void TestRounding() {
1600         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
1601         if (false) { // for debugging specific value
1602             nf.setRoundingMode(BigDecimal.ROUND_HALF_UP);
1603             checkRounding(nf, new BigDecimal("300.0300000000"), 0, new BigDecimal("0.020000000"));
1604         }
1605         // full tests
1606         int[] roundingIncrements = {1, 2, 5, 20, 50, 100};
1607         int[] testValues = {0, 300};
1608         for (int j = 0; j < testValues.length; ++j) {
1609             for (int mode = BigDecimal.ROUND_UP; mode < BigDecimal.ROUND_HALF_EVEN; ++mode) {
1610                 nf.setRoundingMode(mode);
1611                 for (int increment = 0; increment < roundingIncrements.length; ++increment) {
1612                     BigDecimal base = new BigDecimal(testValues[j]);
1613                     BigDecimal rInc = new BigDecimal(roundingIncrements[increment]);
1614                     checkRounding(nf,  base, 20, rInc);
1615                     rInc = new BigDecimal("1.000000000").divide(rInc);
1616                     checkRounding(nf,  base, 20, rInc);
1617                 }
1618             }
1619         }
1620     }
1621
1622     void checkRounding(DecimalFormat nf, BigDecimal base, int iterations, BigDecimal increment) {
1623 //#if defined(FOUNDATION10)
1624 //##        nf.setRoundingIncrement(increment);
1625 //#else
1626         nf.setRoundingIncrement(increment.toBigDecimal());
1627 //#endif
1628         BigDecimal lastParsed = new BigDecimal(Integer.MIN_VALUE); // used to make sure that rounding is monotonic
1629         for (int i = -iterations; i <= iterations; ++i) {
1630             BigDecimal iValue = base.add(increment.multiply(new BigDecimal(i)).movePointLeft(1));
1631             BigDecimal smallIncrement = new BigDecimal("0.00000001");
1632             if (iValue.signum() != 0) {
1633                 smallIncrement.multiply(iValue); // scale unless zero
1634             }
1635             // we not only test the value, but some values in a small range around it.
1636             lastParsed = checkRound(nf, iValue.subtract(smallIncrement), lastParsed);
1637             lastParsed = checkRound(nf, iValue, lastParsed);
1638             lastParsed = checkRound(nf, iValue.add(smallIncrement), lastParsed);
1639         }
1640     }
1641
1642     private BigDecimal checkRound(DecimalFormat nf, BigDecimal iValue, BigDecimal lastParsed) {
1643         String formatedBigDecimal = nf.format(iValue);
1644         String formattedDouble = nf.format(iValue.doubleValue());
1645         if (!equalButForTrailingZeros(formatedBigDecimal, formattedDouble)) {
1646             errln("Failure at: " + iValue + " (" + iValue.doubleValue() + ")"
1647                   + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1648                   + ",\tRounding-increment: " + nf.getRoundingIncrement()
1649                   + ",\tdouble: " + formattedDouble
1650                   + ",\tBigDecimal: " + formatedBigDecimal);
1651         } else {
1652             logln("Value: " + iValue
1653                   + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1654                   + ",\tRounding-increment: " + nf.getRoundingIncrement()
1655                   + ",\tdouble: " + formattedDouble
1656                   + ",\tBigDecimal: " + formatedBigDecimal);
1657         }
1658         try {
1659             // Number should have compareTo(...)
1660             BigDecimal parsed = toBigDecimal(nf.parse(formatedBigDecimal));
1661             if (lastParsed.compareTo(parsed) > 0) {
1662                 errln("Rounding wrong direction!: " + lastParsed + " > " + parsed);
1663             }
1664             lastParsed = parsed;
1665         } catch (ParseException e) {
1666             errln("Parse Failure with: " + formatedBigDecimal);
1667         }
1668         return lastParsed;
1669     }
1670
1671     static BigDecimal toBigDecimal(Number number) {
1672         return number instanceof BigDecimal ? (BigDecimal) number
1673             : number instanceof BigInteger ? new BigDecimal((BigInteger)number)
1674 //#if defined(FOUNDATION10)
1675 //#else
1676             : number instanceof java.math.BigDecimal ? new BigDecimal((java.math.BigDecimal)number)
1677 //#endif
1678             : number instanceof Double ? new BigDecimal(number.doubleValue())
1679             : number instanceof Float ? new BigDecimal(number.floatValue())
1680             : new BigDecimal(number.longValue());
1681     }
1682
1683     static String[] roundingModeNames = {
1684         "ROUND_UP", "ROUND_DOWN", "ROUND_CEILING", "ROUND_FLOOR",
1685         "ROUND_HALF_UP", "ROUND_HALF_DOWN", "ROUND_HALF_EVEN",
1686         "ROUND_UNNECESSARY"
1687     };
1688
1689     private static boolean equalButForTrailingZeros(String formatted1, String formatted2) {
1690         if (formatted1.length() == formatted2.length()) return formatted1.equals(formatted2);
1691         return stripFinalZeros(formatted1).equals(stripFinalZeros(formatted2));
1692     }
1693
1694     private static String stripFinalZeros(String formatted) {
1695         int len1 = formatted.length();
1696         char ch;
1697         while (len1 > 0 && ((ch = formatted.charAt(len1-1)) == '0' || ch == '.')) --len1;
1698         return formatted.substring(0,len1);
1699     }
1700
1701     //------------------------------------------------------------------
1702     // Support methods
1703     //------------------------------------------------------------------
1704
1705     // Format-Parse test
1706     public void expect2(NumberFormat fmt, Number n, String exp) {
1707         // Don't round-trip format test, since we explicitly do it
1708         expect(fmt, n, exp, false);
1709         expect(fmt, exp, n);
1710     }
1711     // Format-Parse test
1712     public void expect3(NumberFormat fmt, Number n, String exp) {
1713         // Don't round-trip format test, since we explicitly do it
1714         expect_rbnf(fmt, n, exp, false);
1715         expect_rbnf(fmt, exp, n);
1716     }
1717
1718     // Format-Parse test (convenience)
1719     public void expect2(NumberFormat fmt, double n, String exp) {
1720         expect2(fmt, new Double(n), exp);
1721     }
1722     // Format-Parse test (convenience)
1723     public void expect3(NumberFormat fmt, double n, String exp) {
1724         expect3(fmt, new Double(n), exp);
1725     }
1726
1727     // Format-Parse test (convenience)
1728     public void expect2(NumberFormat fmt, long n, String exp) {
1729         expect2(fmt, new Long(n), exp);
1730     }
1731     // Format-Parse test (convenience)
1732     public void expect3(NumberFormat fmt, long n, String exp) {
1733         expect3(fmt, new Long(n), exp);
1734     }
1735
1736     // Format test
1737     public void expect(NumberFormat fmt, Number n, String exp, boolean rt) {
1738         StringBuffer saw = new StringBuffer();
1739         FieldPosition pos = new FieldPosition(0);
1740         fmt.format(n, saw, pos);
1741         String pat = ((DecimalFormat)fmt).toPattern();
1742         if (saw.toString().equals(exp)) {
1743             logln("Ok   " + n + " x " +
1744                   pat + " = \"" +
1745                   saw + "\"");
1746             // We should be able to round-trip the formatted string =>
1747             // number => string (but not the other way around: number
1748             // => string => number2, might have number2 != number):
1749             if (rt) {
1750                 try {
1751                     Number n2 = fmt.parse(exp);
1752                     StringBuffer saw2 = new StringBuffer();
1753                     fmt.format(n2, saw2, pos);
1754                     if (!saw2.toString().equals(exp)) {
1755                         errln("FAIL \"" + exp + "\" => " + n2 +
1756                               " => \"" + saw2 + '"');
1757                     }
1758                 } catch (ParseException e) {
1759                     errln(e.getMessage());
1760                     return;
1761                 }
1762             }
1763         } else {
1764             errln("FAIL " + n + " x " +
1765                   pat + " = \"" +
1766                   saw + "\", expected \"" + exp + "\"");
1767         }
1768     }
1769     // Format test
1770     public void expect_rbnf(NumberFormat fmt, Number n, String exp, boolean rt) {
1771         StringBuffer saw = new StringBuffer();
1772         FieldPosition pos = new FieldPosition(0);
1773         fmt.format(n, saw, pos);
1774         if (saw.toString().equals(exp)) {
1775             logln("Ok   " + n + " = \"" +
1776                   saw + "\"");
1777             // We should be able to round-trip the formatted string =>
1778             // number => string (but not the other way around: number
1779             // => string => number2, might have number2 != number):
1780             if (rt) {
1781                 try {
1782                     Number n2 = fmt.parse(exp);
1783                     StringBuffer saw2 = new StringBuffer();
1784                     fmt.format(n2, saw2, pos);
1785                     if (!saw2.toString().equals(exp)) {
1786                         errln("FAIL \"" + exp + "\" => " + n2 +
1787                               " => \"" + saw2 + '"');
1788                     }
1789                 } catch (ParseException e) {
1790                     errln(e.getMessage());
1791                     return;
1792                 }
1793             }
1794         } else {
1795             errln("FAIL " + n + " = \"" +
1796                   saw + "\", expected \"" + exp + "\"");
1797         }
1798     }
1799
1800     // Format test (convenience)
1801     public void expect(NumberFormat fmt, Number n, String exp) {
1802         expect(fmt, n, exp, true);
1803     }
1804
1805     // Format test (convenience)
1806     public void expect(NumberFormat fmt, double n, String exp) {
1807         expect(fmt, new Double(n), exp);
1808     }
1809
1810     // Format test (convenience)
1811     public void expect(NumberFormat fmt, long n, String exp) {
1812         expect(fmt, new Long(n), exp);
1813     }
1814
1815     // Parse test
1816     public void expect(NumberFormat fmt, String str, Number n) {
1817         Number num = null;
1818         try {
1819             num = (Number) fmt.parse(str);
1820         } catch (ParseException e) {
1821             errln(e.getMessage());
1822             return;
1823         }
1824         String pat = ((DecimalFormat)fmt).toPattern();
1825         // A little tricky here -- make sure Double(12345.0) and
1826         // Long(12345) match.
1827         if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1828             logln("Ok   \"" + str + "\" x " +
1829                   pat + " = " +
1830                   num);
1831         } else {
1832             errln("FAIL \"" + str + "\" x " +
1833                   pat + " = " +
1834                   num + ", expected " + n);
1835         }
1836     }
1837
1838     // Parse test
1839     public void expect_rbnf(NumberFormat fmt, String str, Number n) {
1840         Number num = null;
1841         try {
1842             num = (Number) fmt.parse(str);
1843         } catch (ParseException e) {
1844             errln(e.getMessage());
1845             return;
1846         }
1847         // A little tricky here -- make sure Double(12345.0) and
1848         // Long(12345) match.
1849         if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1850             logln("Ok   \"" + str + " = " +
1851                   num);
1852         } else {
1853             errln("FAIL \"" + str + " = " +
1854                   num + ", expected " + n);
1855         }
1856     }
1857
1858     // Parse test (convenience)
1859     public void expect(NumberFormat fmt, String str, double n) {
1860         expect(fmt, str, new Double(n));
1861     }
1862
1863     // Parse test (convenience)
1864     public void expect(NumberFormat fmt, String str, long n) {
1865         expect(fmt, str, new Long(n));
1866     }
1867
1868     private void expectCurrency(NumberFormat nf, Currency curr,
1869                                 double value, String string) {
1870         DecimalFormat fmt = (DecimalFormat) nf;
1871         if (curr != null) {
1872             fmt.setCurrency(curr);
1873         }
1874         String s = fmt.format(value).replace('\u00A0', ' ');
1875
1876         if (s.equals(string)) {
1877             logln("Ok: " + value + " x " + curr + " => " + s);
1878         } else {
1879             errln("FAIL: " + value + " x " + curr + " => " + s +
1880                   ", expected " + string);
1881         }
1882     }
1883
1884     public void expectPad(DecimalFormat fmt, String pat, int pos) {
1885         expectPad(fmt, pat, pos, 0, (char)0);
1886     }
1887
1888     public void expectPad(DecimalFormat fmt, final String pat, int pos, int width, final char pad) {
1889         int apos = 0, awidth = 0;
1890         char apadStr;
1891         try {
1892             fmt.applyPattern(pat);
1893             apos = fmt.getPadPosition();
1894             awidth = fmt.getFormatWidth();
1895             apadStr = fmt.getPadCharacter();
1896         } catch (Exception e) {
1897             apos = -1;
1898             awidth = width;
1899             apadStr = pad;
1900         }
1901
1902         if (apos == pos && awidth == width && apadStr == pad) {
1903             logln("Ok   \"" + pat + "\" pos="
1904                     + apos + ((pos == -1) ? "" : " width=" + awidth + " pad=" + apadStr));
1905         } else {
1906             errln("FAIL \"" + pat + "\" pos=" + apos + " width="
1907                     + awidth + " pad=" + apadStr + ", expected "
1908                     + pos + " " + width + " " + pad);
1909         }
1910     }
1911
1912     public void expectPat(DecimalFormat fmt, final String exp) {
1913         String pat = fmt.toPattern();
1914         if (pat.equals(exp)) {
1915             logln("Ok   \"" + pat + "\"");
1916         } else {
1917             errln("FAIL \"" + pat + "\", expected \"" + exp + "\"");
1918         }
1919     }
1920
1921     public void TestJB3832(){
1922         ULocale locale = new ULocale("pt_PT@currency=PTE");
1923         NumberFormat format = NumberFormat.getCurrencyInstance(locale);
1924         Currency curr = Currency.getInstance(locale);
1925         logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
1926         CurrencyAmount cAmt = new CurrencyAmount(1150.50, curr);
1927         logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
1928         String str = format.format(cAmt);
1929         String expected = "1,150$50\u00a0Esc.";
1930         if(!expected.equals(str)){
1931             errln("Did not get the expected output Expected: "+expected+" Got: "+ str);
1932         }
1933     }
1934
1935     public void TestStrictParse() {
1936         String[] pass = {
1937             "0",           // single zero before end of text is not leading
1938             "0 ",          // single zero at end of number is not leading
1939             "0.",          // single zero before period (or decimal, it's ambiguous) is not leading
1940             "0,",          // single zero before comma (not group separator) is not leading
1941             "0.0",         // single zero before decimal followed by digit is not leading
1942             "0. ",         // same as above before period (or decimal) is not leading
1943             "0.100,5",     // comma stops parse of decimal (no grouping)
1944             ".00",         // leading decimal is ok, even with zeros
1945             "1234567",     // group separators are not required
1946             "12345, ",     // comma not followed by digit is not a group separator, but end of number
1947             "1,234, ",     // if group separator is present, group sizes must be appropriate
1948             "1,234,567",   // ...secondary too
1949             "0E",          // an exponnent not followed by zero or digits is not an exponent
1950         };
1951         String[] fail = {
1952             "00",        // leading zero before zero
1953             "012",       // leading zero before digit
1954             "0,456",     // leading zero before group separator
1955             "1,2",       // wrong number of digits after group separator
1956             ",0",        // leading group separator before zero
1957             ",1",        // leading group separator before digit
1958             ",.02",      // leading group separator before decimal
1959             "1,.02",     // group separator before decimal
1960             "1,,200",    // multiple group separators
1961             "1,45",      // wrong number of digits in primary group
1962             "1,45 that", // wrong number of digits in primary group
1963             "1,45.34",   // wrong number of digits in primary group
1964             "1234,567",  // wrong number of digits in secondary group
1965             "12,34,567", // wrong number of digits in secondary group
1966             "1,23,456,7890", // wrong number of digits in primary and secondary groups
1967         };
1968
1969         DecimalFormat nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
1970         runStrictParseBatch(nf, pass, fail);
1971
1972         String[] scientificPass = {
1973             "0E2",      // single zero before exponent is ok
1974             "1234E2",   // any number of digits before exponent is ok
1975             "1,234E",   // an exponent string not followed by zero or digits is not an exponent
1976         };
1977         String[] scientificFail = {
1978             "00E2",     // double zeros fail
1979             "1,234E2",  // group separators with exponent fail
1980         };
1981
1982         nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
1983         runStrictParseBatch(nf, scientificPass, scientificFail);
1984
1985         String[] mixedPass = {
1986             "12,34,567",
1987             "12,34,567,",
1988             "12,34,567, that",
1989             "12,34,567 that",
1990         };
1991         String[] mixedFail = {
1992             "12,34,56",
1993             "12,34,56,",
1994             "12,34,56, that ",
1995             "12,34,56 that",
1996         };
1997
1998         nf = new DecimalFormat("#,##,##0.#");
1999         runStrictParseBatch(nf, mixedPass, mixedFail);
2000     }
2001
2002     void runStrictParseBatch(DecimalFormat nf, String[] pass, String[] fail) {
2003         nf.setParseStrict(false);
2004         runStrictParseTests("should pass", nf, pass, true);
2005         runStrictParseTests("should also pass", nf, fail, true);
2006         nf.setParseStrict(true);
2007         runStrictParseTests("should still pass", nf, pass, true);
2008         runStrictParseTests("should fail", nf, fail, false);
2009     }
2010
2011     void runStrictParseTests(String msg, DecimalFormat nf, String[] tests, boolean pass) {
2012         logln("");
2013         logln("pattern: '" + nf.toPattern() + "'");
2014         logln(msg);
2015         for (int i = 0; i < tests.length; ++i) {
2016             String str = tests[i];
2017             ParsePosition pp = new ParsePosition(0);
2018             Number n = nf.parse(str, pp);
2019             String formatted = n != null ? nf.format(n) : "null";
2020             String err = pp.getErrorIndex() == -1 ? "" : "(error at " + pp.getErrorIndex() + ")";
2021             if ((err.length() == 0) != pass) {
2022                 errln("'" + str + "' parsed '" +
2023                       str.substring(0, pp.getIndex()) +
2024                       "' returned " + n + " formats to '" +
2025                       formatted + "' " + err);
2026             } else {
2027                 if (err.length() > 0) {
2028                     err = "got expected " + err;
2029                 }
2030                 logln("'" + str + "' parsed '" +
2031                       str.substring(0, pp.getIndex()) +
2032                       "' returned " + n + " formats to '" +
2033                       formatted + "' " + err);
2034             }
2035         }
2036     }
2037     public void TestJB5251(){
2038         //save default locale
2039         ULocale defaultLocale = ULocale.getDefault();
2040         ULocale.setDefault(new ULocale("qr_QR"));
2041         try {
2042             NumberFormat.getInstance();
2043         }
2044         catch (Exception e) {
2045             errln("Numberformat threw exception for non-existent locale. It should use the default.");
2046         }
2047         //reset default locale
2048         ULocale.setDefault(defaultLocale);
2049     }
2050
2051     public void TestParseReturnType() {
2052         String[] defaultNonBigDecimals = {
2053             "123",      // Long
2054             "123.0",    // Long
2055             "0.0",      // Long
2056             "12345678901234567890"      // BigInteger
2057         };
2058
2059         String[] doubles = {
2060             "-0.0",
2061             "NaN",
2062             "\u221E"    // Infinity
2063         };
2064
2065         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2066         DecimalFormat nf = new DecimalFormat("#.#", sym);
2067
2068         if (nf.isParseBigDecimal()) {
2069             errln("FAIL: isParseDecimal() must return false by default");
2070         }
2071
2072         // isParseBigDecimal() is false
2073         for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2074             try {
2075                 Number n = nf.parse(defaultNonBigDecimals[i]);
2076                 if (n instanceof BigDecimal) {
2077                     errln("FAIL: parse returns BigDecimal instance");
2078                 }
2079             } catch (ParseException e) {
2080                 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2081             }
2082         }
2083         // parse results for doubls must be always Double
2084         for (int i = 0; i < doubles.length; i++) {
2085             try {
2086                 Number n = nf.parse(doubles[i]);
2087                 if (!(n instanceof Double)) {
2088                     errln("FAIL: parse does not return Double instance");
2089                 }
2090             } catch (ParseException e) {
2091                 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2092             }
2093         }
2094
2095         // force this DecimalFormat to return BigDecimal
2096         nf.setParseBigDecimal(true);
2097         if (!nf.isParseBigDecimal()) {
2098             errln("FAIL: isParseBigDecimal() must return true");
2099         }
2100
2101         // isParseBigDecimal() is true
2102         for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2103             try {
2104                 Number n = nf.parse(defaultNonBigDecimals[i]);
2105                 if (!(n instanceof BigDecimal)) {
2106                     errln("FAIL: parse does not return BigDecimal instance");
2107                 }
2108             } catch (ParseException e) {
2109                 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2110             }
2111         }
2112         // parse results for doubls must be always Double
2113         for (int i = 0; i < doubles.length; i++) {
2114             try {
2115                 Number n = nf.parse(doubles[i]);
2116                 if (!(n instanceof Double)) {
2117                     errln("FAIL: parse does not return Double instance");
2118                 }
2119             } catch (ParseException e) {
2120                 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2121             }
2122         }
2123     }
2124
2125     public void TestNonpositiveMultiplier() {
2126         DecimalFormat df = new DecimalFormat("0");
2127
2128         // test zero multiplier
2129
2130         try {
2131             df.setMultiplier(0);
2132
2133             // bad
2134             errln("DecimalFormat.setMultiplier(0) did not throw an IllegalArgumentException");
2135         } catch (IllegalArgumentException ex) {
2136             // good
2137         }
2138
2139         // test negative multiplier
2140
2141         try {
2142             df.setMultiplier(-1);
2143
2144             if (df.getMultiplier() != -1) {
2145                 errln("DecimalFormat.setMultiplier(-1) did not change the multiplier to -1");
2146                 return;
2147             }
2148
2149             // good
2150         } catch (IllegalArgumentException ex) {
2151             // bad
2152             errln("DecimalFormat.setMultiplier(-1) threw an IllegalArgumentException");
2153             return;
2154         }
2155
2156         expect(df, "1122.123", -1122.123);
2157         expect(df, "-1122.123", 1122.123);
2158         expect(df, "1.2", -1.2);
2159         expect(df, "-1.2", 1.2);
2160
2161         expect2(df, Long.MAX_VALUE, BigInteger.valueOf(Long.MAX_VALUE).negate().toString());
2162         expect2(df, Long.MIN_VALUE, BigInteger.valueOf(Long.MIN_VALUE).negate().toString());
2163         expect2(df, Long.MAX_VALUE / 2, BigInteger.valueOf(Long.MAX_VALUE / 2).negate().toString());
2164         expect2(df, Long.MIN_VALUE / 2, BigInteger.valueOf(Long.MIN_VALUE / 2).negate().toString());
2165
2166         expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2167         expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2168         
2169 //#if defined(FOUNDATION10)
2170 //#else
2171         expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2172         expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2173 //#endif
2174     }
2175
2176     public void TestJB5358() {
2177         int numThreads = 10;
2178         String numstr = "12345";
2179         double expected = 12345;
2180         DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2181         DecimalFormat fmt = new DecimalFormat("#.#", sym);
2182         ArrayList errors = new ArrayList();
2183
2184         ParseThreadJB5358[] threads = new ParseThreadJB5358[numThreads];
2185         for (int i = 0; i < numThreads; i++) {
2186             threads[i] = new ParseThreadJB5358((DecimalFormat)fmt.clone(), numstr, expected, errors);
2187             threads[i].start();
2188         }
2189         for (int i = 0; i < numThreads; i++) {
2190             try {
2191                 threads[i].join();
2192             } catch (InterruptedException ie) {
2193                 ie.printStackTrace();
2194             }
2195         }
2196         if (errors.size() != 0) {
2197             StringBuffer errBuf = new StringBuffer();
2198             for (int i = 0; i < errors.size(); i++) {
2199                 errBuf.append((String)errors.get(i));
2200                 errBuf.append("\n");
2201             }
2202             errln("FAIL: " + errBuf);
2203         }
2204     }
2205
2206     static private class ParseThreadJB5358 extends Thread {
2207         private DecimalFormat decfmt;
2208         private String numstr;
2209         private double expect;
2210         private ArrayList errors;
2211
2212         public ParseThreadJB5358(DecimalFormat decfmt, String numstr, double expect, ArrayList errors) {
2213             this.decfmt = decfmt;
2214             this.numstr = numstr;
2215             this.expect = expect;
2216             this.errors = errors;
2217         }
2218
2219         public void run() {
2220             for (int i = 0; i < 10000; i++) {
2221                 try {
2222                     Number n = decfmt.parse(numstr);
2223                     if (n.doubleValue() != expect) {
2224                         synchronized(errors) {
2225                             errors.add(new String("Bad parse result - expected:" + expect + " actual:" + n.doubleValue()));
2226                         }
2227                     }
2228                 } catch (Throwable t) {
2229                     synchronized(errors) {
2230                         errors.add(new String(t.getClass().getName() + " - " + t.getMessage()));
2231                     }
2232                 }
2233             }
2234         }
2235     }
2236     
2237     public void TestSetCurrency() {
2238         DecimalFormatSymbols decf1 = DecimalFormatSymbols.getInstance(ULocale.US);
2239         DecimalFormatSymbols decf2 = DecimalFormatSymbols.getInstance(ULocale.US);
2240         decf2.setCurrencySymbol("UKD");
2241         DecimalFormat format1 = new DecimalFormat("000.000", decf1);
2242         DecimalFormat format2 = new DecimalFormat("000.000", decf2);
2243         Currency euro = Currency.getInstance("EUR");
2244         format1.setCurrency(euro);
2245         format2.setCurrency(euro);
2246         assertEquals("Reset with currency symbol", format1, format2);
2247     }
2248 }