This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-configuration.git
commit 7d7d399d0598cb0ca5f81891de34694178156dab Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Sat Mar 16 18:16:32 2024 -0400 [CONFIGURATION-840] More tests --- .../convert/AbstractListDelimiterHandler.java | 40 +++++++++++++-- .../convert/ListDelimiterHandler.java | 31 +++--------- .../TestPropertiesConfiguration.java | 58 ++++++++++++++++++---- 3 files changed, 92 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/apache/commons/configuration2/convert/AbstractListDelimiterHandler.java b/src/main/java/org/apache/commons/configuration2/convert/AbstractListDelimiterHandler.java index 5fbcd7f9..e4ab1554 100644 --- a/src/main/java/org/apache/commons/configuration2/convert/AbstractListDelimiterHandler.java +++ b/src/main/java/org/apache/commons/configuration2/convert/AbstractListDelimiterHandler.java @@ -16,9 +16,13 @@ */ package org.apache.commons.configuration2.convert; +import java.lang.reflect.Array; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; /** * <p> @@ -42,15 +46,45 @@ public abstract class AbstractListDelimiterHandler implements ListDelimiterHandl * @param target the target collection * @param iterator the iterator to process * @param limit a limit for the number of elements to extract + * @param dejaVue Previously visited objects. */ - static void flattenIterator(final ListDelimiterHandler handler, final Collection<Object> target, final Iterator<?> iterator, final int limit) { + static void flattenIterator(final ListDelimiterHandler handler, final Collection<Object> target, final Iterator<?> iterator, final int limit, + Set<Object> dejaVue) { int size = target.size(); while (size < limit && iterator.hasNext()) { - target.addAll(handler.flatten(iterator.next(), limit - size)); - size = target.size(); + final Object next = iterator.next(); + if (!dejaVue.contains(next)) { + target.addAll(flatten(handler, next, limit - size, dejaVue)); + size = target.size(); + } } } + static Collection<?> flatten(final ListDelimiterHandler handler, final Object value, final int limit, final Set<Object> dejaVu) { + dejaVu.add(value); + if (value instanceof String) { + return handler.split((String) value, true); + } + final Collection<Object> result = new LinkedList<>(); + if (value instanceof Path) { + // Don't handle as an Iterable. + result.add(value); + } else if (value instanceof Iterable) { + AbstractListDelimiterHandler.flattenIterator(handler, result, ((Iterable<?>) value).iterator(), limit, dejaVu); + } else if (value instanceof Iterator) { + AbstractListDelimiterHandler.flattenIterator(handler, result, (Iterator<?>) value, limit, dejaVu); + } else if (value != null) { + if (value.getClass().isArray()) { + for (int len = Array.getLength(value), idx = 0, size = 0; idx < len && size < limit; idx++, size = result.size()) { + result.addAll(handler.flatten(Array.get(value, idx), limit - size)); + } + } else { + result.add(value); + } + } + return result; + } + /** * {@inheritDoc} This implementation checks whether the object to be escaped is a string. If yes, it delegates to * {@link #escapeString(String)}, otherwise no escaping is performed. Eventually, the passed in transformer is invoked diff --git a/src/main/java/org/apache/commons/configuration2/convert/ListDelimiterHandler.java b/src/main/java/org/apache/commons/configuration2/convert/ListDelimiterHandler.java index d0fc1ef0..fb194049 100644 --- a/src/main/java/org/apache/commons/configuration2/convert/ListDelimiterHandler.java +++ b/src/main/java/org/apache/commons/configuration2/convert/ListDelimiterHandler.java @@ -16,12 +16,11 @@ */ package org.apache.commons.configuration2.convert; -import java.lang.reflect.Array; -import java.nio.file.Path; import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedList; +import java.util.Collections; +import java.util.IdentityHashMap; import java.util.List; +import java.util.Set; /** * <p> @@ -118,27 +117,9 @@ public interface ListDelimiterHandler { * @since 2.9.0 */ default Collection<?> flatten(final Object value, final int limit) { - if (value instanceof String) { - return split((String) value, true); - } - final Collection<Object> result = new LinkedList<>(); - if (value instanceof Path) { - // Don't handle as an Iterable. - result.add(value); - } else if (value instanceof Iterable) { - AbstractListDelimiterHandler.flattenIterator(this, result, ((Iterable<?>) value).iterator(), limit); - } else if (value instanceof Iterator) { - AbstractListDelimiterHandler.flattenIterator(this, result, (Iterator<?>) value, limit); - } else if (value != null) { - if (value.getClass().isArray()) { - for (int len = Array.getLength(value), idx = 0, size = 0; idx < len && size < limit; idx++, size = result.size()) { - result.addAll(flatten(Array.get(value, idx), limit - size)); - } - } else { - result.add(value); - } - } - return result; + final Set<Object> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>()); + dejaVu.add(value); + return AbstractListDelimiterHandler.flatten(this, value, limit, dejaVu); } } diff --git a/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java b/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java index 52fd5bc0..bfd415b7 100644 --- a/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java +++ b/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java @@ -33,6 +33,8 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.beans.beancontext.BeanContextServicesSupport; +import java.beans.beancontext.BeanContextSupport; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; @@ -53,8 +55,9 @@ import java.net.URLStreamHandler; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; +import java.sql.SQLException; +import java.sql.SQLWarning; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -62,6 +65,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.PriorityQueue; import java.util.Properties; import java.util.Set; @@ -435,20 +439,56 @@ public class TestPropertiesConfiguration { assertFalse(conf.containsKey("!comment")); } - @Test - public void testCompress840() { + private void testCompress840(final Iterable<?> object) { final PropertiesConfiguration configuration = new PropertiesConfiguration(); - final Path path = FileSystems.getDefault().getPath("bar"); final ListDelimiterHandler listDelimiterHandler = configuration.getListDelimiterHandler(); - listDelimiterHandler.flatten(path, 0); + listDelimiterHandler.flatten(object, 0); // Stack overflow: - listDelimiterHandler.flatten(path, 1); - listDelimiterHandler.flatten(path, Integer.MAX_VALUE); - listDelimiterHandler.parse(path); - configuration.addProperty("foo", path); + listDelimiterHandler.flatten(object, 1); + listDelimiterHandler.flatten(object, Integer.MAX_VALUE); + listDelimiterHandler.parse(object); + configuration.addProperty("foo", object); configuration.toString(); } + @Test + public void testCompress840BeanContextServicesSupport() { + testCompress840(new BeanContextServicesSupport()); + testCompress840(new BeanContextServicesSupport(new BeanContextServicesSupport())); + final BeanContextSupport bcs = new BeanContextSupport(); + final BeanContextServicesSupport bcss = new BeanContextServicesSupport(); + bcs.add(FileSystems.getDefault().getPath("bar")); + bcss.add(bcs); + testCompress840(bcss); + bcss.add(FileSystems.getDefault().getPath("bar")); + testCompress840(bcss); + bcss.add(bcss); + testCompress840(bcss); + } + + @Test + public void testCompress840BeanContextSupport() { + testCompress840(new BeanContextSupport()); + testCompress840(new BeanContextSupport(new BeanContextSupport())); + final BeanContextSupport bcs = new BeanContextSupport(); + bcs.add(FileSystems.getDefault().getPath("bar")); + testCompress840(bcs); + bcs.add(bcs); + testCompress840(bcs); + } + + @Test + public void testCompress840Path() { + testCompress840(FileSystems.getDefault().getPath("foo")); + testCompress840(FileSystems.getDefault().getPath("foo", "bar")); + } + + @Test + public void testCompress840PriorityQueue() { + testCompress840(new PriorityQueue<>()); + testCompress840(new PriorityQueue<>(Arrays.asList(FileSystems.getDefault().getPath("foo")))); + } + /** * Tests copying another configuration into the test configuration. This test ensures that the layout object is informed * about the newly added properties.