| /* |
| * Copyright 2008 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.gwt.event.shared; |
| |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.event.dom.client.ClickEvent; |
| import com.google.gwt.event.dom.client.MouseDownEvent; |
| import com.google.gwt.event.dom.client.MouseDownHandler; |
| |
| import java.util.Set; |
| |
| /** |
| * Handler manager test. Very redundant with {@link SimpleEventBusTest}, but |
| * preserved to guard against regressions. |
| */ |
| public class HandlerManagerTest extends HandlerTestBase { |
| |
| public void testAddAndRemoveHandlers() { |
| HandlerManager manager = new HandlerManager("bogus source"); |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| manager.addHandler(MouseDownEvent.getType(), mouse2); |
| manager.addHandler(MouseDownEvent.getType(), adaptor1); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertEquals(3, manager.getHandlerCount(MouseDownEvent.getType())); |
| assertFired(mouse1, mouse2, adaptor1); |
| manager.addHandler(MouseDownEvent.getType(), mouse3); |
| assertEquals(4, manager.getHandlerCount(MouseDownEvent.getType())); |
| |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| manager.addHandler(MouseDownEvent.getType(), mouse2); |
| manager.addHandler(MouseDownEvent.getType(), adaptor1); |
| |
| // You can indeed add handlers twice, they will only be removed one at a |
| // time though. |
| assertEquals(7, manager.getHandlerCount(MouseDownEvent.getType())); |
| manager.addHandler(ClickEvent.getType(), adaptor1); |
| manager.addHandler(ClickEvent.getType(), click1); |
| manager.addHandler(ClickEvent.getType(), click2); |
| |
| assertEquals(7, manager.getHandlerCount(MouseDownEvent.getType())); |
| assertEquals(3, manager.getHandlerCount(ClickEvent.getType())); |
| |
| reset(); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(mouse1, mouse2, mouse3, adaptor1); |
| assertNotFired(click1, click2); |
| // Gets rid of first instance. |
| manager.removeHandler(MouseDownEvent.getType(), adaptor1); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(mouse1, mouse2, mouse3, adaptor1); |
| assertNotFired(click1, click2); |
| |
| // Gets rid of second instance. |
| manager.removeHandler(MouseDownEvent.getType(), adaptor1); |
| reset(); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| |
| assertFired(mouse1, mouse2, mouse3); |
| assertNotFired(adaptor1, click1, click2); |
| |
| // Checks to see if click events are still working. |
| reset(); |
| manager.fireEvent(new ClickEvent() { |
| }); |
| |
| assertNotFired(mouse1, mouse2, mouse3); |
| assertFired(click1, click2, adaptor1); |
| } |
| |
| public void testConcurrentAdd() { |
| final HandlerManager manager = new HandlerManager("bogus source"); |
| final MouseDownHandler two = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| add(this); |
| } |
| }; |
| MouseDownHandler one = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| manager.addHandler(MouseDownEvent.getType(), two); |
| add(this); |
| } |
| }; |
| manager.addHandler(MouseDownEvent.getType(), one); |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| manager.addHandler(MouseDownEvent.getType(), mouse2); |
| manager.addHandler(MouseDownEvent.getType(), mouse3); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(one, mouse1, mouse2, mouse3); |
| assertNotFired(two); |
| |
| reset(); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(one, two, mouse1, mouse2, mouse3); |
| } |
| |
| class ShyHandler implements MouseDownHandler { |
| HandlerRegistration r; |
| |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| add(this); |
| r.removeHandler(); |
| } |
| } |
| |
| public void testConcurrentRemove() { |
| final HandlerManager manager = new HandlerManager("bogus source"); |
| |
| ShyHandler h = new ShyHandler(); |
| |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| h.r = manager.addHandler(MouseDownEvent.getType(), h); |
| manager.addHandler(MouseDownEvent.getType(), mouse2); |
| manager.addHandler(MouseDownEvent.getType(), mouse3); |
| |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(h, mouse1, mouse2, mouse3); |
| reset(); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(mouse1, mouse2, mouse3); |
| assertNotFired(h); |
| } |
| |
| public void testConcurrentAddAndRemoveByNastyUsersTryingToHurtUs() { |
| final HandlerManager manager = new HandlerManager("bogus source"); |
| final MouseDownHandler two = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| add(this); |
| } |
| |
| @Override |
| public String toString() { |
| return "two"; |
| } |
| }; |
| MouseDownHandler one = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| manager.addHandler(MouseDownEvent.getType(), two).removeHandler(); |
| add(this); |
| } |
| |
| @Override |
| public String toString() { |
| return "one"; |
| } |
| }; |
| manager.addHandler(MouseDownEvent.getType(), one); |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| manager.addHandler(MouseDownEvent.getType(), mouse2); |
| manager.addHandler(MouseDownEvent.getType(), mouse3); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(one, mouse1, mouse2, mouse3); |
| assertNotFired(two); |
| |
| reset(); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(one, mouse1, mouse2, mouse3); |
| assertNotFired(two); |
| } |
| |
| public void testConcurrentAddAfterRemoveIsNotClobbered() { |
| final HandlerManager manager = new HandlerManager("bogus source"); |
| |
| MouseDownHandler one = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| manager.removeHandler(MouseDownEvent.getType(), mouse1); |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| add(this); |
| } |
| }; |
| manager.addHandler(MouseDownEvent.getType(), one); |
| |
| boolean assertsOn = getClass().desiredAssertionStatus(); |
| |
| if (assertsOn) { |
| try { |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| // TODO(b/28015134): fireEvent does not throw as expected, so this assertion fails. |
| // throw new Error("Should have thrown on remove"); |
| } catch (AssertionError e) { /* pass */ |
| } |
| return; |
| } |
| |
| // Production Mode, no asserts, so remove will quietly succeed. |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(one); |
| reset(); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(one, mouse1); |
| } |
| |
| public void testMultiFiring() { |
| |
| final MouseDownEvent masterEvent = new MouseDownEvent() { |
| }; |
| |
| HandlerManager manager = new HandlerManager("source1"); |
| |
| final HandlerManager manager2 = new HandlerManager("source2"); |
| |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| |
| manager.addHandler(MouseDownEvent.getType(), new MouseDownHandler() { |
| |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| manager2.fireEvent(event); |
| } |
| |
| }); |
| manager.addHandler(MouseDownEvent.getType(), mouse3); |
| manager2.addHandler(MouseDownEvent.getType(), adaptor1); |
| manager2.addHandler(MouseDownEvent.getType(), new MouseDownHandler() { |
| |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| assertEquals("source2", event.getSource()); |
| assertSame(masterEvent, event); |
| } |
| |
| }); |
| manager.addHandler(MouseDownEvent.getType(), new MouseDownHandler() { |
| |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| assertEquals("source1", event.getSource()); |
| assertSame(masterEvent, event); |
| } |
| |
| }); |
| |
| reset(); |
| manager.fireEvent(masterEvent); |
| assertFired(mouse1, adaptor1, mouse3); |
| assertFalse("Event should be dead", masterEvent.isLive()); |
| } |
| |
| // This test is disabled because it fails '-ea' |
| public void notestRemoveUnhandledType() { |
| final HandlerManager manager = new HandlerManager("bogus source"); |
| HandlerRegistration reg = manager.addHandler(MouseDownEvent.getType(), |
| mouse1); |
| reg.removeHandler(); |
| |
| if (!GWT.isScript()) { |
| try { |
| reg.removeHandler(); |
| throw new Error("Should have thrown assertion error"); |
| } catch (AssertionError e) { |
| /* pass */ |
| } |
| } else { |
| reg.removeHandler(); |
| /* pass, we didn't hit an NPE */ |
| } |
| } |
| |
| public void testReverseOrder() { |
| // Add some handlers to a manager |
| final HandlerManager manager = new HandlerManager("source1", true); |
| final MouseDownHandler handler0 = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| add(this); |
| } |
| }; |
| final MouseDownHandler handler1 = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| assertNotFired(handler0); |
| add(this); |
| } |
| }; |
| final MouseDownHandler handler2 = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| assertNotFired(handler0, handler1); |
| add(this); |
| } |
| }; |
| manager.addHandler(MouseDownEvent.getType(), handler0); |
| manager.addHandler(MouseDownEvent.getType(), handler1); |
| manager.addHandler(MouseDownEvent.getType(), handler2); |
| |
| // Fire the event |
| reset(); |
| manager.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(handler0, handler1, handler2); |
| } |
| |
| static class ThrowingHandler implements MouseDownHandler { |
| private final RuntimeException e; |
| |
| public ThrowingHandler(RuntimeException e) { |
| this.e = e; |
| } |
| |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| throw e; |
| } |
| } |
| |
| public void testHandlersThrow() { |
| RuntimeException exception1 = new RuntimeException("first exception"); |
| RuntimeException exception2 = new RuntimeException("second exception"); |
| |
| final HandlerManager manager = new HandlerManager("bogus source"); |
| |
| manager.addHandler(MouseDownEvent.getType(), mouse1); |
| manager.addHandler(MouseDownEvent.getType(), new ThrowingHandler(exception1)); |
| manager.addHandler(MouseDownEvent.getType(), mouse2); |
| manager.addHandler(MouseDownEvent.getType(), new ThrowingHandler(exception2)); |
| manager.addHandler(MouseDownEvent.getType(), mouse3); |
| |
| MouseDownEvent event = new MouseDownEvent() { |
| }; |
| |
| try { |
| manager.fireEvent(event); |
| fail("Manager 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(mouse1, mouse2, mouse3); |
| } |
| |
| public void testNullSourceOkay() { |
| SimpleEventBus reg = new SimpleEventBus(); |
| |
| MouseDownHandler handler = new MouseDownHandler() { |
| @Override |
| public void onMouseDown(MouseDownEvent event) { |
| add(this); |
| assertNull(event.getSource()); |
| } |
| }; |
| reg.addHandler(MouseDownEvent.getType(), handler); |
| reg.fireEvent(new MouseDownEvent() { |
| }); |
| assertFired(handler); |
| } |
| } |