11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); you may not
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * use this file except in compliance with the License.  You may obtain a copy
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 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, WITHOUT
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * License for the specific language governing permissions and limitations under
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent.testing;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.ListenableFuture;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CancellationException;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CountDownLatch;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutionException;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutorService;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executors;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Future;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeoutException;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Abstract test case parent for anything implementing {@link ListenableFuture}.
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Tests the two get methods and the addListener method.
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Sven Mawson
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic abstract class AbstractListenableFutureTest extends TestCase {
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected CountDownLatch latch;
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected ListenableFuture<Boolean> future;
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected void setUp() throws Exception {
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Create a latch and a future that waits on the latch.
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    latch = new CountDownLatch(1);
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    future = createListenableFuture(Boolean.TRUE, null, latch);
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected void tearDown() throws Exception {
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Make sure we have no waiting threads.
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    latch.countDown();
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Constructs a listenable future with a value available after the latch
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * has counted down.
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected abstract <V> ListenableFuture<V> createListenableFuture(
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value, Exception except, CountDownLatch waitOn);
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Tests that the {@link Future#get()} method blocks until a value is
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * available.
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testGetBlocksUntilValueAvailable() throws Throwable {
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(future.isDone());
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(future.isCancelled());
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch successLatch = new CountDownLatch(1);
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Throwable[] badness = new Throwable[1];
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Wait on the future in a separate thread.
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    new Thread(new Runnable() {
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void run() {
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          assertSame(Boolean.TRUE, future.get());
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          successLatch.countDown();
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (Throwable t) {
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          t.printStackTrace();
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          badness[0] = t;
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }}).start();
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Release the future value.
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    latch.countDown();
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(successLatch.await(10, TimeUnit.SECONDS));
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (badness[0] != null) {
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw badness[0];
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(future.isDone());
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(future.isCancelled());
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Tests that the {@link Future#get(long, TimeUnit)} method times out
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * correctly.
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeoutOnGetWorksCorrectly() throws InterruptedException,
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ExecutionException {
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The task thread waits for the latch, so we expect a timeout here.
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      future.get(20, TimeUnit.MILLISECONDS);
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("Should have timed out trying to get the value.");
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TimeoutException expected) {
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Expected.
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      latch.countDown();
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Tests that a canceled future throws a cancellation exception.
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This method checks the cancel, isCancelled, and isDone methods.
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testCanceledFutureThrowsCancellation() throws Exception {
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(future.isDone());
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(future.isCancelled());
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch successLatch = new CountDownLatch(1);
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Run cancellation in a separate thread as an extra thread-safety test.
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    new Thread(new Runnable() {
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void run() {
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          future.get();
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (CancellationException expected) {
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          successLatch.countDown();
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (Exception ignored) {
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // All other errors are ignored, we expect a cancellation.
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }).start();
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(future.isDone());
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(future.isCancelled());
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    future.cancel(true);
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(future.isDone());
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(future.isCancelled());
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(successLatch.await(200, TimeUnit.MILLISECONDS));
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    latch.countDown();
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testListenersNotifiedOnError() throws Exception {
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch successLatch = new CountDownLatch(1);
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch listenerLatch = new CountDownLatch(1);
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ExecutorService exec = Executors.newCachedThreadPool();
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    future.addListener(new Runnable() {
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void run() {
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        listenerLatch.countDown();
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }, exec);
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    new Thread(new Runnable() {
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void run() {
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          future.get();
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (CancellationException expected) {
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          successLatch.countDown();
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (Exception ignored) {
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // No success latch count down.
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }).start();
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    future.cancel(true);
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(future.isCancelled());
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(future.isDone());
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(successLatch.await(200, TimeUnit.MILLISECONDS));
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(listenerLatch.await(200, TimeUnit.MILLISECONDS));
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    latch.countDown();
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    exec.shutdown();
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    exec.awaitTermination(100, TimeUnit.MILLISECONDS);
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Tests that all listeners complete, even if they were added before or after
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the future was finishing.  Also acts as a concurrency test to make sure the
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * locking is done correctly when a future is finishing so that no listeners
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * can be lost.
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testAllListenersCompleteSuccessfully()
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws InterruptedException, ExecutionException {
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ExecutorService exec = Executors.newCachedThreadPool();
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int listenerCount = 20;
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch listenerLatch = new CountDownLatch(listenerCount);
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Test that listeners added both before and after the value is available
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // get called correctly.
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < 20; i++) {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Right in the middle start up a thread to close the latch.
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (i == 10) {
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new Thread(new Runnable() {
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          public void run() {
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            latch.countDown();
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }).start();
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      future.addListener(new Runnable() {
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        public void run() {
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          listenerLatch.countDown();
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }, exec);
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertSame(Boolean.TRUE, future.get());
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Wait for the listener latch to complete.
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    listenerLatch.await(500, TimeUnit.MILLISECONDS);
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    exec.shutdown();
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    exec.awaitTermination(500, TimeUnit.MILLISECONDS);
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
247