11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2011 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.Uninterruptibles;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ArrayBlockingQueue;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.BlockingQueue;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutorService;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executors;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Future;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.LinkedBlockingQueue;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.PriorityBlockingQueue;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.SynchronousQueue;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Tests for {@link Queues}.
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Dimitris Andreou
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class QueuesTest extends TestCase {
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /*
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * All the following tests relate to BlockingQueue methods in Queues.
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static List<BlockingQueue<Object>> blockingQueues() {
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return ImmutableList.<BlockingQueue<Object>>of(
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new LinkedBlockingQueue<Object>(),
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new LinkedBlockingQueue<Object>(10),
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new SynchronousQueue<Object>(),
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new ArrayBlockingQueue<Object>(10),
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new PriorityBlockingQueue<Object>(10, Ordering.arbitrary()));
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private ExecutorService threadPool;
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void setUp() {
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool = Executors.newCachedThreadPool();
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void tearDown() throws InterruptedException {
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // notice that if a Producer is interrupted (a bug), the Producer will go into an infinite
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // loop, which will be noticed here
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.shutdown();
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue("Some worker didn't finish in time",
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        threadPool.awaitTermination(1, TimeUnit.SECONDS));
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <T> int drain(BlockingQueue<T> q, Collection<? super T> buffer, int maxElements,
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long timeout, TimeUnit unit, boolean interruptibly) throws InterruptedException {
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return interruptibly
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ? Queues.drain(q, buffer, maxElements, timeout, unit)
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        : Queues.drainUninterruptibly(q, buffer, maxElements, timeout, unit);
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testMultipleProducers() throws Exception {
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (BlockingQueue<Object> q : blockingQueues()) {
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      testMultipleProducers(q);
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void testMultipleProducers(BlockingQueue<Object> q)
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws InterruptedException {
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (boolean interruptibly : new boolean[] { true, false }) {
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threadPool.submit(new Producer(q, 20));
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threadPool.submit(new Producer(q, 20));
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threadPool.submit(new Producer(q, 20));
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threadPool.submit(new Producer(q, 20));
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threadPool.submit(new Producer(q, 20));
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      List<Object> buf = Lists.newArrayList();
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int elements = drain(q, buf, 100, Long.MAX_VALUE, TimeUnit.NANOSECONDS, interruptibly);
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals(100, elements);
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals(100, buf.size());
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertDrained(q);
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testDrainTimesOut() throws Exception {
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (BlockingQueue<Object> q : blockingQueues()) {
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      testDrainTimesOut(q);
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void testDrainTimesOut(BlockingQueue<Object> q) throws Exception {
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (boolean interruptibly : new boolean[] { true, false }) {
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals(0, Queues.drain(q, ImmutableList.of(), 1, 10, TimeUnit.MILLISECONDS));
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // producing one, will ask for two
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Future<?> submitter = threadPool.submit(new Producer(q, 1));
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // make sure we time out
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long startTime = System.nanoTime();
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int drained = drain(q, Lists.newArrayList(), 2, 10, TimeUnit.MILLISECONDS, interruptibly);
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertTrue(drained <= 1);
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertTrue((System.nanoTime() - startTime) >= TimeUnit.MILLISECONDS.toNanos(10));
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // If even the first one wasn't there, clean up so that the next test doesn't see an element.
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      submitter.get();
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (drained == 0) {
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertNotNull(q.poll());
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testZeroElements() throws Exception {
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (BlockingQueue<Object> q : blockingQueues()) {
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      testZeroElements(q);
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void testZeroElements(BlockingQueue<Object> q) throws InterruptedException {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (boolean interruptibly : new boolean[] { true, false }) {
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // asking to drain zero elements
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals(0, drain(q, ImmutableList.of(), 0, 10, TimeUnit.MILLISECONDS, interruptibly));
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testEmpty() throws Exception {
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (BlockingQueue<Object> q : blockingQueues()) {
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      testEmpty(q);
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void testEmpty(BlockingQueue<Object> q) {
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertDrained(q);
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNegativeMaxElements() throws Exception {
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (BlockingQueue<Object> q : blockingQueues()) {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      testNegativeMaxElements(q);
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void testNegativeMaxElements(BlockingQueue<Object> q) throws InterruptedException {
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.submit(new Producer(q, 1));
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<Object> buf = Lists.newArrayList();
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int elements = Queues.drain(q, buf, -1, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(elements, 0);
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(buf.isEmpty());
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Clean up produced element to free the producer thread, otherwise it will complain
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // when we shutdown the threadpool.
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Queues.drain(q, buf, 1, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testDrain_throws() throws Exception {
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (BlockingQueue<Object> q : blockingQueues()) {
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      testDrain_throws(q);
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void testDrain_throws(BlockingQueue<Object> q) {
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.submit(new Interrupter(Thread.currentThread()));
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Queues.drain(q, ImmutableList.of(), 100, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (InterruptedException expected) {
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testDrainUninterruptibly_doesNotThrow() throws Exception {
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (BlockingQueue<Object> q : blockingQueues()) {
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      testDrainUninterruptibly_doesNotThrow(q);
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void testDrainUninterruptibly_doesNotThrow(final BlockingQueue<Object> q) {
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Thread mainThread = Thread.currentThread();
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.submit(new Runnable() {
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void run() {
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new Producer(q, 50).run();
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new Interrupter(mainThread).run();
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new Producer(q, 50).run();
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    });
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<Object> buf = Lists.newArrayList();
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int elements =
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Queues.drainUninterruptibly(q, buf, 100, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // so when this drains all elements, we know the thread has also been interrupted in between
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(Thread.interrupted());
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(100, elements);
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(100, buf.size());
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNewLinkedBlockingQueueCapacity() {
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Queues.newLinkedBlockingQueue(0);
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("Should have thrown IllegalArgumentException");
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // any capacity less than 1 should throw IllegalArgumentException
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, Queues.newLinkedBlockingQueue(1).remainingCapacity());
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(11, Queues.newLinkedBlockingQueue(11).remainingCapacity());
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Checks that #drain() invocations behave correctly for a drained (empty) queue.
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void assertDrained(BlockingQueue<Object> q) {
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertNull(q.peek());
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertInterruptibleDrained(q);
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertUninterruptibleDrained(q);
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void assertInterruptibleDrained(BlockingQueue<Object> q) {
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // nothing to drain, thus this should wait doing nothing
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals(0, Queues.drain(q, ImmutableList.of(), 0, 10, TimeUnit.MILLISECONDS));
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (InterruptedException e) {
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError();
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // but does the wait actually occurs?
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.submit(new Interrupter(Thread.currentThread()));
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // if waiting works, this should get stuck
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Queues.drain(q, Lists.newArrayList(), 1, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (InterruptedException expected) {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // we indeed waited; a slow thread had enough time to interrupt us
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // same as above; uninterruptible version
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private void assertUninterruptibleDrained(BlockingQueue<Object> q) {
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0,
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Queues.drainUninterruptibly(q, ImmutableList.of(), 0, 10, TimeUnit.MILLISECONDS));
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // but does the wait actually occurs?
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.submit(new Interrupter(Thread.currentThread()));
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long startTime = System.nanoTime();
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Queues.drainUninterruptibly(
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        q, Lists.newArrayList(), 1, 10, TimeUnit.MILLISECONDS);
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue((System.nanoTime() - startTime) >= TimeUnit.MILLISECONDS.toNanos(10));
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // wait for interrupted status and clear it
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    while (!Thread.interrupted()) { Thread.yield(); }
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class Producer implements Runnable {
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final BlockingQueue<Object> q;
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int elements;
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Producer(BlockingQueue<Object> q, int elements) {
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.q = q;
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.elements = elements;
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void run() {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (int i = 0; i < elements; i++) {
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          q.put(new Object());
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (InterruptedException e) {
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // TODO(user): replace this when there is a better way to spawn threads in tests and
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // have threads propagate their errors back to the test thread.
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        e.printStackTrace();
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // never returns, so that #tearDown() notices that one worker isn't done
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Uninterruptibles.sleepUninterruptibly(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class Interrupter implements Runnable {
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Thread threadToInterrupt;
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Interrupter(Thread threadToInterrupt) {
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.threadToInterrupt = threadToInterrupt;
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public void run() {
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Thread.sleep(100);
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (InterruptedException e) {
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new AssertionError();
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        threadToInterrupt.interrupt();
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
308