package org.limewire.listener;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.Test;
import org.limewire.util.BaseTestCase;
/**
* A class to test the methods of EventListenerList: adding, removing.
* Need to add tests for multiple adds, adds to existing lists, adding different
* types of listeners, as well as broadcasting.
*/
public class EventListenerListTest extends BaseTestCase {
public EventListenerListTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(EventListenerListTest.class);
}
/**
* A simple test to add a listener (for which the key did not exist before),
* and to remove it after.
*/
public void testAddRemoveListener() {
EventListenerList<Object> list = new EventListenerList<Object>();
Listener l = new Listener();
list.addListener(l);
assertTrue(list.removeListener(l));
assertFalse(list.removeListener(l));
}
public void testInlineEvent() {
EventListenerList<Object> list = new EventListenerList<Object>();
Listener l = new Listener();
list.addListener(l);
assertNull(l.thread);
list.broadcast(new Object());
assertEquals(Thread.currentThread(), l.thread);
}
public void testSwingProxyEvent() throws Exception {
EventListenerList<Foo> list = new EventListenerList<Foo>();
SwingProxyListener l = new SwingProxyListener();
list.addListener(l);
assertNull(l.thread);
list.broadcast(new Foo());
assertTrue(l.latch.await(1, TimeUnit.SECONDS));
assertNotEquals(Thread.currentThread(), l.thread);
}
public void testSwingProxyEventWithSubclassedEvent() throws Exception {
EventListenerList<Foo> list = new EventListenerList<Foo>();
SwingProxyListener l = new SwingProxyListener();
list.addListener(l);
assertNull(l.thread);
list.broadcast(new SubFoo());
assertTrue(l.latch.await(1, TimeUnit.SECONDS));
assertNotEquals(Thread.currentThread(), l.thread);
}
public void testBlockingEvent() throws Exception {
CountDownLatch latch = new CountDownLatch(2);
EventListenerList<Foo> list = new EventListenerList<Foo>();
BlockingListener l1 = new BlockingListener(latch);
BlockingListener l2 = new BlockingListener(latch);
list.addListener(l1);
list.addListener(l2);
assertNull(l1.thread);
assertNull(l2.thread);
list.broadcast(new Foo());
assertTrue(latch.await(1, TimeUnit.SECONDS));
assertNotEquals(Thread.currentThread(), l1.thread);
assertNotEquals(Thread.currentThread(), l2.thread);
assertNotEquals(l1.thread, l2.thread);
}
public void testBlockingEventWithQueueNames() throws Exception {
CountDownLatch latch = new CountDownLatch(6);
EventListenerList<Foo> list = new EventListenerList<Foo>();
BlockingListener l1 = new BlockingListener(latch);
BlockingListener l2 = new BlockingListener(latch);
BlockingListenerQueueNameBar bar1 = new BlockingListenerQueueNameBar(latch);
BlockingListenerQueueNameBar bar2 = new BlockingListenerQueueNameBar(latch);
BlockingListenerQueueNameBob bob1 = new BlockingListenerQueueNameBob(latch);
BlockingListenerQueueNameBob bob2 = new BlockingListenerQueueNameBob(latch);
list.addListener(l1);
list.addListener(l2);
list.addListener(bar1);
list.addListener(bar2);
list.addListener(bob1);
list.addListener(bob2);
assertNull(l1.thread);
assertNull(l2.thread);
assertNull(bar1.thread);
assertNull(bar2.thread);
assertNull(bob1.thread);
assertNull(bob2.thread);
list.broadcast(new Foo());
assertTrue(latch.await(1, TimeUnit.SECONDS));
assertNotEquals(Thread.currentThread(), l1.thread);
assertNotEquals(Thread.currentThread(), l2.thread);
assertNotEquals(Thread.currentThread(), bar1.thread);
assertNotEquals(Thread.currentThread(), bar2.thread);
assertNotEquals(Thread.currentThread(), bob1.thread);
assertNotEquals(Thread.currentThread(), bob2.thread);
assertEquals(bar1.thread, bar2.thread);
assertEquals(bob1.thread, bob2.thread);
assertNotEquals(l1.thread, l2.thread);
assertNotEquals(l1.thread, bar1.thread);
assertNotEquals(l1.thread, bob1.thread);
assertNotEquals(l2.thread, bar1.thread);
assertNotEquals(l2.thread, bob1.thread);
assertNotEquals(bar1.thread, bob1.thread);
}
public void testMultipleEventsToNamedBlockingEventAreSequentialInAnotherThread() throws Exception {
EventListenerList<Foo> list = new EventListenerList<Foo>();
final Foo foo1 = new Foo();
final Foo foo2 = new Foo();
final List<Foo> fooList = new CopyOnWriteArrayList<Foo>();
final List<Thread> threadList = new CopyOnWriteArrayList<Thread>();
final CountDownLatch foo1EntryLatch = new CountDownLatch(1);
final CountDownLatch foo2EntryLatch = new CountDownLatch(1);
final CountDownLatch foo1ExitLatch = new CountDownLatch(1);
final CountDownLatch foo2ExitLatch = new CountDownLatch(1);
list.addListener(new EventListener<Foo>() {
@Override
@BlockingEvent(queueName="foo")
public void handleEvent(Foo foo) {
try {
if(foo == foo1) {
assertTrue(foo1EntryLatch.await(2, TimeUnit.SECONDS));
} else if(foo == foo2) {
assertTrue(foo2EntryLatch.await(2, TimeUnit.SECONDS));
} else {
throw new IllegalStateException("wrong foo: " + foo);
}
} catch(InterruptedException ie) {
throw new IllegalStateException(ie);
}
fooList.add(foo);
threadList.add(Thread.currentThread());
if(foo == foo1) {
foo1ExitLatch.countDown();
} else if(foo == foo2) {
foo2ExitLatch.countDown();
} else {
throw new IllegalStateException("wrong foo: " + foo);
}
}
});
list.broadcast(foo1);
list.broadcast(foo2);
Thread.sleep(100);
assertEmpty(fooList);
foo1EntryLatch.countDown();
assertTrue(foo1ExitLatch.await(100, TimeUnit.MILLISECONDS));
assertEquals(1, fooList.size());
assertSame(foo1, fooList.get(0));
assertNotSame(Thread.currentThread(), threadList.get(0));
foo2EntryLatch.countDown();
assertTrue(foo2ExitLatch.await(100, TimeUnit.MILLISECONDS));
assertEquals(2, fooList.size());
assertSame(foo2, fooList.get(1));
assertSame(threadList.get(0), threadList.get(1));
}
private static class Listener implements EventListener<Object> {
private Thread thread;
public void handleEvent(Object event) {
this.thread = Thread.currentThread();
}
}
private static class SwingProxyListener implements EventListener<Foo> {
private final CountDownLatch latch = new CountDownLatch(1);
private volatile Thread thread;
@Override
@SwingEDTEvent
public void handleEvent(Foo event) {
this.thread = Thread.currentThread();
latch.countDown();
}
}
private static class BlockingListener implements EventListener<Foo> {
private final CountDownLatch latch;
private volatile Thread thread;
public BlockingListener(CountDownLatch latch) {
this.latch = latch;
}
@Override
@BlockingEvent
public void handleEvent(Foo event) {
this.thread = Thread.currentThread();
try { Thread.sleep(100); } catch(InterruptedException ix) {}
latch.countDown();
}
}
private static class BlockingListenerQueueNameBar implements EventListener<Foo> {
private final CountDownLatch latch;
private volatile Thread thread;
public BlockingListenerQueueNameBar(CountDownLatch latch) {
this.latch = latch;
}
@Override
@BlockingEvent(queueName="bar")
public void handleEvent(Foo event) {
this.thread = Thread.currentThread();
try { Thread.sleep(100); } catch(InterruptedException ix) {}
latch.countDown();
}
}
private static class BlockingListenerQueueNameBob implements EventListener<Foo> {
private final CountDownLatch latch;
private volatile Thread thread;
public BlockingListenerQueueNameBob(CountDownLatch latch) {
this.latch = latch;
}
@Override
@BlockingEvent(queueName="bob")
public void handleEvent(Foo event) {
this.thread = Thread.currentThread();
try { Thread.sleep(100); } catch(InterruptedException ix) {}
latch.countDown();
}
}
private static class Foo {}
private static class SubFoo extends Foo {}
}