package com.google.dart.tools.core;
import com.google.dart.tools.core.test.util.DartCoreTestLog;
import junit.framework.TestCase;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
/**
* Common {@link TestCase} superclass that asserts no unexpected Eclipse log entries and provides a
* setup method ({@link #setUpOnce()}) that is called once before all tests in the class are
* executed and a teardown method ({@link #tearDownOnce()}) that is called once after all tests in
* the class have been executed.
*/
public abstract class AbstractDartCoreTest extends TestCase {
/**
* The test log
*/
protected static final DartCoreTestLog LOG = DartCoreTestLog.getLog();
/**
* Used to determine when {@link #setUpOnce()} and {@link #tearDownOnce()} should be called.
*/
private static final HashMap<Class<?>, Integer> TEST_COUNTS = new HashMap<Class<?>, Integer>();
/**
* Called once prior to the receiver's first test.
*/
public static void setUpOnce() throws Exception {
}
/**
* Called once after the receiver's last test.
*/
public static void tearDownOnce() throws Exception {
}
/**
* Answer the number of test methods in the specified class
*
* @param testClass the test class (not <code>null</code>)
* @return the number of test methods
*/
private static int countTestMethods(Class<?> testClass) {
int count = 0;
for (Method method : testClass.getDeclaredMethods()) {
if (isTestMethod(method)) {
count++;
}
}
return count;
}
/**
* Answer <code>true</code> if the specified method has name that starts with "test", is public
* but not static, and has no arguments.
*/
private static boolean isTestMethod(Method method) {
if (!method.getName().startsWith("test")) {
return false;
}
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) == 0 || (modifiers & Modifier.STATIC) != 0) {
return false;
}
if (method.getParameterTypes().length > 0) {
return false;
}
return true;
}
public AbstractDartCoreTest() {
super();
}
public AbstractDartCoreTest(String name) {
super(name);
}
/**
* Extend superclass implementation to set up and tear down the DartCore test log and invoke
* {@link #setUpOnce()} and {@link #tearDownOnce()} if defined.
*/
@Override
public void runBare() throws Throwable {
Throwable exception = null;
if (!TEST_COUNTS.containsKey(getClass())) {
TEST_COUNTS.put(getClass(), countTestMethods(getClass()));
invokeStaticMethodIfExists(getClass(), "setUpOnce");
}
LOG.setUp();
try {
super.runBare();
} catch (Throwable running) {
exception = running;
} finally {
try {
LOG.tearDown();
int count = TEST_COUNTS.get(getClass()) - 1;
TEST_COUNTS.put(getClass(), count);
if (count == 0) {
invokeStaticMethodIfExists(getClass(), "tearDownOnce");
}
} catch (Throwable tearingDown) {
if (exception == null) {
exception = tearingDown;
}
}
}
if (exception != null) {
throw exception;
}
}
/**
* Extend superclass implementation to assert no unexpected DartCore log entries
*/
@Override
protected void runTest() throws Throwable {
super.runTest();
LOG.assertEmpty();
}
/**
* Execute the specified method if it exists
*
* @param testClass the class containing the static method to be executed (not <code>null</code>)
* @param methodName the name of the static method (not <code>null</code>)
*/
private void invokeStaticMethodIfExists(Class<?> testClass, String methodName) throws Exception {
Method method;
try {
method = testClass.getDeclaredMethod(methodName, new Class<?>[] {});
} catch (NoSuchMethodException e) {
return;
}
if ((method.getModifiers() & Modifier.PUBLIC) == 0
|| (method.getModifiers() & Modifier.STATIC) == 0) {
throw new IllegalAccessException("Expected " + testClass.getSimpleName() + "#" + methodName
+ " to be a public static method");
}
method.invoke(null);
}
}