From c2c5970efbc0a6411cbcdfe14f303ef6ee9156c2 Mon Sep 17 00:00:00 2001 From: wang007 <704450642@qq.com> Date: Thu, 13 May 2021 01:35:29 +0800 Subject: [PATCH] Fix FutureIml tryComplete. When complete error is regarded as a normal result, the Listener's complete result is inconsistent --- .../io/vertx/core/impl/future/FutureImpl.java | 27 ++++++++++++------- src/test/java/io/vertx/core/FutureTest.java | 15 +++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/vertx/core/impl/future/FutureImpl.java b/src/main/java/io/vertx/core/impl/future/FutureImpl.java index 9424d690e1f..de356a6f93c 100644 --- a/src/main/java/io/vertx/core/impl/future/FutureImpl.java +++ b/src/main/java/io/vertx/core/impl/future/FutureImpl.java @@ -50,28 +50,28 @@ class FutureImpl extends FutureBase { * The result of the operation. This will be null if the operation failed. */ public synchronized T result() { - return value instanceof Throwable ? null : value == NULL_VALUE ? null : (T) value; + return value instanceof CauseHolder ? null : value == NULL_VALUE ? null : (T) value; } /** * An exception describing failure. This will be null if the operation succeeded. */ public synchronized Throwable cause() { - return value instanceof Throwable ? (Throwable) value : null; + return value instanceof CauseHolder ? ((CauseHolder)value).cause : null; } /** * Did it succeed? */ public synchronized boolean succeeded() { - return value != null && !(value instanceof Throwable); + return value != null && !(value instanceof CauseHolder); } /** * Did it fail? */ public synchronized boolean failed() { - return value instanceof Throwable; + return value instanceof CauseHolder; } /** @@ -155,8 +155,8 @@ public void addListener(Listener listener) { return; } } - if (v instanceof Throwable) { - emitFailure((Throwable) v, listener); + if (v instanceof CauseHolder) { + emitFailure(((CauseHolder)v).cause, listener); } else { if (v == NULL_VALUE) { v = null; @@ -190,7 +190,7 @@ public boolean tryFail(Throwable cause) { if (value != null) { return false; } - value = cause; + value = new CauseHolder(cause); l = listener; listener = null; } @@ -203,8 +203,8 @@ public boolean tryFail(Throwable cause) { @Override public String toString() { synchronized (this) { - if (value instanceof Throwable) { - return "Future{cause=" + ((Throwable)value).getMessage() + "}"; + if (value instanceof CauseHolder) { + return "Future{cause=" + ((CauseHolder)value).cause.getMessage() + "}"; } if (value != null) { if (value == NULL_VALUE) { @@ -237,4 +237,13 @@ public void onFailure(Throwable failure) { } } } + + private static class CauseHolder { + + private final Throwable cause; + + CauseHolder(Throwable cause) { + this.cause = cause; + } + } } diff --git a/src/test/java/io/vertx/core/FutureTest.java b/src/test/java/io/vertx/core/FutureTest.java index 8c47616b36b..4634f38123f 100644 --- a/src/test/java/io/vertx/core/FutureTest.java +++ b/src/test/java/io/vertx/core/FutureTest.java @@ -209,6 +209,21 @@ public void testFailureFutureWithNullFailure() { assertNull(failure.getMessage()); } + @Test + public void testCompleteCause() { + Throwable object = new RuntimeException(); + Promise promise = Promise.promise(); + AtomicReference r1 = new AtomicReference<>(); + AtomicReference r2 = new AtomicReference<>(); + promise.future().onSuccess(v -> r1.set(true)).onFailure(v -> r1.set(false)); + Checker checker = new Checker<>(promise.future()); + promise.complete(object); + checker.assertSucceeded(object); + promise.future().onSuccess(v -> r2.set(true)).onFailure(v -> r2.set(false)); + assertTrue(r1.get()); + assertTrue(r2.get()); + } + @Test public void testComposeSuccessToSuccess() { AtomicReference ref = new AtomicReference<>();