/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.envers.test;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.hibernate.testing.junit4.CustomRunner;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runners.Parameterized;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.TestClass;
/**
* Copied & modified from {@link org.junit.runners.Parameterized}.
* <p/>
* The modification is that the generated runners extend {@link CustomRunner} instead of the default
* {@code TestClassRunnerForParameters}.
* <p/>
* The runner itself sets the data using a setter instead of a constructor, and creates only one test instance. Moreover
* it doesn't override {@code classBlock} which causes the custom {@code @BeforeClassOnce} and {@code @AfterClassOnce}
* annotations to work.
*
* @author Adam Warski (adam at warski dot org)
*/
public class EnversRunner extends Suite {
private class TestClassCustomRunnerForParameters extends CustomRunner {
private final int fParameterSetNumber;
private final List<Object[]> fParameterList;
TestClassCustomRunnerForParameters(Class<?> type, List<Object[]> parameterList, int i)
throws InitializationError, NoTestsRemainException {
super( type );
fParameterList = parameterList;
fParameterSetNumber = i;
}
@Override
protected Object getTestInstance() throws Exception {
Object testInstance = super.getTestInstance();
if ( AbstractEnversTest.class.isInstance( testInstance ) ) {
((AbstractEnversTest) testInstance).setTestData( computeParams() );
}
else if ( BaseEnversFunctionalTestCase.class.isInstance( testInstance ) ) {
((BaseEnversFunctionalTestCase) testInstance).setTestData( computeParams() );
}
return testInstance;
}
private Object[] computeParams() throws Exception {
try {
return fParameterList.get( fParameterSetNumber );
}
catch (ClassCastException e) {
throw new Exception(
String.format(
"%s.%s() must return a Collection of arrays.",
getTestClass().getName(), getParametersMethod(
getTestClass()
).getName()
)
);
}
}
@Override
protected String getName() {
return String.format( "[%s]", fParameterSetNumber );
}
@Override
protected String testName(final FrameworkMethod method) {
return String.format(
"%s[%s]", method.getName(),
fParameterSetNumber
);
}
@Override
protected void sortMethods(List<FrameworkMethod> computedTestMethods) {
super.sortMethods( computedTestMethods );
Collections.sort(
computedTestMethods, new Comparator<FrameworkMethod>() {
private int getPriority(FrameworkMethod fm) {
Priority p = fm.getAnnotation( Priority.class );
return p == null ? 0 : p.value();
}
@Override
public int compare(FrameworkMethod fm1, FrameworkMethod fm2) {
return getPriority( fm2 ) - getPriority( fm1 );
}
}
);
}
}
private final ArrayList<Runner> runners = new ArrayList<Runner>();
/**
* Only called reflectively. Do not use programmatically.
*/
public EnversRunner(Class<?> klass) throws Throwable {
super( klass, Collections.<Runner>emptyList() );
List<Object[]> parametersList = getParametersList( getTestClass() );
for ( int i = 0; i < parametersList.size(); i++ ) {
runners.add(
new TestClassCustomRunnerForParameters(
getTestClass().getJavaClass(),
parametersList, i
)
);
}
}
@Override
protected List<Runner> getChildren() {
return runners;
}
@SuppressWarnings("unchecked")
private List<Object[]> getParametersList(TestClass klass)
throws Throwable {
return (List<Object[]>) getParametersMethod( klass ).invokeExplosively(
null
);
}
private FrameworkMethod getParametersMethod(TestClass testClass)
throws Exception {
List<FrameworkMethod> methods = testClass.getAnnotatedMethods( Parameterized.Parameters.class );
for ( FrameworkMethod each : methods ) {
int modifiers = each.getMethod().getModifiers();
if ( Modifier.isStatic( modifiers ) && Modifier.isPublic( modifiers ) ) {
return each;
}
}
throw new Exception(
"No public static parameters method on class "
+ testClass.getName()
);
}
}