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 }