[LANG-1729] NumberUtils.isParsable() returns true for Fullwidth Unicode

digits

Refactor tests
This commit is contained in:
Gary Gregory 2024-04-24 16:51:21 -04:00
parent fff3db29be
commit bdff802a85
1 changed files with 84 additions and 46 deletions

View File

@ -30,6 +30,7 @@ import java.math.BigInteger;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.text.ParseException; import java.text.ParseException;
import java.util.function.Function;
import org.apache.commons.lang3.AbstractLangTest; import org.apache.commons.lang3.AbstractLangTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -97,68 +98,87 @@ public class NumberUtilsTest extends AbstractLangTest {
assertTrue(NumberUtils.compare((short) 213, (short) 32) > 0); assertTrue(NumberUtils.compare((short) 213, (short) 32) > 0);
} }
private boolean isParsableByte(final String s) { private boolean isApplyNonNull(final String s, final Function<String, ?> function) {
final NumberFormat instance = NumberFormat.getInstance();
instance.setParseIntegerOnly(false);
try { try {
instance.parse(s); assertNotNull(function.apply(s));
return true;
} catch (final Exception e) {
if (!s.matches(".*\\s.*")) {
e.printStackTrace();
}
return false;
}
}
private boolean isNumberFormatParsable(final String s) {
final NumberFormat instance = NumberFormat.getInstance();
try {
// Stops parsing when a space is found, then returns an object.
assertNotNull(instance.parse(s));
return true;
} catch (final ParseException e) { } catch (final ParseException e) {
return false; return false;
} }
}
private boolean isNumberIntegerOnlyFormatParsable(final String s) {
final NumberFormat instance = NumberFormat.getInstance();
instance.setParseIntegerOnly(true);
try { try {
Byte.parseByte(s); // Stops parsing when a space is found, then returns an object.
} catch (final NumberFormatException e) { assertNotNull(instance.parse(s));
return true;
} catch (final ParseException e) {
return false; return false;
} }
return NumberUtils.isParsable(s); }
private boolean isParsableByte(final String s) {
final boolean parsable = NumberUtils.isParsable(s);
assertTrue(isNumberFormatParsable(s), s);
assertTrue(isNumberIntegerOnlyFormatParsable(s), s);
assertEquals(parsable, isApplyNonNull(s, Byte::parseByte), s);
return parsable;
}
private boolean isParsableFloat(final String s) {
final boolean parsable = NumberUtils.isParsable(s);
assertTrue(isNumberFormatParsable(s), s);
assertTrue(isNumberIntegerOnlyFormatParsable(s), s);
assertEquals(parsable, isApplyNonNull(s, Float::parseFloat), s);
return parsable;
}
private boolean isParsableDouble(final String s) {
final boolean parsable = NumberUtils.isParsable(s);
assertTrue(isNumberFormatParsable(s), s);
assertTrue(isNumberIntegerOnlyFormatParsable(s), s);
assertEquals(parsable, isApplyNonNull(s, Double::parseDouble), s);
return parsable;
} }
private boolean isParsableInteger(final String s) { private boolean isParsableInteger(final String s) {
final NumberFormat instance = NumberFormat.getInstance(); final boolean parsable = NumberUtils.isParsable(s);
instance.setParseIntegerOnly(false); assertTrue(isNumberFormatParsable(s), s);
try { assertTrue(isNumberIntegerOnlyFormatParsable(s), s);
instance.parse(s); assertEquals(parsable, isApplyNonNull(s, Integer::parseInt), s);
} catch (final ParseException e) { return parsable;
return false;
}
try {
Integer.parseInt(s);
} catch (final NumberFormatException e) {
return false;
}
return NumberUtils.isParsable(s);
} }
private boolean isParsableLong(final String s) { private boolean isParsableLong(final String s) {
final NumberFormat instance = NumberFormat.getInstance(); final boolean parsable = NumberUtils.isParsable(s);
instance.setParseIntegerOnly(false); assertTrue(isNumberFormatParsable(s), s);
try { assertTrue(isNumberIntegerOnlyFormatParsable(s), s);
instance.parse(s); assertEquals(parsable, isApplyNonNull(s, Long::parseLong), s);
} catch (final ParseException e) { return parsable;
return false;
}
try {
Long.parseLong(s);
} catch (final NumberFormatException e) {
return false;
}
return NumberUtils.isParsable(s);
} }
private boolean isParsableShort(final String s) { private boolean isParsableShort(final String s) {
final NumberFormat instance = NumberFormat.getInstance(); final boolean parsable = NumberUtils.isParsable(s);
instance.setParseIntegerOnly(false); assertTrue(isNumberFormatParsable(s), s);
try { assertTrue(isNumberIntegerOnlyFormatParsable(s), s);
instance.parse(s); assertEquals(parsable, isApplyNonNull(s, Short::parseShort), s);
} catch (final ParseException e) { return parsable;
return false;
}
try {
Short.parseShort(s);
} catch (final NumberFormatException e) {
return false;
}
return NumberUtils.isParsable(s);
} }
/** /**
@ -1031,6 +1051,24 @@ public class NumberUtilsTest extends AbstractLangTest {
assertFalse(isParsableByte(" ")); assertFalse(isParsableByte(" "));
} }
@Test
public void testLang1729IsParsableDouble() {
assertTrue(isParsableDouble("1"));
assertFalse(isParsableDouble("1 2 3"));
// TODO Expected to be fixed in Java 23
// assertTrue(isParsableDouble(""));
assertFalse(isParsableDouble(" "));
}
@Test
public void testLang1729IsParsableFloat() {
assertTrue(isParsableFloat("1"));
assertFalse(isParsableFloat("1 2 3"));
// TODO Expected to be fixed in Java 23
// assertTrue(isParsableFloat(""));
assertFalse(isParsableFloat(" "));
}
@Test @Test
public void testLang1729IsParsableInteger() { public void testLang1729IsParsableInteger() {
assertTrue(isParsableInteger("1")); assertTrue(isParsableInteger("1"));