ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ExecutorsTest.java
Revision: 1.4
Committed: Sat Sep 20 18:20:07 2003 UTC (20 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.3: +137 -134 lines
Log Message:
Documentation scaffolding

File Contents

# Content
1 /*
2 * Written by members of JCP JSR-166 Expert Group and released to the
3 * public domain. Use, modify, and redistribute this code in any way
4 * without acknowledgement. Other contributors include Andrew Wright,
5 * Jeffrey Hayes, Pat Fischer, Mike Judd.
6 */
7
8
9 import junit.framework.*;
10 import java.util.*;
11 import java.util.concurrent.*;
12 import java.math.BigInteger;
13
14 public class ExecutorsTest extends JSR166TestCase{
15
16 public static void main(String[] args) {
17 junit.textui.TestRunner.run (suite());
18 }
19 public static Test suite() {
20 return new TestSuite(ExecutorsTest.class);
21 }
22
23 private static final String TEST_STRING = "a test string";
24
25 private static class MyTask implements Runnable {
26 public void run() { completed = true; }
27 public boolean isCompleted() { return completed; }
28 public void reset() { completed = false; }
29 private boolean completed = false;
30 }
31
32 private static class StringTask implements Callable<String> {
33 public String call() { return TEST_STRING; }
34 }
35
36 static class DirectExecutor implements Executor {
37 public void execute(Runnable r) {
38 r.run();
39 }
40 }
41
42 static class TimedCallable<T> implements Callable<T> {
43 private final Executor exec;
44 private final Callable<T> func;
45 private final long msecs;
46
47 TimedCallable(Executor exec, Callable<T> func, long msecs) {
48 this.exec = exec;
49 this.func = func;
50 this.msecs = msecs;
51 }
52
53 public T call() throws Exception {
54 Future<T> ftask = Executors.execute(exec, func);
55 try {
56 return ftask.get(msecs, TimeUnit.MILLISECONDS);
57 } finally {
58 ftask.cancel(true);
59 }
60 }
61 }
62
63
64 private static class Fib implements Callable<BigInteger> {
65 private final BigInteger n;
66 Fib(long n) {
67 if (n < 0) throw new IllegalArgumentException("need non-negative arg, but got " + n);
68 this.n = BigInteger.valueOf(n);
69 }
70 public BigInteger call() {
71 BigInteger f1 = BigInteger.ONE;
72 BigInteger f2 = f1;
73 for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) {
74 BigInteger t = f1.add(f2);
75 f1 = f2;
76 f2 = t;
77 }
78 return f1;
79 }
80 };
81
82
83
84 /**
85 * execute(Executor, Runnable) will throw
86 * RejectedExecutionException Attempting to execute a runnable on
87 * a full ThreadPool will cause such an exception here, up to 5
88 * runnables are attempted on a pool capable on handling one
89 * until it throws an exception
90 */
91 public void testExecute1() {
92 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
93 try {
94
95 for(int i = 0; i < 5; ++i){
96 Executors.execute(p, new MediumRunnable(), Boolean.TRUE);
97 }
98 shouldThrow();
99 } catch(RejectedExecutionException success){}
100 joinPool(p);
101 }
102
103 /**
104 * execute(Executor, Callable) will throw
105 * RejectedExecutionException Attempting to execute a callable on
106 * a full ThreadPool will cause such an exception here, up to 5
107 * runnables are attempted on a pool capable on handling one
108 * until it throws an exception
109 */
110 public void testExecute2() {
111 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
112 try {
113 for(int i = 0; i < 5; ++i) {
114 Executors.execute(p, new SmallCallable());
115 }
116 shouldThrow();
117 } catch(RejectedExecutionException e){}
118 joinPool(p);
119 }
120
121
122 /**
123 * invoke(Executor, Runnable) throws InterruptedException
124 * A single use of invoke starts that will wait long enough
125 * for the invoking thread to be interrupted
126 */
127 public void testInvoke2() {
128 final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
129 Thread t = new Thread(new Runnable() {
130 public void run() {
131 try {
132 Executors.invoke(p,new Runnable() {
133 public void run() {
134 try {
135 Thread.sleep(MEDIUM_DELAY_MS);
136 shouldThrow();
137 } catch(InterruptedException e){
138 }
139 }
140 });
141 } catch(InterruptedException success){
142 } catch(Exception e) {
143 unexpectedException();
144 }
145
146 }
147 });
148 try {
149 t.start();
150 Thread.sleep(SHORT_DELAY_MS);
151 t.interrupt();
152 } catch(Exception e){
153 unexpectedException();
154 }
155 joinPool(p);
156 }
157
158 /**
159 * invoke(Executor, Runnable) will throw
160 * ExecutionException An ExecutionException occurs when the
161 * underlying Runnable throws an exception, here the
162 * DivideByZeroException will cause an ExecutionException
163 */
164 public void testInvoke3() {
165 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
166 try {
167 Runnable r = new Runnable() {
168 public void run() {
169 int i = 5/0;
170 }
171 };
172
173 for(int i =0; i < 5; i++){
174 Executors.invoke(p,r);
175 }
176
177 shouldThrow();
178 } catch(ExecutionException success){
179 } catch(Exception e){
180 unexpectedException();
181 }
182 joinPool(p);
183 }
184
185
186
187 /**
188 * invoke(Executor, Callable) throws
189 * InterruptedException A single use of invoke starts that will
190 * wait long enough for the invoking thread to be interrupted
191 */
192 public void testInvoke5() {
193 final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
194
195 final Callable c = new Callable() {
196 public Object call() {
197 try {
198 Executors.invoke(p, new SmallCallable());
199 shouldThrow();
200 } catch(InterruptedException e){}
201 catch(RejectedExecutionException e2){}
202 catch(ExecutionException e3){}
203 return Boolean.TRUE;
204 }
205 };
206
207
208
209 Thread t = new Thread(new Runnable() {
210 public void run() {
211 try {
212 c.call();
213 } catch(Exception e){}
214 }
215 });
216 try {
217 t.start();
218 Thread.sleep(SHORT_DELAY_MS);
219 t.interrupt();
220 t.join();
221 } catch(InterruptedException e){
222 unexpectedException();
223 }
224
225 joinPool(p);
226 }
227
228 /**
229 * invoke(Executor, Callable) will throw ExecutionException
230 * An ExecutionException occurs when the underlying Runnable throws
231 * an exception, here the DivideByZeroException will cause an ExecutionException
232 */
233 public void testInvoke6() {
234 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
235
236 try {
237 Callable c = new Callable() {
238 public Object call() {
239 int i = 5/0;
240 return Boolean.TRUE;
241 }
242 };
243
244 for(int i =0; i < 5; i++){
245 Executors.invoke(p,c);
246 }
247
248 shouldThrow();
249 } catch(RejectedExecutionException e){}
250 catch(InterruptedException e2){}
251 catch(ExecutionException e3){}
252 joinPool(p);
253 }
254
255 /**
256 *
257 */
258 public void testExecuteRunnable () {
259 try {
260 Executor e = new DirectExecutor();
261 MyTask task = new MyTask();
262 assertFalse(task.isCompleted());
263 Future<String> future = Executors.execute(e, task, TEST_STRING);
264 String result = future.get();
265 assertTrue(task.isCompleted());
266 assertSame(TEST_STRING, result);
267 }
268 catch (ExecutionException ex) {
269 unexpectedException();
270 }
271 catch (InterruptedException ex) {
272 unexpectedException();
273 }
274 }
275
276 /**
277 *
278 */
279 public void testInvokeRunnable () {
280 try {
281 Executor e = new DirectExecutor();
282 MyTask task = new MyTask();
283 assertFalse(task.isCompleted());
284 Executors.invoke(e, task);
285 assertTrue(task.isCompleted());
286 }
287 catch (ExecutionException ex) {
288 unexpectedException();
289 }
290 catch (InterruptedException ex) {
291 unexpectedException();
292 }
293 }
294
295 /**
296 *
297 */
298 public void testExecuteCallable () {
299 try {
300 Executor e = new DirectExecutor();
301 Future<String> future = Executors.execute(e, new StringTask());
302 String result = future.get();
303 assertSame(TEST_STRING, result);
304 }
305 catch (ExecutionException ex) {
306 unexpectedException();
307 }
308 catch (InterruptedException ex) {
309 unexpectedException();
310 }
311 }
312
313 /**
314 *
315 */
316 public void testInvokeCallable () {
317 try {
318 Executor e = new DirectExecutor();
319 String result = Executors.invoke(e, new StringTask());
320
321 assertSame(TEST_STRING, result);
322 }
323 catch (ExecutionException ex) {
324 unexpectedException();
325 }
326 catch (InterruptedException ex) {
327 unexpectedException();
328 }
329 }
330
331 /**
332 * timeouts from execute will time out if they compute too long.
333 */
334 public void testTimedCallable() {
335 int N = 10000;
336 ExecutorService executor = Executors.newSingleThreadExecutor();
337 List<Callable<BigInteger>> tasks = new ArrayList<Callable<BigInteger>>(N);
338 try {
339 long startTime = System.currentTimeMillis();
340
341 long i = 0;
342 while (tasks.size() < N) {
343 tasks.add(new TimedCallable<BigInteger>(executor, new Fib(i), 1));
344 i += 10;
345 }
346
347 int iters = 0;
348 BigInteger sum = BigInteger.ZERO;
349 for (Iterator<Callable<BigInteger>> it = tasks.iterator(); it.hasNext();) {
350 try {
351 ++iters;
352 sum = sum.add(it.next().call());
353 }
354 catch (TimeoutException success) {
355 assertTrue(iters > 0);
356 return;
357 }
358 catch (Exception e) {
359 unexpectedException();
360 }
361 }
362 // if by chance we didn't ever time out, total time must be small
363 long elapsed = System.currentTimeMillis() - startTime;
364 assertTrue(elapsed < N);
365 }
366 finally {
367 joinPool(executor);
368 }
369 }
370
371
372
373
374 }