1 package io.atlassian.fugue.hamcrest;
2
3 import io.atlassian.fugue.Try;
4 import org.hamcrest.Description;
5 import org.hamcrest.Matcher;
6 import org.hamcrest.Matchers;
7 import org.hamcrest.TypeSafeMatcher;
8
9 import static io.atlassian.fugue.Unit.Unit;
10 import static java.util.Objects.requireNonNull;
11
12
13
14
15 public final class TryMatchers {
16
17 private TryMatchers() {
18 throw new UnsupportedOperationException();
19 }
20
21 public static Matcher<Try<?>> isFailure(Matcher<? super Exception> subMatcher) {
22 return new FailureMatcher(requireNonNull(subMatcher, "subMatcher"));
23 }
24
25 public static Matcher<Try<?>> isFailure() {
26 return new FailureMatcher(Matchers.any(Exception.class));
27 }
28
29 public static <A> Matcher<Try<A>> isSuccessful(Matcher<? super A> subMatcher) {
30 return new SuccessfulMatcher<>(requireNonNull(subMatcher, "subMatcher"));
31 }
32
33 private static class FailureMatcher extends TypeSafeMatcher<Try<?>> {
34 private final Matcher<? super Exception> subMatcher;
35
36 private FailureMatcher(Matcher<? super Exception> subMatcher) {
37 this.subMatcher = subMatcher;
38 }
39
40 @Override protected boolean matchesSafely(Try<?> actual) {
41 return actual.toEither().left().exists(subMatcher::matches);
42 }
43
44 @Override public void describeTo(Description description) {
45 description.appendText("failure that ");
46 subMatcher.describeTo(description);
47 }
48
49 @Override protected void describeMismatchSafely(Try<?> actual, Description mismatchDescription) {
50 actual.fold(left -> {
51 mismatchDescription.appendText("was failure that ");
52 subMatcher.describeMismatch(left, mismatchDescription);
53 return Unit();
54 }, right -> {
55 mismatchDescription.appendText("was successful");
56 return Unit();
57 });
58 }
59 }
60
61 private static class SuccessfulMatcher<A> extends TypeSafeMatcher<Try<A>> {
62
63 private final Matcher<? super A> subMatcher;
64
65 private SuccessfulMatcher(Matcher<? super A> subMatcher) {
66 this.subMatcher = subMatcher;
67 }
68
69 @Override protected boolean matchesSafely(Try<A> actual) {
70 return actual.toEither().right().exists(subMatcher::matches);
71 }
72
73 @Override public void describeTo(Description description) {
74 description.appendText("successful that ");
75 subMatcher.describeTo(description);
76 }
77
78 @Override protected void describeMismatchSafely(Try<A> actual, Description mismatchDescription) {
79 actual.fold(left -> {
80 mismatchDescription.appendText("was failure");
81 return Unit();
82 }, right -> {
83 mismatchDescription.appendText("was successful that ");
84 subMatcher.describeMismatch(right, mismatchDescription);
85 return Unit();
86 });
87 }
88 }
89 }