blob: c76e0f0e91573a71117581f5d20c270bf21c0c77 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2015 Frank Becker 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:
* Frank Becker - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.commons.sdk.util;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.osgi.util.NLS;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.internal.runners.model.ReflectiveCallable;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
public class Junit4TestFixtureRunner extends Suite {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public static @interface RunOnlyWhenProperty {
String property() default "";
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public static @interface FixtureDefinition {
Class<?> fixtureClass();
String fixtureType();
}
private class TestClassRunnerForFixture extends BlockJUnit4ClassRunner {
private final int fFixtureSetNumber;
private final List<AbstractTestFixture> fFixtureList;
TestClassRunnerForFixture(Class<?> type, List<AbstractTestFixture> fixtureList, int i)
throws InitializationError {
super(type);
fFixtureList = fixtureList;
fFixtureSetNumber = i;
}
@Override
public Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance(fFixtureList.get(fFixtureSetNumber));
}
@Override
protected String getName() {
return String.format("[%s %s]", fFixtureSetNumber, fFixtureList.get(fFixtureSetNumber).getSimpleInfo());
}
@Override
protected String testName(final FrameworkMethod method) {
if (Boolean.parseBoolean(System.getProperty("org.eclipse.mylyn.tests.all"))) {
return String.format("%s[%s %s]", method.getName(), fFixtureSetNumber,
fFixtureList.get(fFixtureSetNumber).getSimpleInfo());
} else {
return super.testName(method);
}
}
@Override
protected void validateConstructor(List<Throwable> errors) {
validateOnlyOneConstructor(errors);
}
@Override
protected Statement classBlock(RunNotifier notifier) {
return childrenInvoker(notifier);
}
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
Description description = describeChild(method);
if (isIgnored(method)) {
notifier.fireTestIgnored(description);
} else {
Object test = null;
try {
test = new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return createTest();
}
}.run();
} catch (Throwable e) {
StatusHandler.log(new Status(IStatus.ERROR, "org.eclipse.mylyn.commons.sdk.util", //$NON-NLS-1$
NLS.bind("TestClassRunnerForFixture: Testclass {0} has no public constructor", //$NON-NLS-1$
getTestClass().getName()),
e));
return;
}
boolean skipped = false;
if (test != null) {
List<TestRule> testRules = getTestRules(test);
for (TestRule testRule : testRules) {
if (testRule instanceof ConditionalIgnoreRule) {
Statement statement = testRule.apply(null, description);
if (statement instanceof IgnoreStatement) {
skipped = true;
break;
}
}
}
if (skipped) {
notifier.fireTestIgnored(description);
} else {
runTest(methodBlock(method), description, notifier);
}
}
}
}
protected final void runTest(Statement statement, Description description, RunNotifier notifier) {
EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
eachNotifier.fireTestStarted();
try {
statement.evaluate();
} catch (AssumptionViolatedException e) {
eachNotifier.addFailedAssumption(e);
} catch (IgnoreRuleRuntimeException e) {
eachNotifier.fireTestIgnored();
} catch (Throwable e) {
eachNotifier.addFailure(e);
} finally {
eachNotifier.fireTestFinished();
}
}
}
private final ArrayList<Runner> runners = new ArrayList<Runner>();
/**
* Only called reflectively. Do not use programmatically.
*/
public Junit4TestFixtureRunner(Class<?> klass) throws Throwable {
super(klass, Collections.<Runner> emptyList());
if (CommonTestUtil.fixProxyConfiguration()) {
CommonTestUtil.dumpSystemInfo(System.err);
}
String restrictProperty = null;
String restrictValue = null;
Class<?> fixtureClass = null;
String fixtureType = null;
for (Annotation annotation : getTestClass().getAnnotations()) {
if (annotation.annotationType() == RunOnlyWhenProperty.class) {
RunOnlyWhenProperty onlyWhenProperty = (RunOnlyWhenProperty) annotation;
restrictProperty = onlyWhenProperty.property();
restrictValue = onlyWhenProperty.value();
}
if (annotation.annotationType() == FixtureDefinition.class) {
FixtureDefinition fixtueDef = (FixtureDefinition) annotation;
fixtureClass = fixtueDef.fixtureClass();
fixtureType = fixtueDef.fixtureType();
}
}
if (fixtureType != null) {
TestConfiguration defFixture = TestConfiguration.getDefault();
List<AbstractTestFixture> parametersList = (List<AbstractTestFixture>) defFixture.discover(fixtureClass,
fixtureType);
ArrayList<AbstractTestFixture> sortedParametersList = new ArrayList<AbstractTestFixture>(parametersList);
sortedParametersList.sort(new Comparator<AbstractTestFixture>() {
@Override
public int compare(AbstractTestFixture o1, AbstractTestFixture o2) {
return o1.getInfo().compareTo(o2.getInfo());
}
});
List<AbstractTestFixture> fixturesToExecute = new ArrayList<AbstractTestFixture>();
if (restrictProperty != null) {
for (AbstractTestFixture abstractFixture : sortedParametersList) {
String tempProperty = abstractFixture.getProperty(restrictProperty);
if (tempProperty != null && tempProperty.equals(restrictValue)) {
fixturesToExecute.add(abstractFixture);
}
}
if (fixturesToExecute.size() > 0) {
for (int i = 0; i < fixturesToExecute.size(); i++) {
runners.add(new TestClassRunnerForFixture(getTestClass().getJavaClass(), fixturesToExecute, i));
}
}
} else if (sortedParametersList.size() > 0) {
for (int i = 0; i < sortedParametersList.size(); i++) {
runners.add(new TestClassRunnerForFixture(getTestClass().getJavaClass(), sortedParametersList, i));
}
}
} else {
throw new InitializationError("Missing Annotation FixtureDefinition for Junit4TestFixtureRunner");
}
}
@Override
protected List<Runner> getChildren() {
return runners;
}
}