--- jsr166/src/test/tck/SynchronousQueueTest.java 2003/09/07 20:39:11 1.2 +++ jsr166/src/test/tck/SynchronousQueueTest.java 2015/10/04 18:28:51 1.49 @@ -1,463 +1,615 @@ /* - * Written by members of JCP JSR-166 Expert Group and released to the - * public domain. Use, modify, and redistribute this code in any way - * without acknowledgement. Other contributors include Andrew Wright, - * Jeffrey Hayes, Pat Fischer, Mike Judd. + * 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 junit.framework.*; -import java.util.*; -import java.util.concurrent.*; -import java.io.*; - -public class SynchronousQueueTest extends TestCase { - - private final static int N = 1; - private static long SHORT_DELAY_MS = 100; - private static long MEDIUM_DELAY_MS = 1000; - private static long LONG_DELAY_MS = 10000; +import static java.util.concurrent.TimeUnit.MILLISECONDS; - public static void main(String[] args) { - junit.textui.TestRunner.run (suite()); - } +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; - public static Test suite() { - return new TestSuite(SynchronousQueueTest.class); - } +import junit.framework.Test; - public void testEmptyFull() { - SynchronousQueue q = new SynchronousQueue(); - assertTrue(q.isEmpty()); - assertEquals(0, q.size()); - assertEquals(0, q.remainingCapacity()); - assertFalse(q.offer(new Integer(3))); - } - - public void testOfferNull(){ - try { - SynchronousQueue q = new SynchronousQueue(); - q.offer(null); - fail("should throw NPE"); - } catch (NullPointerException success) { } - } - - public void testOffer(){ - SynchronousQueue q = new SynchronousQueue(); - assertFalse(q.offer(new Integer(1))); - } - - public void testAdd(){ - try { - SynchronousQueue q = new SynchronousQueue(); - assertEquals(0, q.remainingCapacity()); - q.add(new Integer(0)); - } catch (IllegalStateException success){ - } - } - - public void testAddAll1(){ - try { - SynchronousQueue q = new SynchronousQueue(); - q.addAll(null); - fail("Cannot add null collection"); - } - catch (NullPointerException success) {} - } - public void testAddAll2(){ - try { - SynchronousQueue q = new SynchronousQueue(); - Integer[] ints = new Integer[N]; - q.addAll(Arrays.asList(ints)); - fail("Cannot add null elements"); - } - catch (NullPointerException success) {} - } - public void testAddAll4(){ - try { - SynchronousQueue q = new SynchronousQueue(); - Integer[] ints = new Integer[N]; - for (int i = 0; i < N; ++i) - ints[i] = new Integer(i); - q.addAll(Arrays.asList(ints)); - fail("Cannot add with insufficient capacity"); - } - catch (IllegalStateException success) {} - } - - public void testPutNull() { - try { - SynchronousQueue q = new SynchronousQueue(); - q.put(null); - fail("put should throw NPE"); - } - catch (NullPointerException success){ - } - catch (InterruptedException ie) { - fail("Unexpected exception"); - } - } +public class SynchronousQueueTest extends JSR166TestCase { - public void testBlockingPut(){ - Thread t = new Thread(new Runnable() { - public void run() { - try { - SynchronousQueue q = new SynchronousQueue(); - q.put(new Integer(0)); - fail("put should block"); - } catch (InterruptedException ie){ - } - }}); - t.start(); - try { - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } - catch (InterruptedException ie) { - fail("Unexpected exception"); + public static class Fair extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new SynchronousQueue(true); } } - public void testPutWithTake() { - final SynchronousQueue q = new SynchronousQueue(); - Thread t = new Thread(new Runnable() { - public void run(){ - int added = 0; - try { - q.put(new Object()); - ++added; - q.put(new Object()); - ++added; - q.put(new Object()); - ++added; - q.put(new Object()); - ++added; - fail("Should block"); - } catch (InterruptedException e){ - assertTrue(added >= 1); - } - } - }); - try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - q.take(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch (Exception e){ - fail("Unexpected exception"); + public static class NonFair extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new SynchronousQueue(false); } } - public void testTimedOffer() { - final SynchronousQueue q = new SynchronousQueue(); - Thread t = new Thread(new Runnable() { - public void run(){ - try { - - assertFalse(q.offer(new Object(), SHORT_DELAY_MS/2, TimeUnit.MILLISECONDS)); - q.offer(new Object(), LONG_DELAY_MS, TimeUnit.MILLISECONDS); - fail("Should block"); - } catch (InterruptedException success){} - } - }); - - try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch (Exception e){ - fail("Unexpected exception"); - } + public static void main(String[] args) { + main(suite(), args); } - - public void testTakeFromEmpty() { - final SynchronousQueue q = new SynchronousQueue(); - Thread t = new Thread(new Runnable() { - public void run(){ - try { - q.take(); - fail("Should block"); - } catch (InterruptedException success){ } - } - }); - try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch (Exception e){ - fail("Unexpected exception"); - } + public static Test suite() { + return newTestSuite(SynchronousQueueTest.class, + new Fair().testSuite(), + new NonFair().testSuite()); } - public void testPoll(){ - SynchronousQueue q = new SynchronousQueue(); - assertNull(q.poll()); + /** + * Any SynchronousQueue is both empty and full + */ + public void testEmptyFull() { testEmptyFull(false); } + public void testEmptyFull_fair() { testEmptyFull(true); } + public void testEmptyFull(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertEquals(0, q.remainingCapacity()); + assertFalse(q.offer(zero)); } - public void testTimedPoll0() { + /** + * offer fails if no active taker + */ + public void testOffer() { testOffer(false); } + public void testOffer_fair() { testOffer(true); } + public void testOffer(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + assertFalse(q.offer(one)); + } + + /** + * add throws IllegalStateException if no active taker + */ + public void testAdd() { testAdd(false); } + public void testAdd_fair() { testAdd(true); } + public void testAdd(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + assertEquals(0, q.remainingCapacity()); try { - SynchronousQueue q = new SynchronousQueue(); - assertNull(q.poll(0, TimeUnit.MILLISECONDS)); - } catch (InterruptedException e){ - fail("Unexpected exception"); - } - } + q.add(one); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * addAll(this) throws IllegalArgumentException + */ + public void testAddAll_self() { testAddAll_self(false); } + public void testAddAll_self_fair() { testAddAll_self(true); } + public void testAddAll_self(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll throws ISE if no active taker + */ + public void testAddAll_ISE() { testAddAll_ISE(false); } + public void testAddAll_ISE_fair() { testAddAll_ISE(true); } + public void testAddAll_ISE(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + Integer[] ints = new Integer[1]; + for (int i = 0; i < ints.length; i++) + ints[i] = i; + Collection coll = Arrays.asList(ints); + try { + q.addAll(coll); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * put blocks interruptibly if no active taker + */ + public void testBlockingPut() { testBlockingPut(false); } + public void testBlockingPut_fair() { testBlockingPut(true); } + public void testBlockingPut(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + Thread.currentThread().interrupt(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); - public void testTimedPoll() { - try { - SynchronousQueue q = new SynchronousQueue(); - assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - } catch (InterruptedException e){ - fail("Unexpected exception"); - } + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); } - public void testInterruptedTimedPoll(){ - Thread t = new Thread(new Runnable() { - public void run() { - try { - SynchronousQueue q = new SynchronousQueue(); - assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - } catch (InterruptedException success){ - } - }}); - t.start(); - try { - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } - catch (InterruptedException ie) { - fail("Unexpected exception"); - } - } + /** + * put blocks interruptibly waiting for take + */ + public void testPutWithTake() { testPutWithTake(false); } + public void testPutWithTake_fair() { testPutWithTake(true); } + public void testPutWithTake(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseTake = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + pleaseTake.countDown(); + q.put(one); - public void testTimedPollWithOffer(){ - final SynchronousQueue q = new SynchronousQueue(); - Thread t = new Thread(new Runnable() { - public void run(){ - try { - assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS); - q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS); - fail("Should block"); - } catch (InterruptedException success) { } - } - }); - try { - t.start(); - Thread.sleep(SHORT_DELAY_MS * 2); - assertTrue(q.offer(new Integer(0), SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - t.interrupt(); - t.join(); - } catch (Exception e){ - fail("Unexpected exception"); - } - } + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + await(pleaseTake); + assertEquals(0, q.remainingCapacity()); + try { assertSame(one, q.take()); } + catch (InterruptedException e) { threadUnexpectedException(e); } - public void testPeek(){ - SynchronousQueue q = new SynchronousQueue(); - assertNull(q.peek()); + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); } - public void testElement(){ - SynchronousQueue q = new SynchronousQueue(); + /** + * timed offer times out if elements not taken + */ + public void testTimedOffer() { testTimedOffer(false); } + public void testTimedOffer_fair() { testTimedOffer(true); } + public void testTimedOffer(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + 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); + } + + /** + * poll return null if no active putter + */ + public void testPoll() { testPoll(false); } + public void testPoll_fair() { testPoll(true); } + public void testPoll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertNull(q.poll()); + } + + /** + * timed poll with zero timeout times out if no active putter + */ + public void testTimedPoll0() { testTimedPoll0(false); } + public void testTimedPoll0_fair() { testTimedPoll0(true); } + public void testTimedPoll0(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + try { assertNull(q.poll(0, MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + } + + /** + * timed poll with nonzero timeout times out if no active putter + */ + public void testTimedPoll() { testTimedPoll(false); } + public void testTimedPoll_fair() { testTimedPoll(true); } + public void testTimedPoll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + long startTime = System.nanoTime(); + try { assertNull(q.poll(timeoutMillis(), MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + + /** + * timed poll before a delayed offer times out, returning null; + * after offer succeeds; on interruption throws + */ + public void testTimedPollWithOffer() { testTimedPollWithOffer(false); } + public void testTimedPollWithOffer_fair() { testTimedPollWithOffer(true); } + public void testTimedPollWithOffer(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseOffer = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + + pleaseOffer.countDown(); + startTime = System.nanoTime(); + assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < MEDIUM_DELAY_MS); + + Thread.currentThread().interrupt(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseOffer); + long startTime = System.nanoTime(); + try { assertTrue(q.offer(zero, LONG_DELAY_MS, MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) < MEDIUM_DELAY_MS); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * peek() returns null if no active putter + */ + public void testPeek() { testPeek(false); } + public void testPeek_fair() { testPeek(true); } + public void testPeek(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertNull(q.peek()); + } + + /** + * element() throws NoSuchElementException if no active putter + */ + public void testElement() { testElement(false); } + public void testElement_fair() { testElement(true); } + public void testElement(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); try { q.element(); - fail("no such element"); - } - catch (NoSuchElementException success) {} + shouldThrow(); + } catch (NoSuchElementException success) {} } - public void testRemove(){ - SynchronousQueue q = new SynchronousQueue(); + /** + * remove() throws NoSuchElementException if no active putter + */ + public void testRemove() { testRemove(false); } + public void testRemove_fair() { testRemove(true); } + public void testRemove(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); try { q.remove(); - fail("remove should throw"); - } catch (NoSuchElementException success){ - } + shouldThrow(); + } catch (NoSuchElementException success) {} } - public void testRemoveElement(){ - SynchronousQueue q = new SynchronousQueue(); - for (int i = 1; i < N; i+=2) { - assertFalse(q.remove(new Integer(i))); - } - assertTrue(q.isEmpty()); - } - - public void testContains(){ - SynchronousQueue q = new SynchronousQueue(); - for (int i = 0; i < N; ++i) { - assertFalse(q.contains(new Integer(i))); - } - } - - public void testClear(){ - SynchronousQueue q = new SynchronousQueue(); + /** + * contains returns false + */ + public void testContains() { testContains(false); } + public void testContains_fair() { testContains(true); } + public void testContains(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertFalse(q.contains(zero)); + } + + /** + * clear ensures isEmpty + */ + public void testClear() { testClear(false); } + public void testClear_fair() { testClear(true); } + public void testClear(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); q.clear(); assertTrue(q.isEmpty()); } - public void testContainsAll(){ - SynchronousQueue q = new SynchronousQueue(); + /** + * containsAll returns false unless empty + */ + public void testContainsAll() { testContainsAll(false); } + public void testContainsAll_fair() { testContainsAll(true); } + public void testContainsAll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); Integer[] empty = new Integer[0]; - Integer[] ints = new Integer[1]; ints[0] = new Integer(0); - // assertTrue(q.containsAll(Arrays.asList(empty))); + assertTrue(q.containsAll(Arrays.asList(empty))); + Integer[] ints = new Integer[1]; ints[0] = zero; assertFalse(q.containsAll(Arrays.asList(ints))); } - public void testRetainAll(){ - SynchronousQueue q = new SynchronousQueue(); + /** + * retainAll returns false + */ + public void testRetainAll() { testRetainAll(false); } + public void testRetainAll_fair() { testRetainAll(true); } + public void testRetainAll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); Integer[] empty = new Integer[0]; - Integer[] ints = new Integer[1]; ints[0] = new Integer(0); - q.retainAll(Arrays.asList(ints)); - // assertTrue(q.containsAll(Arrays.asList(empty))); - assertFalse(q.containsAll(Arrays.asList(ints))); + assertFalse(q.retainAll(Arrays.asList(empty))); + Integer[] ints = new Integer[1]; ints[0] = zero; + assertFalse(q.retainAll(Arrays.asList(ints))); } - public void testRemoveAll(){ - SynchronousQueue q = new SynchronousQueue(); + /** + * removeAll returns false + */ + public void testRemoveAll() { testRemoveAll(false); } + public void testRemoveAll_fair() { testRemoveAll(true); } + public void testRemoveAll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); Integer[] empty = new Integer[0]; - Integer[] ints = new Integer[1]; ints[0] = new Integer(0); - q.removeAll(Arrays.asList(ints)); - // assertTrue(q.containsAll(Arrays.asList(empty))); + assertFalse(q.removeAll(Arrays.asList(empty))); + Integer[] ints = new Integer[1]; ints[0] = zero; assertFalse(q.containsAll(Arrays.asList(ints))); } - - public void testToArray(){ - SynchronousQueue q = new SynchronousQueue(); - Object[] o = q.toArray(); - assertEquals(o.length, 0); - } - - public void testToArray2(){ - SynchronousQueue q = new SynchronousQueue(); - Integer[] ints = new Integer[1]; - assertNull(ints[0]); - } - - public void testIterator(){ - SynchronousQueue q = new SynchronousQueue(); - Iterator it = q.iterator(); - assertFalse(it.hasNext()); - try { - Object x = it.next(); - fail("should throw"); - } - catch (NoSuchElementException success) {} - } - - public void testIteratorRemove(){ - SynchronousQueue q = new SynchronousQueue(); - Iterator it = q.iterator(); + /** + * toArray is empty + */ + public void testToArray() { testToArray(false); } + public void testToArray_fair() { testToArray(true); } + public void testToArray(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Object[] o = q.toArray(); + assertEquals(0, o.length); + } + + /** + * toArray(Integer array) returns its argument with the first + * element (if present) nulled out + */ + public void testToArray2() { testToArray2(false); } + public void testToArray2_fair() { testToArray2(true); } + public void testToArray2(boolean fair) { + final SynchronousQueue q + = new SynchronousQueue(fair); + Integer[] a; + + a = new Integer[0]; + assertSame(a, q.toArray(a)); + + a = new Integer[3]; + Arrays.fill(a, 42); + assertSame(a, q.toArray(a)); + assertNull(a[0]); + for (int i = 1; i < a.length; i++) + assertEquals(42, (int) a[i]); + } + + /** + * toArray(null) throws NPE + */ + public void testToArray_null() { testToArray_null(false); } + public void testToArray_null_fair() { testToArray_null(true); } + public void testToArray_null(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + try { + Object[] o = q.toArray(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * iterator does not traverse any elements + */ + public void testIterator() { testIterator(false); } + public void testIterator_fair() { testIterator(true); } + public void testIterator(boolean fair) { + assertIteratorExhausted(new SynchronousQueue(fair).iterator()); + } + + /** + * iterator remove throws ISE + */ + public void testIteratorRemove() { testIteratorRemove(false); } + public void testIteratorRemove_fair() { testIteratorRemove(true); } + public void testIteratorRemove(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Iterator it = q.iterator(); try { it.remove(); - fail("should throw"); - } - catch (IllegalStateException success) {} + shouldThrow(); + } catch (IllegalStateException success) {} } - public void testToString(){ - SynchronousQueue q = new SynchronousQueue(); + /** + * toString returns a non-null string + */ + public void testToString() { testToString(false); } + public void testToString_fair() { testToString(true); } + public void testToString(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); String s = q.toString(); - assertTrue(s != null); - } - - - public void testOfferInExecutor() { - final SynchronousQueue q = new SynchronousQueue(); - ExecutorService executor = Executors.newFixedThreadPool(2); - final Integer one = new Integer(1); + assertNotNull(s); + } - executor.execute(new Runnable() { - public void run() { - assertFalse(q.offer(one)); - try { - assertTrue(q.offer(one, MEDIUM_DELAY_MS * 2, TimeUnit.MILLISECONDS)); + /** + * offer transfers elements across Executor tasks + */ + public void testOfferInExecutor() { testOfferInExecutor(false); } + public void testOfferInExecutor_fair() { testOfferInExecutor(true); } + public void testOfferInExecutor(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + 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(one)); + threadsStarted.await(); + assertTrue(q.offer(one, LONG_DELAY_MS, MILLISECONDS)); assertEquals(0, q.remainingCapacity()); - } - catch (InterruptedException e) { - fail("should not be interrupted"); - } - } - }); - - executor.execute(new Runnable() { - public void run() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - assertEquals(one, q.take()); - } - catch (InterruptedException e) { - fail("should not be interrupted"); - } - } - }); - - executor.shutdown(); + }}); + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + assertSame(one, q.take()); + }}); + } } - public void testPollInExecutor() { - - final SynchronousQueue q = new SynchronousQueue(); - - ExecutorService executor = Executors.newFixedThreadPool(2); - - executor.execute(new Runnable() { - public void run() { - assertNull(q.poll()); - try { - assertTrue(null != q.poll(MEDIUM_DELAY_MS * 2, TimeUnit.MILLISECONDS)); + /** + * timed poll retrieves elements across Executor threads + */ + public void testPollInExecutor() { testPollInExecutor(false); } + public void testPollInExecutor_fair() { testPollInExecutor(true); } + public void testPollInExecutor(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + 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)); assertTrue(q.isEmpty()); - } - catch (InterruptedException e) { - fail("should not be interrupted"); - } - } - }); - - executor.execute(new Runnable() { - public void run() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - q.put(new Integer(1)); - } - catch (InterruptedException e) { - fail("should not be interrupted"); - } - } - }); - - executor.shutdown(); + }}); + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(one); + }}); + } } + /** + * a deserialized serialized queue is usable + */ public void testSerialization() { - SynchronousQueue q = new SynchronousQueue(); - try { - ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); - ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); - out.writeObject(q); - out.close(); - - ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); - ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); - SynchronousQueue r = (SynchronousQueue)in.readObject(); - assertEquals(q.size(), r.size()); - while (!q.isEmpty()) - assertEquals(q.remove(), r.remove()); - } catch(Exception e){ - fail("unexpected exception"); + final SynchronousQueue x = new SynchronousQueue(); + final SynchronousQueue y = new SynchronousQueue(false); + final SynchronousQueue z = new SynchronousQueue(true); + assertSerialEquals(x, y); + assertNotSerialEquals(x, z); + SynchronousQueue[] qs = { x, y, z }; + for (SynchronousQueue q : qs) { + SynchronousQueue clone = serialClone(q); + assertNotSame(q, clone); + assertSerialEquals(q, clone); + assertTrue(clone.isEmpty()); + assertEquals(0, clone.size()); + assertEquals(0, clone.remainingCapacity()); + assertFalse(clone.offer(zero)); } } + /** + * drainTo(c) of empty queue doesn't transfer elements + */ + public void testDrainTo() { testDrainTo(false); } + public void testDrainTo_fair() { testDrainTo(true); } + public void testDrainTo(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(0, l.size()); + } + + /** + * drainTo empties queue, unblocking a waiting put. + */ + public void testDrainToWithActivePut() { testDrainToWithActivePut(false); } + public void testDrainToWithActivePut_fair() { testDrainToWithActivePut(true); } + public void testDrainToWithActivePut(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(one); + }}); + + ArrayList l = new ArrayList(); + long startTime = System.nanoTime(); + while (l.isEmpty()) { + q.drainTo(l); + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(l.size() == 1); + assertSame(one, l.get(0)); + awaitTermination(t); + } + + /** + * drainTo(c, n) empties up to n elements of queue into c + */ + public void testDrainToN() throws InterruptedException { + final SynchronousQueue q = new SynchronousQueue(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(one); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(two); + }}); + + ArrayList l = new ArrayList(); + int drained; + while ((drained = q.drainTo(l, 1)) == 0) Thread.yield(); + assertEquals(1, drained); + assertEquals(1, l.size()); + while ((drained = q.drainTo(l, 1)) == 0) Thread.yield(); + assertEquals(1, drained); + assertEquals(2, l.size()); + assertTrue(l.contains(one)); + assertTrue(l.contains(two)); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection q = new SynchronousQueue(); + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } + }