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