• 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 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 
setUp()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    */
testBasicMethodCall()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 
testExceptionWrapping()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 
testErrorPassthrough()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 
testEquals()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    */
getRecordingMethod()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    */
getExceptionThrowingMethod()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    */
getErrorThrowingMethod()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    */
recordingMethod(Object arg)174   public void recordingMethod(Object arg) {
175     assertFalse(methodCalled);
176     methodCalled = true;
177     methodArgument = arg;
178   }
179 
exceptionThrowingMethod(Object arg)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 
errorThrowingMethod(Object arg)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