|  | /* | 
|  | * 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; | 
|  |  | 
|  | @Override | 
|  | public void onFoo(FooEvent event) { | 
|  | add(this); | 
|  | r.removeHandler(); | 
|  | } | 
|  | } | 
|  |  | 
|  | class SourcedHandler implements FooEvent.Handler { | 
|  | final String expectedSource; | 
|  |  | 
|  | SourcedHandler(String source) { | 
|  | this.expectedSource = source; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | 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; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | 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() { | 
|  | @Override | 
|  | public void execute() { | 
|  | FooEvent.register(eventBus, fooHandler1); | 
|  | } | 
|  | }); | 
|  | throw new Error("expected AssertionFailedError"); | 
|  | } catch (AssertionFailedError e) { | 
|  | /* pass */ | 
|  | } | 
|  | } | 
|  |  | 
|  | public void testConcurrentAdd() { | 
|  | final SimpleEventBus eventBus = new SimpleEventBus(); | 
|  | final FooEvent.Handler two = new FooEvent.Handler() { | 
|  | @Override | 
|  | public void onFoo(FooEvent event) { | 
|  | add(this); | 
|  | } | 
|  | }; | 
|  | FooEvent.Handler one = new FooEvent.Handler() { | 
|  | @Override | 
|  | 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(); | 
|  |  | 
|  | @Override | 
|  | 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() { | 
|  | @Override | 
|  | public void onFoo(FooEvent event) { | 
|  | add(this); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public String toString() { | 
|  | return "two"; | 
|  | } | 
|  | }; | 
|  | FooEvent.Handler one = new FooEvent.Handler() { | 
|  | @Override | 
|  | 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(); | 
|  | reg.removeHandler(); // should not throw | 
|  | } | 
|  |  | 
|  | 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() { | 
|  | @Override | 
|  | public void execute() { | 
|  | eventBus.addHandler(null, fooHandler1); | 
|  | } | 
|  | }); | 
|  |  | 
|  | assertThrowsNpe(new Command() { | 
|  | @Override | 
|  | public void execute() { | 
|  | FooEvent.register(eventBus, "foo", null); | 
|  | } | 
|  | }); | 
|  | assertThrowsNpe(new Command() { | 
|  | @Override | 
|  | public void execute() { | 
|  | FooEvent.register(eventBus, null, fooHandler1); | 
|  | } | 
|  | }); | 
|  | assertThrowsNpe(new Command() { | 
|  | @Override | 
|  | public void execute() { | 
|  | eventBus.addHandlerToSource(null, "foo", fooHandler1); | 
|  | } | 
|  | }); | 
|  |  | 
|  | assertThrowsNpe(new Command() { | 
|  | @Override | 
|  | public void execute() { | 
|  | eventBus.fireEvent(null); | 
|  | } | 
|  | }); | 
|  |  | 
|  | assertThrowsNpe(new Command() { | 
|  | @Override | 
|  | public void execute() { | 
|  | eventBus.fireEventFromSource(null, ""); | 
|  | } | 
|  | }); | 
|  |  | 
|  | assertThrowsNpe(new Command() { | 
|  | @Override | 
|  | public void execute() { | 
|  | eventBus.fireEventFromSource(new FooEvent() { | 
|  | }, null); | 
|  | } | 
|  | }); | 
|  | assertThrowsNpe(new Command() { | 
|  | @Override | 
|  | public void execute() { | 
|  | eventBus.fireEventFromSource(null, "baker"); | 
|  | } | 
|  | }); | 
|  | } | 
|  |  | 
|  | public void testNullSourceOkay() { | 
|  | SimpleEventBus reg = new SimpleEventBus(); | 
|  |  | 
|  | FooEvent.Handler handler = new FooEvent.Handler() { | 
|  | @Override | 
|  | 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); | 
|  |  | 
|  | @Override | 
|  | 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() { | 
|  | @Override | 
|  | public void onFoo(FooEvent event) { | 
|  | add(this); | 
|  | } | 
|  | }; | 
|  | final FooEvent.Handler handler1 = new FooEvent.Handler() { | 
|  | @Override | 
|  | public void onFoo(FooEvent event) { | 
|  | assertNotFired(handler0); | 
|  | add(this); | 
|  | } | 
|  | }; | 
|  | final FooEvent.Handler handler2 = new FooEvent.Handler() { | 
|  | @Override | 
|  | 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 */ | 
|  | } | 
|  | } | 
|  | } |