diff options
Diffstat (limited to 'src/test/java/org/apache/commons/lang3/event/EventUtilsTest.java')
-rw-r--r-- | src/test/java/org/apache/commons/lang3/event/EventUtilsTest.java | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/src/test/java/org/apache/commons/lang3/event/EventUtilsTest.java b/src/test/java/org/apache/commons/lang3/event/EventUtilsTest.java new file mode 100644 index 000000000..04c110034 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/event/EventUtilsTest.java @@ -0,0 +1,228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.lang3.event; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.VetoableChangeListener; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; +import java.util.Date; +import java.util.Map; +import java.util.TreeMap; + +import javax.naming.event.ObjectChangeListener; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * @since 3.0 + */ +public class EventUtilsTest extends AbstractLangTest { + @Test + public void testConstructor() { + assertNotNull(new EventUtils()); + final Constructor<?>[] cons = EventUtils.class.getDeclaredConstructors(); + assertEquals(1, cons.length); + assertTrue(Modifier.isPublic(cons[0].getModifiers())); + assertTrue(Modifier.isPublic(EventUtils.class.getModifiers())); + assertFalse(Modifier.isFinal(EventUtils.class.getModifiers())); + } + + @Test + public void testAddEventListener() { + final PropertyChangeSource src = new PropertyChangeSource(); + final EventCountingInvocationHandler handler = new EventCountingInvocationHandler(); + final PropertyChangeListener listener = handler.createListener(PropertyChangeListener.class); + assertEquals(0, handler.getEventCount("propertyChange")); + EventUtils.addEventListener(src, PropertyChangeListener.class, listener); + assertEquals(0, handler.getEventCount("propertyChange")); + src.setProperty("newValue"); + assertEquals(1, handler.getEventCount("propertyChange")); + } + + @Test + public void testAddEventListenerWithNoAddMethod() { + final PropertyChangeSource src = new PropertyChangeSource(); + final EventCountingInvocationHandler handler = new EventCountingInvocationHandler(); + final ObjectChangeListener listener = handler.createListener(ObjectChangeListener.class); + final IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> EventUtils.addEventListener(src, ObjectChangeListener.class, listener)); + assertEquals("Class " + src.getClass().getName() + " does not have a public add" + ObjectChangeListener.class.getSimpleName() + " method which takes a parameter of type " + ObjectChangeListener.class.getName() + ".", + e.getMessage()); + } + + @Test + public void testAddEventListenerThrowsException() { + final ExceptionEventSource src = new ExceptionEventSource(); + assertThrows(RuntimeException.class, () -> + EventUtils.addEventListener(src, PropertyChangeListener.class, e -> { + // Do nothing! + }) + ); + } + + @Test + public void testAddEventListenerWithPrivateAddMethod() { + final PropertyChangeSource src = new PropertyChangeSource(); + final EventCountingInvocationHandler handler = new EventCountingInvocationHandler(); + final VetoableChangeListener listener = handler.createListener(VetoableChangeListener.class); + final IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, () -> EventUtils.addEventListener(src, VetoableChangeListener.class, listener)); + assertEquals("Class " + src.getClass().getName() + " does not have a public add" + VetoableChangeListener.class.getSimpleName() + " method which takes a parameter of type " + VetoableChangeListener.class.getName() + ".", + e.getMessage()); + } + + @Test + public void testBindEventsToMethod() { + final PropertyChangeSource src = new PropertyChangeSource(); + final EventCounter counter = new EventCounter(); + EventUtils.bindEventsToMethod(counter, "eventOccurred", src, PropertyChangeListener.class); + assertEquals(0, counter.getCount()); + src.setProperty("newValue"); + assertEquals(1, counter.getCount()); + } + + + @Test + public void testBindEventsToMethodWithEvent() { + final PropertyChangeSource src = new PropertyChangeSource(); + final EventCounterWithEvent counter = new EventCounterWithEvent(); + EventUtils.bindEventsToMethod(counter, "eventOccurred", src, PropertyChangeListener.class); + assertEquals(0, counter.getCount()); + src.setProperty("newValue"); + assertEquals(1, counter.getCount()); + } + + + @Test + public void testBindFilteredEventsToMethod() { + final MultipleEventSource src = new MultipleEventSource(); + final EventCounter counter = new EventCounter(); + EventUtils.bindEventsToMethod(counter, "eventOccurred", src, MultipleEventListener.class, "event1"); + assertEquals(0, counter.getCount()); + src.listeners.fire().event1(new PropertyChangeEvent(new Date(), "Day", Integer.valueOf(0), Integer.valueOf(1))); + assertEquals(1, counter.getCount()); + src.listeners.fire().event2(new PropertyChangeEvent(new Date(), "Day", Integer.valueOf(1), Integer.valueOf(2))); + assertEquals(1, counter.getCount()); + } + + public interface MultipleEventListener { + void event1(PropertyChangeEvent e); + + void event2(PropertyChangeEvent e); + } + + public static class EventCounter { + private int count; + + public void eventOccurred() { + count++; + } + + public int getCount() { + return count; + } + } + + public static class EventCounterWithEvent { + private int count; + + public void eventOccurred(final PropertyChangeEvent e) { + count++; + } + + public int getCount() { + return count; + } + } + + + private static class EventCountingInvocationHandler implements InvocationHandler { + private final Map<String, Integer> eventCounts = new TreeMap<>(); + + public <L> L createListener(final Class<L> listenerType) { + return listenerType.cast(Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[]{listenerType}, + this)); + } + + public int getEventCount(final String eventName) { + final Integer count = eventCounts.get(eventName); + return count == null ? 0 : count.intValue(); + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) { + final Integer count = eventCounts.get(method.getName()); + if (count == null) { + eventCounts.put(method.getName(), Integer.valueOf(1)); + } else { + eventCounts.put(method.getName(), Integer.valueOf(count.intValue() + 1)); + } + return null; + } + } + + public static class MultipleEventSource { + private final EventListenerSupport<MultipleEventListener> listeners = EventListenerSupport.create(MultipleEventListener.class); + + public void addMultipleEventListener(final MultipleEventListener listener) { + listeners.addListener(listener); + } + } + + public static class ExceptionEventSource { + public void addPropertyChangeListener(final PropertyChangeListener listener) { + throw new RuntimeException(); + } + } + + public static class PropertyChangeSource { + private final EventListenerSupport<PropertyChangeListener> listeners = EventListenerSupport.create(PropertyChangeListener.class); + + private String property; + + public void setProperty(final String property) { + final String oldValue = this.property; + this.property = property; + listeners.fire().propertyChange(new PropertyChangeEvent(this, "property", oldValue, property)); + } + + protected void addVetoableChangeListener(final VetoableChangeListener listener) { + // Do nothing! + } + + public void addPropertyChangeListener(final PropertyChangeListener listener) { + listeners.addListener(listener); + } + + public void removePropertyChangeListener(final PropertyChangeListener listener) { + listeners.removeListener(listener); + } + } +} |