Skip to content

Commit

Permalink
Replace generic supplier interface with specific purpose interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
mpkorstanje committed Jun 5, 2018
1 parent a92d0f1 commit 199f9aa
Show file tree
Hide file tree
Showing 30 changed files with 772 additions and 736 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
import cucumber.runner.EventBus;
import cucumber.runner.Runner;
import cucumber.runner.TimeService;
import cucumber.runtime.FeatureSupplier;
import cucumber.runtime.BackendSupplier;
import cucumber.runtime.FeaturePathFeatureSupplier;
import cucumber.runtime.filter.Filters;
import cucumber.runtime.formatter.Plugins;
import cucumber.runtime.filter.RerunFilters;
import cucumber.runtime.formatter.PluginFactory;
import cucumber.runtime.model.FeatureLoader;
import cucumber.runtime.RunnerSupplier;
import cucumber.runtime.ThreadLocalRunnerSupplier;
import cucumber.runtime.RuntimeGlueSupplier;
import cucumber.runtime.Supplier;
import io.cucumber.stepexpression.TypeRegistry;
import cucumber.api.event.TestRunFinished;
import cucumber.api.java.ObjectFactory;
Expand Down Expand Up @@ -104,9 +104,9 @@ public CucumberExecutor(final Arguments arguments, final Instrumentation instrum
this.bus = new EventBus(TimeService.SYSTEM);
this.plugins = new Plugins(classLoader, new PluginFactory(), bus, runtimeOptions);
RuntimeGlueSupplier glueSupplier = new RuntimeGlueSupplier();
this.runner = new RunnerSupplier(runtimeOptions, bus, createBackends(), glueSupplier).get();
this.runner = new ThreadLocalRunnerSupplier(runtimeOptions, bus, createBackends(), glueSupplier).get();
FeatureLoader featureLoader = new FeatureLoader(resourceLoader);
FeatureSupplier featureSupplier = new FeatureSupplier(featureLoader, runtimeOptions);
FeaturePathFeatureSupplier featureSupplier = new FeaturePathFeatureSupplier(featureLoader, runtimeOptions);
RerunFilters rerunFilters = new RerunFilters(runtimeOptions, featureLoader);
Filters filters = new Filters(runtimeOptions, rerunFilters);
UndefinedStepsTracker undefinedStepsTracker = new UndefinedStepsTracker();
Expand Down Expand Up @@ -181,8 +181,8 @@ private RuntimeOptions createRuntimeOptions(final Context context) {
throw new CucumberException("No CucumberOptions annotation");
}

private Supplier<Collection<? extends Backend>> createBackends() {
return new Supplier<Collection<? extends Backend>>() {
private BackendSupplier createBackends() {
return new BackendSupplier() {
@Override
public Collection<? extends Backend> get() {
final Reflections reflections = new Reflections(classFinder);
Expand Down
15 changes: 9 additions & 6 deletions core/src/main/java/cucumber/api/cli/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

import cucumber.runner.EventBus;
import cucumber.runner.TimeService;
import cucumber.runtime.BackendSupplier;
import cucumber.runtime.BackendModuleBackendSupplier;
import cucumber.runtime.ClassFinder;
import cucumber.runtime.FeaturePathFeatureSupplier;
import cucumber.runtime.FeatureSupplier;
import cucumber.runtime.GlueSupplier;
import cucumber.runtime.RunnerSupplier;
import cucumber.runtime.filter.Filters;
import cucumber.runtime.formatter.Plugins;
import cucumber.runtime.filter.RerunFilters;
import cucumber.runtime.RunnerSupplier;
import cucumber.runtime.ThreadLocalRunnerSupplier;
import cucumber.runtime.RuntimeGlueSupplier;
import cucumber.runtime.Runtime;
import cucumber.runtime.RuntimeOptions;
Expand Down Expand Up @@ -39,13 +42,13 @@ public static byte run(String[] argv, ClassLoader classLoader) {

ResourceLoader resourceLoader = new MultiLoader(classLoader);
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
BackendSupplier backendSupplier = new BackendSupplier(resourceLoader, classFinder, runtimeOptions);
BackendModuleBackendSupplier backendSupplier = new BackendModuleBackendSupplier(resourceLoader, classFinder, runtimeOptions);
EventBus bus = new EventBus(TimeService.SYSTEM);
Plugins plugins = new Plugins(classLoader, new PluginFactory(), bus, runtimeOptions);
RuntimeGlueSupplier glueSupplier = new RuntimeGlueSupplier();
RunnerSupplier runnerSupplier = new RunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier);
GlueSupplier glueSupplier = new RuntimeGlueSupplier();
RunnerSupplier runnerSupplier = new ThreadLocalRunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier);
FeatureLoader featureLoader = new FeatureLoader(resourceLoader);
FeatureSupplier featureSupplier = new FeatureSupplier(featureLoader, runtimeOptions);
FeatureSupplier featureSupplier = new FeaturePathFeatureSupplier(featureLoader, runtimeOptions);
RerunFilters rerunFilters = new RerunFilters(runtimeOptions, featureLoader);
Filters filters = new Filters(runtimeOptions, rerunFilters);
Runtime runtime = new Runtime(plugins, runtimeOptions, bus, filters, runnerSupplier, featureSupplier);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cucumber.runtime;

import cucumber.api.TypeRegistryConfigurer;
import cucumber.runtime.io.MultiLoader;
import cucumber.runtime.io.ResourceLoader;
import io.cucumber.stepexpression.TypeRegistry;

import java.util.Collection;
import java.util.List;

import static java.util.Collections.singletonList;


/**
* Supplies instances of {@link Backend} found by scanning {@code cucumber.runtime} for implementations.
*/
public final class BackendModuleBackendSupplier implements BackendSupplier {

private final ResourceLoader resourceLoader;
private final ClassFinder classFinder;
private final RuntimeOptions runtimeOptions;
private final List<String> packages;

public BackendModuleBackendSupplier(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions) {
this(resourceLoader, classFinder, runtimeOptions, singletonList("cucumber.runtime"));
}

BackendModuleBackendSupplier(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions, List<String> packages) {
this.resourceLoader = resourceLoader;
this.classFinder = classFinder;
this.runtimeOptions = runtimeOptions;
this.packages = packages;
}

@Override
public Collection<? extends Backend> get() {
Collection<? extends Backend> backends = loadBackends();
if (backends.isEmpty()) {
throw new CucumberException("No backends were found. Please make sure you have a backend module on your CLASSPATH.");
}
return backends;
}

private Collection<? extends Backend> loadBackends() {
Reflections reflections = new Reflections(classFinder);
TypeRegistryConfigurer typeRegistryConfigurer = reflections.instantiateExactlyOneSubclass(TypeRegistryConfigurer.class, MultiLoader.packageName(runtimeOptions.getGlue()), new Class[0], new Object[0], new DefaultTypeRegistryConfiguration());
TypeRegistry typeRegistry = new TypeRegistry(typeRegistryConfigurer.locale());
typeRegistryConfigurer.configureTypeRegistry(typeRegistry);

return reflections.instantiateSubclasses(Backend.class, packages, new Class[]{ResourceLoader.class, TypeRegistry.class}, new Object[]{resourceLoader, typeRegistry});
}

}
37 changes: 2 additions & 35 deletions core/src/main/java/cucumber/runtime/BackendSupplier.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,7 @@
package cucumber.runtime;

import cucumber.api.TypeRegistryConfigurer;
import cucumber.runtime.io.MultiLoader;
import cucumber.runtime.io.ResourceLoader;
import io.cucumber.stepexpression.TypeRegistry;

import java.util.Collection;

import static java.util.Collections.singletonList;

public class BackendSupplier implements Supplier<Collection<? extends Backend>> {

private final ResourceLoader resourceLoader;
private final ClassFinder classFinder;
private final RuntimeOptions runtimeOptions;

public BackendSupplier(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions) {
this.resourceLoader = resourceLoader;
this.classFinder = classFinder;
this.runtimeOptions = runtimeOptions;
}


@Override
public Collection<? extends Backend> get() {
Collection<? extends Backend> backends = loadBackends(resourceLoader, classFinder, runtimeOptions);

return backends;
}

private static Collection<? extends Backend> loadBackends(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions) {
Reflections reflections = new Reflections(classFinder);
TypeRegistryConfigurer typeRegistryConfigurer = reflections.instantiateExactlyOneSubclass(TypeRegistryConfigurer.class, MultiLoader.packageName(runtimeOptions.getGlue()), new Class[0], new Object[0], new DefaultTypeRegistryConfiguration());
TypeRegistry typeRegistry = new TypeRegistry(typeRegistryConfigurer.locale());
typeRegistryConfigurer.configureTypeRegistry(typeRegistry);
return reflections.instantiateSubclasses(Backend.class, singletonList("cucumber.runtime"), new Class[]{ResourceLoader.class, TypeRegistry.class}, new Object[]{resourceLoader, typeRegistry});
}

public interface BackendSupplier {
Collection<? extends Backend> get();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cucumber.runtime;

import cucumber.runtime.model.CucumberFeature;
import cucumber.runtime.model.FeatureLoader;

import java.util.List;

/**
* Supplies a list of features found on the the feature path provided to RuntimeOptions.
*/
public class FeaturePathFeatureSupplier implements FeatureSupplier {
private final FeatureLoader featureLoader;
private final RuntimeOptions runtimeOptions;

public FeaturePathFeatureSupplier(FeatureLoader featureLoader, RuntimeOptions runtimeOptions) {
this.featureLoader = featureLoader;
this.runtimeOptions = runtimeOptions;
}

@Override
public List<CucumberFeature> get() {
return featureLoader.load(runtimeOptions.getFeaturePaths(), System.out);
}
}
16 changes: 2 additions & 14 deletions core/src/main/java/cucumber/runtime/FeatureSupplier.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
package cucumber.runtime;

import cucumber.runtime.model.CucumberFeature;
import cucumber.runtime.model.FeatureLoader;

import java.util.List;

public class FeatureSupplier implements Supplier<List<CucumberFeature>> {
private final FeatureLoader featureLoader;
private final RuntimeOptions runtimeOptions;

public FeatureSupplier(FeatureLoader featureLoader, RuntimeOptions runtimeOptions) {
this.featureLoader = featureLoader;
this.runtimeOptions = runtimeOptions;
}

@Override
public List<CucumberFeature> get() {
return featureLoader.load(runtimeOptions.getFeaturePaths(), System.out);
}
public interface FeatureSupplier {
List<CucumberFeature> get();
}
5 changes: 5 additions & 0 deletions core/src/main/java/cucumber/runtime/GlueSupplier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package cucumber.runtime;

public interface GlueSupplier {
Glue get();
}
44 changes: 2 additions & 42 deletions core/src/main/java/cucumber/runtime/RunnerSupplier.java
Original file line number Diff line number Diff line change
@@ -1,47 +1,7 @@
package cucumber.runtime;

import cucumber.runner.EventBus;
import cucumber.runner.Runner;

import java.util.Collection;

public class RunnerSupplier implements Supplier<Runner> {

private final Supplier<Collection<? extends Backend>> backendSupplier;
private final RuntimeOptions runtimeOptions;
private final Supplier<Glue> glueSupplier;
private final EventBus eventBus;

private final ThreadLocal<Runner> runners = new ThreadLocal<Runner>();

public RunnerSupplier(
RuntimeOptions runtimeOptions,
EventBus eventBus,
Supplier<Collection<? extends Backend>> backendSupplier,
Supplier<Glue> glueSupplier
) {
this.backendSupplier = backendSupplier;
this.runtimeOptions = runtimeOptions;
this.glueSupplier = glueSupplier;
this.eventBus = eventBus;
}

@Override
public Runner get() {
Runner runner = runners.get();
if (runner == null) {
runner = createRunner();
runners.set(runner);
}
return runner;
}

private Runner createRunner() {
Collection<? extends Backend> backends = backendSupplier.get();
if (backends.isEmpty()) {
throw new CucumberException("No backends were found. Please make sure you have a backend module on your CLASSPATH.");
}
return new Runner(glueSupplier.get(), eventBus.createBatchedEventBus(), backends, runtimeOptions);
}

public interface RunnerSupplier {
Runner get();
}
6 changes: 3 additions & 3 deletions core/src/main/java/cucumber/runtime/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ public class Runtime {
private final Filters filters;
private final EventBus bus;
private final FeatureCompiler compiler = new FeatureCompiler();
private final Supplier<List<CucumberFeature>> featureSupplier;
private final FeatureSupplier featureSupplier;
private final Plugins plugins;

public Runtime(Plugins plugins,
RuntimeOptions runtimeOptions,
EventBus bus,
Filters filters,
Supplier<Runner> runnerSupplier,
Supplier<List<CucumberFeature>> featureSupplier
RunnerSupplier runnerSupplier,
FeatureSupplier featureSupplier
) {

this.plugins = plugins;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package cucumber.runtime;

public final class RuntimeGlueSupplier implements Supplier<Glue> {
public final class RuntimeGlueSupplier implements GlueSupplier {

@Override
public Glue get() {
Expand Down
44 changes: 44 additions & 0 deletions core/src/main/java/cucumber/runtime/ThreadLocalRunnerSupplier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cucumber.runtime;

import cucumber.runner.EventBus;
import cucumber.runner.Runner;

/**
* Returns a distinct runner for each calling thread.
*/
public class ThreadLocalRunnerSupplier implements RunnerSupplier {

private final BackendSupplier backendSupplier;
private final RuntimeOptions runtimeOptions;
private final GlueSupplier glueSupplier;
private final EventBus eventBus;

private final ThreadLocal<Runner> runners = new ThreadLocal<Runner>();

public ThreadLocalRunnerSupplier(
RuntimeOptions runtimeOptions,
EventBus eventBus,
BackendSupplier backendSupplier,
GlueSupplier glueSupplier
) {
this.backendSupplier = backendSupplier;
this.runtimeOptions = runtimeOptions;
this.glueSupplier = glueSupplier;
this.eventBus = eventBus;
}

@Override
public Runner get() {
Runner runner = runners.get();
if (runner == null) {
runner = createRunner();
runners.set(runner);
}
return runner;
}

private Runner createRunner() {
return new Runner(glueSupplier.get(), eventBus.createBatchedEventBus(), backendSupplier.get(), runtimeOptions);
}

}
10 changes: 6 additions & 4 deletions core/src/test/java/cucumber/runner/RunnerTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cucumber.runner;

import cucumber.runtime.RunnerSupplier;
import cucumber.runtime.BackendSupplier;
import cucumber.runtime.ThreadLocalRunnerSupplier;
import cucumber.runtime.RuntimeGlueSupplier;
import cucumber.runtime.Supplier;
import io.cucumber.stepexpression.Argument;
Expand All @@ -26,6 +27,7 @@
import java.util.List;

import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.mockito.ArgumentMatchers.anyListOf;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
Expand Down Expand Up @@ -173,15 +175,15 @@ private Runner createRunner(Backend backend) {

private Runner createRunner(final Backend backend, String options) {
RuntimeOptions runtimeOptions = new RuntimeOptions(options);
Supplier<Collection<? extends Backend>> backendSupplier = new Supplier<Collection<? extends Backend>>() {
BackendSupplier backendSupplier = new BackendSupplier() {
@Override
public Collection<? extends Backend> get() {
return asList(backend);
return singletonList(backend);
}
};
EventBus bus = new EventBus(TimeService.SYSTEM);
RuntimeGlueSupplier glueSupplier = new RuntimeGlueSupplier();
return new RunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier).get();
return new ThreadLocalRunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier).get();
}

private HookDefinition addBeforeHook() {
Expand Down
Loading

0 comments on commit 199f9aa

Please sign in to comment.