/*******************************************************************************
* Copyright (c) 2012 BMW Car IT 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.jnario.jnario.test.util;
import static org.junit.Assert.assertThat;
import static org.junit.experimental.results.ResultMatchers.isSuccessful;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.xtext.junit4.GlobalRegistries;
import org.eclipse.xtext.junit4.GlobalRegistries.GlobalStateMemento;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.eclipse.xtext.util.Files;
import org.junit.experimental.results.PrintableResult;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
public abstract class BehaviorTestRunner extends Runner {
private Map<Description, URI> descriptions;
protected final Class<?> klass;
protected ResourceSet resourceSet = new XtextResourceSet();
private Description rootDescription;
private GlobalStateMemento state;
@Inject
private BehaviorExecutor behaviorExecutor;
public BehaviorTestRunner(Class<?> klass) {
super();
this.klass = klass;
FeatureJavaCompiler.getInstance().addClassPathOfClass(klass);
}
protected void initializeRegistries() {
state = GlobalRegistries.makeCopyOfGlobalState();
injectMembers();
}
protected abstract void injectMembers();
@Override
public Description getDescription() {
if (rootDescription == null) {
rootDescription = Description.createSuiteDescription(klass
.getName());
rootDescription.getChildren().addAll(testDescriptions());
}
return rootDescription;
}
private Collection<? extends Description> testDescriptions() {
if (descriptions == null) {
descriptions = Maps.newHashMap();
IUriProvider uris = ClassPathUriProviderBuilder.startingFrom(klass).select(
new Predicate<URI>() {
public boolean apply(URI uri) {
String fileExtension = uri.fileExtension();
return fileExtension != null && fileExtension.toLowerCase().equals(getModelExtension());
}
});
for (URI input : uris.allUris()) {
descriptions
.put(Description.createTestDescription(klass,
stripFileExtension(input.lastSegment())), input);
}
}
return descriptions.keySet();
}
private String stripFileExtension(String name) {
return name.substring(0, name.length() - getModelExtension().length() - 1);
}
@Override
public void run(RunNotifier notifier) {
initializeRegistries();
try {
for (Entry<Description, URI> entry : allDescriptions()) {
Description description = entry.getKey();
notifier.fireTestStarted(description);
try {
run(entry.getValue());
} catch (Throwable e) {
notifier.fireTestFailure(new Failure(description, e));
}
resourceSet.getResources().clear();
notifier.fireTestFinished(description);
}
} finally {
state.restoreGlobalState();
}
}
public Set<Entry<Description, URI>> allDescriptions() {
getDescription();
return descriptions.entrySet();
}
private void run(URI uri) {
EObject object = load(uri);
if(object != null){
Result result = behaviorExecutor.run(load(uri));
PrintableResult printableResult = new PrintableResult(result.getFailures());
assertThat(printableResult, isSuccessful());
}
}
protected EObject load(URI input) {
Resource resource = resourceSet.getResource(input, true);
if(!resource.getContents().isEmpty()){
return resource.getContents().get(0);
}
return null;
}
protected String toString(URI outputPath) throws IOException {
return Files.readStreamIntoString(URIConverter.INSTANCE
.createInputStream(outputPath));
}
protected abstract String getModelExtension();
}