| /* | |
| * 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; | |
| import com.google.web.bindery.event.shared.testing.CountingEventBus; | |
| import junit.framework.AssertionFailedError; | |
| import java.util.Set; | |
| /** | |
| * Eponymous unit test. | |
| */ | |
| public class SimpleEventBusTest extends EventBusTestBase { | |
| interface Command { | |
| void execute(); | |
| } | |
| class ShyHandler implements FooEvent.Handler { | |
| HandlerRegistration r; | |
| public void onFoo(FooEvent event) { | |
| add(this); | |
| r.removeHandler(); | |
| } | |
| } | |
| class SourcedHandler implements FooEvent.Handler { | |
| final String expectedSource; | |
| SourcedHandler(String source) { | |
| this.expectedSource = source; | |
| } | |
| public void onFoo(FooEvent event) { | |
| add(this); | |
| assertEquals(expectedSource, event.getSource()); | |
| } | |
| } | |
| static class ThrowingHandler implements FooEvent.Handler { | |
| private final RuntimeException e; | |
| public ThrowingHandler(RuntimeException e) { | |
| this.e = e; | |
| } | |
| public void onFoo(FooEvent event) { | |
| throw e; | |
| } | |
| } | |
| public void testAddAndRemoveHandlers() { | |
| CountingEventBus eventBus = new CountingEventBus(new SimpleEventBus()); | |
| FooEvent.register(eventBus, fooHandler1); | |
| FooEvent.register(eventBus, fooHandler2); | |
| HandlerRegistration reg1 = FooEvent.register(eventBus, adaptor1); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertEquals(3, eventBus.getCount(FooEvent.TYPE)); | |
| assertFired(fooHandler1, fooHandler2, adaptor1); | |
| FooEvent.register(eventBus, fooHandler3); | |
| assertEquals(4, eventBus.getCount(FooEvent.TYPE)); | |
| FooEvent.register(eventBus, fooHandler1); | |
| FooEvent.register(eventBus, fooHandler2); | |
| HandlerRegistration reg2 = FooEvent.register(eventBus, adaptor1); | |
| /* | |
| * You can indeed add handlers twice, they will only be removed one at a | |
| * time though. | |
| */ | |
| assertEquals(7, eventBus.getCount(FooEvent.TYPE)); | |
| eventBus.addHandler(BarEvent.TYPE, adaptor1); | |
| eventBus.addHandler(BarEvent.TYPE, barHandler1); | |
| eventBus.addHandler(BarEvent.TYPE, barHandler2); | |
| assertEquals(7, eventBus.getCount(FooEvent.TYPE)); | |
| assertEquals(3, eventBus.getCount(BarEvent.TYPE)); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(fooHandler1, fooHandler2, fooHandler3, adaptor1); | |
| assertNotFired(barHandler1, barHandler2); | |
| // Gets rid of first instance. | |
| reg1.removeHandler(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(fooHandler1, fooHandler2, fooHandler3, adaptor1); | |
| assertNotFired(barHandler1, barHandler2); | |
| // Gets rid of second instance. | |
| reg2.removeHandler(); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(fooHandler1, fooHandler2, fooHandler3); | |
| assertNotFired(adaptor1, barHandler1, barHandler2); | |
| // Checks to see if barHandler events are still working. | |
| reset(); | |
| eventBus.fireEvent(new BarEvent()); | |
| assertNotFired(fooHandler1, fooHandler2, fooHandler3); | |
| assertFired(barHandler1, barHandler2, adaptor1); | |
| } | |
| public void testAssertThrowsNpe() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| try { | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| FooEvent.register(eventBus, fooHandler1); | |
| } | |
| }); | |
| fail("expected AssertionFailedError"); | |
| } catch (AssertionFailedError e) { | |
| /* pass */ | |
| } | |
| } | |
| public void testConcurrentAdd() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| final FooEvent.Handler two = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| add(this); | |
| } | |
| }; | |
| FooEvent.Handler one = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| FooEvent.register(eventBus, two); | |
| add(this); | |
| } | |
| }; | |
| FooEvent.register(eventBus, one); | |
| FooEvent.register(eventBus, fooHandler1); | |
| FooEvent.register(eventBus, fooHandler2); | |
| FooEvent.register(eventBus, fooHandler3); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(one, fooHandler1, fooHandler2, fooHandler3); | |
| assertNotFired(two); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(one, two, fooHandler1, fooHandler2, fooHandler3); | |
| } | |
| public void testConcurrentAddAfterRemoveIsNotClobbered() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| FooEvent.Handler one = new FooEvent.Handler() { | |
| HandlerRegistration reg = addIt(); | |
| public void onFoo(FooEvent event) { | |
| reg.removeHandler(); | |
| addIt(); | |
| add(this); | |
| } | |
| private HandlerRegistration addIt() { | |
| return FooEvent.register(eventBus, fooHandler1); | |
| } | |
| }; | |
| FooEvent.register(eventBus, one); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(one); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(one, fooHandler1); | |
| } | |
| public void testConcurrentAddAndRemoveByNastyUsersTryingToHurtUs() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| final FooEvent.Handler two = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| add(this); | |
| } | |
| @Override | |
| public String toString() { | |
| return "two"; | |
| } | |
| }; | |
| FooEvent.Handler one = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| FooEvent.register(eventBus, two).removeHandler(); | |
| add(this); | |
| } | |
| @Override | |
| public String toString() { | |
| return "one"; | |
| } | |
| }; | |
| FooEvent.register(eventBus, one); | |
| FooEvent.register(eventBus, fooHandler1); | |
| FooEvent.register(eventBus, fooHandler2); | |
| FooEvent.register(eventBus, fooHandler3); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(one, fooHandler1, fooHandler2, fooHandler3); | |
| assertNotFired(two); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(one, fooHandler1, fooHandler2, fooHandler3); | |
| assertNotFired(two); | |
| } | |
| public void testConcurrentRemove() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| ShyHandler h = new ShyHandler(); | |
| FooEvent.register(eventBus, fooHandler1); | |
| h.r = FooEvent.register(eventBus, h); | |
| FooEvent.register(eventBus, fooHandler2); | |
| FooEvent.register(eventBus, fooHandler3); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(h, fooHandler1, fooHandler2, fooHandler3); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(fooHandler1, fooHandler2, fooHandler3); | |
| assertNotFired(h); | |
| } | |
| public void testFromSource() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| SourcedHandler global = new SourcedHandler("able"); | |
| SourcedHandler able = new SourcedHandler("able"); | |
| SourcedHandler baker = new SourcedHandler("baker"); | |
| FooEvent.register(eventBus, global); | |
| FooEvent.register(eventBus, "able", able); | |
| FooEvent.register(eventBus, "baker", baker); | |
| eventBus.fireEventFromSource(new FooEvent(), "able"); | |
| assertFired(global, able); | |
| assertNotFired(baker); | |
| } | |
| public void testHandlersThrow() { | |
| RuntimeException exception1 = new RuntimeException("first exception"); | |
| RuntimeException exception2 = new RuntimeException("second exception"); | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| FooEvent.register(eventBus, fooHandler1); | |
| FooEvent.register(eventBus, new ThrowingHandler(exception1)); | |
| FooEvent.register(eventBus, fooHandler2); | |
| FooEvent.register(eventBus, new ThrowingHandler(exception2)); | |
| FooEvent.register(eventBus, fooHandler3); | |
| FooEvent event = new FooEvent(); | |
| try { | |
| eventBus.fireEvent(event); | |
| fail("eventBus should have thrown"); | |
| } catch (UmbrellaException e) { | |
| Set<Throwable> causes = e.getCauses(); | |
| assertEquals("Exception should wrap the two thrown exceptions", 2, causes.size()); | |
| assertTrue("First exception should be under the umbrella", causes.contains(exception1)); | |
| assertTrue("Second exception should be under the umbrella", causes.contains(exception2)); | |
| } | |
| /* | |
| * Exception should not have prevented all three mouse handlers from getting | |
| * the event. | |
| */ | |
| assertFired(fooHandler1, fooHandler2, fooHandler3); | |
| } | |
| public void testNoDoubleRemove() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| HandlerRegistration reg = FooEvent.register(eventBus, fooHandler1); | |
| reg.removeHandler(); | |
| boolean assertsOn = getClass().desiredAssertionStatus(); | |
| if (assertsOn) { | |
| try { | |
| reg.removeHandler(); | |
| fail("Should have thrown on remove"); | |
| } catch (AssertionError e) { /* pass */ | |
| } | |
| } else { | |
| reg.removeHandler(); | |
| // Succeed on no assert failure | |
| } | |
| } | |
| public void testNoSource() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| SourcedHandler global = new SourcedHandler(null); | |
| SourcedHandler able = new SourcedHandler("able"); | |
| SourcedHandler baker = new SourcedHandler("baker"); | |
| FooEvent.register(eventBus, global); | |
| FooEvent.register(eventBus, "able", able); | |
| FooEvent.register(eventBus, "baker", baker); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(global); | |
| assertNotFired(able, baker); | |
| } | |
| public void testNullChecks() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| eventBus.addHandler(null, fooHandler1); | |
| } | |
| }); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| FooEvent.register(eventBus, "foo", null); | |
| } | |
| }); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| FooEvent.register(eventBus, null, fooHandler1); | |
| } | |
| }); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| eventBus.addHandlerToSource(null, "foo", fooHandler1); | |
| } | |
| }); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| eventBus.fireEvent(null); | |
| } | |
| }); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| eventBus.fireEventFromSource(null, ""); | |
| } | |
| }); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| eventBus.fireEventFromSource(new FooEvent() { | |
| }, null); | |
| } | |
| }); | |
| assertThrowsNpe(new Command() { | |
| public void execute() { | |
| eventBus.fireEventFromSource(null, "baker"); | |
| } | |
| }); | |
| } | |
| public void testNullSourceOkay() { | |
| SimpleEventBus reg = new SimpleEventBus(); | |
| FooEvent.Handler handler = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| add(this); | |
| assertNull(event.getSource()); | |
| } | |
| }; | |
| reg.addHandler(FooEvent.TYPE, handler); | |
| reg.fireEvent(new FooEvent()); | |
| assertFired(handler); | |
| } | |
| public void testRemoveSelf() { | |
| final SimpleEventBus eventBus = new SimpleEventBus(); | |
| FooEvent.Handler h = new FooEvent.Handler() { | |
| HandlerRegistration reg = FooEvent.register(eventBus, this); | |
| public void onFoo(FooEvent event) { | |
| add(this); | |
| reg.removeHandler(); | |
| } | |
| }; | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(h); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertNotFired(h); | |
| } | |
| public void testReverseOrder() { | |
| @SuppressWarnings("deprecation") | |
| final SimpleEventBus eventBus = new SimpleEventBus(true); | |
| final FooEvent.Handler handler0 = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| add(this); | |
| } | |
| }; | |
| final FooEvent.Handler handler1 = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| assertNotFired(handler0); | |
| add(this); | |
| } | |
| }; | |
| final FooEvent.Handler handler2 = new FooEvent.Handler() { | |
| public void onFoo(FooEvent event) { | |
| assertNotFired(handler0, handler1); | |
| add(this); | |
| } | |
| }; | |
| FooEvent.register(eventBus, handler0); | |
| FooEvent.register(eventBus, handler1); | |
| FooEvent.register(eventBus, handler2); | |
| reset(); | |
| eventBus.fireEvent(new FooEvent()); | |
| assertFired(handler0, handler1, handler2); | |
| } | |
| private void assertThrowsNpe(Command command) { | |
| try { | |
| command.execute(); | |
| fail("expected NullPointerException"); | |
| } catch (NullPointerException e) { | |
| /* pass */ | |
| } | |
| } | |
| } |