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.math.BigDecimal;
21  import java.math.BigInteger;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.NoSuchElementException;
27  import java.util.Properties;
28  import java.util.Set;
29  import java.util.StringTokenizer;
30  
31  import junit.framework.TestCase;
32  import junitx.framework.ListAssert;
33  import junitx.framework.ObjectAssert;
34  
35  import org.apache.commons.collections.set.ListOrderedSet;
36  import org.apache.commons.configuration.event.ConfigurationEvent;
37  import org.apache.commons.configuration.event.ConfigurationListener;
38  
39  /***
40   * Tests some basic functions of the BaseConfiguration class. Missing keys will
41   * throw Exceptions
42   *
43   * @version $Id: TestBaseConfiguration.java 588335 2007-10-25 20:22:35Z oheger $
44   */
45  public class TestBaseConfiguration extends TestCase
46  {
47      /*** Constant for the number key.*/
48      static final String KEY_NUMBER = "number";
49  
50      protected BaseConfiguration config = null;
51  
52      protected static Class missingElementException = NoSuchElementException.class;
53      protected static Class incompatibleElementException = ConversionException.class;
54  
55      protected void setUp() throws Exception
56      {
57          config = new BaseConfiguration();
58          config.setThrowExceptionOnMissing(true);
59      }
60  
61      public void testThrowExceptionOnMissing()
62      {
63          assertTrue("Throw Exception Property is not set!", config.isThrowExceptionOnMissing());
64      }
65  
66      public void testGetProperty()
67      {
68          /* should be empty and return null */
69          assertEquals("This returns null", config.getProperty("foo"), null);
70  
71          /* add a real value, and get it two different ways */
72          config.setProperty("number", "1");
73          assertEquals("This returns '1'", config.getProperty("number"), "1");
74          assertEquals("This returns '1'", config.getString("number"), "1");
75      }
76  
77      public void testGetByte()
78      {
79          config.setProperty("number", "1");
80          byte oneB = 1;
81          byte twoB = 2;
82          assertEquals("This returns 1(byte)", oneB, config.getByte("number"));
83          assertEquals("This returns 1(byte)", oneB, config.getByte("number", twoB));
84          assertEquals("This returns 2(default byte)", twoB, config.getByte("numberNotInConfig", twoB));
85          assertEquals("This returns 1(Byte)", new Byte(oneB), config.getByte("number", new Byte("2")));
86  
87          // missing key without default value
88          Throwable t = null;
89          try
90          {
91              config.getByte("numberNotInConfig");
92          }
93          catch (Throwable T)
94          {
95              t = T;
96          }
97          assertNotNull("No exception thrown for missing keys", t);
98          ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
99  
100         // existing key with an incompatible value
101         config.setProperty("test.empty", "");
102         t = null;
103         try
104         {
105             config.getByte("test.empty");
106         }
107         catch (Throwable T)
108         {
109             t = T;
110         }
111         assertNotNull("No exception thrown for incompatible values", t);
112         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
113     }
114 
115     public void testGetShort()
116     {
117         config.setProperty("numberS", "1");
118         short oneS = 1;
119         short twoS = 2;
120         assertEquals("This returns 1(short)", oneS, config.getShort("numberS"));
121         assertEquals("This returns 1(short)", oneS, config.getShort("numberS", twoS));
122         assertEquals("This returns 2(default short)", twoS, config.getShort("numberNotInConfig", twoS));
123         assertEquals("This returns 1(Short)", new Short(oneS), config.getShort("numberS", new Short("2")));
124 
125         // missing key without default value
126         Throwable t = null;
127         try
128         {
129             config.getShort("numberNotInConfig");
130         }
131         catch (Throwable T)
132         {
133             t = T;
134         }
135         assertNotNull("No exception thrown for missing keys", t);
136         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
137 
138         // existing key with an incompatible value
139         config.setProperty("test.empty", "");
140         t = null;
141         try
142         {
143             config.getShort("test.empty");
144         }
145         catch (Throwable T)
146         {
147             t = T;
148         }
149         assertNotNull("No exception thrown for incompatible values", t);
150         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
151     }
152 
153     public void testGetLong()
154     {
155         config.setProperty("numberL", "1");
156         long oneL = 1;
157         long twoL = 2;
158         assertEquals("This returns 1(long)", oneL, config.getLong("numberL"));
159         assertEquals("This returns 1(long)", oneL, config.getLong("numberL", twoL));
160         assertEquals("This returns 2(default long)", twoL, config.getLong("numberNotInConfig", twoL));
161         assertEquals("This returns 1(Long)", new Long(oneL), config.getLong("numberL", new Long("2")));
162 
163         // missing key without default value
164         Throwable t = null;
165         try
166         {
167             config.getLong("numberNotInConfig");
168         }
169         catch (Throwable T)
170         {
171             t = T;
172         }
173         assertNotNull("No exception thrown for missing keys", t);
174         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
175 
176         // existing key with an incompatible value
177         config.setProperty("test.empty", "");
178         t = null;
179         try
180         {
181             config.getLong("test.empty");
182         }
183         catch (Throwable T)
184         {
185             t = T;
186         }
187         assertNotNull("No exception thrown for incompatible values", t);
188         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
189     }
190 
191     public void testGetFloat()
192     {
193         config.setProperty("numberF", "1.0");
194         float oneF = 1;
195         float twoF = 2;
196         assertEquals("This returns 1(float)", oneF, config.getFloat("numberF"), 0);
197         assertEquals("This returns 1(float)", oneF, config.getFloat("numberF", twoF), 0);
198         assertEquals("This returns 2(default float)", twoF, config.getFloat("numberNotInConfig", twoF), 0);
199         assertEquals("This returns 1(Float)", new Float(oneF), config.getFloat("numberF", new Float("2")));
200 
201         // missing key without default value
202         Throwable t = null;
203         try
204         {
205             config.getFloat("numberNotInConfig");
206         }
207         catch (Throwable T)
208         {
209             t = T;
210         }
211         assertNotNull("No exception thrown for missing keys", t);
212         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
213 
214         // existing key with an incompatible value
215         config.setProperty("test.empty", "");
216         t = null;
217         try
218         {
219             config.getFloat("test.empty");
220         }
221         catch (Throwable T)
222         {
223             t = T;
224         }
225         assertNotNull("No exception thrown for incompatible values", t);
226         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
227     }
228 
229     public void testGetDouble()
230     {
231         config.setProperty("numberD", "1.0");
232         double oneD = 1;
233         double twoD = 2;
234         assertEquals("This returns 1(double)", oneD, config.getDouble("numberD"), 0);
235         assertEquals("This returns 1(double)", oneD, config.getDouble("numberD", twoD), 0);
236         assertEquals("This returns 2(default double)", twoD, config.getDouble("numberNotInConfig", twoD), 0);
237         assertEquals("This returns 1(Double)", new Double(oneD), config.getDouble("numberD", new Double("2")));
238 
239         // missing key without default value
240         Throwable t = null;
241         try
242         {
243             config.getDouble("numberNotInConfig");
244         }
245         catch (Throwable T)
246         {
247             t = T;
248         }
249         assertNotNull("No exception thrown for missing keys", t);
250         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
251 
252         // existing key with an incompatible value
253         config.setProperty("test.empty", "");
254         t = null;
255         try
256         {
257             config.getDouble("test.empty");
258         }
259         catch (Throwable T)
260         {
261             t = T;
262         }
263         assertNotNull("No exception thrown for incompatible values", t);
264         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
265     }
266 
267     public void testGetBigDecimal()
268     {
269         config.setProperty("numberBigD", "123.456");
270         BigDecimal number = new BigDecimal("123.456");
271         BigDecimal defaultValue = new BigDecimal("654.321");
272 
273         assertEquals("Existing key", number, config.getBigDecimal("numberBigD"));
274         assertEquals("Existing key with default value", number, config.getBigDecimal("numberBigD", defaultValue));
275         assertEquals("Missing key with default value", defaultValue, config.getBigDecimal("numberNotInConfig", defaultValue));
276 
277         // missing key without default value
278         Throwable t = null;
279         try
280         {
281             config.getBigDecimal("numberNotInConfig");
282         }
283         catch (Throwable T)
284         {
285             t = T;
286         }
287         assertNotNull("No exception thrown for missing keys", t);
288         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
289 
290         // existing key with an incompatible value
291         config.setProperty("test.empty", "");
292         t = null;
293         try
294         {
295             config.getBigDecimal("test.empty");
296         }
297         catch (Throwable T)
298         {
299             t = T;
300         }
301         assertNotNull("No exception thrown for incompatible values", t);
302         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
303     }
304 
305     public void testGetBigInteger()
306     {
307         config.setProperty("numberBigI", "1234567890");
308         BigInteger number = new BigInteger("1234567890");
309         BigInteger defaultValue = new BigInteger("654321");
310 
311         assertEquals("Existing key", number, config.getBigInteger("numberBigI"));
312         assertEquals("Existing key with default value", number, config.getBigInteger("numberBigI", defaultValue));
313         assertEquals("Missing key with default value", defaultValue, config.getBigInteger("numberNotInConfig", defaultValue));
314 
315         // missing key without default value
316         Throwable t = null;
317         try
318         {
319             config.getBigInteger("numberNotInConfig");
320         }
321         catch (Throwable T)
322         {
323             t = T;
324         }
325         assertNotNull("No exception thrown for missing keys", t);
326         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
327 
328         // existing key with an incompatible value
329         config.setProperty("test.empty", "");
330         t = null;
331         try
332         {
333             config.getBigInteger("test.empty");
334         }
335         catch (Throwable T)
336         {
337             t = T;
338         }
339         assertNotNull("No exception thrown for incompatible values", t);
340         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
341     }
342 
343     public void testGetString()
344     {
345         config.setProperty("testString", "The quick brown fox");
346         String string = "The quick brown fox";
347         String defaultValue = "jumps over the lazy dog";
348 
349         assertEquals("Existing key", string, config.getString("testString"));
350         assertEquals("Existing key with default value", string, config.getString("testString", defaultValue));
351         assertEquals("Missing key with default value", defaultValue, config.getString("stringNotInConfig", defaultValue));
352 
353         // missing key without default value
354         Throwable t = null;
355         try
356         {
357             config.getString("stringNotInConfig");
358         }
359         catch (Throwable T)
360         {
361             t = T;
362         }
363         assertNotNull("No exception thrown for missing keys", t);
364         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
365     }
366 
367     public void testGetBoolean()
368     {
369         config.setProperty("boolA", Boolean.TRUE);
370         boolean boolT = true, boolF = false;
371         assertEquals("This returns true", boolT, config.getBoolean("boolA"));
372         assertEquals("This returns true, not the default", boolT, config.getBoolean("boolA", boolF));
373         assertEquals("This returns false(default)", boolF, config.getBoolean("boolNotInConfig", boolF));
374         assertEquals("This returns true(Boolean)", new Boolean(boolT), config.getBoolean("boolA", new Boolean(boolF)));
375 
376         // missing key without default value
377         Throwable t = null;
378         try
379         {
380             config.getBoolean("numberNotInConfig");
381         }
382         catch (Throwable T)
383         {
384             t = T;
385         }
386         assertNotNull("No exception thrown for missing keys", t);
387         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
388 
389         // existing key with an incompatible value
390         config.setProperty("test.empty", "");
391         t = null;
392         try
393         {
394             config.getBoolean("test.empty");
395         }
396         catch (Throwable T)
397         {
398             t = T;
399         }
400         assertNotNull("No exception thrown for incompatible values", t);
401         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
402     }
403 
404     public void testGetList()
405     {
406         config.addProperty("number", "1");
407         config.addProperty("number", "2");
408         List list = config.getList("number");
409         assertNotNull("The list is null", list);
410         assertEquals("List size", 2, list.size());
411         assertTrue("The number 1 is missing from the list", list.contains("1"));
412         assertTrue("The number 2 is missing from the list", list.contains("2"));
413 
414         /*
415          *  now test dan's new fix where we get the first scalar
416          *  when we access a list valued property
417          */
418         try
419         {
420             config.getString("number");
421         }
422         catch (NoSuchElementException nsse)
423         {
424             fail("Should return a string");
425         }
426     }
427 
428     public void testGetInterpolatedList()
429     {
430         config.addProperty("number", "1");
431         config.addProperty("array", "${number}");
432         config.addProperty("array", "${number}");
433 
434         List list = new ArrayList();
435         list.add("1");
436         list.add("1");
437 
438         ListAssert.assertEquals("'array' property", list, config.getList("array"));
439     }
440 
441     public void testGetInterpolatedPrimitives()
442     {
443         config.addProperty("number", "1");
444         config.addProperty("value", "${number}");
445 
446         config.addProperty("boolean", "true");
447         config.addProperty("booleanValue", "${boolean}");
448 
449         // primitive types
450         assertEquals("boolean interpolation", true, config.getBoolean("booleanValue"));
451         assertEquals("byte interpolation", 1, config.getByte("value"));
452         assertEquals("short interpolation", 1, config.getShort("value"));
453         assertEquals("int interpolation", 1, config.getInt("value"));
454         assertEquals("long interpolation", 1, config.getLong("value"));
455         assertEquals("float interpolation", 1, config.getFloat("value"), 0);
456         assertEquals("double interpolation", 1, config.getDouble("value"), 0);
457 
458         // primitive wrappers
459         assertEquals("Boolean interpolation", Boolean.TRUE, config.getBoolean("booleanValue", null));
460         assertEquals("Byte interpolation", new Byte("1"), config.getByte("value", null));
461         assertEquals("Short interpolation", new Short("1"), config.getShort("value", null));
462         assertEquals("Integer interpolation", new Integer("1"), config.getInteger("value", null));
463         assertEquals("Long interpolation", new Long("1"), config.getLong("value", null));
464         assertEquals("Float interpolation", new Float("1"), config.getFloat("value", null));
465         assertEquals("Double interpolation", new Double("1"), config.getDouble("value", null));
466 
467         assertEquals("BigInteger interpolation", new BigInteger("1"), config.getBigInteger("value", null));
468         assertEquals("BigDecimal interpolation", new BigDecimal("1"), config.getBigDecimal("value", null));
469     }
470 
471     public void testCommaSeparatedString()
472     {
473         String prop = "hey, that's a test";
474         config.setProperty("prop.string", prop);
475         try
476         {
477             config.getList("prop.string");
478         }
479         catch (NoSuchElementException nsse)
480         {
481             fail("Should return a list");
482         }
483 
484         String prop2 = "hey//, that's a test";
485         config.clearProperty("prop.string");
486         config.setProperty("prop.string", prop2);
487         try
488         {
489             config.getString("prop.string");
490         }
491         catch (NoSuchElementException nsse)
492         {
493             fail("Should return a list");
494         }
495 
496     }
497 
498     public void testAddProperty() throws Exception
499     {
500         Collection props = new ArrayList();
501         props.add("one");
502         props.add("two,three,four");
503         props.add(new String[] { "5.1", "5.2", "5.3,5.4", "5.5" });
504         props.add("six");
505         config.addProperty("complex.property", props);
506 
507         Object val = config.getProperty("complex.property");
508         assertTrue(val instanceof Collection);
509         Collection col = (Collection) val;
510         assertEquals(10, col.size());
511 
512         props = new ArrayList();
513         props.add("quick");
514         props.add("brown");
515         props.add("fox,jumps");
516         Object[] data = new Object[] {
517                 "The", props, "over,the", "lazy", "dog."
518         };
519         config.setProperty("complex.property", data);
520         val = config.getProperty("complex.property");
521         assertTrue(val instanceof Collection);
522         col = (Collection) val;
523         Iterator it = col.iterator();
524         StringTokenizer tok = new StringTokenizer("The quick brown fox jumps over the lazy dog.", " ");
525         while(tok.hasMoreTokens())
526         {
527             assertTrue(it.hasNext());
528             assertEquals(tok.nextToken(), it.next());
529         }
530         assertFalse(it.hasNext());
531 
532         config.setProperty("complex.property", null);
533         assertFalse(config.containsKey("complex.property"));
534     }
535 
536     public void testPropertyAccess()
537     {
538         config.clearProperty("prop.properties");
539         config.setProperty("prop.properties", "");
540         assertEquals(
541                 "This returns an empty Properties object",
542                 config.getProperties("prop.properties"),
543                 new Properties());
544         config.clearProperty("prop.properties");
545         config.setProperty("prop.properties", "foo=bar, baz=moo, seal=clubber");
546 
547         Properties p = new Properties();
548         p.setProperty("foo", "bar");
549         p.setProperty("baz", "moo");
550         p.setProperty("seal", "clubber");
551         assertEquals(
552                 "This returns a filled in Properties object",
553                 config.getProperties("prop.properties"),
554                 p);
555     }
556 
557     public void testSubset()
558     {
559         /*
560          * test subset : assure we don't reprocess the data elements
561          * when generating the subset
562          */
563 
564         String prop = "hey, that's a test";
565         String prop2 = "hey//, that's a test";
566         config.setProperty("prop.string", prop2);
567         config.setProperty("property.string", "hello");
568 
569         Configuration subEprop = config.subset("prop");
570 
571         assertEquals(
572                 "Returns the full string",
573                 prop,
574                 subEprop.getString("string"));
575         try
576         {
577             subEprop.getString("string");
578         }
579         catch (NoSuchElementException nsse)
580         {
581             fail("Should return a string");
582         }
583         try
584         {
585             subEprop.getList("string");
586         }
587         catch (NoSuchElementException nsse)
588         {
589             fail("Should return a list");
590         }
591 
592         Iterator it = subEprop.getKeys();
593         it.next();
594         assertFalse(it.hasNext());
595 
596         subEprop = config.subset("prop.");
597         it = subEprop.getKeys();
598         assertFalse(it.hasNext());
599     }
600 
601     public void testInterpolation()
602     {
603         InterpolationTestHelper.testInterpolation(config);
604     }
605 
606     public void testMultipleInterpolation()
607     {
608         InterpolationTestHelper.testMultipleInterpolation(config);
609     }
610 
611     public void testInterpolationLoop()
612     {
613         InterpolationTestHelper.testInterpolationLoop(config);
614     }
615 
616     /***
617      * Tests interpolation when a subset configuration is involved.
618      */
619     public void testInterpolationSubset()
620     {
621         InterpolationTestHelper.testInterpolationSubset(config);
622     }
623 
624     /***
625      * Tests interpolation when the referred property is not found.
626      */
627     public void testInterpolationUnknownProperty()
628     {
629         InterpolationTestHelper.testInterpolationUnknownProperty(config);
630     }
631 
632     /***
633      * Tests interpolation of system properties.
634      */
635     public void testInterpolationSystemProperties()
636     {
637         InterpolationTestHelper.testInterpolationSystemProperties(config);
638     }
639 
640     /***
641      * Tests interpolation of constant values.
642      */
643     public void testInterpolationConstants()
644     {
645         InterpolationTestHelper.testInterpolationConstants(config);
646     }
647 
648     /***
649      * Tests whether a variable can be escaped, so that it won't be
650      * interpolated.
651      */
652     public void testInterpolationEscaped()
653     {
654         InterpolationTestHelper.testInterpolationEscaped(config);
655     }
656 
657     /***
658      * Tests accessing and manipulating the interpolator object.
659      */
660     public void testGetInterpolator()
661     {
662         InterpolationTestHelper.testGetInterpolator(config);
663     }
664 
665     /***
666      * Tests obtaining a configuration with all variables replaced by their
667      * actual values.
668      */
669     public void testInterpolatedConfiguration()
670     {
671         InterpolationTestHelper.testInterpolatedConfiguration(config);
672     }
673 
674     public void testGetHexadecimalValue()
675     {
676         config.setProperty("number", "0xFF");
677         assertEquals("byte value", (byte) 0xFF, config.getByte("number"));
678 
679         config.setProperty("number", "0xFFFF");
680         assertEquals("short value", (short) 0xFFFF, config.getShort("number"));
681 
682         config.setProperty("number", "0xFFFFFFFF");
683         assertEquals("int value", 0xFFFFFFFF, config.getInt("number"));
684 
685         config.setProperty("number", "0xFFFFFFFFFFFFFFFF");
686         assertEquals("long value", 0xFFFFFFFFFFFFFFFFL, config.getLong("number"));
687 
688         assertEquals("long value", 0xFFFFFFFFFFFFFFFFL, config.getBigInteger("number").longValue());
689     }
690 
691     public void testResolveContainerStore()
692     {
693         AbstractConfiguration config = new BaseConfiguration();
694 
695         // array of objects
696         config.addPropertyDirect("array", new String[] { "foo", "bar" });
697 
698         assertEquals("first element of the 'array' property", "foo", config.resolveContainerStore("array"));
699 
700         // list of objects
701         List list = new ArrayList();
702         list.add("foo");
703         list.add("bar");
704         config.addPropertyDirect("list", list);
705 
706         assertEquals("first element of the 'list' property", "foo", config.resolveContainerStore("list"));
707 
708         // set of objects
709         Set set = new ListOrderedSet();
710         set.add("foo");
711         set.add("bar");
712         config.addPropertyDirect("set", set);
713 
714         assertEquals("first element of the 'set' property", "foo", config.resolveContainerStore("set"));
715 
716         // arrays of primitives
717         config.addPropertyDirect("array.boolean", new boolean[] { true, false });
718         assertEquals("first element of the 'array.boolean' property", true, config.getBoolean("array.boolean"));
719 
720         config.addPropertyDirect("array.byte", new byte[] { 1, 2 });
721         assertEquals("first element of the 'array.byte' property", 1, config.getByte("array.byte"));
722 
723         config.addPropertyDirect("array.short", new short[] { 1, 2 });
724         assertEquals("first element of the 'array.short' property", 1, config.getShort("array.short"));
725 
726         config.addPropertyDirect("array.int", new int[] { 1, 2 });
727         assertEquals("first element of the 'array.int' property", 1, config.getInt("array.int"));
728 
729         config.addPropertyDirect("array.long", new long[] { 1, 2 });
730         assertEquals("first element of the 'array.long' property", 1, config.getLong("array.long"));
731 
732         config.addPropertyDirect("array.float", new float[] { 1, 2 });
733         assertEquals("first element of the 'array.float' property", 1, config.getFloat("array.float"), 0);
734 
735         config.addPropertyDirect("array.double", new double[] { 1, 2 });
736         assertEquals("first element of the 'array.double' property", 1, config.getDouble("array.double"), 0);
737     }
738 
739     /***
740      * Tests if conversion between number types is possible.
741      */
742     public void testNumberConversions()
743     {
744         config.setProperty(KEY_NUMBER, new Integer(42));
745         assertEquals("Wrong int returned", 42, config.getInt(KEY_NUMBER));
746         assertEquals("Wrong long returned", 42L, config.getLong(KEY_NUMBER));
747         assertEquals("Wrong byte returned", (byte) 42, config
748                 .getByte(KEY_NUMBER));
749         assertEquals("Wrong float returned", 42.0f,
750                 config.getFloat(KEY_NUMBER), 0.01f);
751         assertEquals("Wrong double returned", 42.0, config
752                 .getDouble(KEY_NUMBER), 0.001);
753 
754         assertEquals("Wrong Long returned", new Long(42L), config.getLong(
755                 KEY_NUMBER, null));
756         assertEquals("Wrong BigInt returned", new BigInteger("42"), config
757                 .getBigInteger(KEY_NUMBER));
758         assertEquals("Wrong DigDecimal returned", new BigDecimal("42"), config
759                 .getBigDecimal(KEY_NUMBER));
760     }
761 
762     /***
763      * Tests cloning a BaseConfiguration.
764      */
765     public void testClone()
766     {
767         for (int i = 0; i < 10; i++)
768         {
769             config.addProperty("key" + i, new Integer(i));
770         }
771         BaseConfiguration config2 = (BaseConfiguration) config.clone();
772 
773         for (Iterator it = config.getKeys(); it.hasNext();)
774         {
775             String key = (String) it.next();
776             assertTrue("Key not found: " + key, config2.containsKey(key));
777             assertEquals("Wrong value for key " + key, config.getProperty(key),
778                     config2.getProperty(key));
779         }
780     }
781 
782     /***
783      * Tests whether a cloned configuration is decoupled from its original.
784      */
785     public void testCloneModify()
786     {
787         ConfigurationListener l = new ConfigurationListener()
788         {
789             public void configurationChanged(ConfigurationEvent event)
790             {
791                 // just a dummy
792             }
793         };
794         config.addConfigurationListener(l);
795         config.addProperty("original", Boolean.TRUE);
796         BaseConfiguration config2 = (BaseConfiguration) config.clone();
797 
798         config2.addProperty("clone", Boolean.TRUE);
799         assertFalse("New key appears in original", config.containsKey("clone"));
800         config2.setProperty("original", Boolean.FALSE);
801         assertTrue("Wrong value of original property", config
802                 .getBoolean("original"));
803 
804         assertEquals("Event listener was copied", 0, config2
805                 .getConfigurationListeners().size());
806     }
807 }