1/* GENERATED SOURCE. DO NOT MODIFY. */ 2// © 2016 and later: Unicode, Inc. and others. 3// License & terms of use: http://www.unicode.org/copyright.html#License 4/* 5 ******************************************************************************* 6 * Copyright (C) 2001-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 11/** 12 * Port From: ICU4C v1.8.1 : format : NumberFormatTest 13 * Source File: $ICU4oot/source/test/intltest/numfmtst.cpp 14 **/ 15 16package android.icu.dev.test.format; 17 18import java.io.IOException; 19import java.math.BigInteger; 20import java.text.AttributedCharacterIterator; 21import java.text.FieldPosition; 22import java.text.Format; 23import java.text.ParseException; 24import java.text.ParsePosition; 25import java.util.ArrayList; 26import java.util.Iterator; 27import java.util.List; 28import java.util.Locale; 29import java.util.Set; 30 31import org.junit.Test; 32 33import android.icu.dev.test.TestFmwk; 34import android.icu.dev.test.TestUtil; 35import android.icu.dev.test.format.IntlTestDecimalFormatAPIC.FieldContainer; 36import android.icu.impl.ICUConfig; 37import android.icu.impl.LocaleUtility; 38import android.icu.impl.data.ResourceReader; 39import android.icu.impl.data.TokenIterator; 40import android.icu.math.BigDecimal; 41import android.icu.math.MathContext; 42import android.icu.text.CompactDecimalFormat; 43import android.icu.text.DecimalFormat; 44import android.icu.text.DecimalFormatSymbols; 45import android.icu.text.DisplayContext; 46import android.icu.text.MeasureFormat; 47import android.icu.text.NumberFormat; 48import android.icu.text.NumberFormat.NumberFormatFactory; 49import android.icu.text.NumberFormat.SimpleNumberFormatFactory; 50import android.icu.text.NumberingSystem; 51import android.icu.text.RuleBasedNumberFormat; 52import android.icu.util.Currency; 53import android.icu.util.CurrencyAmount; 54import android.icu.util.ULocale; 55 56public class NumberFormatTest extends TestFmwk { 57 58 private static ULocale EN = new ULocale("en"); 59 60 private static Number toNumber(String s) { 61 if (s.equals("NaN")) { 62 return Double.NaN; 63 } else if (s.equals("-Inf")) { 64 return Double.NEGATIVE_INFINITY; 65 } else if (s.equals("Inf")) { 66 return Double.POSITIVE_INFINITY; 67 } 68 return new BigDecimal(s); 69 } 70 71 72 private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU = 73 new DataDrivenNumberFormatTestUtility.CodeUnderTest() { 74 @Override 75 public Character Id() { return 'J'; } 76 77 @Override 78 public String format(NumberFormatTestData tuple) { 79 DecimalFormat fmt = newDecimalFormat(tuple); 80 String actual = fmt.format(toNumber(tuple.format)); 81 String expected = tuple.output; 82 if (!expected.equals(actual)) { 83 return "Expected " + expected + ", got " + actual; 84 } 85 return null; 86 } 87 88 @Override 89 public String toPattern(NumberFormatTestData tuple) { 90 DecimalFormat fmt = newDecimalFormat(tuple); 91 StringBuilder result = new StringBuilder(); 92 if (tuple.toPattern != null) { 93 String expected = tuple.toPattern; 94 String actual = fmt.toPattern(); 95 if (!expected.equals(actual)) { 96 result.append("Expected toPattern=" + expected + ", got " + actual); 97 } 98 } 99 if (tuple.toLocalizedPattern != null) { 100 String expected = tuple.toLocalizedPattern; 101 String actual = fmt.toLocalizedPattern(); 102 if (!expected.equals(actual)) { 103 result.append("Expected toLocalizedPattern=" + expected + ", got " + actual); 104 } 105 } 106 return result.length() == 0 ? null : result.toString(); 107 } 108 109 @Override 110 public String parse(NumberFormatTestData tuple) { 111 DecimalFormat fmt = newDecimalFormat(tuple); 112 ParsePosition ppos = new ParsePosition(0); 113 Number actual = fmt.parse(tuple.parse, ppos); 114 if (ppos.getIndex() == 0) { 115 if (!tuple.output.equals("fail")) { 116 return "Parse error expected."; 117 } 118 return null; 119 } 120 if (tuple.output.equals("fail")) { 121 return "Parse succeeded: "+actual+", but was expected to fail."; 122 } 123 Number expected = toNumber(tuple.output); 124 // number types cannot be compared, this is the best we can do. 125 if (expected.doubleValue() != (actual.doubleValue())) { 126 return "Expected: " + expected + ", got: " + actual; 127 } 128 return null; 129 } 130 131 @Override 132 public String parseCurrency(NumberFormatTestData tuple) { 133 DecimalFormat fmt = newDecimalFormat(tuple); 134 ParsePosition ppos = new ParsePosition(0); 135 CurrencyAmount currAmt = fmt.parseCurrency(tuple.parse, ppos); 136 if (ppos.getIndex() == 0) { 137 if (!tuple.output.equals("fail")) { 138 return "Parse error expected."; 139 } 140 return null; 141 } 142 if (tuple.output.equals("fail")) { 143 return "Parse succeeded: "+currAmt+", but was expected to fail."; 144 } 145 Number expected = toNumber(tuple.output); 146 Number actual = currAmt.getNumber(); 147 // number types cannot be compared, this is the best we can do. 148 if (expected.doubleValue() != (actual.doubleValue())) { 149 return "Expected: " + expected + ", got: " + actual; 150 } 151 152 if (!tuple.outputCurrency.equals(currAmt.getCurrency().toString())) { 153 return "Expected currency: " + tuple.outputCurrency + ", got: " + currAmt.getCurrency(); 154 } 155 return null; 156 } 157 158 /** 159 * @param tuple 160 * @return 161 */ 162 private DecimalFormat newDecimalFormat(NumberFormatTestData tuple) { 163 164 DecimalFormat fmt = new DecimalFormat( 165 tuple.pattern == null ? "0" : tuple.pattern, 166 new DecimalFormatSymbols(tuple.locale == null ? EN : tuple.locale)); 167 adjustDecimalFormat(tuple, fmt); 168 return fmt; 169 } 170 /** 171 * @param tuple 172 * @param fmt 173 */ 174 private void adjustDecimalFormat(NumberFormatTestData tuple, DecimalFormat fmt) { 175 if (tuple.minIntegerDigits != null) { 176 fmt.setMinimumIntegerDigits(tuple.minIntegerDigits); 177 } 178 if (tuple.maxIntegerDigits != null) { 179 fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits); 180 } 181 if (tuple.minFractionDigits != null) { 182 fmt.setMinimumFractionDigits(tuple.minFractionDigits); 183 } 184 if (tuple.maxFractionDigits != null) { 185 fmt.setMaximumFractionDigits(tuple.maxFractionDigits); 186 } 187 if (tuple.currency != null) { 188 fmt.setCurrency(tuple.currency); 189 } 190 if (tuple.minGroupingDigits != null) { 191 // Oops we don't support this. 192 } 193 if (tuple.useSigDigits != null) { 194 fmt.setSignificantDigitsUsed( 195 tuple.useSigDigits != 0); 196 } 197 if (tuple.minSigDigits != null) { 198 fmt.setMinimumSignificantDigits(tuple.minSigDigits); 199 } 200 if (tuple.maxSigDigits != null) { 201 fmt.setMaximumSignificantDigits(tuple.maxSigDigits); 202 } 203 if (tuple.useGrouping != null) { 204 fmt.setGroupingUsed(tuple.useGrouping != 0); 205 } 206 if (tuple.multiplier != null) { 207 fmt.setMultiplier(tuple.multiplier); 208 } 209 if (tuple.roundingIncrement != null) { 210 fmt.setRoundingIncrement(tuple.roundingIncrement.doubleValue()); 211 } 212 if (tuple.formatWidth != null) { 213 fmt.setFormatWidth(tuple.formatWidth); 214 } 215 if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) { 216 fmt.setPadCharacter(tuple.padCharacter.charAt(0)); 217 } 218 if (tuple.useScientific != null) { 219 fmt.setScientificNotation(tuple.useScientific != 0); 220 } 221 if (tuple.grouping != null) { 222 fmt.setGroupingSize(tuple.grouping); 223 } 224 if (tuple.grouping2 != null) { 225 fmt.setSecondaryGroupingSize(tuple.grouping2); 226 } 227 if (tuple.roundingMode != null) { 228 fmt.setRoundingMode(tuple.roundingMode); 229 } 230 if (tuple.currencyUsage != null) { 231 fmt.setCurrencyUsage(tuple.currencyUsage); 232 } if (tuple.minimumExponentDigits != null) { 233 fmt.setMinimumExponentDigits( 234 tuple.minimumExponentDigits.byteValue()); 235 } 236 if (tuple.exponentSignAlwaysShown != null) { 237 fmt.setExponentSignAlwaysShown( 238 tuple.exponentSignAlwaysShown != 0); 239 } 240 if (tuple.decimalSeparatorAlwaysShown != null) { 241 fmt.setDecimalSeparatorAlwaysShown( 242 tuple.decimalSeparatorAlwaysShown != 0); 243 } 244 if (tuple.padPosition != null) { 245 fmt.setPadPosition(tuple.padPosition); 246 } 247 if (tuple.positivePrefix != null) { 248 fmt.setPositivePrefix(tuple.positivePrefix); 249 } 250 if (tuple.positiveSuffix != null) { 251 fmt.setPositiveSuffix(tuple.positiveSuffix); 252 } 253 if (tuple.negativePrefix != null) { 254 fmt.setNegativePrefix(tuple.negativePrefix); 255 } 256 if (tuple.negativeSuffix != null) { 257 fmt.setNegativeSuffix(tuple.negativeSuffix); 258 } 259 if (tuple.localizedPattern != null) { 260 fmt.applyLocalizedPattern(tuple.localizedPattern); 261 } 262 int lenient = tuple.lenient == null ? 1 : tuple.lenient.intValue(); 263 fmt.setParseStrict(lenient == 0); 264 if (tuple.parseIntegerOnly != null) { 265 fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0); 266 } 267 if (tuple.decimalPatternMatchRequired != null) { 268 fmt.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0); 269 } 270 if (tuple.parseNoExponent != null) { 271 // Oops, not supported for now 272 } 273 } 274 }; 275 276 277 private DataDrivenNumberFormatTestUtility.CodeUnderTest JDK = 278 new DataDrivenNumberFormatTestUtility.CodeUnderTest() { 279 @Override 280 public Character Id() { return 'K'; } 281 282 @Override 283 public String format(NumberFormatTestData tuple) { 284 java.text.DecimalFormat fmt = newDecimalFormat(tuple); 285 String actual = fmt.format(toNumber(tuple.format)); 286 String expected = tuple.output; 287 if (!expected.equals(actual)) { 288 return "Expected " + expected + ", got " + actual; 289 } 290 return null; 291 } 292 293 @Override 294 public String toPattern(NumberFormatTestData tuple) { 295 java.text.DecimalFormat fmt = newDecimalFormat(tuple); 296 StringBuilder result = new StringBuilder(); 297 if (tuple.toPattern != null) { 298 String expected = tuple.toPattern; 299 String actual = fmt.toPattern(); 300 if (!expected.equals(actual)) { 301 result.append("Expected toPattern=" + expected + ", got " + actual); 302 } 303 } 304 if (tuple.toLocalizedPattern != null) { 305 String expected = tuple.toLocalizedPattern; 306 String actual = fmt.toLocalizedPattern(); 307 if (!expected.equals(actual)) { 308 result.append("Expected toLocalizedPattern=" + expected + ", got " + actual); 309 } 310 } 311 return result.length() == 0 ? null : result.toString(); 312 } 313 314 @Override 315 public String parse(NumberFormatTestData tuple) { 316 java.text.DecimalFormat fmt = newDecimalFormat(tuple); 317 ParsePosition ppos = new ParsePosition(0); 318 Number actual = fmt.parse(tuple.parse, ppos); 319 if (ppos.getIndex() == 0) { 320 if (!tuple.output.equals("fail")) { 321 return "Parse error expected."; 322 } 323 return null; 324 } 325 if (tuple.output.equals("fail")) { 326 return "Parse succeeded: "+actual+", but was expected to fail."; 327 } 328 Number expected = toNumber(tuple.output); 329 // number types cannot be compared, this is the best we can do. 330 if (expected.doubleValue() != actual.doubleValue()) { 331 return "Expected: " + expected + ", got: " + actual; 332 } 333 return null; 334 } 335 336 337 338 /** 339 * @param tuple 340 * @return 341 */ 342 private java.text.DecimalFormat newDecimalFormat(NumberFormatTestData tuple) { 343 java.text.DecimalFormat fmt = new java.text.DecimalFormat( 344 tuple.pattern == null ? "0" : tuple.pattern, 345 new java.text.DecimalFormatSymbols( 346 (tuple.locale == null ? EN : tuple.locale).toLocale())); 347 adjustDecimalFormat(tuple, fmt); 348 return fmt; 349 } 350 351 /** 352 * @param tuple 353 * @param fmt 354 */ 355 private void adjustDecimalFormat(NumberFormatTestData tuple, java.text.DecimalFormat fmt) { 356 if (tuple.minIntegerDigits != null) { 357 fmt.setMinimumIntegerDigits(tuple.minIntegerDigits); 358 } 359 if (tuple.maxIntegerDigits != null) { 360 fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits); 361 } 362 if (tuple.minFractionDigits != null) { 363 fmt.setMinimumFractionDigits(tuple.minFractionDigits); 364 } 365 if (tuple.maxFractionDigits != null) { 366 fmt.setMaximumFractionDigits(tuple.maxFractionDigits); 367 } 368 if (tuple.currency != null) { 369 fmt.setCurrency(java.util.Currency.getInstance(tuple.currency.toString())); 370 } 371 if (tuple.minGroupingDigits != null) { 372 // Oops we don't support this. 373 } 374 if (tuple.useSigDigits != null) { 375 // Oops we don't support this 376 } 377 if (tuple.minSigDigits != null) { 378 // Oops we don't support this 379 } 380 if (tuple.maxSigDigits != null) { 381 // Oops we don't support this 382 } 383 if (tuple.useGrouping != null) { 384 fmt.setGroupingUsed(tuple.useGrouping != 0); 385 } 386 if (tuple.multiplier != null) { 387 fmt.setMultiplier(tuple.multiplier); 388 } 389 if (tuple.roundingIncrement != null) { 390 // Not supported 391 } 392 if (tuple.formatWidth != null) { 393 // Not supported 394 } 395 if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) { 396 // Not supported 397 } 398 if (tuple.useScientific != null) { 399 // Not supported 400 } 401 if (tuple.grouping != null) { 402 fmt.setGroupingSize(tuple.grouping); 403 } 404 if (tuple.grouping2 != null) { 405 // Not supported 406 } 407 if (tuple.roundingMode != null) { 408 // Not supported 409 } 410 if (tuple.currencyUsage != null) { 411 // Not supported 412 } 413 if (tuple.minimumExponentDigits != null) { 414 // Not supported 415 } 416 if (tuple.exponentSignAlwaysShown != null) { 417 // Not supported 418 } 419 if (tuple.decimalSeparatorAlwaysShown != null) { 420 fmt.setDecimalSeparatorAlwaysShown( 421 tuple.decimalSeparatorAlwaysShown != 0); 422 } 423 if (tuple.padPosition != null) { 424 // Not supported 425 } 426 if (tuple.positivePrefix != null) { 427 fmt.setPositivePrefix(tuple.positivePrefix); 428 } 429 if (tuple.positiveSuffix != null) { 430 fmt.setPositiveSuffix(tuple.positiveSuffix); 431 } 432 if (tuple.negativePrefix != null) { 433 fmt.setNegativePrefix(tuple.negativePrefix); 434 } 435 if (tuple.negativeSuffix != null) { 436 fmt.setNegativeSuffix(tuple.negativeSuffix); 437 } 438 if (tuple.localizedPattern != null) { 439 fmt.applyLocalizedPattern(tuple.localizedPattern); 440 } 441 442 // lenient parsing not supported by JDK 443 if (tuple.parseIntegerOnly != null) { 444 fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0); 445 } 446 if (tuple.decimalPatternMatchRequired != null) { 447 // Oops, not supported 448 } 449 if (tuple.parseNoExponent != null) { 450 // Oops, not supported for now 451 } 452 } 453 }; 454 455 @Test 456 public void TestRoundingScientific10542() { 457 DecimalFormat format = 458 new DecimalFormat("0.00E0"); 459 460 int[] roundingModes = { 461 BigDecimal.ROUND_CEILING, 462 BigDecimal.ROUND_DOWN, 463 BigDecimal.ROUND_FLOOR, 464 BigDecimal.ROUND_HALF_DOWN, 465 BigDecimal.ROUND_HALF_EVEN, 466 BigDecimal.ROUND_HALF_UP, 467 BigDecimal.ROUND_UP}; 468 String[] descriptions = { 469 "Round Ceiling", 470 "Round Down", 471 "Round Floor", 472 "Round half down", 473 "Round half even", 474 "Round half up", 475 "Round up"}; 476 477 double[] values = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016}; 478 // The order of these expected values correspond to the order of roundingModes and the order of values. 479 String[][] expected = { 480 {"-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3"}, 481 {"-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3"}, 482 {"-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3"}, 483 {"-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3"}, 484 {"-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3"}, 485 {"-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3"}, 486 {"-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"}}; 487 verifyRounding(format, values, expected, roundingModes, descriptions); 488 values = new double[]{-3006.0, -3005, -3004, 3014, 3015, 3016}; 489 // The order of these expected values correspond to the order of roundingModes and the order of values. 490 expected = new String[][]{ 491 {"-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3"}, 492 {"-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3"}, 493 {"-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3"}, 494 {"-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3"}, 495 {"-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3"}, 496 {"-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3"}, 497 {"-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"}}; 498 verifyRounding(format, values, expected, roundingModes, descriptions); 499 values = new double[]{0.0, -0.0}; 500 // The order of these expected values correspond to the order of roundingModes and the order of values. 501 expected = new String[][]{ 502 {"0.00E0", "-0.00E0"}, 503 {"0.00E0", "-0.00E0"}, 504 {"0.00E0", "-0.00E0"}, 505 {"0.00E0", "-0.00E0"}, 506 {"0.00E0", "-0.00E0"}, 507 {"0.00E0", "-0.00E0"}, 508 {"0.00E0", "-0.00E0"}}; 509 verifyRounding(format, values, expected, roundingModes, descriptions); 510 values = new double[]{1e25, 1e25 + 1e15, 1e25 - 1e15}; 511 // The order of these expected values correspond to the order of roundingModes and the order of values. 512 expected = new String[][]{ 513 {"1.00E25", "1.01E25", "1.00E25"}, 514 {"1.00E25", "1.00E25", "9.99E24"}, 515 {"1.00E25", "1.00E25", "9.99E24"}, 516 {"1.00E25", "1.00E25", "1.00E25"}, 517 {"1.00E25", "1.00E25", "1.00E25"}, 518 {"1.00E25", "1.00E25", "1.00E25"}, 519 {"1.00E25", "1.01E25", "1.00E25"}}; 520 verifyRounding(format, values, expected, roundingModes, descriptions); 521 values = new double[]{-1e25, -1e25 + 1e15, -1e25 - 1e15}; 522 // The order of these expected values correspond to the order of roundingModes and the order of values. 523 expected = new String[][]{ 524 {"-1.00E25", "-9.99E24", "-1.00E25"}, 525 {"-1.00E25", "-9.99E24", "-1.00E25"}, 526 {"-1.00E25", "-1.00E25", "-1.01E25"}, 527 {"-1.00E25", "-1.00E25", "-1.00E25"}, 528 {"-1.00E25", "-1.00E25", "-1.00E25"}, 529 {"-1.00E25", "-1.00E25", "-1.00E25"}, 530 {"-1.00E25", "-1.00E25", "-1.01E25"}}; 531 verifyRounding(format, values, expected, roundingModes, descriptions); 532 values = new double[]{1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35}; 533 // The order of these expected values correspond to the order of roundingModes and the order of values. 534 expected = new String[][]{ 535 {"1.00E-25", "1.01E-25", "1.00E-25"}, 536 {"1.00E-25", "1.00E-25", "9.99E-26"}, 537 {"1.00E-25", "1.00E-25", "9.99E-26"}, 538 {"1.00E-25", "1.00E-25", "1.00E-25"}, 539 {"1.00E-25", "1.00E-25", "1.00E-25"}, 540 {"1.00E-25", "1.00E-25", "1.00E-25"}, 541 {"1.00E-25", "1.01E-25", "1.00E-25"}}; 542 verifyRounding(format, values, expected, roundingModes, descriptions); 543 values = new double[]{-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35}; 544 // The order of these expected values correspond to the order of roundingModes and the order of values. 545 expected = new String[][]{ 546 {"-1.00E-25", "-9.99E-26", "-1.00E-25"}, 547 {"-1.00E-25", "-9.99E-26", "-1.00E-25"}, 548 {"-1.00E-25", "-1.00E-25", "-1.01E-25"}, 549 {"-1.00E-25", "-1.00E-25", "-1.00E-25"}, 550 {"-1.00E-25", "-1.00E-25", "-1.00E-25"}, 551 {"-1.00E-25", "-1.00E-25", "-1.00E-25"}, 552 {"-1.00E-25", "-1.00E-25", "-1.01E-25"}}; 553 verifyRounding(format, values, expected, roundingModes, descriptions); 554 } 555 556 private void verifyRounding(DecimalFormat format, double[] values, String[][] expected, int[] roundingModes, 557 String[] descriptions) { 558 for (int i = 0; i < roundingModes.length; i++) { 559 format.setRoundingMode(roundingModes[i]); 560 for (int j = 0; j < values.length; j++) { 561 assertEquals(descriptions[i]+" " +values[j], expected[i][j], format.format(values[j])); 562 } 563 } 564 } 565 566 @Test 567 public void Test10419RoundingWith0FractionDigits() { 568 Object[][] data = new Object[][]{ 569 {BigDecimal.ROUND_CEILING, 1.488, "2"}, 570 {BigDecimal.ROUND_DOWN, 1.588, "1"}, 571 {BigDecimal.ROUND_FLOOR, 1.588, "1"}, 572 {BigDecimal.ROUND_HALF_DOWN, 1.5, "1"}, 573 {BigDecimal.ROUND_HALF_EVEN, 2.5, "2"}, 574 {BigDecimal.ROUND_HALF_UP, 2.5, "3"}, 575 {BigDecimal.ROUND_UP, 1.5, "2"}, 576 }; 577 NumberFormat nff = NumberFormat.getNumberInstance(ULocale.ENGLISH); 578 nff.setMaximumFractionDigits(0); 579 for (Object[] item : data) { 580 nff.setRoundingMode(((Integer) item[0]).intValue()); 581 assertEquals("Test10419", item[2], nff.format(item[1])); 582 } 583 } 584 585 @Test 586 public void TestParseNegativeWithFaLocale() { 587 DecimalFormat parser = (DecimalFormat) NumberFormat.getInstance(new ULocale("fa")); 588 try { 589 double value = parser.parse("-0,5").doubleValue(); 590 assertEquals("Expect -0.5", -0.5, value); 591 } catch (ParseException e) { 592 TestFmwk.errln("Parsing -0.5 should have succeeded."); 593 } 594 } 595 596 @Test 597 public void TestParseNegativeWithAlternativeMinusSign() { 598 DecimalFormat parser = (DecimalFormat) NumberFormat.getInstance(new ULocale("en")); 599 try { 600 double value = parser.parse("\u208B0.5").doubleValue(); 601 assertEquals("Expect -0.5", -0.5, value); 602 } catch (ParseException e) { 603 TestFmwk.errln("Parsing -0.5 should have succeeded."); 604 } 605 } 606 607 // Test various patterns 608 @Test 609 public void TestPatterns() { 610 611 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); 612 final String pat[] = { "#.#", "#.", ".#", "#" }; 613 int pat_length = pat.length; 614 final String newpat[] = { "#0.#", "#0.", "#.0", "#" }; 615 final String num[] = { "0", "0.", ".0", "0" }; 616 for (int i=0; i<pat_length; ++i) 617 { 618 DecimalFormat fmt = new DecimalFormat(pat[i], sym); 619 String newp = fmt.toPattern(); 620 if (!newp.equals(newpat[i])) 621 errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] + 622 "; " + newp + " seen instead"); 623 624 String s = ((NumberFormat)fmt).format(0); 625 if (!s.equals(num[i])) 626 { 627 errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] + 628 "; " + s + " seen instead"); 629 logln("Min integer digits = " + fmt.getMinimumIntegerDigits()); 630 } 631 // BigInteger 0 - ticket#4731 632 s = ((NumberFormat)fmt).format(BigInteger.ZERO); 633 if (!s.equals(num[i])) 634 { 635 errln("FAIL: Pattern " + pat[i] + " should format BigInteger zero as " + num[i] + 636 "; " + s + " seen instead"); 637 logln("Min integer digits = " + fmt.getMinimumIntegerDigits()); 638 } 639 } 640 } 641 642 // Test exponential pattern 643 @Test 644 public void TestExponential() { 645 646 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); 647 final String pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" }; 648 int pat_length = pat.length; 649 650 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 }; 651 int val_length = val.length; 652 final String valFormat[] = { 653 // 0.####E0 654 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271", 655 // 00.000E00 656 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272", 657 // ##0.######E000 658 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273", 659 // 0.###E0;[0.###E0] 660 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" }; 661 /*double valParse[] = 662 { 663 0.01234, 123460000, 1.23E300, -3.1416E-271, 664 0.01234, 123460000, 1.23E300, -3.1416E-271, 665 0.01234, 123456800, 1.23E300, -3.141593E-271, 666 0.01234, 123500000, 1.23E300, -3.142E-271, 667 };*/ //The variable is never used 668 669 int lval[] = { 0, -1, 1, 123456789 }; 670 int lval_length = lval.length; 671 final String lvalFormat[] = { 672 // 0.####E0 673 "0E0", "-1E0", "1E0", "1.2346E8", 674 // 00.000E00 675 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07", 676 // ##0.######E000 677 "0E000", "-1E000", "1E000", "123.4568E006", 678 // 0.###E0;[0.###E0] 679 "0E0", "[1E0]", "1E0", "1.235E8" }; 680 int lvalParse[] = 681 { 682 0, -1, 1, 123460000, 683 0, -1, 1, 123460000, 684 0, -1, 1, 123456800, 685 0, -1, 1, 123500000, 686 }; 687 int ival = 0, ilval = 0; 688 for (int p = 0; p < pat_length; ++p) { 689 DecimalFormat fmt = new DecimalFormat(pat[p], sym); 690 logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" + fmt.toPattern() + "\""); 691 int v; 692 for (v = 0; v < val_length; ++v) { 693 String s; 694 s = ((NumberFormat) fmt).format(val[v]); 695 logln(" " + val[v] + " -format-> " + s); 696 if (!s.equals(valFormat[v + ival])) 697 errln("FAIL: Expected " + valFormat[v + ival]); 698 699 ParsePosition pos = new ParsePosition(0); 700 double a = fmt.parse(s, pos).doubleValue(); 701 if (pos.getIndex() == s.length()) { 702 logln(" -parse-> " + Double.toString(a)); 703 // Use epsilon comparison as necessary 704 } else 705 errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a); 706 } 707 for (v = 0; v < lval_length; ++v) { 708 String s; 709 s = ((NumberFormat) fmt).format(lval[v]); 710 logln(" " + lval[v] + "L -format-> " + s); 711 if (!s.equals(lvalFormat[v + ilval])) 712 errln("ERROR: Expected " + lvalFormat[v + ilval] + " Got: " + s); 713 714 ParsePosition pos = new ParsePosition(0); 715 long a = 0; 716 Number A = fmt.parse(s, pos); 717 if (A != null) { 718 a = A.longValue(); 719 if (pos.getIndex() == s.length()) { 720 logln(" -parse-> " + a); 721 if (a != lvalParse[v + ilval]) 722 errln("FAIL: Expected " + lvalParse[v + ilval]); 723 } else 724 errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + Long.toString(a)); 725 } else { 726 errln("Fail to parse the string: " + s); 727 } 728 } 729 ival += val_length; 730 ilval += lval_length; 731 } 732 } 733 734 // Test the handling of quotes 735 @Test 736 public void TestQuotes() { 737 738 StringBuffer pat; 739 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); 740 pat = new StringBuffer("a'fo''o'b#"); 741 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym); 742 String s = ((NumberFormat)fmt).format(123); 743 logln("Pattern \"" + pat + "\""); 744 logln(" Format 123 . " + s); 745 if (!s.equals("afo'ob123")) 746 errln("FAIL: Expected afo'ob123"); 747 748 s =""; 749 pat = new StringBuffer("a''b#"); 750 fmt = new DecimalFormat(pat.toString(), sym); 751 s = ((NumberFormat)fmt).format(123); 752 logln("Pattern \"" + pat + "\""); 753 logln(" Format 123 . " + s); 754 if (!s.equals("a'b123")) 755 errln("FAIL: Expected a'b123"); 756 } 757 758 @Test 759 public void TestParseCurrencyTrailingSymbol() { 760 // see sun bug 4709840 761 NumberFormat fmt = NumberFormat.getCurrencyInstance(Locale.GERMANY); 762 float val = 12345.67f; 763 String str = fmt.format(val); 764 logln("val: " + val + " str: " + str); 765 try { 766 Number num = fmt.parse(str); 767 logln("num: " + num); 768 } catch (ParseException e) { 769 errln("parse of '" + str + "' threw exception: " + e); 770 } 771 } 772 773 /** 774 * Test the handling of the currency symbol in patterns. 775 **/ 776 @Test 777 public void TestCurrencySign() { 778 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); 779 StringBuffer pat = new StringBuffer(""); 780 char currency = 0x00A4; 781 // "\xA4#,##0.00;-\xA4#,##0.00" 782 pat.append(currency).append("#,##0.00;-").append(currency).append("#,##0.00"); 783 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym); 784 String s = ((NumberFormat) fmt).format(1234.56); 785 pat = new StringBuffer(); 786 logln("Pattern \"" + fmt.toPattern() + "\""); 787 logln(" Format " + 1234.56 + " . " + s); 788 assertEquals("symbol, pos", "$1,234.56", s); 789 790 s = ((NumberFormat) fmt).format(-1234.56); 791 logln(" Format " + Double.toString(-1234.56) + " . " + s); 792 assertEquals("symbol, neg", "-$1,234.56", s); 793 794 pat.setLength(0); 795 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00" 796 pat.append(currency).append(currency).append(" #,##0.00;").append(currency).append(currency).append(" -#,##0.00"); 797 fmt = new DecimalFormat(pat.toString(), sym); 798 s = ((NumberFormat) fmt).format(1234.56); 799 logln("Pattern \"" + fmt.toPattern() + "\""); 800 logln(" Format " + Double.toString(1234.56) + " . " + s); 801 assertEquals("name, pos", "USD 1,234.56", s); 802 803 s = ((NumberFormat) fmt).format(-1234.56); 804 logln(" Format " + Double.toString(-1234.56) + " . " + s); 805 assertEquals("name, neg", "USD -1,234.56", s); 806 } 807 808 @Test 809 public void TestSpaceParsing() { 810 // the data are: 811 // the string to be parsed, parsed position, parsed error index 812 String[][] DATA = { 813 {"$124", "4", "-1"}, 814 {"$124 $124", "4", "-1"}, 815 {"$124 ", "4", "-1"}, 816 {"$ 124 ", "5", "-1"}, 817 {"$\u00A0124 ", "5", "-1"}, 818 {" $ 124 ", "0", "0"}, // TODO: need to handle space correctly 819 {"124$", "0", "3"}, // TODO: need to handle space correctly 820 // {"124 $", "5", "-1"}, TODO: OK or NOT? 821 {"124 $", "0", "3"}, 822 }; 823 NumberFormat foo = NumberFormat.getCurrencyInstance(); 824 for (int i = 0; i < DATA.length; ++i) { 825 ParsePosition parsePosition = new ParsePosition(0); 826 String stringToBeParsed = DATA[i][0]; 827 int parsedPosition = Integer.parseInt(DATA[i][1]); 828 int errorIndex = Integer.parseInt(DATA[i][2]); 829 try { 830 Number result = foo.parse(stringToBeParsed, parsePosition); 831 if (parsePosition.getIndex() != parsedPosition || 832 parsePosition.getErrorIndex() != errorIndex) { 833 errln("FAILED parse " + stringToBeParsed + "; parse position: " + parsePosition.getIndex() + "; error position: " + parsePosition.getErrorIndex()); 834 } 835 if (parsePosition.getErrorIndex() == -1 && 836 result.doubleValue() != 124) { 837 errln("FAILED parse " + stringToBeParsed + "; value " + result.doubleValue()); 838 } 839 } catch (Exception e) { 840 errln("FAILED " + e.toString()); 841 } 842 } 843 } 844 845 846 @Test 847 public void TestMultiCurrencySign() { 848 String[][] DATA = { 849 // the fields in the following test are: 850 // locale, 851 // currency pattern (with negative pattern), 852 // currency number to be formatted, 853 // currency format using currency symbol name, such as "$" for USD, 854 // currency format using currency ISO name, such as "USD", 855 // currency format using plural name, such as "US dollars". 856 // for US locale 857 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"}, 858 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"}, 859 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollars1.00"}, 860 // for CHINA locale 861 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY1,234.56", "\u4EBA\u6C11\u5E011,234.56"}, 862 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY1,234.56)", "(\u4EBA\u6C11\u5E011,234.56)"}, 863 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY1.00", "\u4EBA\u6C11\u5E011.00"} 864 }; 865 866 String doubleCurrencyStr = "\u00A4\u00A4"; 867 String tripleCurrencyStr = "\u00A4\u00A4\u00A4"; 868 869 for (int i=0; i<DATA.length; ++i) { 870 String locale = DATA[i][0]; 871 String pat = DATA[i][1]; 872 Double numberToBeFormat = new Double(DATA[i][2]); 873 DecimalFormatSymbols sym = new DecimalFormatSymbols(new ULocale(locale)); 874 for (int j=1; j<=3; ++j) { 875 // j represents the number of currency sign in the pattern. 876 if (j == 2) { 877 pat = pat.replaceAll("\u00A4", doubleCurrencyStr); 878 } else if (j == 3) { 879 pat = pat.replaceAll("\u00A4\u00A4", tripleCurrencyStr); 880 } 881 DecimalFormat fmt = new DecimalFormat(pat, sym); 882 String s = ((NumberFormat) fmt).format(numberToBeFormat); 883 // DATA[i][3] is the currency format result using a 884 // single currency sign. 885 // DATA[i][4] is the currency format result using 886 // double currency sign. 887 // DATA[i][5] is the currency format result using 888 // triple currency sign. 889 // DATA[i][j+2] is the currency format result using 890 // 'j' number of currency sign. 891 String currencyFormatResult = DATA[i][2+j]; 892 if (!s.equals(currencyFormatResult)) { 893 errln("FAIL format: Expected " + currencyFormatResult); 894 } 895 try { 896 // mix style parsing 897 for (int k=3; k<=5; ++k) { 898 // DATA[i][3] is the currency format result using a 899 // single currency sign. 900 // DATA[i][4] is the currency format result using 901 // double currency sign. 902 // DATA[i][5] is the currency format result using 903 // triple currency sign. 904 String oneCurrencyFormat = DATA[i][k]; 905 if (fmt.parse(oneCurrencyFormat).doubleValue() != 906 numberToBeFormat.doubleValue()) { 907 errln("FAILED parse " + oneCurrencyFormat); 908 } 909 } 910 } catch (ParseException e) { 911 errln("FAILED, DecimalFormat parse currency: " + e.toString()); 912 } 913 } 914 } 915 } 916 917 @Test 918 public void TestCurrencyFormatForMixParsing() { 919 MeasureFormat curFmt = MeasureFormat.getCurrencyFormat(new ULocale("en_US")); 920 String[] formats = { 921 "$1,234.56", // string to be parsed 922 "USD1,234.56", 923 "US dollars1,234.56", 924 "1,234.56 US dollars" 925 }; 926 try { 927 for (int i = 0; i < formats.length; ++i) { 928 String stringToBeParsed = formats[i]; 929 CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(stringToBeParsed); 930 Number val = parsedVal.getNumber(); 931 if (!val.equals(new BigDecimal("1234.56"))) { 932 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val); 933 } 934 if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) { 935 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency"); 936 } 937 } 938 } catch (ParseException e) { 939 errln("parse FAILED: " + e.toString()); 940 } 941 } 942 943 @Test 944 public void TestDecimalFormatCurrencyParse() { 945 // Locale.US 946 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); 947 StringBuffer pat = new StringBuffer(""); 948 char currency = 0x00A4; 949 // "\xA4#,##0.00;-\xA4#,##0.00" 950 pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00"); 951 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym); 952 String[][] DATA = { 953 // the data are: 954 // string to be parsed, the parsed result (number) 955 {"$1.00", "1"}, 956 {"USD1.00", "1"}, 957 {"1.00 US dollar", "1"}, 958 {"$1,234.56", "1234.56"}, 959 {"USD1,234.56", "1234.56"}, 960 {"1,234.56 US dollar", "1234.56"}, 961 }; 962 try { 963 for (int i = 0; i < DATA.length; ++i) { 964 String stringToBeParsed = DATA[i][0]; 965 double parsedResult = Double.parseDouble(DATA[i][1]); 966 Number num = fmt.parse(stringToBeParsed); 967 if (num.doubleValue() != parsedResult) { 968 errln("FAIL parse: Expected " + parsedResult); 969 } 970 } 971 } catch (ParseException e) { 972 errln("FAILED, DecimalFormat parse currency: " + e.toString()); 973 } 974 } 975 976 /** 977 * Test localized currency patterns. 978 */ 979 @Test 980 public void TestCurrency() { 981 String[] DATA = { 982 "fr", "CA", "", "1,50\u00a0$", 983 "de", "DE", "", "1,50\u00a0\u20AC", 984 "de", "DE", "PREEURO", "1,50\u00a0DM", 985 "fr", "FR", "", "1,50\u00a0\u20AC", 986 "fr", "FR", "PREEURO", "1,50\u00a0F", 987 }; 988 989 for (int i=0; i<DATA.length; i+=4) { 990 Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]); 991 NumberFormat fmt = NumberFormat.getCurrencyInstance(locale); 992 String s = fmt.format(1.50); 993 if (s.equals(DATA[i+3])) { 994 logln("Ok: 1.50 x " + locale + " => " + s); 995 } else { 996 logln("FAIL: 1.50 x " + locale + " => " + s + 997 ", expected " + DATA[i+3]); 998 } 999 } 1000 1001 // format currency with CurrencyAmount 1002 for (int i=0; i<DATA.length; i+=4) { 1003 Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]); 1004 1005 Currency curr = Currency.getInstance(locale); 1006 logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false})); 1007 CurrencyAmount cAmt = new CurrencyAmount(1.5, curr); 1008 logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode 1009 1010 NumberFormat fmt = NumberFormat.getCurrencyInstance(locale); 1011 String sCurr = fmt.format(cAmt); 1012 if (sCurr.equals(DATA[i+3])) { 1013 logln("Ok: 1.50 x " + locale + " => " + sCurr); 1014 } else { 1015 errln("FAIL: 1.50 x " + locale + " => " + sCurr + 1016 ", expected " + DATA[i+3]); 1017 } 1018 } 1019 1020 //Cover MeasureFormat.getCurrencyFormat() 1021 ULocale save = ULocale.getDefault(); 1022 ULocale.setDefault(ULocale.US); 1023 MeasureFormat curFmt = MeasureFormat.getCurrencyFormat(); 1024 String strBuf = curFmt.format(new CurrencyAmount(new Float(1234.56), Currency.getInstance("USD"))); 1025 1026 try { 1027 CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(strBuf); 1028 Number val = parsedVal.getNumber(); 1029 if (!val.equals(new BigDecimal("1234.56"))) { 1030 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val); 1031 } 1032 if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) { 1033 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency"); 1034 } 1035 } 1036 catch (ParseException e) { 1037 errln("FAIL: " + e.getMessage()); 1038 } 1039 ULocale.setDefault(save); 1040 } 1041 1042 @Test 1043 public void TestCurrencyIsoPluralFormat() { 1044 String[][] DATA = { 1045 // the data are: 1046 // locale, 1047 // currency amount to be formatted, 1048 // currency ISO code to be formatted, 1049 // format result using CURRENCYSTYLE, 1050 // format result using ISOCURRENCYSTYLE, 1051 // format result using PLURALCURRENCYSTYLE, 1052 {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"}, 1053 {"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"}, 1054 {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"}, 1055 {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00美元"}, 1056 {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56美元"}, 1057 {"zh_CN", "1", "CNY", "¥1.00", "CNY1.00", "1.00人民币"}, 1058 {"zh_CN", "1234.56", "CNY", "¥1,234.56", "CNY1,234.56", "1,234.56人民币"}, 1059 {"ru_RU", "1", "RUB", "1,00 \u20BD", "1,00 RUB", "1,00 российского рубля"}, 1060 {"ru_RU", "2", "RUB", "2,00 \u20BD", "2,00 RUB", "2,00 российского рубля"}, 1061 {"ru_RU", "5", "RUB", "5,00 \u20BD", "5,00 RUB", "5,00 российского рубля"}, 1062 // test locale without currency information 1063 {"root", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"}, 1064 {"root@numbers=latn", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"}, // ensure that the root locale is still used with modifiers 1065 {"root@numbers=arab", "-1.23", "USD", "\u061C-\u0661\u066B\u0662\u0663\u00A0US$", "\u061C-\u0661\u066B\u0662\u0663\u00A0USD", "\u061C-\u0661\u066B\u0662\u0663 USD"}, // ensure that the root locale is still used with modifiers 1066 {"es_AR", "1", "INR", "INR\u00A01,00", "INR\u00A01,00", "1,00 rupia india"}, 1067 {"ar_EG", "1", "USD", "١٫٠٠\u00A0US$", "١٫٠٠\u00A0USD", "١٫٠٠ دولار أمريكي"}, 1068 }; 1069 1070 for (int i=0; i<DATA.length; ++i) { 1071 for (int k = NumberFormat.CURRENCYSTYLE; 1072 k <= NumberFormat.PLURALCURRENCYSTYLE; 1073 ++k) { 1074 // k represents currency format style. 1075 if ( k != NumberFormat.CURRENCYSTYLE && 1076 k != NumberFormat.ISOCURRENCYSTYLE && 1077 k != NumberFormat.PLURALCURRENCYSTYLE ) { 1078 continue; 1079 } 1080 String localeString = DATA[i][0]; 1081 Double numberToBeFormat = new Double(DATA[i][1]); 1082 String currencyISOCode = DATA[i][2]; 1083 ULocale locale = new ULocale(localeString); 1084 NumberFormat numFmt = NumberFormat.getInstance(locale, k); 1085 numFmt.setCurrency(Currency.getInstance(currencyISOCode)); 1086 String strBuf = numFmt.format(numberToBeFormat); 1087 int resultDataIndex = k-1; 1088 if ( k == NumberFormat.CURRENCYSTYLE ) { 1089 resultDataIndex = k+2; 1090 } 1091 // DATA[i][resultDataIndex] is the currency format result 1092 // using 'k' currency style. 1093 String formatResult = DATA[i][resultDataIndex]; 1094 if (!strBuf.equals(formatResult)) { 1095 errln("FAIL: localeID: " + localeString + ", expected(" + formatResult.length() + "): \"" + formatResult + "\", actual(" + strBuf.length() + "): \"" + strBuf + "\""); 1096 } 1097 try { 1098 // test parsing, and test parsing for all currency formats. 1099 for (int j = 3; j < 6; ++j) { 1100 // DATA[i][3] is the currency format result using 1101 // CURRENCYSTYLE formatter. 1102 // DATA[i][4] is the currency format result using 1103 // ISOCURRENCYSTYLE formatter. 1104 // DATA[i][5] is the currency format result using 1105 // PLURALCURRENCYSTYLE formatter. 1106 String oneCurrencyFormatResult = DATA[i][j]; 1107 Number val = numFmt.parse(oneCurrencyFormatResult); 1108 if (val.doubleValue() != numberToBeFormat.doubleValue()) { 1109 errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat); 1110 } 1111 } 1112 } 1113 catch (ParseException e) { 1114 errln("FAIL: " + e.getMessage()); 1115 } 1116 } 1117 } 1118 } 1119 1120 1121 @Test 1122 public void TestMiscCurrencyParsing() { 1123 String[][] DATA = { 1124 // each has: string to be parsed, parsed position, error position 1125 {"1.00 ", "0", "4"}, 1126 {"1.00 UAE dirha", "0", "4"}, 1127 {"1.00 us dollar", "14", "-1"}, 1128 {"1.00 US DOLLAR", "14", "-1"}, 1129 {"1.00 usd", "0", "4"}, 1130 }; 1131 ULocale locale = new ULocale("en_US"); 1132 for (int i=0; i<DATA.length; ++i) { 1133 String stringToBeParsed = DATA[i][0]; 1134 int parsedPosition = Integer.parseInt(DATA[i][1]); 1135 int errorIndex = Integer.parseInt(DATA[i][2]); 1136 NumberFormat numFmt = NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE); 1137 ParsePosition parsePosition = new ParsePosition(0); 1138 Number val = numFmt.parse(stringToBeParsed, parsePosition); 1139 if (parsePosition.getIndex() != parsedPosition || 1140 parsePosition.getErrorIndex() != errorIndex) { 1141 errln("FAIL: parse failed. expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex()); 1142 errln("FAIL: parse failed. expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex()); 1143 } 1144 if (parsePosition.getErrorIndex() == -1 && 1145 val.doubleValue() != 1.00) { 1146 errln("FAIL: parse failed. expected 1.00, actual:" + val); 1147 } 1148 } 1149 } 1150 1151 @Test 1152 public void TestParseCurrency() { 1153 class ParseCurrencyItem { 1154 private final String localeString; 1155 private final String descrip; 1156 private final String currStr; 1157 private final int numExpectPos; 1158 private final int numExpectVal; 1159 private final int curExpectPos; 1160 private final int curExpectVal; 1161 private final String curExpectCurr; 1162 1163 ParseCurrencyItem(String locStr, String desc, String curr, int numExPos, int numExVal, int curExPos, int curExVal, String curExCurr) { 1164 localeString = locStr; 1165 descrip = desc; 1166 currStr = curr; 1167 numExpectPos = numExPos; 1168 numExpectVal = numExVal; 1169 curExpectPos = curExPos; 1170 curExpectVal = curExVal; 1171 curExpectCurr = curExCurr; 1172 } 1173 public String getLocaleString() { return localeString; } 1174 public String getDescrip() { return descrip; } 1175 public String getCurrStr() { return currStr; } 1176 public int getNumExpectPos() { return numExpectPos; } 1177 public int getNumExpectVal() { return numExpectVal; } 1178 public int getCurExpectPos() { return curExpectPos; } 1179 public int getCurExpectVal() { return curExpectVal; } 1180 public String getCurExpectCurr() { return curExpectCurr; } 1181 } 1182 final ParseCurrencyItem[] parseCurrencyItems = { 1183 new ParseCurrencyItem( "en_US", "dollars2", "$2.00", 5, 2, 5, 2, "USD" ), 1184 new ParseCurrencyItem( "en_US", "dollars4", "$4", 2, 4, 2, 4, "USD" ), 1185 new ParseCurrencyItem( "en_US", "dollars9", "9\u00A0$", 0, 0, 0, 0, "" ), 1186 new ParseCurrencyItem( "en_US", "pounds3", "\u00A33.00", 0, 0, 5, 3, "GBP" ), 1187 new ParseCurrencyItem( "en_US", "pounds5", "\u00A35", 0, 0, 2, 5, "GBP" ), 1188 new ParseCurrencyItem( "en_US", "pounds7", "7\u00A0\u00A3", 0, 0, 0, 0, "" ), 1189 new ParseCurrencyItem( "en_US", "euros8", "\u20AC8", 0, 0, 2, 8, "EUR" ), 1190 1191 new ParseCurrencyItem( "en_GB", "pounds3", "\u00A33.00", 5, 3, 5, 3, "GBP" ), 1192 new ParseCurrencyItem( "en_GB", "pounds5", "\u00A35", 2, 5, 2, 5, "GBP" ), 1193 new ParseCurrencyItem( "en_GB", "pounds7", "7\u00A0\u00A3", 0, 0, 0, 0, "" ), 1194 new ParseCurrencyItem( "en_GB", "euros4", "4,00\u00A0\u20AC", 0, 0, 0, 0, "" ), 1195 new ParseCurrencyItem( "en_GB", "euros6", "6\u00A0\u20AC", 0, 0, 0, 0, "" ), 1196 new ParseCurrencyItem( "en_GB", "euros8", "\u20AC8", 0, 0, 2, 8, "EUR" ), 1197 new ParseCurrencyItem( "en_GB", "dollars4", "US$4", 0, 0, 4, 4, "USD" ), 1198 1199 new ParseCurrencyItem( "fr_FR", "euros4", "4,00\u00A0\u20AC", 6, 4, 6, 4, "EUR" ), 1200 new ParseCurrencyItem( "fr_FR", "euros6", "6\u00A0\u20AC", 3, 6, 3, 6, "EUR" ), 1201 new ParseCurrencyItem( "fr_FR", "euros8", "\u20AC8", 0, 0, 0, 0, "" ), 1202 new ParseCurrencyItem( "fr_FR", "dollars2", "$2.00", 0, 0, 0, 0, "" ), 1203 new ParseCurrencyItem( "fr_FR", "dollars4", "$4", 0, 0, 0, 0, "" ), 1204 }; 1205 for (ParseCurrencyItem item: parseCurrencyItems) { 1206 String localeString = item.getLocaleString(); 1207 ULocale uloc = new ULocale(localeString); 1208 NumberFormat fmt = null; 1209 try { 1210 fmt = NumberFormat.getCurrencyInstance(uloc); 1211 } catch (Exception e) { 1212 errln("NumberFormat.getCurrencyInstance fails for locale " + localeString); 1213 continue; 1214 } 1215 String currStr = item.getCurrStr(); 1216 ParsePosition parsePos = new ParsePosition(0); 1217 1218 Number numVal = fmt.parse(currStr, parsePos); 1219 if ( parsePos.getIndex() != item.getNumExpectPos() || (numVal != null && numVal.intValue() != item.getNumExpectVal()) ) { 1220 if (numVal != null) { 1221 errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() + 1222 ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() + 1223 ", get " + parsePos.getIndex() + "/" + numVal.intValue() ); 1224 } else { 1225 errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() + 1226 ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() + 1227 ", get " + parsePos.getIndex() + "/(NULL)" ); 1228 } 1229 } 1230 1231 parsePos.setIndex(0); 1232 CurrencyAmount currAmt = fmt.parseCurrency(currStr, parsePos); 1233 if ( parsePos.getIndex() != item.getCurExpectPos() || (currAmt != null && (currAmt.getNumber().intValue() != item.getCurExpectVal() || 1234 currAmt.getCurrency().getCurrencyCode().compareTo(item.getCurExpectCurr()) != 0)) ) { 1235 if (currAmt != null) { 1236 errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() + 1237 ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() + 1238 ", get " + parsePos.getIndex() + "/" + currAmt.getNumber().intValue() + "/" + currAmt.getCurrency().getCurrencyCode() ); 1239 } else { 1240 errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() + 1241 ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() + 1242 ", get " + parsePos.getIndex() + "/(NULL)" ); 1243 } 1244 } 1245 } 1246 } 1247 1248 @Test 1249 public void TestParseCurrPatternWithDecStyle() { 1250 String currpat = "¤#,##0.00"; 1251 String parsetxt = "x0y$"; 1252 DecimalFormat decfmt = (DecimalFormat)NumberFormat.getInstance(new ULocale("en_US"), NumberFormat.NUMBERSTYLE); 1253 decfmt.applyPattern(currpat); 1254 ParsePosition ppos = new ParsePosition(0); 1255 Number value = decfmt.parse(parsetxt, ppos); 1256 if (ppos.getIndex() != 0) { 1257 errln("DecimalFormat.parse expected to fail but got ppos " + ppos.getIndex() + ", value " + value); 1258 } 1259 } 1260 1261 /** 1262 * Test the Currency object handling, new as of ICU 2.2. 1263 */ 1264 @Test 1265 public void TestCurrencyObject() { 1266 NumberFormat fmt = 1267 NumberFormat.getCurrencyInstance(Locale.US); 1268 1269 expectCurrency(fmt, null, 1234.56, "$1,234.56"); 1270 1271 expectCurrency(fmt, Currency.getInstance(Locale.FRANCE), 1272 1234.56, "\u20AC1,234.56"); // Euro 1273 1274 expectCurrency(fmt, Currency.getInstance(Locale.JAPAN), 1275 1234.56, "\u00A51,235"); // Yen 1276 1277 expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")), 1278 1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548 1279 1280 expectCurrency(fmt, Currency.getInstance(Locale.US), 1281 1234.56, "$1,234.56"); 1282 1283 fmt = NumberFormat.getCurrencyInstance(Locale.FRANCE); 1284 1285 expectCurrency(fmt, null, 1234.56, "1 234,56 \u20AC"); 1286 1287 expectCurrency(fmt, Currency.getInstance(Locale.JAPAN), 1288 1234.56, "1 235 JPY"); // Yen 1289 1290 expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")), 1291 1234.56, "1 234,56 CHF"); // no more rounding here, see cldrbug 5548 1292 1293 expectCurrency(fmt, Currency.getInstance(Locale.US), 1294 1234.56, "1 234,56 $US"); 1295 1296 expectCurrency(fmt, Currency.getInstance(Locale.FRANCE), 1297 1234.56, "1 234,56 \u20AC"); // Euro 1298 } 1299 1300 @Test 1301 public void TestCompatibleCurrencies() { 1302 NumberFormat fmt = 1303 NumberFormat.getCurrencyInstance(Locale.US); 1304 expectParseCurrency(fmt, Currency.getInstance(Locale.JAPAN), "\u00A51,235"); // Yen half-width 1305 expectParseCurrency(fmt, Currency.getInstance(Locale.JAPAN), "\uFFE51,235"); // Yen full-wdith 1306 } 1307 1308 @Test 1309 public void TestCurrencyPatterns() { 1310 int i; 1311 Locale[] locs = NumberFormat.getAvailableLocales(); 1312 for (i=0; i<locs.length; ++i) { 1313 NumberFormat nf = NumberFormat.getCurrencyInstance(locs[i]); 1314 // Make sure currency formats do not have a variable number 1315 // of fraction digits 1316 int min = nf.getMinimumFractionDigits(); 1317 int max = nf.getMaximumFractionDigits(); 1318 if (min != max) { 1319 String a = nf.format(1.0); 1320 String b = nf.format(1.125); 1321 errln("FAIL: " + locs[i] + 1322 " min fraction digits != max fraction digits; "+ 1323 "x 1.0 => " + a + 1324 "; x 1.125 => " + b); 1325 } 1326 1327 // Make sure EURO currency formats have exactly 2 fraction digits 1328 if (nf instanceof DecimalFormat) { 1329 Currency curr = ((DecimalFormat) nf).getCurrency(); 1330 if (curr != null && "EUR".equals(curr.getCurrencyCode())) { 1331 if (min != 2 || max != 2) { 1332 String a = nf.format(1.0); 1333 errln("FAIL: " + locs[i] + 1334 " is a EURO format but it does not have 2 fraction digits; "+ 1335 "x 1.0 => " + 1336 a); 1337 } 1338 } 1339 } 1340 } 1341 } 1342 1343 /** 1344 * Do rudimentary testing of parsing. 1345 */ 1346 @Test 1347 public void TestParse() { 1348 String arg = "0.0"; 1349 DecimalFormat format = new DecimalFormat("00"); 1350 double aNumber = 0l; 1351 try { 1352 aNumber = format.parse(arg).doubleValue(); 1353 } catch (ParseException e) { 1354 System.out.println(e); 1355 } 1356 logln("parse(" + arg + ") = " + aNumber); 1357 } 1358 1359 /** 1360 * Test proper rounding by the format method. 1361 */ 1362 @Test 1363 public void TestRounding487() { 1364 1365 NumberFormat nf = NumberFormat.getInstance(); 1366 roundingTest(nf, 0.00159999, 4, "0.0016"); 1367 roundingTest(nf, 0.00995, 4, "0.01"); 1368 1369 roundingTest(nf, 12.3995, 3, "12.4"); 1370 1371 roundingTest(nf, 12.4999, 0, "12"); 1372 roundingTest(nf, - 19.5, 0, "-20"); 1373 1374 } 1375 1376 /** 1377 * Test the functioning of the secondary grouping value. 1378 */ 1379 @Test 1380 public void TestSecondaryGrouping() { 1381 1382 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); 1383 DecimalFormat f = new DecimalFormat("#,##,###", US); 1384 1385 expect(f, 123456789L, "12,34,56,789"); 1386 expectPat(f, "#,##,###"); 1387 f.applyPattern("#,###"); 1388 1389 f.setSecondaryGroupingSize(4); 1390 expect(f, 123456789L, "12,3456,789"); 1391 expectPat(f, "#,####,###"); 1392 NumberFormat g = NumberFormat.getInstance(new Locale("hi", "IN")); 1393 1394 String out = ""; 1395 long l = 1876543210L; 1396 out = g.format(l); 1397 1398 // expect "1,87,65,43,210", but with Hindi digits 1399 // 01234567890123 1400 boolean ok = true; 1401 if (out.length() != 14) { 1402 ok = false; 1403 } else { 1404 for (int i = 0; i < out.length(); ++i) { 1405 boolean expectGroup = false; 1406 switch (i) { 1407 case 1 : 1408 case 4 : 1409 case 7 : 1410 case 10 : 1411 expectGroup = true; 1412 break; 1413 } 1414 // Later -- fix this to get the actual grouping 1415 // character from the resource bundle. 1416 boolean isGroup = (out.charAt(i) == 0x002C); 1417 if (isGroup != expectGroup) { 1418 ok = false; 1419 break; 1420 } 1421 } 1422 } 1423 if (!ok) { 1424 errln("FAIL Expected "+ l + " x hi_IN . \"1,87,65,43,210\" (with Hindi digits), got \"" 1425 + out + "\""); 1426 } else { 1427 logln("Ok " + l + " x hi_IN . \"" + out + "\""); 1428 } 1429 } 1430 1431 /* 1432 * Internal test utility. 1433 */ 1434 private void roundingTest(NumberFormat nf, double x, int maxFractionDigits, final String expected) { 1435 nf.setMaximumFractionDigits(maxFractionDigits); 1436 String out = nf.format(x); 1437 logln(x + " formats with " + maxFractionDigits + " fractional digits to " + out); 1438 if (!out.equals(expected)) 1439 errln("FAIL: Expected " + expected); 1440 } 1441 1442 /** 1443 * Upgrade to alphaWorks 1444 */ 1445 @Test 1446 public void TestExponent() { 1447 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); 1448 DecimalFormat fmt1 = new DecimalFormat("0.###E0", US); 1449 DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US); 1450 int n = 1234; 1451 expect2(fmt1, n, "1.234E3"); 1452 expect2(fmt2, n, "1.234E+3"); 1453 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3" 1454 1455 } 1456 1457 /** 1458 * Upgrade to alphaWorks 1459 */ 1460 @Test 1461 public void TestScientific() { 1462 1463 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); 1464 1465 // Test pattern round-trip 1466 final String PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" }; 1467 int PAT_length = PAT.length; 1468 int DIGITS[] = { 1469 // min int, max int, min frac, max frac 1470 0, 1, 0, 0, // "#E0" 1471 1, 1, 0, 4, // "0.####E0" 1472 2, 2, 3, 3, // "00.000E00" 1473 1, 3, 0, 4, // "##0.####E000" 1474 1, 1, 0, 3, // "0.###E0;[0.###E0]" 1475 }; 1476 for (int i = 0; i < PAT_length; ++i) { 1477 String pat = PAT[i]; 1478 DecimalFormat df = new DecimalFormat(pat, US); 1479 String pat2 = df.toPattern(); 1480 if (pat.equals(pat2)) { 1481 logln("Ok Pattern rt \"" + pat + "\" . \"" + pat2 + "\""); 1482 } else { 1483 errln("FAIL Pattern rt \"" + pat + "\" . \"" + pat2 + "\""); 1484 } 1485 // Make sure digit counts match what we expect 1486 if (df.getMinimumIntegerDigits() != DIGITS[4 * i] 1487 || df.getMaximumIntegerDigits() != DIGITS[4 * i + 1] 1488 || df.getMinimumFractionDigits() != DIGITS[4 * i + 2] 1489 || df.getMaximumFractionDigits() != DIGITS[4 * i + 3]) { 1490 errln("FAIL \""+ pat+ "\" min/max int; min/max frac = " 1491 + df.getMinimumIntegerDigits() + "/" 1492 + df.getMaximumIntegerDigits() + ";" 1493 + df.getMinimumFractionDigits() + "/" 1494 + df.getMaximumFractionDigits() + ", expect " 1495 + DIGITS[4 * i] + "/" 1496 + DIGITS[4 * i + 1] + ";" 1497 + DIGITS[4 * i + 2] + "/" 1498 + DIGITS[4 * i + 3]); 1499 } 1500 } 1501 1502 expect2(new DecimalFormat("#E0", US), 12345.0, "1.2345E4"); 1503 expect(new DecimalFormat("0E0", US), 12345.0, "1E4"); 1504 1505 // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0" 1506 // so result = 1.234568E4 not 1.2345678901E4 1507 //when the pattern problem is finalized, delete comment mark'//' 1508 //of the following code 1509 expect2(NumberFormat.getScientificInstance(Locale.US), 12345.678901, "1.2345678901E4"); 1510 logln("Testing NumberFormat.getScientificInstance(ULocale) ..."); 1511 expect2(NumberFormat.getScientificInstance(ULocale.US), 12345.678901, "1.2345678901E4"); 1512 1513 expect(new DecimalFormat("##0.###E0", US), 12345.0, "12.34E3"); 1514 expect(new DecimalFormat("##0.###E0", US), 12345.00001, "12.35E3"); 1515 expect2(new DecimalFormat("##0.####E0", US), 12345, "12.345E3"); 1516 1517 // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0" 1518 // so result = 1.234568E4 not 1.2345678901E4 1519 expect2(NumberFormat.getScientificInstance(Locale.FRANCE), 12345.678901, "1,2345678901E4"); 1520 logln("Testing NumberFormat.getScientificInstance(ULocale) ..."); 1521 expect2(NumberFormat.getScientificInstance(ULocale.FRANCE), 12345.678901, "1,2345678901E4"); 1522 1523 expect(new DecimalFormat("##0.####E0", US), 789.12345e-9, "789.12E-9"); 1524 expect2(new DecimalFormat("##0.####E0", US), 780.e-9, "780E-9"); 1525 expect(new DecimalFormat(".###E0", US), 45678.0, ".457E5"); 1526 expect2(new DecimalFormat(".###E0", US), 0, ".0E0"); 1527 /* 1528 expect(new DecimalFormat[] { new DecimalFormat("#E0", US), 1529 new DecimalFormat("##E0", US), 1530 new DecimalFormat("####E0", US), 1531 new DecimalFormat("0E0", US), 1532 new DecimalFormat("00E0", US), 1533 new DecimalFormat("000E0", US), 1534 }, 1535 new Long(45678000), 1536 new String[] { "4.5678E7", 1537 "45.678E6", 1538 "4567.8E4", 1539 "5E7", 1540 "46E6", 1541 "457E5", 1542 } 1543 ); 1544 ! 1545 ! Unroll this test into individual tests below... 1546 ! 1547 */ 1548 expect2(new DecimalFormat("#E0", US), 45678000, "4.5678E7"); 1549 expect2(new DecimalFormat("##E0", US), 45678000, "45.678E6"); 1550 expect2(new DecimalFormat("####E0", US), 45678000, "4567.8E4"); 1551 expect(new DecimalFormat("0E0", US), 45678000, "5E7"); 1552 expect(new DecimalFormat("00E0", US), 45678000, "46E6"); 1553 expect(new DecimalFormat("000E0", US), 45678000, "457E5"); 1554 /* 1555 expect(new DecimalFormat("###E0", US, status), 1556 new Object[] { new Double(0.0000123), "12.3E-6", 1557 new Double(0.000123), "123E-6", 1558 new Double(0.00123), "1.23E-3", 1559 new Double(0.0123), "12.3E-3", 1560 new Double(0.123), "123E-3", 1561 new Double(1.23), "1.23E0", 1562 new Double(12.3), "12.3E0", 1563 new Double(123), "123E0", 1564 new Double(1230), "1.23E3", 1565 }); 1566 ! 1567 ! Unroll this test into individual tests below... 1568 ! 1569 */ 1570 expect2(new DecimalFormat("###E0", US), 0.0000123, "12.3E-6"); 1571 expect2(new DecimalFormat("###E0", US), 0.000123, "123E-6"); 1572 expect2(new DecimalFormat("###E0", US), 0.00123, "1.23E-3"); 1573 expect2(new DecimalFormat("###E0", US), 0.0123, "12.3E-3"); 1574 expect2(new DecimalFormat("###E0", US), 0.123, "123E-3"); 1575 expect2(new DecimalFormat("###E0", US), 1.23, "1.23E0"); 1576 expect2(new DecimalFormat("###E0", US), 12.3, "12.3E0"); 1577 expect2(new DecimalFormat("###E0", US), 123.0, "123E0"); 1578 expect2(new DecimalFormat("###E0", US), 1230.0, "1.23E3"); 1579 /* 1580 expect(new DecimalFormat("0.#E+00", US, status), 1581 new Object[] { new Double(0.00012), "1.2E-04", 1582 new Long(12000), "1.2E+04", 1583 }); 1584 ! 1585 ! Unroll this test into individual tests below... 1586 ! 1587 */ 1588 expect2(new DecimalFormat("0.#E+00", US), 0.00012, "1.2E-04"); 1589 expect2(new DecimalFormat("0.#E+00", US), 12000, "1.2E+04"); 1590 } 1591 1592 /** 1593 * Upgrade to alphaWorks 1594 */ 1595 @Test 1596 public void TestPad() { 1597 1598 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); 1599 expect2(new DecimalFormat("*^##.##", US), 0, "^^^^0"); 1600 expect2(new DecimalFormat("*^##.##", US), -1.3, "^-1.3"); 1601 expect2( 1602 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US), 1603 0, 1604 "0.0E0______ g-m/s^2"); 1605 expect( 1606 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US), 1607 1.0 / 3, 1608 "333.333E-3_ g-m/s^2"); 1609 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US), 0, "0.0______ g-m/s^2"); 1610 expect( 1611 new DecimalFormat("##0.0####*_ 'g-m/s^2'", US), 1612 1.0 / 3, 1613 "0.33333__ g-m/s^2"); 1614 1615 // Test padding before a sign 1616 final String formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)"; 1617 expect2(new DecimalFormat(formatStr, US), -10, "xxxxxxxxxx(10.0)"); 1618 expect2(new DecimalFormat(formatStr, US), -1000, "xxxxxxx(1,000.0)"); 1619 expect2(new DecimalFormat(formatStr, US), -1000000, "xxx(1,000,000.0)"); 1620 expect2(new DecimalFormat(formatStr, US), -100.37, "xxxxxxxx(100.37)"); 1621 expect2(new DecimalFormat(formatStr, US), -10456.37, "xxxxx(10,456.37)"); 1622 expect2(new DecimalFormat(formatStr, US), -1120456.37, "xx(1,120,456.37)"); 1623 expect2(new DecimalFormat(formatStr, US), -112045600.37, "(112,045,600.37)"); 1624 expect2(new DecimalFormat(formatStr, US), -1252045600.37, "(1,252,045,600.37)"); 1625 1626 expect2(new DecimalFormat(formatStr, US), 10, "xxxxxxxxxxxx10.0"); 1627 expect2(new DecimalFormat(formatStr, US), 1000, "xxxxxxxxx1,000.0"); 1628 expect2(new DecimalFormat(formatStr, US), 1000000, "xxxxx1,000,000.0"); 1629 expect2(new DecimalFormat(formatStr, US), 100.37, "xxxxxxxxxx100.37"); 1630 expect2(new DecimalFormat(formatStr, US), 10456.37, "xxxxxxx10,456.37"); 1631 expect2(new DecimalFormat(formatStr, US), 1120456.37, "xxxx1,120,456.37"); 1632 expect2(new DecimalFormat(formatStr, US), 112045600.37, "xx112,045,600.37"); 1633 expect2(new DecimalFormat(formatStr, US), 10252045600.37, "10,252,045,600.37"); 1634 1635 // Test padding between a sign and a number 1636 final String formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)"; 1637 expect2(new DecimalFormat(formatStr2, US), -10, "(10.0xxxxxxxxxx)"); 1638 expect2(new DecimalFormat(formatStr2, US), -1000, "(1,000.0xxxxxxx)"); 1639 expect2(new DecimalFormat(formatStr2, US), -1000000, "(1,000,000.0xxx)"); 1640 expect2(new DecimalFormat(formatStr2, US), -100.37, "(100.37xxxxxxxx)"); 1641 expect2(new DecimalFormat(formatStr2, US), -10456.37, "(10,456.37xxxxx)"); 1642 expect2(new DecimalFormat(formatStr2, US), -1120456.37, "(1,120,456.37xx)"); 1643 expect2(new DecimalFormat(formatStr2, US), -112045600.37, "(112,045,600.37)"); 1644 expect2(new DecimalFormat(formatStr2, US), -1252045600.37, "(1,252,045,600.37)"); 1645 1646 expect2(new DecimalFormat(formatStr2, US), 10, "10.0xxxxxxxxxxxx"); 1647 expect2(new DecimalFormat(formatStr2, US), 1000, "1,000.0xxxxxxxxx"); 1648 expect2(new DecimalFormat(formatStr2, US), 1000000, "1,000,000.0xxxxx"); 1649 expect2(new DecimalFormat(formatStr2, US), 100.37, "100.37xxxxxxxxxx"); 1650 expect2(new DecimalFormat(formatStr2, US), 10456.37, "10,456.37xxxxxxx"); 1651 expect2(new DecimalFormat(formatStr2, US), 1120456.37, "1,120,456.37xxxx"); 1652 expect2(new DecimalFormat(formatStr2, US), 112045600.37, "112,045,600.37xx"); 1653 expect2(new DecimalFormat(formatStr2, US), 10252045600.37, "10,252,045,600.37"); 1654 1655 //testing the setPadCharacter(UnicodeString) and getPadCharacterString() 1656 DecimalFormat fmt = new DecimalFormat("#", US); 1657 char padString = 'P'; 1658 fmt.setPadCharacter(padString); 1659 expectPad(fmt, "*P##.##", DecimalFormat.PAD_BEFORE_PREFIX, 5, padString); 1660 fmt.setPadCharacter('^'); 1661 expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, '^'); 1662 //commented untill implementation is complete 1663 /* fmt.setPadCharacter((UnicodeString)"^^^"); 1664 expectPad(fmt, "*^^^#", DecimalFormat.kPadBeforePrefix, 3, (UnicodeString)"^^^"); 1665 padString.remove(); 1666 padString.append((UChar)0x0061); 1667 padString.append((UChar)0x0302); 1668 fmt.setPadCharacter(padString); 1669 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000}; 1670 UnicodeString pattern(patternChars); 1671 expectPad(fmt, pattern , DecimalFormat.kPadBeforePrefix, 4, padString); 1672 */ 1673 } 1674 1675 /** 1676 * Upgrade to alphaWorks 1677 */ 1678 @Test 1679 public void TestPatterns2() { 1680 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); 1681 DecimalFormat fmt = new DecimalFormat("#", US); 1682 1683 char hat = 0x005E; /*^*/ 1684 1685 expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, hat); 1686 expectPad(fmt, "$*^#", DecimalFormat.PAD_AFTER_PREFIX, 2, hat); 1687 expectPad(fmt, "#*^", DecimalFormat.PAD_BEFORE_SUFFIX, 1, hat); 1688 expectPad(fmt, "#$*^", DecimalFormat.PAD_AFTER_SUFFIX, 2, hat); 1689 expectPad(fmt, "$*^$#", -1); 1690 expectPad(fmt, "#$*^$", -1); 1691 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat.PAD_BEFORE_SUFFIX, 12, (char) 0x0078 /*x*/); 1692 expectPad(fmt, "''#0*x", DecimalFormat.PAD_BEFORE_SUFFIX, 3, (char) 0x0078 /*x*/); 1693 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat.PAD_AFTER_PREFIX, 10, (char) 0x0061 /*a*/); 1694 1695 fmt.applyPattern("AA#,##0.00ZZ"); 1696 fmt.setPadCharacter(hat); 1697 1698 fmt.setFormatWidth(10); 1699 1700 fmt.setPadPosition(DecimalFormat.PAD_BEFORE_PREFIX); 1701 expectPat(fmt, "*^AA#,##0.00ZZ"); 1702 1703 fmt.setPadPosition(DecimalFormat.PAD_BEFORE_SUFFIX); 1704 expectPat(fmt, "AA#,##0.00*^ZZ"); 1705 1706 fmt.setPadPosition(DecimalFormat.PAD_AFTER_SUFFIX); 1707 expectPat(fmt, "AA#,##0.00ZZ*^"); 1708 1709 // 12 3456789012 1710 String exp = "AA*^#,##0.00ZZ"; 1711 fmt.setFormatWidth(12); 1712 fmt.setPadPosition(DecimalFormat.PAD_AFTER_PREFIX); 1713 expectPat(fmt, exp); 1714 1715 fmt.setFormatWidth(13); 1716 // 12 34567890123 1717 expectPat(fmt, "AA*^##,##0.00ZZ"); 1718 1719 fmt.setFormatWidth(14); 1720 // 12 345678901234 1721 expectPat(fmt, "AA*^###,##0.00ZZ"); 1722 1723 fmt.setFormatWidth(15); 1724 // 12 3456789012345 1725 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case 1726 1727 fmt.setFormatWidth(16); 1728 // 12 34567890123456 1729 expectPat(fmt, "AA*^#,###,##0.00ZZ"); 1730 } 1731 1732 @Test 1733 public void TestRegistration() { 1734 final ULocale SRC_LOC = ULocale.FRANCE; 1735 final ULocale SWAP_LOC = ULocale.US; 1736 1737 class TestFactory extends SimpleNumberFormatFactory { 1738 NumberFormat currencyStyle; 1739 1740 TestFactory() { 1741 super(SRC_LOC, true); 1742 currencyStyle = NumberFormat.getIntegerInstance(SWAP_LOC); 1743 } 1744 1745 @Override 1746 public NumberFormat createFormat(ULocale loc, int formatType) { 1747 if (formatType == FORMAT_CURRENCY) { 1748 return currencyStyle; 1749 } 1750 return null; 1751 } 1752 } 1753 1754 NumberFormat f0 = NumberFormat.getIntegerInstance(SWAP_LOC); 1755 NumberFormat f1 = NumberFormat.getIntegerInstance(SRC_LOC); 1756 NumberFormat f2 = NumberFormat.getCurrencyInstance(SRC_LOC); 1757 Object key = NumberFormat.registerFactory(new TestFactory()); 1758 NumberFormat f3 = NumberFormat.getCurrencyInstance(SRC_LOC); 1759 NumberFormat f4 = NumberFormat.getIntegerInstance(SRC_LOC); 1760 NumberFormat.unregister(key); // restore for other tests 1761 NumberFormat f5 = NumberFormat.getCurrencyInstance(SRC_LOC); 1762 1763 float n = 1234.567f; 1764 logln("f0 swap int: " + f0.format(n)); 1765 logln("f1 src int: " + f1.format(n)); 1766 logln("f2 src cur: " + f2.format(n)); 1767 logln("f3 reg cur: " + f3.format(n)); 1768 logln("f4 reg int: " + f4.format(n)); 1769 logln("f5 unreg cur: " + f5.format(n)); 1770 1771 if (!f3.format(n).equals(f0.format(n))) { 1772 errln("registered service did not match"); 1773 } 1774 if (!f4.format(n).equals(f1.format(n))) { 1775 errln("registered service did not inherit"); 1776 } 1777 if (!f5.format(n).equals(f2.format(n))) { 1778 errln("unregistered service did not match original"); 1779 } 1780 } 1781 1782 @Test 1783 public void TestScientific2() { 1784 // jb 2552 1785 DecimalFormat fmt = (DecimalFormat)NumberFormat.getCurrencyInstance(); 1786 Number num = new Double(12.34); 1787 expect(fmt, num, "$12.34"); 1788 fmt.setScientificNotation(true); 1789 expect(fmt, num, "$1.23E1"); 1790 fmt.setScientificNotation(false); 1791 expect(fmt, num, "$12.34"); 1792 } 1793 1794 @Test 1795 public void TestScientificGrouping() { 1796 // jb 2552 1797 DecimalFormat fmt = new DecimalFormat("###.##E0"); 1798 expect(fmt, .01234, "12.3E-3"); 1799 expect(fmt, .1234, "123E-3"); 1800 expect(fmt, 1.234, "1.23E0"); 1801 expect(fmt, 12.34, "12.3E0"); 1802 expect(fmt, 123.4, "123E0"); 1803 expect(fmt, 1234, "1.23E3"); 1804 } 1805 1806 // additional coverage tests 1807 1808 // sigh, can't have static inner classes, why not? 1809 1810 static final class PI extends Number { 1811 /** 1812 * For serialization 1813 */ 1814 private static final long serialVersionUID = -305601227915602172L; 1815 1816 private PI() {} 1817 @Override 1818 public int intValue() { return (int)Math.PI; } 1819 @Override 1820 public long longValue() { return (long)Math.PI; } 1821 @Override 1822 public float floatValue() { return (float)Math.PI; } 1823 @Override 1824 public double doubleValue() { return Math.PI; } 1825 @Override 1826 public byte byteValue() { return (byte)Math.PI; } 1827 @Override 1828 public short shortValue() { return (short)Math.PI; } 1829 1830 public static final Number INSTANCE = new PI(); 1831 } 1832 1833 @Test 1834 public void TestCoverage() { 1835 NumberFormat fmt = NumberFormat.getNumberInstance(); // default locale 1836 logln(fmt.format(new BigInteger("1234567890987654321234567890987654321", 10))); 1837 1838 fmt = NumberFormat.getScientificInstance(); // default locale 1839 1840 logln(fmt.format(PI.INSTANCE)); 1841 1842 try { 1843 logln(fmt.format("12345")); 1844 errln("numberformat of string did not throw exception"); 1845 } 1846 catch (Exception e) { 1847 logln("PASS: numberformat of string failed as expected"); 1848 } 1849 1850 int hash = fmt.hashCode(); 1851 logln("hash code " + hash); 1852 1853 logln("compare to string returns: " + fmt.equals("")); 1854 1855 // For ICU 2.6 - alan 1856 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); 1857 DecimalFormat df = new DecimalFormat("'*&'' '\u00A4' ''&*' #,##0.00", US); 1858 df.setCurrency(Currency.getInstance("INR")); 1859 expect2(df, 1.0, "*&' \u20B9 '&* 1.00"); 1860 expect2(df, -2.0, "-*&' \u20B9 '&* 2.00"); 1861 df.applyPattern("#,##0.00 '*&'' '\u00A4' ''&*'"); 1862 expect2(df, 2.0, "2.00 *&' \u20B9 '&*"); 1863 expect2(df, -1.0, "-1.00 *&' \u20B9 '&*"); 1864 1865 java.math.BigDecimal r; 1866 1867 r = df.getRoundingIncrement(); 1868 if (r != null) { 1869 errln("FAIL: rounding = " + r + ", expect null"); 1870 } 1871 1872 if (df.isScientificNotation()) { 1873 errln("FAIL: isScientificNotation = true, expect false"); 1874 } 1875 1876 df.applyPattern("0.00000"); 1877 df.setScientificNotation(true); 1878 if (!df.isScientificNotation()) { 1879 errln("FAIL: isScientificNotation = false, expect true"); 1880 } 1881 df.setMinimumExponentDigits((byte)2); 1882 if (df.getMinimumExponentDigits() != 2) { 1883 errln("FAIL: getMinimumExponentDigits = " + 1884 df.getMinimumExponentDigits() + ", expect 2"); 1885 } 1886 df.setExponentSignAlwaysShown(true); 1887 if (!df.isExponentSignAlwaysShown()) { 1888 errln("FAIL: isExponentSignAlwaysShown = false, expect true"); 1889 } 1890 df.setSecondaryGroupingSize(0); 1891 if (df.getSecondaryGroupingSize() != 0) { 1892 errln("FAIL: getSecondaryGroupingSize = " + 1893 df.getSecondaryGroupingSize() + ", expect 0"); 1894 } 1895 expect2(df, 3.14159, "3.14159E+00"); 1896 1897 // DecimalFormatSymbols#getInstance 1898 DecimalFormatSymbols decsym1 = DecimalFormatSymbols.getInstance(); 1899 DecimalFormatSymbols decsym2 = new DecimalFormatSymbols(); 1900 if (!decsym1.equals(decsym2)) { 1901 errln("FAIL: DecimalFormatSymbols returned by getInstance()" + 1902 "does not match new DecimalFormatSymbols()."); 1903 } 1904 decsym1 = DecimalFormatSymbols.getInstance(Locale.JAPAN); 1905 decsym2 = DecimalFormatSymbols.getInstance(ULocale.JAPAN); 1906 if (!decsym1.equals(decsym2)) { 1907 errln("FAIL: DecimalFormatSymbols returned by getInstance(Locale.JAPAN)" + 1908 "does not match the one returned by getInstance(ULocale.JAPAN)."); 1909 } 1910 1911 // DecimalFormatSymbols#getAvailableLocales/#getAvailableULocales 1912 Locale[] allLocales = DecimalFormatSymbols.getAvailableLocales(); 1913 if (allLocales.length == 0) { 1914 errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales"); 1915 } else { 1916 logln("PASS: " + allLocales.length + 1917 " available locales returned by DecimalFormatSymbols.getAvailableLocales"); 1918 } 1919 ULocale[] allULocales = DecimalFormatSymbols.getAvailableULocales(); 1920 if (allULocales.length == 0) { 1921 errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales"); 1922 } else { 1923 logln("PASS: " + allULocales.length + 1924 " available locales returned by DecimalFormatSymbols.getAvailableULocales"); 1925 } 1926 } 1927 1928 @Test 1929 public void TestWhiteSpaceParsing() { 1930 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); 1931 DecimalFormat fmt = new DecimalFormat("a b#0c ", US); 1932 int n = 1234; 1933 expect(fmt, "a b1234c ", n); 1934 expect(fmt, "a b1234c ", n); 1935 } 1936 1937 /** 1938 * Test currencies whose display name is a ChoiceFormat. 1939 */ 1940 @Test 1941 public void TestComplexCurrency() { 1942 // CLDR No Longer uses complex currency symbols. 1943 // Skipping this test. 1944 // Locale loc = new Locale("kn", "IN", ""); 1945 // NumberFormat fmt = NumberFormat.getCurrencyInstance(loc); 1946 1947 // expect2(fmt, 1.0, "Re.\u00a01.00"); 1948 // expect(fmt, 1.001, "Re.\u00a01.00"); // tricky 1949 // expect2(fmt, 12345678.0, "Rs.\u00a01,23,45,678.00"); 1950 // expect2(fmt, 0.5, "Rs.\u00a00.50"); 1951 // expect2(fmt, -1.0, "-Re.\u00a01.00"); 1952 // expect2(fmt, -10.0, "-Rs.\u00a010.00"); 1953 } 1954 1955 @Test 1956 public void TestCurrencyKeyword() { 1957 ULocale locale = new ULocale("th_TH@currency=QQQ"); 1958 NumberFormat format = NumberFormat.getCurrencyInstance(locale); 1959 String result = format.format(12.34f); 1960 if (!"QQQ12.34".equals(result)) { 1961 errln("got unexpected currency: " + result); 1962 } 1963 } 1964 1965 /** 1966 * Test alternate numbering systems 1967 */ 1968 @Test 1969 public void TestNumberingSystems() { 1970 class TestNumberingSystemItem { 1971 private final String localeName; 1972 private final double value; 1973 private final boolean isRBNF; 1974 private final String expectedResult; 1975 1976 TestNumberingSystemItem(String loc, double val, boolean rbnf, String exp) { 1977 localeName = loc; 1978 value = val; 1979 isRBNF = rbnf; 1980 expectedResult = exp; 1981 } 1982 } 1983 1984 final TestNumberingSystemItem[] DATA = { 1985 new TestNumberingSystemItem( "en_US@numbers=thai", 1234.567, false, "\u0e51,\u0e52\u0e53\u0e54.\u0e55\u0e56\u0e57" ), 1986 new TestNumberingSystemItem( "en_US@numbers=thai", 1234.567, false, "\u0E51,\u0E52\u0E53\u0E54.\u0E55\u0E56\u0E57" ), 1987 new TestNumberingSystemItem( "en_US@numbers=hebr", 5678.0, true, "\u05D4\u05F3\u05EA\u05E8\u05E2\u05F4\u05D7" ), 1988 new TestNumberingSystemItem( "en_US@numbers=arabext", 1234.567, false, "\u06F1\u066c\u06F2\u06F3\u06F4\u066b\u06F5\u06F6\u06F7" ), 1989 new TestNumberingSystemItem( "de_DE@numbers=foobar", 1234.567, false, "1.234,567" ), 1990 new TestNumberingSystemItem( "ar_EG", 1234.567, false, "\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666\u0667" ), 1991 new TestNumberingSystemItem( "th_TH@numbers=traditional", 1234.567, false, "\u0E51,\u0E52\u0E53\u0E54.\u0E55\u0E56\u0E57" ), // fall back to native per TR35 1992 new TestNumberingSystemItem( "ar_MA", 1234.567, false, "1.234,567" ), 1993 new TestNumberingSystemItem( "en_US@numbers=hanidec", 1234.567, false, "\u4e00,\u4e8c\u4e09\u56db.\u4e94\u516d\u4e03" ), 1994 new TestNumberingSystemItem( "ta_IN@numbers=native", 1234.567, false, "\u0BE7,\u0BE8\u0BE9\u0BEA.\u0BEB\u0BEC\u0BED" ), 1995 new TestNumberingSystemItem( "ta_IN@numbers=traditional", 1235.0, true, "\u0BF2\u0BE8\u0BF1\u0BE9\u0BF0\u0BEB" ), 1996 new TestNumberingSystemItem( "ta_IN@numbers=finance", 1234.567, false, "1,234.567" ), // fall back to default per TR35 1997 new TestNumberingSystemItem( "zh_TW@numbers=native", 1234.567, false, "\u4e00,\u4e8c\u4e09\u56db.\u4e94\u516d\u4e03" ), 1998 new TestNumberingSystemItem( "zh_TW@numbers=traditional", 1234.567, true, "\u4E00\u5343\u4E8C\u767E\u4E09\u5341\u56DB\u9EDE\u4E94\u516D\u4E03" ), 1999 new TestNumberingSystemItem( "zh_TW@numbers=finance", 1234.567, true, "\u58F9\u4EDF\u8CB3\u4F70\u53C3\u62FE\u8086\u9EDE\u4F0D\u9678\u67D2" ) 2000 }; 2001 2002 2003 for (TestNumberingSystemItem item : DATA) { 2004 ULocale loc = new ULocale(item.localeName); 2005 NumberFormat fmt = NumberFormat.getInstance(loc); 2006 if (item.isRBNF) { 2007 expect3(fmt,item.value,item.expectedResult); 2008 } else { 2009 expect2(fmt,item.value,item.expectedResult); 2010 } 2011 } 2012 } 2013 2014 // Coverage tests for methods not being called otherwise. 2015 @Test 2016 public void TestNumberingSystemCoverage() { 2017 // Test getAvaliableNames 2018 String[] availableNames = NumberingSystem.getAvailableNames(); 2019 if (availableNames == null || availableNames.length <= 0) { 2020 errln("ERROR: NumberingSystem.getAvailableNames() returned a null or empty array."); 2021 } else { 2022 boolean latnFound = false; 2023 for (String name : availableNames){ 2024 if ("latn".equals(name)) { 2025 latnFound = true; 2026 break; 2027 } 2028 } 2029 2030 if (!latnFound) { 2031 errln("ERROR: 'latn' numbering system not found on NumberingSystem.getAvailableNames()."); 2032 } 2033 } 2034 2035 // Test NumberingSystem.getInstance() 2036 NumberingSystem ns1 = NumberingSystem.getInstance(); 2037 if (ns1 == null || ns1.isAlgorithmic()) { 2038 errln("ERROR: NumberingSystem.getInstance() returned a null or invalid NumberingSystem"); 2039 } 2040 2041 // Test NumberingSystem.getInstance(int,boolean,String) 2042 /* Parameters used: the ones used in the default constructor 2043 * radix = 10; 2044 * algorithmic = false; 2045 * desc = "0123456789"; 2046 */ 2047 NumberingSystem ns2 = NumberingSystem.getInstance(10, false, "0123456789"); 2048 if (ns2 == null || ns2.isAlgorithmic()) { 2049 errln("ERROR: NumberingSystem.getInstance(int,boolean,String) returned a null or invalid NumberingSystem"); 2050 } 2051 2052 // Test NumberingSystem.getInstance(Locale) 2053 NumberingSystem ns3 = NumberingSystem.getInstance(Locale.ENGLISH); 2054 if (ns3 == null || ns3.isAlgorithmic()) { 2055 errln("ERROR: NumberingSystem.getInstance(Locale) returned a null or invalid NumberingSystem"); 2056 } 2057 } 2058 2059 @Test 2060 public void Test6816() { 2061 Currency cur1 = Currency.getInstance(new Locale("und", "PH")); 2062 2063 NumberFormat nfmt = NumberFormat.getCurrencyInstance(new Locale("und", "PH")); 2064 DecimalFormatSymbols decsym = ((DecimalFormat)nfmt).getDecimalFormatSymbols(); 2065 Currency cur2 = decsym.getCurrency(); 2066 2067 if ( !cur1.getCurrencyCode().equals("PHP") || !cur2.getCurrencyCode().equals("PHP")) { 2068 errln("FAIL: Currencies should match PHP: cur1 = "+cur1.getCurrencyCode()+"; cur2 = "+cur2.getCurrencyCode()); 2069 } 2070 2071 } 2072 2073 @Test 2074 public void TestThreadedFormat() { 2075 2076 class FormatTask implements Runnable { 2077 DecimalFormat fmt; 2078 StringBuffer buf; 2079 boolean inc; 2080 float num; 2081 2082 FormatTask(DecimalFormat fmt, int index) { 2083 this.fmt = fmt; 2084 this.buf = new StringBuffer(); 2085 this.inc = (index & 0x1) == 0; 2086 this.num = inc ? 0 : 10000; 2087 } 2088 2089 @Override 2090 public void run() { 2091 if (inc) { 2092 while (num < 10000) { 2093 buf.append(fmt.format(num) + "\n"); 2094 num += 3.14159; 2095 } 2096 } else { 2097 while (num > 0) { 2098 buf.append(fmt.format(num) + "\n"); 2099 num -= 3.14159; 2100 } 2101 } 2102 } 2103 2104 String result() { 2105 return buf.toString(); 2106 } 2107 } 2108 2109 DecimalFormat fmt = new DecimalFormat("0.####"); 2110 FormatTask[] tasks = new FormatTask[8]; 2111 for (int i = 0; i < tasks.length; ++i) { 2112 tasks[i] = new FormatTask(fmt, i); 2113 } 2114 2115 TestUtil.runUntilDone(tasks); 2116 2117 for (int i = 2; i < tasks.length; i++) { 2118 String str1 = tasks[i].result(); 2119 String str2 = tasks[i-2].result(); 2120 if (!str1.equals(str2)) { 2121 System.out.println("mismatch at " + i); 2122 System.out.println(str1); 2123 System.out.println(str2); 2124 errln("decimal format thread mismatch"); 2125 2126 break; 2127 } 2128 str1 = str2; 2129 } 2130 } 2131 2132 @Test 2133 public void TestPerMill() { 2134 DecimalFormat fmt = new DecimalFormat("###.###\u2030"); 2135 assertEquals("0.4857 x ###.###\u2030", 2136 "485.7\u2030", fmt.format(0.4857)); 2137 2138 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.ENGLISH); 2139 sym.setPerMill('m'); 2140 DecimalFormat fmt2 = new DecimalFormat("", sym); 2141 fmt2.applyLocalizedPattern("###.###m"); 2142 assertEquals("0.4857 x ###.###m", 2143 "485.7m", fmt2.format(0.4857)); 2144 } 2145 2146 @Test 2147 public void TestIllegalPatterns() { 2148 // Test cases: 2149 // Prefix with "-:" for illegal patterns 2150 // Prefix with "+:" for legal patterns 2151 String DATA[] = { 2152 // Unquoted special characters in the suffix are illegal 2153 "-:000.000|###", 2154 "+:000.000'|###'", 2155 }; 2156 for (int i=0; i<DATA.length; ++i) { 2157 String pat=DATA[i]; 2158 boolean valid = pat.charAt(0) == '+'; 2159 pat = pat.substring(2); 2160 Exception e = null; 2161 try { 2162 // locale doesn't matter here 2163 new DecimalFormat(pat); 2164 } catch (IllegalArgumentException e1) { 2165 e = e1; 2166 } catch (IndexOutOfBoundsException e1) { 2167 e = e1; 2168 } 2169 String msg = (e==null) ? "success" : e.getMessage(); 2170 if ((e==null) == valid) { 2171 logln("Ok: pattern \"" + pat + "\": " + msg); 2172 } else { 2173 errln("FAIL: pattern \"" + pat + "\" should have " + 2174 (valid?"succeeded":"failed") + "; got " + msg); 2175 } 2176 } 2177 } 2178 2179 /** 2180 * Parse a CurrencyAmount using the given NumberFormat, with 2181 * the 'delim' character separating the number and the currency. 2182 */ 2183 private static CurrencyAmount parseCurrencyAmount(String str, NumberFormat fmt, 2184 char delim) 2185 throws ParseException { 2186 int i = str.indexOf(delim); 2187 return new CurrencyAmount(fmt.parse(str.substring(0,i)), 2188 Currency.getInstance(str.substring(i+1))); 2189 } 2190 2191 /** 2192 * Return an integer representing the next token from this 2193 * iterator. The integer will be an index into the given list, or 2194 * -1 if there are no more tokens, or -2 if the token is not on 2195 * the list. 2196 */ 2197 private static int keywordIndex(String tok) { 2198 for (int i=0; i<KEYWORDS.length; ++i) { 2199 if (tok.equals(KEYWORDS[i])) { 2200 return i; 2201 } 2202 } 2203 return -1; 2204 } 2205 2206 private static final String KEYWORDS[] = { 2207 /*0*/ "ref=", // <reference pattern to parse numbers> 2208 /*1*/ "loc=", // <locale for formats> 2209 /*2*/ "f:", // <pattern or '-'> <number> <exp. string> 2210 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number> 2211 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string> 2212 /*5*/ "p:", // <pattern or '-'> <string> <exp. number> 2213 /*6*/ "perr:", // <pattern or '-'> <invalid string> 2214 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'> 2215 /*8*/ "fpc:", // <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt> 2216 /*9*/ "strict=", // true or false 2217 }; 2218 2219 @SuppressWarnings("resource") // InputStream is will be closed by the ResourceReader. 2220 @Test 2221 public void TestCases() { 2222 String caseFileName = "NumberFormatTestCases.txt"; 2223 java.io.InputStream is = NumberFormatTest.class.getResourceAsStream(caseFileName); 2224 2225 ResourceReader reader = new ResourceReader(is, caseFileName, "utf-8"); 2226 TokenIterator tokens = new TokenIterator(reader); 2227 2228 Locale loc = new Locale("en", "US", ""); 2229 DecimalFormat ref = null, fmt = null; 2230 MeasureFormat mfmt = null; 2231 String pat = null, str = null, mloc = null; 2232 boolean strict = false; 2233 2234 try { 2235 for (;;) { 2236 String tok = tokens.next(); 2237 if (tok == null) { 2238 break; 2239 } 2240 String where = "(" + tokens.getLineNumber() + ") "; 2241 int cmd = keywordIndex(tok); 2242 switch (cmd) { 2243 case 0: 2244 // ref= <reference pattern> 2245 ref = new DecimalFormat(tokens.next(), 2246 new DecimalFormatSymbols(Locale.US)); 2247 ref.setParseStrict(strict); 2248 logln("Setting reference pattern to:\t" + ref); 2249 break; 2250 case 1: 2251 // loc= <locale> 2252 loc = LocaleUtility.getLocaleFromName(tokens.next()); 2253 pat = ((DecimalFormat) NumberFormat.getInstance(loc)).toPattern(); 2254 logln("Setting locale to:\t" + loc + ", \tand pattern to:\t" + pat); 2255 break; 2256 case 2: // f: 2257 case 3: // fp: 2258 case 4: // rt: 2259 case 5: // p: 2260 tok = tokens.next(); 2261 if (!tok.equals("-")) { 2262 pat = tok; 2263 } 2264 try { 2265 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc)); 2266 fmt.setParseStrict(strict); 2267 } catch (IllegalArgumentException iae) { 2268 errln(where + "Pattern \"" + pat + '"'); 2269 iae.printStackTrace(); 2270 tokens.next(); // consume remaining tokens 2271 //tokens.next(); 2272 if (cmd == 3) tokens.next(); 2273 continue; 2274 } 2275 str = null; 2276 try { 2277 if (cmd == 2 || cmd == 3 || cmd == 4) { 2278 // f: <pattern or '-'> <number> <exp. string> 2279 // fp: <pattern or '-'> <number> <exp. string> <exp. number> 2280 // rt: <pattern or '-'> <number> <string> 2281 String num = tokens.next(); 2282 str = tokens.next(); 2283 Number n = ref.parse(num); 2284 assertEquals(where + '"' + pat + "\".format(" + num + ")", 2285 str, fmt.format(n)); 2286 if (cmd == 3) { // fp: 2287 n = ref.parse(tokens.next()); 2288 } 2289 if (cmd != 2) { // != f: 2290 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")", 2291 n, fmt.parse(str)); 2292 } 2293 } 2294 // p: <pattern or '-'> <string to parse> <exp. number> 2295 else { 2296 str = tokens.next(); 2297 String expstr = tokens.next(); 2298 Number parsed = fmt.parse(str); 2299 Number exp = ref.parse(expstr); 2300 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")", 2301 exp, parsed); 2302 } 2303 } catch (ParseException e) { 2304 errln(where + '"' + pat + "\".parse(\"" + str + 2305 "\") threw an exception"); 2306 e.printStackTrace(); 2307 } 2308 break; 2309 case 6: 2310 // perr: <pattern or '-'> <invalid string> 2311 errln("Under construction"); 2312 return; 2313 case 7: 2314 // pat: <pattern> <exp. toPattern, or '-' or 'err'> 2315 String testpat = tokens.next(); 2316 String exppat = tokens.next(); 2317 boolean err = exppat.equals("err"); 2318 if (testpat.equals("-")) { 2319 if (err) { 2320 errln("Invalid command \"pat: - err\" at " + tokens.describePosition()); 2321 continue; 2322 } 2323 testpat = pat; 2324 } 2325 if (exppat.equals("-")) exppat = testpat; 2326 try { 2327 DecimalFormat f = null; 2328 if (testpat == pat) { // [sic] 2329 f = fmt; 2330 } else { 2331 f = new DecimalFormat(testpat); 2332 f.setParseStrict(strict); 2333 } 2334 if (err) { 2335 errln(where + "Invalid pattern \"" + testpat + 2336 "\" was accepted"); 2337 } else { 2338 assertEquals(where + '"' + testpat + "\".toPattern()", 2339 exppat, f.toPattern()); 2340 } 2341 } catch (IllegalArgumentException iae2) { 2342 if (err) { 2343 logln("Ok: " + where + "Invalid pattern \"" + testpat + 2344 "\" threw an exception"); 2345 } else { 2346 errln(where + "Valid pattern \"" + testpat + 2347 "\" threw an exception"); 2348 iae2.printStackTrace(); 2349 } 2350 } 2351 break; 2352 case 8: // fpc: 2353 tok = tokens.next(); 2354 if (!tok.equals("-")) { 2355 mloc = tok; 2356 ULocale l = new ULocale(mloc); 2357 try { 2358 mfmt = MeasureFormat.getCurrencyFormat(l); 2359 } catch (IllegalArgumentException iae) { 2360 errln(where + "Loc \"" + tok + '"'); 2361 iae.printStackTrace(); 2362 tokens.next(); // consume remaining tokens 2363 tokens.next(); 2364 tokens.next(); 2365 continue; 2366 } 2367 } 2368 str = null; 2369 try { 2370 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt> 2371 String currAmt = tokens.next(); 2372 str = tokens.next(); 2373 CurrencyAmount target = parseCurrencyAmount(currAmt, ref, '/'); 2374 String formatResult = mfmt.format(target); 2375 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")", 2376 str, formatResult); 2377 target = parseCurrencyAmount(tokens.next(), ref, '/'); 2378 CurrencyAmount parseResult = (CurrencyAmount) mfmt.parseObject(str); 2379 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")", 2380 target, parseResult); 2381 } catch (ParseException e) { 2382 errln(where + '"' + pat + "\".parse(\"" + str + 2383 "\") threw an exception"); 2384 e.printStackTrace(); 2385 } 2386 break; 2387 case 9: // strict= true or false 2388 strict = "true".equalsIgnoreCase(tokens.next()); 2389 logln("Setting strict to:\t" + strict); 2390 break; 2391 case -1: 2392 errln("Unknown command \"" + tok + "\" at " + tokens.describePosition()); 2393 return; 2394 } 2395 } 2396 } catch (java.io.IOException e) { 2397 throw new RuntimeException(e); 2398 } finally { 2399 try { 2400 reader.close(); 2401 } catch (IOException ignored) { 2402 } 2403 } 2404 } 2405 2406 @Test 2407 public void TestFieldPositionDecimal() { 2408 DecimalFormat nf = (DecimalFormat) android.icu.text.NumberFormat.getInstance(ULocale.ENGLISH); 2409 nf.setPositivePrefix("FOO"); 2410 nf.setPositiveSuffix("BA"); 2411 StringBuffer buffer = new StringBuffer(); 2412 FieldPosition fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR); 2413 nf.format(35.47, buffer, fp); 2414 assertEquals("35.47", "FOO35.47BA", buffer.toString()); 2415 assertEquals("fp begin", 5, fp.getBeginIndex()); 2416 assertEquals("fp end", 6, fp.getEndIndex()); 2417 } 2418 2419 @Test 2420 public void TestFieldPositionInteger() { 2421 DecimalFormat nf = (DecimalFormat) android.icu.text.NumberFormat.getInstance(ULocale.ENGLISH); 2422 nf.setPositivePrefix("FOO"); 2423 nf.setPositiveSuffix("BA"); 2424 StringBuffer buffer = new StringBuffer(); 2425 FieldPosition fp = new FieldPosition(NumberFormat.Field.INTEGER); 2426 nf.format(35.47, buffer, fp); 2427 assertEquals("35.47", "FOO35.47BA", buffer.toString()); 2428 assertEquals("fp begin", 3, fp.getBeginIndex()); 2429 assertEquals("fp end", 5, fp.getEndIndex()); 2430 } 2431 2432 @Test 2433 public void TestFieldPositionFractionButInteger() { 2434 DecimalFormat nf = (DecimalFormat) android.icu.text.NumberFormat.getInstance(ULocale.ENGLISH); 2435 nf.setPositivePrefix("FOO"); 2436 nf.setPositiveSuffix("BA"); 2437 StringBuffer buffer = new StringBuffer(); 2438 FieldPosition fp = new FieldPosition(NumberFormat.Field.FRACTION); 2439 nf.format(35, buffer, fp); 2440 assertEquals("35", "FOO35BA", buffer.toString()); 2441 assertEquals("fp begin", 5, fp.getBeginIndex()); 2442 assertEquals("fp end", 5, fp.getEndIndex()); 2443 } 2444 2445 @Test 2446 public void TestFieldPositionFraction() { 2447 DecimalFormat nf = (DecimalFormat) android.icu.text.NumberFormat.getInstance(ULocale.ENGLISH); 2448 nf.setPositivePrefix("FOO"); 2449 nf.setPositiveSuffix("BA"); 2450 StringBuffer buffer = new StringBuffer(); 2451 FieldPosition fp = new FieldPosition(NumberFormat.Field.FRACTION); 2452 nf.format(35.47, buffer, fp); 2453 assertEquals("35.47", "FOO35.47BA", buffer.toString()); 2454 assertEquals("fp begin", 6, fp.getBeginIndex()); 2455 assertEquals("fp end", 8, fp.getEndIndex()); 2456 } 2457 2458 @Test 2459 public void TestFieldPositionCurrency() { 2460 DecimalFormat nf = (DecimalFormat) android.icu.text.NumberFormat.getCurrencyInstance(Locale.US); 2461 double amount = 35.47; 2462 double negAmount = -34.567; 2463 FieldPosition cp = new FieldPosition(NumberFormat.Field.CURRENCY); 2464 2465 StringBuffer buffer0 = new StringBuffer(); 2466 nf.format(amount, buffer0, cp); 2467 assertEquals("$35.47", "$35.47", buffer0.toString()); 2468 assertEquals("cp begin", 0, cp.getBeginIndex()); 2469 assertEquals("cp end", 1, cp.getEndIndex()); 2470 2471 StringBuffer buffer01 = new StringBuffer(); 2472 nf.format(negAmount, buffer01, cp); 2473 assertEquals("-$34.57", "-$34.57", buffer01.toString()); 2474 assertEquals("cp begin", 1, cp.getBeginIndex()); 2475 assertEquals("cp end", 2, cp.getEndIndex()); 2476 2477 nf.setCurrency(Currency.getInstance(Locale.FRANCE)); 2478 StringBuffer buffer1 = new StringBuffer(); 2479 nf.format(amount, buffer1, cp); 2480 assertEquals("€35.47", "€35.47", buffer1.toString()); 2481 assertEquals("cp begin", 0, cp.getBeginIndex()); 2482 assertEquals("cp end", 1, cp.getEndIndex()); 2483 2484 nf.setCurrency(Currency.getInstance(new Locale("fr", "ch", ""))); 2485 StringBuffer buffer2 = new StringBuffer(); 2486 nf.format(amount, buffer2, cp); 2487 assertEquals("CHF35.47", "CHF35.47", buffer2.toString()); 2488 assertEquals("cp begin", 0, cp.getBeginIndex()); 2489 assertEquals("cp end", 3, cp.getEndIndex()); 2490 2491 StringBuffer buffer20 = new StringBuffer(); 2492 nf.format(negAmount, buffer20, cp); 2493 assertEquals("-CHF34.57", "-CHF34.57", buffer20.toString()); 2494 assertEquals("cp begin", 1, cp.getBeginIndex()); 2495 assertEquals("cp end", 4, cp.getEndIndex()); 2496 2497 nf = (DecimalFormat) android.icu.text.NumberFormat.getCurrencyInstance(Locale.FRANCE); 2498 StringBuffer buffer3 = new StringBuffer(); 2499 nf.format(amount, buffer3, cp); 2500 assertEquals("35,47 €", "35,47 €", buffer3.toString()); 2501 assertEquals("cp begin", 6, cp.getBeginIndex()); 2502 assertEquals("cp end", 7, cp.getEndIndex()); 2503 2504 StringBuffer buffer4 = new StringBuffer(); 2505 nf.format(negAmount, buffer4, cp); 2506 assertEquals("-34,57 €", "-34,57 €", buffer4.toString()); 2507 assertEquals("cp begin", 7, cp.getBeginIndex()); 2508 assertEquals("cp end", 8, cp.getEndIndex()); 2509 2510 nf.setCurrency(Currency.getInstance(new Locale("fr", "ch"))); 2511 StringBuffer buffer5 = new StringBuffer(); 2512 nf.format(negAmount, buffer5, cp); 2513 assertEquals("-34,57 CHF", "-34,57 CHF", buffer5.toString()); 2514 assertEquals("cp begin", 7, cp.getBeginIndex()); 2515 assertEquals("cp end", 10, cp.getEndIndex()); 2516 2517 NumberFormat plCurrencyFmt = NumberFormat.getInstance(new Locale("fr", "ch"), NumberFormat.PLURALCURRENCYSTYLE); 2518 StringBuffer buffer6 = new StringBuffer(); 2519 plCurrencyFmt.format(negAmount, buffer6, cp); 2520 assertEquals("-34.57 francs suisses", "-34.57 francs suisses", buffer6.toString()); 2521 assertEquals("cp begin", 7, cp.getBeginIndex()); 2522 assertEquals("cp end", 21, cp.getEndIndex()); 2523 2524 // Positive value with PLURALCURRENCYSTYLE. 2525 plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE); 2526 StringBuffer buffer7 = new StringBuffer(); 2527 plCurrencyFmt.format(amount, buffer7, cp); 2528 assertEquals("35.47スイス フラン", "35.47スイス フラン", buffer7.toString()); 2529 assertEquals("cp begin", 5, cp.getBeginIndex()); 2530 assertEquals("cp end", 12, cp.getEndIndex()); 2531 2532 // PLURALCURRENCYSTYLE for non-ASCII. 2533 plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "de"), NumberFormat.PLURALCURRENCYSTYLE); 2534 StringBuffer buffer8 = new StringBuffer(); 2535 plCurrencyFmt.format(negAmount, buffer8, cp); 2536 assertEquals("-34.57ユーロ", "-34.57ユーロ", buffer8.toString()); 2537 assertEquals("cp begin", 6, cp.getBeginIndex()); 2538 assertEquals("cp end", 9, cp.getEndIndex()); 2539 2540 nf = (DecimalFormat) android.icu.text.NumberFormat.getCurrencyInstance(Locale.JAPAN); 2541 nf.setCurrency(Currency.getInstance(new Locale("ja", "jp"))); 2542 StringBuffer buffer9 = new StringBuffer(); 2543 nf.format(negAmount, buffer9, cp); 2544 assertEquals("-¥35", "-¥35", buffer9.toString()); 2545 assertEquals("cp begin", 1, cp.getBeginIndex()); 2546 assertEquals("cp end", 2, cp.getEndIndex()); 2547 2548 // Negative value with PLURALCURRENCYSTYLE. 2549 plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE); 2550 StringBuffer buffer10 = new StringBuffer(); 2551 plCurrencyFmt.format(negAmount, buffer10, cp); 2552 assertEquals("-34.57スイス フラン", "-34.57スイス フラン", buffer10.toString()); 2553 assertEquals("cp begin", 6, cp.getBeginIndex()); 2554 assertEquals("cp end", 13, cp.getEndIndex()); 2555 2556 // Nagative value with PLURALCURRENCYSTYLE, Arabic digits. 2557 nf = (DecimalFormat) android.icu.text.NumberFormat.getCurrencyInstance(new Locale("ar", "eg")); 2558 plCurrencyFmt = NumberFormat.getInstance(new Locale("ar", "eg"), NumberFormat.PLURALCURRENCYSTYLE); 2559 StringBuffer buffer11 = new StringBuffer(); 2560 plCurrencyFmt.format(negAmount, buffer11, cp); 2561 assertEquals("-٣٤٫٥٧ جنيه مصري", "-٣٤٫٥٧ جنيه مصري", buffer11.toString()); 2562 assertEquals("cp begin", 8, cp.getBeginIndex()); 2563 assertEquals("cp end", 17, cp.getEndIndex()); 2564 } 2565 2566 @Test 2567 public void TestRounding() { 2568 DecimalFormat nf = (DecimalFormat) android.icu.text.NumberFormat.getInstance(ULocale.ENGLISH); 2569 if (false) { // for debugging specific value 2570 nf.setRoundingMode(BigDecimal.ROUND_HALF_UP); 2571 checkRounding(nf, new BigDecimal("300.0300000000"), 0, new BigDecimal("0.020000000")); 2572 } 2573 // full tests 2574 int[] roundingIncrements = {1, 2, 5, 20, 50, 100}; 2575 int[] testValues = {0, 300}; 2576 for (int j = 0; j < testValues.length; ++j) { 2577 for (int mode = BigDecimal.ROUND_UP; mode < BigDecimal.ROUND_HALF_EVEN; ++mode) { 2578 nf.setRoundingMode(mode); 2579 for (int increment = 0; increment < roundingIncrements.length; ++increment) { 2580 BigDecimal base = new BigDecimal(testValues[j]); 2581 BigDecimal rInc = new BigDecimal(roundingIncrements[increment]); 2582 checkRounding(nf, base, 20, rInc); 2583 rInc = new BigDecimal("1.000000000").divide(rInc); 2584 checkRounding(nf, base, 20, rInc); 2585 } 2586 } 2587 } 2588 } 2589 2590 @Test 2591 public void TestRoundingPattern() { 2592 class TestRoundingPatternItem { 2593 String pattern; 2594 double roundingIncrement; 2595 double testCase; 2596 String expected; 2597 2598 TestRoundingPatternItem(String pattern, double roundingIncrement, double testCase, String expected) { 2599 this.pattern = pattern; 2600 this.roundingIncrement = roundingIncrement; 2601 this.testCase = testCase; 2602 this.expected = expected; 2603 } 2604 }; 2605 2606 TestRoundingPatternItem []tests = { 2607 new TestRoundingPatternItem("##0.65", 0.65, 1.234, "1.30"), 2608 new TestRoundingPatternItem("#50", 50.0, 1230, "1250") 2609 }; 2610 2611 DecimalFormat df = (DecimalFormat) android.icu.text.NumberFormat.getInstance(ULocale.ENGLISH); 2612 String result; 2613 BigDecimal bd; 2614 for (int i = 0; i < tests.length; i++) { 2615 df.applyPattern(tests[i].pattern); 2616 2617 result = df.format(tests[i].testCase); 2618 2619 if (!tests[i].expected.equals(result)) { 2620 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected); 2621 } 2622 2623 bd = new BigDecimal(tests[i].roundingIncrement); 2624 2625 df.setRoundingIncrement(bd); 2626 2627 result = df.format(tests[i].testCase); 2628 2629 if (!tests[i].expected.equals(result)) { 2630 errln("BigDecimal Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected); 2631 } 2632 } 2633 } 2634 2635 @Test 2636 public void TestBigDecimalRounding() { 2637 String figure = "50.000000004"; 2638 Double dbl = new Double(figure); 2639 BigDecimal dec = new BigDecimal(figure); 2640 2641 DecimalFormat f = (DecimalFormat) NumberFormat.getInstance(); 2642 f.applyPattern("00.00######"); 2643 2644 assertEquals("double format", "50.00", f.format(dbl)); 2645 assertEquals("bigdec format", "50.00", f.format(dec)); 2646 2647 int maxFracDigits = f.getMaximumFractionDigits(); 2648 BigDecimal roundingIncrement = new BigDecimal("1").movePointLeft(maxFracDigits); 2649 2650 f.setRoundingIncrement(roundingIncrement); 2651 f.setRoundingMode(BigDecimal.ROUND_DOWN); 2652 assertEquals("Rounding down", f.format(dbl), f.format(dec)); 2653 2654 f.setRoundingIncrement(roundingIncrement); 2655 f.setRoundingMode(BigDecimal.ROUND_HALF_UP); 2656 assertEquals("Rounding half up", f.format(dbl), f.format(dec)); 2657 } 2658 2659 void checkRounding(DecimalFormat nf, BigDecimal base, int iterations, BigDecimal increment) { 2660 nf.setRoundingIncrement(increment.toBigDecimal()); 2661 BigDecimal lastParsed = new BigDecimal(Integer.MIN_VALUE); // used to make sure that rounding is monotonic 2662 for (int i = -iterations; i <= iterations; ++i) { 2663 BigDecimal iValue = base.add(increment.multiply(new BigDecimal(i)).movePointLeft(1)); 2664 BigDecimal smallIncrement = new BigDecimal("0.00000001"); 2665 if (iValue.signum() != 0) { 2666 smallIncrement.multiply(iValue); // scale unless zero 2667 } 2668 // we not only test the value, but some values in a small range around it. 2669 lastParsed = checkRound(nf, iValue.subtract(smallIncrement), lastParsed); 2670 lastParsed = checkRound(nf, iValue, lastParsed); 2671 lastParsed = checkRound(nf, iValue.add(smallIncrement), lastParsed); 2672 } 2673 } 2674 2675 private BigDecimal checkRound(DecimalFormat nf, BigDecimal iValue, BigDecimal lastParsed) { 2676 String formatedBigDecimal = nf.format(iValue); 2677 String formattedDouble = nf.format(iValue.doubleValue()); 2678 if (!equalButForTrailingZeros(formatedBigDecimal, formattedDouble)) { 2679 2680 errln("Failure at: " + iValue + " (" + iValue.doubleValue() + ")" 2681 + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()] 2682 + ",\tRounding-increment: " + nf.getRoundingIncrement() 2683 + ",\tdouble: " + formattedDouble 2684 + ",\tBigDecimal: " + formatedBigDecimal); 2685 2686 } else { 2687 logln("Value: " + iValue 2688 + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()] 2689 + ",\tRounding-increment: " + nf.getRoundingIncrement() 2690 + ",\tdouble: " + formattedDouble 2691 + ",\tBigDecimal: " + formatedBigDecimal); 2692 } 2693 try { 2694 // Number should have compareTo(...) 2695 BigDecimal parsed = toBigDecimal(nf.parse(formatedBigDecimal)); 2696 if (lastParsed.compareTo(parsed) > 0) { 2697 errln("Rounding wrong direction!: " + lastParsed + " > " + parsed); 2698 } 2699 lastParsed = parsed; 2700 } catch (ParseException e) { 2701 errln("Parse Failure with: " + formatedBigDecimal); 2702 } 2703 return lastParsed; 2704 } 2705 2706 static BigDecimal toBigDecimal(Number number) { 2707 return number instanceof BigDecimal ? (BigDecimal) number 2708 : number instanceof BigInteger ? new BigDecimal((BigInteger)number) 2709 : number instanceof java.math.BigDecimal ? new BigDecimal((java.math.BigDecimal)number) 2710 : number instanceof Double ? new BigDecimal(number.doubleValue()) 2711 : number instanceof Float ? new BigDecimal(number.floatValue()) 2712 : new BigDecimal(number.longValue()); 2713 } 2714 2715 static String[] roundingModeNames = { 2716 "ROUND_UP", "ROUND_DOWN", "ROUND_CEILING", "ROUND_FLOOR", 2717 "ROUND_HALF_UP", "ROUND_HALF_DOWN", "ROUND_HALF_EVEN", 2718 "ROUND_UNNECESSARY" 2719 }; 2720 2721 private static boolean equalButForTrailingZeros(String formatted1, String formatted2) { 2722 if (formatted1.length() == formatted2.length()) return formatted1.equals(formatted2); 2723 return stripFinalZeros(formatted1).equals(stripFinalZeros(formatted2)); 2724 } 2725 2726 private static String stripFinalZeros(String formatted) { 2727 int len1 = formatted.length(); 2728 char ch; 2729 while (len1 > 0 && ((ch = formatted.charAt(len1-1)) == '0' || ch == '.')) --len1; 2730 if (len1==1 && ((ch = formatted.charAt(len1-1)) == '-')) --len1; 2731 return formatted.substring(0,len1); 2732 } 2733 2734 //------------------------------------------------------------------ 2735 // Support methods 2736 //------------------------------------------------------------------ 2737 2738 // Format-Parse test 2739 public void expect2(NumberFormat fmt, Number n, String exp) { 2740 // Don't round-trip format test, since we explicitly do it 2741 expect(fmt, n, exp, false); 2742 expect(fmt, exp, n); 2743 } 2744 // Format-Parse test 2745 public void expect3(NumberFormat fmt, Number n, String exp) { 2746 // Don't round-trip format test, since we explicitly do it 2747 expect_rbnf(fmt, n, exp, false); 2748 expect_rbnf(fmt, exp, n); 2749 } 2750 2751 // Format-Parse test (convenience) 2752 public void expect2(NumberFormat fmt, double n, String exp) { 2753 expect2(fmt, new Double(n), exp); 2754 } 2755 // Format-Parse test (convenience) 2756 public void expect3(NumberFormat fmt, double n, String exp) { 2757 expect3(fmt, new Double(n), exp); 2758 } 2759 2760 // Format-Parse test (convenience) 2761 public void expect2(NumberFormat fmt, long n, String exp) { 2762 expect2(fmt, new Long(n), exp); 2763 } 2764 // Format-Parse test (convenience) 2765 public void expect3(NumberFormat fmt, long n, String exp) { 2766 expect3(fmt, new Long(n), exp); 2767 } 2768 2769 // Format test 2770 public void expect(NumberFormat fmt, Number n, String exp, boolean rt) { 2771 StringBuffer saw = new StringBuffer(); 2772 FieldPosition pos = new FieldPosition(0); 2773 fmt.format(n, saw, pos); 2774 String pat = ((DecimalFormat)fmt).toPattern(); 2775 if (saw.toString().equals(exp)) { 2776 logln("Ok " + n + " x " + 2777 pat + " = \"" + 2778 saw + "\""); 2779 // We should be able to round-trip the formatted string => 2780 // number => string (but not the other way around: number 2781 // => string => number2, might have number2 != number): 2782 if (rt) { 2783 try { 2784 Number n2 = fmt.parse(exp); 2785 StringBuffer saw2 = new StringBuffer(); 2786 fmt.format(n2, saw2, pos); 2787 if (!saw2.toString().equals(exp)) { 2788 errln("expect() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2789 ", FAIL \"" + exp + "\" => " + n2 + " => \"" + saw2 + '"'); 2790 } 2791 } catch (ParseException e) { 2792 errln("expect() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2793 ", " + e.getMessage()); 2794 return; 2795 } 2796 } 2797 } else { 2798 errln("expect() format test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2799 ", FAIL " + n + " x " + pat + " = \"" + saw + "\", expected \"" + exp + "\""); 2800 } 2801 } 2802 // Format test 2803 public void expect_rbnf(NumberFormat fmt, Number n, String exp, boolean rt) { 2804 StringBuffer saw = new StringBuffer(); 2805 FieldPosition pos = new FieldPosition(0); 2806 fmt.format(n, saw, pos); 2807 if (saw.toString().equals(exp)) { 2808 logln("Ok " + n + " = \"" + 2809 saw + "\""); 2810 // We should be able to round-trip the formatted string => 2811 // number => string (but not the other way around: number 2812 // => string => number2, might have number2 != number): 2813 if (rt) { 2814 try { 2815 Number n2 = fmt.parse(exp); 2816 StringBuffer saw2 = new StringBuffer(); 2817 fmt.format(n2, saw2, pos); 2818 if (!saw2.toString().equals(exp)) { 2819 errln("expect_rbnf() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2820 ", FAIL \"" + exp + "\" => " + n2 + " => \"" + saw2 + '"'); 2821 } 2822 } catch (ParseException e) { 2823 errln("expect_rbnf() format test rt, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2824 ", " + e.getMessage()); 2825 return; 2826 } 2827 } 2828 } else { 2829 errln("expect_rbnf() format test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2830 ", FAIL " + n + " = \"" + saw + "\", expected \"" + exp + "\""); 2831 } 2832 } 2833 2834 // Format test (convenience) 2835 public void expect(NumberFormat fmt, Number n, String exp) { 2836 expect(fmt, n, exp, true); 2837 } 2838 2839 // Format test (convenience) 2840 public void expect(NumberFormat fmt, double n, String exp) { 2841 expect(fmt, new Double(n), exp); 2842 } 2843 2844 // Format test (convenience) 2845 public void expect(NumberFormat fmt, long n, String exp) { 2846 expect(fmt, new Long(n), exp); 2847 } 2848 2849 // Parse test 2850 public void expect(NumberFormat fmt, String str, Number n) { 2851 Number num = null; 2852 try { 2853 num = fmt.parse(str); 2854 } catch (ParseException e) { 2855 errln(e.getMessage()); 2856 return; 2857 } 2858 String pat = ((DecimalFormat)fmt).toPattern(); 2859 // A little tricky here -- make sure Double(12345.0) and 2860 // Long(12345) match. 2861 if (num.equals(n) || num.doubleValue() == n.doubleValue()) { 2862 logln("Ok \"" + str + "\" x " + 2863 pat + " = " + 2864 num); 2865 } else { 2866 errln("expect() parse test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2867 ", FAIL \"" + str + "\" x " + pat + " = " + num + ", expected " + n); 2868 } 2869 } 2870 2871 // Parse test 2872 public void expect_rbnf(NumberFormat fmt, String str, Number n) { 2873 Number num = null; 2874 try { 2875 num = fmt.parse(str); 2876 } catch (ParseException e) { 2877 errln(e.getMessage()); 2878 return; 2879 } 2880 // A little tricky here -- make sure Double(12345.0) and 2881 // Long(12345) match. 2882 if (num.equals(n) || num.doubleValue() == n.doubleValue()) { 2883 logln("Ok \"" + str + " = " + 2884 num); 2885 } else { 2886 errln("expect_rbnf() parse test, locale " + fmt.getLocale(ULocale.VALID_LOCALE) + 2887 ", FAIL \"" + str + " = " + num + ", expected " + n); 2888 } 2889 } 2890 2891 // Parse test (convenience) 2892 public void expect(NumberFormat fmt, String str, double n) { 2893 expect(fmt, str, new Double(n)); 2894 } 2895 2896 // Parse test (convenience) 2897 public void expect(NumberFormat fmt, String str, long n) { 2898 expect(fmt, str, new Long(n)); 2899 } 2900 2901 private void expectCurrency(NumberFormat nf, Currency curr, 2902 double value, String string) { 2903 DecimalFormat fmt = (DecimalFormat) nf; 2904 if (curr != null) { 2905 fmt.setCurrency(curr); 2906 } 2907 String s = fmt.format(value).replace('\u00A0', ' '); 2908 2909 if (s.equals(string)) { 2910 logln("Ok: " + value + " x " + curr + " => " + s); 2911 } else { 2912 errln("FAIL: " + value + " x " + curr + " => " + s + 2913 ", expected " + string); 2914 } 2915 } 2916 2917 public void expectPad(DecimalFormat fmt, String pat, int pos) { 2918 expectPad(fmt, pat, pos, 0, (char)0); 2919 } 2920 2921 public void expectPad(DecimalFormat fmt, final String pat, int pos, int width, final char pad) { 2922 int apos = 0, awidth = 0; 2923 char apadStr; 2924 try { 2925 fmt.applyPattern(pat); 2926 apos = fmt.getPadPosition(); 2927 awidth = fmt.getFormatWidth(); 2928 apadStr = fmt.getPadCharacter(); 2929 } catch (Exception e) { 2930 apos = -1; 2931 awidth = width; 2932 apadStr = pad; 2933 } 2934 2935 if (apos == pos && awidth == width && apadStr == pad) { 2936 logln("Ok \"" + pat + "\" pos=" 2937 + apos + ((pos == -1) ? "" : " width=" + awidth + " pad=" + apadStr)); 2938 } else { 2939 errln("FAIL \"" + pat + "\" pos=" + apos + " width=" 2940 + awidth + " pad=" + apadStr + ", expected " 2941 + pos + " " + width + " " + pad); 2942 } 2943 } 2944 2945 public void expectPat(DecimalFormat fmt, final String exp) { 2946 String pat = fmt.toPattern(); 2947 if (pat.equals(exp)) { 2948 logln("Ok \"" + pat + "\""); 2949 } else { 2950 errln("FAIL \"" + pat + "\", expected \"" + exp + "\""); 2951 } 2952 } 2953 2954 2955 private void expectParseCurrency(NumberFormat fmt, Currency expected, String text) { 2956 ParsePosition pos = new ParsePosition(0); 2957 CurrencyAmount currencyAmount = fmt.parseCurrency(text, pos); 2958 assertTrue("Parse of " + text + " should have succeeded.", pos.getIndex() > 0); 2959 assertEquals("Currency should be correct.", expected, currencyAmount.getCurrency()); 2960 } 2961 2962 @Test 2963 public void TestJB3832(){ 2964 ULocale locale = new ULocale("pt_PT@currency=PTE"); 2965 NumberFormat format = NumberFormat.getCurrencyInstance(locale); 2966 Currency curr = Currency.getInstance(locale); 2967 logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false})); 2968 CurrencyAmount cAmt = new CurrencyAmount(1150.50, curr); 2969 logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode 2970 String str = format.format(cAmt); 2971 String expected = "1,150$50\u00a0\u200b"; 2972 if(!expected.equals(str)){ 2973 errln("Did not get the expected output Expected: "+expected+" Got: "+ str); 2974 } 2975 } 2976 2977 @Test 2978 public void TestStrictParse() { 2979 String[] pass = { 2980 "0", // single zero before end of text is not leading 2981 "0 ", // single zero at end of number is not leading 2982 "0.", // single zero before period (or decimal, it's ambiguous) is not leading 2983 "0,", // single zero before comma (not group separator) is not leading 2984 "0.0", // single zero before decimal followed by digit is not leading 2985 "0. ", // same as above before period (or decimal) is not leading 2986 "0.100,5", // comma stops parse of decimal (no grouping) 2987 ".00", // leading decimal is ok, even with zeros 2988 "1234567", // group separators are not required 2989 "12345, ", // comma not followed by digit is not a group separator, but end of number 2990 "1,234, ", // if group separator is present, group sizes must be appropriate 2991 "1,234,567", // ...secondary too 2992 "0E", // an exponent not followed by zero or digits is not an exponent 2993 "00", // leading zero before zero - used to be error - see ticket #7913 2994 "012", // leading zero before digit - used to be error - see ticket #7913 2995 "0,456", // leading zero before group separator - used to be error - see ticket #7913 2996 }; 2997 String[] fail = { 2998 "1,2", // wrong number of digits after group separator 2999 ",0", // leading group separator before zero 3000 ",1", // leading group separator before digit 3001 ",.02", // leading group separator before decimal 3002 "1,.02", // group separator before decimal 3003 "1,,200", // multiple group separators 3004 "1,45", // wrong number of digits in primary group 3005 "1,45 that", // wrong number of digits in primary group 3006 "1,45.34", // wrong number of digits in primary group 3007 "1234,567", // wrong number of digits in secondary group 3008 "12,34,567", // wrong number of digits in secondary group 3009 "1,23,456,7890", // wrong number of digits in primary and secondary groups 3010 }; 3011 3012 DecimalFormat nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH); 3013 runStrictParseBatch(nf, pass, fail); 3014 3015 String[] scientificPass = { 3016 "0E2", // single zero before exponent is ok 3017 "1234E2", // any number of digits before exponent is ok 3018 "1,234E", // an exponent string not followed by zero or digits is not an exponent 3019 "00E2", // leading zeroes now allowed in strict mode - see ticket # 3020 }; 3021 String[] scientificFail = { 3022 "1,234E2", // group separators with exponent fail 3023 }; 3024 3025 nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH); 3026 runStrictParseBatch(nf, scientificPass, scientificFail); 3027 3028 String[] mixedPass = { 3029 "12,34,567", 3030 "12,34,567,", 3031 "12,34,567, that", 3032 "12,34,567 that", 3033 }; 3034 String[] mixedFail = { 3035 "12,34,56", 3036 "12,34,56,", 3037 "12,34,56, that ", 3038 "12,34,56 that", 3039 }; 3040 3041 nf = new DecimalFormat("#,##,##0.#"); 3042 runStrictParseBatch(nf, mixedPass, mixedFail); 3043 } 3044 3045 void runStrictParseBatch(DecimalFormat nf, String[] pass, String[] fail) { 3046 nf.setParseStrict(false); 3047 runStrictParseTests("should pass", nf, pass, true); 3048 runStrictParseTests("should also pass", nf, fail, true); 3049 nf.setParseStrict(true); 3050 runStrictParseTests("should still pass", nf, pass, true); 3051 runStrictParseTests("should fail", nf, fail, false); 3052 } 3053 3054 void runStrictParseTests(String msg, DecimalFormat nf, String[] tests, boolean pass) { 3055 logln(""); 3056 logln("pattern: '" + nf.toPattern() + "'"); 3057 logln(msg); 3058 for (int i = 0; i < tests.length; ++i) { 3059 String str = tests[i]; 3060 ParsePosition pp = new ParsePosition(0); 3061 Number n = nf.parse(str, pp); 3062 String formatted = n != null ? nf.format(n) : "null"; 3063 String err = pp.getErrorIndex() == -1 ? "" : "(error at " + pp.getErrorIndex() + ")"; 3064 if ((err.length() == 0) != pass) { 3065 errln("'" + str + "' parsed '" + 3066 str.substring(0, pp.getIndex()) + 3067 "' returned " + n + " formats to '" + 3068 formatted + "' " + err); 3069 } else { 3070 if (err.length() > 0) { 3071 err = "got expected " + err; 3072 } 3073 logln("'" + str + "' parsed '" + 3074 str.substring(0, pp.getIndex()) + 3075 "' returned " + n + " formats to '" + 3076 formatted + "' " + err); 3077 } 3078 } 3079 } 3080 3081 @Test 3082 public void TestJB5251(){ 3083 //save default locale 3084 ULocale defaultLocale = ULocale.getDefault(); 3085 ULocale.setDefault(new ULocale("qr_QR")); 3086 try { 3087 NumberFormat.getInstance(); 3088 } 3089 catch (Exception e) { 3090 errln("Numberformat threw exception for non-existent locale. It should use the default."); 3091 } 3092 //reset default locale 3093 ULocale.setDefault(defaultLocale); 3094 } 3095 3096 @Test 3097 public void TestParseReturnType() { 3098 String[] defaultNonBigDecimals = { 3099 "123", // Long 3100 "123.0", // Long 3101 "0.0", // Long 3102 "12345678901234567890" // BigInteger 3103 }; 3104 3105 String[] doubles = { 3106 "-0.0", 3107 "NaN", 3108 "\u221E" // Infinity 3109 }; 3110 3111 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); 3112 DecimalFormat nf = new DecimalFormat("#.#", sym); 3113 3114 if (nf.isParseBigDecimal()) { 3115 errln("FAIL: isParseDecimal() must return false by default"); 3116 } 3117 3118 // isParseBigDecimal() is false 3119 for (int i = 0; i < defaultNonBigDecimals.length; i++) { 3120 try { 3121 Number n = nf.parse(defaultNonBigDecimals[i]); 3122 if (n instanceof BigDecimal) { 3123 errln("FAIL: parse returns BigDecimal instance"); 3124 } 3125 } catch (ParseException e) { 3126 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e); 3127 } 3128 } 3129 // parse results for doubls must be always Double 3130 for (int i = 0; i < doubles.length; i++) { 3131 try { 3132 Number n = nf.parse(doubles[i]); 3133 if (!(n instanceof Double)) { 3134 errln("FAIL: parse does not return Double instance"); 3135 } 3136 } catch (ParseException e) { 3137 errln("parse of '" + doubles[i] + "' threw exception: " + e); 3138 } 3139 } 3140 3141 // force this DecimalFormat to return BigDecimal 3142 nf.setParseBigDecimal(true); 3143 if (!nf.isParseBigDecimal()) { 3144 errln("FAIL: isParseBigDecimal() must return true"); 3145 } 3146 3147 // isParseBigDecimal() is true 3148 for (int i = 0; i < defaultNonBigDecimals.length; i++) { 3149 try { 3150 Number n = nf.parse(defaultNonBigDecimals[i]); 3151 if (!(n instanceof BigDecimal)) { 3152 errln("FAIL: parse does not return BigDecimal instance"); 3153 } 3154 } catch (ParseException e) { 3155 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e); 3156 } 3157 } 3158 // parse results for doubls must be always Double 3159 for (int i = 0; i < doubles.length; i++) { 3160 try { 3161 Number n = nf.parse(doubles[i]); 3162 if (!(n instanceof Double)) { 3163 errln("FAIL: parse does not return Double instance"); 3164 } 3165 } catch (ParseException e) { 3166 errln("parse of '" + doubles[i] + "' threw exception: " + e); 3167 } 3168 } 3169 } 3170 3171 @Test 3172 public void TestNonpositiveMultiplier() { 3173 DecimalFormat df = new DecimalFormat("0"); 3174 3175 // test zero multiplier 3176 3177 try { 3178 df.setMultiplier(0); 3179 3180 // bad 3181 errln("DecimalFormat.setMultiplier(0) did not throw an IllegalArgumentException"); 3182 } catch (IllegalArgumentException ex) { 3183 // good 3184 } 3185 3186 // test negative multiplier 3187 3188 try { 3189 df.setMultiplier(-1); 3190 3191 if (df.getMultiplier() != -1) { 3192 errln("DecimalFormat.setMultiplier(-1) did not change the multiplier to -1"); 3193 return; 3194 } 3195 3196 // good 3197 } catch (IllegalArgumentException ex) { 3198 // bad 3199 errln("DecimalFormat.setMultiplier(-1) threw an IllegalArgumentException"); 3200 return; 3201 } 3202 3203 expect(df, "1122.123", -1122.123); 3204 expect(df, "-1122.123", 1122.123); 3205 expect(df, "1.2", -1.2); 3206 expect(df, "-1.2", 1.2); 3207 3208 expect2(df, Long.MAX_VALUE, BigInteger.valueOf(Long.MAX_VALUE).negate().toString()); 3209 expect2(df, Long.MIN_VALUE, BigInteger.valueOf(Long.MIN_VALUE).negate().toString()); 3210 expect2(df, Long.MAX_VALUE / 2, BigInteger.valueOf(Long.MAX_VALUE / 2).negate().toString()); 3211 expect2(df, Long.MIN_VALUE / 2, BigInteger.valueOf(Long.MIN_VALUE / 2).negate().toString()); 3212 3213 expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString()); 3214 expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString()); 3215 3216 expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString()); 3217 expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString()); 3218 } 3219 3220 @Test 3221 public void TestJB5358() { 3222 int numThreads = 10; 3223 String numstr = "12345"; 3224 double expected = 12345; 3225 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); 3226 DecimalFormat fmt = new DecimalFormat("#.#", sym); 3227 ArrayList errors = new ArrayList(); 3228 3229 ParseThreadJB5358[] threads = new ParseThreadJB5358[numThreads]; 3230 for (int i = 0; i < numThreads; i++) { 3231 threads[i] = new ParseThreadJB5358((DecimalFormat)fmt.clone(), numstr, expected, errors); 3232 threads[i].start(); 3233 } 3234 for (int i = 0; i < numThreads; i++) { 3235 try { 3236 threads[i].join(); 3237 } catch (InterruptedException ie) { 3238 ie.printStackTrace(); 3239 } 3240 } 3241 if (errors.size() != 0) { 3242 StringBuffer errBuf = new StringBuffer(); 3243 for (int i = 0; i < errors.size(); i++) { 3244 errBuf.append((String)errors.get(i)); 3245 errBuf.append("\n"); 3246 } 3247 errln("FAIL: " + errBuf); 3248 } 3249 } 3250 3251 static private class ParseThreadJB5358 extends Thread { 3252 private final DecimalFormat decfmt; 3253 private final String numstr; 3254 private final double expect; 3255 private final ArrayList errors; 3256 3257 public ParseThreadJB5358(DecimalFormat decfmt, String numstr, double expect, ArrayList errors) { 3258 this.decfmt = decfmt; 3259 this.numstr = numstr; 3260 this.expect = expect; 3261 this.errors = errors; 3262 } 3263 3264 @Override 3265 public void run() { 3266 for (int i = 0; i < 10000; i++) { 3267 try { 3268 Number n = decfmt.parse(numstr); 3269 if (n.doubleValue() != expect) { 3270 synchronized(errors) { 3271 errors.add(new String("Bad parse result - expected:" + expect + " actual:" + n.doubleValue())); 3272 } 3273 } 3274 } catch (Throwable t) { 3275 synchronized(errors) { 3276 errors.add(new String(t.getClass().getName() + " - " + t.getMessage())); 3277 } 3278 } 3279 } 3280 } 3281 } 3282 3283 @Test 3284 public void TestSetCurrency() { 3285 DecimalFormatSymbols decf1 = DecimalFormatSymbols.getInstance(ULocale.US); 3286 DecimalFormatSymbols decf2 = DecimalFormatSymbols.getInstance(ULocale.US); 3287 decf2.setCurrencySymbol("UKD"); 3288 DecimalFormat format1 = new DecimalFormat("000.000", decf1); 3289 DecimalFormat format2 = new DecimalFormat("000.000", decf2); 3290 Currency euro = Currency.getInstance("EUR"); 3291 format1.setCurrency(euro); 3292 format2.setCurrency(euro); 3293 assertEquals("Reset with currency symbol", format1, format2); 3294 } 3295 3296 /* 3297 * Testing the method public StringBuffer format(Object number, ...) 3298 */ 3299 @Test 3300 public void TestFormat() { 3301 NumberFormat nf = NumberFormat.getInstance(); 3302 StringBuffer sb = new StringBuffer("dummy"); 3303 FieldPosition fp = new FieldPosition(0); 3304 3305 // Tests when "if (number instanceof Long)" is true 3306 try { 3307 nf.format(new Long("0"), sb, fp); 3308 } catch (Exception e) { 3309 errln("NumberFormat.format(Object number, ...) was not suppose to " 3310 + "return an exception for a Long object. Error: " + e); 3311 } 3312 3313 // Tests when "else if (number instanceof BigInteger)" is true 3314 try { 3315 nf.format((Object)new BigInteger("0"), sb, fp); 3316 } catch (Exception e) { 3317 errln("NumberFormat.format(Object number, ...) was not suppose to " 3318 + "return an exception for a BigInteger object. Error: " + e); 3319 } 3320 3321 // Tests when "else if (number instanceof java.math.BigDecimal)" is true 3322 try { 3323 nf.format((Object)new java.math.BigDecimal("0"), sb, fp); 3324 } catch (Exception e) { 3325 errln("NumberFormat.format(Object number, ...) was not suppose to " 3326 + "return an exception for a java.math.BigDecimal object. Error: " + e); 3327 } 3328 3329 // Tests when "else if (number instanceof android.icu.math.BigDecimal)" is true 3330 try { 3331 nf.format((Object)new android.icu.math.BigDecimal("0"), sb, fp); 3332 } catch (Exception e) { 3333 errln("NumberFormat.format(Object number, ...) was not suppose to " 3334 + "return an exception for a android.icu.math.BigDecimal object. Error: " + e); 3335 } 3336 3337 // Tests when "else if (number instanceof CurrencyAmount)" is true 3338 try { 3339 CurrencyAmount ca = new CurrencyAmount(0.0, Currency.getInstance(new ULocale("en_US"))); 3340 nf.format((Object)ca, sb, fp); 3341 } catch (Exception e) { 3342 errln("NumberFormat.format(Object number, ...) was not suppose to " 3343 + "return an exception for a CurrencyAmount object. Error: " + e); 3344 } 3345 3346 // Tests when "else if (number instanceof Number)" is true 3347 try { 3348 nf.format(0.0, sb, fp); 3349 } catch (Exception e) { 3350 errln("NumberFormat.format(Object number, ...) was not suppose to " 3351 + "to return an exception for a Number object. Error: " + e); 3352 } 3353 3354 // Tests when "else" is true 3355 try { 3356 nf.format(new Object(), sb, fp); 3357 errln("NumberFormat.format(Object number, ...) was suppose to " 3358 + "return an exception for an invalid object."); 3359 } catch (Exception e) { 3360 } 3361 3362 try { 3363 nf.format(new String("dummy"), sb, fp); 3364 errln("NumberFormat.format(Object number, ...) was suppose to " 3365 + "return an exception for an invalid object."); 3366 } catch (Exception e) { 3367 } 3368 } 3369 3370 /* 3371 * Coverage tests for the implementation of abstract format methods not being called otherwise 3372 */ 3373 public void TestFormatAbstractImplCoverage() { 3374 NumberFormat df = DecimalFormat.getInstance(Locale.ENGLISH); 3375 NumberFormat cdf = CompactDecimalFormat.getInstance(Locale.ENGLISH, CompactDecimalFormat.CompactStyle.SHORT); 3376 NumberFormat rbf = new RuleBasedNumberFormat(ULocale.ENGLISH, RuleBasedNumberFormat.SPELLOUT); 3377 3378 /* 3379 * Test NumberFormat.format(BigDecimal,StringBuffer,FieldPosition) 3380 */ 3381 StringBuffer sb = new StringBuffer(); 3382 String result = df.format(new BigDecimal(2000.43), sb, new FieldPosition(0)).toString(); 3383 if (!"2,000.43".equals(result)) { 3384 errln("DecimalFormat failed. Expected: 2,000.43 - Actual: " + result); 3385 } 3386 3387 sb.delete(0, sb.length()); 3388 result = cdf.format(new BigDecimal(2000.43), sb, new FieldPosition(0)).toString(); 3389 if (!"2K".equals(result)) { 3390 errln("DecimalFormat failed. Expected: 2K - Actual: " + result); 3391 } 3392 3393 sb.delete(0, sb.length()); 3394 result = rbf.format(new BigDecimal(2000.43), sb, new FieldPosition(0)).toString(); 3395 if (!"two thousand point four three".equals(result)) { 3396 errln("DecimalFormat failed. Expected: 'two thousand point four three' - Actual: '" + result + "'"); 3397 } 3398 } 3399 3400 /* 3401 * Tests the method public final static NumberFormat getInstance(int style) public static NumberFormat 3402 * getInstance(Locale inLocale, int style) public static NumberFormat getInstance(ULocale desiredLocale, int choice) 3403 */ 3404 @Test 3405 public void TestGetInstance() { 3406 // Tests "public final static NumberFormat getInstance(int style)" 3407 int maxStyle = NumberFormat.STANDARDCURRENCYSTYLE; 3408 3409 int[] invalid_cases = { NumberFormat.NUMBERSTYLE - 1, NumberFormat.NUMBERSTYLE - 2, 3410 maxStyle + 1, maxStyle + 2 }; 3411 3412 for (int i = NumberFormat.NUMBERSTYLE; i < maxStyle; i++) { 3413 try { 3414 NumberFormat.getInstance(i); 3415 } catch (Exception e) { 3416 errln("NumberFormat.getInstance(int style) was not suppose to " 3417 + "return an exception for passing value of " + i); 3418 } 3419 } 3420 3421 for (int i = 0; i < invalid_cases.length; i++) { 3422 try { 3423 NumberFormat.getInstance(invalid_cases[i]); 3424 errln("NumberFormat.getInstance(int style) was suppose to " 3425 + "return an exception for passing value of " + invalid_cases[i]); 3426 } catch (Exception e) { 3427 } 3428 } 3429 3430 // Tests "public static NumberFormat getInstance(Locale inLocale, int style)" 3431 String[] localeCases = { "en_US", "fr_FR", "de_DE", "jp_JP" }; 3432 3433 for (int i = NumberFormat.NUMBERSTYLE; i < maxStyle; i++) { 3434 for (int j = 0; j < localeCases.length; j++) { 3435 try { 3436 NumberFormat.getInstance(new Locale(localeCases[j]), i); 3437 } catch (Exception e) { 3438 errln("NumberFormat.getInstance(Locale inLocale, int style) was not suppose to " 3439 + "return an exception for passing value of " + localeCases[j] + ", " + i); 3440 } 3441 } 3442 } 3443 3444 // Tests "public static NumberFormat getInstance(ULocale desiredLocale, int choice)" 3445 // Tests when "if (choice < NUMBERSTYLE || choice > PLURALCURRENCYSTYLE)" is true 3446 for (int i = 0; i < invalid_cases.length; i++) { 3447 try { 3448 NumberFormat.getInstance((ULocale) null, invalid_cases[i]); 3449 errln("NumberFormat.getInstance(ULocale inLocale, int choice) was not suppose to " 3450 + "return an exception for passing value of " + invalid_cases[i]); 3451 } catch (Exception e) { 3452 } 3453 } 3454 } 3455 3456 /* 3457 * Tests the class public static abstract class NumberFormatFactory 3458 */ 3459 @Test 3460 public void TestNumberFormatFactory() { 3461 /* 3462 * The following class allows the method public NumberFormat createFormat(Locale loc, int formatType) to be 3463 * tested. 3464 */ 3465 class TestFactory extends NumberFormatFactory { 3466 @Override 3467 public Set<String> getSupportedLocaleNames() { 3468 return null; 3469 } 3470 3471 @Override 3472 public NumberFormat createFormat(ULocale loc, int formatType) { 3473 return null; 3474 } 3475 } 3476 3477 /* 3478 * The following class allows the method public NumberFormat createFormat(ULocale loc, int formatType) to be 3479 * tested. 3480 */ 3481 class TestFactory1 extends NumberFormatFactory { 3482 @Override 3483 public Set<String> getSupportedLocaleNames() { 3484 return null; 3485 } 3486 3487 @Override 3488 public NumberFormat createFormat(Locale loc, int formatType) { 3489 return null; 3490 } 3491 } 3492 3493 TestFactory tf = new TestFactory(); 3494 TestFactory1 tf1 = new TestFactory1(); 3495 3496 /* 3497 * Tests the method public boolean visible() 3498 */ 3499 if (tf.visible() != true) { 3500 errln("NumberFormatFactory.visible() was suppose to return true."); 3501 } 3502 3503 /* 3504 * Tests the method public NumberFormat createFormat(Locale loc, int formatType) 3505 */ 3506 if (tf.createFormat(new Locale(""), 0) != null) { 3507 errln("NumberFormatFactory.createFormat(Locale loc, int formatType) " + "was suppose to return null"); 3508 } 3509 3510 /* 3511 * Tests the method public NumberFormat createFormat(ULocale loc, int formatType) 3512 */ 3513 if (tf1.createFormat(new ULocale(""), 0) != null) { 3514 errln("NumberFormatFactory.createFormat(ULocale loc, int formatType) " + "was suppose to return null"); 3515 } 3516 } 3517 3518 /* 3519 * Tests the class public static abstract class SimpleNumberFormatFactory extends NumberFormatFactory 3520 */ 3521 @Test 3522 public void TestSimpleNumberFormatFactory() { 3523 class TestSimpleNumberFormatFactory extends SimpleNumberFormatFactory { 3524 /* 3525 * Tests the method public SimpleNumberFormatFactory(Locale locale) 3526 */ 3527 TestSimpleNumberFormatFactory() { 3528 super(new Locale("")); 3529 } 3530 } 3531 @SuppressWarnings("unused") 3532 TestSimpleNumberFormatFactory tsnff = new TestSimpleNumberFormatFactory(); 3533 } 3534 3535 /* 3536 * Tests the method public static ULocale[] getAvailableLocales() 3537 */ 3538 @SuppressWarnings("static-access") 3539 @Test 3540 public void TestGetAvailableLocales() { 3541 // Tests when "if (shim == null)" is true 3542 @SuppressWarnings("serial") 3543 class TestGetAvailableLocales extends NumberFormat { 3544 @Override 3545 public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) { 3546 return null; 3547 } 3548 3549 @Override 3550 public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) { 3551 return null; 3552 } 3553 3554 @Override 3555 public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) { 3556 return null; 3557 } 3558 3559 @Override 3560 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) { 3561 return null; 3562 } 3563 3564 @Override 3565 public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) { 3566 return null; 3567 } 3568 3569 @Override 3570 public Number parse(String text, ParsePosition parsePosition) { 3571 return null; 3572 } 3573 } 3574 3575 try { 3576 TestGetAvailableLocales test = new TestGetAvailableLocales(); 3577 test.getAvailableLocales(); 3578 } catch (Exception e) { 3579 errln("NumberFormat.getAvailableLocales() was not suppose to " 3580 + "return an exception when getting getting available locales."); 3581 } 3582 } 3583 3584 /* 3585 * Tests the method public void setMinimumIntegerDigits(int newValue) 3586 */ 3587 @Test 3588 public void TestSetMinimumIntegerDigits() { 3589 NumberFormat nf = NumberFormat.getInstance(); 3590 // For valid array, it is displayed as {min value, max value} 3591 // Tests when "if (minimumIntegerDigits > maximumIntegerDigits)" is true 3592 int[][] cases = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 2, 0 }, { 2, 1 }, { 10, 0 } }; 3593 int[] expectedMax = { 0, 1, 1, 2, 2, 10 }; 3594 if (cases.length != expectedMax.length) { 3595 errln("Can't continue test case method TestSetMinimumIntegerDigits " 3596 + "since the test case arrays are unequal."); 3597 } else { 3598 for (int i = 0; i < cases.length; i++) { 3599 nf.setMaximumIntegerDigits(cases[i][1]); 3600 nf.setMinimumIntegerDigits(cases[i][0]); 3601 if (nf.getMaximumIntegerDigits() != expectedMax[i]) { 3602 errln("NumberFormat.setMinimumIntegerDigits(int newValue " 3603 + "did not return an expected result for parameter " + cases[i][1] + " and " + cases[i][0] 3604 + " and expected " + expectedMax[i] + " but got " + nf.getMaximumIntegerDigits()); 3605 } 3606 } 3607 } 3608 } 3609 3610 /* 3611 * Tests the method public int getRoundingMode() public void setRoundingMode(int roundingMode) 3612 */ 3613 @Test 3614 public void TestRoundingMode() { 3615 @SuppressWarnings("serial") 3616 class TestRoundingMode extends NumberFormat { 3617 @Override 3618 public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) { 3619 return null; 3620 } 3621 3622 @Override 3623 public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) { 3624 return null; 3625 } 3626 3627 @Override 3628 public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) { 3629 return null; 3630 } 3631 3632 @Override 3633 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) { 3634 return null; 3635 } 3636 3637 @Override 3638 public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) { 3639 return null; 3640 } 3641 3642 @Override 3643 public Number parse(String text, ParsePosition parsePosition) { 3644 return null; 3645 } 3646 } 3647 TestRoundingMode tgrm = new TestRoundingMode(); 3648 3649 // Tests the function 'public void setRoundingMode(int roundingMode)' 3650 try { 3651 tgrm.setRoundingMode(0); 3652 errln("NumberFormat.setRoundingMode(int) was suppose to return an exception"); 3653 } catch (Exception e) { 3654 } 3655 3656 // Tests the function 'public int getRoundingMode()' 3657 try { 3658 tgrm.getRoundingMode(); 3659 errln("NumberFormat.getRoundingMode() was suppose to return an exception"); 3660 } catch (Exception e) { 3661 } 3662 } 3663 3664 /* 3665 * Testing lenient decimal/grouping separator parsing 3666 */ 3667 @Test 3668 public void TestLenientSymbolParsing() { 3669 DecimalFormat fmt = new DecimalFormat(); 3670 DecimalFormatSymbols sym = new DecimalFormatSymbols(); 3671 3672 expect(fmt, "12\u300234", 12.34); 3673 3674 // Ticket#7345 - case 1 3675 // Even strict parsing, the decimal separator set in the symbols 3676 // should be successfully parsed. 3677 3678 sym.setDecimalSeparator('\u3002'); 3679 3680 // non-strict 3681 fmt.setDecimalFormatSymbols(sym); 3682 3683 // strict - failed before the fix for #7345 3684 fmt.setParseStrict(true); 3685 expect(fmt, "23\u300245", 23.45); 3686 fmt.setParseStrict(false); 3687 3688 3689 // Ticket#7345 - case 2 3690 // Decimal separator variants other than DecimalFormatSymbols.decimalSeparator 3691 // should not hide the grouping separator DecimalFormatSymbols.groupingSeparator. 3692 sym.setDecimalSeparator('.'); 3693 sym.setGroupingSeparator(','); 3694 fmt.setDecimalFormatSymbols(sym); 3695 3696 expect(fmt, "1,234.56", 1234.56); 3697 3698 sym.setGroupingSeparator('\uFF61'); 3699 fmt.setDecimalFormatSymbols(sym); 3700 3701 expect(fmt, "2\uFF61345.67", 2345.67); 3702 3703 // Ticket#7128 3704 // 3705 sym.setGroupingSeparator(','); 3706 fmt.setDecimalFormatSymbols(sym); 3707 3708 String skipExtSepParse = ICUConfig.get("android.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false"); 3709 if (skipExtSepParse.equals("true")) { 3710 // When the property SkipExtendedSeparatorParsing is true, 3711 // DecimalFormat does not use the extended equivalent separator 3712 // data and only uses the one in DecimalFormatSymbols. 3713 expect(fmt, "23 456", 23); 3714 } else { 3715 // Lenient separator parsing is enabled by default. 3716 // A space character below is interpreted as a 3717 // group separator, even ',' is used as grouping 3718 // separator in the symbols. 3719 expect(fmt, "12 345", 12345); 3720 } 3721 } 3722 3723 /* 3724 * Testing currency driven max/min fraction digits problem 3725 * reported by ticket#7282 3726 */ 3727 @Test 3728 public void TestCurrencyFractionDigits() { 3729 double value = 99.12345; 3730 3731 // Create currency instance 3732 NumberFormat cfmt = NumberFormat.getCurrencyInstance(new ULocale("ja_JP")); 3733 String text1 = cfmt.format(value); 3734 3735 // Reset the same currency and format the test value again 3736 cfmt.setCurrency(cfmt.getCurrency()); 3737 String text2 = cfmt.format(value); 3738 3739 // output1 and output2 must be identical 3740 if (!text1.equals(text2)) { 3741 errln("NumberFormat.format() should return the same result - text1=" 3742 + text1 + " text2=" + text2); 3743 } 3744 } 3745 3746 /* 3747 * Testing rounding to negative zero problem 3748 * reported by ticket#7609 3749 */ 3750 @Test 3751 public void TestNegZeroRounding() { 3752 3753 DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); 3754 df.setRoundingMode(MathContext.ROUND_HALF_UP); 3755 df.setMinimumFractionDigits(1); 3756 df.setMaximumFractionDigits(1); 3757 String text1 = df.format(-0.01); 3758 3759 df.setRoundingIncrement(0.1); 3760 String text2 = df.format(-0.01); 3761 3762 // output1 and output2 must be identical 3763 if (!text1.equals(text2)) { 3764 errln("NumberFormat.format() should return the same result - text1=" 3765 + text1 + " text2=" + text2); 3766 } 3767 3768 } 3769 3770 @Test 3771 public void TestCurrencyAmountCoverage() { 3772 CurrencyAmount ca, cb; 3773 3774 try { 3775 ca = new CurrencyAmount(null, null); 3776 errln("NullPointerException should have been thrown."); 3777 } catch (NullPointerException ex) { 3778 } 3779 try { 3780 ca = new CurrencyAmount(new Integer(0), null); 3781 errln("NullPointerException should have been thrown."); 3782 } catch (NullPointerException ex) { 3783 } 3784 3785 ca = new CurrencyAmount(new Integer(0), Currency.getInstance(new ULocale("ja_JP"))); 3786 cb = new CurrencyAmount(new Integer(1), Currency.getInstance(new ULocale("ja_JP"))); 3787 if (ca.equals(null)) { 3788 errln("Comparison should return false."); 3789 } 3790 if (!ca.equals(ca)) { 3791 errln("Comparision should return true."); 3792 } 3793 if (ca.equals(cb)) { 3794 errln("Comparison should return false."); 3795 } 3796 } 3797 3798 @Test 3799 public void TestExponentParse() { 3800 ParsePosition parsePos = new ParsePosition(0); 3801 DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US); 3802 DecimalFormat fmt = new DecimalFormat("#####", symbols); 3803 Number result = fmt.parse("5.06e-27", parsePos); 3804 if ( result.doubleValue() != 5.06E-27 || parsePos.getIndex() != 8) { 3805 errln("ERROR: ERROR: parse failed - expected 5.06E-27, 8; got " + result.doubleValue() + ", " + parsePos.getIndex()); 3806 } 3807 } 3808 3809 @Test 3810 public void TestExplicitParents() { 3811 // We use these for testing because decimal and grouping separators will be inherited from es_419 3812 // starting with CLDR 2.0 3813 String[] DATA = { 3814 "es", "CO", "", "1.250,75", 3815 "es", "ES", "", "1.250,75", 3816 "es", "GQ", "", "1.250,75", 3817 "es", "MX", "", "1,250.75", 3818 "es", "US", "", "1,250.75", 3819 "es", "VE", "", "1.250,75", 3820 3821 }; 3822 3823 for (int i=0; i<DATA.length; i+=4) { 3824 Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]); 3825 NumberFormat fmt = NumberFormat.getInstance(locale); 3826 String s = fmt.format(1250.75); 3827 if (s.equals(DATA[i+3])) { 3828 logln("Ok: 1250.75 x " + locale + " => " + s); 3829 } else { 3830 errln("FAIL: 1250.75 x " + locale + " => " + s + 3831 ", expected " + DATA[i+3]); 3832 } 3833 } 3834 } 3835 3836 /* 3837 * Test case for #9240 3838 * ICU4J 49.1 DecimalFormat did not clone the internal object holding 3839 * formatted text attribute information properly. Therefore, DecimalFormat 3840 * created by cloning may return incorrect results or may throw an exception 3841 * when formatToCharacterIterator is invoked from multiple threads. 3842 */ 3843 @Test 3844 public void TestFormatToCharacterIteratorThread() { 3845 final int COUNT = 10; 3846 3847 DecimalFormat fmt1 = new DecimalFormat("#0"); 3848 DecimalFormat fmt2 = (DecimalFormat)fmt1.clone(); 3849 3850 int[] res1 = new int[COUNT]; 3851 int[] res2 = new int[COUNT]; 3852 3853 Thread t1 = new Thread(new FormatCharItrTestThread(fmt1, 1, res1)); 3854 Thread t2 = new Thread(new FormatCharItrTestThread(fmt2, 100, res2)); 3855 3856 t1.start(); 3857 t2.start(); 3858 3859 try { 3860 t1.join(); 3861 t2.join(); 3862 } catch (InterruptedException e) { 3863 //TODO 3864 } 3865 3866 int val1 = res1[0]; 3867 int val2 = res2[0]; 3868 3869 for (int i = 0; i < COUNT; i++) { 3870 if (res1[i] != val1) { 3871 errln("Inconsistent first run limit in test thread 1"); 3872 } 3873 if (res2[i] != val2) { 3874 errln("Inconsistent first run limit in test thread 2"); 3875 } 3876 } 3877 } 3878 3879 @Test 3880 public void TestParseMaxDigits() { 3881 DecimalFormat fmt = new DecimalFormat(); 3882 String number = "100000000000"; 3883 int newParseMax = number.length() - 1; 3884 3885 fmt.setParseMaxDigits(-1); 3886 3887 /* Default value is 1000 */ 3888 if (fmt.getParseMaxDigits() != 1000) { 3889 errln("Fail valid value checking in setParseMaxDigits."); 3890 } 3891 3892 try { 3893 if (fmt.parse(number).doubleValue() == Float.POSITIVE_INFINITY) { 3894 errln("Got Infinity but should NOT when parsing number: " + number); 3895 } 3896 3897 fmt.setParseMaxDigits(newParseMax); 3898 3899 if (fmt.parse(number).doubleValue() != Float.POSITIVE_INFINITY) { 3900 errln("Did not get Infinity but should when parsing number: " + number); 3901 } 3902 } catch (ParseException ex) { 3903 3904 } 3905 } 3906 3907 private static class FormatCharItrTestThread implements Runnable { 3908 private final NumberFormat fmt; 3909 private final int num; 3910 private final int[] result; 3911 3912 FormatCharItrTestThread(NumberFormat fmt, int num, int[] result) { 3913 this.fmt = fmt; 3914 this.num = num; 3915 this.result = result; 3916 } 3917 3918 @Override 3919 public void run() { 3920 for (int i = 0; i < result.length; i++) { 3921 AttributedCharacterIterator acitr = fmt.formatToCharacterIterator(num); 3922 acitr.first(); 3923 result[i] = acitr.getRunLimit(); 3924 } 3925 } 3926 } 3927 3928 @Test 3929 public void TestRoundingBehavior() { 3930 final Object[][] TEST_CASES = { 3931 { 3932 ULocale.US, // ULocale - null for default locale 3933 "#.##", // Pattern 3934 Integer.valueOf(BigDecimal.ROUND_DOWN), // Rounding Mode or null (implicit) 3935 Double.valueOf(0.0d), // Rounding increment, Double or BigDecimal, or null (implicit) 3936 Double.valueOf(123.4567d), // Input value, Long, Double, BigInteger or BigDecimal 3937 "123.45" // Expected result, null for exception 3938 }, 3939 { 3940 ULocale.US, 3941 "#.##", 3942 null, 3943 Double.valueOf(0.1d), 3944 Double.valueOf(123.4567d), 3945 "123.5" 3946 }, 3947 { 3948 ULocale.US, 3949 "#.##", 3950 Integer.valueOf(BigDecimal.ROUND_DOWN), 3951 Double.valueOf(0.1d), 3952 Double.valueOf(123.4567d), 3953 "123.4" 3954 }, 3955 { 3956 ULocale.US, 3957 "#.##", 3958 Integer.valueOf(BigDecimal.ROUND_UNNECESSARY), 3959 null, 3960 Double.valueOf(123.4567d), 3961 null 3962 }, 3963 { 3964 ULocale.US, 3965 "#.##", 3966 Integer.valueOf(BigDecimal.ROUND_DOWN), 3967 null, 3968 Long.valueOf(1234), 3969 "1234" 3970 }, 3971 }; 3972 3973 int testNum = 1; 3974 3975 for (Object[] testCase : TEST_CASES) { 3976 // 0: locale 3977 // 1: pattern 3978 ULocale locale = testCase[0] == null ? ULocale.getDefault() : (ULocale)testCase[0]; 3979 String pattern = (String)testCase[1]; 3980 3981 DecimalFormat fmt = new DecimalFormat(pattern, DecimalFormatSymbols.getInstance(locale)); 3982 3983 // 2: rounding mode 3984 Integer roundingMode = null; 3985 if (testCase[2] != null) { 3986 roundingMode = (Integer)testCase[2]; 3987 fmt.setRoundingMode(roundingMode); 3988 } 3989 3990 // 3: rounding increment 3991 if (testCase[3] != null) { 3992 if (testCase[3] instanceof Double) { 3993 fmt.setRoundingIncrement((Double)testCase[3]); 3994 } else if (testCase[3] instanceof BigDecimal) { 3995 fmt.setRoundingIncrement((BigDecimal)testCase[3]); 3996 } else if (testCase[3] instanceof java.math.BigDecimal) { 3997 fmt.setRoundingIncrement((java.math.BigDecimal)testCase[3]); 3998 } 3999 } 4000 4001 // 4: input number 4002 String s = null; 4003 boolean bException = false; 4004 try { 4005 s = fmt.format(testCase[4]); 4006 } catch (ArithmeticException e) { 4007 bException = true; 4008 } 4009 4010 if (bException) { 4011 if (testCase[5] != null) { 4012 errln("Test case #" + testNum + ": ArithmeticException was thrown."); 4013 } 4014 } else { 4015 if (testCase[5] == null) { 4016 errln("Test case #" + testNum + 4017 ": ArithmeticException must be thrown, but got formatted result: " + 4018 s); 4019 } else { 4020 assertEquals("Test case #" + testNum, testCase[5], s); 4021 } 4022 } 4023 4024 testNum++; 4025 } 4026 } 4027 4028 @Test 4029 public void TestSignificantDigits() { 4030 double input[] = { 4031 0, 0, 4032 123, -123, 4033 12345, -12345, 4034 123.45, -123.45, 4035 123.44501, -123.44501, 4036 0.001234, -0.001234, 4037 0.00000000123, -0.00000000123, 4038 0.0000000000000000000123, -0.0000000000000000000123, 4039 1.2, -1.2, 4040 0.0000000012344501, -0.0000000012344501, 4041 123445.01, -123445.01, 4042 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0, 4043 }; 4044 String[] expected = { 4045 "0.00", "0.00", 4046 "123", "-123", 4047 "12345", "-12345", 4048 "123.45", "-123.45", 4049 "123.45", "-123.45", 4050 "0.001234", "-0.001234", 4051 "0.00000000123", "-0.00000000123", 4052 "0.0000000000000000000123", "-0.0000000000000000000123", 4053 "1.20", "-1.20", 4054 "0.0000000012345", "-0.0000000012345", 4055 "123450", "-123450", 4056 "12345000000000000000000000000000000", "-12345000000000000000000000000000000", 4057 }; 4058 DecimalFormat numberFormat = 4059 (DecimalFormat) NumberFormat.getInstance(ULocale.US); 4060 numberFormat.setSignificantDigitsUsed(true); 4061 numberFormat.setMinimumSignificantDigits(3); 4062 numberFormat.setMaximumSignificantDigits(5); 4063 numberFormat.setGroupingUsed(false); 4064 for (int i = 0; i < input.length; i++) { 4065 assertEquals("TestSignificantDigits", expected[i], numberFormat.format(input[i])); 4066 } 4067 } 4068 4069 @Test 4070 public void TestBug9936() { 4071 DecimalFormat numberFormat = 4072 (DecimalFormat) NumberFormat.getInstance(ULocale.US); 4073 assertFalse("", numberFormat.areSignificantDigitsUsed()); 4074 4075 numberFormat.setSignificantDigitsUsed(true); 4076 assertTrue("", numberFormat.areSignificantDigitsUsed()); 4077 4078 numberFormat.setSignificantDigitsUsed(false); 4079 assertFalse("", numberFormat.areSignificantDigitsUsed()); 4080 4081 numberFormat.setMinimumSignificantDigits(3); 4082 assertTrue("", numberFormat.areSignificantDigitsUsed()); 4083 4084 numberFormat.setSignificantDigitsUsed(false); 4085 numberFormat.setMaximumSignificantDigits(6); 4086 assertTrue("", numberFormat.areSignificantDigitsUsed()); 4087 } 4088 4089 @Test 4090 public void TestShowZero() { 4091 DecimalFormat numberFormat = 4092 (DecimalFormat) NumberFormat.getInstance(ULocale.US); 4093 numberFormat.setSignificantDigitsUsed(true); 4094 numberFormat.setMaximumSignificantDigits(3); 4095 assertEquals("TestShowZero", "0", numberFormat.format(0.0)); 4096 } 4097 4098 @Test 4099 public void TestCurrencyPlurals() { 4100 String[][] tests = { 4101 {"en", "USD", "1", "1 US dollar"}, 4102 {"en", "USD", "1.0", "1.0 US dollars"}, 4103 {"en", "USD", "1.00", "1.00 US dollars"}, 4104 {"en", "USD", "1.99", "1.99 US dollars"}, 4105 {"en", "AUD", "1", "1 Australian dollar"}, 4106 {"en", "AUD", "1.00", "1.00 Australian dollars"}, 4107 {"sl", "USD", "1", "1 ameri\u0161ki dolar"}, 4108 {"sl", "USD", "2", "2 ameri\u0161ka dolarja"}, 4109 {"sl", "USD", "3", "3 ameri\u0161ki dolarji"}, 4110 {"sl", "USD", "5", "5 ameriških dolarjev"}, 4111 {"fr", "USD", "1.99", "1,99 dollar des États-Unis"}, 4112 {"ru", "RUB", "1", "1 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0439 \u0440\u0443\u0431\u043B\u044C"}, 4113 {"ru", "RUB", "2", "2 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u044F"}, 4114 {"ru", "RUB", "5", "5 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u0435\u0439"}, 4115 }; 4116 for (String test[] : tests) { 4117 DecimalFormat numberFormat = (DecimalFormat) DecimalFormat.getInstance(new ULocale(test[0]), NumberFormat.PLURALCURRENCYSTYLE); 4118 numberFormat.setCurrency(Currency.getInstance(test[1])); 4119 double number = Double.parseDouble(test[2]); 4120 int dotPos = test[2].indexOf('.'); 4121 int decimals = dotPos < 0 ? 0 : test[2].length() - dotPos - 1; 4122 int digits = dotPos < 0 ? test[2].length() : test[2].length() - 1; 4123 numberFormat.setMaximumFractionDigits(decimals); 4124 numberFormat.setMinimumFractionDigits(decimals); 4125 String actual = numberFormat.format(number); 4126 assertEquals(test[0] + "\t" + test[1] + "\t" + test[2], test[3], actual); 4127 numberFormat.setMaximumSignificantDigits(digits); 4128 numberFormat.setMinimumSignificantDigits(digits); 4129 actual = numberFormat.format(number); 4130 assertEquals(test[0] + "\t" + test[1] + "\t" + test[2], test[3], actual); 4131 } 4132 } 4133 4134 @Test 4135 public void TestCustomCurrencySignAndSeparator() { 4136 DecimalFormatSymbols custom = new DecimalFormatSymbols(ULocale.US); 4137 4138 custom.setCurrencySymbol("*"); 4139 custom.setMonetaryGroupingSeparator('^'); 4140 custom.setMonetaryDecimalSeparator(':'); 4141 4142 DecimalFormat fmt = new DecimalFormat("\u00A4 #,##0.00", custom); 4143 4144 final String numstr = "* 1^234:56"; 4145 expect2(fmt, 1234.56, numstr); 4146 } 4147 4148 @Test 4149 public void TestParseSignsAndMarks() { 4150 class SignsAndMarksItem { 4151 public String locale; 4152 public boolean lenient; 4153 public String numString; 4154 public double value; 4155 // Simple constructor 4156 public SignsAndMarksItem(String loc, boolean lnt, String numStr, double val) { 4157 locale = loc; 4158 lenient = lnt; 4159 numString = numStr; 4160 value = val; 4161 } 4162 }; 4163 final SignsAndMarksItem[] items = { 4164 // *** Note, ICU4J lenient number parsing does not handle arbitrary whitespace, but can 4165 // treat some whitespace as a grouping separator. The cases marked *** below depend 4166 // on isGroupingUsed() being set for the locale, which in turn depends on grouping 4167 // separators being present in the decimalFormat pattern for the locale (& num sys). 4168 // 4169 // locale lenient numString value 4170 new SignsAndMarksItem("en", false, "12", 12 ), 4171 new SignsAndMarksItem("en", true, "12", 12 ), 4172 new SignsAndMarksItem("en", false, "-23", -23 ), 4173 new SignsAndMarksItem("en", true, "-23", -23 ), 4174 new SignsAndMarksItem("en", true, "- 23", -23 ), // *** 4175 new SignsAndMarksItem("en", false, "\u200E-23", -23 ), 4176 new SignsAndMarksItem("en", true, "\u200E-23", -23 ), 4177 new SignsAndMarksItem("en", true, "\u200E- 23", -23 ), // *** 4178 4179 new SignsAndMarksItem("en@numbers=arab", false, "\u0663\u0664", 34 ), 4180 new SignsAndMarksItem("en@numbers=arab", true, "\u0663\u0664", 34 ), 4181 new SignsAndMarksItem("en@numbers=arab", false, "-\u0664\u0665", -45 ), 4182 new SignsAndMarksItem("en@numbers=arab", true, "-\u0664\u0665", -45 ), 4183 new SignsAndMarksItem("en@numbers=arab", true, "- \u0664\u0665", -45 ), // *** 4184 new SignsAndMarksItem("en@numbers=arab", false, "\u200F-\u0664\u0665", -45 ), 4185 new SignsAndMarksItem("en@numbers=arab", true, "\u200F-\u0664\u0665", -45 ), 4186 new SignsAndMarksItem("en@numbers=arab", true, "\u200F- \u0664\u0665", -45 ), // *** 4187 4188 new SignsAndMarksItem("en@numbers=arabext", false, "\u06F5\u06F6", 56 ), 4189 new SignsAndMarksItem("en@numbers=arabext", true, "\u06F5\u06F6", 56 ), 4190 new SignsAndMarksItem("en@numbers=arabext", false, "-\u06F6\u06F7", -67 ), 4191 new SignsAndMarksItem("en@numbers=arabext", true, "-\u06F6\u06F7", -67 ), 4192 new SignsAndMarksItem("en@numbers=arabext", true, "- \u06F6\u06F7", -67 ), // *** 4193 new SignsAndMarksItem("en@numbers=arabext", false, "\u200E-\u200E\u06F6\u06F7", -67 ), 4194 new SignsAndMarksItem("en@numbers=arabext", true, "\u200E-\u200E\u06F6\u06F7", -67 ), 4195 new SignsAndMarksItem("en@numbers=arabext", true, "\u200E-\u200E \u06F6\u06F7", -67 ), // *** 4196 4197 new SignsAndMarksItem("he", false, "12", 12 ), 4198 new SignsAndMarksItem("he", true, "12", 12 ), 4199 new SignsAndMarksItem("he", false, "-23", -23 ), 4200 new SignsAndMarksItem("he", true, "-23", -23 ), 4201 new SignsAndMarksItem("he", true, "- 23", -23 ), // *** 4202 new SignsAndMarksItem("he", false, "\u200E-23", -23 ), 4203 new SignsAndMarksItem("he", true, "\u200E-23", -23 ), 4204 new SignsAndMarksItem("he", true, "\u200E- 23", -23 ), // *** 4205 4206 new SignsAndMarksItem("ar", false, "\u0663\u0664", 34 ), 4207 new SignsAndMarksItem("ar", true, "\u0663\u0664", 34 ), 4208 new SignsAndMarksItem("ar", false, "-\u0664\u0665", -45 ), 4209 new SignsAndMarksItem("ar", true, "-\u0664\u0665", -45 ), 4210 new SignsAndMarksItem("ar", true, "- \u0664\u0665", -45 ), // *** 4211 new SignsAndMarksItem("ar", false, "\u200F-\u0664\u0665", -45 ), 4212 new SignsAndMarksItem("ar", true, "\u200F-\u0664\u0665", -45 ), 4213 new SignsAndMarksItem("ar", true, "\u200F- \u0664\u0665", -45 ), // *** 4214 4215 new SignsAndMarksItem("ar_MA", false, "12", 12 ), 4216 new SignsAndMarksItem("ar_MA", true, "12", 12 ), 4217 new SignsAndMarksItem("ar_MA", false, "-23", -23 ), 4218 new SignsAndMarksItem("ar_MA", true, "-23", -23 ), 4219 new SignsAndMarksItem("ar_MA", true, "- 23", -23 ), // *** 4220 new SignsAndMarksItem("ar_MA", false, "\u200E-23", -23 ), 4221 new SignsAndMarksItem("ar_MA", true, "\u200E-23", -23 ), 4222 new SignsAndMarksItem("ar_MA", true, "\u200E- 23", -23 ), // *** 4223 4224 new SignsAndMarksItem("fa", false, "\u06F5\u06F6", 56 ), 4225 new SignsAndMarksItem("fa", true, "\u06F5\u06F6", 56 ), 4226 new SignsAndMarksItem("fa", false, "\u2212\u06F6\u06F7", -67 ), 4227 new SignsAndMarksItem("fa", true, "\u2212\u06F6\u06F7", -67 ), 4228 new SignsAndMarksItem("fa", true, "\u2212 \u06F6\u06F7", -67 ), // *** 4229 new SignsAndMarksItem("fa", false, "\u200E\u2212\u200E\u06F6\u06F7", -67 ), 4230 new SignsAndMarksItem("fa", true, "\u200E\u2212\u200E\u06F6\u06F7", -67 ), 4231 new SignsAndMarksItem("fa", true, "\u200E\u2212\u200E \u06F6\u06F7", -67 ), // *** 4232 4233 new SignsAndMarksItem("ps", false, "\u06F5\u06F6", 56 ), 4234 new SignsAndMarksItem("ps", true, "\u06F5\u06F6", 56 ), 4235 new SignsAndMarksItem("ps", false, "-\u06F6\u06F7", -67 ), 4236 new SignsAndMarksItem("ps", true, "-\u06F6\u06F7", -67 ), 4237 new SignsAndMarksItem("ps", true, "- \u06F6\u06F7", -67 ), // *** 4238 new SignsAndMarksItem("ps", false, "\u200E-\u200E\u06F6\u06F7", -67 ), 4239 new SignsAndMarksItem("ps", true, "\u200E-\u200E\u06F6\u06F7", -67 ), 4240 new SignsAndMarksItem("ps", true, "\u200E-\u200E \u06F6\u06F7", -67 ), // *** 4241 new SignsAndMarksItem("ps", false, "-\u200E\u06F6\u06F7", -67 ), 4242 new SignsAndMarksItem("ps", true, "-\u200E\u06F6\u06F7", -67 ), 4243 new SignsAndMarksItem("ps", true, "-\u200E \u06F6\u06F7", -67 ), // *** 4244 }; 4245 for (SignsAndMarksItem item: items) { 4246 ULocale locale = new ULocale(item.locale); 4247 NumberFormat numfmt = NumberFormat.getInstance(locale); 4248 if (numfmt != null) { 4249 numfmt.setParseStrict(!item.lenient); 4250 ParsePosition ppos = new ParsePosition(0); 4251 Number num = numfmt.parse(item.numString, ppos); 4252 if (num != null && ppos.getIndex() == item.numString.length()) { 4253 double parsedValue = num.doubleValue(); 4254 if (parsedValue != item.value) { 4255 errln("FAIL: locale " + item.locale + ", lenient " + item.lenient + ", parse of \"" + item.numString + "\" gives value " + parsedValue); 4256 } 4257 } else { 4258 errln("FAIL: locale " + item.locale + ", lenient " + item.lenient + ", parse of \"" + item.numString + "\" gives position " + ppos.getIndex()); 4259 } 4260 } else { 4261 errln("FAIL: NumberFormat.getInstance for locale " + item.locale); 4262 } 4263 } 4264 } 4265 4266 @Test 4267 public void TestContext() { 4268 // just a minimal sanity check for now 4269 NumberFormat nfmt = NumberFormat.getInstance(); 4270 DisplayContext context = nfmt.getContext(DisplayContext.Type.CAPITALIZATION); 4271 if (context != DisplayContext.CAPITALIZATION_NONE) { 4272 errln("FAIL: Initial NumberFormat.getContext() is not CAPITALIZATION_NONE"); 4273 } 4274 nfmt.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE); 4275 context = nfmt.getContext(DisplayContext.Type.CAPITALIZATION); 4276 if (context != DisplayContext.CAPITALIZATION_FOR_STANDALONE) { 4277 errln("FAIL: NumberFormat.getContext() does not return the value set, CAPITALIZATION_FOR_STANDALONE"); 4278 } 4279 } 4280 4281 @Test 4282 public void TestAccountingCurrency() { 4283 String[][] tests = { 4284 //locale num curr fmt per loc curr std fmt curr acct fmt rt 4285 {"en_US", "1234.5", "$1,234.50", "$1,234.50", "$1,234.50", "true"}, 4286 {"en_US@cf=account", "1234.5", "$1,234.50", "$1,234.50", "$1,234.50", "true"}, 4287 {"en_US", "-1234.5", "-$1,234.50", "-$1,234.50", "($1,234.50)", "true"}, 4288 {"en_US@cf=standard", "-1234.5", "-$1,234.50", "-$1,234.50", "($1,234.50)", "true"}, 4289 {"en_US@cf=account", "-1234.5", "($1,234.50)", "-$1,234.50", "($1,234.50)", "true"}, 4290 {"en_US", "0", "$0.00", "$0.00", "$0.00", "true"}, 4291 {"en_US", "-0.2", "-$0.20", "-$0.20", "($0.20)", "true"}, 4292 {"en_US@cf=standard", "-0.2", "-$0.20", "-$0.20", "($0.20)", "true"}, 4293 {"en_US@cf=account", "-0.2", "($0.20)", "-$0.20", "($0.20)", "true"}, 4294 {"ja_JP", "10000", "¥10,000", "¥10,000", "¥10,000", "true" }, 4295 {"ja_JP", "-1000.5", "-¥1,000", "-¥1,000", "(¥1,000)", "false"}, 4296 {"ja_JP@cf=account", "-1000.5", "(¥1,000)", "-¥1,000", "(¥1,000)", "false"}, 4297 {"de_DE", "-23456.7", "-23.456,70\u00A0€", "-23.456,70\u00A0€", "-23.456,70\u00A0€", "true" }, 4298 }; 4299 for (String[] data : tests) { 4300 ULocale loc = new ULocale(data[0]); 4301 double num = Double.parseDouble(data[1]); 4302 String fmtPerLocExpected = data[2]; 4303 String fmtStandardExpected = data[3]; 4304 String fmtAccountExpected = data[4]; 4305 boolean rt = Boolean.parseBoolean(data[5]); 4306 4307 NumberFormat fmtPerLoc = NumberFormat.getInstance(loc, NumberFormat.CURRENCYSTYLE); 4308 expect(fmtPerLoc, num, fmtPerLocExpected, rt); 4309 4310 NumberFormat fmtStandard = NumberFormat.getInstance(loc, NumberFormat.STANDARDCURRENCYSTYLE); 4311 expect(fmtStandard, num, fmtStandardExpected, rt); 4312 4313 NumberFormat fmtAccount = NumberFormat.getInstance(loc, NumberFormat.ACCOUNTINGCURRENCYSTYLE); 4314 expect(fmtAccount, num, fmtAccountExpected, rt); 4315 } 4316 } 4317 4318 @Test 4319 public void TestCurrencyUsage() { 4320 // the 1st one is checking setter/getter, while the 2nd one checks for getInstance 4321 // compare the Currency and Currency Cash Digits 4322 // Note that as of CLDR 26: 4323 // * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that 4324 // * CAD rounds to .05 in the cash style only. 4325 for (int i = 0; i < 2; i++) { 4326 String original_expected = "PKR124"; 4327 DecimalFormat custom = null; 4328 if (i == 0) { 4329 custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=PKR"), 4330 DecimalFormat.CURRENCYSTYLE); 4331 4332 String original = custom.format(123.567); 4333 assertEquals("Test Currency Context", original_expected, original); 4334 4335 // test the getter 4336 assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(), 4337 Currency.CurrencyUsage.STANDARD); 4338 custom.setCurrencyUsage(Currency.CurrencyUsage.CASH); 4339 assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(), Currency.CurrencyUsage.CASH); 4340 } else { 4341 custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=PKR"), 4342 DecimalFormat.CASHCURRENCYSTYLE); 4343 4344 // test the getter 4345 assertEquals("Test Currency Context Purpose", custom.getCurrencyUsage(), Currency.CurrencyUsage.CASH); 4346 } 4347 4348 String cash_currency = custom.format(123.567); 4349 String cash_currency_expected = "PKR124"; 4350 assertEquals("Test Currency Context", cash_currency_expected, cash_currency); 4351 } 4352 4353 // the 1st one is checking setter/getter, while the 2nd one checks for getInstance 4354 // compare the Currency and Currency Cash Rounding 4355 for (int i = 0; i < 2; i++) { 4356 String original_rounding_expected = "CA$123.57"; 4357 DecimalFormat fmt = null; 4358 if (i == 0) { 4359 fmt = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=CAD"), 4360 DecimalFormat.CURRENCYSTYLE); 4361 4362 String original_rounding = fmt.format(123.566); 4363 assertEquals("Test Currency Context", original_rounding_expected, original_rounding); 4364 4365 fmt.setCurrencyUsage(Currency.CurrencyUsage.CASH); 4366 } else { 4367 fmt = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=CAD"), 4368 DecimalFormat.CASHCURRENCYSTYLE); 4369 } 4370 4371 String cash_rounding_currency = fmt.format(123.567); 4372 String cash__rounding_currency_expected = "CA$123.55"; 4373 assertEquals("Test Currency Context", cash__rounding_currency_expected, cash_rounding_currency); 4374 } 4375 4376 // the 1st one is checking setter/getter, while the 2nd one checks for getInstance 4377 // Test the currency change 4378 for (int i = 0; i < 2; i++) { 4379 DecimalFormat fmt2 = null; 4380 if (i == 1) { 4381 fmt2 = (DecimalFormat) NumberFormat.getInstance(new ULocale("en_US@currency=JPY"), 4382 NumberFormat.CURRENCYSTYLE); 4383 fmt2.setCurrencyUsage(Currency.CurrencyUsage.CASH); 4384 } else { 4385 fmt2 = (DecimalFormat) NumberFormat.getInstance(new ULocale("en_US@currency=JPY"), 4386 NumberFormat.CASHCURRENCYSTYLE); 4387 } 4388 4389 fmt2.setCurrency(Currency.getInstance("PKR")); 4390 String PKR_changed = fmt2.format(123.567); 4391 String PKR_changed_expected = "PKR124"; 4392 assertEquals("Test Currency Context", PKR_changed_expected, PKR_changed); 4393 } 4394 } 4395 4396 @Test 4397 public void TestParseRequiredDecimalPoint() { 4398 4399 String[] testPattern = { "00.####", "00.0", "00" }; 4400 4401 String value2Parse = "99"; 4402 double parseValue = 99; 4403 DecimalFormat parser = new DecimalFormat(); 4404 double result; 4405 boolean hasDecimalPoint; 4406 for (int i = 0; i < testPattern.length; i++) { 4407 parser.applyPattern(testPattern[i]); 4408 hasDecimalPoint = testPattern[i].contains("."); 4409 4410 parser.setDecimalPatternMatchRequired(false); 4411 try { 4412 result = parser.parse(value2Parse).doubleValue(); 4413 assertEquals("wrong parsed value", parseValue, result); 4414 } catch (ParseException e) { 4415 TestFmwk.errln("Parsing " + value2Parse + " should have succeeded with " + testPattern[i] + 4416 " and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired()); 4417 } 4418 4419 parser.setDecimalPatternMatchRequired(true); 4420 try { 4421 result = parser.parse(value2Parse).doubleValue(); 4422 if(hasDecimalPoint){ 4423 TestFmwk.errln("Parsing " + value2Parse + " should NOT have succeeded with " + testPattern[i] + 4424 " and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired()); 4425 } 4426 } catch (ParseException e) { 4427 // OK, should fail 4428 } 4429 } 4430 4431 } 4432 4433 4434 //TODO(junit): investigate 4435 @Test 4436 public void TestDataDrivenICU() { 4437 DataDrivenNumberFormatTestUtility.runSuite( 4438 "numberformattestspecification.txt", ICU); 4439 } 4440 4441 //TODO(junit): investigate 4442 @Test 4443 public void TestDataDrivenJDK() { 4444 // Android patch: Android java.text.DecimalFormat is actually ICU. 4445 if (TestUtil.getJavaVendor() == TestUtil.JavaVendor.Android) return; 4446 // Android patch end. 4447 DataDrivenNumberFormatTestUtility.runSuite( 4448 "numberformattestspecification.txt", JDK); 4449 } 4450 4451 4452 @Test 4453 public void TestCurrFmtNegSameAsPositive() { 4454 DecimalFormatSymbols decfmtsym = DecimalFormatSymbols.getInstance(Locale.US); 4455 decfmtsym.setMinusSign('\u200B'); // ZERO WIDTH SPACE, in ICU4J cannot set to empty string 4456 DecimalFormat decfmt = new DecimalFormat("\u00A4#,##0.00;\u00A4#,##0.00", decfmtsym); 4457 String currFmtResult = decfmt.format(-100.0); 4458 if (!currFmtResult.equals("\u200B$100.00")) { 4459 errln("decfmt.toPattern results wrong, expected \u200B$100.00, got " + currFmtResult); 4460 } 4461 } 4462 4463 @Test 4464 public void TestNumberFormatTestDataToString() { 4465 new NumberFormatTestData().toString(); 4466 } 4467 4468 // Testing for Issue 11805. 4469 @Test 4470 public void TestFormatToCharacterIteratorIssue11805 () { 4471 final double number = -350.76; 4472 DecimalFormat dfUS = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.US); 4473 String strUS = dfUS.format(number); 4474 Set<AttributedCharacterIterator.Attribute> resultUS = dfUS.formatToCharacterIterator(number).getAllAttributeKeys(); 4475 assertEquals("Negative US Results: " + strUS, 5, resultUS.size()); 4476 4477 // For each test, add assert that all the fields are present and in the right spot. 4478 // TODO: Add tests for identify and position of each field, as in IntlTestDecimalFormatAPIC. 4479 4480 DecimalFormat dfDE = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.GERMANY); 4481 String strDE = dfDE.format(number); 4482 Set<AttributedCharacterIterator.Attribute> resultDE = dfDE.formatToCharacterIterator(number).getAllAttributeKeys(); 4483 assertEquals("Negative DE Results: " + strDE, 5, resultDE.size()); 4484 4485 DecimalFormat dfIN = (DecimalFormat) DecimalFormat.getCurrencyInstance(new Locale("hi", "in")); 4486 String strIN = dfIN.format(number); 4487 Set<AttributedCharacterIterator.Attribute> resultIN = dfIN.formatToCharacterIterator(number).getAllAttributeKeys(); 4488 assertEquals("Negative IN Results: " + strIN, 5, resultIN.size()); 4489 4490 DecimalFormat dfJP = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.JAPAN); 4491 String strJP = dfJP.format(number); 4492 Set<AttributedCharacterIterator.Attribute> resultJP = dfJP.formatToCharacterIterator(number).getAllAttributeKeys(); 4493 assertEquals("Negative JA Results: " + strJP, 3, resultJP.size()); 4494 4495 DecimalFormat dfGB = (DecimalFormat) DecimalFormat.getCurrencyInstance(new Locale("en", "gb")); 4496 String strGB = dfGB.format(number); 4497 Set<AttributedCharacterIterator.Attribute> resultGB = dfGB.formatToCharacterIterator(number).getAllAttributeKeys(); 4498 assertEquals("Negative GB Results: " + strGB , 5, resultGB.size()); 4499 4500 DecimalFormat dfPlural = (DecimalFormat) NumberFormat.getInstance(new Locale("en", "gb"), 4501 NumberFormat.PLURALCURRENCYSTYLE); 4502 strGB = dfPlural.format(number); 4503 resultGB = dfPlural.formatToCharacterIterator(number).getAllAttributeKeys(); 4504 assertEquals("Negative GB Results: " + strGB , 5, resultGB.size()); 4505 4506 strGB = dfPlural.format(1); 4507 resultGB = dfPlural.formatToCharacterIterator(1).getAllAttributeKeys(); 4508 assertEquals("Negative GB Results: " + strGB , 4, resultGB.size()); 4509 4510 // Test output with unit value. 4511 DecimalFormat auPlural = (DecimalFormat) NumberFormat.getInstance(new Locale("en", "au"), 4512 NumberFormat.PLURALCURRENCYSTYLE); 4513 String strAU = auPlural.format(1L); 4514 Set<AttributedCharacterIterator.Attribute> resultAU = 4515 auPlural.formatToCharacterIterator(1L).getAllAttributeKeys(); 4516 assertEquals("Unit AU Result: " + strAU , 4, resultAU.size()); 4517 4518 // Verify Permille fields. 4519 DecimalFormatSymbols sym = new DecimalFormatSymbols(new Locale("en", "gb")); 4520 DecimalFormat dfPermille = new DecimalFormat("####0.##\u2030", sym); 4521 strGB = dfPermille.format(number); 4522 resultGB = dfPermille.formatToCharacterIterator(number).getAllAttributeKeys(); 4523 assertEquals("Negative GB Permille Results: " + strGB , 3, resultGB.size()); 4524 } 4525 4526 // Testing for Issue 11808. 4527 @Test 4528 public void TestRoundUnnecessarytIssue11808 () { 4529 DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(); 4530 StringBuffer result = new StringBuffer(""); 4531 df.setRoundingMode(BigDecimal.ROUND_UNNECESSARY); 4532 df.applyPattern("00.0#E0"); 4533 4534 try { 4535 df.format(99999.0, result, new FieldPosition(0)); 4536 fail("Missing ArithmeticException for double: " + result); 4537 } catch (ArithmeticException expected) { 4538 // The exception should be thrown, since rounding is needed. 4539 } 4540 4541 try { 4542 result = df.format(99999, result, new FieldPosition(0)); 4543 fail("Missing ArithmeticException for int: " + result); 4544 } catch (ArithmeticException expected) { 4545 // The exception should be thrown, since rounding is needed. 4546 } 4547 4548 try { 4549 result = df.format(new BigInteger("999999"), result, new FieldPosition(0)); 4550 fail("Missing ArithmeticException for BigInteger: " + result); 4551 } catch (ArithmeticException expected) { 4552 // The exception should be thrown, since rounding is needed. 4553 } 4554 4555 try { 4556 result = df.format(new BigDecimal("99999"), result, new FieldPosition(0)); 4557 fail("Missing ArithmeticException for BigDecimal: " + result); 4558 } catch (ArithmeticException expected) { 4559 // The exception should be thrown, since rounding is needed. 4560 } 4561 4562 try { 4563 result = df.format(new BigDecimal("-99999"), result, new FieldPosition(0)); 4564 fail("Missing ArithmeticException for BigDecimal: " + result); 4565 } catch (ArithmeticException expected) { 4566 // The exception should be thrown, since rounding is needed. 4567 } 4568 } 4569 4570 // Testing for Issue 11735. 4571 @Test 4572 public void TestNPEIssue11735() { 4573 DecimalFormat fmt = new DecimalFormat("0", new DecimalFormatSymbols(new ULocale("en"))); 4574 ParsePosition ppos = new ParsePosition(0); 4575 assertEquals("Currency symbol missing in parse. Expect null result.", 4576 fmt.parseCurrency("53.45", ppos), null); 4577 } 4578 4579 private void CompareAttributedCharacterFormatOutput(AttributedCharacterIterator iterator, 4580 List<FieldContainer> expected, String formattedOutput) { 4581 4582 List<FieldContainer> result = new ArrayList<FieldContainer>(); 4583 while (iterator.getIndex() != iterator.getEndIndex()) { 4584 int start = iterator.getRunStart(); 4585 int end = iterator.getRunLimit(); 4586 Iterator it = iterator.getAttributes().keySet().iterator(); 4587 AttributedCharacterIterator.Attribute attribute = (AttributedCharacterIterator.Attribute) it.next(); 4588 Object value = iterator.getAttribute(attribute); 4589 result.add(new FieldContainer(start, end, attribute, value)); 4590 iterator.setIndex(end); 4591 } 4592 assertEquals("Comparing vector length for " + formattedOutput, 4593 expected.size(), result.size()); 4594 4595 if (!expected.containsAll(result)) { 4596 // Print information on the differences. 4597 for (int i = 0; i < expected.size(); i++) { 4598 System.out.println(" expected[" + i + "] =" + 4599 expected.get(i).start + " " + 4600 expected.get(i).end + " " + 4601 expected.get(i).attribute + " " + 4602 expected.get(i).value); 4603 System.out.println(" result[" + i + "] =" + 4604 result.get(i).start + " " + 4605 result.get(i).end + " " + 4606 result.get(i).attribute + " " + 4607 result.get(i).value); 4608 } 4609 } 4610 // TODO: restore when #11914 is fixed. 4611 // assertTrue("Comparing vector results for " + formattedOutput, 4612 // expected.containsAll(result)); 4613 } 4614 4615 // Testing for Issue 11914, missing FieldPositions for some field types. 4616 @Test 4617 public void TestNPEIssue11914() { 4618 // First test: Double value with grouping separators. 4619 List<FieldContainer> v1 = new ArrayList<FieldContainer>(7); 4620 v1.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER)); 4621 v1.add(new FieldContainer(3, 4, NumberFormat.Field.GROUPING_SEPARATOR)); 4622 v1.add(new FieldContainer(4, 7, NumberFormat.Field.INTEGER)); 4623 v1.add(new FieldContainer(7, 8, NumberFormat.Field.GROUPING_SEPARATOR)); 4624 v1.add(new FieldContainer(8, 11, NumberFormat.Field.INTEGER)); 4625 v1.add(new FieldContainer(11, 12, NumberFormat.Field.DECIMAL_SEPARATOR)); 4626 v1.add(new FieldContainer(12, 15, NumberFormat.Field.FRACTION)); 4627 4628 Number number = new Double(123456789.9753); 4629 ULocale usLoc = new ULocale("en-US"); 4630 DecimalFormatSymbols US = new DecimalFormatSymbols(usLoc); 4631 4632 NumberFormat outFmt = NumberFormat.getNumberInstance(usLoc); 4633 String numFmtted = outFmt.format(number); 4634 AttributedCharacterIterator iterator = 4635 outFmt.formatToCharacterIterator(number); 4636 CompareAttributedCharacterFormatOutput(iterator, v1, numFmtted); 4637 4638 // Second test: Double with scientific notation formatting. 4639 List<FieldContainer> v2 = new ArrayList<FieldContainer>(7); 4640 v2.add(new FieldContainer(0, 1, NumberFormat.Field.INTEGER)); 4641 v2.add(new FieldContainer(1, 2, NumberFormat.Field.DECIMAL_SEPARATOR)); 4642 v2.add(new FieldContainer(2, 5, NumberFormat.Field.FRACTION)); 4643 v2.add(new FieldContainer(5, 6, NumberFormat.Field.EXPONENT_SYMBOL)); 4644 v2.add(new FieldContainer(6, 7, NumberFormat.Field.EXPONENT_SIGN)); 4645 v2.add(new FieldContainer(7, 8, NumberFormat.Field.EXPONENT)); 4646 DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US); 4647 4648 numFmtted = fmt2.format(number); 4649 iterator = fmt2.formatToCharacterIterator(number); 4650 CompareAttributedCharacterFormatOutput(iterator, v2, numFmtted); 4651 4652 // Third test. BigInteger with grouping separators. 4653 List<FieldContainer> v3 = new ArrayList<FieldContainer>(7); 4654 v3.add(new FieldContainer(0, 1, NumberFormat.Field.SIGN)); 4655 v3.add(new FieldContainer(1, 2, NumberFormat.Field.INTEGER)); 4656 v3.add(new FieldContainer(2, 3, NumberFormat.Field.GROUPING_SEPARATOR)); 4657 v3.add(new FieldContainer(3, 6, NumberFormat.Field.INTEGER)); 4658 v3.add(new FieldContainer(6, 7, NumberFormat.Field.GROUPING_SEPARATOR)); 4659 v3.add(new FieldContainer(7, 10, NumberFormat.Field.INTEGER)); 4660 v3.add(new FieldContainer(10, 11, NumberFormat.Field.GROUPING_SEPARATOR)); 4661 v3.add(new FieldContainer(11, 14, NumberFormat.Field.INTEGER)); 4662 v3.add(new FieldContainer(14, 15, NumberFormat.Field.GROUPING_SEPARATOR)); 4663 v3.add(new FieldContainer(15, 18, NumberFormat.Field.INTEGER)); 4664 v3.add(new FieldContainer(18, 19, NumberFormat.Field.GROUPING_SEPARATOR)); 4665 v3.add(new FieldContainer(19, 22, NumberFormat.Field.INTEGER)); 4666 v3.add(new FieldContainer(22, 23, NumberFormat.Field.GROUPING_SEPARATOR)); 4667 v3.add(new FieldContainer(23, 26, NumberFormat.Field.INTEGER)); 4668 BigInteger bigNumberInt = new BigInteger("-1234567890246813579"); 4669 String fmtNumberBigInt = outFmt.format(bigNumberInt); 4670 4671 iterator = outFmt.formatToCharacterIterator(bigNumberInt); 4672 CompareAttributedCharacterFormatOutput(iterator, v3, fmtNumberBigInt); 4673 4674 // Fourth test: BigDecimal with exponential formatting. 4675 List<FieldContainer> v4 = new ArrayList<FieldContainer>(7); 4676 v4.add(new FieldContainer(0, 1, NumberFormat.Field.SIGN)); 4677 v4.add(new FieldContainer(1, 2, NumberFormat.Field.INTEGER)); 4678 v4.add(new FieldContainer(2, 3, NumberFormat.Field.DECIMAL_SEPARATOR)); 4679 v4.add(new FieldContainer(3, 6, NumberFormat.Field.FRACTION)); 4680 v4.add(new FieldContainer(6, 7, NumberFormat.Field.EXPONENT_SYMBOL)); 4681 v4.add(new FieldContainer(7, 8, NumberFormat.Field.EXPONENT_SIGN)); 4682 v4.add(new FieldContainer(8, 9, NumberFormat.Field.EXPONENT)); 4683 4684 java.math.BigDecimal numberBigD = new java.math.BigDecimal(-123456789); 4685 String fmtNumberBigDExp = fmt2.format(numberBigD); 4686 4687 iterator = fmt2.formatToCharacterIterator(numberBigD); 4688 CompareAttributedCharacterFormatOutput(iterator, v4, fmtNumberBigDExp); 4689 4690 } 4691 4692 // Test that the decimal is shown even when there are no fractional digits 4693 @Test 4694 public void Test11621() throws Exception { 4695 String pat = "0.##E0"; 4696 4697 DecimalFormatSymbols icuSym = new DecimalFormatSymbols(Locale.US); 4698 DecimalFormat icuFmt = new DecimalFormat(pat, icuSym); 4699 icuFmt.setDecimalSeparatorAlwaysShown(true); 4700 String icu = ((NumberFormat)icuFmt).format(299792458); 4701 4702 java.text.DecimalFormatSymbols jdkSym = new java.text.DecimalFormatSymbols(Locale.US); 4703 java.text.DecimalFormat jdkFmt = new java.text.DecimalFormat(pat,jdkSym); 4704 jdkFmt.setDecimalSeparatorAlwaysShown(true); 4705 String jdk = ((java.text.NumberFormat)jdkFmt).format(299792458); 4706 4707 assertEquals("ICU and JDK placement of decimal in exponent", jdk, icu); 4708 } 4709 4710 private void checkFormatWithField(String testInfo, Format format, Object object, 4711 String expected, Format.Field field, int begin, int end) { 4712 StringBuffer buffer = new StringBuffer(); 4713 FieldPosition pos = new FieldPosition(field); 4714 format.format(object, buffer, pos); 4715 4716 assertEquals("Test " + testInfo + ": incorrect formatted text", expected, buffer.toString()); 4717 4718 if (begin != pos.getBeginIndex() || end != pos.getEndIndex()) { 4719 assertEquals("Index mismatch", field + " " + begin + ".." + end, 4720 pos.getFieldAttribute() + " " + pos.getBeginIndex() + ".." + pos.getEndIndex()); 4721 } 4722 } 4723 4724 @Test 4725 public void TestMissingFieldPositionsCurrency() { 4726 DecimalFormat formatter = (DecimalFormat) NumberFormat.getCurrencyInstance(ULocale.US); 4727 Number number = new Double(92314587.66); 4728 String result = "$92,314,587.66"; 4729 4730 checkFormatWithField("currency", formatter, number, result, 4731 NumberFormat.Field.CURRENCY, 0, 1); 4732 checkFormatWithField("integer", formatter, number, result, 4733 NumberFormat.Field.INTEGER, 1, 11); 4734 checkFormatWithField("grouping separator", formatter, number, result, 4735 NumberFormat.Field.GROUPING_SEPARATOR, 3, 4); 4736 checkFormatWithField("decimal separator", formatter, number, result, 4737 NumberFormat.Field.DECIMAL_SEPARATOR, 11, 12); 4738 checkFormatWithField("fraction", formatter, number, result, 4739 NumberFormat.Field.FRACTION, 12, 14); 4740 } 4741 4742 @Test 4743 public void TestMissingFieldPositionsNegativeDouble() { 4744 // test for exponential fields with double 4745 DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US); 4746 Number number = new Double(-12345678.90123); 4747 DecimalFormat formatter = new DecimalFormat("0.#####E+00", us_symbols); 4748 String numFmtted = formatter.format(number); 4749 4750 checkFormatWithField("sign", formatter, number, numFmtted, 4751 NumberFormat.Field.SIGN, 0, 1); 4752 checkFormatWithField("integer", formatter, number, numFmtted, 4753 NumberFormat.Field.INTEGER, 1, 2); 4754 checkFormatWithField("decimal separator", formatter, number, numFmtted, 4755 NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3); 4756 checkFormatWithField("exponent symbol", formatter, number, numFmtted, 4757 NumberFormat.Field.EXPONENT_SYMBOL, 8, 9); 4758 checkFormatWithField("exponent sign", formatter, number, numFmtted, 4759 NumberFormat.Field.EXPONENT_SIGN, 9, 10); 4760 checkFormatWithField("exponent", formatter, number, numFmtted, 4761 NumberFormat.Field.EXPONENT, 10, 12); 4762 } 4763 4764 @Test 4765 public void TestMissingFieldPositionsPerCent() { 4766 // Check PERCENT 4767 DecimalFormat percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(ULocale.US); 4768 Number number = new Double(-0.986); 4769 String numberFormatted = percentFormat.format(number); 4770 checkFormatWithField("sign", percentFormat, number, numberFormatted, 4771 NumberFormat.Field.SIGN, 0, 1); 4772 checkFormatWithField("integer", percentFormat, number, numberFormatted, 4773 NumberFormat.Field.INTEGER, 1, 3); 4774 checkFormatWithField("percent", percentFormat, number, numberFormatted, 4775 NumberFormat.Field.PERCENT, 3, 4); 4776 } 4777 4778 @Test 4779 public void TestMissingFieldPositionsPerCentPattern() { 4780 // Check PERCENT with more digits 4781 DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US); 4782 DecimalFormat fmtPercent = new DecimalFormat("0.#####%", us_symbols); 4783 Number number = new Double(-0.986); 4784 String numFmtted = fmtPercent.format(number); 4785 4786 checkFormatWithField("sign", fmtPercent, number, numFmtted, 4787 NumberFormat.Field.SIGN, 0, 1); 4788 checkFormatWithField("integer", fmtPercent, number, numFmtted, 4789 NumberFormat.Field.INTEGER, 1, 3); 4790 checkFormatWithField("decimal separator", fmtPercent, number, numFmtted, 4791 NumberFormat.Field.DECIMAL_SEPARATOR, 3, 4); 4792 checkFormatWithField("fraction", fmtPercent, number, numFmtted, 4793 NumberFormat.Field.FRACTION, 4, 5); 4794 checkFormatWithField("percent", fmtPercent, number, numFmtted, 4795 NumberFormat.Field.PERCENT, 5, 6); 4796 } 4797 4798 @Test 4799 public void TestMissingFieldPositionsPerMille() { 4800 // Check PERMILLE 4801 DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US); 4802 DecimalFormat fmtPerMille = new DecimalFormat("0.######‰", us_symbols); 4803 Number numberPermille = new Double(-0.98654); 4804 String numFmtted = fmtPerMille.format(numberPermille); 4805 4806 checkFormatWithField("sign", fmtPerMille, numberPermille, numFmtted, 4807 NumberFormat.Field.SIGN, 0, 1); 4808 checkFormatWithField("integer", fmtPerMille, numberPermille, numFmtted, 4809 NumberFormat.Field.INTEGER, 1, 4); 4810 checkFormatWithField("decimal separator", fmtPerMille, numberPermille, numFmtted, 4811 NumberFormat.Field.DECIMAL_SEPARATOR, 4, 5); 4812 checkFormatWithField("fraction", fmtPerMille, numberPermille, numFmtted, 4813 NumberFormat.Field.FRACTION, 5, 7); 4814 checkFormatWithField("permille", fmtPerMille, numberPermille, numFmtted, 4815 NumberFormat.Field.PERMILLE, 7, 8); 4816 } 4817 4818 @Test 4819 public void TestMissingFieldPositionsNegativeBigInt() { 4820 DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US); 4821 DecimalFormat formatter = new DecimalFormat("0.#####E+0", us_symbols); 4822 Number number = new BigDecimal("-123456789987654321"); 4823 String bigDecFmtted = formatter.format(number); 4824 4825 checkFormatWithField("sign", formatter, number, bigDecFmtted, 4826 NumberFormat.Field.SIGN, 0, 1); 4827 checkFormatWithField("integer", formatter, number, bigDecFmtted, 4828 NumberFormat.Field.INTEGER, 1, 2); 4829 checkFormatWithField("decimal separator", formatter, number, bigDecFmtted, 4830 NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3); 4831 checkFormatWithField("exponent symbol", formatter, number, bigDecFmtted, 4832 NumberFormat.Field.EXPONENT_SYMBOL, 8, 9); 4833 checkFormatWithField("exponent sign", formatter, number, bigDecFmtted, 4834 NumberFormat.Field.EXPONENT_SIGN, 9, 10); 4835 checkFormatWithField("exponent", formatter, number, bigDecFmtted, 4836 NumberFormat.Field.EXPONENT, 10, 12); 4837 } 4838 4839 @Test 4840 public void TestMissingFieldPositionsNegativeLong() { 4841 Number number = new Long("-123456789987654321"); 4842 DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US); 4843 DecimalFormat formatter = new DecimalFormat("0.#####E+0", us_symbols); 4844 String longFmtted = formatter.format(number); 4845 4846 checkFormatWithField("sign", formatter, number, longFmtted, 4847 NumberFormat.Field.SIGN, 0, 1); 4848 checkFormatWithField("integer", formatter, number, longFmtted, 4849 NumberFormat.Field.INTEGER, 1, 2); 4850 checkFormatWithField("decimal separator", formatter, number, longFmtted, 4851 NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3); 4852 checkFormatWithField("exponent symbol", formatter, number, longFmtted, 4853 NumberFormat.Field.EXPONENT_SYMBOL, 8, 9); 4854 checkFormatWithField("exponent sign", formatter, number, longFmtted, 4855 NumberFormat.Field.EXPONENT_SIGN, 9, 10); 4856 checkFormatWithField("exponent", formatter, number, longFmtted, 4857 NumberFormat.Field.EXPONENT, 10, 12); 4858 } 4859 4860 @Test 4861 public void TestMissingFieldPositionsPositiveBigDec() { 4862 // Check complex positive;negative pattern. 4863 DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US); 4864 DecimalFormat fmtPosNegSign = new DecimalFormat("+0.####E+00;-0.#######E+0", us_symbols); 4865 Number positiveExp = new Double("9876543210"); 4866 String posExpFormatted = fmtPosNegSign.format(positiveExp); 4867 4868 checkFormatWithField("sign", fmtPosNegSign, positiveExp, posExpFormatted, 4869 NumberFormat.Field.SIGN, 0, 1); 4870 checkFormatWithField("integer", fmtPosNegSign, positiveExp, posExpFormatted, 4871 NumberFormat.Field.INTEGER, 1, 2); 4872 checkFormatWithField("decimal separator", fmtPosNegSign, positiveExp, posExpFormatted, 4873 NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3); 4874 checkFormatWithField("fraction", fmtPosNegSign, positiveExp, posExpFormatted, 4875 NumberFormat.Field.FRACTION, 3, 7); 4876 checkFormatWithField("exponent symbol", fmtPosNegSign, positiveExp, posExpFormatted, 4877 NumberFormat.Field.EXPONENT_SYMBOL, 7, 8); 4878 checkFormatWithField("exponent sign", fmtPosNegSign, positiveExp, posExpFormatted, 4879 NumberFormat.Field.EXPONENT_SIGN, 8, 9); 4880 checkFormatWithField("exponent", fmtPosNegSign, positiveExp, posExpFormatted, 4881 NumberFormat.Field.EXPONENT, 9, 11); 4882 } 4883 4884 @Test 4885 public void TestMissingFieldPositionsNegativeBigDec() { 4886 // Check complex positive;negative pattern. 4887 DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US); 4888 DecimalFormat fmtPosNegSign = new DecimalFormat("+0.####E+00;-0.#######E+0", us_symbols); 4889 Number negativeExp = new BigDecimal("-0.000000987654321083"); 4890 String negExpFormatted = fmtPosNegSign.format(negativeExp); 4891 4892 checkFormatWithField("sign", fmtPosNegSign, negativeExp, negExpFormatted, 4893 NumberFormat.Field.SIGN, 0, 1); 4894 checkFormatWithField("integer", fmtPosNegSign, negativeExp, negExpFormatted, 4895 NumberFormat.Field.INTEGER, 1, 2); 4896 checkFormatWithField("decimal separator", fmtPosNegSign, negativeExp, negExpFormatted, 4897 NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3); 4898 checkFormatWithField("fraction", fmtPosNegSign, negativeExp, negExpFormatted, 4899 NumberFormat.Field.FRACTION, 3, 7); 4900 checkFormatWithField("exponent symbol", fmtPosNegSign, negativeExp, negExpFormatted, 4901 NumberFormat.Field.EXPONENT_SYMBOL, 7, 8); 4902 checkFormatWithField("exponent sign", fmtPosNegSign, negativeExp, negExpFormatted, 4903 NumberFormat.Field.EXPONENT_SIGN, 8, 9); 4904 checkFormatWithField("exponent", fmtPosNegSign, negativeExp, negExpFormatted, 4905 NumberFormat.Field.EXPONENT, 9, 11); 4906 } 4907 4908 @Test 4909 public void TestStringSymbols() { 4910 DecimalFormatSymbols symbols = new DecimalFormatSymbols(ULocale.US); 4911 4912 String[] customDigits = {"(0)", "(1)", "(2)", "(3)", "(4)", "(5)", "(6)", "(7)", "(8)", "(9)"}; 4913 symbols.setDigitStrings(customDigits); 4914 symbols.setDecimalSeparatorString("~~"); 4915 symbols.setGroupingSeparatorString("^^"); 4916 4917 DecimalFormat fmt = new DecimalFormat("#,##0.0#", symbols); 4918 4919 expect2(fmt, 1234567.89, "(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)"); 4920 } 4921} 4922