blob: cc50de5da4f85f3eb96279ef13a82c729d3b008b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 Brad Reynolds and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Brad Reynolds - initial API and implementation
* Matthew Hall - bug 208322
******************************************************************************/
package org.eclipse.jface.databinding.conformance.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.eclipse.jface.databinding.conformance.delegate.IObservableContractDelegate;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Builds a test suite.
*
* @since 1.1
*/
public class SuiteBuilder {
private LinkedHashSet content;
public SuiteBuilder() {
content = new LinkedHashSet();
}
/**
* Adds all test methods from the provided <code>testCase</code> to the
* suite.
*
* @param testCase
* @return builder
*/
public SuiteBuilder addTests(Class testCase) {
content.add(testCase);
return this;
}
/**
* Adds all test methods from the provided <code>testCase</code> with the
* provided <code>parameters</code>. A constructor must exist in the
* testCase that accepts a String as the first parameter followed by
* parameters matching the provided parameters. If an appropriate
* constructor is not found an exception will be thrown.
*
* @param testCase
* @param parameters
* @return builder
*/
public SuiteBuilder addParameterizedTests(Class testCase,
Object[] parameters) {
Constructor constructor = findConstructor(testCase, parameters);
if (constructor == null) {
throw new IllegalArgumentException(
"The parameters provided don't match a constructor found in ["
+ testCase.getName() + "]");
}
content.add(new ParameterizedTest(testCase, constructor, parameters));
return this;
}
/**
* Convenience method for invoking
* {@link #addParameterizedTests(Class, Object[])} with a delegate.
*
* @param testCase
* @param delegate
* @return builder
*/
public SuiteBuilder addObservableContractTest(Class testCase,
IObservableContractDelegate delegate) {
addParameterizedTests(testCase, new Object[] {delegate});
return this;
}
/**
* Builds a new TestSuite out of the tests.
*
* @return suite
*/
public TestSuite build() {
TestSuite suite = new TestSuite();
for (Iterator it = content.iterator(); it.hasNext();) {
Object o = it.next();
if (o instanceof Class) {
suite.addTestSuite((Class) o);
} else if (o instanceof ParameterizedTest) {
ParameterizedTest test = (ParameterizedTest) o;
// Outer test named for parameterized test class
TestSuite testClassSuite = new TestSuite();
testClassSuite.setName(test.testClass.getName());
// Inner test named for parameter
TestSuite parameterSuite = new TestSuite();
parameterSuite.setName(test.parameters[0].getClass().getName());
testClassSuite.addTest(parameterSuite);
Method[] methods = test.testClass.getMethods();
for (int i = 0; i < methods.length; i++) {
String name = methods[i].getName();
if (name.startsWith("test")) {
try {
parameterSuite.addTest((Test) test.constructor
.newInstance(toParamArray(name,
test.parameters)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
if (testClassSuite.countTestCases() > 0)
suite.addTest(testClassSuite);
}
}
return suite;
}
private Object[] toParamArray(String testName, Object[] parameters) {
Object[] result = new Object[parameters.length + 1];
result[0] = testName;
System.arraycopy(parameters, 0, result, 1, parameters.length);
return result;
}
/**
* Returns the constructor that has a String as the first parameters and
* then matches the type of the parameters.
* @param clazz
* @param parameters
* @return constructor
*/
private static Constructor findConstructor(Class clazz, Object[] parameters) {
Constructor[] constructors = clazz.getConstructors();
int expectedParametersLength = parameters.length + 1;
for (int i = 0; i < constructors.length; i++) {
Constructor constructor = constructors[i];
Class[] types = constructor.getParameterTypes();
if (types.length != expectedParametersLength
|| !String.class.equals(types[0])) {
continue;
}
boolean skip = false;
for (int j = 1; j < types.length; j++) {
Class type = types[j];
if (!type.isInstance(parameters[j - 1])) {
skip = true;
break;
}
}
if (!skip) {
return constructor;
}
}
return null;
}
/* package */static class ParameterizedTest {
final Constructor constructor;
final Object[] parameters;
private Class testClass;
ParameterizedTest(Class testClass, Constructor constructor,
Object[] parameterss) {
this.testClass = testClass;
this.constructor = constructor;
this.parameters = parameterss;
}
}
}