diff --git a/api-common-java/src/main/java/com/google/api/core/ApiFutureToListenableFuture.java b/api-common-java/src/main/java/com/google/api/core/ApiFutureToListenableFuture.java index e7c6e9f78a..92f5cf7471 100644 --- a/api-common-java/src/main/java/com/google/api/core/ApiFutureToListenableFuture.java +++ b/api-common-java/src/main/java/com/google/api/core/ApiFutureToListenableFuture.java @@ -29,6 +29,7 @@ */ package com.google.api.core; +import com.google.common.base.MoreObjects; import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -74,4 +75,11 @@ public V get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { return apiFuture.get(l, timeUnit); } + + @Override + public String toString() { + return MoreObjects.toStringHelper(ApiFutureToListenableFuture.class.getSimpleName()) + .add("apiFuture", apiFuture) + .toString(); + } } diff --git a/api-common-java/src/main/java/com/google/api/core/ListenableFutureToApiFuture.java b/api-common-java/src/main/java/com/google/api/core/ListenableFutureToApiFuture.java index fe77f56d30..5d59da1b71 100644 --- a/api-common-java/src/main/java/com/google/api/core/ListenableFutureToApiFuture.java +++ b/api-common-java/src/main/java/com/google/api/core/ListenableFutureToApiFuture.java @@ -29,6 +29,7 @@ */ package com.google.api.core; +import com.google.common.base.MoreObjects; import com.google.common.util.concurrent.ForwardingListenableFuture.SimpleForwardingListenableFuture; import com.google.common.util.concurrent.ListenableFuture; @@ -39,4 +40,10 @@ public class ListenableFutureToApiFuture extends SimpleForwardingListenableFu public ListenableFutureToApiFuture(ListenableFuture delegate) { super(delegate); } + + public String toString() { + return MoreObjects.toStringHelper(ListenableFutureToApiFuture.class) + .add("delegate", delegate()) + .toString(); + } } diff --git a/api-common-java/src/test/java/com/google/api/core/ApiFutureToListenableFutureTest.java b/api-common-java/src/test/java/com/google/api/core/ApiFutureToListenableFutureTest.java new file mode 100644 index 0000000000..e835c1cd27 --- /dev/null +++ b/api-common-java/src/test/java/com/google/api/core/ApiFutureToListenableFutureTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.core; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.jupiter.api.Test; + +class ApiFutureToListenableFutureTest { + @Test + void testThatInnerToStringIsNotLost() { + String customInnerToString = "my-custom-inner-tostring"; + ApiFuture apiFuture = + new AbstractApiFuture() { + @Override + public String toString() { + return customInnerToString; + } + }; + ApiFutureToListenableFuture listenableFuture = + new ApiFutureToListenableFuture<>(apiFuture); + assertThat(listenableFuture.toString()).contains(customInnerToString); + } +} diff --git a/api-common-java/src/test/java/com/google/api/core/ListenableFutureToApiFutureTest.java b/api-common-java/src/test/java/com/google/api/core/ListenableFutureToApiFutureTest.java index 707f7aae0f..3e8d2827d3 100644 --- a/api-common-java/src/test/java/com/google/api/core/ListenableFutureToApiFutureTest.java +++ b/api-common-java/src/test/java/com/google/api/core/ListenableFutureToApiFutureTest.java @@ -30,6 +30,8 @@ package com.google.api.core; import com.google.common.truth.Truth; +import com.google.common.util.concurrent.AbstractFuture; +import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import org.junit.jupiter.api.Test; @@ -42,4 +44,20 @@ void testGet() throws Exception { future.set(3); Truth.assertThat(apiFuture.get()).isEqualTo(3); } + + @Test + void testToStringShowsUnderlyingFutureToString() { + String customInnerFutureDesc = "my-custom-toString-impl"; + ListenableFuture listenableFuture = + new AbstractFuture() { + @Override + public String toString() { + return customInnerFutureDesc; + } + }; + + ListenableFutureToApiFuture apiFuture = + new ListenableFutureToApiFuture<>(listenableFuture); + Truth.assertThat(apiFuture.toString()).contains(customInnerFutureDesc); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/retrying/BasicRetryingFuture.java b/gax-java/gax/src/main/java/com/google/api/gax/retrying/BasicRetryingFuture.java index c1a7ad8898..ccf1bfe11c 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/retrying/BasicRetryingFuture.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/retrying/BasicRetryingFuture.java @@ -35,6 +35,7 @@ import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; import com.google.api.gax.tracing.ApiTracer; +import com.google.common.base.MoreObjects; import com.google.common.util.concurrent.AbstractFuture; import com.google.common.util.concurrent.MoreExecutors; import java.util.concurrent.Callable; @@ -265,6 +266,16 @@ private void setAttemptResult(Throwable throwable, ResponseT response, boolean s } } + @Override + public String toString() { + return MoreObjects.toStringHelper(this.getClass()) + .add("super", pendingToString()) + .add("latestCompletedAttemptResult", this.latestCompletedAttemptResult) + .add("attemptResult", this.attemptResult) + .add("attemptSettings", this.attemptSettings) + .toString(); + } + private class CompletionListener implements Runnable { @Override public void run() {