Index: icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java |
=================================================================== |
--- icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java (revision 39589) |
+++ icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java (working copy) |
@@ -14,8 +14,13 @@ |
package com.ibm.icu.dev.test.format; |
+import java.io.ByteArrayInputStream; |
+import java.io.ByteArrayOutputStream; |
import java.io.IOException; |
+import java.io.ObjectInputStream; |
+import java.io.ObjectOutputStream; |
import java.math.BigInteger; |
+import java.math.RoundingMode; |
import java.text.AttributedCharacterIterator; |
import java.text.FieldPosition; |
import java.text.Format; |
@@ -36,6 +41,7 @@ |
import com.ibm.icu.impl.LocaleUtility; |
import com.ibm.icu.impl.data.ResourceReader; |
import com.ibm.icu.impl.data.TokenIterator; |
+import com.ibm.icu.impl.number.rounders.SignificantDigitsRounder.SignificantDigitsMode; |
import com.ibm.icu.math.BigDecimal; |
import com.ibm.icu.math.MathContext; |
import com.ibm.icu.text.CompactDecimalFormat; |
@@ -49,408 +55,12 @@ |
import com.ibm.icu.text.NumberingSystem; |
import com.ibm.icu.text.RuleBasedNumberFormat; |
import com.ibm.icu.util.Currency; |
+import com.ibm.icu.util.Currency.CurrencyUsage; |
import com.ibm.icu.util.CurrencyAmount; |
import com.ibm.icu.util.ULocale; |
public class NumberFormatTest extends TestFmwk { |
- private static ULocale EN = new ULocale("en"); |
- |
- private static Number toNumber(String s) { |
- if (s.equals("NaN")) { |
- return Double.NaN; |
- } else if (s.equals("-Inf")) { |
- return Double.NEGATIVE_INFINITY; |
- } else if (s.equals("Inf")) { |
- return Double.POSITIVE_INFINITY; |
- } |
- return new BigDecimal(s); |
- } |
- |
- |
- private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU = |
- new DataDrivenNumberFormatTestUtility.CodeUnderTest() { |
- @Override |
- public Character Id() { return 'J'; } |
- |
- @Override |
- public String format(NumberFormatTestData tuple) { |
- DecimalFormat fmt = newDecimalFormat(tuple); |
- String actual = fmt.format(toNumber(tuple.format)); |
- String expected = tuple.output; |
- if (!expected.equals(actual)) { |
- return "Expected " + expected + ", got " + actual; |
- } |
- return null; |
- } |
- |
- @Override |
- public String toPattern(NumberFormatTestData tuple) { |
- DecimalFormat fmt = newDecimalFormat(tuple); |
- StringBuilder result = new StringBuilder(); |
- if (tuple.toPattern != null) { |
- String expected = tuple.toPattern; |
- String actual = fmt.toPattern(); |
- if (!expected.equals(actual)) { |
- result.append("Expected toPattern=" + expected + ", got " + actual); |
- } |
- } |
- if (tuple.toLocalizedPattern != null) { |
- String expected = tuple.toLocalizedPattern; |
- String actual = fmt.toLocalizedPattern(); |
- if (!expected.equals(actual)) { |
- result.append("Expected toLocalizedPattern=" + expected + ", got " + actual); |
- } |
- } |
- return result.length() == 0 ? null : result.toString(); |
- } |
- |
- @Override |
- public String parse(NumberFormatTestData tuple) { |
- DecimalFormat fmt = newDecimalFormat(tuple); |
- ParsePosition ppos = new ParsePosition(0); |
- Number actual = fmt.parse(tuple.parse, ppos); |
- if (ppos.getIndex() == 0) { |
- if (!tuple.output.equals("fail")) { |
- return "Parse error expected."; |
- } |
- return null; |
- } |
- if (tuple.output.equals("fail")) { |
- return "Parse succeeded: "+actual+", but was expected to fail."; |
- } |
- Number expected = toNumber(tuple.output); |
- // number types cannot be compared, this is the best we can do. |
- if (expected.doubleValue() != (actual.doubleValue())) { |
- return "Expected: " + expected + ", got: " + actual; |
- } |
- return null; |
- } |
- |
- @Override |
- public String parseCurrency(NumberFormatTestData tuple) { |
- DecimalFormat fmt = newDecimalFormat(tuple); |
- ParsePosition ppos = new ParsePosition(0); |
- CurrencyAmount currAmt = fmt.parseCurrency(tuple.parse, ppos); |
- if (ppos.getIndex() == 0) { |
- if (!tuple.output.equals("fail")) { |
- return "Parse error expected."; |
- } |
- return null; |
- } |
- if (tuple.output.equals("fail")) { |
- return "Parse succeeded: "+currAmt+", but was expected to fail."; |
- } |
- Number expected = toNumber(tuple.output); |
- Number actual = currAmt.getNumber(); |
- // number types cannot be compared, this is the best we can do. |
- if (expected.doubleValue() != (actual.doubleValue())) { |
- return "Expected: " + expected + ", got: " + actual; |
- } |
- |
- if (!tuple.outputCurrency.equals(currAmt.getCurrency().toString())) { |
- return "Expected currency: " + tuple.outputCurrency + ", got: " + currAmt.getCurrency(); |
- } |
- return null; |
- } |
- |
- /** |
- * @param tuple |
- * @return |
- */ |
- private DecimalFormat newDecimalFormat(NumberFormatTestData tuple) { |
- |
- DecimalFormat fmt = new DecimalFormat( |
- tuple.pattern == null ? "0" : tuple.pattern, |
- new DecimalFormatSymbols(tuple.locale == null ? EN : tuple.locale)); |
- adjustDecimalFormat(tuple, fmt); |
- return fmt; |
- } |
- /** |
- * @param tuple |
- * @param fmt |
- */ |
- private void adjustDecimalFormat(NumberFormatTestData tuple, DecimalFormat fmt) { |
- if (tuple.minIntegerDigits != null) { |
- fmt.setMinimumIntegerDigits(tuple.minIntegerDigits); |
- } |
- if (tuple.maxIntegerDigits != null) { |
- fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits); |
- } |
- if (tuple.minFractionDigits != null) { |
- fmt.setMinimumFractionDigits(tuple.minFractionDigits); |
- } |
- if (tuple.maxFractionDigits != null) { |
- fmt.setMaximumFractionDigits(tuple.maxFractionDigits); |
- } |
- if (tuple.currency != null) { |
- fmt.setCurrency(tuple.currency); |
- } |
- if (tuple.minGroupingDigits != null) { |
- // Oops we don't support this. |
- } |
- if (tuple.useSigDigits != null) { |
- fmt.setSignificantDigitsUsed( |
- tuple.useSigDigits != 0); |
- } |
- if (tuple.minSigDigits != null) { |
- fmt.setMinimumSignificantDigits(tuple.minSigDigits); |
- } |
- if (tuple.maxSigDigits != null) { |
- fmt.setMaximumSignificantDigits(tuple.maxSigDigits); |
- } |
- if (tuple.useGrouping != null) { |
- fmt.setGroupingUsed(tuple.useGrouping != 0); |
- } |
- if (tuple.multiplier != null) { |
- fmt.setMultiplier(tuple.multiplier); |
- } |
- if (tuple.roundingIncrement != null) { |
- fmt.setRoundingIncrement(tuple.roundingIncrement.doubleValue()); |
- } |
- if (tuple.formatWidth != null) { |
- fmt.setFormatWidth(tuple.formatWidth); |
- } |
- if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) { |
- fmt.setPadCharacter(tuple.padCharacter.charAt(0)); |
- } |
- if (tuple.useScientific != null) { |
- fmt.setScientificNotation(tuple.useScientific != 0); |
- } |
- if (tuple.grouping != null) { |
- fmt.setGroupingSize(tuple.grouping); |
- } |
- if (tuple.grouping2 != null) { |
- fmt.setSecondaryGroupingSize(tuple.grouping2); |
- } |
- if (tuple.roundingMode != null) { |
- fmt.setRoundingMode(tuple.roundingMode); |
- } |
- if (tuple.currencyUsage != null) { |
- fmt.setCurrencyUsage(tuple.currencyUsage); |
- } if (tuple.minimumExponentDigits != null) { |
- fmt.setMinimumExponentDigits( |
- tuple.minimumExponentDigits.byteValue()); |
- } |
- if (tuple.exponentSignAlwaysShown != null) { |
- fmt.setExponentSignAlwaysShown( |
- tuple.exponentSignAlwaysShown != 0); |
- } |
- if (tuple.decimalSeparatorAlwaysShown != null) { |
- fmt.setDecimalSeparatorAlwaysShown( |
- tuple.decimalSeparatorAlwaysShown != 0); |
- } |
- if (tuple.padPosition != null) { |
- fmt.setPadPosition(tuple.padPosition); |
- } |
- if (tuple.positivePrefix != null) { |
- fmt.setPositivePrefix(tuple.positivePrefix); |
- } |
- if (tuple.positiveSuffix != null) { |
- fmt.setPositiveSuffix(tuple.positiveSuffix); |
- } |
- if (tuple.negativePrefix != null) { |
- fmt.setNegativePrefix(tuple.negativePrefix); |
- } |
- if (tuple.negativeSuffix != null) { |
- fmt.setNegativeSuffix(tuple.negativeSuffix); |
- } |
- if (tuple.localizedPattern != null) { |
- fmt.applyLocalizedPattern(tuple.localizedPattern); |
- } |
- int lenient = tuple.lenient == null ? 1 : tuple.lenient.intValue(); |
- fmt.setParseStrict(lenient == 0); |
- if (tuple.parseIntegerOnly != null) { |
- fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0); |
- } |
- if (tuple.decimalPatternMatchRequired != null) { |
- fmt.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0); |
- } |
- if (tuple.parseNoExponent != null) { |
- // Oops, not supported for now |
- } |
- } |
- }; |
- |
- |
- private DataDrivenNumberFormatTestUtility.CodeUnderTest JDK = |
- new DataDrivenNumberFormatTestUtility.CodeUnderTest() { |
- @Override |
- public Character Id() { return 'K'; } |
- |
- @Override |
- public String format(NumberFormatTestData tuple) { |
- java.text.DecimalFormat fmt = newDecimalFormat(tuple); |
- String actual = fmt.format(toNumber(tuple.format)); |
- String expected = tuple.output; |
- if (!expected.equals(actual)) { |
- return "Expected " + expected + ", got " + actual; |
- } |
- return null; |
- } |
- |
- @Override |
- public String toPattern(NumberFormatTestData tuple) { |
- java.text.DecimalFormat fmt = newDecimalFormat(tuple); |
- StringBuilder result = new StringBuilder(); |
- if (tuple.toPattern != null) { |
- String expected = tuple.toPattern; |
- String actual = fmt.toPattern(); |
- if (!expected.equals(actual)) { |
- result.append("Expected toPattern=" + expected + ", got " + actual); |
- } |
- } |
- if (tuple.toLocalizedPattern != null) { |
- String expected = tuple.toLocalizedPattern; |
- String actual = fmt.toLocalizedPattern(); |
- if (!expected.equals(actual)) { |
- result.append("Expected toLocalizedPattern=" + expected + ", got " + actual); |
- } |
- } |
- return result.length() == 0 ? null : result.toString(); |
- } |
- |
- @Override |
- public String parse(NumberFormatTestData tuple) { |
- java.text.DecimalFormat fmt = newDecimalFormat(tuple); |
- ParsePosition ppos = new ParsePosition(0); |
- Number actual = fmt.parse(tuple.parse, ppos); |
- if (ppos.getIndex() == 0) { |
- if (!tuple.output.equals("fail")) { |
- return "Parse error expected."; |
- } |
- return null; |
- } |
- if (tuple.output.equals("fail")) { |
- return "Parse succeeded: "+actual+", but was expected to fail."; |
- } |
- Number expected = toNumber(tuple.output); |
- // number types cannot be compared, this is the best we can do. |
- if (expected.doubleValue() != actual.doubleValue()) { |
- return "Expected: " + expected + ", got: " + actual; |
- } |
- return null; |
- } |
- |
- |
- |
- /** |
- * @param tuple |
- * @return |
- */ |
- private java.text.DecimalFormat newDecimalFormat(NumberFormatTestData tuple) { |
- java.text.DecimalFormat fmt = new java.text.DecimalFormat( |
- tuple.pattern == null ? "0" : tuple.pattern, |
- new java.text.DecimalFormatSymbols( |
- (tuple.locale == null ? EN : tuple.locale).toLocale())); |
- adjustDecimalFormat(tuple, fmt); |
- return fmt; |
- } |
- |
- /** |
- * @param tuple |
- * @param fmt |
- */ |
- private void adjustDecimalFormat(NumberFormatTestData tuple, java.text.DecimalFormat fmt) { |
- if (tuple.minIntegerDigits != null) { |
- fmt.setMinimumIntegerDigits(tuple.minIntegerDigits); |
- } |
- if (tuple.maxIntegerDigits != null) { |
- fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits); |
- } |
- if (tuple.minFractionDigits != null) { |
- fmt.setMinimumFractionDigits(tuple.minFractionDigits); |
- } |
- if (tuple.maxFractionDigits != null) { |
- fmt.setMaximumFractionDigits(tuple.maxFractionDigits); |
- } |
- if (tuple.currency != null) { |
- fmt.setCurrency(java.util.Currency.getInstance(tuple.currency.toString())); |
- } |
- if (tuple.minGroupingDigits != null) { |
- // Oops we don't support this. |
- } |
- if (tuple.useSigDigits != null) { |
- // Oops we don't support this |
- } |
- if (tuple.minSigDigits != null) { |
- // Oops we don't support this |
- } |
- if (tuple.maxSigDigits != null) { |
- // Oops we don't support this |
- } |
- if (tuple.useGrouping != null) { |
- fmt.setGroupingUsed(tuple.useGrouping != 0); |
- } |
- if (tuple.multiplier != null) { |
- fmt.setMultiplier(tuple.multiplier); |
- } |
- if (tuple.roundingIncrement != null) { |
- // Not supported |
- } |
- if (tuple.formatWidth != null) { |
- // Not supported |
- } |
- if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) { |
- // Not supported |
- } |
- if (tuple.useScientific != null) { |
- // Not supported |
- } |
- if (tuple.grouping != null) { |
- fmt.setGroupingSize(tuple.grouping); |
- } |
- if (tuple.grouping2 != null) { |
- // Not supported |
- } |
- if (tuple.roundingMode != null) { |
- // Not supported |
- } |
- if (tuple.currencyUsage != null) { |
- // Not supported |
- } |
- if (tuple.minimumExponentDigits != null) { |
- // Not supported |
- } |
- if (tuple.exponentSignAlwaysShown != null) { |
- // Not supported |
- } |
- if (tuple.decimalSeparatorAlwaysShown != null) { |
- fmt.setDecimalSeparatorAlwaysShown( |
- tuple.decimalSeparatorAlwaysShown != 0); |
- } |
- if (tuple.padPosition != null) { |
- // Not supported |
- } |
- if (tuple.positivePrefix != null) { |
- fmt.setPositivePrefix(tuple.positivePrefix); |
- } |
- if (tuple.positiveSuffix != null) { |
- fmt.setPositiveSuffix(tuple.positiveSuffix); |
- } |
- if (tuple.negativePrefix != null) { |
- fmt.setNegativePrefix(tuple.negativePrefix); |
- } |
- if (tuple.negativeSuffix != null) { |
- fmt.setNegativeSuffix(tuple.negativeSuffix); |
- } |
- if (tuple.localizedPattern != null) { |
- fmt.applyLocalizedPattern(tuple.localizedPattern); |
- } |
- |
- // lenient parsing not supported by JDK |
- if (tuple.parseIntegerOnly != null) { |
- fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0); |
- } |
- if (tuple.decimalPatternMatchRequired != null) { |
- // Oops, not supported |
- } |
- if (tuple.parseNoExponent != null) { |
- // Oops, not supported for now |
- } |
- } |
- }; |
- |
@Test |
public void TestRoundingScientific10542() { |
DecimalFormat format = |
@@ -610,7 +220,7 @@ |
DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US); |
final String pat[] = { "#.#", "#.", ".#", "#" }; |
int pat_length = pat.length; |
- final String newpat[] = { "#0.#", "#0.", "#.0", "#" }; |
+ final String newpat[] = { "0.#", "0.", "#.0", "0" }; |
final String num[] = { "0", "0.", ".0", "0" }; |
for (int i=0; i<pat_length; ++i) |
{ |
@@ -812,12 +422,14 @@ |
{"$124", "4", "-1"}, |
{"$124 $124", "4", "-1"}, |
{"$124 ", "4", "-1"}, |
+ {"$124 ", "4", "-1"}, |
{"$ 124 ", "5", "-1"}, |
{"$\u00A0124 ", "5", "-1"}, |
- {" $ 124 ", "0", "0"}, // TODO: need to handle space correctly |
- {"124$", "0", "3"}, // TODO: need to handle space correctly |
- // {"124 $", "5", "-1"}, TODO: OK or NOT? |
- {"124 $", "0", "3"}, |
+ {" $ 124 ", "6", "-1"}, |
+ {"124$", "3", "-1"}, |
+ {"124 $", "3", "-1"}, |
+ {"$124\u200D", "4", "-1"}, |
+ {"$\u200D124", "5", "-1"}, |
}; |
NumberFormat foo = NumberFormat.getCurrencyInstance(); |
for (int i = 0; i < DATA.length; ++i) { |
@@ -841,6 +453,34 @@ |
} |
} |
+ @Test |
+ public void TestSpaceParsingStrict() { |
+ // All trailing grouping separators should be ignored in strict mode, not just the first. |
+ Object[][] cases = { |
+ {"123 ", 3, -1}, |
+ {"123 ", 3, -1}, |
+ {"123 ,", 3, -1}, |
+ {"123,", 3, -1}, |
+ {"123, ", 3, -1}, |
+ {"123,,", 3, -1}, |
+ {"123,, ", 3, -1}, |
+ {"123 ,", 3, -1}, |
+ {"123, ", 3, -1}, |
+ {"123, 456", 3, -1}, |
+ {"123 456", 0, 8} // TODO: Does this behavior make sense? |
+ }; |
+ DecimalFormat df = new DecimalFormat("#,###"); |
+ df.setParseStrict(true); |
+ for (Object[] cas : cases) { |
+ String input = (String) cas[0]; |
+ int expectedIndex = (Integer) cas[1]; |
+ int expectedErrorIndex = (Integer) cas[2]; |
+ ParsePosition ppos = new ParsePosition(0); |
+ df.parse(input, ppos); |
+ assertEquals("Failed on index: '" + input + "'", expectedIndex, ppos.getIndex()); |
+ assertEquals("Failed on error: '" + input + "'", expectedErrorIndex, ppos.getErrorIndex()); |
+ } |
+ } |
@Test |
public void TestMultiCurrencySign() { |
@@ -893,7 +533,7 @@ |
} |
try { |
// mix style parsing |
- for (int k=3; k<=5; ++k) { |
+ for (int k=3; k<=4; ++k) { |
// DATA[i][3] is the currency format result using a |
// single currency sign. |
// DATA[i][4] is the currency format result using |
@@ -900,6 +540,7 @@ |
// double currency sign. |
// DATA[i][5] is the currency format result using |
// triple currency sign. |
+ // ICU 59: long name parsing requires currency mode. |
String oneCurrencyFormat = DATA[i][k]; |
if (fmt.parse(oneCurrencyFormat).doubleValue() != |
numberToBeFormat.doubleValue()) { |
@@ -1093,25 +734,20 @@ |
if (!strBuf.equals(formatResult)) { |
errln("FAIL: localeID: " + localeString + ", expected(" + formatResult.length() + "): \"" + formatResult + "\", actual(" + strBuf.length() + "): \"" + strBuf + "\""); |
} |
- try { |
- // test parsing, and test parsing for all currency formats. |
- for (int j = 3; j < 6; ++j) { |
- // DATA[i][3] is the currency format result using |
- // CURRENCYSTYLE formatter. |
- // DATA[i][4] is the currency format result using |
- // ISOCURRENCYSTYLE formatter. |
- // DATA[i][5] is the currency format result using |
- // PLURALCURRENCYSTYLE formatter. |
- String oneCurrencyFormatResult = DATA[i][j]; |
- Number val = numFmt.parse(oneCurrencyFormatResult); |
- if (val.doubleValue() != numberToBeFormat.doubleValue()) { |
- errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat); |
- } |
+ // test parsing, and test parsing for all currency formats. |
+ for (int j = 3; j < 6; ++j) { |
+ // DATA[i][3] is the currency format result using |
+ // CURRENCYSTYLE formatter. |
+ // DATA[i][4] is the currency format result using |
+ // ISOCURRENCYSTYLE formatter. |
+ // DATA[i][5] is the currency format result using |
+ // PLURALCURRENCYSTYLE formatter. |
+ String oneCurrencyFormatResult = DATA[i][j]; |
+ CurrencyAmount val = numFmt.parseCurrency(oneCurrencyFormatResult, null); |
+ if (val.getNumber().doubleValue() != numberToBeFormat.doubleValue()) { |
+ errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat); |
} |
} |
- catch (ParseException e) { |
- errln("FAIL: " + e.getMessage()); |
- } |
} |
} |
} |
@@ -1121,11 +757,12 @@ |
public void TestMiscCurrencyParsing() { |
String[][] DATA = { |
// each has: string to be parsed, parsed position, error position |
- {"1.00 ", "0", "4"}, |
- {"1.00 UAE dirha", "0", "4"}, |
- {"1.00 us dollar", "14", "-1"}, |
- {"1.00 US DOLLAR", "14", "-1"}, |
- {"1.00 usd", "0", "4"}, |
+ {"1.00 ", "4", "-1", "0", "5"}, |
+ {"1.00 UAE dirha", "4", "-1", "0", "14"}, |
+ {"1.00 us dollar", "4", "-1", "14", "-1"}, |
+ {"1.00 US DOLLAR", "4", "-1", "14", "-1"}, |
+ {"1.00 usd", "4", "-1", "8", "-1"}, |
+ {"1.00 USD", "4", "-1", "8", "-1"}, |
}; |
ULocale locale = new ULocale("en_US"); |
for (int i=0; i<DATA.length; ++i) { |
@@ -1132,18 +769,31 @@ |
String stringToBeParsed = DATA[i][0]; |
int parsedPosition = Integer.parseInt(DATA[i][1]); |
int errorIndex = Integer.parseInt(DATA[i][2]); |
+ int currParsedPosition = Integer.parseInt(DATA[i][3]); |
+ int currErrorIndex = Integer.parseInt(DATA[i][4]); |
NumberFormat numFmt = NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE); |
ParsePosition parsePosition = new ParsePosition(0); |
Number val = numFmt.parse(stringToBeParsed, parsePosition); |
if (parsePosition.getIndex() != parsedPosition || |
parsePosition.getErrorIndex() != errorIndex) { |
- errln("FAIL: parse failed. expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex()); |
- errln("FAIL: parse failed. expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex()); |
+ errln("FAIL: parse failed on case "+i+". expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex()); |
+ errln("FAIL: parse failed on case "+i+". expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex()); |
} |
if (parsePosition.getErrorIndex() == -1 && |
val.doubleValue() != 1.00) { |
errln("FAIL: parse failed. expected 1.00, actual:" + val); |
} |
+ parsePosition = new ParsePosition(0); |
+ CurrencyAmount amt = numFmt.parseCurrency(stringToBeParsed, parsePosition); |
+ if (parsePosition.getIndex() != currParsedPosition || |
+ parsePosition.getErrorIndex() != currErrorIndex) { |
+ errln("FAIL: parseCurrency failed on case "+i+". expected error position: " + currErrorIndex + "; actual: " + parsePosition.getErrorIndex()); |
+ errln("FAIL: parseCurrency failed on case "+i+". expected position: " + currParsedPosition +"; actual: " + parsePosition.getIndex()); |
+ } |
+ if (parsePosition.getErrorIndex() == -1 && |
+ amt.getNumber().doubleValue() != 1.00) { |
+ errln("FAIL: parseCurrency failed. expected 1.00, actual:" + val); |
+ } |
} |
} |
@@ -1178,26 +828,28 @@ |
public int getCurExpectVal() { return curExpectVal; } |
public String getCurExpectCurr() { return curExpectCurr; } |
} |
+ // Note: In cases where the number occurs before the currency sign, non-currency mode will parse the number |
+ // and stop when it reaches the currency symbol. |
final ParseCurrencyItem[] parseCurrencyItems = { |
new ParseCurrencyItem( "en_US", "dollars2", "$2.00", 5, 2, 5, 2, "USD" ), |
new ParseCurrencyItem( "en_US", "dollars4", "$4", 2, 4, 2, 4, "USD" ), |
- new ParseCurrencyItem( "en_US", "dollars9", "9\u00A0$", 0, 0, 0, 0, "" ), |
+ new ParseCurrencyItem( "en_US", "dollars9", "9\u00A0$", 1, 9, 3, 9, "USD" ), |
new ParseCurrencyItem( "en_US", "pounds3", "\u00A33.00", 0, 0, 5, 3, "GBP" ), |
new ParseCurrencyItem( "en_US", "pounds5", "\u00A35", 0, 0, 2, 5, "GBP" ), |
- new ParseCurrencyItem( "en_US", "pounds7", "7\u00A0\u00A3", 0, 0, 0, 0, "" ), |
+ new ParseCurrencyItem( "en_US", "pounds7", "7\u00A0\u00A3", 1, 7, 3, 7, "GBP" ), |
new ParseCurrencyItem( "en_US", "euros8", "\u20AC8", 0, 0, 2, 8, "EUR" ), |
new ParseCurrencyItem( "en_GB", "pounds3", "\u00A33.00", 5, 3, 5, 3, "GBP" ), |
new ParseCurrencyItem( "en_GB", "pounds5", "\u00A35", 2, 5, 2, 5, "GBP" ), |
- new ParseCurrencyItem( "en_GB", "pounds7", "7\u00A0\u00A3", 0, 0, 0, 0, "" ), |
- new ParseCurrencyItem( "en_GB", "euros4", "4,00\u00A0\u20AC", 0, 0, 0, 0, "" ), |
- new ParseCurrencyItem( "en_GB", "euros6", "6\u00A0\u20AC", 0, 0, 0, 0, "" ), |
+ new ParseCurrencyItem( "en_GB", "pounds7", "7\u00A0\u00A3", 1, 7, 3, 7, "GBP" ), |
+ new ParseCurrencyItem( "en_GB", "euros4", "4,00\u00A0\u20AC", 4,400, 6,400, "EUR" ), |
+ new ParseCurrencyItem( "en_GB", "euros6", "6\u00A0\u20AC", 1, 6, 3, 6, "EUR" ), |
new ParseCurrencyItem( "en_GB", "euros8", "\u20AC8", 0, 0, 2, 8, "EUR" ), |
new ParseCurrencyItem( "en_GB", "dollars4", "US$4", 0, 0, 4, 4, "USD" ), |
new ParseCurrencyItem( "fr_FR", "euros4", "4,00\u00A0\u20AC", 6, 4, 6, 4, "EUR" ), |
new ParseCurrencyItem( "fr_FR", "euros6", "6\u00A0\u20AC", 3, 6, 3, 6, "EUR" ), |
- new ParseCurrencyItem( "fr_FR", "euros8", "\u20AC8", 0, 0, 0, 0, "" ), |
+ new ParseCurrencyItem( "fr_FR", "euros8", "\u20AC8", 0, 0, 2, 8, "EUR" ), |
new ParseCurrencyItem( "fr_FR", "dollars2", "$2.00", 0, 0, 0, 0, "" ), |
new ParseCurrencyItem( "fr_FR", "dollars4", "$4", 0, 0, 0, 0, "" ), |
}; |
@@ -1245,6 +897,14 @@ |
} |
@Test |
+ public void TestParseCurrencyWithWhitespace() { |
+ DecimalFormat df = new DecimalFormat("#,##0.00 ¤¤"); |
+ ParsePosition ppos = new ParsePosition(0); |
+ df.parseCurrency("1.00 us denmark", ppos); |
+ assertEquals("Expected to fail on 'us denmark' string", 9, ppos.getErrorIndex()); |
+ } |
+ |
+ @Test |
public void TestParseCurrPatternWithDecStyle() { |
String currpat = "¤#,##0.00"; |
String parsetxt = "x0y$"; |
@@ -1382,12 +1042,12 @@ |
DecimalFormat f = new DecimalFormat("#,##,###", US); |
expect(f, 123456789L, "12,34,56,789"); |
- expectPat(f, "#,##,###"); |
+ expectPat(f, "#,##,##0"); |
f.applyPattern("#,###"); |
f.setSecondaryGroupingSize(4); |
expect(f, 123456789L, "12,3456,789"); |
- expectPat(f, "#,####,###"); |
+ expectPat(f, "#,####,##0"); |
NumberFormat g = NumberFormat.getInstance(new Locale("hi", "IN")); |
String out = ""; |
@@ -1482,6 +1142,7 @@ |
errln("FAIL Pattern rt \"" + pat + "\" . \"" + pat2 + "\""); |
} |
// Make sure digit counts match what we expect |
+ if (i == 0) continue; // outputs to 1,1,0,0 since at least one min digit is required. |
if (df.getMinimumIntegerDigits() != DIGITS[4 * i] |
|| df.getMaximumIntegerDigits() != DIGITS[4 * i + 1] |
|| df.getMinimumFractionDigits() != DIGITS[4 * i + 2] |
@@ -1669,6 +1330,9 @@ |
UnicodeString pattern(patternChars); |
expectPad(fmt, pattern , DecimalFormat.kPadBeforePrefix, 4, padString); |
*/ |
+ |
+ // Test multi-char padding sequence specified via pattern |
+ expect2(new DecimalFormat("*'😃'####.00", US), 1.1, "😃😃😃1.10"); |
} |
/** |
@@ -1723,9 +1387,12 @@ |
// 12 3456789012345 |
expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case |
+ // The new implementation produces "AA*^#####,##0.00ZZ", which is functionally equivalent |
+ // to what the old implementation produced, "AA*^#,###,##0.00ZZ" |
fmt.setFormatWidth(16); |
// 12 34567890123456 |
- expectPat(fmt, "AA*^#,###,##0.00ZZ"); |
+ //expectPat(fmt, "AA*^#,###,##0.00ZZ"); |
+ expectPat(fmt, "AA*^#####,##0.00ZZ"); |
} |
@Test |
@@ -1872,7 +1539,8 @@ |
errln("FAIL: isScientificNotation = true, expect false"); |
} |
- df.applyPattern("0.00000"); |
+ // Create a new instance to flush out currency info |
+ df = new DecimalFormat("0.00000", US); |
df.setScientificNotation(true); |
if (!df.isScientificNotation()) { |
errln("FAIL: isScientificNotation = false, expect true"); |
@@ -1925,6 +1593,23 @@ |
} |
@Test |
+ public void TestParseNull() throws ParseException { |
+ DecimalFormat df = new DecimalFormat(); |
+ try { |
+ df.parse(null); |
+ fail("df.parse(null) didn't throw an exception"); |
+ } catch (IllegalArgumentException e){} |
+ try { |
+ df.parse(null, null); |
+ fail("df.parse(null) didn't throw an exception"); |
+ } catch (IllegalArgumentException e){} |
+ try { |
+ df.parseCurrency(null, null); |
+ fail("df.parse(null) didn't throw an exception"); |
+ } catch (IllegalArgumentException e){} |
+ } |
+ |
+ @Test |
public void TestWhiteSpaceParsing() { |
DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US); |
DecimalFormat fmt = new DecimalFormat("a b#0c ", US); |
@@ -1931,6 +1616,13 @@ |
int n = 1234; |
expect(fmt, "a b1234c ", n); |
expect(fmt, "a b1234c ", n); |
+ expect(fmt, "ab1234", n); |
+ |
+ fmt.applyPattern("a b #"); |
+ expect(fmt, "ab1234", n); |
+ expect(fmt, "ab 1234", n); |
+ expect(fmt, "a b1234", n); |
+ expect(fmt, "a b1234", n); |
} |
/** |
@@ -2734,13 +2426,13 @@ |
// Support methods |
//------------------------------------------------------------------ |
- // Format-Parse test |
+ /** Format-Parse test */ |
public void expect2(NumberFormat fmt, Number n, String exp) { |
// Don't round-trip format test, since we explicitly do it |
expect(fmt, n, exp, false); |
expect(fmt, exp, n); |
} |
- // Format-Parse test |
+ /** Format-Parse test */ |
public void expect3(NumberFormat fmt, Number n, String exp) { |
// Don't round-trip format test, since we explicitly do it |
expect_rbnf(fmt, n, exp, false); |
@@ -2747,25 +2439,25 @@ |
expect_rbnf(fmt, exp, n); |
} |
- // Format-Parse test (convenience) |
+ /** Format-Parse test (convenience) */ |
public void expect2(NumberFormat fmt, double n, String exp) { |
expect2(fmt, new Double(n), exp); |
} |
- // Format-Parse test (convenience) |
+ /** RBNF Format-Parse test (convenience) */ |
public void expect3(NumberFormat fmt, double n, String exp) { |
expect3(fmt, new Double(n), exp); |
} |
- // Format-Parse test (convenience) |
+ /** Format-Parse test (convenience) */ |
public void expect2(NumberFormat fmt, long n, String exp) { |
expect2(fmt, new Long(n), exp); |
} |
- // Format-Parse test (convenience) |
+ /** RBNF Format-Parse test (convenience) */ |
public void expect3(NumberFormat fmt, long n, String exp) { |
expect3(fmt, new Long(n), exp); |
} |
- // Format test |
+ /** Format test */ |
public void expect(NumberFormat fmt, Number n, String exp, boolean rt) { |
StringBuffer saw = new StringBuffer(); |
FieldPosition pos = new FieldPosition(0); |
@@ -2798,7 +2490,7 @@ |
", FAIL " + n + " x " + pat + " = \"" + saw + "\", expected \"" + exp + "\""); |
} |
} |
- // Format test |
+ /** RBNF format test */ |
public void expect_rbnf(NumberFormat fmt, Number n, String exp, boolean rt) { |
StringBuffer saw = new StringBuffer(); |
FieldPosition pos = new FieldPosition(0); |
@@ -2830,22 +2522,22 @@ |
} |
} |
- // Format test (convenience) |
+ /** Format test (convenience) */ |
public void expect(NumberFormat fmt, Number n, String exp) { |
expect(fmt, n, exp, true); |
} |
- // Format test (convenience) |
+ /** Format test (convenience) */ |
public void expect(NumberFormat fmt, double n, String exp) { |
expect(fmt, new Double(n), exp); |
} |
- // Format test (convenience) |
+ /** Format test (convenience) */ |
public void expect(NumberFormat fmt, long n, String exp) { |
expect(fmt, new Long(n), exp); |
} |
- // Parse test |
+ /** Parse test */ |
public void expect(NumberFormat fmt, String str, Number n) { |
Number num = null; |
try { |
@@ -2867,7 +2559,7 @@ |
} |
} |
- // Parse test |
+ /** RBNF Parse test */ |
public void expect_rbnf(NumberFormat fmt, String str, Number n) { |
Number num = null; |
try { |
@@ -2887,12 +2579,12 @@ |
} |
} |
- // Parse test (convenience) |
+ /** Parse test (convenience) */ |
public void expect(NumberFormat fmt, String str, double n) { |
expect(fmt, str, new Double(n)); |
} |
- // Parse test (convenience) |
+ /** Parse test (convenience) */ |
public void expect(NumberFormat fmt, String str, long n) { |
expect(fmt, str, new Long(n)); |
} |
@@ -2974,6 +2666,14 @@ |
} |
@Test |
+ public void TestScientificWithGrouping() { |
+ DecimalFormat df = new DecimalFormat("#,##0.000E0"); |
+ expect2(df, 123, "123.0E0"); |
+ expect2(df, 1234, "1,234E0"); |
+ expect2(df, 12340, "1.234E4"); |
+ } |
+ |
+ @Test |
public void TestStrictParse() { |
String[] pass = { |
"0", // single zero before end of text is not leading |
@@ -2992,6 +2692,10 @@ |
"00", // leading zero before zero - used to be error - see ticket #7913 |
"012", // leading zero before digit - used to be error - see ticket #7913 |
"0,456", // leading zero before group separator - used to be error - see ticket #7913 |
+ "999,999", // see ticket #6863 |
+ "-99,999", // see ticket #6863 |
+ "-999,999", // see ticket #6863 |
+ "-9,999,999", // see ticket #6863 |
}; |
String[] fail = { |
"1,2", // wrong number of digits after group separator |
@@ -3018,7 +2722,6 @@ |
"00E2", // leading zeroes now allowed in strict mode - see ticket # |
}; |
String[] scientificFail = { |
- "1,234E2", // group separators with exponent fail |
}; |
nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH); |
@@ -3589,17 +3292,17 @@ |
// For valid array, it is displayed as {min value, max value} |
// Tests when "if (minimumIntegerDigits > maximumIntegerDigits)" is true |
int[][] cases = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 2, 0 }, { 2, 1 }, { 10, 0 } }; |
- int[] expectedMax = { 0, 1, 1, 2, 2, 10 }; |
+ int[] expectedMax = { 1, 1, 1, 2, 2, 10 }; |
if (cases.length != expectedMax.length) { |
errln("Can't continue test case method TestSetMinimumIntegerDigits " |
+ "since the test case arrays are unequal."); |
} else { |
for (int i = 0; i < cases.length; i++) { |
+ nf.setMinimumIntegerDigits(cases[i][0]); |
nf.setMaximumIntegerDigits(cases[i][1]); |
- nf.setMinimumIntegerDigits(cases[i][0]); |
if (nf.getMaximumIntegerDigits() != expectedMax[i]) { |
errln("NumberFormat.setMinimumIntegerDigits(int newValue " |
- + "did not return an expected result for parameter " + cases[i][1] + " and " + cases[i][0] |
+ + "did not return an expected result for parameter " + cases[i][0] + " and " + cases[i][1] |
+ " and expected " + expectedMax[i] + " but got " + nf.getMaximumIntegerDigits()); |
} |
} |
@@ -3875,6 +3578,10 @@ |
} |
} |
+ /* |
+ * This feature had to do with a limitation in DigitList.java that no longer exists in the |
+ * new implementation. |
+ * |
@Test |
public void TestParseMaxDigits() { |
DecimalFormat fmt = new DecimalFormat(); |
@@ -3883,7 +3590,7 @@ |
fmt.setParseMaxDigits(-1); |
- /* Default value is 1000 */ |
+ // Default value is 1000 |
if (fmt.getParseMaxDigits() != 1000) { |
errln("Fail valid value checking in setParseMaxDigits."); |
} |
@@ -3902,6 +3609,7 @@ |
} |
} |
+ */ |
private static class FormatCharItrTestThread implements Runnable { |
private final NumberFormat fmt; |
@@ -4393,12 +4101,26 @@ |
} |
@Test |
+ public void TestCurrencyWithMinMaxFractionDigits() { |
+ DecimalFormat df = new DecimalFormat(); |
+ df.applyPattern("¤#,##0.00"); |
+ df.setCurrency(Currency.getInstance("USD")); |
+ assertEquals("Basic currency format fails", "$1.23", df.format(1.234)); |
+ df.setMaximumFractionDigits(4); |
+ assertEquals("Currency with max fraction == 4", "$1.234", df.format(1.234)); |
+ df.setMinimumFractionDigits(4); |
+ assertEquals("Currency with min fraction == 4", "$1.2340", df.format(1.234)); |
+ } |
+ |
+ @Test |
public void TestParseRequiredDecimalPoint() { |
String[] testPattern = { "00.####", "00.0", "00" }; |
String value2Parse = "99"; |
+ String value2ParseWithDecimal = "99.9"; |
double parseValue = 99; |
+ double parseValueWithDecimal = 99.9; |
DecimalFormat parser = new DecimalFormat(); |
double result; |
boolean hasDecimalPoint; |
@@ -4414,6 +4136,13 @@ |
TestFmwk.errln("Parsing " + value2Parse + " should have succeeded with " + testPattern[i] + |
" and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired()); |
} |
+ try { |
+ result = parser.parse(value2ParseWithDecimal).doubleValue(); |
+ assertEquals("wrong parsed value", parseValueWithDecimal, result); |
+ } catch (ParseException e) { |
+ TestFmwk.errln("Parsing " + value2ParseWithDecimal + " should have succeeded with " + testPattern[i] + |
+ " and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired()); |
+ } |
parser.setDecimalPatternMatchRequired(true); |
try { |
@@ -4425,31 +4154,23 @@ |
} catch (ParseException e) { |
// OK, should fail |
} |
+ try { |
+ result = parser.parse(value2ParseWithDecimal).doubleValue(); |
+ if(!hasDecimalPoint){ |
+ TestFmwk.errln("Parsing " + value2ParseWithDecimal + " should NOT have succeeded with " + testPattern[i] + |
+ " and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired()); |
+ } |
+ } catch (ParseException e) { |
+ // OK, should fail |
+ } |
} |
- |
} |
- |
- //TODO(junit): investigate |
@Test |
- public void TestDataDrivenICU() { |
- DataDrivenNumberFormatTestUtility.runSuite( |
- "numberformattestspecification.txt", ICU); |
- } |
- |
- //TODO(junit): investigate |
- @Test |
- public void TestDataDrivenJDK() { |
- DataDrivenNumberFormatTestUtility.runSuite( |
- "numberformattestspecification.txt", JDK); |
- } |
- |
- |
- @Test |
public void TestCurrFmtNegSameAsPositive() { |
DecimalFormatSymbols decfmtsym = DecimalFormatSymbols.getInstance(Locale.US); |
decfmtsym.setMinusSign('\u200B'); // ZERO WIDTH SPACE, in ICU4J cannot set to empty string |
- DecimalFormat decfmt = new DecimalFormat("\u00A4#,##0.00;\u00A4#,##0.00", decfmtsym); |
+ DecimalFormat decfmt = new DecimalFormat("\u00A4#,##0.00;-\u00A4#,##0.00", decfmtsym); |
String currFmtResult = decfmt.format(-100.0); |
if (!currFmtResult.equals("\u200B$100.00")) { |
errln("decfmt.toPattern results wrong, expected \u200B$100.00, got " + currFmtResult); |
@@ -4458,7 +4179,7 @@ |
@Test |
public void TestNumberFormatTestDataToString() { |
- new NumberFormatTestData().toString(); |
+ new DataDrivenNumberFormatTestData().toString(); |
} |
// Testing for Issue 11805. |
@@ -4603,9 +4324,7 @@ |
result.get(i).value); |
} |
} |
- // TODO: restore when #11914 is fixed. |
- // assertTrue("Comparing vector results for " + formattedOutput, |
- // expected.containsAll(result)); |
+ assertTrue("Comparing vector results for " + formattedOutput, expected.containsAll(result)); |
} |
// Testing for Issue 11914, missing FieldPositions for some field types. |
@@ -4905,26 +4624,44 @@ |
public void TestStringSymbols() { |
DecimalFormatSymbols symbols = new DecimalFormatSymbols(ULocale.US); |
+ // Attempt digits with multiple code points. |
String[] customDigits = {"(0)", "(1)", "(2)", "(3)", "(4)", "(5)", "(6)", "(7)", "(8)", "(9)"}; |
symbols.setDigitStrings(customDigits); |
+ DecimalFormat fmt = new DecimalFormat("#,##0.0#", symbols); |
+ expect2(fmt, 1234567.89, "(1),(2)(3)(4),(5)(6)(7).(8)(9)"); |
+ |
+ // Scientific notation should work. |
+ fmt.applyPattern("@@@E0"); |
+ expect2(fmt, 1230000, "(1).(2)(3)E(6)"); |
+ |
+ // Grouping and decimal with multiple code points are not supported during parsing. |
symbols.setDecimalSeparatorString("~~"); |
symbols.setGroupingSeparatorString("^^"); |
+ fmt.setDecimalFormatSymbols(symbols); |
+ fmt.applyPattern("#,##0.0#"); |
+ assertEquals("Custom decimal and grouping separator string with multiple characters", |
+ fmt.format(1234567.89), "(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)"); |
- DecimalFormat fmt = new DecimalFormat("#,##0.0#", symbols); |
- |
- expect2(fmt, 1234567.89, "(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)"); |
+ // Digits starting at U+1D7CE MATHEMATICAL BOLD DIGIT ZERO |
+ // These are all single code points, so parsing will work. |
+ for (int i=0; i<10; i++) customDigits[i] = new String(Character.toChars(0x1D7CE+i)); |
+ symbols.setDigitStrings(customDigits); |
+ symbols.setDecimalSeparatorString("😁"); |
+ symbols.setGroupingSeparatorString("😎"); |
+ fmt.setDecimalFormatSymbols(symbols); |
+ expect2(fmt, 1234.56, "𝟏😎𝟐𝟑𝟒😁𝟓𝟔"); |
} |
@Test |
public void TestArabicCurrencyPatternInfo() { |
ULocale arLocale = new ULocale("ar"); |
- |
+ |
DecimalFormatSymbols symbols = new DecimalFormatSymbols(arLocale); |
String currSpacingPatn = symbols.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_CURRENCY_MATCH, true); |
if (currSpacingPatn==null || currSpacingPatn.length() == 0) { |
errln("locale ar, getPatternForCurrencySpacing returns null or 0-length string"); |
} |
- |
+ |
DecimalFormat currAcctFormat = (DecimalFormat)NumberFormat.getInstance(arLocale, NumberFormat.ACCOUNTINGCURRENCYSTYLE); |
String currAcctPatn = currAcctFormat.toPattern(); |
if (currAcctPatn==null || currAcctPatn.length() == 0) { |
@@ -4931,4 +4668,460 @@ |
errln("locale ar, toPattern for ACCOUNTINGCURRENCYSTYLE returns null or 0-length string"); |
} |
} |
+ |
+ @Test |
+ public void Test10436() { |
+ DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH); |
+ df.setRoundingMode(MathContext.ROUND_CEILING); |
+ df.setMinimumFractionDigits(0); |
+ df.setMaximumFractionDigits(0); |
+ assertEquals("-.99 should round toward infinity", "-0", df.format(-0.99)); |
+ } |
+ |
+ @Test |
+ public void Test10765() { |
+ NumberFormat fmt = NumberFormat.getInstance(new ULocale("en")); |
+ fmt.setMinimumIntegerDigits(10); |
+ FieldPosition pos = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR); |
+ fmt.format(1234, new StringBuffer(), pos); |
+ assertEquals("FieldPosition should report the first occurence", 1, pos.getBeginIndex()); |
+ assertEquals("FieldPosition should report the first occurence", 2, pos.getEndIndex()); |
+ } |
+ |
+ @Test |
+ public void Test10997() { |
+ NumberFormat fmt = NumberFormat.getCurrencyInstance(new ULocale("en-US")); |
+ fmt.setMinimumFractionDigits(4); |
+ fmt.setMaximumFractionDigits(4); |
+ String str1 = fmt.format(new CurrencyAmount(123.45, Currency.getInstance("USD"))); |
+ String str2 = fmt.format(new CurrencyAmount(123.45, Currency.getInstance("EUR"))); |
+ assertEquals("minFrac 4 should be respected in default currency", "$123.4500", str1); |
+ assertEquals("minFrac 4 should be respected in different currency", "€123.4500", str2); |
+ } |
+ |
+ @Test |
+ public void Test11020() { |
+ DecimalFormatSymbols sym = new DecimalFormatSymbols(ULocale.FRANCE); |
+ DecimalFormat fmt = new DecimalFormat("0.05E0", sym); |
+ String result = fmt.format(12301.2).replace('\u00a0', ' '); |
+ assertEquals("Rounding increment should be applied after magnitude scaling", "1,25E4", result); |
+ } |
+ |
+ @Test |
+ public void Test11025() { |
+ String pattern = "¤¤ **####0.00"; |
+ DecimalFormatSymbols sym = new DecimalFormatSymbols(ULocale.FRANCE); |
+ DecimalFormat fmt = new DecimalFormat(pattern, sym); |
+ String result = fmt.format(433.0); |
+ assertEquals("Number should be padded to 11 characters", "EUR *433,00", result); |
+ } |
+ |
+ @Test |
+ public void Test11640() { |
+ DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); |
+ df.applyPattern("¤¤¤ 0"); |
+ String result = df.getPositivePrefix(); |
+ assertEquals("Triple-currency should give long name on getPositivePrefix", "US dollars ", result); |
+ } |
+ |
+ @Test |
+ public void Test11645() { |
+ String pattern = "#,##0.0#"; |
+ DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(); |
+ fmt.applyPattern(pattern); |
+ DecimalFormat fmtCopy; |
+ |
+ final int newMultiplier = 37; |
+ fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertNotEquals("Value before setter", fmtCopy.getMultiplier(), newMultiplier); |
+ fmtCopy.setMultiplier(newMultiplier); |
+ assertEquals("Value after setter", fmtCopy.getMultiplier(), newMultiplier); |
+ fmtCopy.applyPattern(pattern); |
+ assertEquals("Value after applyPattern", fmtCopy.getMultiplier(), newMultiplier); |
+ assertFalse("multiplier", fmt.equals(fmtCopy)); |
+ |
+ final int newRoundingMode = RoundingMode.CEILING.ordinal(); |
+ fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertNotEquals("Value before setter", fmtCopy.getRoundingMode(), newRoundingMode); |
+ fmtCopy.setRoundingMode(newRoundingMode); |
+ assertEquals("Value after setter", fmtCopy.getRoundingMode(), newRoundingMode); |
+ fmtCopy.applyPattern(pattern); |
+ assertEquals("Value after applyPattern", fmtCopy.getRoundingMode(), newRoundingMode); |
+ assertFalse("roundingMode", fmt.equals(fmtCopy)); |
+ |
+ final Currency newCurrency = Currency.getInstance("EAT"); |
+ fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertNotEquals("Value before setter", fmtCopy.getCurrency(), newCurrency); |
+ fmtCopy.setCurrency(newCurrency); |
+ assertEquals("Value after setter", fmtCopy.getCurrency(), newCurrency); |
+ fmtCopy.applyPattern(pattern); |
+ assertEquals("Value after applyPattern", fmtCopy.getCurrency(), newCurrency); |
+ assertFalse("currency", fmt.equals(fmtCopy)); |
+ |
+ final CurrencyUsage newCurrencyUsage = CurrencyUsage.CASH; |
+ fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertNotEquals("Value before setter", fmtCopy.getCurrencyUsage(), newCurrencyUsage); |
+ fmtCopy.setCurrencyUsage(CurrencyUsage.CASH); |
+ assertEquals("Value after setter", fmtCopy.getCurrencyUsage(), newCurrencyUsage); |
+ fmtCopy.applyPattern(pattern); |
+ assertEquals("Value after applyPattern", fmtCopy.getCurrencyUsage(), newCurrencyUsage); |
+ assertFalse("currencyUsage", fmt.equals(fmtCopy)); |
+ } |
+ |
+ @Test |
+ public void Test11646() { |
+ DecimalFormatSymbols symbols = new DecimalFormatSymbols(new ULocale("en_US")); |
+ String pattern = "\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4"; |
+ DecimalFormat fmt = new DecimalFormat(pattern, symbols); |
+ |
+ // Test equality with affixes. set affix methods can't capture special |
+ // characters which is why equality should fail. |
+ { |
+ DecimalFormat fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertEquals("", fmt, fmtCopy); |
+ fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix()); |
+ assertNotEquals("", fmt, fmtCopy); |
+ } |
+ { |
+ DecimalFormat fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertEquals("", fmt, fmtCopy); |
+ fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix()); |
+ assertNotEquals("", fmt, fmtCopy); |
+ } |
+ { |
+ DecimalFormat fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertEquals("", fmt, fmtCopy); |
+ fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix()); |
+ assertNotEquals("", fmt, fmtCopy); |
+ } |
+ { |
+ DecimalFormat fmtCopy = (DecimalFormat) fmt.clone(); |
+ assertEquals("", fmt, fmtCopy); |
+ fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix()); |
+ assertNotEquals("", fmt, fmtCopy); |
+ } |
+ } |
+ |
+ @Test |
+ public void Test11648() { |
+ DecimalFormat df = new DecimalFormat("0.00"); |
+ df.setScientificNotation(true); |
+ String pat = df.toPattern(); |
+ assertEquals("A valid scientific notation pattern should be produced", "0.00E0", pat); |
+ } |
+ |
+ @Test |
+ public void Test11649() { |
+ String pattern = "\u00a4\u00a4\u00a4 0.00"; |
+ DecimalFormat fmt = new DecimalFormat(pattern); |
+ fmt.setCurrency(Currency.getInstance("USD")); |
+ assertEquals("Triple currency sign should format long name", "US dollars 12.34", fmt.format(12.34)); |
+ |
+ String newPattern = fmt.toPattern(); |
+ assertEquals("Should produce a valid pattern", pattern, newPattern); |
+ |
+ DecimalFormat fmt2 = new DecimalFormat(newPattern); |
+ fmt2.setCurrency(Currency.getInstance("USD")); |
+ assertEquals("Triple currency sign pattern should round-trip", "US dollars 12.34", fmt2.format(12.34)); |
+ } |
+ |
+ @Test |
+ public void Test11686() { |
+ DecimalFormat df = new DecimalFormat(); |
+ df.setPositiveSuffix("0K"); |
+ df.setNegativeSuffix("0N"); |
+ expect2(df, 123, "1230K"); |
+ expect2(df, -123, "1230N"); |
+ } |
+ |
+ @Test |
+ public void Test11839() { |
+ DecimalFormatSymbols dfs = new DecimalFormatSymbols(ULocale.ENGLISH); |
+ dfs.setMinusSign('∸'); |
+ dfs.setPlusSign('∔'); // ∔ U+2214 DOT PLUS |
+ DecimalFormat df = new DecimalFormat("0.00+;0.00-", dfs); |
+ String result = df.format(-1.234); |
+ assertEquals("Locale-specific minus sign should be used", "1.23∸", result); |
+ result = df.format(1.234); |
+ assertEquals("Locale-specific plus sign should be used", "1.23∔", result); |
+ } |
+ |
+ @Test |
+ public void Test12753() { |
+ ULocale locale = new ULocale("en-US"); |
+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); |
+ symbols.setDecimalSeparator('*'); |
+ DecimalFormat df = new DecimalFormat("0.00", symbols); |
+ df.setDecimalPatternMatchRequired(true); |
+ try { |
+ df.parse("123"); |
+ fail("Parsing integer succeeded even though setDecimalPatternMatchRequired was set"); |
+ } catch (ParseException e) { |
+ // Parse failed (expected) |
+ } |
+ } |
+ |
+ @Test |
+ public void Test12962() { |
+ String pat = "**0.00"; |
+ DecimalFormat df = new DecimalFormat(pat); |
+ String newPat = df.toPattern(); |
+ assertEquals("Format width changed upon calling applyPattern", pat.length(), newPat.length()); |
+ } |
+ |
+ @Test |
+ public void Test10354() { |
+ DecimalFormatSymbols dfs = new DecimalFormatSymbols(); |
+ dfs.setNaN(""); |
+ DecimalFormat df = new DecimalFormat(); |
+ df.setDecimalFormatSymbols(dfs); |
+ try { |
+ df.formatToCharacterIterator(Double.NaN); |
+ // pass |
+ } catch (IllegalArgumentException e) { |
+ throw new AssertionError(e); |
+ } |
+ } |
+ |
+ @Test |
+ public void Test11913() { |
+ NumberFormat df = DecimalFormat.getInstance(); |
+ String result = df.format(new BigDecimal("1.23456789E400")); |
+ assertEquals("Should format more than 309 digits", "12,345,678", result.substring(0, 10)); |
+ assertEquals("Should format more than 309 digits", 534, result.length()); |
+ } |
+ |
+ @Test |
+ public void Test12045() { |
+ if (logKnownIssue("12045", "XSU is missing from fr")) { return; } |
+ |
+ NumberFormat nf = NumberFormat.getInstance(new ULocale("fr"), NumberFormat.PLURALCURRENCYSTYLE); |
+ ParsePosition ppos = new ParsePosition(0); |
+ try { |
+ CurrencyAmount result = nf.parseCurrency("2,34 XSU", ppos); |
+ assertEquals("Parsing should succeed on XSU", |
+ new CurrencyAmount(2.34, Currency.getInstance("XSU")), result); |
+ // pass |
+ } catch (Exception e) { |
+ throw new AssertionError("Should have been able to parse XSU", e); |
+ } |
+ } |
+ |
+ @Test |
+ public void Test11739() { |
+ NumberFormat nf = NumberFormat.getCurrencyInstance(new ULocale("sr_BA")); |
+ ((DecimalFormat) nf).applyPattern("0.0 ¤¤¤"); |
+ ParsePosition ppos = new ParsePosition(0); |
+ CurrencyAmount result = nf.parseCurrency("1.500 амерички долар", ppos); |
+ assertEquals("Should parse to 1500 USD", new CurrencyAmount(1500, Currency.getInstance("USD")), result); |
+ } |
+ |
+ @Test |
+ public void Test11647() { |
+ DecimalFormat df = new DecimalFormat(); |
+ df.applyPattern("¤¤¤¤#"); |
+ String actual = df.format(123); |
+ assertEquals("Should replace 4 currency signs with U+FFFD", "\uFFFD123", actual); |
+ } |
+ |
+ @Test |
+ public void Test12567() { |
+ DecimalFormat df1 = (DecimalFormat) NumberFormat.getInstance(NumberFormat.PLURALCURRENCYSTYLE); |
+ DecimalFormat df2 = (DecimalFormat) NumberFormat.getInstance(NumberFormat.NUMBERSTYLE); |
+ df2.setCurrency(df1.getCurrency()); |
+ df2.setCurrencyPluralInfo(df1.getCurrencyPluralInfo()); |
+ df1.applyPattern("0.00"); |
+ df2.applyPattern("0.00"); |
+ assertEquals("df1 == df2", df1, df2); |
+ assertEquals("df2 == df1", df2, df1); |
+ df2.setPositivePrefix("abc"); |
+ assertNotEquals("df1 != df2", df1, df2); |
+ assertNotEquals("df2 != df1", df2, df1); |
+ } |
+ |
+ @Test |
+ public void testPercentZero() { |
+ DecimalFormat df = (DecimalFormat) NumberFormat.getPercentInstance(); |
+ String actual = df.format(0); |
+ assertEquals("Should have one zero digit", "0%", actual); |
+ } |
+ |
+ @Test |
+ public void testCurrencyZeroRounding() { |
+ DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(); |
+ df.setMaximumFractionDigits(0); |
+ String actual = df.format(0); |
+ assertEquals("Should have zero fraction digits", "$0", actual); |
+ } |
+ |
+ @Test |
+ public void testCustomCurrencySymbol() { |
+ DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(); |
+ df.setCurrency(Currency.getInstance("USD")); |
+ DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); |
+ symbols.setCurrencySymbol("#"); |
+ df.setDecimalFormatSymbols(symbols); |
+ String actual = df.format(123); |
+ assertEquals("Should use '#' instad of '$'", "#123.00", actual); |
+ } |
+ |
+ @Test |
+ public void TestBasicSerializationRoundTrip() throws IOException, ClassNotFoundException { |
+ DecimalFormat df0 = new DecimalFormat("A-**#####,#00.00b¤"); |
+ |
+ // Write to byte stream |
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
+ ObjectOutputStream oos = new ObjectOutputStream(baos); |
+ oos.writeObject(df0); |
+ oos.flush(); |
+ baos.close(); |
+ byte[] bytes = baos.toByteArray(); |
+ |
+ // Read from byte stream |
+ ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); |
+ Object obj = ois.readObject(); |
+ ois.close(); |
+ DecimalFormat df1 = (DecimalFormat) obj; |
+ |
+ // Test equality |
+ assertEquals("Did not round-trip through serialization", df0, df1); |
+ |
+ // Test basic functionality |
+ String str0 = df0.format(12345.67); |
+ String str1 = df1.format(12345.67); |
+ assertEquals("Serialized formatter does not produce same output", str0, str1); |
+ } |
+ |
+ @Test |
+ public void testGetSetCurrency() { |
+ DecimalFormat df = new DecimalFormat("¤#"); |
+ assertEquals("Currency should start out null", null, df.getCurrency()); |
+ Currency curr = Currency.getInstance("EUR"); |
+ df.setCurrency(curr); |
+ assertEquals("Currency should equal EUR after set", curr, df.getCurrency()); |
+ String result = df.format(123); |
+ assertEquals("Currency should format as expected in EUR", "€123.00", result); |
+ } |
+ |
+ @Test |
+ public void testRoundingModeSetters() { |
+ DecimalFormat df1 = new DecimalFormat(); |
+ DecimalFormat df2 = new DecimalFormat(); |
+ |
+ df1.setRoundingMode(java.math.BigDecimal.ROUND_CEILING); |
+ assertNotEquals("Rounding mode was set to a non-default", df1, df2); |
+ df2.setRoundingMode(com.ibm.icu.math.BigDecimal.ROUND_CEILING); |
+ assertEquals("Rounding mode from icu.math and java.math should be the same", df1, df2); |
+ df2.setRoundingMode(java.math.RoundingMode.CEILING.ordinal()); |
+ assertEquals("Rounding mode ordinal from java.math.RoundingMode should be the same", df1, df2); |
+ } |
+ |
+ @Test |
+ public void testSignificantDigitsMode() { |
+ String[][] allExpected = { |
+ {"12340.0", "12340.0", "12340.0"}, |
+ {"1234.0", "1234.0", "1234.0"}, |
+ {"123.4", "123.4", "123.4"}, |
+ {"12.34", "12.34", "12.34"}, |
+ {"1.234", "1.23", "1.23"}, |
+ {"0.1234", "0.12", "0.123"}, |
+ {"0.01234", "0.01", "0.0123"}, |
+ {"0.001234", "0.00", "0.00123"} |
+ }; |
+ |
+ DecimalFormat df = new DecimalFormat(); |
+ df.setMinimumFractionDigits(1); |
+ df.setMaximumFractionDigits(2); |
+ df.setMinimumSignificantDigits(3); |
+ df.setMaximumSignificantDigits(4); |
+ df.setGroupingUsed(false); |
+ |
+ SignificantDigitsMode[] modes = new SignificantDigitsMode[] { |
+ SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION, |
+ SignificantDigitsMode.RESPECT_MAXIMUM_FRACTION, |
+ SignificantDigitsMode.ENSURE_MINIMUM_SIGNIFICANT |
+ }; |
+ |
+ for (double d = 12340.0, i=0; d > 0.001; d /= 10, i++) { |
+ for (int j=0; j<modes.length; j++) { |
+ SignificantDigitsMode mode = modes[j]; |
+ df.setSignificantDigitsMode(mode); |
+ String expected = allExpected[(int)i][j]; |
+ String actual = df.format(d); |
+ assertEquals("Significant digits mode getter is broken", |
+ mode, df.getSignificantDigitsMode()); |
+ assertEquals("Significant digits output differs for "+i+", "+j, |
+ expected, actual); |
+ } |
+ } |
+ } |
+ |
+ @Test |
+ public void testParseNoExponent() throws ParseException { |
+ DecimalFormat df = new DecimalFormat(); |
+ assertEquals("Parse no exponent has wrong default", false, df.getParseNoExponent()); |
+ Number result1 = df.parse("123E4"); |
+ df.setParseNoExponent(true); |
+ assertEquals("Parse no exponent getter is broken", true, df.getParseNoExponent()); |
+ Number result2 = df.parse("123E4"); |
+ assertEquals("Exponent did not parse before setParseNoExponent", result1, new Long(1230000)); |
+ assertEquals("Exponent parsed after setParseNoExponent", result2, new Long(123)); |
+ } |
+ |
+ @Test |
+ public void testMinimumGroupingDigits() { |
+ String[][] allExpected = { |
+ {"123", "123"}, |
+ {"1,230", "1230"}, |
+ {"12,300", "12,300"}, |
+ {"1,23,000", "1,23,000"} |
+ }; |
+ |
+ DecimalFormat df = new DecimalFormat("#,##,##0"); |
+ assertEquals("Minimum grouping digits has wrong default", 1, df.getMinimumGroupingDigits()); |
+ |
+ for (int l = 123, i=0; l <= 123000; l *= 10, i++) { |
+ df.setMinimumGroupingDigits(1); |
+ assertEquals("Minimum grouping digits getter is broken", 1, df.getMinimumGroupingDigits()); |
+ String actual = df.format(l); |
+ assertEquals("Output is wrong for 1, "+i, allExpected[i][0], actual); |
+ df.setMinimumGroupingDigits(2); |
+ assertEquals("Minimum grouping digits getter is broken", 2, df.getMinimumGroupingDigits()); |
+ actual = df.format(l); |
+ assertEquals("Output is wrong for 2, "+i, allExpected[i][1], actual); |
+ } |
+ } |
+ |
+ @Test |
+ public void testParseCaseSensitive() { |
+ String[] patterns = {"a#b", "A#B"}; |
+ String[] inputs = {"a500b", "A500b", "a500B", "a500e10b", "a500E10b"}; |
+ int[][] expectedParsePositions = { |
+ {5, 5, 5, 8, 8}, // case insensitive, pattern 0 |
+ {5, 0, 4, 4, 8}, // case sensitive, pattern 0 |
+ {5, 5, 5, 8, 8}, // case insensitive, pattern 1 |
+ {0, 4, 0, 0, 0}, // case sensitive, pattern 1 |
+ }; |
+ |
+ for (int p = 0; p < patterns.length; p++) { |
+ String pat = patterns[p]; |
+ DecimalFormat df = new DecimalFormat(pat); |
+ assertEquals("parseCaseSensitive default is wrong", false, df.getParseCaseSensitive()); |
+ for (int i = 0; i < inputs.length; i++) { |
+ String inp = inputs[i]; |
+ df.setParseCaseSensitive(false); |
+ assertEquals("parseCaseSensitive getter is broken", false, df.getParseCaseSensitive()); |
+ ParsePosition actualInsensitive = new ParsePosition(0); |
+ df.parse(inp, actualInsensitive); |
+ assertEquals("Insensitive, pattern "+p+", input "+i, |
+ expectedParsePositions[p*2][i], actualInsensitive.getIndex()); |
+ df.setParseCaseSensitive(true); |
+ assertEquals("parseCaseSensitive getter is broken", true, df.getParseCaseSensitive()); |
+ ParsePosition actualSensitive = new ParsePosition(0); |
+ df.parse(inp, actualSensitive); |
+ assertEquals("Sensitive, pattern "+p+", input "+i, |
+ expectedParsePositions[p*2+1][i], actualSensitive.getIndex()); |
+ } |
+ } |
+ } |
} |