This is an automated email from the ASF dual-hosted git repository.

apolovtsev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 0a9db0a2f3 IGNITE-21007 Add exception message matcher to 
CompletableFutureExceptionMatcher (#2914)
0a9db0a2f3 is described below

commit 0a9db0a2f36b7e2be2daa71bf8ada3ae71dfcdba
Author: Alexander Polovtcev <[email protected]>
AuthorDate: Mon Dec 4 09:46:54 2023 +0200

    IGNITE-21007 Add exception message matcher to 
CompletableFutureExceptionMatcher (#2914)
---
 .../CompletableFutureExceptionMatcher.java         | 103 +++++++++++++++------
 1 file changed, 76 insertions(+), 27 deletions(-)

diff --git 
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
 
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
index 197057c623..e64aee13f3 100644
--- 
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
+++ 
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
@@ -17,14 +17,13 @@
 
 package org.apache.ignite.internal.testframework.matchers;
 
+import static org.apache.ignite.internal.util.ExceptionUtils.unwrapCause;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.instanceOf;
 import static org.hamcrest.Matchers.is;
 
 import java.util.Arrays;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import org.hamcrest.Description;
@@ -37,7 +36,7 @@ import org.jetbrains.annotations.Nullable;
  */
 public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<CompletableFuture<?>> {
     /** Timeout in seconds. */
-    private static final int TIMEOUT_SECONDS = 1;
+    private static final int TIMEOUT_SECONDS = 10;
 
     /** Matcher to forward the exception of the completable future. */
     private final Matcher<? extends Exception> matcher;
@@ -48,7 +47,7 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
 
     private final TimeUnit timeUnit;
 
-    private final @Nullable Matcher<String> errorMessageFragmentMatcher;
+    private final @Nullable Matcher<String> errorMessageMatcher;
 
     /**
      * Constructor.
@@ -58,20 +57,20 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
      *     or every exception in the stacktrace is explored.
      * @param timeout Timeout value.
      * @param timeUnit Timeout unit.
-     * @param errorMessageFragment Expected error message fragment, {@code 
null} if any message is expected.
+     * @param errorMessageMatcher Expected error message Matcher, {@code null} 
if any message is expected.
      */
     private CompletableFutureExceptionMatcher(
             Matcher<? extends Exception> matcher,
             boolean inspectCause,
             int timeout,
             TimeUnit timeUnit,
-            @Nullable String errorMessageFragment
+            @Nullable Matcher<String> errorMessageMatcher
     ) {
         this.matcher = matcher;
         this.inspectCause = inspectCause;
         this.timeout = timeout;
         this.timeUnit = timeUnit;
-        this.errorMessageFragmentMatcher = errorMessageFragment == null ? null 
: containsString(errorMessageFragment);
+        this.errorMessageMatcher = errorMessageMatcher;
     }
 
     @Override
@@ -81,7 +80,7 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
 
             return false;
         } catch (Throwable e) {
-            Throwable unwrapped = unwrapThrowable(e);
+            Throwable unwrapped = unwrapCause(e);
 
             return inspectCause ? matchesWithCause(unwrapped) : 
matchesException(unwrapped);
         }
@@ -89,15 +88,15 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
 
     private boolean matchesException(Throwable throwable) {
         return matcher.matches(throwable)
-                && (errorMessageFragmentMatcher == null || 
errorMessageFragmentMatcher.matches(throwable.getMessage()));
+                && (errorMessageMatcher == null || 
errorMessageMatcher.matches(throwable.getMessage()));
     }
 
     @Override
     public void describeTo(Description description) {
         description.appendText("a future that completes with an exception that 
").appendDescriptionOf(matcher);
 
-        if (errorMessageFragmentMatcher != null) {
-            description.appendText(" and error message that contains 
").appendDescriptionOf(errorMessageFragmentMatcher);
+        if (errorMessageMatcher != null) {
+            description.appendText(" and error message that contains 
").appendDescriptionOf(errorMessageMatcher);
         }
     }
 
@@ -107,7 +106,7 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
             try {
                 item.join();
             } catch (Exception e) {
-                mismatchDescription.appendText("was completed exceptionally 
with ").appendValue(unwrapThrowable(e));
+                mismatchDescription.appendText("was completed exceptionally 
with ").appendValue(unwrapCause(e));
             }
         } else if (item.isDone()) {
             mismatchDescription.appendText("was completed successfully");
@@ -116,14 +115,6 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
         }
     }
 
-    private static Throwable unwrapThrowable(Throwable e) {
-        while (e instanceof ExecutionException || e instanceof 
CompletionException) {
-            e = e.getCause();
-        }
-
-        return e;
-    }
-
     private boolean matchesWithCause(Throwable e) {
         for (Throwable current = e; current != null; current = 
current.getCause()) {
             if (matchesException(current) || 
Arrays.stream(current.getSuppressed()).anyMatch(this::matchesWithCause)) {
@@ -142,7 +133,7 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
      * Creates a matcher that matches a future that completes exceptionally 
and the exception matches the nested matcher.
      */
     public static CompletableFutureExceptionMatcher willThrow(Matcher<? 
extends Exception> matcher) {
-        return new CompletableFutureExceptionMatcher(matcher, false, 
TIMEOUT_SECONDS, TimeUnit.SECONDS, null);
+        return willThrow(matcher, TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
 
     /**
@@ -153,7 +144,8 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
     }
 
     /**
-     * Creates a matcher that matches a future that completes exceptionally 
and the exception matches the nested matcher.
+     * Creates a matcher that matches a future that completes exceptionally 
and the exception matches the nested matcher and its
+     * message contains a given substring.
      */
     public static CompletableFutureExceptionMatcher willThrow(
             Matcher<? extends Exception> matcher,
@@ -161,9 +153,20 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
             TimeUnit timeUnit,
             String errorMessageFragment
     ) {
-        assert errorMessageFragment != null;
+        return willThrow(matcher, timeout, timeUnit, 
containsString(errorMessageFragment));
+    }
 
-        return new CompletableFutureExceptionMatcher(matcher, false, timeout, 
timeUnit, errorMessageFragment);
+    /**
+     * Creates a matcher that matches a future that completes exceptionally 
and the exception matches the nested matcher and its
+     * message matches {@code errorMessageMatcher}.
+     */
+    public static CompletableFutureExceptionMatcher willThrow(
+            Matcher<? extends Exception> matcher,
+            int timeout,
+            TimeUnit timeUnit,
+            Matcher<String> errorMessageMatcher
+    ) {
+        return new CompletableFutureExceptionMatcher(matcher, false, timeout, 
timeUnit, errorMessageMatcher);
     }
 
     /**
@@ -174,12 +177,21 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
     }
 
     /**
-     * Creates a matcher that matches a future that completes with an 
exception of the provided type.
+     * Creates a matcher that matches a future that completes with an 
exception of the provided type and its
+     * message contains a given substring.
      */
     public static CompletableFutureExceptionMatcher willThrow(Class<? extends 
Exception> cls, String errorMessageFragment) {
         return willThrow(cls, TIMEOUT_SECONDS, TimeUnit.SECONDS, 
errorMessageFragment);
     }
 
+    /**
+     * Creates a matcher that matches a future that completes with an 
exception of the provided type and its
+     * message matches {@code errorMessageMatcher}.
+     */
+    public static CompletableFutureExceptionMatcher willThrow(Class<? extends 
Exception> cls, Matcher<String> errorMessageMatcher) {
+        return willThrow(cls, TIMEOUT_SECONDS, TimeUnit.SECONDS, 
errorMessageMatcher);
+    }
+
     /**
      * Creates a matcher that matches a future that completes with an 
exception of the provided type.
      */
@@ -188,7 +200,8 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
     }
 
     /**
-     * Creates a matcher that matches a future that completes with an 
exception of the provided type.
+     * Creates a matcher that matches a future that completes with an 
exception of the provided type and its
+     * message contains a given substring.
      */
     public static CompletableFutureExceptionMatcher willThrow(
             Class<? extends Exception> cls,
@@ -199,6 +212,19 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
         return willThrow(is(instanceOf(cls)), timeout, timeUnit, 
errorMessageFragment);
     }
 
+    /**
+     * Creates a matcher that matches a future that completes with an 
exception of the provided type and its
+     * message matches {@code errorMessageMatcher}.
+     */
+    public static CompletableFutureExceptionMatcher willThrow(
+            Class<? extends Exception> cls,
+            int timeout,
+            TimeUnit timeUnit,
+            Matcher<String> errorMessageMatcher
+    ) {
+        return willThrow(is(instanceOf(cls)), timeout, timeUnit, 
errorMessageMatcher);
+    }
+
     /**
      * Creates a matcher that matches a future that completes exceptionally 
and decently fast.
      *
@@ -224,7 +250,30 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
      * Creates a matcher that matches a future that completes with an 
exception that has a given {@code cause} in the exception stacktrace.
      */
     public static CompletableFutureExceptionMatcher 
willThrowWithCauseOrSuppressed(Class<? extends Exception> cause) {
-        return new CompletableFutureExceptionMatcher(is(instanceOf(cause)), 
true, TIMEOUT_SECONDS, TimeUnit.SECONDS, null);
+        return new CompletableFutureExceptionMatcher(
+                is(instanceOf(cause)),
+                true,
+                TIMEOUT_SECONDS,
+                TimeUnit.SECONDS,
+                null
+        );
+    }
+
+    /**
+     * Creates a matcher that matches a future that completes with an 
exception that has a given {@code cause} in the exception stacktrace
+     * and its message contains a given substring.
+     */
+    public static CompletableFutureExceptionMatcher 
willThrowWithCauseOrSuppressed(
+            Class<? extends Exception> cause,
+            String errorMessageFragment
+    ) {
+        return new CompletableFutureExceptionMatcher(
+                is(instanceOf(cause)),
+                true,
+                TIMEOUT_SECONDS,
+                TimeUnit.SECONDS,
+                containsString(errorMessageFragment)
+        );
     }
 
     /**

Reply via email to