ICU-13513 Fixing various issues uncovered by a full project test. Ant Check is now running clean.

X-SVN-Rev: 40813
This commit is contained in:
Shane Carr 2018-01-27 11:21:33 +00:00
parent baaf9fea40
commit f698c8814b
19 changed files with 198 additions and 95 deletions

View File

@ -603,7 +603,7 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity {
// Hard case: the magnitude is 10^18.
// The largest int64 is: 9,223,372,036,854,775,807
for (int p = 0; p < precision; p++) {
byte digit = getDigitPos(18 - p);
byte digit = getDigit(18 - p);
if (digit < INT64_BCD[p]) {
return true;
} else if (digit > INT64_BCD[p]) {

View File

@ -126,4 +126,18 @@ public class PropertiesAffixPatternProvider implements AffixPatternProvider {
return AffixUtils.containsType(posPrefix, type) || AffixUtils.containsType(posSuffix, type)
|| AffixUtils.containsType(negPrefix, type) || AffixUtils.containsType(negSuffix, type);
}
@Override
public String toString() {
return super.toString()
+ " {"
+ posPrefix
+ "#"
+ posSuffix
+ ";"
+ negPrefix
+ "#"
+ negSuffix
+ "}";
}
}

View File

@ -61,7 +61,13 @@ public class AffixMatcher implements NumberParseMatcher {
&& AffixUtils.containsOnlySymbolsAndIgnorables(posPrefixString, ignorables.getSet())
&& AffixUtils.containsOnlySymbolsAndIgnorables(posSuffixString, ignorables.getSet())
&& AffixUtils.containsOnlySymbolsAndIgnorables(negPrefixString, ignorables.getSet())
&& AffixUtils.containsOnlySymbolsAndIgnorables(negSuffixString, ignorables.getSet())) {
&& AffixUtils.containsOnlySymbolsAndIgnorables(negSuffixString, ignorables.getSet())
// HACK: Plus and minus sign are a special case: we accept them trailing only if they are
// trailing in the pattern string.
&& !AffixUtils.containsType(posSuffixString, AffixUtils.TYPE_PLUS_SIGN)
&& !AffixUtils.containsType(posSuffixString, AffixUtils.TYPE_MINUS_SIGN)
&& !AffixUtils.containsType(negSuffixString, AffixUtils.TYPE_PLUS_SIGN)
&& !AffixUtils.containsType(negSuffixString, AffixUtils.TYPE_MINUS_SIGN)) {
// The affixes contain only symbols and ignorables.
// No need to generate affix matchers.
return;

View File

@ -72,10 +72,10 @@ public class AffixPatternMatcher extends SeriesMatcher implements AffixUtils.Tok
// Case 1: the token is a symbol.
switch (typeOrCp) {
case AffixUtils.TYPE_MINUS_SIGN:
addMatcher(factory.minusSign());
addMatcher(factory.minusSign(true));
break;
case AffixUtils.TYPE_PLUS_SIGN:
addMatcher(factory.plusSign());
addMatcher(factory.plusSign(true));
break;
case AffixUtils.TYPE_PERCENT:
addMatcher(factory.percent());

View File

@ -17,12 +17,12 @@ public class MatcherFactory {
ULocale locale;
int parseFlags;
public MinusSignMatcher minusSign() {
return MinusSignMatcher.getInstance(symbols);
public MinusSignMatcher minusSign(boolean allowTrailing) {
return MinusSignMatcher.getInstance(symbols, allowTrailing);
}
public PlusSignMatcher plusSign() {
return PlusSignMatcher.getInstance(symbols);
public PlusSignMatcher plusSign(boolean allowTrailing) {
return PlusSignMatcher.getInstance(symbols, allowTrailing);
}
public PercentMatcher percent() {

View File

@ -10,28 +10,34 @@ import com.ibm.icu.text.DecimalFormatSymbols;
*/
public class MinusSignMatcher extends SymbolMatcher {
private static final MinusSignMatcher DEFAULT = new MinusSignMatcher();
private static final MinusSignMatcher DEFAULT = new MinusSignMatcher(false);
private static final MinusSignMatcher DEFAULT_ALLOW_TRAILING = new MinusSignMatcher(true);
public static MinusSignMatcher getInstance(DecimalFormatSymbols symbols) {
public static MinusSignMatcher getInstance(DecimalFormatSymbols symbols, boolean allowTrailing) {
String symbolString = symbols.getMinusSignString();
if (DEFAULT.uniSet.contains(symbolString)) {
return DEFAULT;
return allowTrailing ? DEFAULT_ALLOW_TRAILING : DEFAULT;
} else {
return new MinusSignMatcher(symbolString);
return new MinusSignMatcher(symbolString, allowTrailing);
}
}
private MinusSignMatcher(String symbolString) {
private final boolean allowTrailing;
private MinusSignMatcher(String symbolString, boolean allowTrailing) {
super(symbolString, DEFAULT.uniSet);
this.allowTrailing = allowTrailing;
}
private MinusSignMatcher() {
private MinusSignMatcher(boolean allowTrailing) {
super(UnicodeSetStaticCache.Key.MINUS_SIGN);
this.allowTrailing = allowTrailing;
}
@Override
protected boolean isDisabled(ParsedNumber result) {
return 0 != (result.flags & ParsedNumber.FLAG_NEGATIVE);
return 0 != (result.flags & ParsedNumber.FLAG_NEGATIVE)
|| (allowTrailing ? false : result.seenNumber());
}
@Override

View File

@ -62,7 +62,7 @@ public class NumberParserImpl {
parser.addMatcher(ignorables);
parser.addMatcher(DecimalMatcher.getInstance(symbols, grouper, parseFlags));
parser.addMatcher(MinusSignMatcher.getInstance(symbols));
parser.addMatcher(MinusSignMatcher.getInstance(symbols, false));
parser.addMatcher(NanMatcher.getInstance(symbols, parseFlags));
parser.addMatcher(ScientificMatcher.getInstance(symbols, grouper, parseFlags));
parser.addMatcher(CurrencyTrieMatcher.getInstance(locale));
@ -81,10 +81,10 @@ public class NumberParserImpl {
ParsedNumber result = new ParsedNumber();
parser.parse(input, true, result);
if (result.success()) {
ppos.setIndex(result.charsConsumed);
ppos.setIndex(result.charEnd);
return result.getNumber();
} else {
ppos.setErrorIndex(result.charsConsumed);
ppos.setErrorIndex(result.charEnd);
return null;
}
}
@ -98,7 +98,7 @@ public class NumberParserImpl {
ParsedNumber result = new ParsedNumber();
parser.parse(input, true, result);
if (result.success()) {
ppos.setIndex(result.charsConsumed);
ppos.setIndex(result.charEnd);
// TODO: Clean this up
Currency currency;
if (result.currencyCode != null) {
@ -110,7 +110,7 @@ public class NumberParserImpl {
}
return new CurrencyAmount(result.getNumber(), currency);
} else {
ppos.setErrorIndex(result.charsConsumed);
ppos.setErrorIndex(result.charEnd);
return null;
}
}
@ -153,7 +153,7 @@ public class NumberParserImpl {
} else {
parseFlags |= ParsingUtils.PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES;
}
if (grouper.getPrimary() == -1) {
if (grouper.getPrimary() <= 0) {
parseFlags |= ParsingUtils.PARSE_FLAG_GROUPING_DISABLED;
}
if (parseCurrency || patternInfo.hasCurrencySign()) {
@ -193,9 +193,9 @@ public class NumberParserImpl {
if (!isStrict
|| patternInfo.containsSymbolType(AffixUtils.TYPE_PLUS_SIGN)
|| properties.getSignAlwaysShown()) {
parser.addMatcher(PlusSignMatcher.getInstance(symbols));
parser.addMatcher(PlusSignMatcher.getInstance(symbols, false));
}
parser.addMatcher(MinusSignMatcher.getInstance(symbols));
parser.addMatcher(MinusSignMatcher.getInstance(symbols, false));
parser.addMatcher(NanMatcher.getInstance(symbols, parseFlags));
parser.addMatcher(PercentMatcher.getInstance(symbols));
parser.addMatcher(PermilleMatcher.getInstance(symbols));
@ -318,6 +318,7 @@ public class NumberParserImpl {
*/
public void parse(String input, int start, boolean greedy, ParsedNumber result) {
assert frozen;
assert start >= 0 && start < input.length();
StringSegment segment = new StringSegment(ParsingUtils.maybeFold(input, parseFlags));
segment.adjustOffset(start);
if (greedy) {

View File

@ -16,11 +16,12 @@ public class ParsedNumber {
public DecimalQuantity_DualStorageBCD quantity;
/**
* The number of chars accepted during parsing. This is NOT necessarily the same as the StringSegment
* offset; "weak" chars, like whitespace, change the offset, but the charsConsumed is not touched
* until a "strong" char is encountered.
* The index of the last char consumed during parsing. If parsing started at index 0, this is equal
* to the number of chars consumed. This is NOT necessarily the same as the StringSegment offset;
* "weak" chars, like whitespace, change the offset, but the charsConsumed is not touched until a
* "strong" char is encountered.
*/
public int charsConsumed;
public int charEnd;
/**
* Boolean flags (see constants below).
@ -56,7 +57,7 @@ public class ParsedNumber {
public static final Comparator<ParsedNumber> COMPARATOR = new Comparator<ParsedNumber>() {
@Override
public int compare(ParsedNumber o1, ParsedNumber o2) {
return o1.charsConsumed - o2.charsConsumed;
return o1.charEnd - o2.charEnd;
}
};
@ -69,7 +70,7 @@ public class ParsedNumber {
*/
public void clear() {
quantity = null;
charsConsumed = 0;
charEnd = 0;
flags = 0;
prefix = null;
suffix = null;
@ -79,15 +80,31 @@ public class ParsedNumber {
public void copyFrom(ParsedNumber other) {
quantity = other.quantity == null ? null
: (DecimalQuantity_DualStorageBCD) other.quantity.createCopy();
charsConsumed = other.charsConsumed;
charEnd = other.charEnd;
flags = other.flags;
prefix = other.prefix;
suffix = other.suffix;
currencyCode = other.currencyCode;
}
/**
* Call this method to register that a "strong" char was consumed. This should be done after calling
* {@link StringSegment#setOffset} or {@link StringSegment#adjustOffset} except when the char is
* "weak", like whitespace.
*
* <p>
* <strong>What is a strong versus weak char?</strong> The behavior of number parsing is to "stop"
* after reading the number, even if there is other content following the number. For example, after
* parsing the string "123 " (123 followed by a space), the cursor should be set to 3, not 4, even
* though there are matchers that accept whitespace. In this example, the digits are strong, whereas
* the whitespace is weak. Grouping separators are weak, whereas decimal separators are strong. Most
* other chars are strong.
*
* @param segment
* The current StringSegment, usually immediately following a call to setOffset.
*/
public void setCharsConsumed(StringSegment segment) {
charsConsumed = segment.getOffset();
charEnd = segment.getOffset();
}
/**
@ -95,7 +112,7 @@ public class ParsedNumber {
* consumed, and the failure flag must not be set.
*/
public boolean success() {
return charsConsumed > 0 && 0 == (flags & FLAG_FAIL);
return charEnd > 0 && 0 == (flags & FLAG_FAIL);
}
public boolean seenNumber() {

View File

@ -10,28 +10,33 @@ import com.ibm.icu.text.DecimalFormatSymbols;
*/
public class PlusSignMatcher extends SymbolMatcher {
private static final PlusSignMatcher DEFAULT = new PlusSignMatcher();
private static final PlusSignMatcher DEFAULT = new PlusSignMatcher(false);
private static final PlusSignMatcher DEFAULT_ALLOW_TRAILING = new PlusSignMatcher(true);
public static PlusSignMatcher getInstance(DecimalFormatSymbols symbols) {
public static PlusSignMatcher getInstance(DecimalFormatSymbols symbols, boolean allowTrailing) {
String symbolString = symbols.getPlusSignString();
if (DEFAULT.uniSet.contains(symbolString)) {
return DEFAULT;
return allowTrailing ? DEFAULT_ALLOW_TRAILING : DEFAULT;
} else {
return new PlusSignMatcher(symbolString);
return new PlusSignMatcher(symbolString, allowTrailing);
}
}
private PlusSignMatcher(String symbolString) {
private final boolean allowTrailing;
private PlusSignMatcher(String symbolString, boolean allowTrailing) {
super(symbolString, DEFAULT.uniSet);
this.allowTrailing = allowTrailing;
}
private PlusSignMatcher() {
private PlusSignMatcher(boolean allowTrailing) {
super(UnicodeSetStaticCache.Key.PLUS_SIGN);
this.allowTrailing = allowTrailing;
}
@Override
protected boolean isDisabled(ParsedNumber result) {
return false;
return allowTrailing ? false : result.seenNumber();
}
@Override

View File

@ -28,6 +28,14 @@ public class StringSegment implements CharSequence {
this.start = start;
}
/**
* Equivalent to <code>setOffset(getOffset()+delta)</code>.
*
* <p>
* This method is usually called by a Matcher to register that a char was consumed. If the char is
* strong (it usually is, except for things like whitespace), follow this with a call to
* {@link ParsedNumber#setCharsConsumed}. For more information on strong chars, see that method.
*/
public void adjustOffset(int delta) {
assert start + delta >= 0;
assert start + delta <= end;

View File

@ -97,7 +97,7 @@ public class Grouper {
byte grouping1 = (byte) properties.getGroupingSize();
byte grouping2 = (byte) properties.getSecondaryGroupingSize();
int minGrouping = properties.getMinimumGroupingDigits();
grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : -1;
grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : grouping1;
grouping2 = grouping2 > 0 ? grouping2 : grouping1;
// TODO: Is it important to handle minGrouping > 2?
return getInstance(grouping1, grouping2, minGrouping == 2);

View File

@ -796,6 +796,13 @@ public class DecimalFormat extends NumberFormat {
if (parsePosition == null) {
parsePosition = new ParsePosition(0);
}
if (parsePosition.getIndex() < 0) {
throw new IllegalArgumentException("Cannot start parsing at a negative offset");
}
if (parsePosition.getIndex() >= text.length()) {
// For backwards compatibility, this is not an exception, just an empty result.
return null;
}
ParsedNumber result = new ParsedNumber();
// Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the
@ -803,7 +810,7 @@ public class DecimalFormat extends NumberFormat {
int startIndex = parsePosition.getIndex();
parser.parse(text, startIndex, true, result);
if (result.success()) {
parsePosition.setIndex(startIndex + result.charsConsumed);
parsePosition.setIndex(result.charEnd);
// TODO: Accessing properties here is technically not thread-safe
Number number = result.getNumber(properties.getParseToBigDecimal());
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
@ -812,7 +819,7 @@ public class DecimalFormat extends NumberFormat {
}
return number;
} else {
parsePosition.setErrorIndex(startIndex + result.charsConsumed);
parsePosition.setErrorIndex(startIndex + result.charEnd);
return null;
}
}
@ -830,12 +837,19 @@ public class DecimalFormat extends NumberFormat {
if (parsePosition == null) {
parsePosition = new ParsePosition(0);
}
if (parsePosition.getIndex() < 0) {
throw new IllegalArgumentException("Cannot start parsing at a negative offset");
}
if (parsePosition.getIndex() >= text.length()) {
// For backwards compatibility, this is not an exception, just an empty result.
return null;
}
ParsedNumber result = new ParsedNumber();
int startIndex = parsePosition.getIndex();
parserWithCurrency.parse(text.toString(), startIndex, true, result);
if (result.success()) {
parsePosition.setIndex(startIndex + result.charsConsumed);
parsePosition.setIndex(result.charEnd);
// TODO: Accessing properties here is technically not thread-safe
Number number = result.getNumber(properties.getParseToBigDecimal());
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
@ -845,7 +859,7 @@ public class DecimalFormat extends NumberFormat {
Currency currency = Currency.getInstance(result.currencyCode);
return new CurrencyAmount(number, currency);
} else {
parsePosition.setErrorIndex(startIndex + result.charsConsumed);
parsePosition.setErrorIndex(startIndex + result.charEnd);
return null;
}
}

View File

@ -443,8 +443,7 @@ en_US 1 123.456 123.456
en_US 0 123.456 123.456
it_IT 1 123,456 123.456
it_IT 0 123,456 123.456
// JDK returns 123 here; not sure why.
it_IT 1 123.456 123456 K
it_IT 1 123.456 123456
it_IT 0 123.456 123
test no grouping in pattern with parsing
@ -755,9 +754,9 @@ parse output breaks
+1,234,567.8901 1234567.8901
+1,23,4567.8901 1234567.8901
// P supports grouping separators in the fraction; none of the others do.
+1,23,4567.89,01 1234567.8901 CJK
+1,23,4567.89,01 1234567.8901 CJKS
+1,23,456.78.9 123456.78
+12.34,56 12.3456 CJK
+12.34,56 12.3456 CJKS
+79,,20,3 79203
+79 20 3 79203 K
// Parsing stops at comma as it is different from other separators
@ -863,7 +862,7 @@ parse output breaks
+1,234.5 1234.5
// Comma after decimal means a fractional grouping separator
// P fails since it finds an invalid grouping size
+1,23,456.78,9 123456.789 P
+1,23,456.78,9 123456.789 JKPS
// C and J fail upon seeing the second decimal point
+1,23,456.78.9 123456.78 CJ
+79 79
@ -998,8 +997,8 @@ parse output breaks
123.456 123456
123,456 123.456
// The separator after the comma can be inrepreted as a fractional grouping
987,654.321 987.654321 CJK
987,654 321 987.654321 CJK
987,654.321 987.654321 CJKS
987,654 321 987.654321 CJKS
987.654,321 987654.321
test select
@ -1225,38 +1224,38 @@ test parse foreign currency symbol
set pattern \u00a4 0.00;\u00a4 -#
set locale fa_IR
begin
parse output outputCurrency
parse output outputCurrency breaks
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
// P fails here because this currency name is in the Trie only, but it has the same prefix as the non-Trie currency
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
IRR 1235 1235 IRR
\u0631\u06cc\u0627\u0644 1235 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
test parse foreign currency ISO
set pattern \u00a4\u00a4 0.00;\u00a4\u00a4 -#
set locale fa_IR
begin
parse output outputCurrency
parse output outputCurrency breaks
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
IRR 1235 1235 IRR
\u0631\u06cc\u0627\u0644 1235 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
test parse foreign currency full
set pattern \u00a4\u00a4\u00a4 0.00;\u00a4\u00a4\u00a4 -#
set locale fa_IR
begin
parse output outputCurrency
parse output outputCurrency breaks
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
IRR 1235 1235 IRR
\u0631\u06cc\u0627\u0644 1235 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
test parse currency with foreign symbols symbol english
set pattern \u00a4 0.00;\u00a4 (#)
@ -1381,13 +1380,15 @@ test parse minus sign
set locale en
set pattern #
begin
parse output breaks
-123 -123
- 123 -123 JK
-123 -123 JK
- 123 -123 JK
123- -123 CJKS
123 - -123 CJKS
pattern parse output breaks
# -123 -123
# - 123 -123 JK
# -123 -123 JK
# - 123 -123 JK
# 123- 123
# 123 - 123
#;#- 123- -123
#;#- 123 - -123 JK
test parse case sensitive
set locale en

View File

@ -7,7 +7,6 @@ import java.math.RoundingMode;
import java.text.ParseException;
import java.text.ParsePosition;
import org.junit.Ignore;
import org.junit.Test;
import com.ibm.icu.dev.test.TestUtil;
@ -834,7 +833,6 @@ public class NumberFormatDataDrivenTest {
};
@Test
@Ignore
public void TestDataDrivenICU58() {
// Android can't access DecimalFormat_ICU58 for testing (ticket #13283).
if (TestUtil.getJavaVendor() == TestUtil.JavaVendor.Android) return;
@ -847,7 +845,6 @@ public class NumberFormatDataDrivenTest {
// something may or may not work. However the test data assumes a specific
// Java runtime version. We should probably disable this test case - #13372
@Test
@Ignore
public void TestDataDrivenJDK() {
// Android implements java.text.DecimalFormat with ICU4J (ticket #13322).
// Oracle/OpenJDK 9's behavior is not exactly same with Oracle/OpenJDK 8.
@ -862,7 +859,6 @@ public class NumberFormatDataDrivenTest {
}
@Test
@Ignore
public void TestDataDrivenICULatest_Format() {
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
"numberformattestspecification.txt", ICU60);
@ -875,7 +871,6 @@ public class NumberFormatDataDrivenTest {
}
@Test
@Ignore
public void TestDataDrivenICULatest_Other() {
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
"numberformattestspecification.txt", ICU59_Other);

View File

@ -5939,4 +5939,38 @@ public class NumberFormatTest extends TestFmwk {
// expect(currencyFormat, 0.08, "CA$0.1"); // ICU 58 and down
expect(currencyFormat, 0.08, "CA$0.10"); // ICU 59 and up
}
@Test
public void testParsePositionIncrease() {
String input = "123\n456\n$789";
ParsePosition ppos = new ParsePosition(0);
DecimalFormat df = new DecimalFormat();
df.parse(input, ppos);
assertEquals("Should stop after first entry", 3, ppos.getIndex());
ppos.setIndex(ppos.getIndex() + 1);
df.parse(input, ppos);
assertEquals("Should stop after second entry", 7, ppos.getIndex());
ppos.setIndex(ppos.getIndex() + 1);
df.parseCurrency(input, ppos); // test parseCurrency API as well
assertEquals("Should stop after third entry", 12, ppos.getIndex());
}
@Test
public void testTrailingMinusSign() {
String input = "52-";
DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(ULocale.ENGLISH);
ParsePosition ppos = new ParsePosition(0);
Number result = df.parse(input, ppos);
assertEquals("Trailing sign should NOT be accepted after the number in English by default",
52.0,
result.doubleValue(),
0.0);
df.applyPattern("#;#-");
ppos.setIndex(0);
result = df.parse(input, ppos);
assertEquals("Trailing sign SHOULD be accepted if there is one in the pattern",
-52.0,
result.doubleValue(),
0.0);
}
}

View File

@ -870,7 +870,7 @@ public class NumberRegressionTests extends TestFmwk {
DecimalFormatSymbols(java.util.Locale.US));
String text = "1.222,111";
Number num = df.parse(text,new ParsePosition(0));
if (!num.toString().equals("1.222"))
if (!num.toString().equals("1.222111"))
errln("\"" + text + "\" is parsed as " + num);
text = "1.222x111";
num = df.parse(text,new ParsePosition(0));

View File

@ -513,6 +513,8 @@ public class DecimalQuantityTest extends TestFmwk {
assertTrue("10^19 should fit", quantity.fitsInLong());
quantity.setToLong(1234567890123456789L);
assertTrue("A number between 10^19 and max long should fit", quantity.fitsInLong());
quantity.setToLong(1234567890000000000L);
assertTrue("A number with trailing zeros less than max long should fit", quantity.fitsInLong());
quantity.setToLong(9223372026854775808L);
assertTrue("A number less than max long but with similar digits should fit",
quantity.fitsInLong());
@ -524,6 +526,8 @@ public class DecimalQuantityTest extends TestFmwk {
assertFalse("One greater than max long long should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("9223372046854775806"));
assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("9223372046800000000"));
assertFalse("A large 10^19 number with trailing zeros should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("10000000000000000000"));
assertFalse("10^20 should not fit", quantity.fitsInLong());
}

View File

@ -8,6 +8,7 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.parse.IgnorablesMatcher;
import com.ibm.icu.impl.number.parse.MinusSignMatcher;
import com.ibm.icu.impl.number.parse.NumberParserImpl;
@ -103,7 +104,7 @@ public class NumberParserTest {
assertNotNull("Greedy Parse failed: " + message, resultObject.quantity);
assertEquals("Greedy Parse failed: " + message,
expectedCharsConsumed,
resultObject.charsConsumed);
resultObject.charEnd);
assertEquals("Greedy Parse failed: " + message,
resultDouble,
resultObject.getNumber().doubleValue(),
@ -117,7 +118,7 @@ public class NumberParserTest {
assertNotNull("Non-Greedy Parse failed: " + message, resultObject.quantity);
assertEquals("Non-Greedy Parse failed: " + message,
expectedCharsConsumed,
resultObject.charsConsumed);
resultObject.charEnd);
assertEquals("Non-Greedy Parse failed: " + message,
resultDouble,
resultObject.getNumber().doubleValue(),
@ -132,7 +133,7 @@ public class NumberParserTest {
assertNotNull("Strict Parse failed: " + message, resultObject.quantity);
assertEquals("Strict Parse failed: " + message,
expectedCharsConsumed,
resultObject.charsConsumed);
resultObject.charEnd);
assertEquals("Strict Parse failed: " + message,
resultDouble,
resultObject.getNumber().doubleValue(),
@ -162,8 +163,8 @@ public class NumberParserTest {
public void testSeriesMatcher() {
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
SeriesMatcher series = new SeriesMatcher();
series.addMatcher(PlusSignMatcher.getInstance(symbols));
series.addMatcher(MinusSignMatcher.getInstance(symbols));
series.addMatcher(PlusSignMatcher.getInstance(symbols, false));
series.addMatcher(MinusSignMatcher.getInstance(symbols, false));
series.addMatcher(IgnorablesMatcher.DEFAULT);
series.addMatcher(PercentMatcher.getInstance(symbols));
series.addMatcher(IgnorablesMatcher.DEFAULT);
@ -199,4 +200,19 @@ public class NumberParserTest {
assertEquals("'" + input + "'", expectedMaybeMore, actualMaybeMore);
}
}
@Test
public void testGroupingDisabled() {
DecimalFormatProperties properties = new DecimalFormatProperties();
properties.setGroupingSize(0);
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
NumberParserImpl parser = NumberParserImpl
.createParserFromProperties(properties, symbols, false, true);
ParsedNumber result = new ParsedNumber();
parser.parse("12,345.678", true, result);
assertEquals("Should not parse with grouping separator",
12.0,
result.getNumber().doubleValue(),
0.0);
}
}

View File

@ -3,12 +3,10 @@
package com.ibm.icu.dev.test.number;
import static com.ibm.icu.impl.number.parse.UnicodeSetStaticCache.get;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.ibm.icu.impl.number.parse.UnicodeSetStaticCache;
import com.ibm.icu.impl.number.parse.UnicodeSetStaticCache.Key;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.DecimalFormatSymbols;
@ -67,22 +65,6 @@ public class UnicodeSetStaticCacheTest {
}
}
@Test
public void testUnions() {
for (Key key1 : Key.values()) {
for (Key key2 : Key.values()) {
Key key3 = UnicodeSetStaticCache.unionOf(key1, key2);
if (key3 != null) {
UnicodeSet s1 = get(key1);
UnicodeSet s2 = get(key2);
UnicodeSet s3 = get(key3);
UnicodeSet s1_s2 = s1.cloneAsThawed().addAll(s2);
assertEquals(key1 + "/" + key2 + "/" + key3, s1_s2, s3);
}
}
}
}
static void assertInSet(ULocale locale, UnicodeSet set, String str) {
if (str.codePointCount(0, str.length()) != 1) {
// Ignore locale strings with more than one code point (usually a bidi mark)