Skip to content

Commit 199f9aa

Browse files
committed
Replace generic supplier interface with specific purpose interfaces
1 parent a92d0f1 commit 199f9aa

File tree

30 files changed

+772
-736
lines changed

30 files changed

+772
-736
lines changed

android/src/main/java/cucumber/runtime/android/CucumberExecutor.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
import cucumber.runner.EventBus;
1111
import cucumber.runner.Runner;
1212
import cucumber.runner.TimeService;
13-
import cucumber.runtime.FeatureSupplier;
13+
import cucumber.runtime.BackendSupplier;
14+
import cucumber.runtime.FeaturePathFeatureSupplier;
1415
import cucumber.runtime.filter.Filters;
1516
import cucumber.runtime.formatter.Plugins;
1617
import cucumber.runtime.filter.RerunFilters;
1718
import cucumber.runtime.formatter.PluginFactory;
1819
import cucumber.runtime.model.FeatureLoader;
19-
import cucumber.runtime.RunnerSupplier;
20+
import cucumber.runtime.ThreadLocalRunnerSupplier;
2021
import cucumber.runtime.RuntimeGlueSupplier;
21-
import cucumber.runtime.Supplier;
2222
import io.cucumber.stepexpression.TypeRegistry;
2323
import cucumber.api.event.TestRunFinished;
2424
import cucumber.api.java.ObjectFactory;
@@ -104,9 +104,9 @@ public CucumberExecutor(final Arguments arguments, final Instrumentation instrum
104104
this.bus = new EventBus(TimeService.SYSTEM);
105105
this.plugins = new Plugins(classLoader, new PluginFactory(), bus, runtimeOptions);
106106
RuntimeGlueSupplier glueSupplier = new RuntimeGlueSupplier();
107-
this.runner = new RunnerSupplier(runtimeOptions, bus, createBackends(), glueSupplier).get();
107+
this.runner = new ThreadLocalRunnerSupplier(runtimeOptions, bus, createBackends(), glueSupplier).get();
108108
FeatureLoader featureLoader = new FeatureLoader(resourceLoader);
109-
FeatureSupplier featureSupplier = new FeatureSupplier(featureLoader, runtimeOptions);
109+
FeaturePathFeatureSupplier featureSupplier = new FeaturePathFeatureSupplier(featureLoader, runtimeOptions);
110110
RerunFilters rerunFilters = new RerunFilters(runtimeOptions, featureLoader);
111111
Filters filters = new Filters(runtimeOptions, rerunFilters);
112112
UndefinedStepsTracker undefinedStepsTracker = new UndefinedStepsTracker();
@@ -181,8 +181,8 @@ private RuntimeOptions createRuntimeOptions(final Context context) {
181181
throw new CucumberException("No CucumberOptions annotation");
182182
}
183183

184-
private Supplier<Collection<? extends Backend>> createBackends() {
185-
return new Supplier<Collection<? extends Backend>>() {
184+
private BackendSupplier createBackends() {
185+
return new BackendSupplier() {
186186
@Override
187187
public Collection<? extends Backend> get() {
188188
final Reflections reflections = new Reflections(classFinder);

core/src/main/java/cucumber/api/cli/Main.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
import cucumber.runner.EventBus;
44
import cucumber.runner.TimeService;
5-
import cucumber.runtime.BackendSupplier;
5+
import cucumber.runtime.BackendModuleBackendSupplier;
66
import cucumber.runtime.ClassFinder;
7+
import cucumber.runtime.FeaturePathFeatureSupplier;
78
import cucumber.runtime.FeatureSupplier;
9+
import cucumber.runtime.GlueSupplier;
10+
import cucumber.runtime.RunnerSupplier;
811
import cucumber.runtime.filter.Filters;
912
import cucumber.runtime.formatter.Plugins;
1013
import cucumber.runtime.filter.RerunFilters;
11-
import cucumber.runtime.RunnerSupplier;
14+
import cucumber.runtime.ThreadLocalRunnerSupplier;
1215
import cucumber.runtime.RuntimeGlueSupplier;
1316
import cucumber.runtime.Runtime;
1417
import cucumber.runtime.RuntimeOptions;
@@ -39,13 +42,13 @@ public static byte run(String[] argv, ClassLoader classLoader) {
3942

4043
ResourceLoader resourceLoader = new MultiLoader(classLoader);
4144
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
42-
BackendSupplier backendSupplier = new BackendSupplier(resourceLoader, classFinder, runtimeOptions);
45+
BackendModuleBackendSupplier backendSupplier = new BackendModuleBackendSupplier(resourceLoader, classFinder, runtimeOptions);
4346
EventBus bus = new EventBus(TimeService.SYSTEM);
4447
Plugins plugins = new Plugins(classLoader, new PluginFactory(), bus, runtimeOptions);
45-
RuntimeGlueSupplier glueSupplier = new RuntimeGlueSupplier();
46-
RunnerSupplier runnerSupplier = new RunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier);
48+
GlueSupplier glueSupplier = new RuntimeGlueSupplier();
49+
RunnerSupplier runnerSupplier = new ThreadLocalRunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier);
4750
FeatureLoader featureLoader = new FeatureLoader(resourceLoader);
48-
FeatureSupplier featureSupplier = new FeatureSupplier(featureLoader, runtimeOptions);
51+
FeatureSupplier featureSupplier = new FeaturePathFeatureSupplier(featureLoader, runtimeOptions);
4952
RerunFilters rerunFilters = new RerunFilters(runtimeOptions, featureLoader);
5053
Filters filters = new Filters(runtimeOptions, rerunFilters);
5154
Runtime runtime = new Runtime(plugins, runtimeOptions, bus, filters, runnerSupplier, featureSupplier);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package cucumber.runtime;
2+
3+
import cucumber.api.TypeRegistryConfigurer;
4+
import cucumber.runtime.io.MultiLoader;
5+
import cucumber.runtime.io.ResourceLoader;
6+
import io.cucumber.stepexpression.TypeRegistry;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
import static java.util.Collections.singletonList;
12+
13+
14+
/**
15+
* Supplies instances of {@link Backend} found by scanning {@code cucumber.runtime} for implementations.
16+
*/
17+
public final class BackendModuleBackendSupplier implements BackendSupplier {
18+
19+
private final ResourceLoader resourceLoader;
20+
private final ClassFinder classFinder;
21+
private final RuntimeOptions runtimeOptions;
22+
private final List<String> packages;
23+
24+
public BackendModuleBackendSupplier(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions) {
25+
this(resourceLoader, classFinder, runtimeOptions, singletonList("cucumber.runtime"));
26+
}
27+
28+
BackendModuleBackendSupplier(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions, List<String> packages) {
29+
this.resourceLoader = resourceLoader;
30+
this.classFinder = classFinder;
31+
this.runtimeOptions = runtimeOptions;
32+
this.packages = packages;
33+
}
34+
35+
@Override
36+
public Collection<? extends Backend> get() {
37+
Collection<? extends Backend> backends = loadBackends();
38+
if (backends.isEmpty()) {
39+
throw new CucumberException("No backends were found. Please make sure you have a backend module on your CLASSPATH.");
40+
}
41+
return backends;
42+
}
43+
44+
private Collection<? extends Backend> loadBackends() {
45+
Reflections reflections = new Reflections(classFinder);
46+
TypeRegistryConfigurer typeRegistryConfigurer = reflections.instantiateExactlyOneSubclass(TypeRegistryConfigurer.class, MultiLoader.packageName(runtimeOptions.getGlue()), new Class[0], new Object[0], new DefaultTypeRegistryConfiguration());
47+
TypeRegistry typeRegistry = new TypeRegistry(typeRegistryConfigurer.locale());
48+
typeRegistryConfigurer.configureTypeRegistry(typeRegistry);
49+
50+
return reflections.instantiateSubclasses(Backend.class, packages, new Class[]{ResourceLoader.class, TypeRegistry.class}, new Object[]{resourceLoader, typeRegistry});
51+
}
52+
53+
}
Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,7 @@
11
package cucumber.runtime;
22

3-
import cucumber.api.TypeRegistryConfigurer;
4-
import cucumber.runtime.io.MultiLoader;
5-
import cucumber.runtime.io.ResourceLoader;
6-
import io.cucumber.stepexpression.TypeRegistry;
7-
83
import java.util.Collection;
94

10-
import static java.util.Collections.singletonList;
11-
12-
public class BackendSupplier implements Supplier<Collection<? extends Backend>> {
13-
14-
private final ResourceLoader resourceLoader;
15-
private final ClassFinder classFinder;
16-
private final RuntimeOptions runtimeOptions;
17-
18-
public BackendSupplier(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions) {
19-
this.resourceLoader = resourceLoader;
20-
this.classFinder = classFinder;
21-
this.runtimeOptions = runtimeOptions;
22-
}
23-
24-
25-
@Override
26-
public Collection<? extends Backend> get() {
27-
Collection<? extends Backend> backends = loadBackends(resourceLoader, classFinder, runtimeOptions);
28-
29-
return backends;
30-
}
31-
32-
private static Collection<? extends Backend> loadBackends(ResourceLoader resourceLoader, ClassFinder classFinder, RuntimeOptions runtimeOptions) {
33-
Reflections reflections = new Reflections(classFinder);
34-
TypeRegistryConfigurer typeRegistryConfigurer = reflections.instantiateExactlyOneSubclass(TypeRegistryConfigurer.class, MultiLoader.packageName(runtimeOptions.getGlue()), new Class[0], new Object[0], new DefaultTypeRegistryConfiguration());
35-
TypeRegistry typeRegistry = new TypeRegistry(typeRegistryConfigurer.locale());
36-
typeRegistryConfigurer.configureTypeRegistry(typeRegistry);
37-
return reflections.instantiateSubclasses(Backend.class, singletonList("cucumber.runtime"), new Class[]{ResourceLoader.class, TypeRegistry.class}, new Object[]{resourceLoader, typeRegistry});
38-
}
39-
5+
public interface BackendSupplier {
6+
Collection<? extends Backend> get();
407
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package cucumber.runtime;
2+
3+
import cucumber.runtime.model.CucumberFeature;
4+
import cucumber.runtime.model.FeatureLoader;
5+
6+
import java.util.List;
7+
8+
/**
9+
* Supplies a list of features found on the the feature path provided to RuntimeOptions.
10+
*/
11+
public class FeaturePathFeatureSupplier implements FeatureSupplier {
12+
private final FeatureLoader featureLoader;
13+
private final RuntimeOptions runtimeOptions;
14+
15+
public FeaturePathFeatureSupplier(FeatureLoader featureLoader, RuntimeOptions runtimeOptions) {
16+
this.featureLoader = featureLoader;
17+
this.runtimeOptions = runtimeOptions;
18+
}
19+
20+
@Override
21+
public List<CucumberFeature> get() {
22+
return featureLoader.load(runtimeOptions.getFeaturePaths(), System.out);
23+
}
24+
}
Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
package cucumber.runtime;
22

33
import cucumber.runtime.model.CucumberFeature;
4-
import cucumber.runtime.model.FeatureLoader;
54

65
import java.util.List;
76

8-
public class FeatureSupplier implements Supplier<List<CucumberFeature>> {
9-
private final FeatureLoader featureLoader;
10-
private final RuntimeOptions runtimeOptions;
11-
12-
public FeatureSupplier(FeatureLoader featureLoader, RuntimeOptions runtimeOptions) {
13-
this.featureLoader = featureLoader;
14-
this.runtimeOptions = runtimeOptions;
15-
}
16-
17-
@Override
18-
public List<CucumberFeature> get() {
19-
return featureLoader.load(runtimeOptions.getFeaturePaths(), System.out);
20-
}
7+
public interface FeatureSupplier {
8+
List<CucumberFeature> get();
219
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package cucumber.runtime;
2+
3+
public interface GlueSupplier {
4+
Glue get();
5+
}
Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,7 @@
11
package cucumber.runtime;
22

3-
import cucumber.runner.EventBus;
43
import cucumber.runner.Runner;
54

6-
import java.util.Collection;
7-
8-
public class RunnerSupplier implements Supplier<Runner> {
9-
10-
private final Supplier<Collection<? extends Backend>> backendSupplier;
11-
private final RuntimeOptions runtimeOptions;
12-
private final Supplier<Glue> glueSupplier;
13-
private final EventBus eventBus;
14-
15-
private final ThreadLocal<Runner> runners = new ThreadLocal<Runner>();
16-
17-
public RunnerSupplier(
18-
RuntimeOptions runtimeOptions,
19-
EventBus eventBus,
20-
Supplier<Collection<? extends Backend>> backendSupplier,
21-
Supplier<Glue> glueSupplier
22-
) {
23-
this.backendSupplier = backendSupplier;
24-
this.runtimeOptions = runtimeOptions;
25-
this.glueSupplier = glueSupplier;
26-
this.eventBus = eventBus;
27-
}
28-
29-
@Override
30-
public Runner get() {
31-
Runner runner = runners.get();
32-
if (runner == null) {
33-
runner = createRunner();
34-
runners.set(runner);
35-
}
36-
return runner;
37-
}
38-
39-
private Runner createRunner() {
40-
Collection<? extends Backend> backends = backendSupplier.get();
41-
if (backends.isEmpty()) {
42-
throw new CucumberException("No backends were found. Please make sure you have a backend module on your CLASSPATH.");
43-
}
44-
return new Runner(glueSupplier.get(), eventBus.createBatchedEventBus(), backends, runtimeOptions);
45-
}
46-
5+
public interface RunnerSupplier {
6+
Runner get();
477
}

core/src/main/java/cucumber/runtime/Runtime.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ public class Runtime {
2525
private final Filters filters;
2626
private final EventBus bus;
2727
private final FeatureCompiler compiler = new FeatureCompiler();
28-
private final Supplier<List<CucumberFeature>> featureSupplier;
28+
private final FeatureSupplier featureSupplier;
2929
private final Plugins plugins;
3030

3131
public Runtime(Plugins plugins,
3232
RuntimeOptions runtimeOptions,
3333
EventBus bus,
3434
Filters filters,
35-
Supplier<Runner> runnerSupplier,
36-
Supplier<List<CucumberFeature>> featureSupplier
35+
RunnerSupplier runnerSupplier,
36+
FeatureSupplier featureSupplier
3737
) {
3838

3939
this.plugins = plugins;

core/src/main/java/cucumber/runtime/RuntimeGlueSupplier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package cucumber.runtime;
22

3-
public final class RuntimeGlueSupplier implements Supplier<Glue> {
3+
public final class RuntimeGlueSupplier implements GlueSupplier {
44

55
@Override
66
public Glue get() {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package cucumber.runtime;
2+
3+
import cucumber.runner.EventBus;
4+
import cucumber.runner.Runner;
5+
6+
/**
7+
* Returns a distinct runner for each calling thread.
8+
*/
9+
public class ThreadLocalRunnerSupplier implements RunnerSupplier {
10+
11+
private final BackendSupplier backendSupplier;
12+
private final RuntimeOptions runtimeOptions;
13+
private final GlueSupplier glueSupplier;
14+
private final EventBus eventBus;
15+
16+
private final ThreadLocal<Runner> runners = new ThreadLocal<Runner>();
17+
18+
public ThreadLocalRunnerSupplier(
19+
RuntimeOptions runtimeOptions,
20+
EventBus eventBus,
21+
BackendSupplier backendSupplier,
22+
GlueSupplier glueSupplier
23+
) {
24+
this.backendSupplier = backendSupplier;
25+
this.runtimeOptions = runtimeOptions;
26+
this.glueSupplier = glueSupplier;
27+
this.eventBus = eventBus;
28+
}
29+
30+
@Override
31+
public Runner get() {
32+
Runner runner = runners.get();
33+
if (runner == null) {
34+
runner = createRunner();
35+
runners.set(runner);
36+
}
37+
return runner;
38+
}
39+
40+
private Runner createRunner() {
41+
return new Runner(glueSupplier.get(), eventBus.createBatchedEventBus(), backendSupplier.get(), runtimeOptions);
42+
}
43+
44+
}

core/src/test/java/cucumber/runner/RunnerTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cucumber.runner;
22

3-
import cucumber.runtime.RunnerSupplier;
3+
import cucumber.runtime.BackendSupplier;
4+
import cucumber.runtime.ThreadLocalRunnerSupplier;
45
import cucumber.runtime.RuntimeGlueSupplier;
56
import cucumber.runtime.Supplier;
67
import io.cucumber.stepexpression.Argument;
@@ -26,6 +27,7 @@
2627
import java.util.List;
2728

2829
import static java.util.Arrays.asList;
30+
import static java.util.Collections.singletonList;
2931
import static org.mockito.ArgumentMatchers.anyListOf;
3032
import static org.mockito.Mockito.doThrow;
3133
import static org.mockito.Mockito.inOrder;
@@ -173,15 +175,15 @@ private Runner createRunner(Backend backend) {
173175

174176
private Runner createRunner(final Backend backend, String options) {
175177
RuntimeOptions runtimeOptions = new RuntimeOptions(options);
176-
Supplier<Collection<? extends Backend>> backendSupplier = new Supplier<Collection<? extends Backend>>() {
178+
BackendSupplier backendSupplier = new BackendSupplier() {
177179
@Override
178180
public Collection<? extends Backend> get() {
179-
return asList(backend);
181+
return singletonList(backend);
180182
}
181183
};
182184
EventBus bus = new EventBus(TimeService.SYSTEM);
183185
RuntimeGlueSupplier glueSupplier = new RuntimeGlueSupplier();
184-
return new RunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier).get();
186+
return new ThreadLocalRunnerSupplier(runtimeOptions, bus, backendSupplier, glueSupplier).get();
185187
}
186188

187189
private HookDefinition addBeforeHook() {

0 commit comments

Comments
 (0)