001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.configuration.plist;
019    
020    import static org.junit.Assert.assertEquals;
021    import static org.junit.Assert.assertFalse;
022    import static org.junit.Assert.assertNotNull;
023    import static org.junit.Assert.assertTrue;
024    import static org.junit.Assert.fail;
025    
026    import java.io.File;
027    import java.io.StringReader;
028    import java.util.Calendar;
029    import java.util.Date;
030    import java.util.Iterator;
031    import java.util.List;
032    import java.util.TimeZone;
033    
034    import junitx.framework.ArrayAssert;
035    import junitx.framework.ListAssert;
036    import junitx.framework.ObjectAssert;
037    
038    import org.apache.commons.configuration.Configuration;
039    import org.apache.commons.configuration.ConfigurationAssert;
040    import org.apache.commons.configuration.ConfigurationComparator;
041    import org.apache.commons.configuration.ConfigurationException;
042    import org.apache.commons.configuration.StrictConfigurationComparator;
043    import org.junit.Before;
044    import org.junit.Test;
045    
046    /**
047     * @author Emmanuel Bourg
048     * @version $Id: TestPropertyListConfiguration.java 1225902 2011-12-30 19:46:24Z oheger $
049     */
050    public class TestPropertyListConfiguration
051    {
052        private PropertyListConfiguration config;
053    
054        private String testProperties = ConfigurationAssert.getTestFile("test.plist").getAbsolutePath();
055    
056        @Before
057        public void setUp() throws Exception
058        {
059            config = new PropertyListConfiguration();
060            config.setFileName(testProperties);
061            config.load();
062        }
063    
064        @Test
065        public void testLoad()
066        {
067            assertFalse("the configuration is empty", config.isEmpty());
068        }
069    
070        @Test
071        public void testLoadWithError()
072        {
073            config = new PropertyListConfiguration();
074            try {
075                config.load(new StringReader(""));
076                fail("No exception thrown on loading an empty file");
077            } catch (ConfigurationException e) {
078                // expected
079                assertNotNull(e.getMessage());
080            }
081        }
082    
083        @Test
084        public void testString()
085        {
086            assertEquals("simple-string", "string1", config.getProperty("simple-string"));
087        }
088    
089        @Test
090        public void testQuotedString()
091        {
092            assertEquals("quoted-string", "string2", config.getProperty("quoted-string"));
093            assertEquals("quoted-string2", "this is a string", config.getProperty("quoted-string2"));
094            assertEquals("complex-string", "this is a \"complex\" string {(=,;)}", config.getProperty("complex-string"));
095        }
096    
097        @Test
098        public void testEmptyArray()
099        {
100            String key = "empty-array";
101            assertNotNull("array null", config.getProperty(key));
102    
103            List<?> list = (List<?>) config.getProperty(key);
104            assertTrue("array is not empty", list.isEmpty());
105        }
106    
107        @Test
108        public void testArray()
109        {
110            String key = "array";
111            assertNotNull("array null", config.getProperty(key));
112    
113            List<?> list = (List<?>) config.getProperty(key);
114            assertFalse("array is empty", list.isEmpty());
115    
116            assertEquals("1st value", "value1", list.get(0));
117            assertEquals("2nd value", "value2", list.get(1));
118            assertEquals("3rd value", "value3", list.get(2));
119        }
120    
121        @Test
122        public void testNestedArrays()
123        {
124            String key = "nested-arrays";
125    
126            Object array = config.getProperty(key);
127    
128            // root array
129            assertNotNull("array not found", array);
130            ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, array);
131            List<?> list = config.getList(key);
132    
133            assertFalse("empty array", list.isEmpty());
134            assertEquals("size", 2, list.size());
135    
136            // 1st array
137            ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, list.get(0));
138            List<?> list1 = (List<?>) list.get(0);
139            assertFalse("nested array 1 is empty", list1.isEmpty());
140            assertEquals("size", 2, list1.size());
141            assertEquals("1st element", "a", list1.get(0));
142            assertEquals("2nd element", "b", list1.get(1));
143    
144            // 2nd array
145            ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, list.get(1));
146            List<?> list2 = (List<?>) list.get(1);
147            assertFalse("nested array 2 is empty", list2.isEmpty());
148            assertEquals("size", 2, list2.size());
149            assertEquals("1st element", "c", list2.get(0));
150            assertEquals("2nd element", "d", list2.get(1));
151        }
152    
153        @Test
154        public void testDictionary()
155        {
156            assertEquals("1st element in dictionary", "bar1", config.getProperty("dictionary.foo1"));
157            assertEquals("2nd element in dictionary", "bar2", config.getProperty("dictionary.foo2"));
158        }
159    
160        @Test
161        public void testDictionaryArray()
162        {
163            String key = "dictionary-array";
164    
165            Object array = config.getProperty(key);
166    
167            // root array
168            assertNotNull("array not found", array);
169            ObjectAssert.assertInstanceOf("the array element is not parsed as a List", List.class, array);
170            List<?> list = config.getList(key);
171    
172            assertFalse("empty array", list.isEmpty());
173            assertEquals("size", 2, list.size());
174    
175            // 1st dictionary
176            ObjectAssert.assertInstanceOf("the dict element is not parsed as a Configuration", Configuration.class, list.get(0));
177            Configuration conf1 = (Configuration) list.get(0);
178            assertFalse("configuration 1 is empty", conf1.isEmpty());
179            assertEquals("configuration element", "bar", conf1.getProperty("foo"));
180    
181            // 2nd dictionary
182            ObjectAssert.assertInstanceOf("the dict element is not parsed as a Configuration", Configuration.class, list.get(1));
183            Configuration conf2 = (Configuration) list.get(1);
184            assertFalse("configuration 2 is empty", conf2.isEmpty());
185            assertEquals("configuration element", "value", conf2.getProperty("key"));
186        }
187    
188        @Test
189        public void testNestedDictionaries()
190        {
191            assertEquals("nested property", "value", config.getString("nested-dictionaries.foo.bar.key"));
192        }
193    
194        @Test
195        public void testData()
196        {
197            ObjectAssert.assertInstanceOf("data", (new byte[0]).getClass(), config.getProperty("data"));
198            ArrayAssert.assertEquals("data", "foo bar".getBytes(), (byte[]) config.getProperty("data"));
199        }
200    
201        @Test
202        public void testDate() throws Exception
203        {
204            Calendar cal = Calendar.getInstance();
205            cal.clear();
206            cal.set(2002, 2, 22, 11, 30, 0);
207            cal.setTimeZone(TimeZone.getTimeZone("GMT+0100"));
208            Date date = cal.getTime();
209    
210            assertEquals("date", date, config.getProperty("date"));
211        }
212    
213        @Test
214        public void testSave() throws Exception
215        {
216            File savedFile = new File("target/testsave.plist");
217    
218            // remove the file previously saved if necessary
219            if (savedFile.exists())
220            {
221                assertTrue(savedFile.delete());
222            }
223    
224            // save the configuration
225            String filename = savedFile.getAbsolutePath();
226            config.save(filename);
227    
228            assertTrue("The saved file doesn't exist", savedFile.exists());
229    
230            // read the configuration and compare the properties
231            Configuration checkConfig = new PropertyListConfiguration(new File(filename));
232    
233            Iterator<String> it = config.getKeys();
234            while (it.hasNext())
235            {
236                String key = it.next();
237                assertTrue("The saved configuration doesn't contain the key '" + key + "'", checkConfig.containsKey(key));
238    
239                Object value = checkConfig.getProperty(key);
240                if (value instanceof byte[])
241                {
242                    byte[] array = (byte[]) value;
243                    ArrayAssert.assertEquals("Value of the '" + key + "' property", (byte[]) config.getProperty(key), array);
244                }
245                else if (value instanceof List)
246                {
247                    List<?> list1 = (List<?>) config.getProperty(key);
248                    List<?> list2 = (List<?>) value;
249    
250                    assertEquals("The size of the list for the key '" + key + "' doesn't match", list1.size(), list2.size());
251    
252                    for (int i = 0; i < list2.size(); i++)
253                    {
254                        Object value1 = list1.get(i);
255                        Object value2 = list2.get(i);
256    
257                        if (value1 instanceof Configuration)
258                        {
259                            ConfigurationComparator comparator = new StrictConfigurationComparator();
260                            assertTrue("The dictionnary at index " + i + " for the key '" + key + "' doesn't match", comparator.compare((Configuration) value1, (Configuration) value2));
261                        }
262                        else
263                        {
264                            assertEquals("Element at index " + i + " for the key '" + key + "'", value1, value2);
265                        }
266                    }
267    
268                    ListAssert.assertEquals("Value of the '" + key + "' property", (List<?>) config.getProperty(key), list1);
269                }
270                else
271                {
272                    assertEquals("Value of the '" + key + "' property", config.getProperty(key), checkConfig.getProperty(key));
273                }
274    
275            }
276        }
277    
278        @Test
279        public void testSaveEmptyDictionary() throws Exception
280        {
281            File savedFile = new File("target/testsave.plist");
282    
283            // remove the file previously saved if necessary
284            if (savedFile.exists())
285            {
286                assertTrue(savedFile.delete());
287            }
288    
289            // save the configuration
290            String filename = savedFile.getAbsolutePath();
291            config.save(filename);
292    
293            assertTrue("The saved file doesn't exist", savedFile.exists());
294    
295            // read the configuration and compare the properties
296            PropertyListConfiguration checkConfig = new PropertyListConfiguration(new File(filename));
297    
298            assertFalse(config.getRootNode().getChildren("empty-dictionary").isEmpty());
299            assertFalse(checkConfig.getRootNode().getChildren("empty-dictionary").isEmpty());
300        }
301    
302        @Test
303        public void testQuoteString()
304        {
305            assertEquals("null string", null, config.quoteString(null));
306            assertEquals("simple string", "abcd", config.quoteString("abcd"));
307            assertEquals("string with a space", "\"ab cd\"", config.quoteString("ab cd"));
308            assertEquals("string with a quote", "\"foo\\\"bar\"", config.quoteString("foo\"bar"));
309            assertEquals("string with a special char", "\"foo;bar\"", config.quoteString("foo;bar"));
310        }
311    
312        /**
313         * Ensure that setProperty doesn't alter an array of byte
314         * since it's a first class type in plist file
315         */
316        @Test
317        public void testSetDataProperty() throws Exception
318        {
319            byte[] expected = new byte[]{1, 2, 3, 4};
320            PropertyListConfiguration config = new PropertyListConfiguration();
321            config.setProperty("foo", expected);
322            config.save("target/testdata.plist");
323    
324            PropertyListConfiguration config2 = new PropertyListConfiguration("target/testdata.plist");
325            Object array = config2.getProperty("foo");
326    
327            assertNotNull("data not found", array);
328            assertEquals("property type", byte[].class, array.getClass());
329            ArrayAssert.assertEquals(expected, (byte[]) array);
330        }
331    
332        /**
333         * Ensure that addProperty doesn't alter an array of byte
334         */
335        @Test
336        public void testAddDataProperty() throws Exception
337        {
338            byte[] expected = new byte[]{1, 2, 3, 4};
339            PropertyListConfiguration config = new PropertyListConfiguration();
340            config.addProperty("foo", expected);
341            config.save("target/testdata.plist");
342    
343            PropertyListConfiguration config2 = new PropertyListConfiguration("target/testdata.plist");
344            Object array = config2.getProperty("foo");
345    
346            assertNotNull("data not found", array);
347            assertEquals("property type", byte[].class, array.getClass());
348            ArrayAssert.assertEquals(expected, (byte[]) array);
349        }
350    
351        @Test
352        public void testInitCopy()
353        {
354            PropertyListConfiguration copy = new PropertyListConfiguration(config);
355            assertFalse("Nothing was copied", copy.isEmpty());
356        }
357    
358        /**
359         * Tests parsing a date with an invalid numeric value.
360         */
361        @Test(expected = ParseException.class)
362        public void testParseDateNoNumber() throws ParseException
363        {
364            PropertyListConfiguration
365                    .parseDate("<*D2002-03-22 1c:30:00 +0100>");
366        }
367    
368        /**
369         * Tests parsing a date that is not long enough.
370         */
371        @Test(expected = ParseException.class)
372        public void testParseDateTooShort() throws ParseException
373        {
374            PropertyListConfiguration.parseDate("<*D2002-03-22 11:3>");
375        }
376    
377        /**
378         * Tests parsing a date that contains an invalid separator character.
379         */
380        @Test(expected = ParseException.class)
381        public void testParseDateInvalidChar() throws ParseException
382        {
383            PropertyListConfiguration
384                    .parseDate("<*D2002+03-22 11:30:00 +0100>");
385        }
386    
387        /**
388         * Tries parsing a null date. This should cause an exception.n
389         */
390        @Test(expected = ParseException.class)
391        public void testParseDateNull() throws ParseException
392        {
393            PropertyListConfiguration.parseDate(null);
394        }
395    
396        /**
397         * Tests formatting a date.
398         */
399        @Test
400        public void testFormatDate()
401        {
402            Calendar cal = Calendar.getInstance();
403            cal.clear();
404            cal.set(2007, 9, 29, 23, 4, 30);
405            cal.setTimeZone(TimeZone.getTimeZone("GMT-0230"));
406            assertEquals("Wrong date literal (1)", "<*D2007-10-29 23:04:30 -0230>",
407                    PropertyListConfiguration.formatDate(cal));
408            cal.clear();
409            cal.set(2007, 9, 30, 22, 2, 15);
410            cal.setTimeZone(TimeZone.getTimeZone("GMT+1111"));
411            assertEquals("Wrong date literal (2)", "<*D2007-10-30 22:02:15 +1111>",
412                    PropertyListConfiguration.formatDate(cal));
413        }
414    }