package org.apache.commons.collections4;
import java.util.ArrayList;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.lang.reflect.Method;
import junit.framework.TestSuite;
class BulkTestSuiteMaker {
/**
* The class that defines simple and bulk tests methods.
*/
private final Class<? extends org.apache.commons.collections4.BulkTest> startingClass;
/**
* List of ignored simple test names.
*/
private List<java.lang.String> ignored;
/**
* The TestSuite we're currently populating. Can change over time.
*/
private TestSuite result;
/**
* The prefix for simple test methods. Used to check if a test is in
* the ignored list.
*/
private String prefix;
/**
* Constructor.
*
* @param startingClass the starting class
*/
public BulkTestSuiteMaker(final Class<? extends org.apache.commons.collections4.BulkTest> startingClass) {
this.startingClass = startingClass;
}
/**
* Makes a hierarchical TestSuite based on the starting class.
*
* @return the hierarchical TestSuite for startingClass
*/
public TestSuite make() {
this.result = new TestSuite();
this.prefix = BulkTestSuiteMaker.getBaseName(startingClass);
result.setName(prefix);
final BulkTest bulk = BulkTestSuiteMaker.makeFirstTestCase(startingClass);
ignored = new ArrayList<java.lang.String>();
final String[] s = bulk.ignoredTests();
if (s != null) {
ignored.addAll(java.util.Arrays.asList(s));
}
make(bulk);
return result;
}
/**
* Appends all the simple tests and bulk tests defined by the given
* instance's class to the current TestSuite.
*
* @param bulk An instance of the class that defines simple and bulk
* tests for us to append
*/
void make(final BulkTest bulk) {
final Class<? extends org.apache.commons.collections4.BulkTest> c = bulk.getClass();
final Method[] all = c.getMethods();
for (final Method element : all) {
if (BulkTestSuiteMaker.isTest(element)) {
addTest(bulk, element);
}
if (BulkTestSuiteMaker.isBulk(element)) {
addBulk(bulk, element);
}
}
}
/**
* Adds the simple test defined by the given method to the TestSuite.
*
* @param bulk The instance of the class that defined the method
* (I know it's weird. But the point is, we can clone the instance
* and not have to worry about constructors.)
* @param m The simple test method
*/
void addTest(final BulkTest bulk, final Method m) {
final BulkTest bulk2 = ((BulkTest)(bulk.clone()));
bulk2.setName(m.getName());
bulk2.verboseName = ((prefix) + ".") + (m.getName());
if (ignored.contains(bulk2.verboseName)) {
return ;
}
result.addTest(bulk2);
}
/**
* Adds a whole new suite of tests that are defined by the result of
* the given bulk test method. In other words, the given bulk test
* method is invoked, and the resulting BulkTest instance is examined
* for yet more simple and bulk tests.
*
* @param bulk The instance of the class that defined the method
* @param m The bulk test method
*/
void addBulk(final BulkTest bulk, final Method m) {
final String verboseName = ((prefix) + ".") + (m.getName());
if (ignored.contains(verboseName)) {
return ;
}
BulkTest bulk2;
try {
bulk2 = ((BulkTest)(m.invoke(bulk, ((java.lang.Object[])(null)))));
if (bulk2 == null) {
return ;
}
} catch (final InvocationTargetException ex) {
ex.getTargetException().printStackTrace();
throw new Error();
} catch (final IllegalAccessException ex) {
ex.printStackTrace();
throw new Error();
}
final String oldPrefix = prefix;
final TestSuite oldResult = result;
prefix = ((prefix) + ".") + (m.getName());
result = new TestSuite();
result.setName(m.getName());
make(bulk2);
oldResult.addTest(result);
prefix = oldPrefix;
result = oldResult;
}
/**
* Returns the base name of the given class.
*
* @param c the class
* @return the name of that class, minus any package names
*/
private static String getBaseName(final Class<?> c) {
String name = c.getName();
final int p = name.lastIndexOf('.');
if (p > 0) {
name = name.substring((p + 1));
}
return name;
}
private static <T>Constructor<T> getTestCaseConstructor(final Class<T> c) {
try {
return c.getConstructor(new Class[]{ String.class });
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException((c + " must provide a (String) constructor"));
}
}
private static <T extends org.apache.commons.collections4.BulkTest>BulkTest makeTestCase(final Class<T> c, final Method m) {
final Constructor<T> con = BulkTestSuiteMaker.getTestCaseConstructor(c);
try {
return con.newInstance(m.getName());
} catch (final InvocationTargetException e) {
e.printStackTrace();
throw new RuntimeException();
} catch (final IllegalAccessException e) {
throw new Error();
} catch (final InstantiationException e) {
throw new RuntimeException();
}
}
private static <T extends org.apache.commons.collections4.BulkTest>BulkTest makeFirstTestCase(final Class<T> c) {
final Method[] all = c.getMethods();
for (final Method element : all) {
if (BulkTestSuiteMaker.isTest(element)) {
return BulkTestSuiteMaker.makeTestCase(c, element);
}
}
throw new IllegalArgumentException(((c.getName()) + " must provide at least one test method."));
}
/**
* Returns true if the given method is a simple test method.
*/
private static boolean isTest(final Method m) {
if (!(m.getName().startsWith("test"))) {
return false;
}
if ((m.getReturnType()) != (Void.TYPE)) {
return false;
}
if ((m.getParameterTypes().length) != 0) {
return false;
}
final int mods = m.getModifiers();
if (java.lang.reflect.Modifier.isStatic(mods)) {
return false;
}
if (java.lang.reflect.Modifier.isAbstract(mods)) {
return false;
}
return true;
}
/**
* Returns true if the given method is a bulk test method.
*/
private static boolean isBulk(final Method m) {
if (!(m.getName().startsWith("bulkTest"))) {
return false;
}
if ((m.getReturnType()) != (BulkTest.class)) {
return false;
}
if ((m.getParameterTypes().length) != 0) {
return false;
}
final int mods = m.getModifiers();
if (java.lang.reflect.Modifier.isStatic(mods)) {
return false;
}
if (java.lang.reflect.Modifier.isAbstract(mods)) {
return false;
}
return true;
}
}