ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ExecutorsTest.java
Revision: 1.3
Committed: Sun Sep 14 20:42:40 2003 UTC (20 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.2: +23 -51 lines
Log Message:
New base class JSR166TestCase

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