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