From d5c58cfb75ba50d958f50c6df2fcbb8fe35d92a3 Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Thu, 30 May 2019 11:48:13 +0000 Subject: [PATCH 1/4] Fix return type of StreamMatchers.empty & .equalTo Return type is parameterized to yield a Matcher of the specific Stream-type, instead of just Matcher>. See https://github.com/unruly/java-8-matchers/issues/18 for more detailed discussion. --- .../probablyfine/matchers/StreamMatchers.java | 14 +++++++------- .../matchers/StreamMatchersTest.java | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java b/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java index 469b895..cbe7877 100644 --- a/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java +++ b/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java @@ -13,13 +13,13 @@ public class StreamMatchers { - public static > Matcher> empty() { - return new TypeSafeMatcher>() { + public static > Matcher empty() { + return new TypeSafeMatcher() { private Iterator actualIterator; @Override - protected boolean matchesSafely(BaseStream actual) { + protected boolean matchesSafely(S actual) { actualIterator = actual.iterator(); return !actualIterator.hasNext(); } @@ -30,7 +30,7 @@ public void describeTo(Description description) { } @Override - protected void describeMismatchSafely(BaseStream item, Description description) { + protected void describeMismatchSafely(S item, Description description) { description.appendText("A non empty Stream starting with ").appendValue(actualIterator.next()); } }; @@ -50,10 +50,10 @@ protected void describeMismatchSafely(BaseStream item, Description descrip * @see #startsWithLong * @see #startsWithDouble */ - public static > Matcher> equalTo(BaseStream expected) { - return new BaseStreamMatcher>() { + public static > Matcher equalTo(S expected) { + return new BaseStreamMatcher() { @Override - protected boolean matchesSafely(BaseStream actual) { + protected boolean matchesSafely(S actual) { return remainingItemsEqual(expected.iterator(), actual.iterator()); } }; diff --git a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java index ed64b3e..b6e89eb 100644 --- a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java +++ b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java @@ -4,9 +4,16 @@ import org.hamcrest.Matchers; import org.junit.Test; -import java.util.stream.*; - -import static org.hamcrest.Matchers.*; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; public class StreamMatchersTest { @@ -203,7 +210,7 @@ public void startsWithItemsIntStream_success() throws Exception { @Test public void equalTo_failureMessages() throws Exception { - Matcher>> matcher = StreamMatchers.equalTo(Stream.of("a", "b", "c", "d", "e", "f", "g", "h")); + Matcher> matcher = StreamMatchers.equalTo(Stream.of("a", "b", "c", "d", "e", "f", "g", "h")); Stream testData = Stream.of("a", "b", "c", "d", "e"); Helper.testFailingMatcher(testData, matcher, "Stream of [\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\",\"h\"]", "Stream of [\"a\",\"b\",\"c\",\"d\",\"e\"]"); } @@ -219,7 +226,7 @@ public void contains_failureMessages() throws Exception { @Test public void equalToIntStream_failureMessages() throws Exception { IntStream testData = IntStream.range(8, 10); - Matcher> matcher = StreamMatchers.equalTo(IntStream.range(0, 6)); + Matcher matcher = StreamMatchers.equalTo(IntStream.range(0, 6)); Helper.testFailingMatcher(testData, matcher, "Stream of [<0>,<1>,<2>,<3>,<4>,<5>]", "Stream of [<8>,<9>]"); } From ed171255624bf7d357999cb6f2872ccd5a72a070 Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Sat, 11 Apr 2020 16:59:17 +0200 Subject: [PATCH 2/4] Allow S to be inferred to supertype See https://github.com/unruly/java-8-matchers/issues/18#issuecomment-612429327 --- .../co/probablyfine/matchers/StreamMatchers.java | 14 +++++++++----- .../probablyfine/matchers/StreamMatchersTest.java | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java b/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java index cbe7877..6c5e634 100644 --- a/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java +++ b/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java @@ -7,13 +7,17 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.PrimitiveIterator; import java.util.Objects; -import java.util.stream.*; +import java.util.PrimitiveIterator; +import java.util.stream.BaseStream; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; public class StreamMatchers { - public static > Matcher empty() { + public static > Matcher empty() { return new TypeSafeMatcher() { private Iterator actualIterator; @@ -50,7 +54,7 @@ protected void describeMismatchSafely(S item, Description description) { * @see #startsWithLong * @see #startsWithDouble */ - public static > Matcher equalTo(S expected) { + public static > Matcher equalTo(S expected) { return new BaseStreamMatcher() { @Override protected boolean matchesSafely(S actual) { @@ -912,7 +916,7 @@ public T next() { private static class IntArrayIterator implements PrimitiveIterator.OfInt { private final int[] expected; private int currentPos = 0; - + public IntArrayIterator(int... expected) { this.expected = expected; } diff --git a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java index b6e89eb..fcb1339 100644 --- a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java +++ b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java @@ -3,7 +3,9 @@ import org.hamcrest.Matcher; import org.hamcrest.Matchers; import org.junit.Test; +import uk.co.probablyfine.matchers.function.DescribableFunction; +import java.util.stream.BaseStream; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; @@ -15,6 +17,7 @@ import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; +import static uk.co.probablyfine.matchers.Java8Matchers.where; public class StreamMatchersTest { @Test @@ -215,6 +218,18 @@ public void equalTo_failureMessages() throws Exception { Helper.testFailingMatcher(testData, matcher, "Stream of [\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\",\"h\"]", "Stream of [\"a\",\"b\",\"c\",\"d\",\"e\"]"); } + @Test + public void equalTo_handles_types() { + Stream expectedStream = Stream.of('x', 'y', 'z'); + assertThat("xyz", where(s -> s.chars().mapToObj(i -> (char) i), StreamMatchers.equalTo(expectedStream))); + + BaseStream> expectedBaseStream = Stream.of('x', 'y', 'z'); + assertThat("xyz", where(s -> s.chars().mapToObj(i -> (char) i), StreamMatchers.equalTo(expectedBaseStream))); + + DescribableFunction>> characters = s -> s.chars().mapToObj(i -> (char) i); + assertThat("xyz", where(characters, StreamMatchers.equalTo(Stream.of('x', 'y', 'z')))); + } + @Test public void contains_failureMessages() throws Exception { From e0d2c45b433dd0ec4ebf646bd4e3eb95a76bcb34 Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Wed, 15 Apr 2020 16:47:57 +0200 Subject: [PATCH 3/4] Fix typing for StreamMatchers.contains --- .../java/uk/co/probablyfine/matchers/StreamMatchers.java | 4 ++-- .../uk/co/probablyfine/matchers/StreamMatchersTest.java | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java b/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java index 6c5e634..9907658 100644 --- a/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java +++ b/src/main/java/uk/co/probablyfine/matchers/StreamMatchers.java @@ -370,7 +370,7 @@ public void describeTo(Description description) { * @see #startsWithDouble(double...) */ @SafeVarargs - public static > Matcher contains(Matcher... expectedMatchers) { + public static > Matcher contains(Matcher... expectedMatchers) { return new BaseMatcherStreamMatcher() { @Override @@ -393,7 +393,7 @@ protected boolean matchesSafely(S actual) { * @see #startsWithDouble(double...) */ @SafeVarargs - public static > Matcher contains(T... expected) { + public static > Matcher contains(T... expected) { return new BaseStreamMatcher() { @Override protected boolean matchesSafely(S actual) { diff --git a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java index fcb1339..6e4afc4 100644 --- a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java +++ b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java @@ -230,6 +230,15 @@ public void equalTo_handles_types() { assertThat("xyz", where(characters, StreamMatchers.equalTo(Stream.of('x', 'y', 'z')))); } + @Test + public void contains_handles_types() { + assertThat("xyz", where(s -> s.chars().mapToObj(i -> (char) i), contains('x', 'y', 'z'))); + + DescribableFunction>> characters = s -> s.chars().mapToObj(i -> (char) i); + assertThat("xyz", where(characters, contains('x', 'y', 'z'))); + assertThat("xyz", where(characters, not(contains('x', 'y')))); + } + @Test public void contains_failureMessages() throws Exception { From c9736405da9cc8c5bfc528987798202e44f2f8a9 Mon Sep 17 00:00:00 2001 From: Rune Flobakk Date: Wed, 15 Apr 2020 16:52:29 +0200 Subject: [PATCH 4/4] Make it compile on Java 11 This is peculiar. It seems the type inference through multiple levels of method invokations is better with Java 8 than Java 11. Anyway, the outermost is(..) invocation is redundant (and in my opinion also decreases readability), so they are removed to make the code compile on Java 11. --- .../co/probablyfine/matchers/StreamMatchersTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java index 6e4afc4..29da849 100644 --- a/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java +++ b/src/test/java/uk/co/probablyfine/matchers/StreamMatchersTest.java @@ -27,7 +27,7 @@ public void equalTo_failureDifferingSingleItem() throws Exception { @Test public void contains_failureDifferingSingleItem() throws Exception { - assertThat(Stream.of("a"), is(Matchers.not(StreamMatchers.contains("b")))); + assertThat(Stream.of("a"), not(StreamMatchers.contains("b"))); } @Test @@ -37,7 +37,7 @@ public void equalTo_failureDifferingLength() throws Exception { @Test public void contains_failureDifferingLength() throws Exception { - assertThat(Stream.of("a"), is(Matchers.not(StreamMatchers.contains("a", "b")))); + assertThat(Stream.of("a"), not(StreamMatchers.contains("a", "b"))); } @Test @@ -47,7 +47,7 @@ public void equalTo_failureDifferingItems() throws Exception { @Test public void contains_failureDifferingItems() throws Exception { - assertThat(Stream.of("a","c"), is(Matchers.not(StreamMatchers.contains("a", "b")))); + assertThat(Stream.of("a","c"), not(StreamMatchers.contains("a", "b"))); } @Test @@ -232,11 +232,11 @@ public void equalTo_handles_types() { @Test public void contains_handles_types() { - assertThat("xyz", where(s -> s.chars().mapToObj(i -> (char) i), contains('x', 'y', 'z'))); + assertThat("xyz", where(s -> s.chars().mapToObj(i -> (char) i), StreamMatchers.contains('x', 'y', 'z'))); DescribableFunction>> characters = s -> s.chars().mapToObj(i -> (char) i); - assertThat("xyz", where(characters, contains('x', 'y', 'z'))); - assertThat("xyz", where(characters, not(contains('x', 'y')))); + assertThat("xyz", where(characters, StreamMatchers.contains('x', 'y', 'z'))); + assertThat("xyz", where(characters, not(StreamMatchers.contains('x', 'y')))); }