/*******************************************************************************
* Copyright (c) 2012 itemis AG (http://www.itemis.eu) 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
*******************************************************************************/
package org.xpect.runner;
import static org.xpect.runner.DescriptionFactory.createFileDescription;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.emf.common.util.URI;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.Filterable;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.manipulation.Sortable;
import org.junit.runner.manipulation.Sorter;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.xpect.XjmMethod;
import org.xpect.XjmTestMethod;
import org.xpect.XpectFile;
import org.xpect.XpectInvocation;
import org.xpect.XpectJavaModel;
import org.xpect.setup.ThisRootTestClass;
import org.xpect.state.Creates;
import org.xpect.state.StateContainer;
import com.google.common.collect.Lists;
/**
* @author Moritz Eysholdt - Initial contribution and API
*/
public class XpectFileRunner extends Runner implements Filterable, Sortable {
private List<Runner> children;
private Description description;
private final StateContainer state;
private final XpectFile xpectFile;
public XpectFileRunner(StateContainer state, XpectFile file) {
this.xpectFile = file;
this.state = state;
}
@Creates
public XpectFileRunner create() {
return this;
}
protected List<Runner> createChildren() {
List<Runner> children = Lists.newArrayList();
if (xpectFile != null) {
XpectJavaModel xjm = xpectFile.getJavaModel();
for (XjmMethod method : xjm.getMethods().values())
if (method instanceof XjmTestMethod) {
Runner testRunner = createTestRunner((XjmTestMethod) method);
if (testRunner != null)
children.add(testRunner);
}
for (XpectInvocation inv : xpectFile.getInvocations()) {
Runner testRunner = createTestRunner(inv);
if (testRunner != null)
children.add(testRunner);
}
}
return children;
}
protected Description createDescription() {
Description result = createFileDescription(getJavaTestClass(), getURIProvider(), getUri());
for (Runner child : getChildren())
result.addChild(child.getDescription());
return result;
}
protected Runner createTestRunner(XjmTestMethod method) {
StateContainer childState = TestExecutor.createState(state, TestExecutor.createTestConfiguration(method));
return childState.get(TestRunner.class).get();
}
protected Runner createTestRunner(XpectInvocation invocation) {
StateContainer childState = TestExecutor.createState(state, TestExecutor.createXpectConfiguration(invocation));
return childState.get(XpectTestRunner.class).get();
}
public void filter(Filter filter) throws NoTestsRemainException {
List<Runner> filtered = Lists.newArrayList();
for (Runner child : getChildren())
if (filter.shouldRun(child.getDescription()))
filtered.add(child);
this.description = null;
this.children = filtered;
}
protected List<Runner> getChildren() {
if (children == null)
children = createChildren();
return children;
}
public Description getDescription() {
if (description == null)
description = createDescription();
return description;
}
public Class<?> getJavaTestClass() {
return state.get(Class.class, ThisRootTestClass.class).get();
}
public IXpectURIProvider getURIProvider() {
return state.get(IXpectURIProvider.class).get();
}
public StateContainer getState() {
return state;
}
public URI getUri() {
return xpectFile.eResource().getURI();
}
public XpectFile getXpectFile() {
return xpectFile;
}
public void run(RunNotifier notifier) {
try {
state.get(ValidatingSetup.class).get().validate();
if (getChildren().isEmpty()) {
notifier.fireTestStarted(getDescription());
notifier.fireTestFinished(getDescription());
} else
for (Runner child : getChildren())
try {
child.run(notifier);
} catch (Throwable t) {
notifier.fireTestFailure(new Failure(getDescription(), t));
}
} catch (Throwable t) {
notifier.fireTestFailure(new Failure(getDescription(), t));
} finally {
try {
state.invalidate();
} catch (Throwable t) {
notifier.fireTestFailure(new Failure(getDescription(), t));
}
}
}
public void sort(final Sorter sorter) {
this.description = null;
Collections.sort(getChildren(), new Comparator<Runner>() {
public int compare(Runner o1, Runner o2) {
return sorter.compare(o1.getDescription(), o2.getDescription());
}
});
}
}