11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkState;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.util.concurrent.Futures.immediateFuture;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.util.concurrent.JdkFutureAdapters.listenInPoolThread;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.concurrent.Executors.newCachedThreadPool;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.concurrent.TimeUnit.SECONDS;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.testing.NullPointerTester;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.FuturesTest.ExecutorSpy;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.FuturesTest.SingleCallListener;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.AssertionFailedError;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CountDownLatch;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutorService;
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Future;
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit;
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unit tests for {@link JdkFutureAdapters}.
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Sven Mawson
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kurt Alfred Kluever
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class JdkFutureAdaptersTest extends TestCase {
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final String DATA1 = "data";
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testListenInPoolThreadReturnsSameFuture() throws Exception {
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ListenableFuture<String> listenableFuture = immediateFuture(DATA1);
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertSame(listenableFuture, listenInPoolThread(listenableFuture));
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testListenInPoolThreadIgnoresExecutorWhenDelegateIsDone()
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws Exception {
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    NonListenableSettableFuture<String> abstractFuture =
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        NonListenableSettableFuture.create();
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    abstractFuture.set(DATA1);
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ExecutorSpy spy = new ExecutorSpy(sameThreadExecutor());
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ListenableFuture<String> listenableFuture =
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        listenInPoolThread(abstractFuture, spy);
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SingleCallListener singleCallListener = new SingleCallListener();
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    singleCallListener.expectCall();
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(spy.wasExecuted);
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(singleCallListener.wasCalled());
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(listenableFuture.isDone()); // We call AbstractFuture#set above.
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // #addListener() will run the listener immediately because the Future is
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // already finished (we explicitly set the result of it above).
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    listenableFuture.addListener(singleCallListener, sameThreadExecutor());
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(DATA1, listenableFuture.get());
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // 'spy' should have been ignored since 'abstractFuture' was done before
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // a listener was added.
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(spy.wasExecuted);
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(singleCallListener.wasCalled());
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(listenableFuture.isDone());
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testListenInPoolThreadUsesGivenExecutor() throws Exception {
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ExecutorService executorService = newCachedThreadPool(
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new ThreadFactoryBuilder().setDaemon(true).build());
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    NonListenableSettableFuture<String> abstractFuture =
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        NonListenableSettableFuture.create();
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ExecutorSpy spy = new ExecutorSpy(executorService);
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ListenableFuture<String> listenableFuture =
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        listenInPoolThread(abstractFuture, spy);
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SingleCallListener singleCallListener = new SingleCallListener();
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    singleCallListener.expectCall();
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(spy.wasExecuted);
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(singleCallListener.wasCalled());
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(listenableFuture.isDone());
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    listenableFuture.addListener(singleCallListener, executorService);
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    abstractFuture.set(DATA1);
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(DATA1, listenableFuture.get());
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    singleCallListener.waitForCall();
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(spy.wasExecuted);
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(singleCallListener.wasCalled());
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(listenableFuture.isDone());
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A Future that doesn't implement ListenableFuture, useful for testing
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * listenInPoolThread.
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class NonListenableSettableFuture<V>
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ForwardingFuture<V> {
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    static <V> NonListenableSettableFuture<V> create() {
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new NonListenableSettableFuture<V>();
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final SettableFuture<V> delegate = SettableFuture.create();
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected Future<V> delegate() {
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate;
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void set(V value) {
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      delegate.set(value);
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class RuntimeExceptionThrowingFuture<V>
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      implements Future<V> {
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch allowGetToComplete = new CountDownLatch(1);
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean cancel(boolean mayInterruptIfRunning) {
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionFailedError();
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get() throws InterruptedException {
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      /*
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * Wait a little to give us time to call addListener before the future's
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * value is set in addition to the call we'll make after then.
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       */
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      allowGetToComplete.await(1, SECONDS);
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new RuntimeException("expected, should be caught");
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get(long timeout, TimeUnit unit) {
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionFailedError();
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isCancelled() {
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionFailedError();
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isDone() {
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      /*
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * If isDone is true during the call to listenInPoolThread,
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * listenInPoolThread doesn't start a thread. Make sure it's false the
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * first time through (and forever after, since no one else cares about
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * it).
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       */
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class RecordingRunnable implements Runnable {
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch wasRun = new CountDownLatch(1);
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // synchronized so that checkState works as expected.
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public synchronized void run() {
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkState(wasRun.getCount() > 0);
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      wasRun.countDown();
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testListenInPoolThreadRunsListenerAfterRuntimeException()
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws Exception {
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    RuntimeExceptionThrowingFuture<String> input =
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new RuntimeExceptionThrowingFuture<String>();
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The compiler recognizes that "input instanceof ListenableFuture" is
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * impossible. We want the test, though, in case that changes in the future,
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * so we use isInstance instead.
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse("Can't test the main listenInPoolThread path "
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        + "if the input is already a ListenableFuture",
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ListenableFuture.class.isInstance(input));
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ListenableFuture<String> listenable = listenInPoolThread(input);
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * This will occur before the waiting get() in the
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * listenInPoolThread-spawned thread completes:
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    RecordingRunnable earlyListener = new RecordingRunnable();
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    listenable.addListener(earlyListener, sameThreadExecutor());
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    input.allowGetToComplete.countDown();
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Now give the get() thread time to finish:
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(earlyListener.wasRun.await(1, SECONDS));
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Now test an additional addListener call, which will be run in-thread:
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    RecordingRunnable lateListener = new RecordingRunnable();
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    listenable.addListener(lateListener, sameThreadExecutor());
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(lateListener.wasRun.await(1, SECONDS));
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNullArguments() throws Exception {
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    NullPointerTester tester = new NullPointerTester();
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    tester.setDefault(Future.class, immediateFuture(DATA1));
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    tester.testAllPublicStaticMethods(JdkFutureAdapters.class);
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
215