11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 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.util.concurrent.MoreExecutors.sameThreadExecutor; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.testing.NullPointerTester; 220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.util.concurrent.ExecutionList; 230888a09821a98ac0680fad765217302858e70fa4Paul Duffin 240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.TestCase; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CountDownLatch; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executor; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executors; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit; 307dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.concurrent.atomic.AtomicInteger; 317dd252788645e940eada959bdde927426e2531c9Paul Duffin 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unit tests for {@link ExecutionList}. 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Nishant Thakkar 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Sven Mawson 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class ExecutionListTest extends TestCase { 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 407dd252788645e940eada959bdde927426e2531c9Paul Duffin private final ExecutionList list = new ExecutionList(); 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRunOnPopulatedList() throws Exception { 437dd252788645e940eada959bdde927426e2531c9Paul Duffin Executor exec = Executors.newCachedThreadPool(); 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CountDownLatch countDownLatch = new CountDownLatch(3); 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert list.add(new MockRunnable(countDownLatch), exec); 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert list.add(new MockRunnable(countDownLatch), exec); 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert list.add(new MockRunnable(countDownLatch), exec); 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(countDownLatch.getCount(), 3L); 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert list.execute(); 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Verify that all of the runnables execute in a reasonable amount of time. 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS)); 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 567dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testExecute_idempotent() { 577dd252788645e940eada959bdde927426e2531c9Paul Duffin final AtomicInteger runCalled = new AtomicInteger(); 587dd252788645e940eada959bdde927426e2531c9Paul Duffin list.add(new Runnable() { 597dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public void run() { 607dd252788645e940eada959bdde927426e2531c9Paul Duffin runCalled.getAndIncrement(); 617dd252788645e940eada959bdde927426e2531c9Paul Duffin } 627dd252788645e940eada959bdde927426e2531c9Paul Duffin }, MoreExecutors.sameThreadExecutor()); 637dd252788645e940eada959bdde927426e2531c9Paul Duffin list.execute(); 647dd252788645e940eada959bdde927426e2531c9Paul Duffin assertEquals(1, runCalled.get()); 657dd252788645e940eada959bdde927426e2531c9Paul Duffin list.execute(); 667dd252788645e940eada959bdde927426e2531c9Paul Duffin assertEquals(1, runCalled.get()); 677dd252788645e940eada959bdde927426e2531c9Paul Duffin } 687dd252788645e940eada959bdde927426e2531c9Paul Duffin 697dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testExecute_idempotentConcurrently() throws InterruptedException { 707dd252788645e940eada959bdde927426e2531c9Paul Duffin final CountDownLatch okayToRun = new CountDownLatch(1); 717dd252788645e940eada959bdde927426e2531c9Paul Duffin final AtomicInteger runCalled = new AtomicInteger(); 727dd252788645e940eada959bdde927426e2531c9Paul Duffin list.add(new Runnable() { 737dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public void run() { 747dd252788645e940eada959bdde927426e2531c9Paul Duffin try { 757dd252788645e940eada959bdde927426e2531c9Paul Duffin okayToRun.await(); 767dd252788645e940eada959bdde927426e2531c9Paul Duffin } catch (InterruptedException e) { 777dd252788645e940eada959bdde927426e2531c9Paul Duffin Thread.currentThread().interrupt(); 787dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new RuntimeException(e); 797dd252788645e940eada959bdde927426e2531c9Paul Duffin } 807dd252788645e940eada959bdde927426e2531c9Paul Duffin runCalled.getAndIncrement(); 817dd252788645e940eada959bdde927426e2531c9Paul Duffin } 827dd252788645e940eada959bdde927426e2531c9Paul Duffin }, MoreExecutors.sameThreadExecutor()); 837dd252788645e940eada959bdde927426e2531c9Paul Duffin Runnable execute = new Runnable() { 847dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public void run() { 857dd252788645e940eada959bdde927426e2531c9Paul Duffin list.execute(); 867dd252788645e940eada959bdde927426e2531c9Paul Duffin } 877dd252788645e940eada959bdde927426e2531c9Paul Duffin }; 887dd252788645e940eada959bdde927426e2531c9Paul Duffin Thread thread1 = new Thread(execute); 897dd252788645e940eada959bdde927426e2531c9Paul Duffin Thread thread2 = new Thread(execute); 907dd252788645e940eada959bdde927426e2531c9Paul Duffin thread1.start(); 917dd252788645e940eada959bdde927426e2531c9Paul Duffin thread2.start(); 927dd252788645e940eada959bdde927426e2531c9Paul Duffin assertEquals(0, runCalled.get()); 937dd252788645e940eada959bdde927426e2531c9Paul Duffin okayToRun.countDown(); 947dd252788645e940eada959bdde927426e2531c9Paul Duffin thread1.join(); 957dd252788645e940eada959bdde927426e2531c9Paul Duffin thread2.join(); 967dd252788645e940eada959bdde927426e2531c9Paul Duffin assertEquals(1, runCalled.get()); 977dd252788645e940eada959bdde927426e2531c9Paul Duffin } 987dd252788645e940eada959bdde927426e2531c9Paul Duffin 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testAddAfterRun() throws Exception { 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Run the previous test 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testRunOnPopulatedList(); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // If it passed, then verify an Add will be executed without calling run 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CountDownLatch countDownLatch = new CountDownLatch(1); 1057dd252788645e940eada959bdde927426e2531c9Paul Duffin list.add(new MockRunnable(countDownLatch), Executors.newCachedThreadPool()); 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS)); 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin public void testOrdering() throws Exception { 1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin final AtomicInteger integer = new AtomicInteger(); 1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin for (int i = 0; i < 10; i++) { 1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin final int expectedCount = i; 1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin list.add( 1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin new Runnable() { 1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public void run() { 1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin integer.compareAndSet(expectedCount, expectedCount + 1); 1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin }, 1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin MoreExecutors.sameThreadExecutor()); 1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin list.execute(); 1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin assertEquals(10, integer.get()); 1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class MockRunnable implements Runnable { 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CountDownLatch countDownLatch; 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MockRunnable(CountDownLatch countDownLatch) { 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.countDownLatch = countDownLatch; 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1327dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public void run() { 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert countDownLatch.countDown(); 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testExceptionsCaught() { 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert list.add(THROWING_RUNNABLE, sameThreadExecutor()); 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert list.execute(); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert list.add(THROWING_RUNNABLE, sameThreadExecutor()); 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1437dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testNulls() { 1447dd252788645e940eada959bdde927426e2531c9Paul Duffin new NullPointerTester().testAllPublicInstanceMethods(new ExecutionList()); 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final Runnable THROWING_RUNNABLE = new Runnable() { 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public void run() { 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException(); 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 153