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