[cvs] / jsr166 / src / test / tck / AbstractExecutorServiceTest.java Repository:
ViewVC logotype

Diff of /jsr166/src/test/tck/AbstractExecutorServiceTest.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.39, Sun Oct 4 06:05:53 2015 UTC revision 1.40, Sun Oct 4 18:18:48 2015 UTC
# Line 192  Line 192 
192      public void testInterruptedSubmit() throws InterruptedException {      public void testInterruptedSubmit() throws InterruptedException {
193          final CountDownLatch submitted    = new CountDownLatch(1);          final CountDownLatch submitted    = new CountDownLatch(1);
194          final CountDownLatch quittingTime = new CountDownLatch(1);          final CountDownLatch quittingTime = new CountDownLatch(1);
         final ExecutorService p  
             = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS,  
                                      new ArrayBlockingQueue<Runnable>(10));  
195          final Callable<Void> awaiter = new CheckedCallable<Void>() {          final Callable<Void> awaiter = new CheckedCallable<Void>() {
196              public Void realCall() throws InterruptedException {              public Void realCall() throws InterruptedException {
197                  quittingTime.await();                  quittingTime.await();
198                  return null;                  return null;
199              }};              }};
200          try {          final ExecutorService p
201                = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS,
202                                         new ArrayBlockingQueue<Runnable>(10));
203            try (PoolCleaner cleaner = cleaner(p)) {
204              Thread t = new Thread(new CheckedInterruptedRunnable() {              Thread t = new Thread(new CheckedInterruptedRunnable() {
205                  public void realRun() throws Exception {                  public void realRun() throws Exception {
206                      Future<Void> future = p.submit(awaiter);                      Future<Void> future = p.submit(awaiter);
# Line 211  Line 211 
211              submitted.await();              submitted.await();
212              t.interrupt();              t.interrupt();
213              t.join();              t.join();
         } finally {  
214              quittingTime.countDown();              quittingTime.countDown();
             joinPool(p);  
215          }          }
216      }      }
217    
# Line 222  Line 220 
220       * throws exception       * throws exception
221       */       */
222      public void testSubmitEE() throws InterruptedException {      public void testSubmitEE() throws InterruptedException {
223          ThreadPoolExecutor p =          final ThreadPoolExecutor p =
224              new ThreadPoolExecutor(1, 1,              new ThreadPoolExecutor(1, 1,
225                                     60, TimeUnit.SECONDS,                                     60, TimeUnit.SECONDS,
226                                     new ArrayBlockingQueue<Runnable>(10));                                     new ArrayBlockingQueue<Runnable>(10));
227            try (PoolCleaner cleaner = cleaner(p)) {
228          Callable c = new Callable() {          Callable c = new Callable() {
229              public Object call() { throw new ArithmeticException(); }};              public Object call() { throw new ArithmeticException(); }};
   
230          try {          try {
231              p.submit(c).get();              p.submit(c).get();
232              shouldThrow();              shouldThrow();
233          } catch (ExecutionException success) {          } catch (ExecutionException success) {
234              assertTrue(success.getCause() instanceof ArithmeticException);              assertTrue(success.getCause() instanceof ArithmeticException);
235          }          }
236          joinPool(p);          }
237      }      }
238    
239      /**      /**
240       * invokeAny(null) throws NPE       * invokeAny(null) throws NPE
241       */       */
242      public void testInvokeAny1() throws Exception {      public void testInvokeAny1() throws Exception {
243          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
244            try (PoolCleaner cleaner = cleaner(e)) {
245          try {          try {
246              e.invokeAny(null);              e.invokeAny(null);
247              shouldThrow();              shouldThrow();
248          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
249          }          }
250      }      }
251    
# Line 257  Line 253 
253       * invokeAny(empty collection) throws IAE       * invokeAny(empty collection) throws IAE
254       */       */
255      public void testInvokeAny2() throws Exception {      public void testInvokeAny2() throws Exception {
256          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
257            try (PoolCleaner cleaner = cleaner(e)) {
258          try {          try {
259              e.invokeAny(new ArrayList<Callable<String>>());              e.invokeAny(new ArrayList<Callable<String>>());
260              shouldThrow();              shouldThrow();
261          } catch (IllegalArgumentException success) {              } catch (IllegalArgumentException success) {}
         } finally {  
             joinPool(e);  
262          }          }
263      }      }
264    
# Line 271  Line 266 
266       * invokeAny(c) throws NPE if c has null elements       * invokeAny(c) throws NPE if c has null elements
267       */       */
268      public void testInvokeAny3() throws Exception {      public void testInvokeAny3() throws Exception {
269          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
270            try (PoolCleaner cleaner = cleaner(e)) {
271          List<Callable<Long>> l = new ArrayList<Callable<Long>>();          List<Callable<Long>> l = new ArrayList<Callable<Long>>();
272          l.add(new Callable<Long>() {          l.add(new Callable<Long>() {
273              public Long call() { throw new ArithmeticException(); }});              public Long call() { throw new ArithmeticException(); }});
# Line 279  Line 275 
275          try {          try {
276              e.invokeAny(l);              e.invokeAny(l);
277              shouldThrow();              shouldThrow();
278          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
279          }          }
280      }      }
281    
# Line 289  Line 283 
283       * invokeAny(c) throws ExecutionException if no task in c completes       * invokeAny(c) throws ExecutionException if no task in c completes
284       */       */
285      public void testInvokeAny4() throws InterruptedException {      public void testInvokeAny4() throws InterruptedException {
286          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
287            try (PoolCleaner cleaner = cleaner(e)) {
288          List<Callable<String>> l = new ArrayList<Callable<String>>();          List<Callable<String>> l = new ArrayList<Callable<String>>();
289          l.add(new NPETask());          l.add(new NPETask());
290          try {          try {
# Line 297  Line 292 
292              shouldThrow();              shouldThrow();
293          } catch (ExecutionException success) {          } catch (ExecutionException success) {
294              assertTrue(success.getCause() instanceof NullPointerException);              assertTrue(success.getCause() instanceof NullPointerException);
295          } finally {              }
             joinPool(e);  
296          }          }
297      }      }
298    
# Line 306  Line 300 
300       * invokeAny(c) returns result of some task in c if at least one completes       * invokeAny(c) returns result of some task in c if at least one completes
301       */       */
302      public void testInvokeAny5() throws Exception {      public void testInvokeAny5() throws Exception {
303          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
304          try {          try (PoolCleaner cleaner = cleaner(e)) {
305              List<Callable<String>> l = new ArrayList<Callable<String>>();              List<Callable<String>> l = new ArrayList<Callable<String>>();
306              l.add(new StringTask());              l.add(new StringTask());
307              l.add(new StringTask());              l.add(new StringTask());
308              String result = e.invokeAny(l);              String result = e.invokeAny(l);
309              assertSame(TEST_STRING, result);              assertSame(TEST_STRING, result);
         } finally {  
             joinPool(e);  
310          }          }
311      }      }
312    
# Line 322  Line 314 
314       * invokeAll(null) throws NPE       * invokeAll(null) throws NPE
315       */       */
316      public void testInvokeAll1() throws InterruptedException {      public void testInvokeAll1() throws InterruptedException {
317          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
318            try (PoolCleaner cleaner = cleaner(e)) {
319          try {          try {
320              e.invokeAll(null);              e.invokeAll(null);
321              shouldThrow();              shouldThrow();
322          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
323          }          }
324      }      }
325    
# Line 336  Line 327 
327       * invokeAll(empty collection) returns empty collection       * invokeAll(empty collection) returns empty collection
328       */       */
329      public void testInvokeAll2() throws InterruptedException {      public void testInvokeAll2() throws InterruptedException {
330          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
331          try {          try (PoolCleaner cleaner = cleaner(e)) {
332              List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());              List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
333              assertTrue(r.isEmpty());              assertTrue(r.isEmpty());
         } finally {  
             joinPool(e);  
334          }          }
335      }      }
336    
# Line 349  Line 338 
338       * invokeAll(c) throws NPE if c has null elements       * invokeAll(c) throws NPE if c has null elements
339       */       */
340      public void testInvokeAll3() throws InterruptedException {      public void testInvokeAll3() throws InterruptedException {
341          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
342            try (PoolCleaner cleaner = cleaner(e)) {
343          List<Callable<String>> l = new ArrayList<Callable<String>>();          List<Callable<String>> l = new ArrayList<Callable<String>>();
344          l.add(new StringTask());          l.add(new StringTask());
345          l.add(null);          l.add(null);
346          try {          try {
347              e.invokeAll(l);              e.invokeAll(l);
348              shouldThrow();              shouldThrow();
349          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
350          }          }
351      }      }
352    
# Line 366  Line 354 
354       * get of returned element of invokeAll(c) throws exception on failed task       * get of returned element of invokeAll(c) throws exception on failed task
355       */       */
356      public void testInvokeAll4() throws Exception {      public void testInvokeAll4() throws Exception {
357          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
358          try {          try (PoolCleaner cleaner = cleaner(e)) {
359              List<Callable<String>> l = new ArrayList<Callable<String>>();              List<Callable<String>> l = new ArrayList<Callable<String>>();
360              l.add(new NPETask());              l.add(new NPETask());
361              List<Future<String>> futures = e.invokeAll(l);              List<Future<String>> futures = e.invokeAll(l);
# Line 378  Line 366 
366              } catch (ExecutionException success) {              } catch (ExecutionException success) {
367                  assertTrue(success.getCause() instanceof NullPointerException);                  assertTrue(success.getCause() instanceof NullPointerException);
368              }              }
         } finally {  
             joinPool(e);  
369          }          }
370      }      }
371    
# Line 387  Line 373 
373       * invokeAll(c) returns results of all completed tasks in c       * invokeAll(c) returns results of all completed tasks in c
374       */       */
375      public void testInvokeAll5() throws Exception {      public void testInvokeAll5() throws Exception {
376          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
377          try {          try (PoolCleaner cleaner = cleaner(e)) {
378              List<Callable<String>> l = new ArrayList<Callable<String>>();              List<Callable<String>> l = new ArrayList<Callable<String>>();
379              l.add(new StringTask());              l.add(new StringTask());
380              l.add(new StringTask());              l.add(new StringTask());
# Line 396  Line 382 
382              assertEquals(2, futures.size());              assertEquals(2, futures.size());
383              for (Future<String> future : futures)              for (Future<String> future : futures)
384                  assertSame(TEST_STRING, future.get());                  assertSame(TEST_STRING, future.get());
         } finally {  
             joinPool(e);  
385          }          }
386      }      }
387    
# Line 405  Line 389 
389       * timed invokeAny(null) throws NPE       * timed invokeAny(null) throws NPE
390       */       */
391      public void testTimedInvokeAny1() throws Exception {      public void testTimedInvokeAny1() throws Exception {
392          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
393            try (PoolCleaner cleaner = cleaner(e)) {
394          try {          try {
395              e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);              e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
396              shouldThrow();              shouldThrow();
397          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
398          }          }
399      }      }
400    
# Line 419  Line 402 
402       * timed invokeAny(null time unit) throws NPE       * timed invokeAny(null time unit) throws NPE
403       */       */
404      public void testTimedInvokeAnyNullTimeUnit() throws Exception {      public void testTimedInvokeAnyNullTimeUnit() throws Exception {
405          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
406            try (PoolCleaner cleaner = cleaner(e)) {
407          List<Callable<String>> l = new ArrayList<Callable<String>>();          List<Callable<String>> l = new ArrayList<Callable<String>>();
408          l.add(new StringTask());          l.add(new StringTask());
409          try {          try {
410              e.invokeAny(l, MEDIUM_DELAY_MS, null);              e.invokeAny(l, MEDIUM_DELAY_MS, null);
411              shouldThrow();              shouldThrow();
412          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
413          }          }
414      }      }
415    
# Line 435  Line 417 
417       * timed invokeAny(empty collection) throws IAE       * timed invokeAny(empty collection) throws IAE
418       */       */
419      public void testTimedInvokeAny2() throws Exception {      public void testTimedInvokeAny2() throws Exception {
420          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
421            try (PoolCleaner cleaner = cleaner(e)) {
422          try {          try {
423              e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);                  e.invokeAny(new ArrayList<Callable<String>>(),
424                                MEDIUM_DELAY_MS, MILLISECONDS);
425              shouldThrow();              shouldThrow();
426          } catch (IllegalArgumentException success) {              } catch (IllegalArgumentException success) {}
         } finally {  
             joinPool(e);  
427          }          }
428      }      }
429    
# Line 449  Line 431 
431       * timed invokeAny(c) throws NPE if c has null elements       * timed invokeAny(c) throws NPE if c has null elements
432       */       */
433      public void testTimedInvokeAny3() throws Exception {      public void testTimedInvokeAny3() throws Exception {
434          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
435            try (PoolCleaner cleaner = cleaner(e)) {
436          List<Callable<Long>> l = new ArrayList<Callable<Long>>();          List<Callable<Long>> l = new ArrayList<Callable<Long>>();
437          l.add(new Callable<Long>() {          l.add(new Callable<Long>() {
438              public Long call() { throw new ArithmeticException(); }});              public Long call() { throw new ArithmeticException(); }});
# Line 457  Line 440 
440          try {          try {
441              e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);              e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
442              shouldThrow();              shouldThrow();
443          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
444          }          }
445      }      }
446    
# Line 467  Line 448 
448       * timed invokeAny(c) throws ExecutionException if no task completes       * timed invokeAny(c) throws ExecutionException if no task completes
449       */       */
450      public void testTimedInvokeAny4() throws Exception {      public void testTimedInvokeAny4() throws Exception {
451          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
452            try (PoolCleaner cleaner = cleaner(e)) {
453          List<Callable<String>> l = new ArrayList<Callable<String>>();          List<Callable<String>> l = new ArrayList<Callable<String>>();
454          l.add(new NPETask());          l.add(new NPETask());
455          try {          try {
# Line 475  Line 457 
457              shouldThrow();              shouldThrow();
458          } catch (ExecutionException success) {          } catch (ExecutionException success) {
459              assertTrue(success.getCause() instanceof NullPointerException);              assertTrue(success.getCause() instanceof NullPointerException);
460          } finally {              }
             joinPool(e);  
461          }          }
462      }      }
463    
# Line 484  Line 465 
465       * timed invokeAny(c) returns result of some task in c       * timed invokeAny(c) returns result of some task in c
466       */       */
467      public void testTimedInvokeAny5() throws Exception {      public void testTimedInvokeAny5() throws Exception {
468          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
469          try {          try (PoolCleaner cleaner = cleaner(e)) {
470              List<Callable<String>> l = new ArrayList<Callable<String>>();              List<Callable<String>> l = new ArrayList<Callable<String>>();
471              l.add(new StringTask());              l.add(new StringTask());
472              l.add(new StringTask());              l.add(new StringTask());
473              String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);              String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
474              assertSame(TEST_STRING, result);              assertSame(TEST_STRING, result);
         } finally {  
             joinPool(e);  
475          }          }
476      }      }
477    
# Line 500  Line 479 
479       * timed invokeAll(null) throws NPE       * timed invokeAll(null) throws NPE
480       */       */
481      public void testTimedInvokeAll1() throws InterruptedException {      public void testTimedInvokeAll1() throws InterruptedException {
482          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
483            try (PoolCleaner cleaner = cleaner(e)) {
484          try {          try {
485              e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);              e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
486              shouldThrow();              shouldThrow();
487          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
488          }          }
489      }      }
490    
# Line 514  Line 492 
492       * timed invokeAll(null time unit) throws NPE       * timed invokeAll(null time unit) throws NPE
493       */       */
494      public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {      public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
495          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
496            try (PoolCleaner cleaner = cleaner(e)) {
497          List<Callable<String>> l = new ArrayList<Callable<String>>();          List<Callable<String>> l = new ArrayList<Callable<String>>();
498          l.add(new StringTask());          l.add(new StringTask());
499          try {          try {
500              e.invokeAll(l, MEDIUM_DELAY_MS, null);              e.invokeAll(l, MEDIUM_DELAY_MS, null);
501              shouldThrow();              shouldThrow();
502          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
503          }          }
504      }      }
505    
# Line 530  Line 507 
507       * timed invokeAll(empty collection) returns empty collection       * timed invokeAll(empty collection) returns empty collection
508       */       */
509      public void testTimedInvokeAll2() throws InterruptedException {      public void testTimedInvokeAll2() throws InterruptedException {
510          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
511          try {          try (PoolCleaner cleaner = cleaner(e)) {
512              List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);              List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
513              assertTrue(r.isEmpty());              assertTrue(r.isEmpty());
         } finally {  
             joinPool(e);  
514          }          }
515      }      }
516    
# Line 543  Line 518 
518       * timed invokeAll(c) throws NPE if c has null elements       * timed invokeAll(c) throws NPE if c has null elements
519       */       */
520      public void testTimedInvokeAll3() throws InterruptedException {      public void testTimedInvokeAll3() throws InterruptedException {
521          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
522            try (PoolCleaner cleaner = cleaner(e)) {
523          List<Callable<String>> l = new ArrayList<Callable<String>>();          List<Callable<String>> l = new ArrayList<Callable<String>>();
524          l.add(new StringTask());          l.add(new StringTask());
525          l.add(null);          l.add(null);
526          try {          try {
527              e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);              e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
528              shouldThrow();              shouldThrow();
529          } catch (NullPointerException success) {              } catch (NullPointerException success) {}
         } finally {  
             joinPool(e);  
530          }          }
531      }      }
532    
# Line 560  Line 534 
534       * get of returned element of invokeAll(c) throws exception on failed task       * get of returned element of invokeAll(c) throws exception on failed task
535       */       */
536      public void testTimedInvokeAll4() throws Exception {      public void testTimedInvokeAll4() throws Exception {
537          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
538          try {          try (PoolCleaner cleaner = cleaner(e)) {
539              List<Callable<String>> l = new ArrayList<Callable<String>>();              List<Callable<String>> l = new ArrayList<Callable<String>>();
540              l.add(new NPETask());              l.add(new NPETask());
541              List<Future<String>> futures =              List<Future<String>> futures =
# Line 573  Line 547 
547              } catch (ExecutionException success) {              } catch (ExecutionException success) {
548                  assertTrue(success.getCause() instanceof NullPointerException);                  assertTrue(success.getCause() instanceof NullPointerException);
549              }              }
         } finally {  
             joinPool(e);  
550          }          }
551      }      }
552    
# Line 582  Line 554 
554       * timed invokeAll(c) returns results of all completed tasks in c       * timed invokeAll(c) returns results of all completed tasks in c
555       */       */
556      public void testTimedInvokeAll5() throws Exception {      public void testTimedInvokeAll5() throws Exception {
557          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
558          try {          try (PoolCleaner cleaner = cleaner(e)) {
559              List<Callable<String>> l = new ArrayList<Callable<String>>();              List<Callable<String>> l = new ArrayList<Callable<String>>();
560              l.add(new StringTask());              l.add(new StringTask());
561              l.add(new StringTask());              l.add(new StringTask());
# Line 592  Line 564 
564              assertEquals(2, futures.size());              assertEquals(2, futures.size());
565              for (Future<String> future : futures)              for (Future<String> future : futures)
566                  assertSame(TEST_STRING, future.get());                  assertSame(TEST_STRING, future.get());
         } finally {  
             joinPool(e);  
567          }          }
568      }      }
569    
# Line 601  Line 571 
571       * timed invokeAll cancels tasks not completed by timeout       * timed invokeAll cancels tasks not completed by timeout
572       */       */
573      public void testTimedInvokeAll6() throws Exception {      public void testTimedInvokeAll6() throws Exception {
574          ExecutorService e = new DirectExecutorService();          final ExecutorService e = new DirectExecutorService();
575          try {          try (PoolCleaner cleaner = cleaner(e)) {
576              for (long timeout = timeoutMillis();;) {              for (long timeout = timeoutMillis();;) {
577                  List<Callable<String>> tasks = new ArrayList<>();                  List<Callable<String>> tasks = new ArrayList<>();
578                  tasks.add(new StringTask("0"));                  tasks.add(new StringTask("0"));
# Line 629  Line 599 
599                  assertTrue(futures.get(2).isCancelled());                  assertTrue(futures.get(2).isCancelled());
600                  break;                  break;
601              }              }
         } finally {  
             joinPool(e);  
602          }          }
603      }      }
604    

Legend:
Removed from v.1.39  
changed lines
  Added in v.1.40

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8