Skip to content

Commit

Permalink
Locale-dependent tests: calculate expected results as output varies b…
Browse files Browse the repository at this point in the history
…etween JVMs
  • Loading branch information
sebbASF committed Dec 21, 2024
1 parent 902d086 commit 78a9ebc
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 99 deletions.
35 changes: 2 additions & 33 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
<commons.jacoco.instructionRatio>0.87</commons.jacoco.instructionRatio>
<commons.jacoco.methodRatio>0.81</commons.jacoco.methodRatio>
<commons.jacoco.branchRatio>0.74</commons.jacoco.branchRatio>
<commons.jacoco.lineRatio>0.78</commons.jacoco.lineRatio>
<commons.jacoco.lineRatio>0.78</commons.jacoco.lineRatio>
<commons.jacoco.complexityRatio>0.71</commons.jacoco.complexityRatio>
</properties>

Expand Down Expand Up @@ -316,37 +316,6 @@
</plugins>
</build>
</profile>
<profile>
<id>jdk9-cldr</id>
<activation>
<jdk>[1.9,)</jdk>
</activation>
<!--
Temporary fix to allow tests to work under Java 9+, which changed to use CLDR names.
This causes several Date/Time tests to fail, as some language strings have changed.
e.g. German now uses "Dez." rather than "Dez" for the short version of "December"
(see: TimeValidatorTest#testTimeZone)
Is the test data wrong, or should the code still be able to parse "Dez"?
-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--
systemPropertyVariables are set too late in Surefire
versions after 2.21.0 and before 3.0-M4 (but only on Windows!)
Use the command-line instead to ensure the property is set early enough
Use ${argLine} to get JaCoCo to work properly.
-->
<argLine>${argLine} -Djava.locale.providers=COMPAT,SPI</argLine>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<developers>
Expand Down Expand Up @@ -426,7 +395,7 @@
<email>ggregory at apache.org</email>
<url>https://www.garygregory.com</url>
<organization>The Apache Software Foundation</organization>
<organizationUrl>https://www.apache.org/</organizationUrl>
<organizationUrl>https://www.apache.org/</organizationUrl>
<roles>
<role>PMC Member</role>
</roles>
Expand Down
1 change: 1 addition & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<release version="1.10.0" date="YYYY-MM-DD" description="This is a maintenance and bug fix release; requires Java 8.">
<!-- FIX -->
<action type="fix" dev="sebb">Locale-dependent tests: calculate expected results as output varies between JVMs</action>
<action type="fix" dev="sebb">Locale default tests: ensure original is restored on failure</action>
<action type="fix" dev="ggregory" due-to="Johannes Weberhofer">Fix order of actual and expected parameters in assertEquals() #246.</action>
<action type="fix" dev="ggregory" due-to="Johannes Weberhofer">InetAddressValidator does not need its instance variable, so uses a touch less memory.</action>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.text.DateFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
Expand Down Expand Up @@ -115,8 +116,12 @@ public void testCalendarValidatorMethods() {
final Locale locale = Locale.GERMAN;
final String pattern = "yyyy-MM-dd";
final String patternVal = "2005-12-31";
final String germanVal = "31 Dez 2005";
final String germanPattern = "dd MMM yyyy";
// Don't rely on specific German format - it varies between JVMs
DateFormat df = new SimpleDateFormat(germanPattern, locale);
Calendar cal = Calendar.getInstance(Locale.US);
cal.set(2005, 11, 31); // month is 0-based
final String germanVal = df.format(cal.getTime());
final String localeVal = "31.12.2005";
final String defaultVal = "12/31/05";
final String xxxx = "XXXX";
Expand Down Expand Up @@ -228,7 +233,7 @@ public void testCompare() {

// invalid compare
final Exception e = assertThrows(IllegalArgumentException.class, () -> calValidator.compare(value, value, -1), "Invalid Compare field");
assertEquals(e.getMessage(), "Invalid field: -1", "check message");
assertEquals("Invalid field: -1", e.getMessage(), "check message");
}

/**
Expand All @@ -237,6 +242,16 @@ public void testCompare() {
@Test
public void testDateTimeStyle() {
Locale.setDefault(Locale.UK);
// Formats vary between JVMs, so create the test strings using the current JVM
final DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
final Calendar cal = Calendar.getInstance();
cal.set(2005, 11, 31, 14, 23); // month is 0-based
final String val = df.format(cal.getTime());

final DateFormat usdf = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.US);
final Calendar uscal = Calendar.getInstance(Locale.US);
uscal.set(2005, 11, 31, 14, 23); // month is 0-based
final String usval = usdf.format(uscal.getTime());

final AbstractCalendarValidator dateTimeValidator = new AbstractCalendarValidator(true, DateFormat.SHORT, DateFormat.SHORT) {
private static final long serialVersionUID = 1L;
Expand All @@ -246,8 +261,8 @@ protected Object processParsedValue(final Object value, final Format formatter)
return value;
}
};
assertTrue(dateTimeValidator.isValid("31/12/05 14:23"), "validate(A) default");
assertTrue(dateTimeValidator.isValid("12/31/05 2:23 PM", Locale.US), "validate(A) locale ");
assertTrue(dateTimeValidator.isValid(val), "validate(A) default");
assertTrue(dateTimeValidator.isValid(usval, Locale.US), "validate(A) locale ");
}

/**
Expand All @@ -259,20 +274,51 @@ public void testFormat() {
// Set the default Locale
Locale.setDefault(Locale.UK);

final Calendar cal20050101 = createCalendar(GMT, 20051231, 11500);
final Calendar cal20051231 = createCalendar(GMT, 20051231, 11500);
// validator defaults to SHORT, but the format varies between JVMs
final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
final String val = df.format(cal20051231.getTime());
final DateFormat dfus = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
final String usval = dfus.format(cal20051231.getTime());
final String germanPattern = "dd MMM yyyy";
final DateFormat dedf = new SimpleDateFormat(germanPattern, Locale.GERMAN);
final String deval = dedf.format(cal20051231.getTime());
assertNull(calValidator.format(null), "null");
assertEquals("31/12/05", calValidator.format(cal20050101), "default");
assertEquals("12/31/05", calValidator.format(cal20050101, Locale.US), "locale");
assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd HH:mm"), "2005-12-31 01:15", "patternA");
assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd z"), "2005-12-31 GMT", "patternB");
assertEquals("31 Dez 2005", calValidator.format(cal20050101, "dd MMM yyyy", Locale.GERMAN), "both");
assertEquals(val, calValidator.format(cal20051231), "default");
assertEquals(usval, calValidator.format(cal20051231, Locale.US), "locale");
assertEquals(calValidator.format(cal20051231, "yyyy-MM-dd HH:mm"), "2005-12-31 01:15", "patternA");
assertEquals(calValidator.format(cal20051231, "yyyy-MM-dd z"), "2005-12-31 GMT", "patternB");
assertEquals(deval, calValidator.format(cal20051231, germanPattern, Locale.GERMAN), "both");

// EST Time Zone
assertEquals("30/12/05", calValidator.format(cal20050101, EST), "EST default");
assertEquals("12/30/05", calValidator.format(cal20050101, Locale.US, EST), "EST locale");
assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd HH:mm", EST), "2005-12-30 20:15", "EST patternA");
assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd z", EST), "2005-12-30 EST", "EST patternB");
assertEquals("30 Dez 2005", calValidator.format(cal20050101, "dd MMM yyyy", Locale.GERMAN, EST), "EST both");
final DateFormat dfest = DateFormat.getDateInstance(DateFormat.SHORT);
dfest.setTimeZone(EST);
final String valest = dfest.format(cal20051231.getTime());

final DateFormat dfusest = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
dfusest.setTimeZone(EST);
final String valusest = dfusest.format(cal20051231.getTime());

final DateFormat dedfest = new SimpleDateFormat(germanPattern, Locale.GERMAN);
dedfest.setTimeZone(EST);
final String devalest = dedfest.format(cal20051231.getTime());

assertEquals(valest, calValidator.format(cal20051231, EST), "EST default");
assertEquals(valusest, calValidator.format(cal20051231, Locale.US, EST), "EST locale");

final String patternA = "yyyy-MM-dd HH:mm";
final DateFormat dfA = new SimpleDateFormat(patternA);
dfA.setTimeZone(EST);
final String valA = dfA.format(cal20051231.getTime());
assertEquals(valA, calValidator.format(cal20051231, patternA, EST), "EST patternA");

final String patternB = "yyyy-MM-dd z";
final DateFormat dfB = new SimpleDateFormat(patternB);
dfB.setTimeZone(EST);
final String valB = dfB.format(cal20051231.getTime());

assertEquals(valB, calValidator.format(cal20051231, patternB, EST), "EST patternB");
assertEquals(devalest, calValidator.format(cal20051231, germanPattern, Locale.GERMAN, EST), "EST both");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.math.BigDecimal;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;

import org.junit.jupiter.api.AfterEach;
Expand Down Expand Up @@ -88,14 +90,19 @@ public void testIntegerValid() {
final CurrencyValidator validator = new CurrencyValidator();
final BigDecimal expected = new BigDecimal("1234.00");
final BigDecimal negative = new BigDecimal("-1234.00");
// Generate the exected strings, as these vary between JVMs
final String ukPlus = NumberFormat.getCurrencyInstance(Locale.UK).format(1234);
final String ukMinus = NumberFormat.getCurrencyInstance(Locale.UK).format(-1234);
final String usPlus = NumberFormat.getCurrencyInstance(Locale.US).format(1234);
final String usMinus = NumberFormat.getCurrencyInstance(Locale.US).format(-1234);

assertEquals(expected, validator.validate(ukPound + "1,234"), "Default locale");
assertEquals(expected, validator.validate(ukPlus), "Default locale");

assertEquals(expected, validator.validate(ukPound + "1,234", Locale.UK), "UK locale");
assertEquals(negative, validator.validate("-" + ukPound + "1,234", Locale.UK), "UK negative");
assertEquals(expected, validator.validate(ukPlus, Locale.UK), "UK locale");
assertEquals(negative, validator.validate(ukMinus, Locale.UK), "UK negative");

assertEquals(expected, validator.validate(usDollar + "1,234", Locale.US), "US locale");
assertEquals(negative, validator.validate("(" + usDollar + "1,234)", Locale.US), "US negative");
assertEquals(expected, validator.validate(usPlus, Locale.US), "US locale");
assertEquals(negative, validator.validate(usMinus, Locale.US), "US negative");
}

/**
Expand All @@ -105,19 +112,32 @@ public void testIntegerValid() {
public void testInvalid() {
final BigDecimalValidator validator = CurrencyValidator.getInstance();

final String ukPlus = NumberFormat.getCurrencyInstance(Locale.UK).format(1234.56);
final String usPlus = NumberFormat.getCurrencyInstance(Locale.US).format(1234.56);
final String ukMinus = NumberFormat.getCurrencyInstance(Locale.UK).format(-1234.56);
final String usMinus = NumberFormat.getCurrencyInstance(Locale.US).format(-1234.56);

// Invalid Missing
assertFalse(validator.isValid(null), "isValid() Null Value");
assertFalse(validator.isValid(""), "isValid() Empty Value");
assertNull(validator.validate(null), "validate() Null Value");
assertNull(validator.validate(""), "validate() Empty Value");

// Invalid UK
assertFalse(validator.isValid(usDollar + "1,234.56", Locale.UK), "UK wrong symbol");
assertFalse(validator.isValid("(" + ukPound + "1,234.56)", Locale.UK), "UK wrong negative");
assertFalse(validator.isValid(usPlus, Locale.UK), "UK wrong symbol: " + usPlus);
if (ukMinus.startsWith("-")) {
assertFalse(validator.isValid("(" + ukPound + "1,234.56)", Locale.UK), "UK wrong negative: " + ukMinus);
} else {
assertFalse(validator.isValid("-" + ukPound + "1,234.56", Locale.UK), "UK wrong negative: " + ukMinus);
}

// Invalid US
assertFalse(validator.isValid(ukPound + "1,234.56", Locale.US), "US wrong symbol");
assertFalse(validator.isValid("-" + usDollar + "1,234.56", Locale.US), "US wrong negative");
assertFalse(validator.isValid(ukPlus, Locale.US), "US wrong symbol: " + ukPlus);
if (usMinus.startsWith("-")) {
assertFalse(validator.isValid("(" + usDollar + "1,234.56)", Locale.US), "UK wrong negative: " + usMinus);
} else {
assertFalse(validator.isValid("-" + usDollar + "1,234.56", Locale.US), "UK wrong negative: " + usMinus);
}
}

/**
Expand Down Expand Up @@ -165,20 +185,37 @@ public void testValid() {
final BigDecimal noDecimal = new BigDecimal("1234.00");
final BigDecimal oneDecimal = new BigDecimal("1234.50");

assertEquals(expected, validator.validate(ukPound + "1,234.56"), "Default locale");

assertEquals(expected, validator.validate(ukPound + "1,234.56", Locale.UK), "UK locale");
assertEquals(negative, validator.validate("-" + ukPound + "1,234.56", Locale.UK), "UK negative");
assertEquals(noDecimal, validator.validate(ukPound + "1,234", Locale.UK), "UK no decimal");
assertEquals(oneDecimal, validator.validate(ukPound + "1,234.5", Locale.UK), "UK 1 decimal");
assertEquals(expected, validator.validate(ukPound + "1,234.567", Locale.UK), "UK 3 decimal");
// Generate the exected strings, as these vary between JVMs
final String ukPlus = NumberFormat.getCurrencyInstance(Locale.UK).format(1234.56);
final String ukPlus0Decimal = NumberFormat.getCurrencyInstance(Locale.UK).format(1234);
final String ukPlus1Decimal = NumberFormat.getCurrencyInstance(Locale.UK).format(1234.5);
// Note that NumberFormat may perform rounding up or truncation, so we cheat
final String ukPlus3Decimal = NumberFormat.getCurrencyInstance(Locale.UK).format(1234.56) + "7";
final String ukMinus = NumberFormat.getCurrencyInstance(Locale.UK).format(-1234.56);
final String usPlus = NumberFormat.getCurrencyInstance(Locale.US).format(1234.56);
final String usPlus0Decimal = NumberFormat.getCurrencyInstance(Locale.US).format(1234);
final String usPlus1Decimal = NumberFormat.getCurrencyInstance(Locale.US).format(1234.5);
// Note that NumberFormat may perform rounding up or truncation, so we cheat
final String usPlus3Decimal = NumberFormat.getCurrencyInstance(Locale.US).format(1234.56) + "7";
final String usMinus = NumberFormat.getCurrencyInstance(Locale.US).format(-1234.56);

assertEquals(expected, validator.validate(ukPlus), "Default locale");

assertEquals(expected, validator.validate(ukPlus, Locale.UK), "UK locale");
assertEquals(negative, validator.validate(ukMinus, Locale.UK), "UK negative");
assertEquals(noDecimal, validator.validate(ukPlus0Decimal, Locale.UK), "UK no decimal");
assertEquals(oneDecimal, validator.validate(ukPlus1Decimal, Locale.UK), "UK 1 decimal");
assertEquals(expected, validator.validate(ukPlus3Decimal, Locale.UK), "UK 3 decimal: " + ukPlus3Decimal);
// TODO: The following expects the value to be truncated, rather than rounded up - is that correct?
assertEquals(expected, validator.validate(ukPlus3Decimal, Locale.UK), "UK 3 decimal: " + ukPlus3Decimal);
assertEquals(expected, validator.validate("1,234.56", Locale.UK), "UK no symbol");

assertEquals(expected, validator.validate(usDollar + "1,234.56", Locale.US), "US locale");
assertEquals(negative, validator.validate("(" + usDollar + "1,234.56)", Locale.US), "US negative");
assertEquals(noDecimal, validator.validate(usDollar + "1,234", Locale.US), "US no decimal");
assertEquals(oneDecimal, validator.validate(usDollar + "1,234.5", Locale.US), "US 1 decimal");
assertEquals(expected, validator.validate(usDollar + "1,234.567", Locale.US), "US 3 decimal");
assertEquals(expected, validator.validate(usPlus, Locale.US), "US locale");
assertEquals(negative, validator.validate(usMinus, Locale.US), "US negative");
assertEquals(noDecimal, validator.validate(usPlus0Decimal, Locale.US), "US no decimal");
assertEquals(oneDecimal, validator.validate(usPlus1Decimal, Locale.US), "US 1 decimal");
// TODO: The following expects the value to be truncated, rather than rounded up - is that correct?
assertEquals(expected, validator.validate(usPlus3Decimal, Locale.US), "US 3 decimal: " + usPlus3Decimal);
assertEquals(expected, validator.validate("1,234.56", Locale.US), "US no symbol");
}
}
Loading

0 comments on commit 78a9ebc

Please sign in to comment.