public static <T> ListenableFuture<T> toListenableFuture(Task<T> task) {
    // Setup cancellation propagation from ListenableFuture -> Task.
    SettableFuture<T> listenableFuture = new SettableFuture<T>() {
      @Override
      public boolean cancel(boolean mayInterruptIfRunning) {
        return super.cancel(mayInterruptIfRunning) && task.cancel(new CancellationException());
      }

      @Override
      public boolean setException(Throwable ex) {
        if (!task.isDone() && ex instanceof CancellationException) {
          task.cancel((CancellationException) ex);
        }
        return super.setException(ex);
      }
    };

    // Setup forward event propagation Task -> ListenableFuture.
    task.addListener(promise -> {
      if (!promise.isFailed()) {
        listenableFuture.set(promise.get());
      }
      else {
        if (promise.getError() instanceof com.linkedin.parseq.CancellationException) {
          listenableFuture.cancel(true);
        } else {
          listenableFuture.setException(promise.getError());
        }
      }
    });

    return listenableFuture;
  }
@Test
  public void testToListenableFuture() throws Exception {
    Task<String> task;

    final SettablePromise<String> p = Promises.settable();
    task = Task.async("test", () -> p);

    ListenableFuture<String> future = ListenableFutureUtil.toListenableFuture(task);

    // Test cancel propagation from ListenableFuture to task
    future.cancel(true);
    runUntilComplete(task);
    Assert.assertTrue(task.isDone());
    Assert.assertTrue(task.isFailed());
    Assert.assertEquals(task.getError().getCause().getClass(), CancellationException.class);

    final SettablePromise<String>  p1 = Promises.settable();
    task = Task.async("test", () -> p1);

    future = ListenableFutureUtil.toListenableFuture(task);

    // Test successful completion of task.
    p1.done("COMPLETED");
    runUntilComplete(task);
    Assert.assertTrue(future.isDone());
    Assert.assertEquals(future.get(), "COMPLETED");

    final SettablePromise<String> p2 = Promises.settable();
    task = Task.async("test", () -> p2);
    future = ListenableFutureUtil.toListenableFuture(task);

    p2.fail(new RuntimeException("Test"));
    runUntilComplete(task);
    Assert.assertTrue(future.isDone());
    Assert.assertTrue(future.isDone());
    try {
      future.get();
      Assert.fail("ExecutionException not thrown");
    } catch (ExecutionException e) {
      Assert.assertEquals(e.getCause().getClass(), RuntimeException.class);
      Assert.assertEquals(e.getCause().getMessage(), "Test");
    }

    final SettablePromise<String> p3 = Promises.settable();
    task = Task.async("test", () -> p3);
    future = ListenableFutureUtil.toListenableFuture(task);

    // Test cancellation of task.
    task.cancel(new RuntimeException("Cancelled"));
    Assert.assertTrue(future.isDone());
    Assert.assertTrue(future.isCancelled());
    try {
      future.get();
      Assert.fail("Cancellation Exception not thrown");
    } catch (CancellationException e) {
      // Ignored since we expected a cancellation exception!
    } catch (Throwable e) {
      Assert.fail("Unexpected Exception thrown", e);
    }
  }