Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 052cba1f authored by bkchoi's avatar bkchoi
Browse files

Fix the infinite loop bug for AndroidFuture.ThenCombine.

The bug was found and fixed in
android.car.util.concurrent.AndroidFuture. The same fix is being
duplicated from commit 9dcaf6862035676b2574e92cb72cba67ff0a879b.

Bug: 218377773

Test: atest com.android.internal.infra.AndroidFutureTest

Change-Id: I1e13d512a449a7330c74ed06f6afd90e3c4f9493
parent d0e75eb2
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -455,7 +455,14 @@ public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable
            if (mSourceU != null) {
                // T done
                mResultT = (T) res;
                mSourceU.whenComplete(this);

                // Subscribe to the second job completion.
                mSourceU.whenComplete((r, e) -> {
                    // Mark the first job completion by setting mSourceU to null, so that next time
                    // the execution flow goes to the else case below.
                    mSourceU = null;
                    accept(r, e);
                });
            } else {
                // U done
                try {
+32 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import org.junit.runner.RunWith;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.function.BiFunction;

/**
 * Unit test for {@link AndroidFuture}.
@@ -154,4 +155,35 @@ public class AndroidFutureTest {
                expectThrows(ExecutionException.class, future1::get);
        assertThat(executionException.getCause()).isInstanceOf(UnsupportedOperationException.class);
    }

    @Test
    public void testThenCombine() throws Exception {
        String nearFutureString = "near future comes";
        AndroidFuture<String> nearFuture = AndroidFuture.supply(() -> nearFutureString);
        String farFutureString = " before far future.";
        AndroidFuture<String> farFuture = AndroidFuture.supply(() -> farFutureString);
        AndroidFuture<String> combinedFuture =
                nearFuture.thenCombine(farFuture, ((s1, s2) -> s1 + s2));

        assertThat(combinedFuture.get()).isEqualTo(nearFutureString + farFutureString);
    }

    @Test
    public void testThenCombine_functionThrowingException() throws Exception {
        String nearFutureString = "near future comes";
        AndroidFuture<String> nearFuture = AndroidFuture.supply(() -> nearFutureString);
        String farFutureString = " before far future.";
        AndroidFuture<String> farFuture = AndroidFuture.supply(() -> farFutureString);
        UnsupportedOperationException exception = new UnsupportedOperationException(
                "Unsupported operation exception thrown!");
        BiFunction<String, String, String> throwingFunction = (s1, s2) -> {
            throw exception;
        };
        AndroidFuture<String> combinedFuture = nearFuture.thenCombine(farFuture, throwingFunction);

        ExecutionException thrown = expectThrows(ExecutionException.class,
                () -> combinedFuture.get());

        assertThat(thrown.getCause()).isSameInstanceAs(exception);
    }
}