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