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