blob: b0a332aa16586d63c64830e1c7fbed38341e394d [file] [log] [blame]
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.eventbus;
import com.google.common.testing.EqualsTester;
import junit.framework.TestCase;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Test case for {@link EventSubscriber}.
*
* @author Cliff Biffle
*/
public class EventSubscriberTest extends TestCase {
private static final Object FIXTURE_ARGUMENT = new Object();
private boolean methodCalled;
private Object methodArgument;
@Override protected void setUp() throws Exception {
super.setUp();
methodCalled = false;
methodArgument = null;
}
/**
* Checks that a no-frills, no-issues method call is properly executed.
*
* @throws Exception if the aforementioned proper execution is not to be had.
*/
public void testBasicMethodCall() throws Exception {
Method method = getRecordingMethod();
EventSubscriber subscriber = new EventSubscriber(this, method);
subscriber.handleEvent(FIXTURE_ARGUMENT);
assertTrue("Subscriber must call provided method.", methodCalled);
assertTrue("Subscriber argument must be *exactly* the provided object.",
methodArgument == FIXTURE_ARGUMENT);
}
public void testExceptionWrapping() {
Method method = getExceptionThrowingMethod();
EventSubscriber subscriber = new EventSubscriber(this, method);
try {
subscriber.handleEvent(new Object());
fail("Subscribers whose methods throw must throw InvocationTargetException");
} catch (InvocationTargetException e) {
assertTrue("Expected exception must be wrapped.",
e.getCause() instanceof IntentionalException);
}
}
public void testErrorPassthrough() throws InvocationTargetException {
Method method = getErrorThrowingMethod();
EventSubscriber subscriber = new EventSubscriber(this, method);
try {
subscriber.handleEvent(new Object());
fail("Subscribers whose methods throw Errors must rethrow them");
} catch (JudgmentError e) {
// Expected.
}
}
public void testEquals() throws Exception {
Method charAt = String.class.getMethod("charAt", int.class);
Method concat = String.class.getMethod("concat", String.class);
new EqualsTester()
.addEqualityGroup(
new EventSubscriber("foo", charAt), new EventSubscriber("foo", charAt))
.addEqualityGroup(new EventSubscriber("bar", charAt))
.addEqualityGroup(new EventSubscriber("foo", concat))
.testEquals();
}
/**
* Gets a reference to {@link #recordingMethod(Object)}.
*
* @return a Method wrapping {@link #recordingMethod(Object)}.
* @throws IllegalStateException if executed in a context where reflection is
* unavailable.
* @throws AssertionError if something odd has happened to
* {@link #recordingMethod(Object)}.
*/
private Method getRecordingMethod() {
Method method;
try {
method = getClass().getMethod("recordingMethod", Object.class);
} catch (SecurityException e) {
throw new IllegalStateException("This test needs access to reflection.");
} catch (NoSuchMethodException e) {
throw new AssertionError(
"Someone changed EventSubscriberTest#recordingMethod's visibility, " +
"signature, or removed it entirely. (Must be public.)");
}
return method;
}
/**
* Gets a reference to {@link #exceptionThrowingMethod(Object)}.
*
* @return a Method wrapping {@link #exceptionThrowingMethod(Object)}.
* @throws IllegalStateException if executed in a context where reflection is
* unavailable.
* @throws AssertionError if something odd has happened to
* {@link #exceptionThrowingMethod(Object)}.
*/
private Method getExceptionThrowingMethod() {
Method method;
try {
method = getClass().getMethod("exceptionThrowingMethod", Object.class);
} catch (SecurityException e) {
throw new IllegalStateException("This test needs access to reflection.");
} catch (NoSuchMethodException e) {
throw new AssertionError(
"Someone changed EventSubscriberTest#exceptionThrowingMethod's " +
"visibility, signature, or removed it entirely. (Must be public.)");
}
return method;
}
/**
* Gets a reference to {@link #errorThrowingMethod(Object)}.
*
* @return a Method wrapping {@link #errorThrowingMethod(Object)}.
* @throws IllegalStateException if executed in a context where reflection is
* unavailable.
* @throws AssertionError if something odd has happened to
* {@link #errorThrowingMethod(Object)}.
*/
private Method getErrorThrowingMethod() {
Method method;
try {
method = getClass().getMethod("errorThrowingMethod", Object.class);
} catch (SecurityException e) {
throw new IllegalStateException("This test needs access to reflection.");
} catch (NoSuchMethodException e) {
throw new AssertionError(
"Someone changed EventSubscriberTest#errorThrowingMethod's " +
"visibility, signature, or removed it entirely. (Must be public.)");
}
return method;
}
/**
* Records the provided object in {@link #methodArgument} and sets
* {@link #methodCalled}. This method is called reflectively by EventSubscriber
* during tests, and must remain public.
*
* @param arg argument to record.
*/
public void recordingMethod(Object arg) {
assertFalse(methodCalled);
methodCalled = true;
methodArgument = arg;
}
public void exceptionThrowingMethod(Object arg) throws Exception {
throw new IntentionalException();
}
/** Local exception subclass to check variety of exception thrown. */
class IntentionalException extends Exception {
private static final long serialVersionUID = -2500191180248181379L;
}
public void errorThrowingMethod(Object arg) {
throw new JudgmentError();
}
/** Local Error subclass to check variety of error thrown. */
class JudgmentError extends Error {
private static final long serialVersionUID = 634248373797713373L;
}
}