Skip to content

Commit

Permalink
Merge #809 "Add support for execution order for Groovy hooks".
Browse files Browse the repository at this point in the history
Update History.md.
  • Loading branch information
brasmusson committed Jan 1, 2015
2 parents c0a6c0f + b2b9f94 commit 6fce323
Show file tree
Hide file tree
Showing 69 changed files with 1,162 additions and 355 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ matrix:
# Other relevant APIs:
# addon-google_apis-google-16
- ./.travis_android_update > /dev/null
- jdk: oraclejdk8
script: mvn -q deploy -P java8 -pl java8 --settings .travis-settings.xml -Dno.gem.deploy=true

branches:
only:
Expand Down
6 changes: 6 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [1.2.1-SNAPSHOT](https://github.com/cucumber/cucumber-jvm/compare/v1.2.0...master) (In Git)

* [Groovy] Add support for execution order for Groovy hooks ([#809](https://github.com/cucumber/cucumber-jvm/pull/809), [#807](https://github.com/cucumber/cucumber-jvm/issues/807) Mohammad Shamsi)
* [JUnit] JUnit 4.12 compatibility ([#794](https://github.com/cucumber/cucumber-jvm/pull/794), [#792](https://github.com/cucumber/cucumber-jvm/issues/792) Johann Vanackere)
* [Java] Java 8 lambda step definitions. ([#738](https://github.com/cucumber/cucumber-jvm/issues/738), [#767](https://github.com/cucumber/cucumber-jvm/pull/767) Romain Manni-Bucau, Aslak Hellesøy with help from Dan Bodart).

## [1.2.0](https://github.com/cucumber/cucumber-jvm/compare/v1.1.8...v1.2.0) (2014-10-30)

* [Clojure] Added clojure_cukes example to the maven build ([#790](https://github.com/cucumber/cucumber-jvm/pull/790) Jestine Paul)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import dalvik.system.DexFile;
import gherkin.formatter.Formatter;
import gherkin.formatter.Reporter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -53,11 +54,6 @@ public class CucumberExecutor {
*/
private final ClassFinder classFinder;

/**
* The {@link cucumber.runtime.io.ResourceLoader} to load resource files like .feature files.
*/
private final ResourceLoader resourceLoader;

/**
* The {@link cucumber.runtime.RuntimeOptions} to get the {@link CucumberFeature}s from.
*/
Expand All @@ -76,7 +72,7 @@ public class CucumberExecutor {
/**
* Creates a new instance for the given parameters.
*
* @param arguments the {@link cucumber.runtime.android.Arguments} which configure this execution
* @param arguments the {@link cucumber.runtime.android.Arguments} which configure this execution
* @param instrumentation the {@link android.app.Instrumentation} to report to
*/
public CucumberExecutor(final Arguments arguments, final Instrumentation instrumentation) {
Expand All @@ -87,8 +83,9 @@ public CucumberExecutor(final Arguments arguments, final Instrumentation instrum
this.instrumentation = instrumentation;
this.classLoader = context.getClassLoader();
this.classFinder = createDexClassFinder(context);
this.resourceLoader = new AndroidResourceLoader(context);
this.runtimeOptions = createRuntimeOptions(context);

ResourceLoader resourceLoader = new AndroidResourceLoader(context);
this.runtime = new Runtime(resourceLoader, classLoader, createBackends(), runtimeOptions);
this.cucumberFeatures = runtimeOptions.cucumberFeatures(resourceLoader);
}
Expand Down Expand Up @@ -149,8 +146,7 @@ private RuntimeOptions createRuntimeOptions(final Context context) {
for (final Class<?> clazz : classFinder.getDescendants(Object.class, context.getPackageName())) {
if (clazz.isAnnotationPresent(CucumberOptions.class)) {
Log.d(TAG, "Found CucumberOptions in class " + clazz.getName());
final Class<?> optionsAnnotatedClass = clazz;
final RuntimeOptionsFactory factory = new RuntimeOptionsFactory(optionsAnnotatedClass);
final RuntimeOptionsFactory factory = new RuntimeOptionsFactory(clazz);
return factory.create();
}
}
Expand Down
6 changes: 4 additions & 2 deletions clojure/src/main/clj/cucumber/runtime/clj.clj
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
(hook-fun))
(matches [hd tags]
(.evaluate te tags))
(getOrder [hd] 0)))))
(getOrder [hd] 0)
(isScenarioScoped [hd] false)))))

(defmethod add-hook-definition :after [_ tag-expression hook-fun location]
(let [te (TagExpression. tag-expression)
Expand All @@ -123,7 +124,8 @@
(hook-fun scenario-result)))
(matches [hd tags]
(.evaluate te tags))
(getOrder [hd] 0)))))
(getOrder [hd] 0)
(isScenarioScoped [hd] false)))))

