Home | History | Annotate | Download | only in eventbus
      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 com.google.common.testing.EqualsTester;
     20 
     21 import junit.framework.TestCase;
     22 
     23 import java.lang.reflect.InvocationTargetException;
     24 import java.lang.reflect.Method;
     25 
     26 /**
     27  * Test case for {@link EventSubscriber}.
     28  *
     29  * @author Cliff Biffle
     30  */
     31 public class EventSubscriberTest extends TestCase {
     32 
     33   private static final Object FIXTURE_ARGUMENT = new Object();
     34 
     35   private boolean methodCalled;
     36   private Object methodArgument;
     37 
     38   @Override protected void setUp() throws Exception {
     39     super.setUp();
     40 
     41     methodCalled = false;
     42     methodArgument = null;
     43   }
     44 
     45   /**
     46    * Checks that a no-frills, no-issues method call is properly executed.
     47    *
     48    * @throws Exception  if the aforementioned proper execution is not to be had.
     49    */
     50   public void testBasicMethodCall() throws Exception {
     51     Method method = getRecordingMethod();
     52 
     53     EventSubscriber subscriber = new EventSubscriber(this, method);
     54 
     55     subscriber.handleEvent(FIXTURE_ARGUMENT);
     56 
     57     assertTrue("Subscriber must call provided method.", methodCalled);
     58     assertTrue("Subscriber argument must be *exactly* the provided object.",
     59         methodArgument == FIXTURE_ARGUMENT);
     60   }
     61 
     62   public void testExceptionWrapping() {
     63     Method method = getExceptionThrowingMethod();
     64     EventSubscriber subscriber = new EventSubscriber(this, method);
     65 
     66     try {
     67       subscriber.handleEvent(new Object());
     68       fail("Subscribers whose methods throw must throw InvocationTargetException");
     69     } catch (InvocationTargetException e) {
     70       assertTrue("Expected exception must be wrapped.",
     71           e.getCause() instanceof IntentionalException);
     72     }
     73   }
     74 
     75   public void testErrorPassthrough() throws InvocationTargetException {
     76     Method method = getErrorThrowingMethod();
     77     EventSubscriber subscriber = new EventSubscriber(this, method);
     78 
     79     try {
     80       subscriber.handleEvent(new Object());
     81       fail("Subscribers whose methods throw Errors must rethrow them");
     82     } catch (JudgmentError e) {
     83       // Expected.
     84     }
     85   }
     86 
     87   public void testEquals() throws Exception {
     88     Method charAt = String.class.getMethod("charAt", int.class);
     89     Method concat = String.class.getMethod("concat", String.class);
     90     new EqualsTester()
     91         .addEqualityGroup(
     92             new EventSubscriber("foo", charAt), new EventSubscriber("foo", charAt))
     93         .addEqualityGroup(new EventSubscriber("bar", charAt))
     94         .addEqualityGroup(new EventSubscriber("foo", concat))
     95         .testEquals();
     96   }
     97 
     98   /**
     99    * Gets a reference to {@link #recordingMethod(Object)}.
    100    *
    101    * @return a Method wrapping {@link #recordingMethod(Object)}.
    102    * @throws IllegalStateException if executed in a context where reflection is
    103    *         unavailable.
    104    * @throws AssertionError if something odd has happened to
    105    *         {@link #recordingMethod(Object)}.
    106    */
    107   private Method getRecordingMethod() {
    108     Method method;
    109     try {
    110       method = getClass().getMethod("recordingMethod", Object.class);
    111     } catch (SecurityException e) {
    112       throw new IllegalStateException("This test needs access to reflection.");
    113     } catch (NoSuchMethodException e) {
    114       throw new AssertionError(
    115           "Someone changed EventSubscriberTest#recordingMethod's visibility, " +
    116           "signature, or removed it entirely.  (Must be public.)");
    117     }
    118     return method;
    119   }
    120 
    121   /**
    122    * Gets a reference to {@link #exceptionThrowingMethod(Object)}.
    123    *
    124    * @return a Method wrapping {@link #exceptionThrowingMethod(Object)}.
    125    * @throws IllegalStateException if executed in a context where reflection is
    126    *         unavailable.
    127    * @throws AssertionError if something odd has happened to
    128    *         {@link #exceptionThrowingMethod(Object)}.
    129    */
    130   private Method getExceptionThrowingMethod() {
    131     Method method;
    132     try {
    133       method = getClass().getMethod("exceptionThrowingMethod", Object.class);
    134     } catch (SecurityException e) {
    135       throw new IllegalStateException("This test needs access to reflection.");
    136     } catch (NoSuchMethodException e) {
    137       throw new AssertionError(
    138           "Someone changed EventSubscriberTest#exceptionThrowingMethod's " +
    139           "visibility, signature, or removed it entirely.  (Must be public.)");
    140     }
    141     return method;
    142   }
    143 
    144   /**
    145    * Gets a reference to {@link #errorThrowingMethod(Object)}.
    146    *
    147    * @return a Method wrapping {@link #errorThrowingMethod(Object)}.
    148    * @throws IllegalStateException if executed in a context where reflection is
    149    *         unavailable.
    150    * @throws AssertionError if something odd has happened to
    151    *         {@link #errorThrowingMethod(Object)}.
    152    */
    153   private Method getErrorThrowingMethod() {
    154     Method method;
    155     try {
    156       method = getClass().getMethod("errorThrowingMethod", Object.class);
    157     } catch (SecurityException e) {
    158       throw new IllegalStateException("This test needs access to reflection.");
    159     } catch (NoSuchMethodException e) {
    160       throw new AssertionError(
    161           "Someone changed EventSubscriberTest#errorThrowingMethod's " +
    162           "visibility, signature, or removed it entirely.  (Must be public.)");
    163     }
    164     return method;
    165   }
    166 
    167   /**
    168    * Records the provided object in {@link #methodArgument} and sets
    169    * {@link #methodCalled}.  This method is called reflectively by EventSubscriber
    170    * during tests, and must remain public.
    171    *
    172    * @param arg  argument to record.
    173    */
    174   public void recordingMethod(Object arg) {
    175     assertFalse(methodCalled);
    176     methodCalled = true;
    177     methodArgument = arg;
    178   }
    179 
    180   public void exceptionThrowingMethod(Object arg) throws Exception {
    181     throw new IntentionalException();
    182   }
    183   /** Local exception subclass to check variety of exception thrown. */
    184   class IntentionalException extends Exception {
    185     private static final long serialVersionUID = -2500191180248181379L;
    186   }
    187 
    188   public void errorThrowingMethod(Object arg) {
    189     throw new JudgmentError();
    190   }
    191   /** Local Error subclass to check variety of error thrown. */
    192   class JudgmentError extends Error {
    193     private static final long serialVersionUID = 634248373797713373L;
    194   }
    195 }
    196