From c2919752fd660ffa6dfb6902fbbb30210a201897 Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Fri, 29 Jan 2016 11:44:19 -0800
Subject: [PATCH] 8146467: Integrate JSR 166 jck tests into JDK repo
Reviewed-by: martin, psandoz, chegar, fyuan, jjg
---
.../tck/AbstractExecutorServiceTest.java | 635 +++
.../concurrent/tck/AbstractQueueTest.java | 205 +
.../AbstractQueuedLongSynchronizerTest.java | 1280 ++++++
.../tck/AbstractQueuedSynchronizerTest.java | 1283 ++++++
.../tck/ArrayBlockingQueueTest.java | 955 ++++
.../util/concurrent/tck/ArrayDequeTest.java | 945 ++++
.../java/util/concurrent/tck/Atomic8Test.java | 596 +++
.../concurrent/tck/AtomicBooleanTest.java | 169 +
.../tck/AtomicIntegerArrayTest.java | 370 ++
.../tck/AtomicIntegerFieldUpdaterTest.java | 363 ++
.../concurrent/tck/AtomicIntegerTest.java | 294 ++
.../concurrent/tck/AtomicLongArrayTest.java | 369 ++
.../tck/AtomicLongFieldUpdaterTest.java | 363 ++
.../util/concurrent/tck/AtomicLongTest.java | 297 ++
.../tck/AtomicMarkableReferenceTest.java | 180 +
.../tck/AtomicReferenceArrayTest.java | 246 +
.../tck/AtomicReferenceFieldUpdaterTest.java | 265 ++
.../concurrent/tck/AtomicReferenceTest.java | 170 +
.../tck/AtomicStampedReferenceTest.java | 180 +
.../concurrent/tck/BlockingQueueTest.java | 403 ++
.../util/concurrent/tck/Collection8Test.java | 124 +
.../tck/CollectionImplementation.java | 46 +
.../util/concurrent/tck/CollectionTest.java | 68 +
.../concurrent/tck/CompletableFutureTest.java | 3979 +++++++++++++++++
.../tck/ConcurrentHashMap8Test.java | 1118 +++++
.../concurrent/tck/ConcurrentHashMapTest.java | 833 ++++
.../tck/ConcurrentLinkedDequeTest.java | 926 ++++
.../tck/ConcurrentLinkedQueueTest.java | 564 +++
.../tck/ConcurrentSkipListMapTest.java | 1306 ++++++
.../tck/ConcurrentSkipListSetTest.java | 1007 +++++
.../tck/ConcurrentSkipListSubMapTest.java | 1450 ++++++
.../tck/ConcurrentSkipListSubSetTest.java | 1141 +++++
.../tck/CopyOnWriteArrayListTest.java | 783 ++++
.../tck/CopyOnWriteArraySetTest.java | 432 ++
.../concurrent/tck/CountDownLatchTest.java | 223 +
.../concurrent/tck/CountedCompleterTest.java | 1872 ++++++++
.../concurrent/tck/CyclicBarrierTest.java | 491 ++
.../util/concurrent/tck/DelayQueueTest.java | 820 ++++
.../concurrent/tck/DoubleAccumulatorTest.java | 183 +
.../util/concurrent/tck/DoubleAdderTest.java | 197 +
.../java/util/concurrent/tck/EntryTest.java | 157 +
.../util/concurrent/tck/ExchangerTest.java | 180 +
.../tck/ExecutorCompletionServiceTest.java | 241 +
.../util/concurrent/tck/ExecutorsTest.java | 623 +++
.../concurrent/tck/ForkJoinPool8Test.java | 1615 +++++++
.../util/concurrent/tck/ForkJoinPoolTest.java | 991 ++++
.../concurrent/tck/ForkJoinTask8Test.java | 1228 +++++
.../util/concurrent/tck/ForkJoinTaskTest.java | 1685 +++++++
.../util/concurrent/tck/FutureTaskTest.java | 866 ++++
.../util/concurrent/tck/JSR166TestCase.java | 1814 ++++++++
.../tck/LinkedBlockingDequeTest.java | 1848 ++++++++
.../tck/LinkedBlockingQueueTest.java | 889 ++++
.../util/concurrent/tck/LinkedListTest.java | 669 +++
.../tck/LinkedTransferQueueTest.java | 1085 +++++
.../util/concurrent/tck/LockSupportTest.java | 403 ++
.../concurrent/tck/LongAccumulatorTest.java | 183 +
.../util/concurrent/tck/LongAdderTest.java | 220 +
.../java/util/concurrent/tck/PhaserTest.java | 820 ++++
.../tck/PriorityBlockingQueueTest.java | 764 ++++
.../concurrent/tck/PriorityQueueTest.java | 528 +++
.../concurrent/tck/RecursiveActionTest.java | 1272 ++++++
.../concurrent/tck/RecursiveTaskTest.java | 1053 +++++
.../concurrent/tck/ReentrantLockTest.java | 1163 +++++
.../tck/ReentrantReadWriteLockTest.java | 1703 +++++++
.../tck/ScheduledExecutorSubclassTest.java | 1286 ++++++
.../concurrent/tck/ScheduledExecutorTest.java | 1259 ++++++
.../util/concurrent/tck/SemaphoreTest.java | 669 +++
.../concurrent/tck/SplittableRandomTest.java | 555 +++
.../util/concurrent/tck/StampedLockTest.java | 906 ++++
.../tck/SubmissionPublisherTest.java | 1010 +++++
.../concurrent/tck/SynchronousQueueTest.java | 643 +++
.../java/util/concurrent/tck/SystemTest.java | 96 +
.../tck/ThreadLocalRandom8Test.java | 262 ++
.../concurrent/tck/ThreadLocalRandomTest.java | 368 ++
.../util/concurrent/tck/ThreadLocalTest.java | 128 +
.../tck/ThreadPoolExecutorSubclassTest.java | 2062 +++++++++
.../tck/ThreadPoolExecutorTest.java | 2093 +++++++++
.../java/util/concurrent/tck/ThreadTest.java | 100 +
.../util/concurrent/tck/TimeUnitTest.java | 463 ++
.../java/util/concurrent/tck/TreeMapTest.java | 1111 +++++
.../java/util/concurrent/tck/TreeSetTest.java | 1008 +++++
.../util/concurrent/tck/TreeSubMapTest.java | 1138 +++++
.../util/concurrent/tck/TreeSubSetTest.java | 1139 +++++
83 files changed, 65427 insertions(+)
create mode 100644 jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AbstractQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ArrayDequeTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/Atomic8Test.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicIntegerFieldUpdaterTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicLongFieldUpdaterTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicLongTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicMarkableReferenceTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicReferenceFieldUpdaterTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/AtomicStampedReferenceTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/BlockingQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/Collection8Test.java
create mode 100644 jdk/test/java/util/concurrent/tck/CollectionImplementation.java
create mode 100644 jdk/test/java/util/concurrent/tck/CollectionTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/CompletableFutureTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/CountDownLatchTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/CountedCompleterTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/DelayQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/DoubleAccumulatorTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/DoubleAdderTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/EntryTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ExchangerTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ExecutorsTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java
create mode 100644 jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java
create mode 100644 jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/FutureTaskTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/JSR166TestCase.java
create mode 100644 jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/LinkedListTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/LockSupportTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/LongAccumulatorTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/LongAdderTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/PhaserTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/PriorityQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/RecursiveActionTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/RecursiveTaskTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ReentrantLockTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ReentrantReadWriteLockTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/SemaphoreTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/SplittableRandomTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/StampedLockTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/SystemTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java
create mode 100644 jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ThreadLocalTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/ThreadTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/TimeUnitTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/TreeMapTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/TreeSetTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/TreeSubMapTest.java
create mode 100644 jdk/test/java/util/concurrent/tck/TreeSubSetTest.java
diff --git a/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java b/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java
new file mode 100644
index 00000000000..9e140da9f72
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java
@@ -0,0 +1,635 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractExecutorServiceTest extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+ public static Test suite() {
+ return new TestSuite(AbstractExecutorServiceTest.class);
+ }
+
+ /**
+ * A no-frills implementation of AbstractExecutorService, designed
+ * to test the submit methods only.
+ */
+ static class DirectExecutorService extends AbstractExecutorService {
+ public void execute(Runnable r) { r.run(); }
+ public void shutdown() { shutdown = true; }
+ public List shutdownNow() {
+ shutdown = true;
+ return Collections.EMPTY_LIST;
+ }
+ public boolean isShutdown() { return shutdown; }
+ public boolean isTerminated() { return isShutdown(); }
+ public boolean awaitTermination(long timeout, TimeUnit unit) {
+ return isShutdown();
+ }
+ private volatile boolean shutdown = false;
+ }
+
+ /**
+ * execute(runnable) runs it to completion
+ */
+ public void testExecuteRunnable() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ final AtomicBoolean done = new AtomicBoolean(false);
+ Future> future = e.submit(new CheckedRunnable() {
+ public void realRun() {
+ done.set(true);
+ }});
+ assertNull(future.get());
+ assertNull(future.get(0, MILLISECONDS));
+ assertTrue(done.get());
+ assertTrue(future.isDone());
+ assertFalse(future.isCancelled());
+ }
+
+ /**
+ * Completed submit(callable) returns result
+ */
+ public void testSubmitCallable() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(new StringTask());
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ }
+
+ /**
+ * Completed submit(runnable) returns successfully
+ */
+ public void testSubmitRunnable() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future> future = e.submit(new NoOpRunnable());
+ future.get();
+ assertTrue(future.isDone());
+ }
+
+ /**
+ * Completed submit(runnable, result) returns result
+ */
+ public void testSubmitRunnable2() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(new NoOpRunnable(), TEST_STRING);
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ }
+
+ /**
+ * A submitted privileged action runs to completion
+ */
+ public void testSubmitPrivilegedAction() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(Executors.callable(new PrivilegedAction() {
+ public Object run() {
+ return TEST_STRING;
+ }}));
+
+ assertSame(TEST_STRING, future.get());
+ }};
+
+ runWithPermissions(r,
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"),
+ new RuntimePermission("modifyThread"));
+ }
+
+ /**
+ * A submitted privileged exception action runs to completion
+ */
+ public void testSubmitPrivilegedExceptionAction() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
+ public Object run() {
+ return TEST_STRING;
+ }}));
+
+ assertSame(TEST_STRING, future.get());
+ }};
+
+ runWithPermissions(r);
+ }
+
+ /**
+ * A submitted failed privileged exception action reports exception
+ */
+ public void testSubmitFailedPrivilegedExceptionAction() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ throw new IndexOutOfBoundsException();
+ }}));
+
+ try {
+ future.get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof IndexOutOfBoundsException);
+ }}};
+
+ runWithPermissions(r);
+ }
+
+ /**
+ * execute(null runnable) throws NPE
+ */
+ public void testExecuteNullRunnable() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.submit((Runnable) null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * submit(null callable) throws NPE
+ */
+ public void testSubmitNullCallable() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.submit((Callable) null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * submit(callable).get() throws InterruptedException if interrupted
+ */
+ public void testInterruptedSubmit() throws InterruptedException {
+ final CountDownLatch submitted = new CountDownLatch(1);
+ final CountDownLatch quittingTime = new CountDownLatch(1);
+ final Callable awaiter = new CheckedCallable() {
+ public Void realCall() throws InterruptedException {
+ assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS));
+ return null;
+ }};
+ final ExecutorService p
+ = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS,
+ new ArrayBlockingQueue(10));
+ try (PoolCleaner cleaner = cleaner(p, quittingTime)) {
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws Exception {
+ Future future = p.submit(awaiter);
+ submitted.countDown();
+ future.get();
+ }});
+
+ await(submitted);
+ t.interrupt();
+ awaitTermination(t);
+ }
+ }
+
+ /**
+ * get of submit(callable) throws ExecutionException if callable
+ * throws exception
+ */
+ public void testSubmitEE() throws InterruptedException {
+ final ThreadPoolExecutor p =
+ new ThreadPoolExecutor(1, 1,
+ 60, TimeUnit.SECONDS,
+ new ArrayBlockingQueue(10));
+ try (PoolCleaner cleaner = cleaner(p)) {
+ Callable c = new Callable() {
+ public Object call() { throw new ArithmeticException(); }};
+ try {
+ p.submit(c).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof ArithmeticException);
+ }
+ }
+ }
+
+ /**
+ * invokeAny(null) throws NPE
+ */
+ public void testInvokeAny1() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ try {
+ e.invokeAny(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * invokeAny(empty collection) throws IAE
+ */
+ public void testInvokeAny2() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ try {
+ e.invokeAny(new ArrayList>());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+ }
+
+ /**
+ * invokeAny(c) throws NPE if c has null elements
+ */
+ public void testInvokeAny3() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new Callable() {
+ public Long call() { throw new ArithmeticException(); }});
+ l.add(null);
+ try {
+ e.invokeAny(l);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * invokeAny(c) throws ExecutionException if no task in c completes
+ */
+ public void testInvokeAny4() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new NPETask());
+ try {
+ e.invokeAny(l);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ }
+ }
+ }
+
+ /**
+ * invokeAny(c) returns result of some task in c if at least one completes
+ */
+ public void testInvokeAny5() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l);
+ assertSame(TEST_STRING, result);
+ }
+ }
+
+ /**
+ * invokeAll(null) throws NPE
+ */
+ public void testInvokeAll1() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ try {
+ e.invokeAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * invokeAll(empty collection) returns empty collection
+ */
+ public void testInvokeAll2() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> r = e.invokeAll(new ArrayList>());
+ assertTrue(r.isEmpty());
+ }
+ }
+
+ /**
+ * invokeAll(c) throws NPE if c has null elements
+ */
+ public void testInvokeAll3() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ l.add(null);
+ try {
+ e.invokeAll(l);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * get of returned element of invokeAll(c) throws exception on failed task
+ */
+ public void testInvokeAll4() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new NPETask());
+ List> futures = e.invokeAll(l);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ }
+ }
+ }
+
+ /**
+ * invokeAll(c) returns results of all completed tasks in c
+ */
+ public void testInvokeAll5() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List> futures = e.invokeAll(l);
+ assertEquals(2, futures.size());
+ for (Future future : futures)
+ assertSame(TEST_STRING, future.get());
+ }
+ }
+
+ /**
+ * timed invokeAny(null) throws NPE
+ */
+ public void testTimedInvokeAny1() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ try {
+ e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * timed invokeAny(null time unit) throws NPE
+ */
+ public void testTimedInvokeAnyNullTimeUnit() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * timed invokeAny(empty collection) throws IAE
+ */
+ public void testTimedInvokeAny2() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ try {
+ e.invokeAny(new ArrayList>(),
+ MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAny3() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new Callable() {
+ public Long call() { throw new ArithmeticException(); }});
+ l.add(null);
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws ExecutionException if no task completes
+ */
+ public void testTimedInvokeAny4() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ long startTime = System.nanoTime();
+ List> l = new ArrayList>();
+ l.add(new NPETask());
+ try {
+ e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ }
+ assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) returns result of some task in c
+ */
+ public void testTimedInvokeAny5() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ long startTime = System.nanoTime();
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
+ assertSame(TEST_STRING, result);
+ assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+ }
+ }
+
+ /**
+ * timed invokeAll(null) throws NPE
+ */
+ public void testTimedInvokeAll1() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ try {
+ e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * timed invokeAll(null time unit) throws NPE
+ */
+ public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ try {
+ e.invokeAll(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * timed invokeAll(empty collection) returns empty collection
+ */
+ public void testTimedInvokeAll2() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> r = e.invokeAll(new ArrayList>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ assertTrue(r.isEmpty());
+ }
+ }
+
+ /**
+ * timed invokeAll(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAll3() throws InterruptedException {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ l.add(null);
+ try {
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ }
+
+ /**
+ * get of returned element of invokeAll(c) throws exception on failed task
+ */
+ public void testTimedInvokeAll4() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new NPETask());
+ List> futures =
+ e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ }
+ }
+ }
+
+ /**
+ * timed invokeAll(c) returns results of all completed tasks in c
+ */
+ public void testTimedInvokeAll5() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ List> l = new ArrayList>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List> futures =
+ e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
+ assertEquals(2, futures.size());
+ for (Future future : futures)
+ assertSame(TEST_STRING, future.get());
+ }
+ }
+
+ /**
+ * timed invokeAll cancels tasks not completed by timeout
+ */
+ public void testTimedInvokeAll6() throws Exception {
+ final ExecutorService e = new DirectExecutorService();
+ try (PoolCleaner cleaner = cleaner(e)) {
+ for (long timeout = timeoutMillis();;) {
+ List> tasks = new ArrayList<>();
+ tasks.add(new StringTask("0"));
+ tasks.add(Executors.callable(possiblyInterruptedRunnable(timeout),
+ TEST_STRING));
+ tasks.add(new StringTask("2"));
+ long startTime = System.nanoTime();
+ List> futures =
+ e.invokeAll(tasks, timeout, MILLISECONDS);
+ assertEquals(tasks.size(), futures.size());
+ assertTrue(millisElapsedSince(startTime) >= timeout);
+ for (Future future : futures)
+ assertTrue(future.isDone());
+ try {
+ assertEquals("0", futures.get(0).get());
+ assertEquals(TEST_STRING, futures.get(1).get());
+ } catch (CancellationException retryWithLongerTimeout) {
+ // unusual delay before starting second task
+ timeout *= 2;
+ if (timeout >= LONG_DELAY_MS / 2)
+ fail("expected exactly one task to be cancelled");
+ continue;
+ }
+ assertTrue(futures.get(2).isCancelled());
+ break;
+ }
+ }
+ }
+
+}
diff --git a/jdk/test/java/util/concurrent/tck/AbstractQueueTest.java b/jdk/test/java/util/concurrent/tck/AbstractQueueTest.java
new file mode 100644
index 00000000000..ddc769d3a45
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/AbstractQueueTest.java
@@ -0,0 +1,205 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import java.util.AbstractQueue;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractQueueTest extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+ public static Test suite() {
+ return new TestSuite(AbstractQueueTest.class);
+ }
+
+ static class Succeed extends AbstractQueue {
+ public boolean offer(Integer x) {
+ if (x == null) throw new NullPointerException();
+ return true;
+ }
+ public Integer peek() { return one; }
+ public Integer poll() { return one; }
+ public int size() { return 0; }
+ public Iterator iterator() { return null; } // not needed
+ }
+
+ static class Fail extends AbstractQueue {
+ public boolean offer(Integer x) {
+ if (x == null) throw new NullPointerException();
+ return false;
+ }
+ public Integer peek() { return null; }
+ public Integer poll() { return null; }
+ public int size() { return 0; }
+ public Iterator iterator() { return null; } // not needed
+ }
+
+ /**
+ * add returns true if offer succeeds
+ */
+ public void testAddS() {
+ Succeed q = new Succeed();
+ assertTrue(q.add(two));
+ }
+
+ /**
+ * add throws ISE true if offer fails
+ */
+ public void testAddF() {
+ Fail q = new Fail();
+ try {
+ q.add(one);
+ shouldThrow();
+ } catch (IllegalStateException success) {}
+ }
+
+ /**
+ * add throws NPE if offer does
+ */
+ public void testAddNPE() {
+ Succeed q = new Succeed();
+ try {
+ q.add(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove returns normally if poll succeeds
+ */
+ public void testRemoveS() {
+ Succeed q = new Succeed();
+ q.remove();
+ }
+
+ /**
+ * remove throws NSEE if poll returns null
+ */
+ public void testRemoveF() {
+ Fail q = new Fail();
+ try {
+ q.remove();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * element returns normally if peek succeeds
+ */
+ public void testElementS() {
+ Succeed q = new Succeed();
+ q.element();
+ }
+
+ /**
+ * element throws NSEE if peek returns null
+ */
+ public void testElementF() {
+ Fail q = new Fail();
+ try {
+ q.element();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * addAll(null) throws NPE
+ */
+ public void testAddAll1() {
+ Succeed q = new Succeed();
+ try {
+ q.addAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * addAll(this) throws IAE
+ */
+ public void testAddAllSelf() {
+ Succeed q = new Succeed();
+ try {
+ q.addAll(q);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * addAll of a collection with null elements throws NPE
+ */
+ public void testAddAll2() {
+ Succeed q = new Succeed();
+ Integer[] ints = new Integer[SIZE];
+ try {
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * addAll of a collection with any null elements throws NPE after
+ * possibly adding some elements
+ */
+ public void testAddAll3() {
+ Succeed q = new Succeed();
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE - 1; ++i)
+ ints[i] = new Integer(i);
+ try {
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * addAll throws ISE if an add fails
+ */
+ public void testAddAll4() {
+ Fail q = new Fail();
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ try {
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ } catch (IllegalStateException success) {}
+ }
+
+}
diff --git a/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java b/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java
new file mode 100644
index 00000000000..88bdd13b4dc
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java
@@ -0,0 +1,1280 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
+import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+ public static Test suite() {
+ return new TestSuite(AbstractQueuedLongSynchronizerTest.class);
+ }
+
+ /**
+ * A simple mutex class, adapted from the class javadoc. Exclusive
+ * acquire tests exercise this as a sample user extension.
+ */
+ static class Mutex extends AbstractQueuedLongSynchronizer {
+ /** An eccentric value > 32 bits for locked synchronizer state. */
+ static final long LOCKED = (1L << 63) | (1L << 15);
+
+ static final long UNLOCKED = 0;
+
+ public boolean isHeldExclusively() {
+ long state = getState();
+ assertTrue(state == UNLOCKED || state == LOCKED);
+ return state == LOCKED;
+ }
+
+ public boolean tryAcquire(long acquires) {
+ assertEquals(LOCKED, acquires);
+ return compareAndSetState(UNLOCKED, LOCKED);
+ }
+
+ public boolean tryRelease(long releases) {
+ if (getState() != LOCKED) throw new IllegalMonitorStateException();
+ setState(UNLOCKED);
+ return true;
+ }
+
+ public boolean tryAcquireNanos(long nanos) throws InterruptedException {
+ return tryAcquireNanos(LOCKED, nanos);
+ }
+
+ public boolean tryAcquire() {
+ return tryAcquire(LOCKED);
+ }
+
+ public boolean tryRelease() {
+ return tryRelease(LOCKED);
+ }
+
+ public void acquire() {
+ acquire(LOCKED);
+ }
+
+ public void acquireInterruptibly() throws InterruptedException {
+ acquireInterruptibly(LOCKED);
+ }
+
+ public void release() {
+ release(LOCKED);
+ }
+
+ public ConditionObject newCondition() {
+ return new ConditionObject();
+ }
+ }
+
+ /**
+ * A simple latch class, to test shared mode.
+ */
+ static class BooleanLatch extends AbstractQueuedLongSynchronizer {
+ public boolean isSignalled() { return getState() != 0; }
+
+ public long tryAcquireShared(long ignore) {
+ return isSignalled() ? 1 : -1;
+ }
+
+ public boolean tryReleaseShared(long ignore) {
+ setState(1L << 62);
+ return true;
+ }
+ }
+
+ /**
+ * A runnable calling acquireInterruptibly that does not expect to
+ * be interrupted.
+ */
+ class InterruptibleSyncRunnable extends CheckedRunnable {
+ final Mutex sync;
+ InterruptibleSyncRunnable(Mutex sync) { this.sync = sync; }
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly();
+ }
+ }
+
+ /**
+ * A runnable calling acquireInterruptibly that expects to be
+ * interrupted.
+ */
+ class InterruptedSyncRunnable extends CheckedInterruptedRunnable {
+ final Mutex sync;
+ InterruptedSyncRunnable(Mutex sync) { this.sync = sync; }
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly();
+ }
+ }
+
+ /** A constant to clarify calls to checking methods below. */
+ static final Thread[] NO_THREADS = new Thread[0];
+
+ /**
+ * Spin-waits until sync.isQueued(t) becomes true.
+ */
+ void waitForQueuedThread(AbstractQueuedLongSynchronizer sync,
+ Thread t) {
+ long startTime = System.nanoTime();
+ while (!sync.isQueued(t)) {
+ if (millisElapsedSince(startTime) > LONG_DELAY_MS)
+ throw new AssertionFailedError("timed out");
+ Thread.yield();
+ }
+ assertTrue(t.isAlive());
+ }
+
+ /**
+ * Checks that sync has exactly the given queued threads.
+ */
+ void assertHasQueuedThreads(AbstractQueuedLongSynchronizer sync,
+ Thread... expected) {
+ Collection actual = sync.getQueuedThreads();
+ assertEquals(expected.length > 0, sync.hasQueuedThreads());
+ assertEquals(expected.length, sync.getQueueLength());
+ assertEquals(expected.length, actual.size());
+ assertEquals(expected.length == 0, actual.isEmpty());
+ assertEquals(new HashSet(actual),
+ new HashSet(Arrays.asList(expected)));
+ }
+
+ /**
+ * Checks that sync has exactly the given (exclusive) queued threads.
+ */
+ void assertHasExclusiveQueuedThreads(AbstractQueuedLongSynchronizer sync,
+ Thread... expected) {
+ assertHasQueuedThreads(sync, expected);
+ assertEquals(new HashSet(sync.getExclusiveQueuedThreads()),
+ new HashSet(sync.getQueuedThreads()));
+ assertEquals(0, sync.getSharedQueuedThreads().size());
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ }
+
+ /**
+ * Checks that sync has exactly the given (shared) queued threads.
+ */
+ void assertHasSharedQueuedThreads(AbstractQueuedLongSynchronizer sync,
+ Thread... expected) {
+ assertHasQueuedThreads(sync, expected);
+ assertEquals(new HashSet(sync.getSharedQueuedThreads()),
+ new HashSet(sync.getQueuedThreads()));
+ assertEquals(0, sync.getExclusiveQueuedThreads().size());
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ }
+
+ /**
+ * Checks that condition c has exactly the given waiter threads,
+ * after acquiring mutex.
+ */
+ void assertHasWaitersUnlocked(Mutex sync, ConditionObject c,
+ Thread... threads) {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, threads);
+ sync.release();
+ }
+
+ /**
+ * Checks that condition c has exactly the given waiter threads.
+ */
+ void assertHasWaitersLocked(Mutex sync, ConditionObject c,
+ Thread... threads) {
+ assertEquals(threads.length > 0, sync.hasWaiters(c));
+ assertEquals(threads.length, sync.getWaitQueueLength(c));
+ assertEquals(threads.length == 0, sync.getWaitingThreads(c).isEmpty());
+ assertEquals(threads.length, sync.getWaitingThreads(c).size());
+ assertEquals(new HashSet(sync.getWaitingThreads(c)),
+ new HashSet(Arrays.asList(threads)));
+ }
+
+ enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil }
+
+ /**
+ * Awaits condition using the specified AwaitMethod.
+ */
+ void await(ConditionObject c, AwaitMethod awaitMethod)
+ throws InterruptedException {
+ long timeoutMillis = 2 * LONG_DELAY_MS;
+ switch (awaitMethod) {
+ case await:
+ c.await();
+ break;
+ case awaitTimed:
+ assertTrue(c.await(timeoutMillis, MILLISECONDS));
+ break;
+ case awaitNanos:
+ long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+ long nanosRemaining = c.awaitNanos(nanosTimeout);
+ assertTrue(nanosRemaining > 0);
+ break;
+ case awaitUntil:
+ assertTrue(c.awaitUntil(delayedDate(timeoutMillis)));
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Checks that awaiting the given condition times out (using the
+ * default timeout duration).
+ */
+ void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
+ long timeoutMillis = timeoutMillis();
+ long startTime;
+ try {
+ switch (awaitMethod) {
+ case awaitTimed:
+ startTime = System.nanoTime();
+ assertFalse(c.await(timeoutMillis, MILLISECONDS));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ break;
+ case awaitNanos:
+ startTime = System.nanoTime();
+ long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+ long nanosRemaining = c.awaitNanos(nanosTimeout);
+ assertTrue(nanosRemaining <= 0);
+ assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ break;
+ case awaitUntil:
+ // We shouldn't assume that nanoTime and currentTimeMillis
+ // use the same time source, so don't use nanoTime here.
+ java.util.Date delayedDate = delayedDate(timeoutMillis());
+ assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
+ assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+ break;
+ default:
+ throw new UnsupportedOperationException();
+ }
+ } catch (InterruptedException ie) { threadUnexpectedException(ie); }
+ }
+
+ /**
+ * isHeldExclusively is false upon construction
+ */
+ public void testIsHeldExclusively() {
+ Mutex sync = new Mutex();
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * acquiring released sync succeeds
+ */
+ public void testAcquire() {
+ Mutex sync = new Mutex();
+ sync.acquire();
+ assertTrue(sync.isHeldExclusively());
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * tryAcquire on a released sync succeeds
+ */
+ public void testTryAcquire() {
+ Mutex sync = new Mutex();
+ assertTrue(sync.tryAcquire());
+ assertTrue(sync.isHeldExclusively());
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * hasQueuedThreads reports whether there are waiting threads
+ */
+ public void testHasQueuedThreads() {
+ final Mutex sync = new Mutex();
+ assertFalse(sync.hasQueuedThreads());
+ sync.acquire();
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.hasQueuedThreads());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.hasQueuedThreads());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertTrue(sync.hasQueuedThreads());
+ sync.release();
+ awaitTermination(t2);
+ assertFalse(sync.hasQueuedThreads());
+ }
+
+ /**
+ * isQueued(null) throws NullPointerException
+ */
+ public void testIsQueuedNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.isQueued(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * isQueued reports whether a thread is queued
+ */
+ public void testIsQueued() {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertFalse(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ sync.acquire();
+ t1.start();
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ t2.start();
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ t1.interrupt();
+ awaitTermination(t1);
+ assertFalse(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ sync.release();
+ awaitTermination(t2);
+ assertFalse(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ }
+
+ /**
+ * getFirstQueuedThread returns first waiting thread or null if none
+ */
+ public void testGetFirstQueuedThread() {
+ final Mutex sync = new Mutex();
+ assertNull(sync.getFirstQueuedThread());
+ sync.acquire();
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertEquals(t2, sync.getFirstQueuedThread());
+ sync.release();
+ awaitTermination(t2);
+ assertNull(sync.getFirstQueuedThread());
+ }
+
+ /**
+ * hasContended reports false if no thread has ever blocked, else true
+ */
+ public void testHasContended() {
+ final Mutex sync = new Mutex();
+ assertFalse(sync.hasContended());
+ sync.acquire();
+ assertFalse(sync.hasContended());
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.hasContended());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.hasContended());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertTrue(sync.hasContended());
+ sync.release();
+ awaitTermination(t2);
+ assertTrue(sync.hasContended());
+ }
+
+ /**
+ * getQueuedThreads returns all waiting threads
+ */
+ public void testGetQueuedThreads() {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ sync.acquire();
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ t1.start();
+ waitForQueuedThread(sync, t1);
+ assertHasExclusiveQueuedThreads(sync, t1);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ assertFalse(sync.getQueuedThreads().contains(t2));
+ t2.start();
+ waitForQueuedThread(sync, t2);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ assertTrue(sync.getQueuedThreads().contains(t2));
+ t1.interrupt();
+ awaitTermination(t1);
+ assertHasExclusiveQueuedThreads(sync, t2);
+ sync.release();
+ awaitTermination(t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ }
+
+ /**
+ * getExclusiveQueuedThreads returns all exclusive waiting threads
+ */
+ public void testGetExclusiveQueuedThreads() {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ sync.acquire();
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ t1.start();
+ waitForQueuedThread(sync, t1);
+ assertHasExclusiveQueuedThreads(sync, t1);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ assertFalse(sync.getExclusiveQueuedThreads().contains(t2));
+ t2.start();
+ waitForQueuedThread(sync, t2);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+ t1.interrupt();
+ awaitTermination(t1);
+ assertHasExclusiveQueuedThreads(sync, t2);
+ sync.release();
+ awaitTermination(t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ }
+
+ /**
+ * getSharedQueuedThreads does not include exclusively waiting threads
+ */
+ public void testGetSharedQueuedThreads_Exclusive() {
+ final Mutex sync = new Mutex();
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.acquire();
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.release();
+ awaitTermination(t2);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ }
+
+ /**
+ * getSharedQueuedThreads returns all shared waiting threads
+ */
+ public void testGetSharedQueuedThreads_Shared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertHasSharedQueuedThreads(l, NO_THREADS);
+ Thread t1 = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ l.acquireSharedInterruptibly(0);
+ }});
+ waitForQueuedThread(l, t1);
+ assertHasSharedQueuedThreads(l, t1);
+ Thread t2 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ l.acquireSharedInterruptibly(0);
+ }});
+ waitForQueuedThread(l, t2);
+ assertHasSharedQueuedThreads(l, t1, t2);
+ t1.interrupt();
+ awaitTermination(t1);
+ assertHasSharedQueuedThreads(l, t2);
+ assertTrue(l.releaseShared(0));
+ awaitTermination(t2);
+ assertHasSharedQueuedThreads(l, NO_THREADS);
+ }
+
+ /**
+ * tryAcquireNanos is interruptible
+ */
+ public void testTryAcquireNanos_Interruptible() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.tryAcquireNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS));
+ }});
+
+ waitForQueuedThread(sync, t);
+ t.interrupt();
+ awaitTermination(t);
+ }
+
+ /**
+ * tryAcquire on exclusively held sync fails
+ */
+ public void testTryAcquireWhenSynced() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() {
+ assertFalse(sync.tryAcquire());
+ }});
+
+ awaitTermination(t);
+ sync.release();
+ }
+
+ /**
+ * tryAcquireNanos on an exclusively held sync times out
+ */
+ public void testAcquireNanos_Timeout() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ long startTime = System.nanoTime();
+ long nanos = MILLISECONDS.toNanos(timeoutMillis());
+ assertFalse(sync.tryAcquireNanos(nanos));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+ }});
+
+ awaitTermination(t);
+ sync.release();
+ }
+
+ /**
+ * getState is true when acquired and false when not
+ */
+ public void testGetState() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ assertTrue(sync.isHeldExclusively());
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+
+ final BooleanLatch acquired = new BooleanLatch();
+ final BooleanLatch done = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertTrue(acquired.releaseShared(0));
+ done.acquireShared(0);
+ sync.release();
+ }});
+
+ acquired.acquireShared(0);
+ assertTrue(sync.isHeldExclusively());
+ assertTrue(done.releaseShared(0));
+ awaitTermination(t);
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * acquireInterruptibly succeeds when released, else is interruptible
+ */
+ public void testAcquireInterruptibly() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final BooleanLatch threadStarted = new BooleanLatch();
+ sync.acquireInterruptibly();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertTrue(threadStarted.releaseShared(0));
+ sync.acquireInterruptibly();
+ }});
+
+ threadStarted.acquireShared(0);
+ waitForQueuedThread(sync, t);
+ t.interrupt();
+ awaitTermination(t);
+ assertTrue(sync.isHeldExclusively());
+ }
+
+ /**
+ * owns is true for a condition created by sync else false
+ */
+ public void testOwns() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ assertTrue(sync.owns(c));
+ assertFalse(sync2.owns(c));
+ }
+
+ /**
+ * Calling await without holding sync throws IllegalMonitorStateException
+ */
+ public void testAwait_IMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ for (AwaitMethod awaitMethod : AwaitMethod.values()) {
+ long startTime = System.nanoTime();
+ try {
+ await(c, awaitMethod);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {
+ } catch (InterruptedException e) { threadUnexpectedException(e); }
+ assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+ }
+ }
+
+ /**
+ * Calling signal without holding sync throws IllegalMonitorStateException
+ */
+ public void testSignal_IMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ c.signal();
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * Calling signalAll without holding sync throws IllegalMonitorStateException
+ */
+ public void testSignalAll_IMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ c.signalAll();
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ }
+
+ /**
+ * await/awaitNanos/awaitUntil without a signal times out
+ */
+ public void testAwaitTimed_Timeout() { testAwait_Timeout(AwaitMethod.awaitTimed); }
+ public void testAwaitNanos_Timeout() { testAwait_Timeout(AwaitMethod.awaitNanos); }
+ public void testAwaitUntil_Timeout() { testAwait_Timeout(AwaitMethod.awaitUntil); }
+ public void testAwait_Timeout(AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ sync.acquire();
+ assertAwaitTimesOut(c, awaitMethod);
+ sync.release();
+ }
+
+ /**
+ * await/awaitNanos/awaitUntil returns when signalled
+ */
+ public void testSignal_await() { testSignal(AwaitMethod.await); }
+ public void testSignal_awaitTimed() { testSignal(AwaitMethod.awaitTimed); }
+ public void testSignal_awaitNanos() { testSignal(AwaitMethod.awaitNanos); }
+ public void testSignal_awaitUntil() { testSignal(AwaitMethod.awaitUntil); }
+ public void testSignal(final AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertTrue(acquired.releaseShared(0));
+ await(c, awaitMethod);
+ sync.release();
+ }});
+
+ acquired.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ c.signal();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t);
+ sync.release();
+ awaitTermination(t);
+ }
+
+ /**
+ * hasWaiters(null) throws NullPointerException
+ */
+ public void testHasWaitersNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.hasWaiters(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * getWaitQueueLength(null) throws NullPointerException
+ */
+ public void testGetWaitQueueLengthNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.getWaitQueueLength(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * getWaitingThreads throws NPE if null
+ */
+ public void testGetWaitingThreadsNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.getWaitingThreads(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * hasWaiters throws IllegalArgumentException if not owned
+ */
+ public void testHasWaitersIAE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.hasWaiters(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * hasWaiters throws IllegalMonitorStateException if not synced
+ */
+ public void testHasWaitersIMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ sync.hasWaiters(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitQueueLength throws IllegalArgumentException if not owned
+ */
+ public void testGetWaitQueueLengthIAE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.getWaitQueueLength(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitQueueLength throws IllegalMonitorStateException if not synced
+ */
+ public void testGetWaitQueueLengthIMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ sync.getWaitQueueLength(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitingThreads throws IllegalArgumentException if not owned
+ */
+ public void testGetWaitingThreadsIAE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.getWaitingThreads(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitingThreads throws IllegalMonitorStateException if not synced
+ */
+ public void testGetWaitingThreadsIMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ sync.getWaitingThreads(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * hasWaiters returns true when a thread is waiting, else false
+ */
+ public void testHasWaiters() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertFalse(sync.hasWaiters(c));
+ assertTrue(acquired.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+
+ acquired.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertTrue(sync.hasWaiters(c));
+ c.signal();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t);
+ assertFalse(sync.hasWaiters(c));
+ sync.release();
+
+ awaitTermination(t);
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitQueueLength returns number of waiting threads
+ */
+ public void testGetWaitQueueLength() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired1 = new BooleanLatch();
+ final BooleanLatch acquired2 = new BooleanLatch();
+ final Thread t1 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertEquals(0, sync.getWaitQueueLength(c));
+ assertTrue(acquired1.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+ acquired1.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertEquals(1, sync.getWaitQueueLength(c));
+ sync.release();
+
+ final Thread t2 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertEquals(1, sync.getWaitQueueLength(c));
+ assertTrue(acquired2.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+ acquired2.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1, t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertEquals(2, sync.getWaitQueueLength(c));
+ c.signalAll();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertEquals(0, sync.getWaitQueueLength(c));
+ sync.release();
+
+ awaitTermination(t1);
+ awaitTermination(t2);
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitingThreads returns only and all waiting threads
+ */
+ public void testGetWaitingThreads() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired1 = new BooleanLatch();
+ final BooleanLatch acquired2 = new BooleanLatch();
+ final Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ assertTrue(acquired1.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+
+ final Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(1, sync.getWaitingThreads(c).size());
+ assertTrue(acquired2.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertFalse(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).contains(t2));
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(0, sync.getWaitingThreads(c).size());
+ sync.release();
+
+ t1.start();
+ acquired1.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).contains(t2));
+ assertFalse(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(1, sync.getWaitingThreads(c).size());
+ sync.release();
+
+ t2.start();
+ acquired2.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1, t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertTrue(sync.getWaitingThreads(c).contains(t2));
+ assertFalse(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(2, sync.getWaitingThreads(c).size());
+ c.signalAll();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertFalse(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).contains(t2));
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(0, sync.getWaitingThreads(c).size());
+ sync.release();
+
+ awaitTermination(t1);
+ awaitTermination(t2);
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * awaitUninterruptibly is uninterruptible
+ */
+ public void testAwaitUninterruptibly() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch pleaseInterrupt = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() {
+ sync.acquire();
+ assertTrue(pleaseInterrupt.releaseShared(0));
+ c.awaitUninterruptibly();
+ assertTrue(Thread.interrupted());
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ sync.release();
+ }});
+
+ pleaseInterrupt.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ sync.release();
+ t.interrupt();
+ assertHasWaitersUnlocked(sync, c, t);
+ assertThreadStaysAlive(t);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ c.signal();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t);
+ sync.release();
+ awaitTermination(t);
+ }
+
+ /**
+ * await/awaitNanos/awaitUntil is interruptible
+ */
+ public void testInterruptible_await() { testInterruptible(AwaitMethod.await); }
+ public void testInterruptible_awaitTimed() { testInterruptible(AwaitMethod.awaitTimed); }
+ public void testInterruptible_awaitNanos() { testInterruptible(AwaitMethod.awaitNanos); }
+ public void testInterruptible_awaitUntil() { testInterruptible(AwaitMethod.awaitUntil); }
+ public void testInterruptible(final AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch pleaseInterrupt = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertTrue(pleaseInterrupt.releaseShared(0));
+ await(c, awaitMethod);
+ }});
+
+ pleaseInterrupt.acquireShared(0);
+ t.interrupt();
+ awaitTermination(t);
+ }
+
+ /**
+ * signalAll wakes up all threads
+ */
+ public void testSignalAll_await() { testSignalAll(AwaitMethod.await); }
+ public void testSignalAll_awaitTimed() { testSignalAll(AwaitMethod.awaitTimed); }
+ public void testSignalAll_awaitNanos() { testSignalAll(AwaitMethod.awaitNanos); }
+ public void testSignalAll_awaitUntil() { testSignalAll(AwaitMethod.awaitUntil); }
+ public void testSignalAll(final AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired1 = new BooleanLatch();
+ final BooleanLatch acquired2 = new BooleanLatch();
+ Thread t1 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ acquired1.releaseShared(0);
+ await(c, awaitMethod);
+ sync.release();
+ }});
+
+ Thread t2 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ acquired2.releaseShared(0);
+ await(c, awaitMethod);
+ sync.release();
+ }});
+
+ acquired1.acquireShared(0);
+ acquired2.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1, t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ c.signalAll();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ sync.release();
+ awaitTermination(t1);
+ awaitTermination(t2);
+ }
+
+ /**
+ * toString indicates current state
+ */
+ public void testToString() {
+ Mutex sync = new Mutex();
+ assertTrue(sync.toString().contains("State = " + Mutex.UNLOCKED));
+ sync.acquire();
+ assertTrue(sync.toString().contains("State = " + Mutex.LOCKED));
+ }
+
+ /**
+ * A serialized AQS deserializes with current state, but no queued threads
+ */
+ public void testSerialization() {
+ Mutex sync = new Mutex();
+ assertFalse(serialClone(sync).isHeldExclusively());
+ sync.acquire();
+ Thread t = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t);
+ assertTrue(sync.isHeldExclusively());
+
+ Mutex clone = serialClone(sync);
+ assertTrue(clone.isHeldExclusively());
+ assertHasExclusiveQueuedThreads(sync, t);
+ assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+ t.interrupt();
+ awaitTermination(t);
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+ assertTrue(clone.isHeldExclusively());
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+ }
+
+ /**
+ * tryReleaseShared setting state changes getState
+ */
+ public void testGetStateWithReleaseShared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertFalse(l.isSignalled());
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ }
+
+ /**
+ * releaseShared has no effect when already signalled
+ */
+ public void testReleaseShared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertFalse(l.isSignalled());
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ }
+
+ /**
+ * acquireSharedInterruptibly returns after release, but not before
+ */
+ public void testAcquireSharedInterruptibly() {
+ final BooleanLatch l = new BooleanLatch();
+
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ assertTrue(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ assertTrue(l.isSignalled());
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ assertThreadStaysAlive(t);
+ assertHasSharedQueuedThreads(l, t);
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ awaitTermination(t);
+ }
+
+ /**
+ * tryAcquireSharedNanos returns after release, but not before
+ */
+ public void testTryAcquireSharedNanos() {
+ final BooleanLatch l = new BooleanLatch();
+
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+ assertTrue(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(l.isSignalled());
+ assertTrue(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(l.isSignalled());
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ assertThreadStaysAlive(t);
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ awaitTermination(t);
+ }
+
+ /**
+ * acquireSharedInterruptibly is interruptible
+ */
+ public void testAcquireSharedInterruptibly_Interruptible() {
+ final BooleanLatch l = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ awaitTermination(t);
+ assertFalse(l.isSignalled());
+ }
+
+ /**
+ * tryAcquireSharedNanos is interruptible
+ */
+ public void testTryAcquireSharedNanos_Interruptible() {
+ final BooleanLatch l = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+ l.tryAcquireSharedNanos(0, nanos);
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ awaitTermination(t);
+ assertFalse(l.isSignalled());
+ }
+
+ /**
+ * tryAcquireSharedNanos times out if not released before timeout
+ */
+ public void testTryAcquireSharedNanos_Timeout() {
+ final BooleanLatch l = new BooleanLatch();
+ final BooleanLatch observedQueued = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ for (long millis = timeoutMillis();
+ !observedQueued.isSignalled();
+ millis *= 2) {
+ long nanos = MILLISECONDS.toNanos(millis);
+ long startTime = System.nanoTime();
+ assertFalse(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(millisElapsedSince(startTime) >= millis);
+ }
+ assertFalse(l.isSignalled());
+ }});
+
+ waitForQueuedThread(l, t);
+ observedQueued.releaseShared(0);
+ assertFalse(l.isSignalled());
+ awaitTermination(t);
+ assertFalse(l.isSignalled());
+ }
+
+ /**
+ * awaitNanos/timed await with 0 wait times out immediately
+ */
+ public void testAwait_Zero() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ sync.acquire();
+ assertTrue(c.awaitNanos(0L) <= 0);
+ assertFalse(c.await(0L, NANOSECONDS));
+ sync.release();
+ }
+
+ /**
+ * awaitNanos/timed await with maximum negative wait times does not underflow
+ */
+ public void testAwait_NegativeInfinity() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ sync.acquire();
+ assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0);
+ assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS));
+ sync.release();
+ }
+
+}
diff --git a/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java b/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java
new file mode 100644
index 00000000000..8341a7e296c
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java
@@ -0,0 +1,1283 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+ public static Test suite() {
+ return new TestSuite(AbstractQueuedSynchronizerTest.class);
+ }
+
+ /**
+ * A simple mutex class, adapted from the class javadoc. Exclusive
+ * acquire tests exercise this as a sample user extension. Other
+ * methods/features of AbstractQueuedSynchronizer are tested via
+ * other test classes, including those for ReentrantLock,
+ * ReentrantReadWriteLock, and Semaphore.
+ */
+ static class Mutex extends AbstractQueuedSynchronizer {
+ /** An eccentric value for locked synchronizer state. */
+ static final int LOCKED = (1 << 31) | (1 << 15);
+
+ static final int UNLOCKED = 0;
+
+ @Override public boolean isHeldExclusively() {
+ int state = getState();
+ assertTrue(state == UNLOCKED || state == LOCKED);
+ return state == LOCKED;
+ }
+
+ @Override public boolean tryAcquire(int acquires) {
+ assertEquals(LOCKED, acquires);
+ return compareAndSetState(UNLOCKED, LOCKED);
+ }
+
+ @Override public boolean tryRelease(int releases) {
+ if (getState() != LOCKED) throw new IllegalMonitorStateException();
+ assertEquals(LOCKED, releases);
+ setState(UNLOCKED);
+ return true;
+ }
+
+ public boolean tryAcquireNanos(long nanos) throws InterruptedException {
+ return tryAcquireNanos(LOCKED, nanos);
+ }
+
+ public boolean tryAcquire() {
+ return tryAcquire(LOCKED);
+ }
+
+ public boolean tryRelease() {
+ return tryRelease(LOCKED);
+ }
+
+ public void acquire() {
+ acquire(LOCKED);
+ }
+
+ public void acquireInterruptibly() throws InterruptedException {
+ acquireInterruptibly(LOCKED);
+ }
+
+ public void release() {
+ release(LOCKED);
+ }
+
+ public ConditionObject newCondition() {
+ return new ConditionObject();
+ }
+ }
+
+ /**
+ * A simple latch class, to test shared mode.
+ */
+ static class BooleanLatch extends AbstractQueuedSynchronizer {
+ public boolean isSignalled() { return getState() != 0; }
+
+ public int tryAcquireShared(int ignore) {
+ return isSignalled() ? 1 : -1;
+ }
+
+ public boolean tryReleaseShared(int ignore) {
+ setState(1);
+ return true;
+ }
+ }
+
+ /**
+ * A runnable calling acquireInterruptibly that does not expect to
+ * be interrupted.
+ */
+ class InterruptibleSyncRunnable extends CheckedRunnable {
+ final Mutex sync;
+ InterruptibleSyncRunnable(Mutex sync) { this.sync = sync; }
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly();
+ }
+ }
+
+ /**
+ * A runnable calling acquireInterruptibly that expects to be
+ * interrupted.
+ */
+ class InterruptedSyncRunnable extends CheckedInterruptedRunnable {
+ final Mutex sync;
+ InterruptedSyncRunnable(Mutex sync) { this.sync = sync; }
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly();
+ }
+ }
+
+ /** A constant to clarify calls to checking methods below. */
+ static final Thread[] NO_THREADS = new Thread[0];
+
+ /**
+ * Spin-waits until sync.isQueued(t) becomes true.
+ */
+ void waitForQueuedThread(AbstractQueuedSynchronizer sync, Thread t) {
+ long startTime = System.nanoTime();
+ while (!sync.isQueued(t)) {
+ if (millisElapsedSince(startTime) > LONG_DELAY_MS)
+ throw new AssertionFailedError("timed out");
+ Thread.yield();
+ }
+ assertTrue(t.isAlive());
+ }
+
+ /**
+ * Checks that sync has exactly the given queued threads.
+ */
+ void assertHasQueuedThreads(AbstractQueuedSynchronizer sync,
+ Thread... expected) {
+ Collection actual = sync.getQueuedThreads();
+ assertEquals(expected.length > 0, sync.hasQueuedThreads());
+ assertEquals(expected.length, sync.getQueueLength());
+ assertEquals(expected.length, actual.size());
+ assertEquals(expected.length == 0, actual.isEmpty());
+ assertEquals(new HashSet(actual),
+ new HashSet(Arrays.asList(expected)));
+ }
+
+ /**
+ * Checks that sync has exactly the given (exclusive) queued threads.
+ */
+ void assertHasExclusiveQueuedThreads(AbstractQueuedSynchronizer sync,
+ Thread... expected) {
+ assertHasQueuedThreads(sync, expected);
+ assertEquals(new HashSet(sync.getExclusiveQueuedThreads()),
+ new HashSet(sync.getQueuedThreads()));
+ assertEquals(0, sync.getSharedQueuedThreads().size());
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ }
+
+ /**
+ * Checks that sync has exactly the given (shared) queued threads.
+ */
+ void assertHasSharedQueuedThreads(AbstractQueuedSynchronizer sync,
+ Thread... expected) {
+ assertHasQueuedThreads(sync, expected);
+ assertEquals(new HashSet(sync.getSharedQueuedThreads()),
+ new HashSet(sync.getQueuedThreads()));
+ assertEquals(0, sync.getExclusiveQueuedThreads().size());
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ }
+
+ /**
+ * Checks that condition c has exactly the given waiter threads,
+ * after acquiring mutex.
+ */
+ void assertHasWaitersUnlocked(Mutex sync, ConditionObject c,
+ Thread... threads) {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, threads);
+ sync.release();
+ }
+
+ /**
+ * Checks that condition c has exactly the given waiter threads.
+ */
+ void assertHasWaitersLocked(Mutex sync, ConditionObject c,
+ Thread... threads) {
+ assertEquals(threads.length > 0, sync.hasWaiters(c));
+ assertEquals(threads.length, sync.getWaitQueueLength(c));
+ assertEquals(threads.length == 0, sync.getWaitingThreads(c).isEmpty());
+ assertEquals(threads.length, sync.getWaitingThreads(c).size());
+ assertEquals(new HashSet(sync.getWaitingThreads(c)),
+ new HashSet(Arrays.asList(threads)));
+ }
+
+ enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil }
+
+ /**
+ * Awaits condition using the specified AwaitMethod.
+ */
+ void await(ConditionObject c, AwaitMethod awaitMethod)
+ throws InterruptedException {
+ long timeoutMillis = 2 * LONG_DELAY_MS;
+ switch (awaitMethod) {
+ case await:
+ c.await();
+ break;
+ case awaitTimed:
+ assertTrue(c.await(timeoutMillis, MILLISECONDS));
+ break;
+ case awaitNanos:
+ long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+ long nanosRemaining = c.awaitNanos(nanosTimeout);
+ assertTrue(nanosRemaining > 0);
+ break;
+ case awaitUntil:
+ assertTrue(c.awaitUntil(delayedDate(timeoutMillis)));
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Checks that awaiting the given condition times out (using the
+ * default timeout duration).
+ */
+ void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
+ long timeoutMillis = timeoutMillis();
+ long startTime;
+ try {
+ switch (awaitMethod) {
+ case awaitTimed:
+ startTime = System.nanoTime();
+ assertFalse(c.await(timeoutMillis, MILLISECONDS));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ break;
+ case awaitNanos:
+ startTime = System.nanoTime();
+ long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis);
+ long nanosRemaining = c.awaitNanos(nanosTimeout);
+ assertTrue(nanosRemaining <= 0);
+ assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ break;
+ case awaitUntil:
+ // We shouldn't assume that nanoTime and currentTimeMillis
+ // use the same time source, so don't use nanoTime here.
+ java.util.Date delayedDate = delayedDate(timeoutMillis());
+ assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
+ assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+ break;
+ default:
+ throw new UnsupportedOperationException();
+ }
+ } catch (InterruptedException ie) { threadUnexpectedException(ie); }
+ }
+
+ /**
+ * isHeldExclusively is false upon construction
+ */
+ public void testIsHeldExclusively() {
+ Mutex sync = new Mutex();
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * acquiring released sync succeeds
+ */
+ public void testAcquire() {
+ Mutex sync = new Mutex();
+ sync.acquire();
+ assertTrue(sync.isHeldExclusively());
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * tryAcquire on a released sync succeeds
+ */
+ public void testTryAcquire() {
+ Mutex sync = new Mutex();
+ assertTrue(sync.tryAcquire());
+ assertTrue(sync.isHeldExclusively());
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * hasQueuedThreads reports whether there are waiting threads
+ */
+ public void testHasQueuedThreads() {
+ final Mutex sync = new Mutex();
+ assertFalse(sync.hasQueuedThreads());
+ sync.acquire();
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.hasQueuedThreads());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.hasQueuedThreads());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertTrue(sync.hasQueuedThreads());
+ sync.release();
+ awaitTermination(t2);
+ assertFalse(sync.hasQueuedThreads());
+ }
+
+ /**
+ * isQueued(null) throws NullPointerException
+ */
+ public void testIsQueuedNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.isQueued(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * isQueued reports whether a thread is queued
+ */
+ public void testIsQueued() {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertFalse(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ sync.acquire();
+ t1.start();
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ t2.start();
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ t1.interrupt();
+ awaitTermination(t1);
+ assertFalse(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ sync.release();
+ awaitTermination(t2);
+ assertFalse(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ }
+
+ /**
+ * getFirstQueuedThread returns first waiting thread or null if none
+ */
+ public void testGetFirstQueuedThread() {
+ final Mutex sync = new Mutex();
+ assertNull(sync.getFirstQueuedThread());
+ sync.acquire();
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertEquals(t2, sync.getFirstQueuedThread());
+ sync.release();
+ awaitTermination(t2);
+ assertNull(sync.getFirstQueuedThread());
+ }
+
+ /**
+ * hasContended reports false if no thread has ever blocked, else true
+ */
+ public void testHasContended() {
+ final Mutex sync = new Mutex();
+ assertFalse(sync.hasContended());
+ sync.acquire();
+ assertFalse(sync.hasContended());
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.hasContended());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.hasContended());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertTrue(sync.hasContended());
+ sync.release();
+ awaitTermination(t2);
+ assertTrue(sync.hasContended());
+ }
+
+ /**
+ * getQueuedThreads returns all waiting threads
+ */
+ public void testGetQueuedThreads() {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ sync.acquire();
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ t1.start();
+ waitForQueuedThread(sync, t1);
+ assertHasExclusiveQueuedThreads(sync, t1);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ assertFalse(sync.getQueuedThreads().contains(t2));
+ t2.start();
+ waitForQueuedThread(sync, t2);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ assertTrue(sync.getQueuedThreads().contains(t2));
+ t1.interrupt();
+ awaitTermination(t1);
+ assertHasExclusiveQueuedThreads(sync, t2);
+ sync.release();
+ awaitTermination(t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ }
+
+ /**
+ * getExclusiveQueuedThreads returns all exclusive waiting threads
+ */
+ public void testGetExclusiveQueuedThreads() {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ sync.acquire();
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ t1.start();
+ waitForQueuedThread(sync, t1);
+ assertHasExclusiveQueuedThreads(sync, t1);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ assertFalse(sync.getExclusiveQueuedThreads().contains(t2));
+ t2.start();
+ waitForQueuedThread(sync, t2);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+ t1.interrupt();
+ awaitTermination(t1);
+ assertHasExclusiveQueuedThreads(sync, t2);
+ sync.release();
+ awaitTermination(t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ }
+
+ /**
+ * getSharedQueuedThreads does not include exclusively waiting threads
+ */
+ public void testGetSharedQueuedThreads_Exclusive() {
+ final Mutex sync = new Mutex();
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.acquire();
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t1);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync));
+ waitForQueuedThread(sync, t2);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.interrupt();
+ awaitTermination(t1);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.release();
+ awaitTermination(t2);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ }
+
+ /**
+ * getSharedQueuedThreads returns all shared waiting threads
+ */
+ public void testGetSharedQueuedThreads_Shared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertHasSharedQueuedThreads(l, NO_THREADS);
+ Thread t1 = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ l.acquireSharedInterruptibly(0);
+ }});
+ waitForQueuedThread(l, t1);
+ assertHasSharedQueuedThreads(l, t1);
+ Thread t2 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ l.acquireSharedInterruptibly(0);
+ }});
+ waitForQueuedThread(l, t2);
+ assertHasSharedQueuedThreads(l, t1, t2);
+ t1.interrupt();
+ awaitTermination(t1);
+ assertHasSharedQueuedThreads(l, t2);
+ assertTrue(l.releaseShared(0));
+ awaitTermination(t2);
+ assertHasSharedQueuedThreads(l, NO_THREADS);
+ }
+
+ /**
+ * tryAcquireNanos is interruptible
+ */
+ public void testTryAcquireNanos_Interruptible() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.tryAcquireNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS));
+ }});
+
+ waitForQueuedThread(sync, t);
+ t.interrupt();
+ awaitTermination(t);
+ }
+
+ /**
+ * tryAcquire on exclusively held sync fails
+ */
+ public void testTryAcquireWhenSynced() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() {
+ assertFalse(sync.tryAcquire());
+ }});
+
+ awaitTermination(t);
+ sync.release();
+ }
+
+ /**
+ * tryAcquireNanos on an exclusively held sync times out
+ */
+ public void testAcquireNanos_Timeout() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ long startTime = System.nanoTime();
+ long nanos = MILLISECONDS.toNanos(timeoutMillis());
+ assertFalse(sync.tryAcquireNanos(nanos));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+ }});
+
+ awaitTermination(t);
+ sync.release();
+ }
+
+ /**
+ * getState is true when acquired and false when not
+ */
+ public void testGetState() {
+ final Mutex sync = new Mutex();
+ sync.acquire();
+ assertTrue(sync.isHeldExclusively());
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+
+ final BooleanLatch acquired = new BooleanLatch();
+ final BooleanLatch done = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertTrue(acquired.releaseShared(0));
+ done.acquireShared(0);
+ sync.release();
+ }});
+
+ acquired.acquireShared(0);
+ assertTrue(sync.isHeldExclusively());
+ assertTrue(done.releaseShared(0));
+ awaitTermination(t);
+ assertFalse(sync.isHeldExclusively());
+ }
+
+ /**
+ * acquireInterruptibly succeeds when released, else is interruptible
+ */
+ public void testAcquireInterruptibly() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final BooleanLatch threadStarted = new BooleanLatch();
+ sync.acquireInterruptibly();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertTrue(threadStarted.releaseShared(0));
+ sync.acquireInterruptibly();
+ }});
+
+ threadStarted.acquireShared(0);
+ waitForQueuedThread(sync, t);
+ t.interrupt();
+ awaitTermination(t);
+ assertTrue(sync.isHeldExclusively());
+ }
+
+ /**
+ * owns is true for a condition created by sync else false
+ */
+ public void testOwns() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ assertTrue(sync.owns(c));
+ assertFalse(sync2.owns(c));
+ }
+
+ /**
+ * Calling await without holding sync throws IllegalMonitorStateException
+ */
+ public void testAwait_IMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ for (AwaitMethod awaitMethod : AwaitMethod.values()) {
+ long startTime = System.nanoTime();
+ try {
+ await(c, awaitMethod);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {
+ } catch (InterruptedException e) { threadUnexpectedException(e); }
+ assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+ }
+ }
+
+ /**
+ * Calling signal without holding sync throws IllegalMonitorStateException
+ */
+ public void testSignal_IMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ c.signal();
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * Calling signalAll without holding sync throws IllegalMonitorStateException
+ */
+ public void testSignalAll_IMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ c.signalAll();
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ }
+
+ /**
+ * await/awaitNanos/awaitUntil without a signal times out
+ */
+ public void testAwaitTimed_Timeout() { testAwait_Timeout(AwaitMethod.awaitTimed); }
+ public void testAwaitNanos_Timeout() { testAwait_Timeout(AwaitMethod.awaitNanos); }
+ public void testAwaitUntil_Timeout() { testAwait_Timeout(AwaitMethod.awaitUntil); }
+ public void testAwait_Timeout(AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ sync.acquire();
+ assertAwaitTimesOut(c, awaitMethod);
+ sync.release();
+ }
+
+ /**
+ * await/awaitNanos/awaitUntil returns when signalled
+ */
+ public void testSignal_await() { testSignal(AwaitMethod.await); }
+ public void testSignal_awaitTimed() { testSignal(AwaitMethod.awaitTimed); }
+ public void testSignal_awaitNanos() { testSignal(AwaitMethod.awaitNanos); }
+ public void testSignal_awaitUntil() { testSignal(AwaitMethod.awaitUntil); }
+ public void testSignal(final AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertTrue(acquired.releaseShared(0));
+ await(c, awaitMethod);
+ sync.release();
+ }});
+
+ acquired.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ c.signal();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t);
+ sync.release();
+ awaitTermination(t);
+ }
+
+ /**
+ * hasWaiters(null) throws NullPointerException
+ */
+ public void testHasWaitersNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.hasWaiters(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * getWaitQueueLength(null) throws NullPointerException
+ */
+ public void testGetWaitQueueLengthNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.getWaitQueueLength(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * getWaitingThreads(null) throws NullPointerException
+ */
+ public void testGetWaitingThreadsNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.getWaitingThreads(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * hasWaiters throws IllegalArgumentException if not owned
+ */
+ public void testHasWaitersIAE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.hasWaiters(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * hasWaiters throws IllegalMonitorStateException if not synced
+ */
+ public void testHasWaitersIMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ sync.hasWaiters(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitQueueLength throws IllegalArgumentException if not owned
+ */
+ public void testGetWaitQueueLengthIAE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.getWaitQueueLength(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitQueueLength throws IllegalMonitorStateException if not synced
+ */
+ public void testGetWaitQueueLengthIMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ sync.getWaitQueueLength(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitingThreads throws IllegalArgumentException if not owned
+ */
+ public void testGetWaitingThreadsIAE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.getWaitingThreads(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitingThreads throws IllegalMonitorStateException if not synced
+ */
+ public void testGetWaitingThreadsIMSE() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ try {
+ sync.getWaitingThreads(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * hasWaiters returns true when a thread is waiting, else false
+ */
+ public void testHasWaiters() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertFalse(sync.hasWaiters(c));
+ assertTrue(acquired.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+
+ acquired.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertTrue(sync.hasWaiters(c));
+ c.signal();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t);
+ assertFalse(sync.hasWaiters(c));
+ sync.release();
+
+ awaitTermination(t);
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitQueueLength returns number of waiting threads
+ */
+ public void testGetWaitQueueLength() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired1 = new BooleanLatch();
+ final BooleanLatch acquired2 = new BooleanLatch();
+ final Thread t1 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertEquals(0, sync.getWaitQueueLength(c));
+ assertTrue(acquired1.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+ acquired1.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertEquals(1, sync.getWaitQueueLength(c));
+ sync.release();
+
+ final Thread t2 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertEquals(1, sync.getWaitQueueLength(c));
+ assertTrue(acquired2.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+ acquired2.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1, t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertEquals(2, sync.getWaitQueueLength(c));
+ c.signalAll();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertEquals(0, sync.getWaitQueueLength(c));
+ sync.release();
+
+ awaitTermination(t1);
+ awaitTermination(t2);
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * getWaitingThreads returns only and all waiting threads
+ */
+ public void testGetWaitingThreads() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired1 = new BooleanLatch();
+ final BooleanLatch acquired2 = new BooleanLatch();
+ final Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ assertTrue(acquired1.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+
+ final Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(1, sync.getWaitingThreads(c).size());
+ assertTrue(acquired2.releaseShared(0));
+ c.await();
+ sync.release();
+ }});
+
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertFalse(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).contains(t2));
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(0, sync.getWaitingThreads(c).size());
+ sync.release();
+
+ t1.start();
+ acquired1.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1);
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).contains(t2));
+ assertFalse(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(1, sync.getWaitingThreads(c).size());
+ sync.release();
+
+ t2.start();
+ acquired2.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1, t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertTrue(sync.getWaitingThreads(c).contains(t2));
+ assertFalse(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(2, sync.getWaitingThreads(c).size());
+ c.signalAll();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ assertFalse(sync.getWaitingThreads(c).contains(t1));
+ assertFalse(sync.getWaitingThreads(c).contains(t2));
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ assertEquals(0, sync.getWaitingThreads(c).size());
+ sync.release();
+
+ awaitTermination(t1);
+ awaitTermination(t2);
+ assertHasWaitersUnlocked(sync, c, NO_THREADS);
+ }
+
+ /**
+ * awaitUninterruptibly is uninterruptible
+ */
+ public void testAwaitUninterruptibly() {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch pleaseInterrupt = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() {
+ sync.acquire();
+ assertTrue(pleaseInterrupt.releaseShared(0));
+ c.awaitUninterruptibly();
+ assertTrue(Thread.interrupted());
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ sync.release();
+ }});
+
+ pleaseInterrupt.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ sync.release();
+ t.interrupt();
+ assertHasWaitersUnlocked(sync, c, t);
+ assertThreadStaysAlive(t);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ c.signal();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t);
+ sync.release();
+ awaitTermination(t);
+ }
+
+ /**
+ * await/awaitNanos/awaitUntil is interruptible
+ */
+ public void testInterruptible_await() { testInterruptible(AwaitMethod.await); }
+ public void testInterruptible_awaitTimed() { testInterruptible(AwaitMethod.awaitTimed); }
+ public void testInterruptible_awaitNanos() { testInterruptible(AwaitMethod.awaitNanos); }
+ public void testInterruptible_awaitUntil() { testInterruptible(AwaitMethod.awaitUntil); }
+ public void testInterruptible(final AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch pleaseInterrupt = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ assertTrue(pleaseInterrupt.releaseShared(0));
+ await(c, awaitMethod);
+ }});
+
+ pleaseInterrupt.acquireShared(0);
+ t.interrupt();
+ awaitTermination(t);
+ }
+
+ /**
+ * signalAll wakes up all threads
+ */
+ public void testSignalAll_await() { testSignalAll(AwaitMethod.await); }
+ public void testSignalAll_awaitTimed() { testSignalAll(AwaitMethod.awaitTimed); }
+ public void testSignalAll_awaitNanos() { testSignalAll(AwaitMethod.awaitNanos); }
+ public void testSignalAll_awaitUntil() { testSignalAll(AwaitMethod.awaitUntil); }
+ public void testSignalAll(final AwaitMethod awaitMethod) {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ final BooleanLatch acquired1 = new BooleanLatch();
+ final BooleanLatch acquired2 = new BooleanLatch();
+ Thread t1 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ acquired1.releaseShared(0);
+ await(c, awaitMethod);
+ sync.release();
+ }});
+
+ Thread t2 = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire();
+ acquired2.releaseShared(0);
+ await(c, awaitMethod);
+ sync.release();
+ }});
+
+ acquired1.acquireShared(0);
+ acquired2.acquireShared(0);
+ sync.acquire();
+ assertHasWaitersLocked(sync, c, t1, t2);
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ c.signalAll();
+ assertHasWaitersLocked(sync, c, NO_THREADS);
+ assertHasExclusiveQueuedThreads(sync, t1, t2);
+ sync.release();
+ awaitTermination(t1);
+ awaitTermination(t2);
+ }
+
+ /**
+ * toString indicates current state
+ */
+ public void testToString() {
+ Mutex sync = new Mutex();
+ assertTrue(sync.toString().contains("State = " + Mutex.UNLOCKED));
+ sync.acquire();
+ assertTrue(sync.toString().contains("State = " + Mutex.LOCKED));
+ }
+
+ /**
+ * A serialized AQS deserializes with current state, but no queued threads
+ */
+ public void testSerialization() {
+ Mutex sync = new Mutex();
+ assertFalse(serialClone(sync).isHeldExclusively());
+ sync.acquire();
+ Thread t = newStartedThread(new InterruptedSyncRunnable(sync));
+ waitForQueuedThread(sync, t);
+ assertTrue(sync.isHeldExclusively());
+
+ Mutex clone = serialClone(sync);
+ assertTrue(clone.isHeldExclusively());
+ assertHasExclusiveQueuedThreads(sync, t);
+ assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+ t.interrupt();
+ awaitTermination(t);
+ sync.release();
+ assertFalse(sync.isHeldExclusively());
+ assertTrue(clone.isHeldExclusively());
+ assertHasExclusiveQueuedThreads(sync, NO_THREADS);
+ assertHasExclusiveQueuedThreads(clone, NO_THREADS);
+ }
+
+ /**
+ * tryReleaseShared setting state changes getState
+ */
+ public void testGetStateWithReleaseShared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertFalse(l.isSignalled());
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ }
+
+ /**
+ * releaseShared has no effect when already signalled
+ */
+ public void testReleaseShared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertFalse(l.isSignalled());
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ }
+
+ /**
+ * acquireSharedInterruptibly returns after release, but not before
+ */
+ public void testAcquireSharedInterruptibly() {
+ final BooleanLatch l = new BooleanLatch();
+
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ assertTrue(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ assertTrue(l.isSignalled());
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ assertThreadStaysAlive(t);
+ assertHasSharedQueuedThreads(l, t);
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ awaitTermination(t);
+ }
+
+ /**
+ * tryAcquireSharedNanos returns after release, but not before
+ */
+ public void testTryAcquireSharedNanos() {
+ final BooleanLatch l = new BooleanLatch();
+
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+ assertTrue(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(l.isSignalled());
+ assertTrue(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(l.isSignalled());
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ assertThreadStaysAlive(t);
+ assertTrue(l.releaseShared(0));
+ assertTrue(l.isSignalled());
+ awaitTermination(t);
+ }
+
+ /**
+ * acquireSharedInterruptibly is interruptible
+ */
+ public void testAcquireSharedInterruptibly_Interruptible() {
+ final BooleanLatch l = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ awaitTermination(t);
+ assertFalse(l.isSignalled());
+ }
+
+ /**
+ * tryAcquireSharedNanos is interruptible
+ */
+ public void testTryAcquireSharedNanos_Interruptible() {
+ final BooleanLatch l = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS);
+ l.tryAcquireSharedNanos(0, nanos);
+ }});
+
+ waitForQueuedThread(l, t);
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ awaitTermination(t);
+ assertFalse(l.isSignalled());
+ }
+
+ /**
+ * tryAcquireSharedNanos times out if not released before timeout
+ */
+ public void testTryAcquireSharedNanos_Timeout() {
+ final BooleanLatch l = new BooleanLatch();
+ final BooleanLatch observedQueued = new BooleanLatch();
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ for (long millis = timeoutMillis();
+ !observedQueued.isSignalled();
+ millis *= 2) {
+ long nanos = MILLISECONDS.toNanos(millis);
+ long startTime = System.nanoTime();
+ assertFalse(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(millisElapsedSince(startTime) >= millis);
+ }
+ assertFalse(l.isSignalled());
+ }});
+
+ waitForQueuedThread(l, t);
+ observedQueued.releaseShared(0);
+ assertFalse(l.isSignalled());
+ awaitTermination(t);
+ assertFalse(l.isSignalled());
+ }
+
+ /**
+ * awaitNanos/timed await with 0 wait times out immediately
+ */
+ public void testAwait_Zero() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ sync.acquire();
+ assertTrue(c.awaitNanos(0L) <= 0);
+ assertFalse(c.await(0L, NANOSECONDS));
+ sync.release();
+ }
+
+ /**
+ * awaitNanos/timed await with maximum negative wait times does not underflow
+ */
+ public void testAwait_NegativeInfinity() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final ConditionObject c = sync.newCondition();
+ sync.acquire();
+ assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0);
+ assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS));
+ sync.release();
+ }
+
+}
diff --git a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java
new file mode 100644
index 00000000000..e7fa0316197
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java
@@ -0,0 +1,955 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+
+import junit.framework.Test;
+
+public class ArrayBlockingQueueTest extends JSR166TestCase {
+
+ public static class Fair extends BlockingQueueTest {
+ protected BlockingQueue emptyCollection() {
+ return new ArrayBlockingQueue(SIZE, true);
+ }
+ }
+
+ public static class NonFair extends BlockingQueueTest {
+ protected BlockingQueue emptyCollection() {
+ return new ArrayBlockingQueue(SIZE, false);
+ }
+ }
+
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+
+ public static Test suite() {
+ return newTestSuite(ArrayBlockingQueueTest.class,
+ new Fair().testSuite(),
+ new NonFair().testSuite());
+ }
+
+ /**
+ * Returns a new queue of given size containing consecutive
+ * Integers 0 ... n.
+ */
+ private ArrayBlockingQueue populatedQueue(int n) {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(n);
+ assertTrue(q.isEmpty());
+ for (int i = 0; i < n; i++)
+ assertTrue(q.offer(new Integer(i)));
+ assertFalse(q.isEmpty());
+ assertEquals(0, q.remainingCapacity());
+ assertEquals(n, q.size());
+ return q;
+ }
+
+ /**
+ * A new queue has the indicated capacity
+ */
+ public void testConstructor1() {
+ assertEquals(SIZE, new ArrayBlockingQueue(SIZE).remainingCapacity());
+ }
+
+ /**
+ * Constructor throws IAE if capacity argument nonpositive
+ */
+ public void testConstructor2() {
+ try {
+ new ArrayBlockingQueue(0);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Initializing from null Collection throws NPE
+ */
+ public void testConstructor3() {
+ try {
+ new ArrayBlockingQueue(1, true, null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Initializing from Collection of null elements throws NPE
+ */
+ public void testConstructor4() {
+ Collection elements = Arrays.asList(new Integer[SIZE]);
+ try {
+ new ArrayBlockingQueue(SIZE, false, elements);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Initializing from Collection with some null elements throws NPE
+ */
+ public void testConstructor5() {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE - 1; ++i)
+ ints[i] = i;
+ Collection elements = Arrays.asList(ints);
+ try {
+ new ArrayBlockingQueue(SIZE, false, elements);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Initializing from too large collection throws IAE
+ */
+ public void testConstructor6() {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = i;
+ Collection elements = Arrays.asList(ints);
+ try {
+ new ArrayBlockingQueue(SIZE - 1, false, elements);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Queue contains all elements of collection used to initialize
+ */
+ public void testConstructor7() {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = i;
+ Collection elements = Arrays.asList(ints);
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE, true, elements);
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
+ }
+
+ /**
+ * Queue transitions from empty to full when elements added
+ */
+ public void testEmptyFull() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+ assertTrue(q.isEmpty());
+ assertEquals(2, q.remainingCapacity());
+ q.add(one);
+ assertFalse(q.isEmpty());
+ q.add(two);
+ assertFalse(q.isEmpty());
+ assertEquals(0, q.remainingCapacity());
+ assertFalse(q.offer(three));
+ }
+
+ /**
+ * remainingCapacity decreases on add, increases on remove
+ */
+ public void testRemainingCapacity() {
+ BlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.remainingCapacity());
+ assertEquals(SIZE, q.size() + q.remainingCapacity());
+ assertEquals(i, q.remove());
+ }
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE - i, q.remainingCapacity());
+ assertEquals(SIZE, q.size() + q.remainingCapacity());
+ assertTrue(q.add(i));
+ }
+ }
+
+ /**
+ * Offer succeeds if not full; fails if full
+ */
+ public void testOffer() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(1);
+ assertTrue(q.offer(zero));
+ assertFalse(q.offer(one));
+ }
+
+ /**
+ * add succeeds if not full; throws ISE if full
+ */
+ public void testAdd() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.add(new Integer(i)));
+ }
+ assertEquals(0, q.remainingCapacity());
+ try {
+ q.add(new Integer(SIZE));
+ shouldThrow();
+ } catch (IllegalStateException success) {}
+ }
+
+ /**
+ * addAll(this) throws IAE
+ */
+ public void testAddAllSelf() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ try {
+ q.addAll(q);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * addAll of a collection with any null elements throws NPE after
+ * possibly adding some elements
+ */
+ public void testAddAll3() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE - 1; ++i)
+ ints[i] = new Integer(i);
+ try {
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * addAll throws ISE if not enough room
+ */
+ public void testAddAll4() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(1);
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ try {
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ } catch (IllegalStateException success) {}
+ }
+
+ /**
+ * Queue contains all elements, in traversal order, of successful addAll
+ */
+ public void testAddAll5() {
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
+ }
+
+ /**
+ * all elements successfully put are contained
+ */
+ public void testPut() throws InterruptedException {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer x = new Integer(i);
+ q.put(x);
+ assertTrue(q.contains(x));
+ }
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * put blocks interruptibly if full
+ */
+ public void testBlockingPut() throws InterruptedException {
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ q.put(i);
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+
+ Thread.currentThread().interrupt();
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ assertFalse(Thread.interrupted());
+
+ pleaseInterrupt.countDown();
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ assertFalse(Thread.interrupted());
+ }});
+
+ await(pleaseInterrupt);
+ assertThreadStaysAlive(t);
+ t.interrupt();
+ awaitTermination(t);
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * put blocks interruptibly waiting for take when full
+ */
+ public void testPutWithTake() throws InterruptedException {
+ final int capacity = 2;
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(capacity);
+ final CountDownLatch pleaseTake = new CountDownLatch(1);
+ final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < capacity; i++)
+ q.put(i);
+ pleaseTake.countDown();
+ q.put(86);
+
+ pleaseInterrupt.countDown();
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ assertFalse(Thread.interrupted());
+ }});
+
+ await(pleaseTake);
+ assertEquals(0, q.remainingCapacity());
+ assertEquals(0, q.take());
+
+ await(pleaseInterrupt);
+ assertThreadStaysAlive(t);
+ t.interrupt();
+ awaitTermination(t);
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * timed offer times out if full and elements not taken
+ */
+ public void testTimedOffer() throws InterruptedException {
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+ final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Object());
+ q.put(new Object());
+ long startTime = System.nanoTime();
+ assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+ pleaseInterrupt.countDown();
+ try {
+ q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ await(pleaseInterrupt);
+ assertThreadStaysAlive(t);
+ t.interrupt();
+ awaitTermination(t);
+ }
+
+ /**
+ * take retrieves elements in FIFO order
+ */
+ public void testTake() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
+ }
+
+ /**
+ * Take removes existing elements until empty, then blocks interruptibly
+ */
+ public void testBlockingTake() throws InterruptedException {
+ final ArrayBlockingQueue q = populatedQueue(SIZE);
+ final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
+
+ Thread.currentThread().interrupt();
+ try {
+ q.take();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ assertFalse(Thread.interrupted());
+
+ pleaseInterrupt.countDown();
+ try {
+ q.take();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ assertFalse(Thread.interrupted());
+ }});
+
+ await(pleaseInterrupt);
+ assertThreadStaysAlive(t);
+ t.interrupt();
+ awaitTermination(t);
+ }
+
+ /**
+ * poll succeeds unless empty
+ */
+ public void testPoll() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll());
+ }
+ assertNull(q.poll());
+ }
+
+ /**
+ * timed poll with zero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPoll0() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(0, MILLISECONDS));
+ }
+ assertNull(q.poll(0, MILLISECONDS));
+ checkEmpty(q);
+ }
+
+ /**
+ * timed poll with nonzero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPoll() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ long startTime = System.nanoTime();
+ assertEquals(i, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+ }
+ long startTime = System.nanoTime();
+ assertNull(q.poll(timeoutMillis(), MILLISECONDS));
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+ checkEmpty(q);
+ }
+
+ /**
+ * Interrupted timed poll throws InterruptedException instead of
+ * returning timeout status
+ */
+ public void testInterruptedTimedPoll() throws InterruptedException {
+ final BlockingQueue q = populatedQueue(SIZE);
+ final CountDownLatch aboutToWait = new CountDownLatch(1);
+ Thread t = newStartedThread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ long startTime = System.nanoTime();
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
+ }
+ aboutToWait.countDown();
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {
+ assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+ }
+ }});
+
+ await(aboutToWait);
+ waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
+ t.interrupt();
+ awaitTermination(t);
+ checkEmpty(q);
+ }
+
+ /**
+ * peek returns next element, or null if empty
+ */
+ public void testPeek() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.peek());
+ assertEquals(i, q.poll());
+ assertTrue(q.peek() == null ||
+ !q.peek().equals(i));
+ }
+ assertNull(q.peek());
+ }
+
+ /**
+ * element returns next element, or throws NSEE if empty
+ */
+ public void testElement() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.element());
+ assertEquals(i, q.poll());
+ }
+ try {
+ q.element();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * remove removes next element, or throws NSEE if empty
+ */
+ public void testRemove() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.remove());
+ }
+ try {
+ q.remove();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * contains(x) reports true when elements added but not yet removed
+ */
+ public void testContains() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.contains(new Integer(i)));
+ assertEquals(i, q.poll());
+ assertFalse(q.contains(new Integer(i)));
+ }
+ }
+
+ /**
+ * clear removes all elements
+ */
+ public void testClear() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ q.clear();
+ assertTrue(q.isEmpty());
+ assertEquals(0, q.size());
+ assertEquals(SIZE, q.remainingCapacity());
+ q.add(one);
+ assertFalse(q.isEmpty());
+ assertTrue(q.contains(one));
+ q.clear();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * containsAll(c) is true when c contains a subset of elements
+ */
+ public void testContainsAll() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ ArrayBlockingQueue p = new ArrayBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.containsAll(p));
+ assertFalse(p.containsAll(q));
+ p.add(new Integer(i));
+ }
+ assertTrue(p.containsAll(q));
+ }
+
+ /**
+ * retainAll(c) retains only those elements of c and reports true if changed
+ */
+ public void testRetainAll() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ ArrayBlockingQueue p = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ boolean changed = q.retainAll(p);
+ if (i == 0)
+ assertFalse(changed);
+ else
+ assertTrue(changed);
+
+ assertTrue(q.containsAll(p));
+ assertEquals(SIZE - i, q.size());
+ p.remove();
+ }
+ }
+
+ /**
+ * removeAll(c) removes only those elements of c and reports true if changed
+ */
+ public void testRemoveAll() {
+ for (int i = 1; i < SIZE; ++i) {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ ArrayBlockingQueue p = populatedQueue(i);
+ assertTrue(q.removeAll(p));
+ assertEquals(SIZE - i, q.size());
+ for (int j = 0; j < i; ++j) {
+ Integer x = (Integer)(p.remove());
+ assertFalse(q.contains(x));
+ }
+ }
+ }
+
+ void checkToArray(ArrayBlockingQueue q) {
+ int size = q.size();
+ Object[] o = q.toArray();
+ assertEquals(size, o.length);
+ Iterator it = q.iterator();
+ for (int i = 0; i < size; i++) {
+ Integer x = (Integer) it.next();
+ assertEquals((Integer)o[0] + i, (int) x);
+ assertSame(o[i], x);
+ }
+ }
+
+ /**
+ * toArray() contains all elements in FIFO order
+ */
+ public void testToArray() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; i++) {
+ checkToArray(q);
+ q.add(i);
+ }
+ // Provoke wraparound
+ for (int i = 0; i < SIZE; i++) {
+ checkToArray(q);
+ assertEquals(i, q.poll());
+ checkToArray(q);
+ q.add(SIZE + i);
+ }
+ for (int i = 0; i < SIZE; i++) {
+ checkToArray(q);
+ assertEquals(SIZE + i, q.poll());
+ }
+ }
+
+ void checkToArray2(ArrayBlockingQueue q) {
+ int size = q.size();
+ Integer[] a1 = (size == 0) ? null : new Integer[size - 1];
+ Integer[] a2 = new Integer[size];
+ Integer[] a3 = new Integer[size + 2];
+ if (size > 0) Arrays.fill(a1, 42);
+ Arrays.fill(a2, 42);
+ Arrays.fill(a3, 42);
+ Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1);
+ Integer[] b2 = (Integer[]) q.toArray(a2);
+ Integer[] b3 = (Integer[]) q.toArray(a3);
+ assertSame(a2, b2);
+ assertSame(a3, b3);
+ Iterator it = q.iterator();
+ for (int i = 0; i < size; i++) {
+ Integer x = (Integer) it.next();
+ assertSame(b1[i], x);
+ assertEquals(b1[0] + i, (int) x);
+ assertSame(b2[i], x);
+ assertSame(b3[i], x);
+ }
+ assertNull(a3[size]);
+ assertEquals(42, (int) a3[size + 1]);
+ if (size > 0) {
+ assertNotSame(a1, b1);
+ assertEquals(size, b1.length);
+ for (int i = 0; i < a1.length; i++) {
+ assertEquals(42, (int) a1[i]);
+ }
+ }
+ }
+
+ /**
+ * toArray(a) contains all elements in FIFO order
+ */
+ public void testToArray2() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; i++) {
+ checkToArray2(q);
+ q.add(i);
+ }
+ // Provoke wraparound
+ for (int i = 0; i < SIZE; i++) {
+ checkToArray2(q);
+ assertEquals(i, q.poll());
+ checkToArray2(q);
+ q.add(SIZE + i);
+ }
+ for (int i = 0; i < SIZE; i++) {
+ checkToArray2(q);
+ assertEquals(SIZE + i, q.poll());
+ }
+ }
+
+ /**
+ * toArray(incompatible array type) throws ArrayStoreException
+ */
+ public void testToArray1_BadArg() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ try {
+ q.toArray(new String[10]);
+ shouldThrow();
+ } catch (ArrayStoreException success) {}
+ }
+
+ /**
+ * iterator iterates through all elements
+ */
+ public void testIterator() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ Iterator it = q.iterator();
+ int i;
+ for (i = 0; it.hasNext(); i++)
+ assertTrue(q.contains(it.next()));
+ assertEquals(i, SIZE);
+ assertIteratorExhausted(it);
+
+ it = q.iterator();
+ for (i = 0; it.hasNext(); i++)
+ assertEquals(it.next(), q.take());
+ assertEquals(i, SIZE);
+ assertIteratorExhausted(it);
+ }
+
+ /**
+ * iterator of empty collection has no elements
+ */
+ public void testEmptyIterator() {
+ assertIteratorExhausted(new ArrayBlockingQueue(SIZE).iterator());
+ }
+
+ /**
+ * iterator.remove removes current element
+ */
+ public void testIteratorRemove() {
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(3);
+ q.add(two);
+ q.add(one);
+ q.add(three);
+
+ Iterator it = q.iterator();
+ it.next();
+ it.remove();
+
+ it = q.iterator();
+ assertSame(it.next(), one);
+ assertSame(it.next(), three);
+ assertFalse(it.hasNext());
+ }
+
+ /**
+ * iterator ordering is FIFO
+ */
+ public void testIteratorOrdering() {
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(3);
+ q.add(one);
+ q.add(two);
+ q.add(three);
+
+ assertEquals("queue should be full", 0, q.remainingCapacity());
+
+ int k = 0;
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ assertEquals(++k, it.next());
+ }
+ assertEquals(3, k);
+ }
+
+ /**
+ * Modifications do not cause iterators to fail
+ */
+ public void testWeaklyConsistentIteration() {
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(3);
+ q.add(one);
+ q.add(two);
+ q.add(three);
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ q.remove();
+ it.next();
+ }
+ assertEquals(0, q.size());
+ }
+
+ /**
+ * toString contains toStrings of elements
+ */
+ public void testToString() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ String s = q.toString();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(s.contains(String.valueOf(i)));
+ }
+ }
+
+ /**
+ * offer transfers elements across Executor tasks
+ */
+ public void testOfferInExecutor() {
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+ q.add(one);
+ q.add(two);
+ final CheckedBarrier threadsStarted = new CheckedBarrier(2);
+ final ExecutorService executor = Executors.newFixedThreadPool(2);
+ try (PoolCleaner cleaner = cleaner(executor)) {
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(q.offer(three));
+ threadsStarted.await();
+ assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
+ assertEquals(0, q.remainingCapacity());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadsStarted.await();
+ assertEquals(0, q.remainingCapacity());
+ assertSame(one, q.take());
+ }});
+ }
+ }
+
+ /**
+ * timed poll retrieves elements across Executor threads
+ */
+ public void testPollInExecutor() {
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+ final CheckedBarrier threadsStarted = new CheckedBarrier(2);
+ final ExecutorService executor = Executors.newFixedThreadPool(2);
+ try (PoolCleaner cleaner = cleaner(executor)) {
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll());
+ threadsStarted.await();
+ assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ checkEmpty(q);
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadsStarted.await();
+ q.put(one);
+ }});
+ }
+ }
+
+ /**
+ * A deserialized serialized queue has same elements in same order
+ */
+ public void testSerialization() throws Exception {
+ Queue x = populatedQueue(SIZE);
+ Queue y = serialClone(x);
+
+ assertNotSame(x, y);
+ assertEquals(x.size(), y.size());
+ assertEquals(x.toString(), y.toString());
+ assertTrue(Arrays.equals(x.toArray(), y.toArray()));
+ while (!x.isEmpty()) {
+ assertFalse(y.isEmpty());
+ assertEquals(x.remove(), y.remove());
+ }
+ assertTrue(y.isEmpty());
+ }
+
+ /**
+ * drainTo(c) empties queue into another collection c
+ */
+ public void testDrainTo() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertEquals(0, q.size());
+ assertEquals(SIZE, l.size());
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ q.add(zero);
+ q.add(one);
+ assertFalse(q.isEmpty());
+ assertTrue(q.contains(zero));
+ assertTrue(q.contains(one));
+ l.clear();
+ q.drainTo(l);
+ assertEquals(0, q.size());
+ assertEquals(2, l.size());
+ for (int i = 0; i < 2; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ }
+
+ /**
+ * drainTo empties full queue, unblocking a waiting put.
+ */
+ public void testDrainToWithActivePut() throws InterruptedException {
+ final ArrayBlockingQueue q = populatedQueue(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Integer(SIZE + 1));
+ }});
+
+ t.start();
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertTrue(l.size() >= SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ t.join();
+ assertTrue(q.size() + l.size() >= SIZE);
+ }
+
+ /**
+ * drainTo(c, n) empties first min(n, size) elements of queue into c
+ */
+ public void testDrainToN() {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE * 2);
+ for (int i = 0; i < SIZE + 2; ++i) {
+ for (int j = 0; j < SIZE; j++)
+ assertTrue(q.offer(new Integer(j)));
+ ArrayList l = new ArrayList();
+ q.drainTo(l, i);
+ int k = (i < SIZE) ? i : SIZE;
+ assertEquals(k, l.size());
+ assertEquals(SIZE - k, q.size());
+ for (int j = 0; j < k; ++j)
+ assertEquals(l.get(j), new Integer(j));
+ do {} while (q.poll() != null);
+ }
+ }
+
+ /**
+ * remove(null), contains(null) always return false
+ */
+ public void testNeverContainsNull() {
+ Collection>[] qs = {
+ new ArrayBlockingQueue