blob: c2ea77e34fa3d18baaebcef1aa37e4adfc1bbc8c [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.plist;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.StringReader;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import junitx.framework.ArrayAssert;
import junitx.framework.ListAssert;
import junitx.framework.ObjectAssert;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ConfigurationAssert;
import org.apache.commons.configuration2.ConfigurationComparator;
import org.apache.commons.configuration2.HierarchicalConfiguration;
import org.apache.commons.configuration2.StrictConfigurationComparator;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.io.FileHandler;
import org.apache.commons.configuration2.tree.ImmutableNode;
import org.apache.commons.configuration2.tree.NodeHandler;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
/**
*/
public class TestPropertyListConfiguration
{
/** A helper object for dealing with temporary files. */
@Rule
public TemporaryFolder folder = new TemporaryFolder();
private PropertyListConfiguration config;
private final File testProperties = ConfigurationAssert.getTestFile("test.plist");
@Before
public void setUp() throws Exception
{
config = new PropertyListConfiguration();
load(config, testProperties);
}
/**
* Loads a configuration from the specified test file.
*
* @param c the configuration to be loaded
* @param f the file to be loaded
* @throws ConfigurationException if an error occurs
*/
private static void load(final PropertyListConfiguration c, final File f)
throws ConfigurationException
{
new FileHandler(c).load(f);
}
@Test
public void testLoad()
{
assertFalse("the configuration is empty", config.isEmpty());
}
@Test
public void testLoadWithError()
{
config = new PropertyListConfiguration();
try {
new FileHandler(config).load(new StringReader(""));
fail("No exception thrown on loading an empty file");
} catch (final ConfigurationException e) {
// expected
assertNotNull(e.getMessage());
}
}
@Test
public void testString()
{
assertEquals("simple-string", "string1", config.getProperty("simple-string"));
}
@Test
public void testQuotedString()
{
assertEquals("quoted-string", "string2", config.getProperty("quoted-string"));
assertEquals("quoted-string2", "this is a string", config.getProperty("quoted-string2"));
assertEquals("complex-string", "this is a \"complex\" string {(=,;)}", config.getProperty("complex-string"));
}
@Test
public void testEmptyArray()
{
final String key = "empty-array";
assertNotNull("array null", config.getProperty(key));
final List<?> list = (List<?>) config.getProperty(key);
assertTrue("array is not empty", list.isEmpty());
}
@Test
public void testArray()
{
final String key = "array";
assertNotNull("array null", config.getProperty(key));
final List<?> list = (List<?>) config.getProperty(key);
assertFalse("array is empty", list.isEmpty());
assertEquals("1st value", "value1", list.get(0));
assertEquals("2nd value", "value2", list.get(1));
assertEquals("3rd value", "value3", list.get(2));
}
@Test
public void testNestedArrays()
{
final String key = "nested-arrays";
final Object array = config.getProperty(key);
// root array
assertNotNull("array not found", array);
ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, array);
final List<?> list = config.getList(key);
assertFalse("empty array", list.isEmpty());
assertEquals("size", 2, list.size());
// 1st array
ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, list.get(0));
final List<?> list1 = (List<?>) list.get(0);
assertFalse("nested array 1 is empty", list1.isEmpty());
assertEquals("size", 2, list1.size());
assertEquals("1st element", "a", list1.get(0));
assertEquals("2nd element", "b", list1.get(1));
// 2nd array
ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, list.get(1));
final List<?> list2 = (List<?>) list.get(1);
assertFalse("nested array 2 is empty", list2.isEmpty());
assertEquals("size", 2, list2.size());
assertEquals("1st element", "c", list2.get(0));
assertEquals("2nd element", "d", list2.get(1));
}
@Test
public void testDictionary()
{
assertEquals("1st element in dictionary", "bar1", config.getProperty("dictionary.foo1"));
assertEquals("2nd element in dictionary", "bar2", config.getProperty("dictionary.foo2"));
}
@Test
public void testDictionaryArray()
{
final String key = "dictionary-array";
final Object array = config.getProperty(key);
// root array
assertNotNull("array not found", array);
ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, array);
final List<?> list = config.getList(key);
assertFalse("empty array", list.isEmpty());
assertEquals("size", 2, list.size());
// 1st dictionary
ObjectAssert.assertInstanceOf("the dict element is not parsed as a Configuration", Configuration.class, list.get(0));
final Configuration conf1 = (Configuration) list.get(0);
assertFalse("configuration 1 is empty", conf1.isEmpty());
assertEquals("configuration element", "bar", conf1.getProperty("foo"));
// 2nd dictionary
ObjectAssert.assertInstanceOf("the dict element is not parsed as a Configuration", Configuration.class, list.get(1));
final Configuration conf2 = (Configuration) list.get(1);
assertFalse("configuration 2 is empty", conf2.isEmpty());
assertEquals("configuration element", "value", conf2.getProperty("key"));
}
@Test
public void testNestedDictionaries()
{
assertEquals("nested property", "value", config.getString("nested-dictionaries.foo.bar.key"));
}
@Test
public void testData()
{
ObjectAssert.assertInstanceOf("data", ArrayUtils.EMPTY_BYTE_ARRAY.getClass(), config.getProperty("data"));
ArrayAssert.assertEquals("data", "foo bar".getBytes(), (byte[]) config.getProperty("data"));
}
@Test
public void testDate() throws Exception
{
final Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2002, Calendar.MARCH, 22, 11, 30, 0);
cal.setTimeZone(TimeZone.getTimeZone("GMT+0100"));
final Date date = cal.getTime();
assertEquals("date", date, config.getProperty("date"));
}
/**
* Saves the test configuration to the specified file.
*
* @param file the target file
* @throws ConfigurationException if an error occurs
*/
private void saveConfig(final File file) throws ConfigurationException
{
new FileHandler(config).save(file);
}
@Test
public void testSave() throws Exception
{
final File savedFile = folder.newFile("testsave.plist");
// save the configuration
saveConfig(savedFile);
assertTrue("The saved file doesn't exist", savedFile.exists());
// read the configuration and compare the properties
final PropertyListConfiguration checkConfig = new PropertyListConfiguration();
load(checkConfig, savedFile);
final Iterator<String> it = config.getKeys();
while (it.hasNext())
{
final String key = it.next();
assertTrue("The saved configuration doesn't contain the key '" + key + "'", checkConfig.containsKey(key));
final Object value = checkConfig.getProperty(key);
if (value instanceof byte[])
{
final byte[] array = (byte[]) value;
ArrayAssert.assertEquals("Value of the '" + key + "' property", (byte[]) config.getProperty(key), array);
}
else if (value instanceof List)
{
final List<?> list1 = (List<?>) config.getProperty(key);
final List<?> list2 = (List<?>) value;
assertEquals("The size of the list for the key '" + key + "' doesn't match", list1.size(), list2.size());
for (int i = 0; i < list2.size(); i++)
{
final Object value1 = list1.get(i);
final Object value2 = list2.get(i);
if (value1 instanceof Configuration)
{
final ConfigurationComparator comparator = new StrictConfigurationComparator();
assertTrue("The dictionnary at index " + i + " for the key '" + key + "' doesn't match", comparator.compare((Configuration) value1, (Configuration) value2));
}
else
{
assertEquals("Element at index " + i + " for the key '" + key + "'", value1, value2);
}
}
ListAssert.assertEquals("Value of the '" + key + "' property", (List<?>) config.getProperty(key), list1);
}
else
{
assertEquals("Value of the '" + key + "' property", config.getProperty(key), checkConfig.getProperty(key));
}
}
}
@Test
public void testSaveEmptyDictionary() throws Exception
{
final File savedFile = folder.newFile("testsave.plist");
// save the configuration
saveConfig(savedFile);
assertTrue("The saved file doesn't exist", savedFile.exists());
// read the configuration and compare the properties
final PropertyListConfiguration checkConfig = new PropertyListConfiguration();
load(checkConfig, savedFile);
assertFalse(getNamedChildren(config, "empty-dictionary").isEmpty());
assertFalse(getNamedChildren(checkConfig, "empty-dictionary").isEmpty());
}
/**
* Returns a list with the children of the given configuration's root note
* with the specified name.
*
* @param config the configuration
* @param name the name of the desired children
* @return the list with the corresponding child nodes
*/
private static List<ImmutableNode> getNamedChildren(
final HierarchicalConfiguration<ImmutableNode> config, final String name)
{
final NodeHandler<ImmutableNode> handler =
config.getNodeModel().getNodeHandler();
return handler.getChildren(handler.getRootNode(), name);
}
@Test
public void testQuoteString()
{
assertEquals("null string", null, config.quoteString(null));
assertEquals("simple string", "abcd", config.quoteString("abcd"));
assertEquals("string with a space", "\"ab cd\"", config.quoteString("ab cd"));
assertEquals("string with a quote", "\"foo\\\"bar\"", config.quoteString("foo\"bar"));
assertEquals("string with a special char", "\"foo;bar\"", config.quoteString("foo;bar"));
}
/**
* Ensure that setProperty doesn't alter an array of byte
* since it's a first class type in plist file
*/
@Test
public void testSetDataProperty() throws Exception
{
final File saveFile = folder.newFile();
final byte[] expected = new byte[]{1, 2, 3, 4};
config = new PropertyListConfiguration();
config.setProperty("foo", expected);
saveConfig(saveFile);
final PropertyListConfiguration config2 = new PropertyListConfiguration();
load(config2, saveFile);
final Object array = config2.getProperty("foo");
assertNotNull("data not found", array);
assertEquals("property type", byte[].class, array.getClass());
ArrayAssert.assertEquals(expected, (byte[]) array);
}
/**
* Ensure that addProperty doesn't alter an array of byte
*/
@Test
public void testAddDataProperty() throws Exception
{
final File saveFile = folder.newFile();
final byte[] expected = new byte[]{1, 2, 3, 4};
config = new PropertyListConfiguration();
config.addProperty("foo", expected);
saveConfig(saveFile);
final PropertyListConfiguration config2 = new PropertyListConfiguration();
load(config2, saveFile);
final Object array = config2.getProperty("foo");
assertNotNull("data not found", array);
assertEquals("property type", byte[].class, array.getClass());
ArrayAssert.assertEquals(expected, (byte[]) array);
}
@Test
public void testInitCopy()
{
final PropertyListConfiguration copy = new PropertyListConfiguration(config);
assertFalse("Nothing was copied", copy.isEmpty());
}
/**
* Tests parsing a date with an invalid numeric value.
*/
@Test(expected = ParseException.class)
public void testParseDateNoNumber() throws ParseException
{
PropertyListConfiguration
.parseDate("<*D2002-03-22 1c:30:00 +0100>");
}
/**
* Tests parsing a date that is not long enough.
*/
@Test(expected = ParseException.class)
public void testParseDateTooShort() throws ParseException
{
PropertyListConfiguration.parseDate("<*D2002-03-22 11:3>");
}
/**
* Tests parsing a date that contains an invalid separator character.
*/
@Test(expected = ParseException.class)
public void testParseDateInvalidChar() throws ParseException
{
PropertyListConfiguration
.parseDate("<*D2002+03-22 11:30:00 +0100>");
}
/**
* Tries parsing a null date. This should cause an exception.n
*/
@Test(expected = ParseException.class)
public void testParseDateNull() throws ParseException
{
PropertyListConfiguration.parseDate(null);
}
/**
* Tests formatting a date.
*/
@Test
public void testFormatDate()
{
final Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2007, Calendar.OCTOBER, 29, 23, 4, 30);
cal.setTimeZone(TimeZone.getTimeZone("GMT-0230"));
assertEquals("Wrong date literal (1)", "<*D2007-10-29 23:04:30 -0230>",
PropertyListConfiguration.formatDate(cal));
cal.clear();
cal.set(2007, Calendar.OCTOBER, 30, 22, 2, 15);
cal.setTimeZone(TimeZone.getTimeZone("GMT+1111"));
assertEquals("Wrong date literal (2)", "<*D2007-10-30 22:02:15 +1111>",
PropertyListConfiguration.formatDate(cal));
}
}