blob: 07492af4ada1c104e50a59968b302a1334605998 [file] [log] [blame]
/*
* 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.configuration2;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.convert.DisabledListDelimiterHandler;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.apache.commons.configuration2.io.FileHandler;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* Test class to test the handling of list structures in XMLConfiguration.
*/
public class TestXMLListHandling {
/** XML to be loaded by the configuration. */
private static final String SOURCE = "<config>" + "<values>a,b,c</values>" + "<split><value>1</value><value>2</value></split>"
+ "<mixed><values>foo,blah</values><values>bar,baz</values></mixed>" + "</config>";
/** Key for the string property with multiple values. */
private static final String KEY_VALUES = "values";
/** Key for the split list property. */
private static final String KEY_SPLIT = "split.value";
/** The XML element name for the single values of the split list. */
private static final String ELEM_SPLIT = "value";
/**
* Checks whether the specified XML contains a list of values as a single, comma-separated string.
*
* @param xml the XML
* @param key the key
* @param values the expected values
*/
private static void checkCommaSeparated(final String xml, final String key, final String... values) {
final String strValues = StringUtils.join(values, ',');
final String element = element(key, strValues);
assertThat(xml, containsString(element));
}
/**
* Checks whether the specified XML contains a list of values as multiple XML elements.
*
* @param xml the XML
* @param key the key
* @param values the expected values
*/
private static void checkSplit(final String xml, final String key, final String... values) {
for (final String v : values) {
assertThat(xml, containsString(element(key, v)));
}
}
/**
* Generates an XML element with the specified value as body.
*
* @param key the key
* @param value the value
* @return the string representation of this element
*/
private static String element(final String key, final String value) {
return "<" + key + '>' + value + "</" + key + '>';
}
/**
* Parses the specified string into an XML configuration.
*
* @param xml the XML to be parsed
* @return the resulting configuration
*/
private static XMLConfiguration readFromString(final String xml) throws ConfigurationException {
final XMLConfiguration config = new XMLConfiguration();
config.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
final FileHandler handler = new FileHandler(config);
handler.load(new StringReader(xml));
return config;
}
/** Configuration to be tested. */
private XMLConfiguration config;
/**
* Saves the test configuration into a string.
*
* @return the resulting string
*/
private String saveToString() throws ConfigurationException {
final StringWriter writer = new StringWriter(4096);
final FileHandler handler = new FileHandler(config);
handler.save(writer);
return writer.toString();
}
@BeforeEach
public void setUp() throws Exception {
config = readFromString(SOURCE);
}
/**
* Tests that a list item can be added without affecting the format.
*/
@Test
public void testAddListItem() throws ConfigurationException {
config.addProperty(KEY_VALUES, "d");
config.addProperty(KEY_SPLIT, "3");
final String xml = saveToString();
checkSplit(xml, ELEM_SPLIT, "1", "2", "3");
checkCommaSeparated(xml, KEY_VALUES, "a", "b", "c", "d");
}
/**
* Tries to save the configuration with a different list delimiter handler which does not support escaping of lists.
* This should fail with a meaningful exception message.
*/
@Test
public void testIncompatibleListDelimiterOnSaving() {
config.setListDelimiterHandler(DisabledListDelimiterHandler.INSTANCE);
assertThrows(ConfigurationRuntimeException.class, this::saveToString);
}
/**
* Tests whether a list consisting of multiple elements where some elements define multiple values is handled correctly.
*/
@Test
public void testMixedList() throws ConfigurationException {
final List<String> expected = Arrays.asList("foo", "blah", "bar", "baz");
assertEquals(expected, config.getList("mixed.values"));
final String xml = saveToString();
final XMLConfiguration c2 = readFromString(xml);
assertEquals(expected, c2.getList("mixed.values"));
}
/**
* Tests that a list item can be removed without affecting the format.
*/
@Test
public void testRemoveListItem() throws ConfigurationException {
config.clearProperty(KEY_VALUES + "(2)");
config.clearProperty(KEY_SPLIT + "(1)");
final String xml = saveToString();
checkSplit(xml, ELEM_SPLIT, "1");
checkCommaSeparated(xml, KEY_VALUES, "a", "b");
}
/**
* Tests that the list format is kept if properties are not touched,
*/
@Test
public void testSaveNoChanges() throws ConfigurationException {
final String xml = saveToString();
checkSplit(xml, ELEM_SPLIT, "1", "2");
checkCommaSeparated(xml, KEY_VALUES, "a", "b", "c");
}
}