    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.Iterator;
    23  import java.util.List;
    24  import java.util.NoSuchElementException;
    25  import java.util.Properties;
    26
    27  import junit.framework.TestCase;
    28  import junitx.framework.ObjectAssert;
    29
    30  /***
    31   * Tests some basic functions of the BaseConfiguration class. Missing keys might
    32   * return null.
    33   *
    34   * @version $Id: TestBaseNullConfiguration.java 439648 2006-09-02 20:42:10Z oheger $
    35   */
    36  public class TestBaseNullConfiguration extends TestCase
    37  {
    38      protected BaseConfiguration config = null;
    39
    40      protected static Class missingElementException = NoSuchElementException.class;
    41      protected static Class incompatibleElementException = ConversionException.class;
    42
    43      protected void setUp() throws Exception
    44      {
    45          config = new BaseConfiguration();
    46          config.setThrowExceptionOnMissing(false);
    47      }
    48
    49      public void testThrowExceptionOnMissing()
    50      {
    51          assertFalse("Throw Exception Property is set!", config.isThrowExceptionOnMissing());
    52      }
    53
    54      public void testGetProperty()
    55      {
    56          /* should be empty and return null */
    57          assertEquals("This returns null", config.getProperty("foo"), null);
    58
    59          /* add a real value, and get it two different ways */
    60          config.setProperty("number", "1");
    61          assertEquals("This returns '1'", config.getProperty("number"), "1");
    62          assertEquals("This returns '1'", config.getString("number"), "1");
    63      }
    64
    65      public void testGetByte()
    66      {
    67          config.setProperty("number", "1");
    68          byte oneB = 1;
    69          byte twoB = 2;
    70          assertEquals("This returns 1(byte)", oneB, config.getByte("number"));
    71          assertEquals("This returns 1(byte)", oneB, config.getByte("number", twoB));
    72          assertEquals("This returns 2(default byte)", twoB, config.getByte("numberNotInConfig", twoB));
    73          assertEquals("This returns 1(Byte)", new Byte(oneB), config.getByte("number", new Byte("2")));
    74
    75          // missing key without default value
    76          Throwable t = null;
    77          try {
    78              config.getByte("numberNotInConfig");
    79          } catch (Throwable T) {
    80              t = T;
    81          }
    82          assertNotNull("No exception thrown for missing keys", t);
    83          ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
    84
    85          // existing key with an incompatible value
    86          config.setProperty("test.empty", "");
    87          t = null;
    88          try {
    89              config.getByte("test.empty");
    90          } catch (Throwable T) {
    91              t = T;
    92          }
    93          assertNotNull("No exception thrown for incompatible values", t);
    94          ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    95      }
    96
    97      public void testGetShort()
    98      {
    99          config.setProperty("numberS", "1");
    100         short oneS = 1;
    101         short twoS = 2;
    102         assertEquals("This returns 1(short)", oneS, config.getShort("numberS"));
    103         assertEquals("This returns 1(short)", oneS, config.getShort("numberS", twoS));
    104         assertEquals("This returns 2(default short)", twoS, config.getShort("numberNotInConfig", twoS));
    105         assertEquals("This returns 1(Short)", new Short(oneS), config.getShort("numberS", new Short("2")));
    106
    107         // missing key without default value
    108         Throwable t = null;
    109         try {
    110             config.getShort("numberNotInConfig");
    111         } catch (Throwable T) {
    112             t = T;
    113         }
    114         assertNotNull("No exception thrown for missing keys", t);
    115         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
    116
    117         // existing key with an incompatible value
    118         config.setProperty("test.empty", "");
    119         t = null;
    120         try {
    121             config.getShort("test.empty");
    122         } catch (Throwable T) {
    123             t = T;
    124         }
    125         assertNotNull("No exception thrown for incompatible values", t);
    126         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    127     }
    128
    129     public void testGetLong()
    130     {
    131         config.setProperty("numberL", "1");
    132         long oneL = 1;
    133         long twoL = 2;
    134         assertEquals("This returns 1(long)", oneL, config.getLong("numberL"));
    135         assertEquals("This returns 1(long)", oneL, config.getLong("numberL", twoL));
    136         assertEquals("This returns 2(default long)", twoL, config.getLong("numberNotInConfig", twoL));
    137         assertEquals("This returns 1(Long)", new Long(oneL), config.getLong("numberL", new Long("2")));
    138
    139         // missing key without default value
    140         Throwable t = null;
    141         try {
    142             config.getLong("numberNotInConfig");
    143         } catch (Throwable T) {
    144             t = T;
    145         }
    146         assertNotNull("No exception thrown for missing keys", t);
    147         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
    148
    149         // existing key with an incompatible value
    150         config.setProperty("test.empty", "");
    151         t = null;
    152         try {
    153             config.getLong("test.empty");
    154         } catch (Throwable T) {
    155             t = T;
    156         }
    157         assertNotNull("No exception thrown for incompatible values", t);
    158         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    159     }
    160
    161     public void testGetFloat()
    162     {
    163         config.setProperty("numberF", "1.0");
    164         float oneF = 1;
    165         float twoF = 2;
    166         assertEquals("This returns 1(float)", oneF, config.getFloat("numberF"), 0);
    167         assertEquals("This returns 1(float)", oneF, config.getFloat("numberF", twoF), 0);
    168         assertEquals("This returns 2(default float)", twoF, config.getFloat("numberNotInConfig", twoF), 0);
    169         assertEquals("This returns 1(Float)", new Float(oneF), config.getFloat("numberF", new Float("2")));
    170
    171         // missing key without default value
    172         Throwable t = null;
    173         try {
    174             config.getFloat("numberNotInConfig");
    175         } catch (Throwable T) {
    176             t = T;
    177         }
    178         assertNotNull("No exception thrown for missing keys", t);
    179         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
    180
    181         // existing key with an incompatible value
    182         config.setProperty("test.empty", "");
    183         t = null;
    184         try {
    185             config.getFloat("test.empty");
    186         } catch (Throwable T) {
    187             t = T;
    188         }
    189         assertNotNull("No exception thrown for incompatible values", t);
    190         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    191     }
    192
    193     public void testGetDouble()
    194     {
    195         config.setProperty("numberD", "1.0");
    196         double oneD = 1;
    197         double twoD = 2;
    198         assertEquals("This returns 1(double)", oneD, config.getDouble("numberD"), 0);
    199         assertEquals("This returns 1(double)", oneD, config.getDouble("numberD", twoD), 0);
    200         assertEquals("This returns 2(default double)", twoD, config.getDouble("numberNotInConfig", twoD), 0);
    201         assertEquals("This returns 1(Double)", new Double(oneD), config.getDouble("numberD", new Double("2")));
    202
    203         // missing key without default value
    204         Throwable t = null;
    205         try {
    206             config.getDouble("numberNotInConfig");
    207         } catch (Throwable T) {
    208             t = T;
    209         }
    210         assertNotNull("No exception thrown for missing keys", t);
    211         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
    212
    213         // existing key with an incompatible value
    214         config.setProperty("test.empty", "");
    215         t = null;
    216         try {
    217             config.getDouble("test.empty");
    218         } catch (Throwable T) {
    219             t = T;
    220         }
    221         assertNotNull("No exception thrown for incompatible values", t);
    222         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    223     }
    224
    225     public void testGetBigDecimal()
    226     {
    227         config.setProperty("numberBigD", "123.456");
    228         BigDecimal number = new BigDecimal("123.456");
    229         BigDecimal defaultValue = new BigDecimal("654.321");
    230
    231         assertEquals("Existing key", number, config.getBigDecimal("numberBigD"));
    232         assertEquals("Existing key with default value", number, config.getBigDecimal("numberBigD", defaultValue));
    233         assertEquals("Missing key with default value", defaultValue, config.getBigDecimal("numberNotInConfig", defaultValue));
    234
    235         // missing key without default value
    236                 assertEquals("Missing Key is not null!", null, config.getBigDecimal("numberNotInConfig"));
    237
    238         // existing key with an incompatible value
    239         config.setProperty("test.empty", "");
    240         Throwable t = null;
    241         try {
    242             config.getBigDecimal("test.empty");
    243         } catch (Throwable T) {
    244             t = T;
    245         }
    246         assertNotNull("No exception thrown for incompatible values", t);
    247         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    248     }
    249
    250     public void testGetBigInteger()
    251     {
    252         config.setProperty("numberBigI", "1234567890");
    253         BigInteger number = new BigInteger("1234567890");
    254         BigInteger defaultValue = new BigInteger("654321");
    255
    256         assertEquals("Existing key", number, config.getBigInteger("numberBigI"));
    257         assertEquals("Existing key with default value", number, config.getBigInteger("numberBigI", defaultValue));
    258         assertEquals("Missing key with default value", defaultValue, config.getBigInteger("numberNotInConfig", defaultValue));
    259
    260         // missing key without default value
    261                 assertEquals("Missing Key is not null!", null, config.getBigInteger("numberNotInConfig"));
    262
    263         // existing key with an incompatible value
    264         config.setProperty("test.empty", "");
    265         Throwable t = null;
    266         try {
    267             config.getBigInteger("test.empty");
    268         } catch (Throwable T) {
    269             t = T;
    270         }
    271         assertNotNull("No exception thrown for incompatible values", t);
    272         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    273     }
    274
    275
    276     public void testGetString()
    277     {
    278         config.setProperty("testString", "The quick brown fox");
    279         String string = new String("The quick brown fox");
    280         String defaultValue = new String("jumps over the lazy dog");
    281
    282         assertEquals("Existing key", string, config.getString("testString"));
    283         assertEquals("Existing key with default value", string, config.getString("testString", defaultValue));
    284         assertEquals("Missing key with default value", defaultValue, config.getString("stringNotInConfig", defaultValue));
    285
    286         // missing key without default value
    287                 assertEquals("Missing Key is not null!", null, config.getString("stringNotInConfig"));
    288
    289     }
    290
    291     public void testGetBoolean()
    292     {
    293         config.setProperty("boolA", Boolean.TRUE);
    294         boolean boolT = true, boolF = false;
    295         assertEquals("This returns true", boolT, config.getBoolean("boolA"));
    296         assertEquals("This returns true, not the default", boolT, config.getBoolean("boolA", boolF));
    297         assertEquals("This returns false(default)", boolF, config.getBoolean("boolNotInConfig", boolF));
    298         assertEquals("This returns true(Boolean)", new Boolean(boolT), config.getBoolean("boolA", new Boolean(boolF)));
    299
    300         // missing key without default value
    301         Throwable t = null;
    302         try {
    303             config.getBoolean("numberNotInConfig");
    304         } catch (Throwable T) {
    305             t = T;
    306         }
    307         assertNotNull("No exception thrown for missing keys", t);
    308         ObjectAssert.assertInstanceOf("Exception thrown for missing keys", missingElementException, t);
    309
    310         // existing key with an incompatible value
    311         config.setProperty("test.empty", "");
    312         t = null;
    313         try {
    314             config.getBoolean("test.empty");
    315         } catch (Throwable T) {
    316             t = T;
    317         }
    318         assertNotNull("No exception thrown for incompatible values", t);
    319         ObjectAssert.assertInstanceOf("Exception thrown for incompatible values", incompatibleElementException, t);
    320     }
    321
    322     public void testGetList()
    323     {
    324         config.addProperty("number", "1");
    325         config.addProperty("number", "2");
    326         List list = config.getList("number");
    327         assertNotNull("The list is null", list);
    328         assertEquals("List size", 2, list.size());
    329         assertTrue("The number 1 is missing from the list", list.contains("1"));
    330         assertTrue("The number 2 is missing from the list", list.contains("2"));
    331
    332         /*
    333          *  now test dan's new fix where we get the first scalar
    334          *  when we access a list valued property
    335          */
    336         try
    337         {
    338             config.getString("number");
    339         }
    340         catch (NoSuchElementException nsse)
    341         {
    342             fail("Should return a string");
    343         }
    344     }
    345
    346     public void testCommaSeparatedString()
    347     {
    348         String prop = "hey, that's a test";
    349         config.setProperty("prop.string", prop);
    350         try
    351         {
    352             config.getList("prop.string");
    353         }
    354         catch (NoSuchElementException nsse)
    355         {
    356             fail("Should return a list");
    357         }
    358
    359         String prop2 = "hey//, that's a test";
    360         config.clearProperty("prop.string");
    361         config.setProperty("prop.string", prop2);
    362         try
    363         {
    364             config.getString("prop.string");
    365         }
    366         catch (NoSuchElementException nsse)
    367         {
    368             fail("Should return a list");
    369         }
    370
    371     }
    372
    373     public void testPropertyAccess()
    374     {
    375         config.clearProperty("prop.properties");
    376         config.setProperty("prop.properties", "");
    377         assertEquals(
    378             "This returns an empty Properties object",
    379             config.getProperties("prop.properties"),
    380             new Properties());
    381         config.clearProperty("prop.properties");
    382         config.setProperty("prop.properties", "foo=bar, baz=moo, seal=clubber");
    383
    384         Properties p = new Properties();
    385         p.setProperty("foo", "bar");
    386         p.setProperty("baz", "moo");
    387         p.setProperty("seal", "clubber");
    388         assertEquals(
    389             "This returns a filled in Properties object",
    390             config.getProperties("prop.properties"),
    391             p);
    392     }
    393
    394     public void testSubset()
    395     {
    396         /*
    397          * test subset : assure we don't reprocess the data elements
    398          * when generating the subset
    399          */
    400
    401         String prop = "hey, that's a test";
    402         String prop2 = "hey//, that's a test";
    403         config.setProperty("prop.string", prop2);
    404         config.setProperty("property.string", "hello");
    405
    406         Configuration subEprop = config.subset("prop");
    407
    408         assertEquals(
    409             "Returns the full string",
    410             prop,
    411             subEprop.getString("string"));
    412         try
    413         {
    414             subEprop.getString("string");
    415         }
    416         catch (NoSuchElementException nsse)
    417         {
    418             fail("Should return a string");
    419         }
    420         try
    421         {
    422             subEprop.getList("string");
    423         }
    424         catch (NoSuchElementException nsse)
    425         {
    426             fail("Should return a list");
    427         }
    428
    429         Iterator it = subEprop.getKeys();
    430         it.next();
    431         assertFalse(it.hasNext());
    432
    433         subEprop = config.subset("prop.");
    434         it = subEprop.getKeys();
    435         assertFalse(it.hasNext());
    436     }
    437
    438     public void testInterpolation() throws Exception
    439     {
    440         config.setProperty("applicationRoot", "/home/applicationRoot");
    441         config.setProperty("db", "${applicationRoot}/db/hypersonic");
    442         String unInterpolatedValue = "${applicationRoot2}/db/hypersonic";
    443         config.setProperty("dbFailedInterpolate", unInterpolatedValue);
    444         String dbProp = "/home/applicationRoot/db/hypersonic";
    445
    446         //construct a new config, using config as the defaults config for it.
    447         BaseConfiguration superProp = config;
    448
    449         assertEquals(
    450             "Checking interpolated variable",dbProp,
    451             superProp.getString("db"));
    452         assertEquals(
    453             "lookup fails, leave variable as is",
    454             superProp.getString("dbFailedInterpolate"),
    455             unInterpolatedValue);
    456
    457         superProp.setProperty("arrayInt", "${applicationRoot}/1");
    458         String[] arrayInt = superProp.getStringArray("arrayInt");
    459         assertEquals(
    460             "check first entry was interpolated",
    461             "/home/applicationRoot/1",
    462             arrayInt[0]);
    463     }
    464
    465     public void testMultipleInterpolation() throws Exception
    466     {
    467         config.setProperty("test.base-level", "/base-level");
    468         config.setProperty("test.first-level", "${test.base-level}/first-level");
    469         config.setProperty(
    470             "test.second-level",
    471             "${test.first-level}/second-level");
    472         config.setProperty(
    473             "test.third-level",
    474             "${test.second-level}/third-level");
    475
    476         String expectedValue =
    477             "/base-level/first-level/second-level/third-level";
    478
    479         assertEquals(config.getString("test.third-level"), expectedValue);
    480     }
    481
    482     public void testInterpolationLoop() throws Exception
    483     {
    484         config.setProperty("test.a", "${test.b}");
    485         config.setProperty("test.b", "${test.a}");
    486
    487         try
    488         {
    489             config.getString("test.a");
    490         }
    491         catch (IllegalStateException e)
    492         {
    493             return;
    494         }
    495
    496         fail("IllegalStateException should have been thrown for looped property references");
    497     }
    498
    499 }
    500