| /* |
| * 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.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertThat; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.text.MessageFormat; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.apache.commons.configuration2.SynchronizerTestImpl.Methods; |
| import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl; |
| import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; |
| import org.apache.commons.configuration2.builder.fluent.Parameters; |
| import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler; |
| import org.apache.commons.configuration2.ex.ConfigurationException; |
| import org.apache.commons.configuration2.sync.ReadWriteSynchronizer; |
| import org.apache.commons.configuration2.tree.DefaultExpressionEngine; |
| import org.apache.commons.configuration2.tree.DefaultExpressionEngineSymbols; |
| import org.apache.commons.configuration2.tree.ImmutableNode; |
| import org.apache.commons.configuration2.tree.NodeHandler; |
| import org.apache.commons.configuration2.tree.NodeNameMatchers; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.TemporaryFolder; |
| |
| /** |
| * Test class for {@code INIConfiguration}. |
| * |
| */ |
| public class TestINIConfiguration |
| { |
| private static String LINE_SEPARATOR = System.getProperty("line.separator"); |
| |
| /** Constant for the content of an ini file. */ |
| private static final String INI_DATA = "[section1]" + LINE_SEPARATOR |
| + "var1 = foo" + LINE_SEPARATOR + "var2 = 451" + LINE_SEPARATOR |
| + LINE_SEPARATOR + "[section2]" + LINE_SEPARATOR + "var1 = 123.45" |
| + LINE_SEPARATOR + "var2 = bar" + LINE_SEPARATOR + LINE_SEPARATOR |
| + "[section3]" + LINE_SEPARATOR + "var1 = true" + LINE_SEPARATOR |
| + "interpolated = ${section3.var1}" + LINE_SEPARATOR |
| + "multi = foo" + LINE_SEPARATOR + "multi = bar" + LINE_SEPARATOR |
| + LINE_SEPARATOR; |
| |
| private static final String INI_DATA2 = "[section4]" + LINE_SEPARATOR |
| + "var1 = \"quoted value\"" + LINE_SEPARATOR |
| + "var2 = \"quoted value\\nwith \\\"quotes\\\"\"" + LINE_SEPARATOR |
| + "var3 = 123 ; comment" + LINE_SEPARATOR |
| + "var4 = \"1;2;3\" ; comment" + LINE_SEPARATOR |
| + "var5 = '\\'quoted\\' \"value\"' ; comment" + LINE_SEPARATOR |
| + "var6 = \"\"" + LINE_SEPARATOR; |
| |
| private static final String INI_DATA3 = "[section5]" + LINE_SEPARATOR |
| + "multiLine = one \\" + LINE_SEPARATOR |
| + " two \\" + LINE_SEPARATOR |
| + " three" + LINE_SEPARATOR |
| + "singleLine = C:\\Temp\\" + LINE_SEPARATOR |
| + "multiQuoted = one \\" + LINE_SEPARATOR |
| + "\" two \" \\" + LINE_SEPARATOR |
| + " three" + LINE_SEPARATOR |
| + "multiComment = one \\ ; a comment" + LINE_SEPARATOR |
| + "two" + LINE_SEPARATOR |
| + "multiQuotedComment = \" one \" \\ ; comment" + LINE_SEPARATOR |
| + "two" + LINE_SEPARATOR |
| + "noFirstLine = \\" + LINE_SEPARATOR |
| + " line 2" + LINE_SEPARATOR |
| + "continueNoLine = one \\" + LINE_SEPARATOR; |
| |
| private static final String INI_DATA4 = "[section6]" + LINE_SEPARATOR |
| + "key1{0}value1" + LINE_SEPARATOR |
| + "key2{0}value2" + LINE_SEPARATOR + LINE_SEPARATOR |
| + "[section7]" + LINE_SEPARATOR |
| + "key3{0}value3" + LINE_SEPARATOR; |
| |
| private static final String INI_DATA_SEPARATORS = "[section]" |
| + LINE_SEPARATOR + "var1 = value1" + LINE_SEPARATOR |
| + "var2 : value2" + LINE_SEPARATOR |
| + "var3=value3" + LINE_SEPARATOR |
| + "var4:value4" + LINE_SEPARATOR |
| + "var5 : value=5" + LINE_SEPARATOR |
| + "var:6=value" + LINE_SEPARATOR |
| + "var:7=\"value7\"" + LINE_SEPARATOR |
| + "var:8 = \"value8\"" + LINE_SEPARATOR; |
| |
| /** An ini file that contains only a property in the global section. */ |
| private static final String INI_DATA_GLOBAL_ONLY = "globalVar = testGlobal" |
| + LINE_SEPARATOR + LINE_SEPARATOR; |
| |
| /** An ini file with a global section. */ |
| private static final String INI_DATA_GLOBAL = INI_DATA_GLOBAL_ONLY |
| + INI_DATA; |
| |
| /** A helper object for creating temporary files. */ |
| @Rule |
| public TemporaryFolder folder = new TemporaryFolder(); |
| |
| /** |
| * Creates a INIConfiguration object that is initialized from |
| * the given data. |
| * |
| * @param data the data of the configuration (an ini file as string) |
| * @return the initialized configuration |
| * @throws ConfigurationException if an error occurs |
| */ |
| private static INIConfiguration setUpConfig(final String data) |
| throws ConfigurationException |
| { |
| final INIConfiguration instance = new INIConfiguration(); |
| instance.setListDelimiterHandler(new DefaultListDelimiterHandler(',')); |
| load(instance, data); |
| return instance; |
| } |
| |
| /** |
| * Loads the specified content into the given configuration instance. |
| * |
| * @param instance the configuration |
| * @param data the data to be loaded |
| * @throws ConfigurationException if an error occurs |
| */ |
| private static void load(final INIConfiguration instance, final String data) |
| throws ConfigurationException |
| { |
| final StringReader reader = new StringReader(data); |
| try |
| { |
| instance.read(reader); |
| } |
| catch (final IOException e) |
| { |
| throw new ConfigurationException(e); |
| } |
| reader.close(); |
| } |
| |
| /** |
| * Saves the specified configuration to a string. The string can be compared |
| * with an expected value or again loaded into a configuration. |
| * |
| * @param config the configuration to be saved |
| * @return the content of this configuration saved to a string |
| * @throws ConfigurationException if an error occurs |
| */ |
| private static String saveToString(final INIConfiguration config) |
| throws ConfigurationException |
| { |
| final StringWriter writer = new StringWriter(); |
| try |
| { |
| config.write(writer); |
| } |
| catch (final IOException e) |
| { |
| throw new ConfigurationException(e); |
| } |
| return writer.toString(); |
| } |
| |
| /** |
| * Writes a test ini file. |
| * |
| * @param content the content of the file |
| * @return the newly created file |
| * @throws IOException if an error occurs |
| */ |
| private File writeTestFile(final String content) throws IOException |
| { |
| final File file = folder.newFile(); |
| final PrintWriter out = new PrintWriter(new FileWriter(file)); |
| try |
| { |
| out.println(content); |
| } |
| finally |
| { |
| out.close(); |
| } |
| return file; |
| } |
| |
| /** |
| * Test of save method, of class {@link INIConfiguration}. |
| */ |
| @Test |
| public void testSave() throws Exception |
| { |
| final Writer writer = new StringWriter(); |
| final INIConfiguration instance = new INIConfiguration(); |
| instance.addProperty("section1.var1", "foo"); |
| instance.addProperty("section1.var2", "451"); |
| instance.addProperty("section2.var1", "123.45"); |
| instance.addProperty("section2.var2", "bar"); |
| instance.addProperty("section3.var1", "true"); |
| instance.addProperty("section3.interpolated", "${section3.var1}"); |
| instance.addProperty("section3.multi", "foo"); |
| instance.addProperty("section3.multi", "bar"); |
| instance.write(writer); |
| |
| assertEquals("Wrong content of ini file", INI_DATA, writer.toString()); |
| } |
| |
| /** |
| * Test of save method with changed separator |
| */ |
| @Test |
| public void testSeparatorUsedInINIOutput() throws Exception |
| { |
| final String outputSeparator = ": "; |
| final String input = MessageFormat.format(INI_DATA4, "=").trim(); |
| final String expectedOutput = MessageFormat.format(INI_DATA4, outputSeparator).trim(); |
| |
| final INIConfiguration instance = new FileBasedConfigurationBuilder<>( |
| INIConfiguration.class) |
| .configure(new Parameters().ini().setSeparatorUsedInOutput(outputSeparator)) |
| .getConfiguration(); |
| load(instance, input); |
| |
| final Writer writer = new StringWriter(); |
| instance.write(writer); |
| final String result = writer.toString().trim(); |
| |
| assertEquals("Wrong content of ini file", expectedOutput, result); |
| } |
| |
| /** |
| * Test of read method with changed separator. |
| */ |
| @Test |
| public void testSeparatorUsedInINIInput() throws Exception |
| { |
| final String inputSeparator = "="; |
| final String input = "[section]" + LINE_SEPARATOR |
| + "k1:v1$key1=value1" + LINE_SEPARATOR |
| + "k1:v1,k2:v2$key2=value2" + LINE_SEPARATOR |
| + "key3:value3" + LINE_SEPARATOR |
| + "key4 = value4" + LINE_SEPARATOR; |
| |
| final INIConfiguration instance = new FileBasedConfigurationBuilder<>( |
| INIConfiguration.class) |
| .configure(new Parameters().ini().setSeparatorUsedInInput(inputSeparator)) |
| .getConfiguration(); |
| load(instance, input); |
| |
| assertEquals("value1", instance.getString("section.k1:v1$key1")); |
| assertEquals("value2", instance.getString("section.k1:v1,k2:v2$key2")); |
| assertEquals("", instance.getString("section.key3:value3")); |
| assertEquals("value4", instance.getString("section.key4").trim()); |
| } |
| |
| /** |
| * Test of read method with changed comment leading separator |
| */ |
| @Test |
| public void testCommentLeadingSeparatorUsedInINIInput() throws Exception |
| { |
| final String inputCommentLeadingSeparator = ";"; |
| final String input = "[section]" + LINE_SEPARATOR |
| + "key1=a;b;c" + LINE_SEPARATOR |
| + "key2=a#b#c" + LINE_SEPARATOR |
| + ";key3=value3" + LINE_SEPARATOR |
| + "#key4=value4" + LINE_SEPARATOR; |
| |
| final INIConfiguration instance = new FileBasedConfigurationBuilder<>( |
| INIConfiguration.class) |
| .configure(new Parameters().ini() |
| .setCommentLeadingCharsUsedInInput(inputCommentLeadingSeparator)) |
| .getConfiguration(); |
| load(instance, input); |
| |
| assertEquals("a;b;c", instance.getString("section.key1")); |
| assertEquals("a#b#c", instance.getString("section.key2")); |
| assertNull("", instance.getString("section.;key3")); |
| assertEquals("value4", instance.getString("section.#key4")); |
| } |
| |
| /** |
| * Helper method for testing a save operation. This method constructs a |
| * configuration from the specified content string. Then it saves this |
| * configuration and checks whether the result matches the original content. |
| * |
| * @param content the content of the configuration |
| * @throws ConfigurationException if an error occurs |
| */ |
| private void checkSave(final String content) throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(content); |
| final String sOutput = saveToString(config); |
| assertEquals("Wrong content of ini file", content, sOutput); |
| } |
| |
| /** |
| * Tests saving a configuration that contains a global section. |
| */ |
| @Test |
| public void testSaveWithGlobalSection() throws ConfigurationException |
| { |
| checkSave(INI_DATA_GLOBAL); |
| } |
| |
| /** |
| * Tests whether a configuration that contains only a global section can be |
| * saved correctly. |
| */ |
| @Test |
| public void testSaveWithOnlyGlobalSection() throws ConfigurationException |
| { |
| checkSave(INI_DATA_GLOBAL_ONLY); |
| } |
| |
| /** |
| * Tests whether list delimiter parsing can be disabled. |
| */ |
| @Test |
| public void testSaveWithDelimiterParsingDisabled() |
| throws ConfigurationException |
| { |
| final INIConfiguration config = new INIConfiguration(); |
| final String data = |
| INI_DATA.substring(0, INI_DATA.length() - LINE_SEPARATOR.length()) |
| + "nolist = 1,2, 3"; |
| load(config, data); |
| assertEquals("Wrong property value", "1,2, 3", |
| config.getString("section3.nolist")); |
| final String content = saveToString(config); |
| final INIConfiguration config2 = new INIConfiguration(); |
| load(config2, content); |
| assertEquals("Wrong property value after reload", "1,2, 3", |
| config2.getString("section3.nolist")); |
| } |
| |
| /** |
| * Test of load method, of class {@link INIConfiguration}. |
| */ |
| @Test |
| public void testLoad() throws Exception |
| { |
| checkLoad(INI_DATA); |
| } |
| |
| /** |
| * Tests the load() method when the alternative value separator is used (a |
| * ':' for '='). |
| */ |
| @Test |
| public void testLoadAlternativeSeparator() throws Exception |
| { |
| checkLoad(INI_DATA.replace('=', ':')); |
| } |
| |
| /** |
| * Tests whether an instance can be created using a file-based builder. |
| */ |
| @Test |
| public void testLoadFromBuilder() throws ConfigurationException, |
| IOException |
| { |
| final File file = writeTestFile(INI_DATA); |
| final FileBasedConfigurationBuilder<INIConfiguration> builder = |
| new FileBasedConfigurationBuilder<>( |
| INIConfiguration.class); |
| builder.configure(new FileBasedBuilderParametersImpl() |
| .setFile(file)); |
| final INIConfiguration config = builder.getConfiguration(); |
| checkContent(config); |
| } |
| |
| /** |
| * Tests the values of some properties to ensure that the configuration was |
| * correctly loaded. |
| * |
| * @param instance the configuration to check |
| */ |
| private void checkContent(final INIConfiguration instance) |
| { |
| assertEquals("var1", "foo", instance.getString("section1.var1")); |
| assertEquals("var2", 451, instance.getInt("section1.var2")); |
| assertEquals("section2.var1", 123.45, |
| instance.getDouble("section2.var1"), .001); |
| assertEquals("section2.var2", "bar", |
| instance.getString("section2.var2")); |
| assertEquals("section3.var1", true, |
| instance.getBoolean("section3.var1")); |
| assertEquals("Wrong number of sections", 3, instance.getSections() |
| .size()); |
| assertTrue( |
| "Wrong sections", |
| instance.getSections().containsAll( |
| Arrays.asList("section1", "section2", "section3"))); |
| } |
| |
| /** |
| * Helper method for testing the load operation. Loads the specified content |
| * into a configuration and then checks some properties. |
| * |
| * @param data the data to load |
| */ |
| private void checkLoad(final String data) throws ConfigurationException |
| { |
| final INIConfiguration instance = setUpConfig(data); |
| checkContent(instance); |
| } |
| |
| /** |
| * Test of isCommentLine method, of class |
| * {@link INIConfiguration}. |
| */ |
| @Test |
| public void testIsCommentLine() |
| { |
| final INIConfiguration instance = new INIConfiguration(); |
| assertTrue(instance.isCommentLine("#comment1")); |
| assertTrue(instance.isCommentLine(";comment1")); |
| assertFalse(instance.isCommentLine("nocomment=true")); |
| assertFalse(instance.isCommentLine(null)); |
| } |
| |
| /** |
| * Test of isSectionLine method, of class |
| * {@link INIConfiguration}. |
| */ |
| @Test |
| public void testIsSectionLine() |
| { |
| final INIConfiguration instance = new INIConfiguration(); |
| assertTrue(instance.isSectionLine("[section]")); |
| assertFalse(instance.isSectionLine("nosection=true")); |
| assertFalse(instance.isSectionLine(null)); |
| } |
| |
| /** |
| * Test of getSections method, of class {@link INIConfiguration} |
| * . |
| */ |
| @Test |
| public void testGetSections() |
| { |
| final INIConfiguration instance = new INIConfiguration(); |
| instance.addProperty("test1.foo", "bar"); |
| instance.addProperty("test2.foo", "abc"); |
| final Set<String> expResult = new HashSet<>(); |
| expResult.add("test1"); |
| expResult.add("test2"); |
| final Set<String> result = instance.getSections(); |
| assertEquals(expResult, result); |
| } |
| |
| @Test |
| public void testQuotedValue() throws Exception |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA2); |
| assertEquals("value", "quoted value", config.getString("section4.var1")); |
| } |
| |
| @Test |
| public void testQuotedValueWithQuotes() throws Exception |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA2); |
| assertEquals("value", "quoted value\\nwith \"quotes\"", config |
| .getString("section4.var2")); |
| } |
| |
| @Test |
| public void testValueWithComment() throws Exception |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA2); |
| assertEquals("value", "123", config.getString("section4.var3")); |
| } |
| |
| @Test |
| public void testQuotedValueWithComment() throws Exception |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA2); |
| assertEquals("value", "1;2;3", config.getString("section4.var4")); |
| } |
| |
| @Test |
| public void testQuotedValueWithSingleQuotes() throws Exception |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA2); |
| assertEquals("value", "'quoted' \"value\"", config |
| .getString("section4.var5")); |
| } |
| |
| @Test |
| public void testWriteValueWithCommentChar() throws Exception |
| { |
| final INIConfiguration config = new INIConfiguration(); |
| config.setProperty("section.key1", "1;2;3"); |
| |
| final StringWriter writer = new StringWriter(); |
| config.write(writer); |
| |
| final INIConfiguration config2 = new INIConfiguration(); |
| config2.read(new StringReader(writer.toString())); |
| |
| assertEquals("value", "1;2;3", config2.getString("section.key1")); |
| } |
| |
| /** |
| * Tests whether whitespace is left unchanged for quoted values. |
| */ |
| @Test |
| public void testQuotedValueWithWhitespace() throws Exception |
| { |
| final String content = "CmdPrompt = \" [test@cmd ~]$ \""; |
| final INIConfiguration config = setUpConfig(content); |
| assertEquals("Wrong propert value", " [test@cmd ~]$ ", config |
| .getString("CmdPrompt")); |
| } |
| |
| /** |
| * Tests a quoted value with space and a comment. |
| */ |
| @Test |
| public void testQuotedValueWithWhitespaceAndComment() throws Exception |
| { |
| final String content = "CmdPrompt = \" [test@cmd ~]$ \" ; a comment"; |
| final INIConfiguration config = setUpConfig(content); |
| assertEquals("Wrong propert value", " [test@cmd ~]$ ", config |
| .getString("CmdPrompt")); |
| } |
| |
| /** |
| * Tests an empty quoted value. |
| */ |
| @Test |
| public void testQuotedValueEmpty() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA2); |
| assertEquals("Wrong value for empty property", "", config |
| .getString("section4.var6")); |
| } |
| |
| /** |
| * Tests a property that has no value. |
| */ |
| @Test |
| public void testGetPropertyNoValue() throws ConfigurationException |
| { |
| final String data = INI_DATA2 + LINE_SEPARATOR + "noValue =" |
| + LINE_SEPARATOR; |
| final INIConfiguration config = setUpConfig(data); |
| assertEquals("Wrong value of key", "", config |
| .getString("section4.noValue")); |
| } |
| |
| /** |
| * Tests a property that has no key. |
| */ |
| @Test |
| public void testGetPropertyNoKey() throws ConfigurationException |
| { |
| final String data = INI_DATA2 + LINE_SEPARATOR + "= noKey" |
| + LINE_SEPARATOR; |
| final INIConfiguration config = setUpConfig(data); |
| assertEquals("Cannot find property with no key", "noKey", config |
| .getString("section4. ")); |
| } |
| |
| /** |
| * Tests reading a property from the global section. |
| */ |
| @Test |
| public void testGlobalProperty() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| assertEquals("Wrong value of global property", "testGlobal", config |
| .getString("globalVar")); |
| } |
| |
| /** |
| * Tests whether the sub configuration for the global section is connected |
| * to its parent. |
| */ |
| @Test |
| public void testGlobalSectionConnected() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| final HierarchicalConfiguration<ImmutableNode> sub = config.getSection(null); |
| config.setProperty("globalVar", "changed"); |
| assertEquals("Wrong value in sub", "changed", |
| sub.getString("globalVar")); |
| } |
| |
| /** |
| * Tests whether the specified configuration contains exactly the expected |
| * sections. |
| * |
| * @param config the configuration to check |
| * @param expected an array with the expected sections |
| */ |
| private void checkSectionNames(final INIConfiguration config, |
| final String[] expected) |
| { |
| final Set<String> sectionNames = config.getSections(); |
| final Iterator<String> it = sectionNames.iterator(); |
| for (int idx = 0; idx < expected.length; idx++) |
| { |
| assertEquals("Wrong section at " + idx, expected[idx], it.next()); |
| } |
| assertFalse("Too many sections", it.hasNext()); |
| } |
| |
| /** |
| * Tests the names of the sections returned by the configuration. |
| * |
| * @param data the data of the ini configuration |
| * @param expected the expected section names |
| * @return the configuration instance |
| */ |
| private INIConfiguration checkSectionNames(final String data, |
| final String[] expected) throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(data); |
| checkSectionNames(config, expected); |
| return config; |
| } |
| |
| /** |
| * Tests querying the sections if a global section if available. |
| */ |
| @Test |
| public void testGetSectionsWithGlobal() throws ConfigurationException |
| { |
| checkSectionNames(INI_DATA_GLOBAL, new String[]{ |
| null, "section1", "section2", "section3" |
| }); |
| } |
| |
| /** |
| * Tests querying the sections if there is no global section. |
| */ |
| @Test |
| public void testGetSectionsNoGlobal() throws ConfigurationException |
| { |
| checkSectionNames(INI_DATA, new String[]{ |
| "section1", "section2", "section3" |
| }); |
| } |
| |
| /** |
| * Tests whether the sections of a configuration can be queried that |
| * contains only a global section. |
| */ |
| @Test |
| public void testGetSectionsGlobalOnly() throws ConfigurationException |
| { |
| checkSectionNames(INI_DATA_GLOBAL_ONLY, new String[]{ |
| null |
| }); |
| } |
| |
| /** |
| * Tests whether variables containing a dot are not misinterpreted as |
| * sections. This test is related to CONFIGURATION-327. |
| */ |
| @Test |
| public void testGetSectionsDottedVar() throws ConfigurationException |
| { |
| final String data = "dotted.var = 1" + LINE_SEPARATOR + INI_DATA_GLOBAL; |
| final INIConfiguration config = checkSectionNames(data, |
| new String[] { |
| null, "section1", "section2", "section3" |
| }); |
| assertEquals("Wrong value of dotted variable", 1, config |
| .getInt("dotted..var")); |
| } |
| |
| /** |
| * Tests whether a section added later is also found by getSections(). |
| */ |
| @Test |
| public void testGetSectionsAdded() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA2); |
| config.addProperty("section5.test", Boolean.TRUE); |
| checkSectionNames(config, new String[]{ |
| "section4", "section5" |
| }); |
| } |
| |
| /** |
| * Tests querying the properties of an existing section. |
| */ |
| @Test |
| public void testGetSectionExisting() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA); |
| final HierarchicalConfiguration<ImmutableNode> section = |
| config.getSection("section1"); |
| assertEquals("Wrong value of var1", "foo", section.getString("var1")); |
| assertEquals("Wrong value of var2", "451", section.getString("var2")); |
| } |
| |
| /** |
| * Tests whether the sub configuration returned by getSection() is connected |
| * to the parent. |
| */ |
| @Test |
| public void testGetSectionConnected() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA); |
| final HierarchicalConfiguration<ImmutableNode> section = |
| config.getSection("section1"); |
| section.setProperty("var1", "foo2"); |
| assertEquals("Not connected to parent", "foo2", |
| config.getString("section1.var1")); |
| } |
| |
| /** |
| * Tests querying the properties of a section that was merged from two |
| * sections with the same name. |
| */ |
| @Test |
| public void testGetSectionMerged() throws ConfigurationException |
| { |
| final String data = INI_DATA + "[section1]" + LINE_SEPARATOR |
| + "var3 = merged" + LINE_SEPARATOR; |
| final INIConfiguration config = setUpConfig(data); |
| final HierarchicalConfiguration<ImmutableNode> section = config.getSection("section1"); |
| assertEquals("Wrong value of var1", "foo", section.getString("var1")); |
| assertEquals("Wrong value of var2", "451", section.getString("var2")); |
| assertEquals("Wrong value of var3", "merged", section.getString("var3")); |
| } |
| |
| /** |
| * Tests querying the content of the global section. |
| */ |
| @Test |
| public void testGetSectionGlobal() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| final HierarchicalConfiguration<ImmutableNode> section = config.getSection(null); |
| assertEquals("Wrong value of global variable", "testGlobal", section |
| .getString("globalVar")); |
| } |
| |
| /** |
| * Tests concurrent access to the global section. |
| */ |
| @Test |
| public void testGetSectionGloabalMultiThreaded() |
| throws ConfigurationException, InterruptedException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| config.setSynchronizer(new ReadWriteSynchronizer()); |
| final int threadCount = 10; |
| final GlobalSectionTestThread[] threads = new GlobalSectionTestThread[threadCount]; |
| for (int i = 0; i < threadCount; i++) |
| { |
| threads[i] = new GlobalSectionTestThread(config); |
| threads[i].start(); |
| } |
| for (int i = 0; i < threadCount; i++) |
| { |
| threads[i].join(); |
| assertFalse("Exception occurred", threads[i].error); |
| } |
| } |
| |
| /** |
| * Tests querying the content of the global section if there is none. |
| */ |
| @Test |
| public void testGetSectionGlobalNonExisting() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA); |
| final HierarchicalConfiguration<ImmutableNode> section = config.getSection(null); |
| assertTrue("Sub config not empty", section.isEmpty()); |
| } |
| |
| /** |
| * Tests querying a non existing section. |
| */ |
| @Test |
| public void testGetSectionNonExisting() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA); |
| final HierarchicalConfiguration<ImmutableNode> section = config |
| .getSection("Non existing section"); |
| assertTrue("Sub config not empty", section.isEmpty()); |
| } |
| |
| /** |
| * Tests a property whose value spans multiple lines. |
| */ |
| @Test |
| public void testLineContinuation() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA3); |
| assertEquals("Wrong value", "one" + LINE_SEPARATOR + "two" |
| + LINE_SEPARATOR + "three", config |
| .getString("section5.multiLine")); |
| } |
| |
| /** |
| * Tests a property value that ends on a backslash, which is no line |
| * continuation character. |
| */ |
| @Test |
| public void testLineContinuationNone() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA3); |
| assertEquals("Wrong value", "C:\\Temp\\", config |
| .getString("section5.singleLine")); |
| } |
| |
| /** |
| * Tests a property whose value spans multiple lines when quoting is |
| * involved. In this case whitespace must not be trimmed. |
| */ |
| @Test |
| public void testLineContinuationQuoted() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA3); |
| assertEquals("Wrong value", "one" + LINE_SEPARATOR + " two " |
| + LINE_SEPARATOR + "three", config |
| .getString("section5.multiQuoted")); |
| } |
| |
| /** |
| * Tests a property whose value spans multiple lines with a comment. |
| */ |
| @Test |
| public void testLineContinuationComment() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA3); |
| assertEquals("Wrong value", "one" + LINE_SEPARATOR + "two", config |
| .getString("section5.multiComment")); |
| } |
| |
| /** |
| * Tests a property with a quoted value spanning multiple lines and a |
| * comment. |
| */ |
| @Test |
| public void testLineContinuationQuotedComment() |
| throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA3); |
| assertEquals("Wrong value", " one " + LINE_SEPARATOR + "two", config |
| .getString("section5.multiQuotedComment")); |
| } |
| |
| /** |
| * Tests a multi-line property value with an empty line. |
| */ |
| @Test |
| public void testLineContinuationEmptyLine() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA3); |
| assertEquals("Wrong value", LINE_SEPARATOR + "line 2", config |
| .getString("section5.noFirstLine")); |
| } |
| |
| /** |
| * Tests a line continuation at the end of the file. |
| */ |
| @Test |
| public void testLineContinuationAtEnd() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA3); |
| assertEquals("Wrong value", "one" + LINE_SEPARATOR, config |
| .getString("section5.continueNoLine")); |
| } |
| |
| /** |
| * Tests whether a configuration can be saved that contains section keys |
| * with delimiter characters. This test is related to CONFIGURATION-409. |
| */ |
| @Test |
| public void testSaveKeysWithDelimiters() throws ConfigurationException, IOException |
| { |
| INIConfiguration conf = new INIConfiguration(); |
| final String section = "Section..with..dots"; |
| conf.addProperty(section + ".test1", "test1"); |
| conf.addProperty(section + ".test2", "test2"); |
| final StringWriter writer = new StringWriter(); |
| conf.write(writer); |
| conf = new INIConfiguration(); |
| conf.read(new StringReader(writer.toString())); |
| assertEquals("Wrong value (1)", "test1", conf.getString(section + ".test1")); |
| assertEquals("Wrong value (2)", "test2", conf.getString(section + ".test2")); |
| } |
| |
| /** |
| * Tests that loading and saving a configuration that contains keys with |
| * delimiter characters works correctly. This test is related to |
| * CONFIGURATION-622. |
| */ |
| @Test |
| public void testPropertyWithDelimiter() throws ConfigurationException |
| { |
| final String data = INI_DATA + "key.dot = dotValue"; |
| final INIConfiguration conf = new INIConfiguration(); |
| load(conf, data); |
| assertEquals("Wrong property value", "dotValue", |
| conf.getString("section3.key..dot")); |
| final String output = saveToString(conf); |
| assertThat(output, containsString("key.dot = dotValue")); |
| } |
| |
| /** |
| * Tests whether a value which contains a semicolon can be loaded |
| * successfully. This test is related to CONFIGURATION-434. |
| */ |
| @Test |
| public void testValueWithSemicolon() throws ConfigurationException |
| { |
| final String path = |
| "C:\\Program Files\\jar\\manage.jar;" |
| + "C:\\Program Files\\jar\\guiLauncher.jar"; |
| final String content = |
| "[Environment]" + LINE_SEPARATOR + "Application Type=any" |
| + LINE_SEPARATOR + "Class Path=" + path + " ;comment" |
| + LINE_SEPARATOR + "Path=" + path |
| + "\t; another comment"; |
| final INIConfiguration config = setUpConfig(content); |
| assertEquals("Wrong class path", path, |
| config.getString("Environment.Class Path")); |
| assertEquals("Wrong path", path, config.getString("Environment.Path")); |
| } |
| |
| /** |
| * Tests whether the different separators with or without whitespace are |
| * recognized. |
| */ |
| @Test |
| public void testSeparators() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_SEPARATORS); |
| for (int i = 1; i <= 4; i++) |
| { |
| assertEquals("Wrong value", "value" + i, |
| config.getString("section.var" + i)); |
| } |
| } |
| |
| /** |
| * Tests property definitions containing multiple separators. |
| */ |
| @Test |
| public void testMultipleSeparators() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_SEPARATORS); |
| assertEquals("Wrong value for var5", "value=5", |
| config.getString("section.var5")); |
| assertEquals("Wrong value for var6", "6=value", |
| config.getString("section.var")); |
| } |
| |
| /** |
| * Tests property definitions containing multiple separators that are |
| * quoted. |
| */ |
| @Test |
| public void testMultipleSeparatorsQuoted() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_SEPARATORS); |
| assertEquals("Wrong value for var7", "value7", |
| config.getString("section.var:7")); |
| assertEquals("Wrong value for var8", "value8", |
| config.getString("section.var:8")); |
| } |
| |
| /** |
| * Tests whether a section that has been cleared can be manipulated and |
| * saved later. |
| */ |
| @Test |
| public void testSaveClearedSection() throws ConfigurationException, IOException |
| { |
| final String data = "[section]\ntest = failed\n"; |
| final INIConfiguration config = setUpConfig(data); |
| SubnodeConfiguration sub = config.getSection("section"); |
| assertFalse("No content", sub.isEmpty()); |
| sub.clear(); |
| sub.close(); |
| sub = config.getSection("section"); |
| sub.setProperty("test", "success"); |
| final StringWriter writer = new StringWriter(); |
| config.write(writer); |
| final HierarchicalConfiguration<?> config2 = setUpConfig(writer.toString()); |
| assertEquals("Wrong value", "success", |
| config2.getString("section.test")); |
| } |
| |
| /** |
| * Tests whether a duplicate session is merged. |
| */ |
| @Test |
| public void testMergeDuplicateSection() throws ConfigurationException, IOException |
| { |
| final String data = |
| "[section]\nvar1 = sec1\n\n" + "[section]\nvar2 = sec2\n"; |
| final INIConfiguration config = setUpConfig(data); |
| assertEquals("Wrong value 1", "sec1", config.getString("section.var1")); |
| assertEquals("Wrong value 2", "sec2", config.getString("section.var2")); |
| final HierarchicalConfiguration<ImmutableNode> sub = config.getSection("section"); |
| assertEquals("Wrong sub value 1", "sec1", sub.getString("var1")); |
| assertEquals("Wrong sub value 2", "sec2", sub.getString("var2")); |
| final StringWriter writer = new StringWriter(); |
| config.write(writer); |
| final String content = writer.toString(); |
| final int pos = content.indexOf("[section]"); |
| assertTrue("Section not found: " + content, pos >= 0); |
| assertTrue("Section found multiple times: " + content, |
| content.indexOf("[section]", pos + 1) < 0); |
| } |
| |
| /** |
| * Tests whether a section that was created by getSection() can be |
| * manipulated. |
| */ |
| @Test |
| public void testGetSectionNonExistingManipulate() |
| throws ConfigurationException, IOException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA); |
| HierarchicalConfiguration<ImmutableNode> section = config.getSection("newSection"); |
| section.addProperty("test", "success"); |
| assertEquals("Main config not updated", "success", |
| config.getString("newSection.test")); |
| final StringWriter writer = new StringWriter(); |
| config.write(writer); |
| final INIConfiguration config2 = setUpConfig(writer.toString()); |
| section = config2.getSection("newSection"); |
| assertEquals("Wrong value", "success", section.getString("test")); |
| } |
| |
| /** |
| * Tests whether getSection() can deal with duplicate sections. |
| */ |
| @Test |
| public void testGetSectionDuplicate() |
| { |
| final INIConfiguration config = |
| new INIConfiguration(); |
| config.addProperty("section.var1", "value1"); |
| config.addProperty("section(-1).var2", "value2"); |
| final HierarchicalConfiguration<ImmutableNode> section = config.getSection("section"); |
| final Iterator<String> keys = section.getKeys(); |
| assertEquals("Wrong key", "var1", keys.next()); |
| assertFalse("Too many keys", keys.hasNext()); |
| } |
| |
| /** |
| * Tests whether the list delimiter character is recognized. |
| */ |
| @Test |
| public void testValueWithDelimiters() throws ConfigurationException |
| { |
| final INIConfiguration config = |
| setUpConfig("[test]" + LINE_SEPARATOR + "list=1,2,3" |
| + LINE_SEPARATOR); |
| final List<Object> list = config.getList("test.list"); |
| assertEquals("Wrong number of elements", 3, list.size()); |
| assertEquals("Wrong element at 1", "1", list.get(0)); |
| assertEquals("Wrong element at 2", "2", list.get(1)); |
| assertEquals("Wrong element at 3", "3", list.get(2)); |
| } |
| |
| /** |
| * Tests whether parsing of lists can be disabled. |
| */ |
| @Test |
| public void testListParsingDisabled() throws ConfigurationException |
| { |
| final INIConfiguration config = |
| new INIConfiguration(); |
| load(config, "[test]" + LINE_SEPARATOR + "nolist=1,2,3"); |
| assertEquals("Wrong value", "1,2,3", config.getString("test.nolist")); |
| } |
| |
| /** |
| * Tests whether synchronization is performed when querying the |
| * configuration's sections. |
| */ |
| @Test |
| public void testGetSectionsSynchronized() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA); |
| final SynchronizerTestImpl sync = new SynchronizerTestImpl(); |
| config.setSynchronizer(sync); |
| assertFalse("No sections", config.getSections().isEmpty()); |
| sync.verify(Methods.BEGIN_READ, Methods.END_READ); |
| } |
| |
| /** |
| * Tests whether the configuration deals correctly with list delimiters. |
| */ |
| @Test |
| public void testListDelimiterHandling() throws ConfigurationException |
| { |
| final INIConfiguration config = new INIConfiguration(); |
| config.setListDelimiterHandler(new DefaultListDelimiterHandler(',')); |
| config.addProperty("list", "a,b,c"); |
| config.addProperty("listesc", "3\\,1415"); |
| final String output = saveToString(config); |
| final INIConfiguration config2 = setUpConfig(output); |
| assertEquals("Wrong list size", 3, config2.getList("list").size()); |
| assertEquals("Wrong list element", "b", config2.getList("list").get(1)); |
| assertEquals("Wrong escaped list element", "3,1415", |
| config2.getString("listesc")); |
| } |
| |
| /** |
| * Tests whether property values are correctly escaped even if they are part |
| * of a property with multiple values. |
| */ |
| @Test |
| public void testListDelimiterHandlingInList() throws ConfigurationException |
| { |
| final String data = |
| INI_DATA + "[sectest]" + LINE_SEPARATOR |
| + "list = 3\\,1415,pi,\\\\Test\\,5" + LINE_SEPARATOR; |
| final INIConfiguration config = setUpConfig(data); |
| final INIConfiguration config2 = setUpConfig(saveToString(config)); |
| final List<Object> list = config2.getList("sectest.list"); |
| assertEquals("Wrong number of values", 3, list.size()); |
| assertEquals("Wrong element 1", "3,1415", list.get(0)); |
| assertEquals("Wrong element 3", "\\Test,5", list.get(2)); |
| } |
| |
| /** |
| * Tests whether only properties with values occur in the enumeration of the |
| * global section. |
| */ |
| @Test |
| public void testKeysOfGlobalSection() throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| final HierarchicalConfiguration<ImmutableNode> sub = config.getSection(null); |
| final Iterator<String> keys = sub.getKeys(); |
| assertEquals("Wrong key", "globalVar", keys.next()); |
| if (keys.hasNext()) |
| { |
| final StringBuilder buf = new StringBuilder(); |
| do |
| { |
| buf.append(keys.next()).append(' '); |
| } while (keys.hasNext()); |
| fail("Got additional keys: " + buf); |
| } |
| } |
| |
| /** |
| * Tests whether the node handler of a global section correctly filters |
| * named children. |
| */ |
| @Test |
| public void testGlobalSectionNodeHandlerGetChildrenByName() |
| throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| final SubnodeConfiguration sub = config.getSection(null); |
| final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler(); |
| assertTrue( |
| "Sections not filtered", |
| handler.getChildren( |
| sub.getModel().getNodeHandler().getRootNode(), |
| "section1").isEmpty()); |
| } |
| |
| /** |
| * Tests whether the node handler of a global section correctly determines |
| * the number of children. |
| */ |
| @Test |
| public void testGlobalSectionNodeHandlerGetChildrenCount() |
| throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| final SubnodeConfiguration sub = config.getSection(null); |
| final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler(); |
| assertEquals("Wrong number of children", 1, |
| handler.getChildrenCount(handler.getRootNode(), null)); |
| } |
| |
| /** |
| * Tests whether the node handler of a global section correctly returns a |
| * child by index. |
| */ |
| @Test |
| public void testGlobalSectionNodeHandlerGetChildByIndex() |
| throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| final SubnodeConfiguration sub = config.getSection(null); |
| final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler(); |
| final ImmutableNode child = handler.getChild(handler.getRootNode(), 0); |
| assertEquals("Wrong child", "globalVar", child.getNodeName()); |
| try |
| { |
| handler.getChild(handler.getRootNode(), 1); |
| fail("Could obtain child with invalid index!"); |
| } |
| catch (final IndexOutOfBoundsException iex) |
| { |
| // ok |
| } |
| } |
| |
| /** |
| * Tests whether the node handler of a global section correctly determines |
| * the index of a child. |
| */ |
| @Test |
| public void testGlobalSectionNodeHandlerIndexOfChild() |
| throws ConfigurationException |
| { |
| final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL); |
| final SubnodeConfiguration sub = config.getSection(null); |
| final NodeHandler<ImmutableNode> handler = sub.getModel().getNodeHandler(); |
| final List<ImmutableNode> children = handler.getRootNode().getChildren(); |
| assertEquals("Wrong index", 0, |
| handler.indexOfChild(handler.getRootNode(), children.get(0))); |
| assertEquals("Wrong index of section child", -1, |
| handler.indexOfChild(handler.getRootNode(), children.get(1))); |
| } |
| |
| /** |
| * Tests whether an expression engine can be used which ignores case. |
| */ |
| @Test |
| public void testExpressionEngineIgnoringCase() |
| throws ConfigurationException |
| { |
| final DefaultExpressionEngine engine = |
| new DefaultExpressionEngine( |
| DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS, |
| NodeNameMatchers.EQUALS_IGNORE_CASE); |
| final INIConfiguration config = new INIConfiguration(); |
| config.setExpressionEngine(engine); |
| load(config, INI_DATA); |
| |
| checkContent(config); |
| assertEquals("Wrong result (1)", "foo", |
| config.getString("Section1.var1")); |
| assertEquals("Wrong result (2)", "foo", |
| config.getString("section1.Var1")); |
| assertEquals("Wrong result (1)", "foo", |
| config.getString("SECTION1.VAR1")); |
| } |
| |
| /** |
| * Tests whether an empty section can be saved. This is related to |
| * CONFIGURATION-671. |
| */ |
| @Test |
| public void testWriteEmptySection() |
| throws ConfigurationException, IOException |
| { |
| final String section = "[EmptySection]"; |
| final INIConfiguration config = setUpConfig(section); |
| assertEquals("Wrong number of sections", 1, |
| config.getSections().size()); |
| assertTrue("Section not found", |
| config.getSections().contains("EmptySection")); |
| |
| final StringWriter writer = new StringWriter(); |
| config.write(writer); |
| assertEquals("Wrong saved configuration", |
| section + LINE_SEPARATOR + LINE_SEPARATOR, writer.toString()); |
| } |
| |
| /** |
| * A thread class for testing concurrent access to the global section. |
| */ |
| private static class GlobalSectionTestThread extends Thread |
| { |
| /** The configuration. */ |
| private final INIConfiguration config; |
| |
| /** A flag whether an error was found. */ |
| volatile boolean error; |
| |
| /** |
| * Creates a new instance of {@code GlobalSectionTestThread} and |
| * initializes it. |
| * |
| * @param conf the configuration object |
| */ |
| public GlobalSectionTestThread(final INIConfiguration conf) |
| { |
| config = conf; |
| } |
| |
| /** |
| * Accesses the global section in a loop. If there is no correct |
| * synchronization, this can cause an exception. |
| */ |
| @Override |
| public void run() |
| { |
| final int loopCount = 250; |
| |
| for (int i = 0; i < loopCount && !error; i++) |
| { |
| try |
| { |
| config.getSection(null); |
| } |
| catch (final IllegalStateException istex) |
| { |
| error = true; |
| } |
| } |
| } |
| } |
| } |