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;
019    
020    import static org.junit.Assert.assertEquals;
021    import static org.junit.Assert.assertNotNull;
022    import static org.junit.Assert.assertSame;
023    import static org.junit.Assert.assertTrue;
024    
025    import java.lang.annotation.ElementType;
026    import java.math.BigDecimal;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    import org.junit.Test;
031    
032    /**
033     * Test class for PropertyConverter.
034     *
035     * @author Emmanuel Bourg
036     * @version $Id: TestPropertyConverter.java 1301990 2012-03-17 20:10:46Z oheger $
037     */
038    public class TestPropertyConverter
039    {
040        /** Constant for an enumeration class used by some tests. */
041        private static final Class<ElementType> ENUM_CLASS = ElementType.class;
042    
043        @Test
044        public void testSplit()
045        {
046            String s = "abc, xyz , 123";
047            List<String> list = PropertyConverter.split(s, ',');
048    
049            assertEquals("size", 3, list.size());
050            assertEquals("1st token for '" + s + "'", "abc", list.get(0));
051            assertEquals("2nd token for '" + s + "'", "xyz", list.get(1));
052            assertEquals("3rd token for '" + s + "'", "123", list.get(2));
053        }
054    
055        @Test
056        public void testSplitNoTrim()
057        {
058            String s = "abc, xyz , 123";
059            List<String> list = PropertyConverter.split(s, ',', false);
060    
061            assertEquals("size", 3, list.size());
062            assertEquals("1st token for '" + s + "'", "abc", list.get(0));
063            assertEquals("2nd token for '" + s + "'", " xyz ", list.get(1));
064            assertEquals("3rd token for '" + s + "'", " 123", list.get(2));
065        }
066    
067        @Test
068        public void testSplitWithEscapedSeparator()
069        {
070            String s = "abc\\,xyz, 123";
071            List<String> list = PropertyConverter.split(s, ',');
072    
073            assertEquals("size", 2, list.size());
074            assertEquals("1st token for '" + s + "'", "abc,xyz", list.get(0));
075            assertEquals("2nd token for '" + s + "'", "123", list.get(1));
076        }
077    
078        @Test
079        public void testSplitEmptyValues()
080        {
081            String s = ",,";
082            List<String> list = PropertyConverter.split(s, ',');
083    
084            assertEquals("size", 3, list.size());
085            assertEquals("1st token for '" + s + "'", "", list.get(0));
086            assertEquals("2nd token for '" + s + "'", "", list.get(1));
087            assertEquals("3rd token for '" + s + "'", "", list.get(2));
088        }
089    
090        @Test
091        public void testSplitWithEndingSlash()
092        {
093            String s = "abc, xyz\\";
094            List<String> list = PropertyConverter.split(s, ',');
095    
096            assertEquals("size", 2, list.size());
097            assertEquals("1st token for '" + s + "'", "abc", list.get(0));
098            assertEquals("2nd token for '" + s + "'", "xyz\\", list.get(1));
099        }
100    
101        @Test
102        public void testSplitNull()
103        {
104            List<String> list = PropertyConverter.split(null, ',');
105            assertNotNull(list);
106            assertTrue(list.isEmpty());
107        }
108    
109        /**
110         * Tests whether an escape character can be itself escaped.
111         */
112        @Test
113        public void testSplitEscapeEscapeChar()
114        {
115            List<String> list = PropertyConverter.split("C:\\Temp\\\\,xyz", ',');
116            assertEquals("Wrong list size", 2, list.size());
117            assertEquals("Wrong element 1", "C:\\Temp\\", list.get(0));
118            assertEquals("Wrong element 2", "xyz", list.get(1));
119        }
120    
121        /**
122         * Tests whether delimiters are correctly escaped.
123         */
124        @Test
125        public void testEscapeDelimiters()
126        {
127            assertEquals("Wrong escaped delimiters",
128                    "C:\\\\Temp\\\\\\,D:\\\\Data\\\\", PropertyConverter
129                            .escapeDelimiters("C:\\Temp\\,D:\\Data\\", ','));
130        }
131    
132        /**
133         * Tests whether only the list delimiter can be escaped.
134         */
135        @Test
136        public void testEscapeListDelimiter()
137        {
138            assertEquals("Wrong escaped list delimiter", "C:\\Temp\\\\,D:\\Data\\",
139                    PropertyConverter.escapeListDelimiter("C:\\Temp\\,D:\\Data\\",
140                            ','));
141        }
142    
143        @Test
144        public void testToIterator()
145        {
146            int[] array = new int[]{1, 2, 3};
147    
148            Iterator<?> it = PropertyConverter.toIterator(array, ',');
149    
150            assertEquals("1st element", new Integer(1), it.next());
151            assertEquals("2nd element", new Integer(2), it.next());
152            assertEquals("3rd element", new Integer(3), it.next());
153        }
154    
155        /**
156         * Tests the interpolation features.
157         */
158        @Test
159        public void testInterpolateString()
160        {
161            PropertiesConfiguration config = new PropertiesConfiguration();
162            config.addProperty("animal", "quick brown fox");
163            config.addProperty("target", "lazy dog");
164            assertEquals("Wrong interpolation",
165                    "The quick brown fox jumps over the lazy dog.",
166                    PropertyConverter.interpolate("The ${animal} jumps over the ${target}.", config));
167        }
168    
169        /**
170         * Tests interpolation of an object. Here nothing should be substituted.
171         */
172        @Test
173        public void testInterpolateObject()
174        {
175            assertEquals("Object was not correctly interpolated", new Integer(42),
176                    PropertyConverter.interpolate(new Integer(42), new PropertiesConfiguration()));
177        }
178    
179        /**
180         * Tests complex interpolation where the variables' values contain in turn
181         * other variables.
182         */
183        @Test
184        public void testInterpolateRecursive()
185        {
186            PropertiesConfiguration config = new PropertiesConfiguration();
187            config.addProperty("animal", "${animal_attr} fox");
188            config.addProperty("target", "${target_attr} dog");
189            config.addProperty("animal_attr", "quick brown");
190            config.addProperty("target_attr", "lazy");
191            assertEquals("Wrong complex interpolation",
192                    "The quick brown fox jumps over the lazy dog.",
193                    PropertyConverter.interpolate("The ${animal} jumps over the ${target}.", config));
194        }
195    
196        /**
197         * Tests an interpolation that leads to a cycle. This should throw an
198         * exception.
199         */
200        @Test(expected = IllegalStateException.class)
201        public void testCyclicInterpolation()
202        {
203            PropertiesConfiguration config = new PropertiesConfiguration();
204            config.addProperty("animal", "${animal_attr} ${species}");
205            config.addProperty("animal_attr", "quick brown");
206            config.addProperty("species", "${animal}");
207            PropertyConverter.interpolate("This is a ${animal}", config);
208        }
209    
210        /**
211         * Tests interpolation if a variable is unknown. Then the variable won't be
212         * substituted.
213         */
214        @Test
215        public void testInterpolationUnknownVariable()
216        {
217            PropertiesConfiguration config = new PropertiesConfiguration();
218            config.addProperty("animal", "quick brown fox");
219            assertEquals("Wrong interpolation",
220                    "The quick brown fox jumps over ${target}.",
221                    PropertyConverter.interpolate("The ${animal} jumps over ${target}.", config));
222        }
223    
224        /**
225         * Tests conversion to numbers when the passed in objects are already
226         * numbers.
227         */
228        @Test
229        public void testToNumberDirect()
230        {
231            Integer i = new Integer(42);
232            assertSame("Wrong integer", i, PropertyConverter.toNumber(i, Integer.class));
233            BigDecimal d = new BigDecimal("3.1415");
234            assertSame("Wrong BigDecimal", d, PropertyConverter.toNumber(d, Integer.class));
235        }
236    
237        /**
238         * Tests conversion to numbers when the passed in objects have a compatible
239         * string representation.
240         */
241        @Test
242        public void testToNumberFromString()
243        {
244            assertEquals("Incorrect Integer value", new Integer(42), PropertyConverter.toNumber("42", Integer.class));
245            assertEquals("Incorrect Short value", new Short((short) 10), PropertyConverter.toNumber(new StringBuffer("10"), Short.class));
246        }
247    
248        /**
249         * Tests conversion to numbers when the passed in objects are strings with
250         * prefixes for special radices.
251         */
252        @Test
253        public void testToNumberFromHexString()
254        {
255            Number n = PropertyConverter.toNumber("0x10", Integer.class);
256            assertEquals("Incorrect Integer value", 16, n.intValue());
257        }
258    
259        /**
260         * Tests conversion to numbers when an invalid Hex value is passed in.
261         * This should cause an exception.
262         */
263        @Test(expected = ConversionException.class)
264        public void testToNumberFromInvalidHexString()
265        {
266            PropertyConverter.toNumber("0xNotAHexValue", Integer.class);
267        }
268    
269        /**
270         * Tests conversion to numbers when the passed in objects are strings with
271         * prefixes for special radices.
272         */
273        @Test
274        public void testToNumberFromBinaryString()
275        {
276            Number n = PropertyConverter.toNumber("0b1111", Integer.class);
277            assertEquals("Incorrect Integer value", 15, n.intValue());
278        }
279    
280        /**
281         * Tests conversion to numbers when an invalid binary value is passed in.
282         * This should cause an exception.
283         */
284        @Test(expected = ConversionException.class)
285        public void testToNumberFromInvalidBinaryString()
286        {
287            PropertyConverter.toNumber("0bNotABinValue", Integer.class);
288        }
289    
290        /**
291         * Tests conversion to numbers when the passed in objects have no numeric
292         * String representation. This should cause an exception.
293         */
294        @Test(expected = ConversionException.class)
295        public void testToNumberFromInvalidString()
296        {
297            PropertyConverter.toNumber("Not a number", Byte.class);
298        }
299    
300        /**
301         * Tests conversion to numbers when the passed in target class is invalid.
302         * This should cause an exception.
303         */
304        @Test(expected = ConversionException.class)
305        public void testToNumberWithInvalidClass()
306        {
307            PropertyConverter.toNumber("42", Object.class);
308        }
309    
310        @Test
311        public void testToEnumFromEnum()
312        {
313            assertEquals(ElementType.METHOD, PropertyConverter.toEnum(ElementType.METHOD, ENUM_CLASS));
314        }
315    
316        @Test
317        public void testToEnumFromString()
318        {
319            assertEquals(ElementType.METHOD, PropertyConverter.toEnum("METHOD", ENUM_CLASS));
320        }
321    
322        @Test(expected = ConversionException.class)
323        public void testToEnumFromInvalidString()
324        {
325            PropertyConverter.toEnum("FOO", ENUM_CLASS);
326        }
327    
328        @Test
329        public void testToEnumFromNumber()
330        {
331            assertEquals(ElementType.METHOD, PropertyConverter.toEnum(
332                    Integer.valueOf(ElementType.METHOD.ordinal()),
333                    ENUM_CLASS));
334        }
335    
336        @Test(expected = ConversionException.class)
337        public void testToEnumFromInvalidNumber()
338        {
339            PropertyConverter.toEnum(Integer.valueOf(-1), ENUM_CLASS);
340        }
341    
342        /**
343         * Tests a trivial conversion: the value has already the desired type.
344         */
345        @Test
346        public void testToNoConversionNeeded()
347        {
348            String value = "testValue";
349            assertEquals("Wrong conversion result", value,
350                    PropertyConverter.to(String.class, value, null));
351        }
352    }