1 package com.atlassian.vcache.internal.test;
2
3 import org.hamcrest.Description;
4 import org.hamcrest.Factory;
5 import org.hamcrest.Matcher;
6 import org.hamcrest.TypeSafeMatcher;
7
8 import java.util.Optional;
9 import java.util.concurrent.CompletableFuture;
10 import java.util.concurrent.CompletionStage;
11
12 import static java.util.Objects.requireNonNull;
13
14
15
16
17
18
19 public class CompletionStageSuccessful<T> extends TypeSafeMatcher<CompletionStage<T>> {
20 private final Optional<Matcher<T>> valueMatcher;
21
22 public CompletionStageSuccessful(Optional<Matcher<T>> valueMatcher) {
23 this.valueMatcher = requireNonNull(valueMatcher);
24 }
25
26 @Override
27 protected boolean matchesSafely(CompletionStage<T> stage) {
28 try {
29 final CompletableFuture<T> future = stage.toCompletableFuture();
30 return !future.isCompletedExceptionally()
31 && (!valueMatcher.isPresent() || valueMatcher.get().matches(future.get()));
32 } catch (Exception e) {
33 return false;
34 }
35 }
36
37 @Override
38 public void describeTo(Description description) {
39 if (valueMatcher.isPresent()) {
40 description.appendText("successful result which ");
41 description.appendDescriptionOf(valueMatcher.get());
42 } else {
43 description.appendText("successful result");
44 }
45 }
46
47 @Override
48 protected void describeMismatchSafely(CompletionStage<T> stage, Description mismatchDescription) {
49 final CompletableFuture<T> future = stage.toCompletableFuture();
50
51 if (future.isCompletedExceptionally()) {
52 mismatchDescription.appendText("isCompletedExceptionally() is true");
53 } else if (valueMatcher.isPresent()) {
54 try {
55 mismatchDescription.appendText("result was " + future.get());
56 } catch (Exception e) {
57 mismatchDescription.appendText("get() throws " + e);
58 }
59 }
60 }
61
62 @Factory
63 public static <T> Matcher<CompletionStage<T>> successfulWith(Matcher<T> valueMatcher) {
64 return new CompletionStageSuccessful<>(Optional.of(valueMatcher));
65 }
66
67 @Factory
68 public static <T> Matcher<CompletionStage<T>> successful() {
69 return new CompletionStageSuccessful<>(Optional.empty());
70 }
71 }