    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.Collection;
    20
    21  import junit.framework.TestCase;
    22
    23  /***
    24   * Test class for EventSource.
    25   *
    26   * @version $Id: TestEventSource.java 495918 2007-01-13 16:33:02Z oheger $
    27   */
    28  public class TestEventSource extends TestCase
    29  {
    30      /*** Constant for the event type used for testing. */
    31      static final int TEST_TYPE = 42;
    32
    33      /*** Constant for the event property name. */
    34      static final String TEST_PROPNAME = "test.property.name";
    35
    36      /*** Constant for the event property value. */
    37      static final Object TEST_PROPVALUE = "a test property value";
    38
    39      /*** The object under test. */
    40      CountingEventSource source;
    41
    42      protected void setUp() throws Exception
    43      {
    44          super.setUp();
    45          source = new CountingEventSource();
    46      }
    47
    48      /***
    49       * Tests a newly created source object.
    50       */
    51      public void testInit()
    52      {
    53          assertTrue("Listeners list is not empty", source
    54                  .getConfigurationListeners().isEmpty());
    55          assertFalse("Removing listener", source
    56                  .removeConfigurationListener(new TestListener()));
    57          assertFalse("Detail events are enabled", source.isDetailEvents());
    58          assertTrue("Error listeners list is not empty", source
    59                  .getErrorListeners().isEmpty());
    60      }
    61
    62      /***
    63       * Tests registering a new listener.
    64       */
    65      public void testAddConfigurationListener()
    66      {
    67          TestListener l = new TestListener();
    68          source.addConfigurationListener(l);
    69          Collection listeners = source.getConfigurationListeners();
    70          assertEquals("Wrong number of listeners", 1, listeners.size());
    71          assertTrue("Listener not in list", listeners.contains(l));
    72      }
    73
    74      /***
    75       * Tests adding an undefined configuration listener. This should cause an
    76       * exception.
    77       */
    78      public void testAddNullConfigurationListener()
    79      {
    80          try
    81          {
    82              source.addConfigurationListener(null);
    83              fail("Could add null listener!");
    84          }
    85          catch (IllegalArgumentException iex)
    86          {
    87              // ok
    88          }
    89      }
    90
    91      /***
    92       * Tests removing a listener.
    93       */
    94      public void testRemoveConfigurationListener()
    95      {
    96          TestListener l = new TestListener();
    97          assertFalse("Listener can be removed?", source
    98                  .removeConfigurationListener(l));
    99          source.addConfigurationListener(l);
    100         source.addConfigurationListener(new TestListener());
    101         assertFalse("Unknown listener can be removed", source
    102                 .removeConfigurationListener(new TestListener()));
    103         assertTrue("Could not remove listener", source
    104                 .removeConfigurationListener(l));
    105         assertFalse("Listener still in list", source
    106                 .getConfigurationListeners().contains(l));
    107     }
    108
    109     /***
    110      * Tests if a null listener can be removed. This should be a no-op.
    111      */
    112     public void testRemoveNullConfigurationListener()
    113     {
    114         source.addConfigurationListener(new TestListener());
    115         assertFalse("Null listener can be removed", source
    116                 .removeConfigurationListener(null));
    117         assertEquals("Listener list was modified", 1, source
    118                 .getConfigurationListeners().size());
    119     }
    120
    121     /***
    122      * Tests whether the listeners list is read only.
    123      */
    124     public void testGetConfigurationListenersUpdate()
    125     {
    126         source.addConfigurationListener(new TestListener());
    127         Collection list = source.getConfigurationListeners();
    128         try
    129         {
    130             list.add("test");
    131             fail("Could manipulate list!");
    132         }
    133         catch (Exception ex)
    134         {
    135             // ok
    136         }
    137     }
    138
    139     /***
    140      * Tests that the collection returned by getConfigurationListeners() is
    141      * really a snapshot. A later added listener must not be visible.
    142      */
    143     public void testGetConfigurationListenersAddNew()
    144     {
    145         Collection list = source.getConfigurationListeners();
    146         source.addConfigurationListener(new TestListener());
    147         assertTrue("Listener snapshot not empty", list.isEmpty());
    148     }
    149
    150     /***
    151      * Tests enabling and disabling the detail events flag.
    152      */
    153     public void testSetDetailEvents()
    154     {
    155         source.setDetailEvents(true);
    156         assertTrue("Detail events are disabled", source.isDetailEvents());
    157         source.setDetailEvents(true);
    158         source.setDetailEvents(false);
    159         assertTrue("Detail events are disabled again", source.isDetailEvents());
    160         source.setDetailEvents(false);
    161         assertFalse("Detail events are still enabled", source.isDetailEvents());
    162     }
    163
    164     /***
    165      * Tests delivering an event to a listener.
    166      */
    167     public void testFireEvent()
    168     {
    169         TestListener l = new TestListener();
    170         source.addConfigurationListener(l);
    171         source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, true);
    172         assertEquals("Not 1 event created", 1, source.eventCount);
    173         assertEquals("Listener not called once", 1, l.numberOfCalls);
    174         assertEquals("Wrong event type", TEST_TYPE, l.lastEvent.getType());
    175         assertEquals("Wrong property name", TEST_PROPNAME, l.lastEvent
    176                 .getPropertyName());
    177         assertEquals("Wrong property value", TEST_PROPVALUE, l.lastEvent
    178                 .getPropertyValue());
    179         assertTrue("Wrong before event flag", l.lastEvent.isBeforeUpdate());
    180     }
    181
    182     /***
    183      * Tests firering an event if there are no listeners.
    184      */
    185     public void testFireEventNoListeners()
    186     {
    187         source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false);
    188         assertEquals("An event object was created", 0, source.eventCount);
    189     }
    190
    191     /***
    192      * Tests generating a detail event if detail events are not allowed.
    193      */
    194     public void testFireEventNoDetails()
    195     {
    196         TestListener l = new TestListener();
    197         source.addConfigurationListener(l);
    198         source.setDetailEvents(false);
    199         source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false);
    200         assertEquals("Event object was created", 0, source.eventCount);
    201         assertEquals("Listener was called", 0, l.numberOfCalls);
    202     }
    203
    204     /***
    205      * Tests whether an event listener can deregister itself in reaction of a
    206      * delivered event.
    207      */
    208     public void testRemoveListenerInFireEvent()
    209     {
    210         ConfigurationListener lstRemove = new ConfigurationListener()
    211         {
    212             public void configurationChanged(ConfigurationEvent event)
    213             {
    214                 source.removeConfigurationListener(this);
    215             }
    216         };
    217
    218         source.addConfigurationListener(lstRemove);
    219         TestListener l = new TestListener();
    220         source.addConfigurationListener(l);
    221         source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false);
    222         assertEquals("Listener was not called", 1, l.numberOfCalls);
    223         assertEquals("Listener was not removed", 1, source
    224                 .getConfigurationListeners().size());
    225     }
    226
    227     /***
    228      * Tests registering a new error listener.
    229      */
    230     public void testAddErrorListener()
    231     {
    232         TestListener l = new TestListener();
    233         source.addErrorListener(l);
    234         Collection listeners = source.getErrorListeners();
    235         assertEquals("Wrong number of listeners", 1, listeners.size());
    236         assertTrue("Listener not in list", listeners.contains(l));
    237     }
    238
    239     /***
    240      * Tests adding an undefined error listener. This should cause an exception.
    241      */
    242     public void testAddNullErrorListener()
    243     {
    244         try
    245         {
    246             source.addErrorListener(null);
    247             fail("Could add null error listener!");
    248         }
    249         catch (IllegalArgumentException iex)
    250         {
    251             // ok
    252         }
    253     }
    254
    255     /***
    256      * Tests removing an error listener.
    257      */
    258     public void testRemoveErrorListener()
    259     {
    260         TestListener l = new TestListener();
    261         assertFalse("Listener can be removed?", source.removeErrorListener(l));
    262         source.addErrorListener(l);
    263         source.addErrorListener(new TestListener());
    264         assertFalse("Unknown listener can be removed", source
    265                 .removeErrorListener(new TestListener()));
    266         assertTrue("Could not remove listener", source.removeErrorListener(l));
    267         assertFalse("Listener still in list", source.getErrorListeners()
    268                 .contains(l));
    269     }
    270
    271     /***
    272      * Tests if a null error listener can be removed. This should be a no-op.
    273      */
    274     public void testRemoveNullErrorListener()
    275     {
    276         source.addErrorListener(new TestListener());
    277         assertFalse("Null listener can be removed", source
    278                 .removeErrorListener(null));
    279         assertEquals("Listener list was modified", 1, source
    280                 .getErrorListeners().size());
    281     }
    282
    283     /***
    284      * Tests whether the listeners list is read only.
    285      */
    286     public void testGetErrorListenersUpdate()
    287     {
    288         source.addErrorListener(new TestListener());
    289         Collection list = source.getErrorListeners();
    290         try
    291         {
    292             list.add("test");
    293             fail("Could manipulate list!");
    294         }
    295         catch (Exception ex)
    296         {
    297             // ok
    298         }
    299     }
    300
    301     /***
    302      * Tests delivering an error event to a listener.
    303      */
    304     public void testFireError()
    305     {
    306         TestListener l = new TestListener();
    307         source.addErrorListener(l);
    308         Exception testException = new Exception("A test");
    309         source.fireError(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE,
    310                 testException);
    311         assertEquals("Not 1 event created", 1, source.errorCount);
    312         assertEquals("Error listener not called once", 1, l.numberOfErrors);
    313         assertEquals("Normal event was generated", 0, l.numberOfCalls);
    314         assertEquals("Wrong event type", TEST_TYPE, l.lastEvent.getType());
    315         assertEquals("Wrong property name", TEST_PROPNAME, l.lastEvent
    316                 .getPropertyName());
    317         assertEquals("Wrong property value", TEST_PROPVALUE, l.lastEvent
    318                 .getPropertyValue());
    319         assertEquals("Wrong Throwable object", testException,
    320                 ((ConfigurationErrorEvent) l.lastEvent).getCause());
    321     }
    322
    323     /***
    324      * Tests firering an error event if there are no error listeners.
    325      */
    326     public void testFireErrorNoListeners()
    327     {
    328         source.fireError(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE,
    329                 new Exception());
    330         assertEquals("An error event object was created", 0, source.errorCount);
    331     }
    332
    333     /***
    334      * Tests cloning an event source object. The registered listeners should not
    335      * be registered at the clone.
    336      */
    337     public void testClone() throws CloneNotSupportedException
    338     {
    339         source.addConfigurationListener(new TestListener());
    340         source.addErrorListener(new TestListener());
    341         EventSource copy = (EventSource) source.clone();
    342         assertTrue("Configuration listeners registered for clone", copy
    343                 .getConfigurationListeners().isEmpty());
    344         assertTrue("Error listeners registered for clone", copy
    345                 .getErrorListeners().isEmpty());
    346     }
    347
    348     /***
    349      * A test event listener implementation.
    350      */
    351     static class TestListener implements ConfigurationListener,
    352             ConfigurationErrorListener
    353     {
    354         ConfigurationEvent lastEvent;
    355
    356         int numberOfCalls;
    357
    358         int numberOfErrors;
    359
    360         public void configurationChanged(ConfigurationEvent event)
    361         {
    362             lastEvent = event;
    363             numberOfCalls++;
    364         }
    365
    366         public void configurationError(ConfigurationErrorEvent event)
    367         {
    368             lastEvent = event;
    369             numberOfErrors++;
    370         }
    371     }
    372
    373     /***
    374      * A specialized event source implementation that counts the number of
    375      * created event objects. It is used to test whether the
    376      * <code>fireEvent()</code> methods only creates event objects if
    377      * necessary. It also allows testing the clone() operation.
    378      */
    379     static class CountingEventSource extends EventSource implements Cloneable
    380     {
    381         int eventCount;
    382
    383         int errorCount;
    384
    385         protected ConfigurationEvent createEvent(int type, String propName,
    386                 Object propValue, boolean before)
    387         {
    388             eventCount++;
    389             return super.createEvent(type, propName, propValue, before);
    390         }
    391
    392         protected ConfigurationErrorEvent createErrorEvent(int type,
    393                 String propName, Object value, Throwable ex)
    394         {
    395             errorCount++;
    396             return super.createErrorEvent(type, propName, value, ex);
    397         }
    398     }
    399 }