From 641aa1c663ebead0189bf001a06ee56463070ddb Mon Sep 17 00:00:00 2001 From: ggregory Date: Fri, 13 Oct 2017 19:01:37 -0600 Subject: [PATCH] Brute force test all available locales (it's fast.) for MapUtils which previously failed on locales that do not use '.' as the decimal separator. No main code changes. --- pom.xml | 6 ++ .../commons/collections4/MapUtilsTest.java | 29 +++++- .../junit/AbstractAvailableLocalesTest.java | 95 +++++++++++++++++++ .../junit/ObjectToStringComparator.java | 40 ++++++++ .../junit/SetDefaultLocaleTestRule.java | 58 +++++++++++ 5 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 src/test/java/org/apache/commons/collections4/junit/AbstractAvailableLocalesTest.java create mode 100644 src/test/java/org/apache/commons/collections4/junit/ObjectToStringComparator.java create mode 100644 src/test/java/org/apache/commons/collections4/junit/SetDefaultLocaleTestRule.java diff --git a/pom.xml b/pom.xml index 0ff63937d..5dbb2e3c1 100644 --- a/pom.xml +++ b/pom.xml @@ -453,6 +453,12 @@ 3.5 test + + org.apache.commons + commons-lang3 + 3.6 + test + diff --git a/src/test/java/org/apache/commons/collections4/MapUtilsTest.java b/src/test/java/org/apache/commons/collections4/MapUtilsTest.java index 7a94a08b5..fc3e3d6e6 100644 --- a/src/test/java/org/apache/commons/collections4/MapUtilsTest.java +++ b/src/test/java/org/apache/commons/collections4/MapUtilsTest.java @@ -24,6 +24,8 @@ import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -31,6 +33,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListResourceBundle; +import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.ResourceBundle; @@ -38,6 +41,7 @@ import java.util.Set; import java.util.TreeMap; import org.apache.commons.collections4.collection.TransformedCollectionTest; +import org.apache.commons.collections4.junit.AbstractAvailableLocalesTest; import org.apache.commons.collections4.keyvalue.DefaultKeyValue; import org.apache.commons.collections4.keyvalue.DefaultMapEntry; import org.apache.commons.collections4.map.HashedMap; @@ -51,7 +55,11 @@ import org.junit.Test; * */ @SuppressWarnings("boxing") -public class MapUtilsTest { +public class MapUtilsTest extends AbstractAvailableLocalesTest { + + public MapUtilsTest(Locale locale) { + super(locale); + } public Predicate getPredicate() { return new Predicate() { @@ -951,7 +959,8 @@ public class MapUtilsTest { final Map inStr = new HashMap<>(); - inStr.put("str1", "2.0"); + char decimalSeparator = getDecimalSeparator(); + inStr.put("str1", "2" + decimalSeparator + "0"); assertEquals(MapUtils.getDoubleValue(inStr,"str1", 0.0), 2.0, 0); } @@ -969,9 +978,10 @@ public class MapUtilsTest { assertEquals(MapUtils.getFloat(in,"noKey", 1.0f), 1.0, 0); final Map inStr = new HashMap<>(); - inStr.put("str1", "2.0"); + char decimalSeparator = getDecimalSeparator(); + inStr.put("str1", "2" + decimalSeparator + "0"); - assertEquals( MapUtils.getFloatValue(inStr,"str1", 0.0f), 2.0, 0); + assertEquals(MapUtils.getFloatValue(inStr,"str1", 0.0f), 2.0, 0); } @Test @@ -1145,5 +1155,14 @@ public class MapUtilsTest { Map map = MapUtils.orderedMap(inMap); assertTrue("returned object should be a OrderedMap", map instanceof OrderedMap); } - + + private char getDecimalSeparator() { + NumberFormat numberFormat = NumberFormat.getInstance(); + if (numberFormat instanceof DecimalFormat) { + return ((DecimalFormat) numberFormat).getDecimalFormatSymbols().getDecimalSeparator(); + } + return '.'; + } + + } diff --git a/src/test/java/org/apache/commons/collections4/junit/AbstractAvailableLocalesTest.java b/src/test/java/org/apache/commons/collections4/junit/AbstractAvailableLocalesTest.java new file mode 100644 index 000000000..ea4d1d044 --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/junit/AbstractAvailableLocalesTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.collections4.junit; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import org.apache.commons.lang3.reflect.FieldUtils; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public abstract class AbstractAvailableLocalesTest { + +// public static List combine(final Object[] objects, final List locales) { +// final List result = new ArrayList<>(objects.length * locales.size()); +// Arrays.stream(objects).forEachOrdered(object -> locales.stream().forEachOrdered(locale -> result.add(new Object[] { object, locale }))); +// return result; +// } +// +// public static List combine(final Object[] objects, final Locale[] locales) { +// final List result = new ArrayList<>(objects.length * locales.length); +// Arrays.stream(objects).forEachOrdered(object -> Arrays.stream(locales).forEachOrdered(locale -> result.add(new Object[] { object, locale }))); +// return result; +// } + +// public static List combineAvailableLocales(final Object[] objects) { +// return combine(objects, getSortedAvailableLocales()); +// } +// +// public static List combineDeclaredLocales(final Object[] objects) { +// return combine(objects, getSortedDeclaredLocales()); +// } + + @Parameters(name = "{0}") + public static Locale[] getSortedAvailableLocales() { + final Locale[] availableLocales = Locale.getAvailableLocales(); + Arrays.sort(availableLocales, new ObjectToStringComparator()); + return availableLocales; + } + + public static List getSortedDeclaredLocales() { + final Field[] allFields = FieldUtils.getAllFields(Locale.class); + final List availableLocales = new ArrayList<>(allFields.length); + for (final Field field : allFields) { + final int modifiers = field.getModifiers(); + if (field.getType() == Locale.class && Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) { + try { + availableLocales.add((Locale) field.get(Locale.class)); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new IllegalStateException("Field " + field, e); + } + } + } + Collections.sort(availableLocales, new ObjectToStringComparator()); + return availableLocales; + } + + private final Locale locale; + + @Rule + public final SetDefaultLocaleTestRule rule; + + public AbstractAvailableLocalesTest(final Locale locale) { + super(); + this.locale = locale; + this.rule = new SetDefaultLocaleTestRule(locale); + } + + public Locale getLocale() { + return locale; + } +} diff --git a/src/test/java/org/apache/commons/collections4/junit/ObjectToStringComparator.java b/src/test/java/org/apache/commons/collections4/junit/ObjectToStringComparator.java new file mode 100644 index 000000000..972cd6e47 --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/junit/ObjectToStringComparator.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.collections4.junit; + +import java.io.Serializable; +import java.util.Comparator; + +public final class ObjectToStringComparator implements Comparator, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public int compare(final Object o1, final Object o2) { + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } + return o1.toString().compareTo(o2.toString()); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/commons/collections4/junit/SetDefaultLocaleTestRule.java b/src/test/java/org/apache/commons/collections4/junit/SetDefaultLocaleTestRule.java new file mode 100644 index 000000000..f1f57c30a --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/junit/SetDefaultLocaleTestRule.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.collections4.junit; + +import java.util.Locale; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Sets the default {@code Locale} to the given locale for the duration of the test. + */ +public class SetDefaultLocaleTestRule implements TestRule { + + private final Locale locale; + + public SetDefaultLocaleTestRule(final Locale locale) { + super(); + this.locale = locale; + } + + @Override + public Statement apply(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + final Locale savedLocale = Locale.getDefault(); + Locale.setDefault(getLocale()); + try { + base.evaluate(); + } finally { + Locale.setDefault(savedLocale); + } + } + }; + } + + public Locale getLocale() { + return locale; + } + +}