1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.util.concurrent; 18 19 import static com.google.common.util.concurrent.MoreExecutors.directExecutor; 20 21 import com.google.common.testing.NullPointerTester; 22 23 import junit.framework.TestCase; 24 25 import java.util.concurrent.CountDownLatch; 26 import java.util.concurrent.Executor; 27 import java.util.concurrent.Executors; 28 import java.util.concurrent.TimeUnit; 29 import java.util.concurrent.atomic.AtomicInteger; 30 31 /** 32 * Unit tests for {@link ExecutionList}. 33 * 34 * @author Nishant Thakkar 35 * @author Sven Mawson 36 */ 37 public class ExecutionListTest extends TestCase { 38 39 private final ExecutionList list = new ExecutionList(); 40 41 public void testRunOnPopulatedList() throws Exception { 42 Executor exec = Executors.newCachedThreadPool(); 43 CountDownLatch countDownLatch = new CountDownLatch(3); 44 list.add(new MockRunnable(countDownLatch), exec); 45 list.add(new MockRunnable(countDownLatch), exec); 46 list.add(new MockRunnable(countDownLatch), exec); 47 assertEquals(countDownLatch.getCount(), 3L); 48 49 list.execute(); 50 51 // Verify that all of the runnables execute in a reasonable amount of time. 52 assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS)); 53 } 54 55 public void testExecute_idempotent() { 56 final AtomicInteger runCalled = new AtomicInteger(); 57 list.add(new Runnable() { 58 @Override public void run() { 59 runCalled.getAndIncrement(); 60 } 61 }, directExecutor()); 62 list.execute(); 63 assertEquals(1, runCalled.get()); 64 list.execute(); 65 assertEquals(1, runCalled.get()); 66 } 67 68 public void testExecute_idempotentConcurrently() throws InterruptedException { 69 final CountDownLatch okayToRun = new CountDownLatch(1); 70 final AtomicInteger runCalled = new AtomicInteger(); 71 list.add(new Runnable() { 72 @Override public void run() { 73 try { 74 okayToRun.await(); 75 } catch (InterruptedException e) { 76 Thread.currentThread().interrupt(); 77 throw new RuntimeException(e); 78 } 79 runCalled.getAndIncrement(); 80 } 81 }, directExecutor()); 82 Runnable execute = new Runnable() { 83 @Override public void run() { 84 list.execute(); 85 } 86 }; 87 Thread thread1 = new Thread(execute); 88 Thread thread2 = new Thread(execute); 89 thread1.start(); 90 thread2.start(); 91 assertEquals(0, runCalled.get()); 92 okayToRun.countDown(); 93 thread1.join(); 94 thread2.join(); 95 assertEquals(1, runCalled.get()); 96 } 97 98 public void testAddAfterRun() throws Exception { 99 // Run the previous test 100 testRunOnPopulatedList(); 101 102 // If it passed, then verify an Add will be executed without calling run 103 CountDownLatch countDownLatch = new CountDownLatch(1); 104 list.add(new MockRunnable(countDownLatch), Executors.newCachedThreadPool()); 105 assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS)); 106 } 107 108 public void testOrdering() throws Exception { 109 final AtomicInteger integer = new AtomicInteger(); 110 for (int i = 0; i < 10; i++) { 111 final int expectedCount = i; 112 list.add( 113 new Runnable() { 114 @Override public void run() { 115 integer.compareAndSet(expectedCount, expectedCount + 1); 116 } 117 }, 118 MoreExecutors.directExecutor()); 119 } 120 list.execute(); 121 assertEquals(10, integer.get()); 122 } 123 124 private class MockRunnable implements Runnable { 125 CountDownLatch countDownLatch; 126 127 MockRunnable(CountDownLatch countDownLatch) { 128 this.countDownLatch = countDownLatch; 129 } 130 131 @Override public void run() { 132 countDownLatch.countDown(); 133 } 134 } 135 136 public void testExceptionsCaught() { 137 list.add(THROWING_RUNNABLE, directExecutor()); 138 list.execute(); 139 list.add(THROWING_RUNNABLE, directExecutor()); 140 } 141 142 public void testNulls() { 143 new NullPointerTester().testAllPublicInstanceMethods(new ExecutionList()); 144 } 145 146 private static final Runnable THROWING_RUNNABLE = new Runnable() { 147 @Override public void run() { 148 throw new RuntimeException(); 149 } 150 }; 151 } 152