1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.configuration;
19  
20  import java.lang.reflect.Method;
21  import java.math.BigDecimal;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import org.apache.commons.lang.SystemUtils;
26  
27  import junit.framework.TestCase;
28  
29  /***
30   * Test class for PropertyConverter.
31   *
32   * @author Emmanuel Bourg
33   * @version $Revision: 536324 $, $Date: 2007-05-08 22:54:33 +0200 (Di, 08 Mai 2007) $
34   */
35  public class TestPropertyConverter extends TestCase
36  {
37      public void testSplit()
38      {
39          String s = "abc, xyz , 123";
40          List list = PropertyConverter.split(s, ',');
41  
42          assertEquals("size", 3, list.size());
43          assertEquals("1st token for '" + s + "'", "abc", list.get(0));
44          assertEquals("2nd token for '" + s + "'", "xyz", list.get(1));
45          assertEquals("3rd token for '" + s + "'", "123", list.get(2));
46      }
47  
48      public void testSplitWithEscapedSeparator()
49      {
50          String s = "abc//,xyz, 123";
51          List list = PropertyConverter.split(s, ',');
52  
53          assertEquals("size", 2, list.size());
54          assertEquals("1st token for '" + s + "'", "abc,xyz", list.get(0));
55          assertEquals("2nd token for '" + s + "'", "123", list.get(1));
56      }
57  
58      public void testSplitEmptyValues()
59      {
60          String s = ",,";
61          List list = PropertyConverter.split(s, ',');
62  
63          assertEquals("size", 3, list.size());
64          assertEquals("1st token for '" + s + "'", "", list.get(0));
65          assertEquals("2nd token for '" + s + "'", "", list.get(1));
66          assertEquals("3rd token for '" + s + "'", "", list.get(2));
67      }
68  
69      public void testSplitWithEndingSlash()
70      {
71          String s = "abc, xyz//";
72          List list = PropertyConverter.split(s, ',');
73  
74          assertEquals("size", 2, list.size());
75          assertEquals("1st token for '" + s + "'", "abc", list.get(0));
76          assertEquals("2nd token for '" + s + "'", "xyz//", list.get(1));
77      }
78  
79      public void testSplitNull()
80      {
81          List list = PropertyConverter.split(null, ',');
82          assertNotNull(list);
83          assertTrue(list.isEmpty());
84      }
85  
86      /***
87       * Tests whether an escape character can be itself escaped.
88       */
89      public void testSplitEscapeEscapeChar()
90      {
91          List list = PropertyConverter.split("C://Temp////,xyz", ',');
92          assertEquals("Wrong list size", 2, list.size());
93          assertEquals("Wrong element 1", "C://Temp//", list.get(0));
94          assertEquals("Wrong element 2", "xyz", list.get(1));
95      }
96  
97      /***
98       * Tests whether delimiters are correctly escaped.
99       */
100     public void testEscapeDelimiters()
101     {
102         assertEquals("Wrong escaped delimiters",
103                 "C:////Temp//////,D:////Data////", PropertyConverter
104                         .escapeDelimiters("C://Temp//,D://Data//", ','));
105     }
106 
107     public void testToIterator()
108     {
109         int[] array = new int[]{1, 2, 3};
110 
111         Iterator it = PropertyConverter.toIterator(array, ',');
112 
113         assertEquals("1st element", new Integer(1), it.next());
114         assertEquals("2nd element", new Integer(2), it.next());
115         assertEquals("3rd element", new Integer(3), it.next());
116     }
117 
118     /***
119      * Tests the interpolation features.
120      */
121     public void testInterpolateString()
122     {
123         PropertiesConfiguration config = new PropertiesConfiguration();
124         config.addProperty("animal", "quick brown fox");
125         config.addProperty("target", "lazy dog");
126         assertEquals("Wrong interpolation",
127                 "The quick brown fox jumps over the lazy dog.",
128                 PropertyConverter.interpolate("The ${animal} jumps over the ${target}.", config));
129     }
130 
131     /***
132      * Tests interpolation of an object. Here nothing should be substituted.
133      */
134     public void testInterpolateObject()
135     {
136         assertEquals("Object was not correctly interpolated", new Integer(42),
137                 PropertyConverter.interpolate(new Integer(42), new PropertiesConfiguration()));
138     }
139 
140     /***
141      * Tests complex interpolation where the variables' values contain in turn
142      * other variables.
143      */
144     public void testInterpolateRecursive()
145     {
146         PropertiesConfiguration config = new PropertiesConfiguration();
147         config.addProperty("animal", "${animal_attr} fox");
148         config.addProperty("target", "${target_attr} dog");
149         config.addProperty("animal_attr", "quick brown");
150         config.addProperty("target_attr", "lazy");
151         assertEquals("Wrong complex interpolation",
152                 "The quick brown fox jumps over the lazy dog.",
153                 PropertyConverter.interpolate("The ${animal} jumps over the ${target}.", config));
154     }
155 
156     /***
157      * Tests an interpolation that leads to a cycle. This should throw an
158      * exception.
159      */
160     public void testCyclicInterpolation()
161     {
162         PropertiesConfiguration config = new PropertiesConfiguration();
163         config.addProperty("animal", "${animal_attr} ${species}");
164         config.addProperty("animal_attr", "quick brown");
165         config.addProperty("species", "${animal}");
166         try
167         {
168             PropertyConverter.interpolate("This is a ${animal}", config);
169             fail("Cyclic interpolation was not detected!");
170         }
171         catch (IllegalStateException iex)
172         {
173             // ok
174         }
175     }
176 
177     /***
178      * Tests interpolation if a variable is unknown. Then the variable won't be
179      * substituted.
180      */
181     public void testInterpolationUnknownVariable()
182     {
183         PropertiesConfiguration config = new PropertiesConfiguration();
184         config.addProperty("animal", "quick brown fox");
185         assertEquals("Wrong interpolation",
186                 "The quick brown fox jumps over ${target}.",
187                 PropertyConverter.interpolate("The ${animal} jumps over ${target}.", config));
188     }
189 
190     /***
191      * Tests conversion to numbers when the passed in objects are already
192      * numbers.
193      */
194     public void testToNumberDirect()
195     {
196         Integer i = new Integer(42);
197         assertSame("Wrong integer", i, PropertyConverter.toNumber(i, Integer.class));
198         BigDecimal d = new BigDecimal("3.1415");
199         assertSame("Wrong BigDecimal", d, PropertyConverter.toNumber(d, Integer.class));
200     }
201 
202     /***
203      * Tests conversion to numbers when the passed in objects have a compatible
204      * string representation.
205      */
206     public void testToNumberFromString()
207     {
208         assertEquals("Incorrect Integer value", new Integer(42), PropertyConverter.toNumber("42", Integer.class));
209         assertEquals("Incorrect Short value", new Short((short) 10), PropertyConverter.toNumber(new StringBuffer("10"), Short.class));
210     }
211 
212     /***
213      * Tests conversion to numbers when the passed in objects are strings with
214      * prefixes for special radices.
215      */
216     public void testToNumberFromHexString()
217     {
218         Number n = PropertyConverter.toNumber("0x10", Integer.class);
219         assertEquals("Incorrect Integer value", 16, n.intValue());
220     }
221 
222     /***
223      * Tests conversion to numbers when an invalid Hex value is passed in. This
224      * should cause an exception.
225      */
226     public void testToNumberFromInvalidHexString()
227     {
228         try
229         {
230             PropertyConverter.toNumber("0xNotAHexValue", Integer.class);
231             fail("Could convert invalid hex value!");
232         }
233         catch (ConversionException cex)
234         {
235             // ok
236         }
237     }
238 
239     /***
240      * Tests conversion to numbers when the passed in objects have no numeric
241      * String representation. This should cause an exception.
242      */
243     public void testToNumberFromInvalidString()
244     {
245         try
246         {
247             PropertyConverter.toNumber("Not a number", Byte.class);
248             fail("Could convert invalid String!");
249         }
250         catch (ConversionException cex)
251         {
252             // ok
253         }
254     }
255 
256     /***
257      * Tests conversion to numbers when the passed in target class is invalid.
258      * This should cause an exception.
259      */
260     public void testToNumberWithInvalidClass()
261     {
262         try
263         {
264             PropertyConverter.toNumber("42", Object.class);
265             fail("Could convert to invalid target class!");
266         }
267         catch (ConversionException cex)
268         {
269             //ok
270         }
271     }
272 
273     // enumeration type used for the tests, Java 5 only
274     private Class enumClass;
275     private Object enumObject;
276     {
277         if (SystemUtils.isJavaVersionAtLeast(1.5f))
278         {
279             try
280             {
281                 enumClass = Class.forName("java.lang.annotation.ElementType");
282 
283                 Method valueOfMethod = enumClass.getMethod("valueOf", new Class[] { String.class });
284                 enumObject = valueOfMethod.invoke(null, new Object[] { "METHOD" });
285             }
286             catch (Exception e)
287             {
288             }
289         }
290     }
291 
292     public void testToEnumFromEnum()
293     {
294         if (!SystemUtils.isJavaVersionAtLeast(1.5f))
295         {
296             return;
297         }
298 
299         assertEquals(enumObject, PropertyConverter.toEnum(enumObject, enumClass));
300     }
301 
302     public void testToEnumFromString()
303     {
304         if (!SystemUtils.isJavaVersionAtLeast(1.5f))
305         {
306             return;
307         }
308 
309         assertEquals(enumObject, PropertyConverter.toEnum("METHOD", enumClass));
310     }
311 
312     public void testToEnumFromInvalidString()
313     {
314         if (!SystemUtils.isJavaVersionAtLeast(1.5f))
315         {
316             return;
317         }
318 
319         try
320         {
321             assertEquals(enumObject, PropertyConverter.toEnum("FOO", enumClass));
322             fail("Could convert invalid String!");
323         }
324         catch (ConversionException e)
325         {
326             // expected
327         }
328     }
329 
330     public void testToEnumFromNumber()
331     {
332         if (!SystemUtils.isJavaVersionAtLeast(1.5f))
333         {
334             return;
335         }
336 
337         assertEquals(enumObject, PropertyConverter.toEnum(new Integer(2), enumClass));
338     }
339 
340     public void testToEnumFromInvalidNumber()
341     {
342         if (!SystemUtils.isJavaVersionAtLeast(1.5f))
343         {
344             return;
345         }
346         
347         try
348         {
349             assertEquals(enumObject, PropertyConverter.toEnum(new Integer(-1), enumClass));
350             fail("Could convert invalid number!");
351         }
352         catch (ConversionException e)
353         {
354             // expected
355         }
356     }
357 }