    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  package org.apache.commons.configuration.event;
    18
    19  import java.util.LinkedList;
    20
    21  import org.apache.commons.configuration.AbstractConfiguration;
    22  import org.apache.commons.configuration.event.ConfigurationEvent;
    23  import org.apache.commons.configuration.event.ConfigurationListener;
    24
    25  import junit.framework.TestCase;
    26
    27  /***
    28   * Base class for testing events generated by configuration classes derived from
    29   * AbstractConfiguration. This class implements a couple of tests related to
    30   * event generation. Concrete sub classes only have to implement the
    31   * <code>createConfiguration()</code> method for creating an instance of a
    32   * specific configuration class. Because tests for detail events depend on a
    33   * concrete implementation an exact sequence of events cannot be checked.
    34   * Instead the corresponding test methods check whether the enclosing events
    35   * (not the detail events) are of the expected type.
    36   *
    37   * @version $Id: AbstractTestConfigurationEvents.java 439648 2006-09-02 20:42:10Z oheger $
    38   */
    39  public abstract class AbstractTestConfigurationEvents extends TestCase
    40  {
    41      /*** Constant for a test property name. */
    42      static final String TEST_PROPNAME = "event.test";
    43
    44      /*** Constant for a test property value. */
    45      static final String TEST_PROPVALUE = "a value";
    46
    47      /*** Constant for an existing property. */
    48      static final String EXIST_PROPERTY = "event.property";
    49
    50      /*** The configuration to be tested. */
    51      protected AbstractConfiguration config;
    52
    53      /*** A test event listener. */
    54      protected TestConfigurationListener l;
    55
    56      protected void setUp() throws Exception
    57      {
    58          super.setUp();
    59          config = createConfiguration();
    60          config.addProperty(EXIST_PROPERTY, "existing value");
    61          l = new TestConfigurationListener();
    62          config.addConfigurationListener(l);
    63      }
    64
    65      /***
    66       * Creates the configuration instance to be tested.
    67       *
    68       * @return the configuration instance under test
    69       */
    70      protected abstract AbstractConfiguration createConfiguration();
    71
    72      /***
    73       * Tests events generated by addProperty().
    74       */
    75      public void testAddPropertyEvent()
    76      {
    77          config.addProperty(TEST_PROPNAME, TEST_PROPVALUE);
    78          l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME,
    79                  TEST_PROPVALUE, true);
    80          l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME,
    81                  TEST_PROPVALUE, false);
    82          l.done();
    83      }
    84
    85      /***
    86       * Tests events generated by addProperty() when detail events are enabled.
    87       */
    88      public void testAddPropertyEventWithDetails()
    89      {
    90          config.setDetailEvents(true);
    91          config.addProperty(TEST_PROPNAME, TEST_PROPVALUE);
    92          l.checkEventCount(2);
    93          l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME,
    94                  TEST_PROPVALUE, true);
    95          l.skipToLast(AbstractConfiguration.EVENT_ADD_PROPERTY);
    96          l.checkEvent(AbstractConfiguration.EVENT_ADD_PROPERTY, TEST_PROPNAME,
    97                  TEST_PROPVALUE, false);
    98          l.done();
    99      }
    100
    101     /***
    102      * Tests events generated by clearProperty().
    103      */
    104     public void testClearPropertyEvent()
    105     {
    106         config.clearProperty(EXIST_PROPERTY);
    107         l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY,
    108                 EXIST_PROPERTY, null, true);
    109         l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY,
    110                 EXIST_PROPERTY, null, false);
    111         l.done();
    112     }
    113
    114     /***
    115      * Tests events generated by clearProperty() when detail events are enabled.
    116      */
    117     public void testClearPropertyEventWithDetails()
    118     {
    119         config.setDetailEvents(true);
    120         config.clearProperty(EXIST_PROPERTY);
    121         l.checkEventCount(2);
    122         l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY,
    123                 EXIST_PROPERTY, null, true);
    124         l.skipToLast(AbstractConfiguration.EVENT_CLEAR_PROPERTY);
    125         l.checkEvent(AbstractConfiguration.EVENT_CLEAR_PROPERTY,
    126                 EXIST_PROPERTY, null, false);
    127         l.done();
    128     }
    129
    130     /***
    131      * Tests events generated by setProperty().
    132      */
    133     public void testSetPropertyEvent()
    134     {
    135         config.setProperty(EXIST_PROPERTY, TEST_PROPVALUE);
    136         l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY,
    137                 TEST_PROPVALUE, true);
    138         l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY,
    139                 TEST_PROPVALUE, false);
    140         l.done();
    141     }
    142
    143     /***
    144      * Tests events generated by setProperty() when detail events are enabled.
    145      */
    146     public void testSetPropertyEventWithDetails()
    147     {
    148         config.setDetailEvents(true);
    149         config.setProperty(EXIST_PROPERTY, TEST_PROPVALUE);
    150         l.checkEventCount(2);
    151         l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY,
    152                 TEST_PROPVALUE, true);
    153         l.skipToLast(AbstractConfiguration.EVENT_SET_PROPERTY);
    154         l.checkEvent(AbstractConfiguration.EVENT_SET_PROPERTY, EXIST_PROPERTY,
    155                 TEST_PROPVALUE, false);
    156         l.done();
    157     }
    158
    159     /***
    160      * Tests the events generated by the clear() method.
    161      */
    162     public void testClearEvent()
    163     {
    164         config.clear();
    165         l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, true);
    166         l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, false);
    167         l.done();
    168     }
    169
    170     /***
    171      * Tests the events generated by the clear method when detail events are
    172      * enabled.
    173      */
    174     public void testClearEventWithDetails()
    175     {
    176         config.setDetailEvents(true);
    177         config.clear();
    178         l.checkEventCount(2);
    179         l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, true);
    180         l.skipToLast(AbstractConfiguration.EVENT_CLEAR);
    181         l.checkEvent(AbstractConfiguration.EVENT_CLEAR, null, null, false);
    182         l.done();
    183     }
    184
    185     /***
    186      * A test event listener class used for testing events generated by the
    187      * configuration.
    188      */
    189     class TestConfigurationListener implements ConfigurationListener
    190     {
    191         /*** Stores the received events. */
    192         private LinkedList events = new LinkedList();
    193
    194         public void configurationChanged(ConfigurationEvent event)
    195         {
    196             events.add(event);
    197         }
    198
    199         /***
    200          * Checks if at least <code>minEvents</code> events have been
    201          * received.
    202          *
    203          * @param minEvents the minimum number of expected events
    204          */
    205         public void checkEventCount(int minEvents)
    206         {
    207             assertTrue("Too view events received", events.size() >= minEvents);
    208         }
    209
    210         /***
    211          * Checks an expected event.
    212          *
    213          * @param type the event type
    214          * @param propName the expected property name
    215          * @param propValue the expected property value
    216          * @param before the expected before flag
    217          */
    218         public void checkEvent(int type, String propName, Object propValue,
    219                 boolean before)
    220         {
    221             assertFalse("Too few events received", events.isEmpty());
    222             ConfigurationEvent e = (ConfigurationEvent) events.removeFirst();
    223             assertEquals("Wrong event source", config, e.getSource());
    224             assertEquals("Wrong event type", type, e.getType());
    225             assertEquals("Wrong property name", propName, e.getPropertyName());
    226             assertEquals("Wrong property value", propValue, e
    227                     .getPropertyValue());
    228             assertEquals("Wrong before flag", before, e.isBeforeUpdate());
    229         }
    230
    231         /***
    232          * Skips to the last received event and checks that no events of the
    233          * given type have been received. This method is used by checks for
    234          * detail events to ignore the detail events.
    235          *
    236          * @param type the event type
    237          */
    238         public void skipToLast(int type)
    239         {
    240             while (events.size() > 1)
    241             {
    242                 ConfigurationEvent e = (ConfigurationEvent) events
    243                         .removeFirst();
    244                 assertTrue("Found end event in details", type != e.getType());
    245             }
    246         }
    247
    248         /***
    249          * Checks if all events has been processed.
    250          */
    251         public void done()
    252         {
    253             assertTrue("Too many events received", events.isEmpty());
    254         }
    255     }
    256 }