Adding some extra capabilities to CountingEventBus so that we can reduce the
boilerplate involved in testing events fired on the EventBus.
Review at http://gwt-code-reviews.appspot.com/1526803
Review by: skybrian@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10594 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/web/bindery/event/shared/testing/CountingEventBus.java b/user/src/com/google/web/bindery/event/shared/testing/CountingEventBus.java
index 4b657a4..b9dc703 100644
--- a/user/src/com/google/web/bindery/event/shared/testing/CountingEventBus.java
+++ b/user/src/com/google/web/bindery/event/shared/testing/CountingEventBus.java
@@ -25,11 +25,13 @@
import java.util.Map;
/**
- * Wraps an {@link EventBus} to keep a count of registered handlers. Handy for
- * tests.
+ * Wraps an {@link EventBus} to keep a count of registered handlers and how many times events have
+ * fired. Handy for tests.
*/
public class CountingEventBus extends EventBus {
- private final Map<Type<?>, Integer> counts = new HashMap<Event.Type<?>, Integer>();
+ private final KeyedCounter<Type<?>> handlerCounts = new KeyedCounter<Event.Type<?>>();
+ private final KeyedCounter<Type<?>> firedCounts = new KeyedCounter<Event.Type<?>> ();
+ private final KeyedCounter<TypeSourcePair> sourceCounts = new KeyedCounter<TypeSourcePair>();
private final EventBus wrapped;
public CountingEventBus() {
@@ -42,47 +44,125 @@
@Override
public <H> HandlerRegistration addHandler(Type<H> type, H handler) {
- increment(type);
final HandlerRegistration superReg = wrapped.addHandler(type, handler);
+ handlerCounts.increment(type);
return makeReg(type, superReg);
}
@Override
public <H> HandlerRegistration addHandlerToSource(final Type<H> type, Object source, H handler) {
- increment(type);
final HandlerRegistration superReg = wrapped.addHandlerToSource(type, source, handler);
+ handlerCounts.increment(type);
return makeReg(type, superReg);
}
@Override
public void fireEvent(Event<?> event) {
wrapped.fireEvent(event);
+ firedCounts.increment(event.getAssociatedType());
+ sourceCounts.increment(new TypeSourcePair(event.getAssociatedType(), null));
}
@Override
public void fireEventFromSource(Event<?> event, Object source) {
wrapped.fireEventFromSource(event, source);
+ firedCounts.increment(event.getAssociatedType());
+ sourceCounts.increment(new TypeSourcePair(event.getAssociatedType(), source));
}
+ /**
+ * How many handlers are registered for the given {@code type}.
+ *
+ * @deprecated Please use {@code getHandlerCount}.
+ */
public int getCount(Type<?> type) {
- Integer count = counts.get(type);
- return count == null ? 0 : count;
+ return getHandlerCount(type);
}
- private void decrement(Type<?> type) {
- counts.put(type, getCount(type) - 1);
+ /**
+ * How many events have fired for the given {@code type}. These events may not have been
+ * passed to any handlers.
+ */
+ public int getFiredCount(Type<?> type) {
+ return firedCounts.getCount(type);
}
- private <H> void increment(final Type<H> type) {
- counts.put(type, getCount(type) + 1);
+ /**
+ * How many events have fired for the given pairing of {@code type} and {@code source}. These
+ * events may not have been passed to any handlers.
+ */
+ public int getFiredCountFromSource(Type<?> type, Object source) {
+ return sourceCounts.getCount(new TypeSourcePair(type, source));
+ }
+
+ /**
+ * How many handlers are registered for the given {@code type}.
+ */
+ public int getHandlerCount(Type<?> type) {
+ return handlerCounts.getCount(type);
}
private <H> HandlerRegistration makeReg(final Type<H> type, final HandlerRegistration superReg) {
return new HandlerRegistration() {
public void removeHandler() {
- decrement(type);
+ handlerCounts.decrement(type);
superReg.removeHandler();
}
};
}
+
+ private class TypeSourcePair {
+ final Type<?> type;
+ final Object source;
+
+ TypeSourcePair(Type<?> type, Object source) {
+ this.type = type;
+ this.source = source;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TypeSourcePair)) {
+ return false;
+ }
+
+ TypeSourcePair pair = (TypeSourcePair) o;
+ return doNullEquals(type, pair.type) && doNullEquals(source, pair.source);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = (hash * 31) + (type == null ? 0 : type.hashCode());
+ hash = (hash * 31) + (source == null ? 0 : source.hashCode());
+ return hash;
+ }
+
+ private boolean doNullEquals(Object a, Object b) {
+ if ((a == null) ^ (b == null)) {
+ return false;
+ }
+ return ((a == null) && (b == null)) || a.equals(b);
+ }
+ }
+
+ private class KeyedCounter<K> {
+ private Map<K, Integer> counts = new HashMap<K, Integer>();
+
+ int getCount(K key) {
+ Integer count = counts.get(key);
+ return count == null ? 0 : count;
+ }
+
+ void decrement(K key) {
+ counts.put(key, getCount(key) - 1);
+ }
+
+ void increment(K key) {
+ counts.put(key, getCount(key) + 1);
+ }
+ }
}
diff --git a/user/test/com/google/web/bindery/event/shared/BarEvent.java b/user/test/com/google/web/bindery/event/shared/BarEvent.java
index 35b21f9..ab366ff 100644
--- a/user/test/com/google/web/bindery/event/shared/BarEvent.java
+++ b/user/test/com/google/web/bindery/event/shared/BarEvent.java
@@ -19,11 +19,14 @@
* For {@link EventBus} tests.
*/
public class BarEvent extends Event<BarEvent.Handler> {
- interface Handler {
+ /**
+ * The handler for the event.
+ */
+ public interface Handler {
void onBar(BarEvent e);
}
- static final Type<Handler> TYPE = new Type<Handler>();
+ public static final Type<Handler> TYPE = new Type<Handler>();
public static HandlerRegistration register(EventBus bus, Handler handler) {
return bus.addHandler(TYPE, handler);
diff --git a/user/test/com/google/web/bindery/event/shared/EventBusTestBase.java b/user/test/com/google/web/bindery/event/shared/EventBusTestBase.java
index 129b182..0dd4d16 100644
--- a/user/test/com/google/web/bindery/event/shared/EventBusTestBase.java
+++ b/user/test/com/google/web/bindery/event/shared/EventBusTestBase.java
@@ -25,7 +25,10 @@
*/
public abstract class EventBusTestBase extends TestCase {
- class Adaptor implements FooEvent.Handler, BarEvent.Handler {
+ /**
+ * Handler implementation to allow for easy testing of whether the handler is being called.
+ */
+ protected class Adaptor implements FooEvent.Handler, BarEvent.Handler {
public void onFoo(FooEvent event) {
add(this);
@@ -41,11 +44,11 @@
}
}
- Adaptor adaptor1 = new Adaptor();
+ protected Adaptor adaptor1 = new Adaptor();
private HashSet<Object> active = new HashSet<Object>();
- FooEvent.Handler fooHandler1 = new FooEvent.Handler() {
+ protected FooEvent.Handler fooHandler1 = new FooEvent.Handler() {
public void onFoo(FooEvent event) {
add(fooHandler1);
}
@@ -56,7 +59,7 @@
}
};
- FooEvent.Handler fooHandler2 = new FooEvent.Handler() {
+ protected FooEvent.Handler fooHandler2 = new FooEvent.Handler() {
public void onFoo(FooEvent event) {
add(fooHandler2);
}
@@ -67,7 +70,7 @@
}
};
- FooEvent.Handler fooHandler3 = new FooEvent.Handler() {
+ protected FooEvent.Handler fooHandler3 = new FooEvent.Handler() {
public void onFoo(FooEvent event) {
add(fooHandler3);
}
@@ -78,7 +81,7 @@
}
};
- BarEvent.Handler barHandler1 = new BarEvent.Handler() {
+ protected BarEvent.Handler barHandler1 = new BarEvent.Handler() {
public void onBar(BarEvent event) {
add(barHandler1);
@@ -90,7 +93,7 @@
}
};
- BarEvent.Handler barHandler2 = new BarEvent.Handler() {
+ protected BarEvent.Handler barHandler2 = new BarEvent.Handler() {
public void onBar(BarEvent event) {
add(barHandler2);
@@ -102,7 +105,7 @@
}
};
- BarEvent.Handler barHandler3 = new BarEvent.Handler() {
+ protected BarEvent.Handler barHandler3 = new BarEvent.Handler() {
public void onBar(BarEvent event) {
add(barHandler3);
@@ -114,24 +117,24 @@
}
};
- void add(Object handler) {
+ protected void add(Object handler) {
active.add(handler);
}
- void assertFired(Object... handler) {
+ protected void assertFired(Object... handler) {
for (int i = 0; i < handler.length; i++) {
assertTrue(handler[i] + " should have fired", active.contains(handler[i]));
}
}
- void assertNotFired(Object... handler) {
+ protected void assertNotFired(Object... handler) {
for (int i = 0; i < handler.length; i++) {
assertFalse(handler[i] + " should not have fired",
active.contains(handler[i]));
}
}
- void reset() {
+ protected void reset() {
active.clear();
}
diff --git a/user/test/com/google/web/bindery/event/shared/FooEvent.java b/user/test/com/google/web/bindery/event/shared/FooEvent.java
index a63f53a..ee746b2 100644
--- a/user/test/com/google/web/bindery/event/shared/FooEvent.java
+++ b/user/test/com/google/web/bindery/event/shared/FooEvent.java
@@ -19,11 +19,14 @@
* For {@link EventBus} tests.
*/
public class FooEvent extends Event<FooEvent.Handler> {
- interface Handler {
+ /**
+ * The handler for the event.
+ */
+ public interface Handler {
void onFoo(FooEvent e);
}
- static final Type<Handler> TYPE = new Type<Handler>();
+ public static final Type<Handler> TYPE = new Type<Handler>();
public static HandlerRegistration register(EventBus bus, Handler handler) {
return bus.addHandler(TYPE, handler);
diff --git a/user/test/com/google/web/bindery/event/shared/testing/CountingEventBusTest.java b/user/test/com/google/web/bindery/event/shared/testing/CountingEventBusTest.java
new file mode 100644
index 0000000..6ab4f1d
--- /dev/null
+++ b/user/test/com/google/web/bindery/event/shared/testing/CountingEventBusTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed 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 com.google.web.bindery.event.shared.testing;
+
+import com.google.web.bindery.event.shared.BarEvent;
+import com.google.web.bindery.event.shared.Event.Type;
+import com.google.web.bindery.event.shared.EventBusTestBase;
+import com.google.web.bindery.event.shared.FooEvent;
+import com.google.web.bindery.event.shared.HandlerRegistration;
+import com.google.web.bindery.event.shared.SimpleEventBus;
+
+/**
+ * Eponymous unit tests.
+ */
+public class CountingEventBusTest extends EventBusTestBase {
+ private CountingEventBus eventBus;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ eventBus = new CountingEventBus(new SimpleEventBus());
+ }
+
+ public void testAddAndRemoveMultipleHandlers() {
+ HandlerRegistration fooReg = eventBus.addHandler(FooEvent.TYPE, fooHandler1);
+ checkHandlerCount(1, FooEvent.TYPE);
+
+ HandlerRegistration barReg1 = eventBus.addHandler(BarEvent.TYPE, barHandler1);
+ HandlerRegistration barReg2 = eventBus.addHandler(BarEvent.TYPE, barHandler2);
+ checkHandlerCount(2, BarEvent.TYPE);
+
+ fooReg.removeHandler();
+ checkHandlerCount(0, FooEvent.TYPE);
+
+ barReg2.removeHandler();
+ checkHandlerCount(1, BarEvent.TYPE);
+
+ barReg1.removeHandler();
+ checkHandlerCount(0, BarEvent.TYPE);
+ }
+
+ public void testAddAndRemoveSourcedHandlers() {
+ Object source1 = new Object();
+ Object source2 = new Object();
+
+ HandlerRegistration fooReg1 = eventBus.addHandlerToSource(FooEvent.TYPE, source1, fooHandler1);
+ checkHandlerCount(1, FooEvent.TYPE);
+
+ HandlerRegistration fooReg2 = eventBus.addHandlerToSource(FooEvent.TYPE, source2, fooHandler2);
+ checkHandlerCount(2, FooEvent.TYPE);
+
+ fooReg2.removeHandler();
+ checkHandlerCount(1, FooEvent.TYPE);
+
+ fooReg1.removeHandler();
+ checkHandlerCount(0, FooEvent.TYPE);
+ }
+
+ public void testFireEvent() {
+ checkTotalEvents(0, FooEvent.TYPE);
+ checkTotalEvents(0, BarEvent.TYPE);
+
+ for (int i = 0; i < 5; i++) {
+ eventBus.fireEvent(new FooEvent());
+ checkTotalEvents(i + 1, FooEvent.TYPE);
+ checkTotalEvents(i, BarEvent.TYPE);
+
+ eventBus.fireEvent(new BarEvent());
+ checkTotalEvents(i + 1, FooEvent.TYPE);
+ checkTotalEvents(i + 1, BarEvent.TYPE);
+ }
+ }
+
+ public void testFireEventFromSource() {
+ Object source1 = new Object();
+ Object source2 = new Object();
+
+ eventBus.fireEvent(new FooEvent());
+ checkSourceEvents(0, FooEvent.TYPE, source1);
+ checkSourceEvents(0, FooEvent.TYPE, source2);
+ checkTotalEvents(1, FooEvent.TYPE);
+
+ eventBus.fireEventFromSource(new FooEvent(), source1);
+ checkSourceEvents(1, FooEvent.TYPE, source1);
+ checkSourceEvents(0, FooEvent.TYPE, source2);
+ checkSourceEvents(1, FooEvent.TYPE, null);
+ assertEquals(2, eventBus.getFiredCount(FooEvent.TYPE));
+
+ eventBus.fireEventFromSource(new FooEvent(), source1);
+ checkSourceEvents(2, FooEvent.TYPE, source1);
+ checkSourceEvents(0, FooEvent.TYPE, source2);
+ checkSourceEvents(1, FooEvent.TYPE, null);
+ assertEquals(3, eventBus.getFiredCount(FooEvent.TYPE));
+
+ eventBus.fireEventFromSource(new FooEvent(), source2);
+ checkSourceEvents(2, FooEvent.TYPE, source1);
+ checkSourceEvents(1, FooEvent.TYPE, source2);
+ checkSourceEvents(1, FooEvent.TYPE, null);
+ assertEquals(4, eventBus.getFiredCount(FooEvent.TYPE));
+
+ eventBus.fireEventFromSource(new BarEvent(), source2);
+ checkSourceEvents(2, FooEvent.TYPE, source1);
+ checkSourceEvents(1, FooEvent.TYPE, source2);
+ checkSourceEvents(1, FooEvent.TYPE, null);
+ assertEquals(4, eventBus.getFiredCount(FooEvent.TYPE));
+ checkSourceEvents(1, BarEvent.TYPE, source2);
+ assertEquals(1, eventBus.getFiredCount(BarEvent.TYPE));
+ }
+
+ public void testFireEventFromSource_LotsOfEvents() {
+ Object source = new Object();
+
+ for (int i = 0; i < Integer.MAX_VALUE; i++) {
+ eventBus.fireEventFromSource(new FooEvent(), source);
+ assertEquals(i + 1, eventBus.getFiredCount(FooEvent.TYPE));
+ assertEquals(i + 1, eventBus.getFiredCountFromSource(FooEvent.TYPE, source));
+ }
+ }
+
+ private void checkHandlerCount(int expected, Type<?> type) {
+ assertEquals(expected, eventBus.getHandlerCount(type));
+ assertEquals(expected, eventBus.getCount(type));
+ }
+
+ private void checkSourceEvents(int expectedCount, Type<?> type, Object source) {
+ assertEquals(expectedCount, eventBus.getFiredCountFromSource(type, source));
+ }
+
+ private void checkTotalEvents(int expectedCount, Type<?> type) {
+ assertEquals(expectedCount, eventBus.getFiredCount(type));
+ assertEquals(expectedCount, eventBus.getFiredCountFromSource(type, null));
+ }
+}
+