(defmacro step-macros [& names]
(cons 'do
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/cucumber/runtime/Glue.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ public interface Glue {
StepDefinitionMatch stepDefinitionMatch(String featurePath, Step step, I18n i18n);

void reportStepDefinitions(StepDefinitionReporter stepDefinitionReporter);

void removeScenarioScopedGlue();
}
5 changes: 5 additions & 0 deletions core/src/main/java/cucumber/runtime/HookDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ public interface HookDefinition {
boolean matches(Collection<Tag> tags);

int getOrder();

/**
* @return true if this instance is scoped to a single scenario, or false if it can be reused across scenarios.
*/
boolean isScenarioScoped();
}
12 changes: 12 additions & 0 deletions core/src/main/java/cucumber/runtime/ParameterInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ public static List<ParameterInfo> fromMethod(Method method) {
return result;
}

public static List<ParameterInfo> fromTypes(Type[] genericParameterTypes) {
List<ParameterInfo> result = new ArrayList<ParameterInfo>();
for (int i = 0; i < genericParameterTypes.length; i++) {
String format = null;
String delimiter = DEFAULT_DELIMITER;
boolean transposed = false;
Transformer<?> transformer = null;
result.add(new ParameterInfo(genericParameterTypes[i], format, delimiter, transposed, transformer));
}
return result;
}

private static boolean isAnnotatedWith(Annotation source, Class<? extends Annotation> requiredAnnotation) {
return getAnnotationForAnnotation(source, requiredAnnotation) != null;
}
Expand Down
34 changes: 31 additions & 3 deletions core/src/main/java/cucumber/runtime/RuntimeGlue.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class RuntimeGlue implements Glue {
private final Map<String, StepDefinition> stepDefinitionsByPattern = new TreeMap<String, StepDefinition>();
private final List<HookDefinition> beforeHooks = new ArrayList<HookDefinition>();
private final List<HookDefinition> afterHooks = new ArrayList<HookDefinition>();
final Map<String, StepDefinition> stepDefinitionsByPattern = new TreeMap<String, StepDefinition>();
final List<HookDefinition> beforeHooks = new ArrayList<HookDefinition>();
final List<HookDefinition> afterHooks = new ArrayList<HookDefinition>();

private final UndefinedStepsTracker tracker;
private final LocalizedXStreams localizedXStreams;
Expand Down Expand Up @@ -91,4 +92,31 @@ public void reportStepDefinitions(StepDefinitionReporter stepDefinitionReporter)
stepDefinitionReporter.stepDefinition(stepDefinition);
}
}

@Override
public void removeScenarioScopedGlue() {
removeScenarioScopedHooks(beforeHooks);
removeScenarioScopedHooks(afterHooks);
removeScenarioScopedStepdefs();
}

private void removeScenarioScopedHooks(List<HookDefinition> beforeHooks1) {
Iterator<HookDefinition> hookIterator = beforeHooks1.iterator();
while(hookIterator.hasNext()) {
HookDefinition hook = hookIterator.next();
if(hook.isScenarioScoped()) {
hookIterator.remove();
}
}
}

private void removeScenarioScopedStepdefs() {
Iterator<Map.Entry<String, StepDefinition>> stepdefs = stepDefinitionsByPattern.entrySet().iterator();
while(stepdefs.hasNext()) {
StepDefinition stepDefinition = stepdefs.next().getValue();
if(stepDefinition.isScenarioScoped()) {
stepdefs.remove();
}
}
}
}
5 changes: 5 additions & 0 deletions core/src/main/java/cucumber/runtime/StepDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ public interface StepDefinition {
* @return the pattern associated with this instance. Used for error reporting only.
*/
String getPattern();

/**
* @return true if this instance is scoped to a single scenario, or false if it can be reused across scenarios.
*/
boolean isScenarioScoped();
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public List<String> map(DataTableRow row) {
return arguments;
}

Throwable removeFrameworkFramesAndAppendStepLocation(Throwable error, StackTraceElement stepLocation) {
private Throwable removeFrameworkFramesAndAppendStepLocation(Throwable error, StackTraceElement stepLocation) {
StackTraceElement[] stackTraceElements = error.getStackTrace();
if (stackTraceElements.length == 0 || stepLocation == null) {
return error;
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/cucumber/runtime/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,18 @@ public static Object invoke(final Object target, final Method method, long timeo
return Timeout.timeout(new Timeout.Callback<Object>() {
@Override
public Object call() throws Throwable {
boolean accessible = method.isAccessible();
try {
method.setAccessible(true);
return method.invoke(target, args);
} catch (IllegalArgumentException e) {
throw new CucumberException("Failed to invoke " + MethodFormat.FULL.format(method), e);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (IllegalAccessException e) {
throw new CucumberException("Failed to invoke " + MethodFormat.FULL.format(method), e);
} finally {
method.setAccessible(accessible);
}
}
}, timeoutMillis);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,43 @@

import cucumber.runtime.CucumberException;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Iterator;

public class ClasspathIterable implements Iterable<Resource> {
private final ClassLoader cl;
private final ResourceIteratorFactory resourceIteratorFactory;
public class ClasspathResourceIterable implements Iterable<Resource> {
private final ResourceIteratorFactory resourceIteratorFactory =
new DelegatingResourceIteratorFactory(new ZipThenFileResourceIteratorFactory());

private final ClassLoader classLoader;
private final String path;
private final String suffix;

public ClasspathIterable(ClassLoader cl, String path, String suffix) {
this.cl = cl;
this.resourceIteratorFactory = new DelegatingResourceIteratorFactory();
public ClasspathResourceIterable(ClassLoader classLoader, String path, String suffix) {
this.classLoader = classLoader;
this.path = path;
this.suffix = suffix;
}

@Override
public Iterator<Resource> iterator() {
try {
FlatteningIterator iterator = new FlatteningIterator();
Enumeration<URL> resources = cl.getResources(path);
FlatteningIterator<Resource> iterator = new FlatteningIterator<Resource>();
Enumeration<URL> resources = classLoader.getResources(path);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
iterator.push(this.resourceIteratorFactory.createIterator(url, path, suffix));
Iterator<Resource> resourceIterator = resourceIteratorFactory.createIterator(url, path, suffix);
iterator.push(resourceIterator);
}
return iterator;
} catch (IOException e) {
throw new CucumberException(e);
}
}

static String filePath(URL jarUrl) throws UnsupportedEncodingException, MalformedURLException {
String path = new File(new URL(jarUrl.getFile()).getFile()).getAbsolutePath();
String pathToJar = path.substring(0, path.lastIndexOf("!"));
return URLDecoder.decode(pathToJar, "UTF-8");
}

static boolean hasSuffix(String suffix, String name) {
return suffix == null || name.endsWith(suffix);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ public ClasspathResourceLoader(ClassLoader classLoader) {

@Override
public Iterable<Resource> resources(String path, String suffix) {
return new ClasspathIterable(classLoader, path, suffix);
return new ClasspathResourceIterable(classLoader, path, suffix);
}
}
Loading

0 comments on commit 6fce323

Please sign in to comment.