From f141674d1619d95053d38a9cd8f93a8959b4a211 Mon Sep 17 00:00:00 2001 From: "He-Pin(kerr)" Date: Wed, 4 Jun 2025 08:28:29 +0000 Subject: [PATCH] 8347491: IllegalArgumentationException thrown by ThreadPoolExecutor doesn't have a useful message Reviewed-by: vklang, liach, pminborg --- .../concurrent/AbstractExecutorService.java | 19 +- .../concurrent/ExecutorCompletionService.java | 13 +- .../util/concurrent/ThreadPoolExecutor.java | 46 +-- .../tck/ThreadPoolExecutorTest.java | 269 +++++++++++++----- 4 files changed, 248 insertions(+), 99 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java b/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java index 1b1ba4b29a0..0d26607591d 100644 --- a/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Objects; /** * Provides default implementations of {@link ExecutorService} @@ -119,7 +120,7 @@ public abstract class AbstractExecutorService implements ExecutorService { */ @Override public Future submit(Runnable task) { - if (task == null) throw new NullPointerException(); + Objects.requireNonNull(task, "task"); RunnableFuture ftask = newTaskFor(task, null); execute(ftask); return ftask; @@ -131,7 +132,7 @@ public abstract class AbstractExecutorService implements ExecutorService { */ @Override public Future submit(Runnable task, T result) { - if (task == null) throw new NullPointerException(); + Objects.requireNonNull(task, "task"); RunnableFuture ftask = newTaskFor(task, result); execute(ftask); return ftask; @@ -143,7 +144,7 @@ public abstract class AbstractExecutorService implements ExecutorService { */ @Override public Future submit(Callable task) { - if (task == null) throw new NullPointerException(); + Objects.requireNonNull(task, "task"); RunnableFuture ftask = newTaskFor(task); execute(ftask); return ftask; @@ -155,11 +156,10 @@ public abstract class AbstractExecutorService implements ExecutorService { private T doInvokeAny(Collection> tasks, boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException { - if (tasks == null) - throw new NullPointerException(); + Objects.requireNonNull(tasks, "tasks"); int ntasks = tasks.size(); if (ntasks == 0) - throw new IllegalArgumentException(); + throw new IllegalArgumentException("tasks is empty"); ArrayList> futures = new ArrayList<>(ntasks); ExecutorCompletionService ecs = new ExecutorCompletionService(this); @@ -262,8 +262,7 @@ public abstract class AbstractExecutorService implements ExecutorService { @Override public List> invokeAll(Collection> tasks) throws InterruptedException { - if (tasks == null) - throw new NullPointerException(); + Objects.requireNonNull(tasks, "tasks"); ArrayList> futures = new ArrayList<>(tasks.size()); try { for (Callable t : tasks) { @@ -294,8 +293,8 @@ public abstract class AbstractExecutorService implements ExecutorService { public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { - if (tasks == null) - throw new NullPointerException(); + Objects.requireNonNull(tasks, "tasks"); + Objects.requireNonNull(unit, "unit"); final long nanos = unit.toNanos(timeout); final long deadline = System.nanoTime() + nanos; ArrayList> futures = new ArrayList<>(tasks.size()); diff --git a/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java b/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java index 3c09b4882d0..249c2ebf4d9 100644 --- a/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java +++ b/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java @@ -35,6 +35,8 @@ package java.util.concurrent; +import java.util.Objects; + /** * A {@link CompletionService} that uses a supplied {@link Executor} * to execute tasks. This class arranges that submitted tasks are, @@ -145,8 +147,7 @@ public class ExecutorCompletionService implements CompletionService { * @throws NullPointerException if executor is {@code null} */ public ExecutorCompletionService(Executor executor) { - if (executor == null) - throw new NullPointerException(); + Objects.requireNonNull(executor, "executor"); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; @@ -168,8 +169,8 @@ public class ExecutorCompletionService implements CompletionService { */ public ExecutorCompletionService(Executor executor, BlockingQueue> completionQueue) { - if (executor == null || completionQueue == null) - throw new NullPointerException(); + Objects.requireNonNull(executor, "executor"); + Objects.requireNonNull(completionQueue, "completionQueue"); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; @@ -181,7 +182,7 @@ public class ExecutorCompletionService implements CompletionService { * @throws NullPointerException {@inheritDoc} */ public Future submit(Callable task) { - if (task == null) throw new NullPointerException(); + Objects.requireNonNull(task, "task"); RunnableFuture f = newTaskFor(task); executor.execute(new QueueingFuture(f, completionQueue)); return f; @@ -192,7 +193,7 @@ public class ExecutorCompletionService implements CompletionService { * @throws NullPointerException {@inheritDoc} */ public Future submit(Runnable task, V result) { - if (task == null) throw new NullPointerException(); + Objects.requireNonNull(task, "task"); RunnableFuture f = newTaskFor(task, result); executor.execute(new QueueingFuture(f, completionQueue)); return f; diff --git a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java index 0bf5669b6e1..029e31ef9f6 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -1251,13 +1251,19 @@ public class ThreadPoolExecutor extends AbstractExecutorService { BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { - if (corePoolSize < 0 || - maximumPoolSize <= 0 || - maximumPoolSize < corePoolSize || - keepAliveTime < 0) - throw new IllegalArgumentException(); - if (workQueue == null || threadFactory == null || handler == null) - throw new NullPointerException(); + if (corePoolSize < 0) { + throw new IllegalArgumentException("corePoolSize must be non-negative"); + } else if (maximumPoolSize <= 0) { + throw new IllegalArgumentException("maximumPoolSize must be positive"); + } else if (maximumPoolSize < corePoolSize) { + throw new IllegalArgumentException("maximumPoolSize must be greater than or equal to corePoolSize"); + } else if (keepAliveTime < 0) { + throw new IllegalArgumentException("keepAliveTime must be non-negative"); + } + Objects.requireNonNull(unit, "unit"); + Objects.requireNonNull(workQueue, "workQueue"); + Objects.requireNonNull(threadFactory, "threadFactory"); + Objects.requireNonNull(handler, "handler"); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; @@ -1284,8 +1290,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @throws NullPointerException if {@code command} is null */ public void execute(Runnable command) { - if (command == null) - throw new NullPointerException(); + Objects.requireNonNull(command, "command"); /* * Proceed in 3 steps: * @@ -1446,8 +1451,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @see #getThreadFactory */ public void setThreadFactory(ThreadFactory threadFactory) { - if (threadFactory == null) - throw new NullPointerException(); + Objects.requireNonNull(threadFactory, "threadFactory"); this.threadFactory = threadFactory; } @@ -1469,8 +1473,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @see #getRejectedExecutionHandler */ public void setRejectedExecutionHandler(RejectedExecutionHandler handler) { - if (handler == null) - throw new NullPointerException(); + Objects.requireNonNull(handler, "handler"); this.handler = handler; } @@ -1498,8 +1501,11 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @see #getCorePoolSize */ public void setCorePoolSize(int corePoolSize) { - if (corePoolSize < 0 || maximumPoolSize < corePoolSize) - throw new IllegalArgumentException(); + if (corePoolSize < 0) { + throw new IllegalArgumentException("corePoolSize must be non-negative"); + } else if (corePoolSize > maximumPoolSize) { + throw new IllegalArgumentException("corePoolSize must be less than or equal to maximumPoolSize"); + } int delta = corePoolSize - this.corePoolSize; this.corePoolSize = corePoolSize; if (workerCountOf(ctl.get()) > corePoolSize) @@ -1623,8 +1629,11 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @see #getMaximumPoolSize */ public void setMaximumPoolSize(int maximumPoolSize) { - if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize) - throw new IllegalArgumentException(); + if (maximumPoolSize <= 0) { + throw new IllegalArgumentException("maximumPoolSize must be positive"); + } else if (maximumPoolSize < corePoolSize) { + throw new IllegalArgumentException("maximumPoolSize must be greater than or equal to corePoolSize"); + } this.maximumPoolSize = maximumPoolSize; if (workerCountOf(ctl.get()) > maximumPoolSize) interruptIdleWorkers(); @@ -1658,9 +1667,10 @@ public class ThreadPoolExecutor extends AbstractExecutorService { */ public void setKeepAliveTime(long time, TimeUnit unit) { if (time < 0) - throw new IllegalArgumentException(); + throw new IllegalArgumentException("time must be non-negative"); if (time == 0 && allowsCoreThreadTimeOut()) throw new IllegalArgumentException("Core threads must have nonzero keep alive times"); + Objects.requireNonNull(unit, "unit"); long keepAliveTime = unit.toNanos(time); long delta = keepAliveTime - this.keepAliveTime; this.keepAliveTime = keepAliveTime; diff --git a/test/jdk/java/util/concurrent/tck/ThreadPoolExecutorTest.java b/test/jdk/java/util/concurrent/tck/ThreadPoolExecutorTest.java index 73e6deda987..d9ce643a26d 100644 --- a/test/jdk/java/util/concurrent/tck/ThreadPoolExecutorTest.java +++ b/test/jdk/java/util/concurrent/tck/ThreadPoolExecutorTest.java @@ -41,22 +41,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.*; import java.util.concurrent.ThreadPoolExecutor.AbortPolicy; import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy; import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy; @@ -66,6 +51,7 @@ import java.util.concurrent.atomic.AtomicReference; import junit.framework.Test; import junit.framework.TestSuite; +import org.junit.Assert; public class ThreadPoolExecutorTest extends JSR166TestCase { public static void main(String[] args) { @@ -304,7 +290,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { p.setThreadFactory(null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("threadFactory", success.getMessage()); + } } } @@ -364,7 +352,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { p.setRejectedExecutionHandler(null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("handler", success.getMessage()); + } } } @@ -737,7 +727,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ThreadPoolExecutor(-1, 1, 1L, SECONDS, new ArrayBlockingQueue(10)); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("corePoolSize must be non-negative", success.getMessage()); + } } /** @@ -748,7 +740,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ThreadPoolExecutor(1, -1, 1L, SECONDS, new ArrayBlockingQueue(10)); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -759,7 +753,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ThreadPoolExecutor(1, 0, 1L, SECONDS, new ArrayBlockingQueue(10)); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -770,7 +766,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ThreadPoolExecutor(1, 2, -1L, SECONDS, new ArrayBlockingQueue(10)); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("keepAliveTime must be non-negative", success.getMessage()); + } } /** @@ -781,7 +779,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ThreadPoolExecutor(2, 1, 1L, SECONDS, new ArrayBlockingQueue(10)); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals( + "maximumPoolSize must be greater than or equal to corePoolSize", + success.getMessage() + ); + } } /** @@ -792,7 +795,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ThreadPoolExecutor(1, 2, 1L, SECONDS, (BlockingQueue) null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("workQueue", success.getMessage()); + } } /** @@ -804,7 +809,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new SimpleThreadFactory()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("corePoolSize must be non-negative", success.getMessage()); + } } /** @@ -816,7 +823,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new SimpleThreadFactory()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -828,7 +837,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new SimpleThreadFactory()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -840,7 +851,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new SimpleThreadFactory()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("keepAliveTime must be non-negative", success.getMessage()); + } } /** @@ -852,7 +865,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new SimpleThreadFactory()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals( + "maximumPoolSize must be greater than or equal to corePoolSize", + success.getMessage() + ); + } } /** @@ -864,7 +882,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { (BlockingQueue) null, new SimpleThreadFactory()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("workQueue", success.getMessage()); + } } /** @@ -876,7 +896,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), (ThreadFactory) null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("threadFactory", success.getMessage()); + } } /** @@ -888,7 +910,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("corePoolSize must be non-negative", success.getMessage()); + } } /** @@ -900,7 +924,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -912,7 +938,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -924,7 +952,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("keepAliveTime must be non-negative", success.getMessage()); + } } /** @@ -936,7 +966,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals( + "maximumPoolSize must be greater than or equal to corePoolSize", + success.getMessage() + ); + } } /** @@ -948,7 +983,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { (BlockingQueue) null, new NoOpREHandler()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("workQueue", success.getMessage()); + } } /** @@ -960,7 +997,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new ArrayBlockingQueue(10), (RejectedExecutionHandler) null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("handler", success.getMessage()); + } } /** @@ -973,7 +1012,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new SimpleThreadFactory(), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("corePoolSize must be non-negative", success.getMessage()); + } } /** @@ -986,7 +1027,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new SimpleThreadFactory(), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -999,7 +1042,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new SimpleThreadFactory(), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } /** @@ -1012,7 +1057,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new SimpleThreadFactory(), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("keepAliveTime must be non-negative", success.getMessage()); + } } /** @@ -1025,7 +1072,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new SimpleThreadFactory(), new NoOpREHandler()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals( + "maximumPoolSize must be greater than or equal to corePoolSize", + success.getMessage() + ); + } } /** @@ -1038,7 +1090,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new SimpleThreadFactory(), new NoOpREHandler()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("workQueue", success.getMessage()); + } } /** @@ -1051,7 +1105,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { new SimpleThreadFactory(), (RejectedExecutionHandler) null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("handler", success.getMessage()); + } } /** @@ -1064,7 +1120,24 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { (ThreadFactory) null, new NoOpREHandler()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("threadFactory", success.getMessage()); + } + } + + /** + * Constructor throws if unit is null + */ + public void testConstructorNullPointerException9() { + try { + new ThreadPoolExecutor(1, 2, 1L, (TimeUnit) null, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (NullPointerException success) { + assertEquals("unit", success.getMessage()); + } } /** @@ -1228,7 +1301,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { p.setCorePoolSize(-1); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("corePoolSize must be non-negative", success.getMessage()); + } } } @@ -1245,7 +1320,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { p.setMaximumPoolSize(1); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals( + "maximumPoolSize must be greater than or equal to corePoolSize", + success.getMessage() + ); + } } } @@ -1262,7 +1342,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { p.setMaximumPoolSize(-1); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("maximumPoolSize must be positive", success.getMessage()); + } } } @@ -1282,13 +1364,25 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { p.setMaximumPoolSize(s - 1); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals( + s == 1 + ? "maximumPoolSize must be positive" + : "maximumPoolSize must be greater than or equal to corePoolSize", + success.getMessage() + ); + } assertEquals(s, p.getCorePoolSize()); assertEquals(s, p.getMaximumPoolSize()); try { p.setCorePoolSize(s + 1); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals( + "corePoolSize must be less than or equal to maximumPoolSize", + success.getMessage() + ); + } assertEquals(s, p.getCorePoolSize()); assertEquals(s, p.getMaximumPoolSize()); } @@ -1299,7 +1393,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { * setKeepAliveTime throws IllegalArgumentException * when given a negative value */ - public void testKeepAliveTimeIllegalArgumentException() { + public void testKeepAliveTimeInvalidLengthIllegalArgumentException() { final ThreadPoolExecutor p = new ThreadPoolExecutor(2, 3, LONG_DELAY_MS, MILLISECONDS, @@ -1308,7 +1402,28 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { p.setKeepAliveTime(-1, MILLISECONDS); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("time must be non-negative", success.getMessage()); + } + } + } + + /** + * setKeepAliveTime throws IllegalArgumentException + * when given a null unit + */ + public void testKeepAliveTimeNullTimeUnitIllegalArgumentException() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setKeepAliveTime(1, (TimeUnit) null); + shouldThrow(); + } catch (NullPointerException success) { + assertEquals("unit", success.getMessage()); + } } } @@ -1399,7 +1514,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAny(null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("tasks", success.getMessage()); + } } } @@ -1415,7 +1532,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAny(new ArrayList>()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("tasks is empty", success.getMessage()); + } } } @@ -1435,7 +1554,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAny(l); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("task", success.getMessage()); + } latch.countDown(); } } @@ -1489,7 +1610,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAll(null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("tasks", success.getMessage()); + } } } @@ -1524,7 +1647,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAll(l); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals(null, success.getMessage()); + } } } @@ -1581,7 +1706,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAny(null, randomTimeout(), randomTimeUnit()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("tasks", success.getMessage()); + } } } @@ -1599,7 +1726,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAny(l, randomTimeout(), null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("Cannot invoke \"java.util.concurrent.TimeUnit.toNanos(long)\" because \"unit\" is null", success.getMessage()); + } } } @@ -1616,7 +1745,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { e.invokeAny(new ArrayList>(), randomTimeout(), randomTimeUnit()); shouldThrow(); - } catch (IllegalArgumentException success) {} + } catch (IllegalArgumentException success) { + assertEquals("tasks is empty", success.getMessage()); + } } } @@ -1636,7 +1767,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAny(l, randomTimeout(), randomTimeUnit()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("task", success.getMessage()); + } latch.countDown(); } } @@ -1694,7 +1827,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAll(null, randomTimeout(), randomTimeUnit()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("tasks", success.getMessage()); + } } } @@ -1712,7 +1847,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAll(l, randomTimeout(), null); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals("unit", success.getMessage()); + } } } @@ -1748,7 +1885,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase { try { e.invokeAll(l, randomTimeout(), randomTimeUnit()); shouldThrow(); - } catch (NullPointerException success) {} + } catch (NullPointerException success) { + assertEquals(null, success.getMessage()); + } } }