1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.eventbus; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import com.google.common.testing.EqualsTester; 22 import java.lang.reflect.InvocationTargetException; 23 import java.lang.reflect.Method; 24 import junit.framework.TestCase; 25 26 /** 27 * Tests for {@link Subscriber}. 28 * 29 * @author Cliff Biffle 30 * @author Colin Decker 31 */ 32 public class SubscriberTest extends TestCase { 33 34 private static final Object FIXTURE_ARGUMENT = new Object(); 35 36 private EventBus bus; 37 private boolean methodCalled; 38 private Object methodArgument; 39 40 @Override setUp()41 protected void setUp() throws Exception { 42 bus = new EventBus(); 43 methodCalled = false; 44 methodArgument = null; 45 } 46 testCreate()47 public void testCreate() { 48 Subscriber s1 = Subscriber.create(bus, this, getTestSubscriberMethod("recordingMethod")); 49 assertThat(s1).isInstanceOf(Subscriber.SynchronizedSubscriber.class); 50 51 // a thread-safe method should not create a synchronized subscriber 52 Subscriber s2 = Subscriber.create(bus, this, getTestSubscriberMethod("threadSafeMethod")); 53 assertThat(s2).isNotInstanceOf(Subscriber.SynchronizedSubscriber.class); 54 } 55 testInvokeSubscriberMethod_basicMethodCall()56 public void testInvokeSubscriberMethod_basicMethodCall() throws Throwable { 57 Method method = getTestSubscriberMethod("recordingMethod"); 58 Subscriber subscriber = Subscriber.create(bus, this, method); 59 60 subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT); 61 62 assertTrue("Subscriber must call provided method", methodCalled); 63 assertTrue( 64 "Subscriber argument must be exactly the provided object.", 65 methodArgument == FIXTURE_ARGUMENT); 66 } 67 testInvokeSubscriberMethod_exceptionWrapping()68 public void testInvokeSubscriberMethod_exceptionWrapping() throws Throwable { 69 Method method = getTestSubscriberMethod("exceptionThrowingMethod"); 70 Subscriber subscriber = Subscriber.create(bus, this, method); 71 72 try { 73 subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT); 74 fail("Subscribers whose methods throw must throw InvocationTargetException"); 75 } catch (InvocationTargetException expected) { 76 assertThat(expected).hasCauseThat().isInstanceOf(IntentionalException.class); 77 } 78 } 79 testInvokeSubscriberMethod_errorPassthrough()80 public void testInvokeSubscriberMethod_errorPassthrough() throws Throwable { 81 Method method = getTestSubscriberMethod("errorThrowingMethod"); 82 Subscriber subscriber = Subscriber.create(bus, this, method); 83 84 try { 85 subscriber.invokeSubscriberMethod(FIXTURE_ARGUMENT); 86 fail("Subscribers whose methods throw Errors must rethrow them"); 87 } catch (JudgmentError expected) { 88 } 89 } 90 testEquals()91 public void testEquals() throws Exception { 92 Method charAt = String.class.getMethod("charAt", int.class); 93 Method concat = String.class.getMethod("concat", String.class); 94 new EqualsTester() 95 .addEqualityGroup( 96 Subscriber.create(bus, "foo", charAt), Subscriber.create(bus, "foo", charAt)) 97 .addEqualityGroup(Subscriber.create(bus, "bar", charAt)) 98 .addEqualityGroup(Subscriber.create(bus, "foo", concat)) 99 .testEquals(); 100 } 101 getTestSubscriberMethod(String name)102 private Method getTestSubscriberMethod(String name) { 103 try { 104 return getClass().getDeclaredMethod(name, Object.class); 105 } catch (NoSuchMethodException e) { 106 throw new AssertionError(); 107 } 108 } 109 110 /** 111 * Records the provided object in {@link #methodArgument} and sets {@link #methodCalled}. This 112 * method is called reflectively by Subscriber during tests, and must remain public. 113 * 114 * @param arg argument to record. 115 */ 116 @Subscribe recordingMethod(Object arg)117 public void recordingMethod(Object arg) { 118 assertFalse(methodCalled); 119 methodCalled = true; 120 methodArgument = arg; 121 } 122 123 @Subscribe exceptionThrowingMethod(Object arg)124 public void exceptionThrowingMethod(Object arg) throws Exception { 125 throw new IntentionalException(); 126 } 127 128 /** Local exception subclass to check variety of exception thrown. */ 129 class IntentionalException extends Exception { 130 131 private static final long serialVersionUID = -2500191180248181379L; 132 } 133 134 @Subscribe errorThrowingMethod(Object arg)135 public void errorThrowingMethod(Object arg) { 136 throw new JudgmentError(); 137 } 138 139 @Subscribe 140 @AllowConcurrentEvents threadSafeMethod(Object arg)141 public void threadSafeMethod(Object arg) {} 142 143 /** Local Error subclass to check variety of error thrown. */ 144 class JudgmentError extends Error { 145 146 private static final long serialVersionUID = 634248373797713373L; 147 } 148 } 149