• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
setUp()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    */
testBasicMethodCall()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    */
testRejectionOfNullMethods()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    */
testRejectionOfNullTargets()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 
testExceptionWrapping()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 
testErrorPassthrough()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    */
getRecordingMethod()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    */
getExceptionThrowingMethod()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    */
getErrorThrowingMethod()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    */
recordingMethod(Object arg)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 
exceptionThrowingMethod(Object arg)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 
errorThrowingMethod(Object arg)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