Skip to content

Commit 36952b9

Browse files
authored
[Core] Merge duplicate plugin options (#2191)
It is possible to declare duplicate plugins. Either through `@CucumberOptions`, or `cucumber.plugin`, ect or a combination thereof. This can be used to ensure certain plugins are always active during a build in CI. Merging duplicate plugin options should ensure that plugins are not instantiated twice with the same output. Fixes: #2190
1 parent 656fc60 commit 36952b9

File tree

6 files changed

+67
-10
lines changed

6 files changed

+67
-10
lines changed

Diff for: CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
### Removed
1818

1919
### Fixed
20-
* [Core] SummaryPrinter outputs clickable links ([#2184](https://github.com/cucumber/cucumber-jvm/issues/2184) M.P. Korstanje)
20+
* [Core] SummaryPrinter outputs clickable links ([#2184](https://github.com/cucumber/cucumber-jvm/issues/2184) M.P. Korstanje)
21+
* [Core] Merge duplicate plugin options ([#2190](https://github.com/cucumber/cucumber-jvm/issues/2190) M.P. Korstanje)
2122

2223
## [6.9.0] (2020-11-12)
2324

Diff for: core/src/main/java/io/cucumber/core/options/PluginOption.java

+13
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.HashMap;
2626
import java.util.HashSet;
2727
import java.util.Map;
28+
import java.util.Objects;
2829
import java.util.Set;
2930
import java.util.regex.Matcher;
3031
import java.util.regex.Pattern;
@@ -206,4 +207,16 @@ boolean isSummaryPrinter() {
206207
return SummaryPrinter.class.isAssignableFrom(pluginClass);
207208
}
208209

210+
@Override
211+
public boolean equals(Object o) {
212+
if (this == o) return true;
213+
if (o == null || getClass() != o.getClass()) return false;
214+
PluginOption that = (PluginOption) o;
215+
return pluginClass.equals(that.pluginClass) && Objects.equals(argument, that.argument);
216+
}
217+
218+
@Override
219+
public int hashCode() {
220+
return Objects.hash(pluginClass, argument);
221+
}
209222
}

Diff for: core/src/main/java/io/cucumber/core/options/RuntimeOptions.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.net.URI;
1313
import java.util.ArrayList;
1414
import java.util.HashMap;
15+
import java.util.LinkedHashSet;
1516
import java.util.List;
1617
import java.util.Map;
1718
import java.util.Set;
@@ -37,8 +38,8 @@ public final class RuntimeOptions implements
3738
private final List<Expression> tagExpressions = new ArrayList<>();
3839
private final List<Pattern> nameFilters = new ArrayList<>();
3940
private final List<FeatureWithLines> featurePaths = new ArrayList<>();
40-
private final List<Plugin> formatters = new ArrayList<>();
41-
private final List<Plugin> summaryPrinters = new ArrayList<>();
41+
private final Set<Plugin> formatters = new LinkedHashSet<>();
42+
private final Set<Plugin> summaryPrinters = new LinkedHashSet<>();
4243
private boolean dryRun;
4344
private boolean monochrome = false;
4445
private boolean wip = false;
@@ -106,11 +107,11 @@ void setThreads(int threads) {
106107

107108
@Override
108109
public List<Plugin> plugins() {
109-
List<Plugin> plugins = new ArrayList<>();
110+
Set<Plugin> plugins = new LinkedHashSet<>();
110111
plugins.addAll(formatters);
111112
plugins.addAll(summaryPrinters);
112113
plugins.addAll(getPublishPlugin());
113-
return plugins;
114+
return new ArrayList<>(plugins);
114115
}
115116

116117
private List<Plugin> getPublishPlugin() {

Diff for: core/src/test/java/io/cucumber/core/options/BooleanStringTest.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@
1111
class BooleanStringTest {
1212

1313
@Test
14-
public void null_is_false() {
14+
void null_is_false() {
1515
assertThat(BooleanString.parseBoolean(null), is(false));
1616
}
1717

1818
@ParameterizedTest
1919
@ValueSource(strings = { "false", "no", "0" })
20-
public void falsy_values_are_false(String value) {
20+
void falsy_values_are_false(String value) {
2121
assertThat(BooleanString.parseBoolean(value), is(false));
2222
}
2323

2424
@ParameterizedTest
2525
@ValueSource(strings = { "true", "yes", "1" })
26-
public void truthy_values_are_true(String value) {
26+
void truthy_values_are_true(String value) {
2727
assertThat(BooleanString.parseBoolean(value), is(true));
2828
}
2929

3030
@ParameterizedTest
3131
@ValueSource(strings = { "y", "n", "-1", " ", "" })
32-
public void unknown_values_throw_illegal_argument_exception(String value) {
32+
void unknown_values_throw_illegal_argument_exception(String value) {
3333
assertThrows(IllegalArgumentException.class, () -> BooleanString.parseBoolean(value));
3434
}
3535

Diff for: core/src/test/java/io/cucumber/core/options/PluginOptionTest.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.cucumber.core.options;
22

3+
import io.cucumber.core.plugin.HtmlFormatter;
34
import io.cucumber.core.plugin.PrettyFormatter;
45
import io.cucumber.core.plugin.TeamCityPlugin;
56
import org.junit.jupiter.api.Test;
@@ -8,6 +9,8 @@
89
import static org.hamcrest.core.Is.is;
910
import static org.hamcrest.core.IsNull.nullValue;
1011
import static org.junit.jupiter.api.Assertions.assertAll;
12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
1114
import static org.junit.jupiter.api.Assertions.assertThrows;
1215

1316
class PluginOptionTest {
@@ -77,7 +80,7 @@ void throws_for_plugins_that_do_not_implement_plugin() {
7780
}
7881

7982
@Test
80-
void throws_for_uknown_plugins() {
83+
void throws_for_unknown_plugins() {
8184
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
8285
() -> PluginOption.parse("no-such-plugin"));
8386

@@ -93,4 +96,19 @@ void throws_for_uknown_plugins() {
9396
"PLUGIN can also be a fully qualified class name, allowing registration of 3rd party plugins. The 3rd party plugin must implement io.cucumber.plugin.Plugin"));
9497
}
9598

99+
100+
@Test
101+
void should_implement_equals_and_hashcode(){
102+
PluginOption prettyPluginA = PluginOption.forClass(PrettyFormatter.class);
103+
PluginOption prettyPluginB = PluginOption.forClass(PrettyFormatter.class);
104+
PluginOption htmlPluginA = PluginOption.forClass(HtmlFormatter.class, "out.html");
105+
PluginOption htmlPluginB = PluginOption.forClass(HtmlFormatter.class, "out.html");
106+
107+
assertEquals(prettyPluginA, prettyPluginB);
108+
assertEquals(prettyPluginA.hashCode(), prettyPluginB.hashCode());
109+
assertEquals(htmlPluginA, htmlPluginB);
110+
assertEquals(htmlPluginA.hashCode(), htmlPluginB.hashCode());
111+
assertNotEquals(prettyPluginA, htmlPluginA);
112+
assertNotEquals(prettyPluginA.hashCode(), htmlPluginA.hashCode());
113+
}
96114
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.cucumber.core.options;
2+
3+
import io.cucumber.core.plugin.PrettyFormatter;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.util.Arrays;
7+
8+
import static java.util.Collections.singletonList;
9+
import static org.hamcrest.CoreMatchers.is;
10+
import static org.hamcrest.MatcherAssert.assertThat;
11+
12+
class RuntimeOptionsTest {
13+
14+
private final PluginOption aPlugin = PluginOption.forClass(PrettyFormatter.class);
15+
16+
@Test
17+
void shouldRemoveDuplicatePluginRegistrations() {
18+
RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
19+
runtimeOptions.addSummaryPrinters(Arrays.asList(aPlugin, aPlugin));
20+
runtimeOptions.addFormatters(Arrays.asList(aPlugin, aPlugin));
21+
assertThat(runtimeOptions.plugins(), is(singletonList(aPlugin)));
22+
}
23+
24+
}

0 commit comments

Comments
 (0)