CallbackToFutureAdapter { @NonNull public static <T> ListenableFuture<T> getFuture(@NonNull Resolver<T> callback) { Completer<T> completer = new Completer<>(); SafeFuture<T> safeFuture = new SafeFuture<>(completer); completer.future = safeFuture; completer.tag = callback.getClass(); final Object tag; try { tag = callback.attachCompleter(completer); if (tag != null) { completer.tag = tag; } } catch (Exception e) { safeFuture.setException(e); } return safeFuture; } private  CallbackToFutureAdapter(); @NonNull static ListenableFuture<T> getFuture(@NonNull Resolver<T> callback);  }
@Test public void testSuccess() { final AtomicReference<Completer<String>> completerRef = new AtomicReference<>(); ListenableFuture<String> future = CallbackToFutureAdapter.getFuture( new CallbackToFutureAdapter.Resolver<String>() { @Override public Object attachCompleter(Completer<String> completer) { completerRef.set(completer); return "my special callback"; } }); assertThat(future.isDone()).isFalse(); assertThat(future.toString()).contains("my special callback"); completerRef.get().set("my special result"); assertFutureCompletedWith(future, "my special result"); }
@Test public void testCancellationListenersCalledOnFutureCancelled() { final AtomicReference<Completer<String>> completerRef = new AtomicReference<>(); final AtomicBoolean wasCalled = new AtomicBoolean(); ListenableFuture<String> future = CallbackToFutureAdapter.getFuture( new CallbackToFutureAdapter.Resolver<String>() { @Override public Object attachCompleter(Completer<String> completer) { completer.addCancellationListener(new Runnable() { @Override public void run() { wasCalled.set(true); } }, DirectExecutor.INSTANCE); completerRef.set(completer); return null; } }); assertThat(future.cancel(true)).isTrue(); assertThat(wasCalled.get()).isTrue(); assertThat(completerRef.get().setCancelled()).isFalse(); }
@Test public void testCancellationListenersNotCalledOnCompleterCancelled() { final AtomicBoolean wasCalled = new AtomicBoolean(); ListenableFuture<String> future = CallbackToFutureAdapter.getFuture( new CallbackToFutureAdapter.Resolver<String>() { @Override public Object attachCompleter(Completer<String> completer) { completer.addCancellationListener(new Runnable() { @Override public void run() { wasCalled.set(true); } }, DirectExecutor.INSTANCE); completer.setCancelled(); return null; } }); assertThat(future.isCancelled()).isTrue(); assertThat(wasCalled.get()).isFalse(); }
@Test public void testNoRecursiveToString() { final AtomicReference<Runnable> callbackRef = new AtomicReference<>(); ListenableFuture<String> future = CallbackToFutureAdapter.getFuture( new CallbackToFutureAdapter.Resolver<String>() { @Override public Object attachCompleter(final Completer<String> completer) { Runnable callback = new Runnable() { @Override public void run() { completer.set("my special result"); } @Override public String toString() { return "custom callback, completer=[" + completer + "]"; } }; callbackRef.set(callback); return callback; } }); assertThat(future.isDone()).isFalse(); assertThat(future.toString()).contains("custom callback"); callbackRef.get().run(); assertFutureCompletedWith(future, "my special result"); }