001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.configuration.event; 018 019 import static org.junit.Assert.assertEquals; 020 import static org.junit.Assert.assertFalse; 021 import static org.junit.Assert.assertTrue; 022 023 import java.util.Collection; 024 025 import org.junit.Before; 026 import org.junit.Test; 027 028 /** 029 * Test class for EventSource. 030 * 031 * @version $Id: TestEventSource.java 1225652 2011-12-29 21:00:57Z oheger $ 032 */ 033 public class TestEventSource 034 { 035 /** Constant for the event type used for testing. */ 036 static final int TEST_TYPE = 42; 037 038 /** Constant for the event property name. */ 039 static final String TEST_PROPNAME = "test.property.name"; 040 041 /** Constant for the event property value. */ 042 static final Object TEST_PROPVALUE = "a test property value"; 043 044 /** The object under test. */ 045 CountingEventSource source; 046 047 @Before 048 public void setUp() throws Exception 049 { 050 source = new CountingEventSource(); 051 } 052 053 /** 054 * Tests a newly created source object. 055 */ 056 @Test 057 public void testInit() 058 { 059 assertTrue("Listeners list is not empty", source 060 .getConfigurationListeners().isEmpty()); 061 assertFalse("Removing listener", source 062 .removeConfigurationListener(new TestListener())); 063 assertFalse("Detail events are enabled", source.isDetailEvents()); 064 assertTrue("Error listeners list is not empty", source 065 .getErrorListeners().isEmpty()); 066 } 067 068 /** 069 * Tests registering a new listener. 070 */ 071 @Test 072 public void testAddConfigurationListener() 073 { 074 TestListener l = new TestListener(); 075 source.addConfigurationListener(l); 076 Collection<ConfigurationListener> listeners = source.getConfigurationListeners(); 077 assertEquals("Wrong number of listeners", 1, listeners.size()); 078 assertTrue("Listener not in list", listeners.contains(l)); 079 } 080 081 /** 082 * Tests adding an undefined configuration listener. This should cause an 083 * exception. 084 */ 085 @Test(expected = IllegalArgumentException.class) 086 public void testAddNullConfigurationListener() 087 { 088 source.addConfigurationListener(null); 089 } 090 091 /** 092 * Tests removing a listener. 093 */ 094 @Test 095 public void testRemoveConfigurationListener() 096 { 097 TestListener l = new TestListener(); 098 assertFalse("Listener can be removed?", source 099 .removeConfigurationListener(l)); 100 source.addConfigurationListener(l); 101 source.addConfigurationListener(new TestListener()); 102 assertFalse("Unknown listener can be removed", source 103 .removeConfigurationListener(new TestListener())); 104 assertTrue("Could not remove listener", source 105 .removeConfigurationListener(l)); 106 assertFalse("Listener still in list", source 107 .getConfigurationListeners().contains(l)); 108 } 109 110 /** 111 * Tests if a null listener can be removed. This should be a no-op. 112 */ 113 @Test 114 public void testRemoveNullConfigurationListener() 115 { 116 source.addConfigurationListener(new TestListener()); 117 assertFalse("Null listener can be removed", source 118 .removeConfigurationListener(null)); 119 assertEquals("Listener list was modified", 1, source 120 .getConfigurationListeners().size()); 121 } 122 123 /** 124 * Tests whether the listeners list is read only. 125 */ 126 @Test(expected = UnsupportedOperationException.class) 127 public void testGetConfigurationListenersUpdate() 128 { 129 source.addConfigurationListener(new TestListener()); 130 Collection<ConfigurationListener> list = source.getConfigurationListeners(); 131 list.clear(); 132 } 133 134 /** 135 * Tests that the collection returned by getConfigurationListeners() is 136 * really a snapshot. A later added listener must not be visible. 137 */ 138 @Test 139 public void testGetConfigurationListenersAddNew() 140 { 141 Collection<ConfigurationListener> list = source.getConfigurationListeners(); 142 source.addConfigurationListener(new TestListener()); 143 assertTrue("Listener snapshot not empty", list.isEmpty()); 144 } 145 146 /** 147 * Tests enabling and disabling the detail events flag. 148 */ 149 @Test 150 public void testSetDetailEvents() 151 { 152 source.setDetailEvents(true); 153 assertTrue("Detail events are disabled", source.isDetailEvents()); 154 source.setDetailEvents(true); 155 source.setDetailEvents(false); 156 assertTrue("Detail events are disabled again", source.isDetailEvents()); 157 source.setDetailEvents(false); 158 assertFalse("Detail events are still enabled", source.isDetailEvents()); 159 } 160 161 /** 162 * Tests delivering an event to a listener. 163 */ 164 @Test 165 public void testFireEvent() 166 { 167 TestListener l = new TestListener(); 168 source.addConfigurationListener(l); 169 source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, true); 170 assertEquals("Not 1 event created", 1, source.eventCount); 171 assertEquals("Listener not called once", 1, l.numberOfCalls); 172 assertEquals("Wrong event type", TEST_TYPE, l.lastEvent.getType()); 173 assertEquals("Wrong property name", TEST_PROPNAME, l.lastEvent 174 .getPropertyName()); 175 assertEquals("Wrong property value", TEST_PROPVALUE, l.lastEvent 176 .getPropertyValue()); 177 assertTrue("Wrong before event flag", l.lastEvent.isBeforeUpdate()); 178 } 179 180 /** 181 * Tests firing an event if there are no listeners. 182 */ 183 @Test 184 public void testFireEventNoListeners() 185 { 186 source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false); 187 assertEquals("An event object was created", 0, source.eventCount); 188 } 189 190 /** 191 * Tests generating a detail event if detail events are not allowed. 192 */ 193 @Test 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 @Test 209 public void testRemoveListenerInFireEvent() 210 { 211 ConfigurationListener lstRemove = new ConfigurationListener() 212 { 213 public void configurationChanged(ConfigurationEvent event) 214 { 215 source.removeConfigurationListener(this); 216 } 217 }; 218 219 source.addConfigurationListener(lstRemove); 220 TestListener l = new TestListener(); 221 source.addConfigurationListener(l); 222 source.fireEvent(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, false); 223 assertEquals("Listener was not called", 1, l.numberOfCalls); 224 assertEquals("Listener was not removed", 1, source 225 .getConfigurationListeners().size()); 226 } 227 228 /** 229 * Tests registering a new error listener. 230 */ 231 @Test 232 public void testAddErrorListener() 233 { 234 TestListener l = new TestListener(); 235 source.addErrorListener(l); 236 Collection<ConfigurationErrorListener> listeners = source.getErrorListeners(); 237 assertEquals("Wrong number of listeners", 1, listeners.size()); 238 assertTrue("Listener not in list", listeners.contains(l)); 239 } 240 241 /** 242 * Tests adding an undefined error listener. This should cause an exception. 243 */ 244 @Test(expected = IllegalArgumentException.class) 245 public void testAddNullErrorListener() 246 { 247 source.addErrorListener(null); 248 } 249 250 /** 251 * Tests removing an error listener. 252 */ 253 @Test 254 public void testRemoveErrorListener() 255 { 256 TestListener l = new TestListener(); 257 assertFalse("Listener can be removed?", source.removeErrorListener(l)); 258 source.addErrorListener(l); 259 source.addErrorListener(new TestListener()); 260 assertFalse("Unknown listener can be removed", source 261 .removeErrorListener(new TestListener())); 262 assertTrue("Could not remove listener", source.removeErrorListener(l)); 263 assertFalse("Listener still in list", source.getErrorListeners() 264 .contains(l)); 265 } 266 267 /** 268 * Tests if a null error listener can be removed. This should be a no-op. 269 */ 270 @Test 271 public void testRemoveNullErrorListener() 272 { 273 source.addErrorListener(new TestListener()); 274 assertFalse("Null listener can be removed", source 275 .removeErrorListener(null)); 276 assertEquals("Listener list was modified", 1, source 277 .getErrorListeners().size()); 278 } 279 280 /** 281 * Tests whether the listeners list is read only. 282 */ 283 @Test(expected = UnsupportedOperationException.class) 284 public void testGetErrorListenersUpdate() 285 { 286 source.addErrorListener(new TestListener()); 287 Collection<ConfigurationErrorListener> list = source.getErrorListeners(); 288 list.clear(); 289 } 290 291 /** 292 * Tests delivering an error event to a listener. 293 */ 294 @Test 295 public void testFireError() 296 { 297 TestListener l = new TestListener(); 298 source.addErrorListener(l); 299 Exception testException = new Exception("A test"); 300 source.fireError(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, 301 testException); 302 assertEquals("Not 1 event created", 1, source.errorCount); 303 assertEquals("Error listener not called once", 1, l.numberOfErrors); 304 assertEquals("Normal event was generated", 0, l.numberOfCalls); 305 assertEquals("Wrong event type", TEST_TYPE, l.lastEvent.getType()); 306 assertEquals("Wrong property name", TEST_PROPNAME, l.lastEvent 307 .getPropertyName()); 308 assertEquals("Wrong property value", TEST_PROPVALUE, l.lastEvent 309 .getPropertyValue()); 310 assertEquals("Wrong Throwable object", testException, 311 ((ConfigurationErrorEvent) l.lastEvent).getCause()); 312 } 313 314 /** 315 * Tests firing an error event if there are no error listeners. 316 */ 317 @Test 318 public void testFireErrorNoListeners() 319 { 320 source.fireError(TEST_TYPE, TEST_PROPNAME, TEST_PROPVALUE, 321 new Exception()); 322 assertEquals("An error event object was created", 0, source.errorCount); 323 } 324 325 /** 326 * Tests cloning an event source object. The registered listeners should not 327 * be registered at the clone. 328 */ 329 @Test 330 public void testClone() throws CloneNotSupportedException 331 { 332 source.addConfigurationListener(new TestListener()); 333 source.addErrorListener(new TestListener()); 334 EventSource copy = (EventSource) source.clone(); 335 assertTrue("Configuration listeners registered for clone", copy 336 .getConfigurationListeners().isEmpty()); 337 assertTrue("Error listeners registered for clone", copy 338 .getErrorListeners().isEmpty()); 339 } 340 341 /** 342 * A test event listener implementation. 343 */ 344 static class TestListener implements ConfigurationListener, 345 ConfigurationErrorListener 346 { 347 ConfigurationEvent lastEvent; 348 349 int numberOfCalls; 350 351 int numberOfErrors; 352 353 public void configurationChanged(ConfigurationEvent event) 354 { 355 lastEvent = event; 356 numberOfCalls++; 357 } 358 359 public void configurationError(ConfigurationErrorEvent event) 360 { 361 lastEvent = event; 362 numberOfErrors++; 363 } 364 } 365 366 /** 367 * A specialized event source implementation that counts the number of 368 * created event objects. It is used to test whether the 369 * {@code fireEvent()} methods only creates event objects if 370 * necessary. It also allows testing the clone() operation. 371 */ 372 static class CountingEventSource extends EventSource implements Cloneable 373 { 374 int eventCount; 375 376 int errorCount; 377 378 @Override 379 protected ConfigurationEvent createEvent(int type, String propName, 380 Object propValue, boolean before) 381 { 382 eventCount++; 383 return super.createEvent(type, propName, propValue, before); 384 } 385 386 @Override 387 protected ConfigurationErrorEvent createErrorEvent(int type, 388 String propName, Object value, Throwable ex) 389 { 390 errorCount++; 391 return super.createErrorEvent(type, propName, value, ex); 392 } 393 } 394 }