blob: 10cabe6538022cfe63f393cd407dc8a3f4e0d812 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 EclipseSource Muenchen GmbH.
*
* 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:
******************************************************************************/
package org.eclipse.emf.emfstore.fuzzy;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.emfstore.fuzzy.Annotations.Data;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
/**
* A {@link org.junit.runner.Runner} for each {@link org.junit.runners.model.TestClass}.
* Used in the {@link FuzzyRunner}.
*
* @author Julian Sommerfeldt
*
*/
public class FuzzyTestClassRunner extends BlockJUnit4ClassRunner {
/**
* Which run is it?
*/
private int counter;
/**
* The {@link FuzzyDataProvider}, which "contains" the data for the test.
*/
private FuzzyDataProvider<?> dataProvider;
/**
* The {@link FrameworkField} of the {@link TestClass} where to put in the data.
*/
private FrameworkField dataField;
/**
* The {@link FrameworkField} for the {@link Util}.
*/
private FrameworkField utilField;
private Util util;
private FrameworkField optionsField;
/**
* Constructor.
*
* @param type The testclass
* @param dataProvider The {@link FuzzyDataProvider} providing the data to put into the dataField
* @param dataField The datafield in the testclass
* @param utilField the utilfield in the testclass
* @param optionsField the options field in the testclass
* @param util The {@link Util} class
* @param counter The counter of the run
* @throws InitializationError If there was a problem during the initialization of the test
*/
FuzzyTestClassRunner(Class<?> type, FuzzyDataProvider<?> dataProvider, FrameworkField dataField,
FrameworkField utilField, FrameworkField optionsField, Util util, int counter) throws InitializationError {
super(type);
this.counter = counter;
this.dataField = dataField;
this.utilField = utilField;
this.optionsField = optionsField;
this.util = util;
this.dataProvider = dataProvider;
}
@SuppressWarnings("unchecked")
@Override
public Object createTest() {
try {
// create a new instance of the testclass
Object testInstance = getTestClass().getOnlyConstructor().newInstance();
// set the options to dataprovider
if (optionsField != null) {
Object options = getValueFromField(optionsField.getField(), testInstance);
if (options == null) {
throw new IllegalStateException(
"The options field has to be not null! Fill it or remove annotation.");
}
try {
dataProvider.setOptions((Map<String, Object>) options);
} catch (ClassCastException e) {
throw new ClassCastException("The options field is not of type: Map<String, Object>!");
}
}
// get the new data from dataprovider
Object data = dataProvider.get(counter);
// set the data to the datafield
setValueToField(dataField.getField(), testInstance, data,
"The field annotated with " + Data.class.getSimpleName()
+ " does not fit to the type of the dataprovider (" + dataProvider.getClass() + ").");
// set the util to the util field
if (util != null && utilField != null) {
setValueToField(utilField.getField(), testInstance, util,
"The field annotated " + Util.class.getSimpleName() + " does not fit to the Util type!");
}
return testInstance;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private Object getValueFromField(Field field, Object instance) throws IllegalAccessException {
try{
field.setAccessible(true);
Object o = field.get(instance);
return o;
} finally {
field.setAccessible(false);
}
}
private void setValueToField(Field field, Object instance, Object value, String errorMsg) throws IllegalAccessException
{
try {
field.setAccessible(true);
field.set(instance, value);
} finally {
field.setAccessible(false);
}
}
@Override
protected List<FrameworkMethod> getChildren() {
List<Test> testsToRun = dataProvider.getTestsToRun();
List<FrameworkMethod> allChildren = super.getChildren();
// check if it should filter tests
if (testsToRun != null) {
List<FrameworkMethod> filteredChildren = new ArrayList<FrameworkMethod>();
for (Test test : testsToRun) {
String name = test.getName();
int seedCount = test.getSeedCount();
for (FrameworkMethod child : allChildren) {
if (seedCount == counter && name.equals(child.getName())) {
filteredChildren.add(child);
}
}
}
return filteredChildren;
}
// if not return all children
return allChildren;
}
private String testName(String name) {
return String.format("%s%s[%s]", name, FuzzyRunner.NAME_SEPARATOR, counter);
}
@Override
protected String testName(final FrameworkMethod method) {
return testName(method.getName());
}
@Override
protected String getName() {
return String.format("%s%s[%s]", getTestClass().getName(), FuzzyRunner.NAME_SEPARATOR, counter);
}
@Override
protected Statement classBlock(RunNotifier notifier) {
return childrenInvoker(notifier);
}
}