package com.annimon.stream.test.hamcrest; import com.annimon.stream.Stream; import com.annimon.stream.function.Function; import java.util.List; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeDiagnosingMatcher; import static org.hamcrest.MatcherAssert.assertThat; public class StreamMatcher { private StreamMatcher() { } public static Matcher<Stream<?>> isEmpty() { return new IsEmptyMatcher(); } public static Matcher<Stream<?>> hasElements() { return new HasElementsMatcher(); } public static <T> Matcher<Stream<T>> elements(Matcher<Iterable<? extends T>> matcher) { return new ElementsMatcher<T>(matcher); } public static <T> Function<Stream<T>, Void> assertIsEmpty() { return new Function<Stream<T>, Void>() { @Override public Void apply(Stream<T> t) { assertThat(t, isEmpty()); return null; } }; } public static <T> Function<Stream<T>, Void> assertHasElements() { return new Function<Stream<T>, Void>() { @Override public Void apply(Stream<T> t) { assertThat(t, hasElements()); return null; } }; } public static <T> Function<Stream<T>, Void> assertElements(final Matcher<Iterable<? extends T>> matcher) { return new Function<Stream<T>, Void>() { @Override public Void apply(Stream<T> t) { assertThat(t, elements(matcher)); return null; } }; } public static class IsEmptyMatcher extends TypeSafeDiagnosingMatcher<Stream<?>> { @Override protected boolean matchesSafely(Stream<?> stream, Description mismatchDescription) { mismatchDescription.appendText("Stream was not empty"); return stream.count() == 0; } @Override public void describeTo(Description description) { description.appendText("an empty stream"); } } public static class HasElementsMatcher extends TypeSafeDiagnosingMatcher<Stream<?>> { @Override protected boolean matchesSafely(Stream<?> stream, Description mismatchDescription) { mismatchDescription.appendText("Stream was empty"); return stream.count() > 0; } @Override public void describeTo(Description description) { description.appendText("a non-empty stream"); } } public static class ElementsMatcher<T> extends TypeSafeDiagnosingMatcher<Stream<T>> { private final Matcher<Iterable<? extends T>> matcher; private List<T> streamElements; public ElementsMatcher(Matcher<Iterable<? extends T>> matcher) { this.matcher = matcher; } @Override protected boolean matchesSafely(Stream<T> stream, Description mismatchDescription) { final List<T> elements; if (streamElements == null) { elements = stream.toList(); streamElements = elements; } else { elements = streamElements; } if (!matcher.matches(elements)) { mismatchDescription.appendText("Stream elements "); matcher.describeMismatch(elements, mismatchDescription); return false; } return true; } @Override public void describeTo(Description description) { description.appendText("Stream elements ").appendDescriptionOf(matcher); } } }