1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
33
34
35
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
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
100 testRunOnPopulatedList();
101
102
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 }