Skip to content

[Core] Allow runner to register bus as concurrent or serial event source #1656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions core/src/main/java/cucumber/runtime/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ public class Runtime {

private final ExitStatus exitStatus;

private final RuntimeOptions runtimeOptions;

private final RunnerSupplier runnerSupplier;
private final Filters filters;
private final EventBus bus;
Expand All @@ -62,7 +60,6 @@ public Runtime(final Plugins plugins,
final ExecutorService executor) {

this.plugins = plugins;
this.runtimeOptions = runtimeOptions;
this.filters = filters;
this.bus = bus;
this.runnerSupplier = runnerSupplier;
Expand Down Expand Up @@ -208,10 +205,15 @@ public Runtime build() {
? this.backendSupplier
: new BackendModuleBackendSupplier(resourceLoader, classFinder, this.runtimeOptions);

final Plugins plugins = new Plugins(this.classLoader, new PluginFactory(), this.eventBus, this.runtimeOptions);
final Plugins plugins = new Plugins(this.classLoader, new PluginFactory(), this.runtimeOptions);
for (final Plugin plugin : additionalPlugins) {
plugins.addPlugin(plugin);
}
if (this.runtimeOptions.isMultiThreaded()) {
plugins.setSerialEventBusOnEventListenerPlugins(this.eventBus);
} else {
plugins.setEventBusOnEventListenerPlugins(this.eventBus);
}

final RunnerSupplier runnerSupplier = runtimeOptions.isMultiThreaded()
? new ThreadLocalRunnerSupplier(this.runtimeOptions, eventBus, backendSupplier)
Expand Down
39 changes: 23 additions & 16 deletions core/src/main/java/cucumber/runtime/formatter/Plugins.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,29 @@ public final class Plugins {
private boolean pluginNamesInstantiated;

private final PluginFactory pluginFactory;
private final EventPublisher eventPublisher;
private EventPublisher orderedEventPublisher;
private final PluginOptions pluginOptions;

public Plugins(ClassLoader classLoader, PluginFactory pluginFactory, EventPublisher eventPublisher, PluginOptions pluginOptions) {
public Plugins(ClassLoader classLoader, PluginFactory pluginFactory, PluginOptions pluginOptions) {
this.classLoader = classLoader;
this.pluginFactory = pluginFactory;
this.eventPublisher = eventPublisher;
this.pluginOptions = pluginOptions;
this.plugins = createPlugins();
}


private EventPublisher getOrderedEventPublisher() {
private EventPublisher getOrderedEventPublisher(EventPublisher eventPublisher) {
// The ordered event publisher stores all events
// so don't create it unless we need it.
if(orderedEventPublisher == null){
orderedEventPublisher = createCanonicalOrderEventPublisher();
orderedEventPublisher = createCanonicalOrderEventPublisher(eventPublisher);
}
return orderedEventPublisher;
}

private EventPublisher createCanonicalOrderEventPublisher() {
private static EventPublisher createCanonicalOrderEventPublisher(EventPublisher eventPublisher) {
final CanonicalOrderEventPublisher canonicalOrderEventPublisher = new CanonicalOrderEventPublisher();
this.eventPublisher.registerHandlerFor(Event.class, new EventHandler<Event>() {
eventPublisher.registerHandlerFor(Event.class, new EventHandler<Event>() {
@Override
public void receive(Event event) {
canonicalOrderEventPublisher.handle(event);
Expand Down Expand Up @@ -86,7 +84,6 @@ private void addPlugin(List<Plugin> plugins, Plugin plugin) {
plugins.add(plugin);
setMonochromeOnColorAwarePlugins(plugin);
setStrictOnStrictAwarePlugins(plugin);
setEventBusOnEventListenerPlugins(plugin);
}

private void setMonochromeOnColorAwarePlugins(Plugin plugin) {
Expand All @@ -103,16 +100,26 @@ private void setStrictOnStrictAwarePlugins(Plugin plugin) {
}
}

private void setEventBusOnEventListenerPlugins(Plugin plugin) {
if (plugin instanceof ConcurrentEventListener) {
ConcurrentEventListener formatter = (ConcurrentEventListener) plugin;
formatter.setEventPublisher(eventPublisher);
} else if (plugin instanceof EventListener) {
EventListener formatter = (EventListener) plugin;
formatter.setEventPublisher(getOrderedEventPublisher());
}
public void setEventBusOnEventListenerPlugins(EventPublisher eventPublisher) {
for (Plugin plugin : plugins) {
if (plugin instanceof ConcurrentEventListener) {
((ConcurrentEventListener) plugin).setEventPublisher(eventPublisher);
} else if (plugin instanceof EventListener) {
((EventListener) plugin).setEventPublisher(eventPublisher);
}
}
}

public void setSerialEventBusOnEventListenerPlugins(EventPublisher eventPublisher) {
for (Plugin plugin : plugins) {
if (plugin instanceof ConcurrentEventListener) {
((ConcurrentEventListener) plugin).setEventPublisher(eventPublisher);
} else if (plugin instanceof EventListener) {
EventPublisher orderedEventPublisher = getOrderedEventPublisher(eventPublisher);
((EventListener) plugin).setEventPublisher(orderedEventPublisher);
}
}
}

/**
* Creates a dynamic proxy that multiplexes method invocations to all plugins of the same type.
Expand Down
18 changes: 12 additions & 6 deletions core/src/test/java/cucumber/runtime/RuntimeOptionsFactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public void create_without_options() {
assertFalse(runtimeOptions.isStrict());
assertThat(runtimeOptions.getFeaturePaths(), contains(uri("classpath:cucumber/runtime")));
assertThat(runtimeOptions.getGlue(), contains(uri("classpath:cucumber/runtime")));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), runtimeOptions);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), runtimeOptions);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasSize(2));
assertPluginExists(plugins.getPlugins(), "cucumber.runtime.formatter.ProgressFormatter");
Expand All @@ -59,7 +60,9 @@ public static URI uri(String str) {
public void create_without_options_with_base_class_without_options() {
RuntimeOptionsFactory runtimeOptionsFactory = new RuntimeOptionsFactory(WithoutOptionsWithBaseClassWithoutOptions.class);
RuntimeOptions runtimeOptions = runtimeOptionsFactory.create();
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), runtimeOptions);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), runtimeOptions);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(runtimeOptions.getFeaturePaths(), contains(uri("classpath:cucumber/runtime")));
assertThat(runtimeOptions.getGlue(), contains(uri("classpath:cucumber/runtime")));

Expand Down Expand Up @@ -105,17 +108,20 @@ private String getRegexpPattern(Object pattern) {
public void create_default_summary_printer_when_no_summary_printer_plugin_is_defined() {
RuntimeOptionsFactory runtimeOptionsFactory = new RuntimeOptionsFactory(ClassWithNoSummaryPrinterPlugin.class);
RuntimeOptions runtimeOptions = runtimeOptionsFactory.create();
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), runtimeOptions);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), runtimeOptions);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));
assertPluginExists(plugins.getPlugins(), "cucumber.runtime.formatter.DefaultSummaryPrinter");
}

@Test
public void inherit_plugin_from_baseclass() {
RuntimeOptionsFactory runtimeOptionsFactory = new RuntimeOptionsFactory(SubClassWithFormatter.class);
RuntimeOptions runtimeOptions = runtimeOptionsFactory.create();
List<Plugin> plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), runtimeOptions).getPlugins();
assertPluginExists(plugins, "cucumber.runtime.formatter.JSONFormatter");
assertPluginExists(plugins, "cucumber.runtime.formatter.PrettyFormatter");
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), runtimeOptions);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));
List<Plugin> pluginList = plugins.getPlugins();
assertPluginExists(pluginList, "cucumber.runtime.formatter.JSONFormatter");
assertPluginExists(pluginList, "cucumber.runtime.formatter.PrettyFormatter");
}

@Test
Expand Down
47 changes: 35 additions & 12 deletions core/src/test/java/cucumber/runtime/RuntimeOptionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,35 +147,44 @@ public void assigns_glue() {
@Test
public void creates_html_formatter() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "html:target/some/dir", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins().get(0).getClass().getName(), is("cucumber.runtime.formatter.HTMLFormatter"));
}

@Test
public void creates_progress_formatter_as_default() {
RuntimeOptions options = new RuntimeOptions(asList("--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));
assertThat(plugins.getPlugins().get(0).getClass().getName(), is("cucumber.runtime.formatter.ProgressFormatter"));
}

@Test
public void creates_progress_formatter_when_no_formatter_plugin_is_specified() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "cucumber.runtime.formatter.AnyStepDefinitionReporter", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.ProgressFormatter")));
}

@Test
public void creates_default_summary_printer_when_no_summary_printer_plugin_is_specified() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "pretty", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.DefaultSummaryPrinter")));
}

@Test
public void creates_null_summary_printer() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "null_summary", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.NullSummaryPrinter")));
assertThat(plugins.getPlugins(), not(hasItem(plugin("cucumber.runtime.formatter.DefaultSummaryPrinter"))));
}
Expand Down Expand Up @@ -354,7 +363,9 @@ public void clobbers_line_filters_from_cli_if_features_specified_in_cucumber_opt
public void clobbers_formatter_plugins_from_cli_if_formatters_specified_in_cucumber_options_property() {
properties.setProperty("cucumber.options", "--plugin pretty");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "html:target/some/dir", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.PrettyFormatter")));
assertThat(plugins.getPlugins(), not(hasItem(plugin("cucumber.runtime.formatter.HTMLFormatter"))));
}
Expand All @@ -363,7 +374,9 @@ public void clobbers_formatter_plugins_from_cli_if_formatters_specified_in_cucum
public void adds_to_formatter_plugins_with_add_plugin_option() {
properties.setProperty("cucumber.options", "--add-plugin pretty");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "html:target/some/dir", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.HTMLFormatter")));
assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.PrettyFormatter")));
}
Expand All @@ -372,7 +385,9 @@ public void adds_to_formatter_plugins_with_add_plugin_option() {
public void clobbers_summary_plugins_from_cli_if_summary_printer_specified_in_cucumber_options_property() {
properties.setProperty("cucumber.options", "--plugin default_summary");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "null_summary", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.DefaultSummaryPrinter")));
assertThat(plugins.getPlugins(), not(hasItem(plugin("cucumber.runtime.formatter.NullSummaryPrinter"))));
}
Expand All @@ -381,7 +396,9 @@ public void clobbers_summary_plugins_from_cli_if_summary_printer_specified_in_cu
public void adds_to_summary_plugins_with_add_plugin_option() {
properties.setProperty("cucumber.options", "--add-plugin default_summary");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "null_summary", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.NullSummaryPrinter")));
assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.DefaultSummaryPrinter")));
}
Expand All @@ -390,7 +407,9 @@ public void adds_to_summary_plugins_with_add_plugin_option() {
public void does_not_clobber_plugins_of_different_type_when_specifying_plugins_in_cucumber_options_property() {
properties.setProperty("cucumber.options", "--plugin default_summary");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "pretty", "--glue", "somewhere"));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.PrettyFormatter")));
assertThat(plugins.getPlugins(), hasItem(plugin("cucumber.runtime.formatter.DefaultSummaryPrinter")));
}
Expand Down Expand Up @@ -430,15 +449,19 @@ public void ensure_less_than_1_thread_is_not_allowed() {
@Test
public void set_monochrome_on_color_aware_formatters() {
RuntimeOptions options = new RuntimeOptions(new Env(), asList("--monochrome", "--plugin", AwareFormatter.class.getName()));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

AwareFormatter formatter = (AwareFormatter) plugins.getPlugins().get(0);
assertThat(formatter.isMonochrome(), is(true));
}

@Test
public void set_strict_on_strict_aware_formatters() {
RuntimeOptions options = new RuntimeOptions(new Env(), asList("--strict", "--plugin", AwareFormatter.class.getName()));
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), new TimeServiceEventBus(TimeService.SYSTEM), options);
Plugins plugins = new Plugins(getClass().getClassLoader(), new PluginFactory(), options);
plugins.setEventBusOnEventListenerPlugins(new TimeServiceEventBus(TimeService.SYSTEM));

AwareFormatter formatter = (AwareFormatter) plugins.getPlugins().get(0);
assertThat(formatter.isStrict(), is(true));

Expand Down
Loading