1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  */
  22 
  23 /*
  24  * This file is available under and governed by the GNU General Public
  25  * License version 2 only, as published by the Free Software Foundation.
  26  * However, the following notice accompanied the original version of this
  27  * file:
  28  *
  29  * Written by Doug Lea and Martin Buchholz with assistance from members
  30  * of JCP JSR-166 Expert Group and released to the public domain, as
  31  * explained at http://creativecommons.org/publicdomain/zero/1.0/
  32  *
  33  * Other contributors include Andrew Wright, Jeffrey Hayes,
  34  * Pat Fisher, Mike Judd.
  35  */
  36 
  37 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  38 
  39 import java.util.ArrayList;
  40 import java.util.Arrays;
  41 import java.util.Collection;
  42 import java.util.Queue;
  43 import java.util.concurrent.BlockingQueue;
  44 import java.util.concurrent.CountDownLatch;
  45 
  46 import junit.framework.Test;
  47 import junit.framework.TestSuite;
  48 
  49 /**
  50  * Contains "contract" tests applicable to all BlockingQueue implementations.
  51  */
  52 public abstract class BlockingQueueTest extends JSR166TestCase {
  53     /*
  54      * This is the start of an attempt to refactor the tests for the
  55      * various related implementations of related interfaces without
  56      * too much duplicated code.  junit does not really support such
  57      * testing.  Here subclasses of TestCase not only contain tests,
  58      * but also configuration information that describes the
  59      * implementation class, most importantly how to instantiate
  60      * instances.
  61      */
  62 
  63     /** Like suite(), but non-static */
  64     public Test testSuite() {
  65         // TODO: filter the returned tests using the configuration
  66         // information provided by the subclass via protected methods.
  67         return new TestSuite(this.getClass());
  68     }
  69 
  70     //----------------------------------------------------------------
  71     // Configuration methods
  72     //----------------------------------------------------------------
  73 
  74     /** Returns an empty instance of the implementation class. */
  75     protected abstract BlockingQueue emptyCollection();
  76 
  77     /**
  78      * Returns an element suitable for insertion in the collection.
  79      * Override for collections with unusual element types.
  80      */
  81     protected Object makeElement(int i) {
  82         return Integer.valueOf(i);
  83     }
  84 
  85     //----------------------------------------------------------------
  86     // Tests
  87     //----------------------------------------------------------------
  88 
  89     /**
  90      * offer(null) throws NullPointerException
  91      */
  92     public void testOfferNull() {
  93         final Queue q = emptyCollection();
  94         try {
  95             q.offer(null);
  96             shouldThrow();
  97         } catch (NullPointerException success) {}
  98     }
  99 
 100     /**
 101      * add(null) throws NullPointerException
 102      */
 103     public void testAddNull() {
 104         final Collection q = emptyCollection();
 105         try {
 106             q.add(null);
 107             shouldThrow();
 108         } catch (NullPointerException success) {}
 109     }
 110 
 111     /**
 112      * timed offer(null) throws NullPointerException
 113      */
 114     public void testTimedOfferNull() throws InterruptedException {
 115         final BlockingQueue q = emptyCollection();
 116         long startTime = System.nanoTime();
 117         try {
 118             q.offer(null, LONG_DELAY_MS, MILLISECONDS);
 119             shouldThrow();
 120         } catch (NullPointerException success) {}
 121         assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 122     }
 123 
 124     /**
 125      * put(null) throws NullPointerException
 126      */
 127     public void testPutNull() throws InterruptedException {
 128         final BlockingQueue q = emptyCollection();
 129         try {
 130             q.put(null);
 131             shouldThrow();
 132         } catch (NullPointerException success) {}
 133     }
 134 
 135     /**
 136      * addAll(null) throws NullPointerException
 137      */
 138     public void testAddAllNull() throws InterruptedException {
 139         final Collection q = emptyCollection();
 140         try {
 141             q.addAll(null);
 142             shouldThrow();
 143         } catch (NullPointerException success) {}
 144     }
 145 
 146     /**
 147      * addAll of a collection with null elements throws NullPointerException
 148      */
 149     public void testAddAllNullElements() {
 150         final Collection q = emptyCollection();
 151         final Collection<Integer> elements = Arrays.asList(new Integer[SIZE]);
 152         try {
 153             q.addAll(elements);
 154             shouldThrow();
 155         } catch (NullPointerException success) {}
 156     }
 157 
 158     /**
 159      * toArray(null) throws NullPointerException
 160      */
 161     public void testToArray_NullArray() {
 162         final Collection q = emptyCollection();
 163         try {
 164             q.toArray((Object[])null);
 165             shouldThrow();
 166         } catch (NullPointerException success) {}
 167     }
 168 
 169     /**
 170      * drainTo(null) throws NullPointerException
 171      */
 172     public void testDrainToNull() {
 173         final BlockingQueue q = emptyCollection();
 174         try {
 175             q.drainTo(null);
 176             shouldThrow();
 177         } catch (NullPointerException success) {}
 178     }
 179 
 180     /**
 181      * drainTo(this) throws IllegalArgumentException
 182      */
 183     public void testDrainToSelf() {
 184         final BlockingQueue q = emptyCollection();
 185         try {
 186             q.drainTo(q);
 187             shouldThrow();
 188         } catch (IllegalArgumentException success) {}
 189     }
 190 
 191     /**
 192      * drainTo(null, n) throws NullPointerException
 193      */
 194     public void testDrainToNullN() {
 195         final BlockingQueue q = emptyCollection();
 196         try {
 197             q.drainTo(null, 0);
 198             shouldThrow();
 199         } catch (NullPointerException success) {}
 200     }
 201 
 202     /**
 203      * drainTo(this, n) throws IllegalArgumentException
 204      */
 205     public void testDrainToSelfN() {
 206         final BlockingQueue q = emptyCollection();
 207         try {
 208             q.drainTo(q, 0);
 209             shouldThrow();
 210         } catch (IllegalArgumentException success) {}
 211     }
 212 
 213     /**
 214      * drainTo(c, n) returns 0 and does nothing when n <= 0
 215      */
 216     public void testDrainToNonPositiveMaxElements() {
 217         final BlockingQueue q = emptyCollection();
 218         final int[] ns = { 0, -1, -42, Integer.MIN_VALUE };
 219         final ArrayList sink = new ArrayList();
 220         for (int n : ns) {
 221             assertEquals(0, q.drainTo(sink, n));
 222             assertTrue(sink.isEmpty());
 223         }
 224         if (q.remainingCapacity() > 0) {
 225             // Not SynchronousQueue, that is
 226             Object one = makeElement(1);
 227             q.add(one);
 228             for (int n : ns)
 229                 assertEquals(0, q.drainTo(sink, n));
 230             assertEquals(1, q.size());
 231             assertSame(one, q.poll());
 232             assertTrue(sink.isEmpty());
 233         }
 234     }
 235 
 236     /**
 237      * timed poll before a delayed offer times out; after offer succeeds;
 238      * on interruption throws
 239      */
 240     public void testTimedPollWithOffer() throws InterruptedException {
 241         final BlockingQueue q = emptyCollection();
 242         final CheckedBarrier barrier = new CheckedBarrier(2);
 243         final Object zero = makeElement(0);
 244         Thread t = newStartedThread(new CheckedRunnable() {
 245             public void realRun() throws InterruptedException {
 246                 long startTime = System.nanoTime();
 247                 assertNull(q.poll(timeoutMillis(), MILLISECONDS));
 248                 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 249 
 250                 barrier.await();
 251 
 252                 assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
 253 
 254                 Thread.currentThread().interrupt();
 255                 try {
 256                     q.poll(randomTimeout(), randomTimeUnit());
 257                     shouldThrow();
 258                 } catch (InterruptedException success) {}
 259                 assertFalse(Thread.interrupted());
 260 
 261                 barrier.await();
 262                 try {
 263                     q.poll(LONG_DELAY_MS, MILLISECONDS);
 264                     shouldThrow();
 265                 } catch (InterruptedException success) {}
 266                 assertFalse(Thread.interrupted());
 267 
 268                 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 269             }});
 270 
 271         barrier.await();
 272         long startTime = System.nanoTime();
 273         assertTrue(q.offer(zero, LONG_DELAY_MS, MILLISECONDS));
 274         assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
 275 
 276         barrier.await();
 277         if (randomBoolean()) assertThreadBlocks(t, Thread.State.TIMED_WAITING);
 278         t.interrupt();
 279         awaitTermination(t);
 280     }
 281 
 282     /**
 283      * take() blocks interruptibly when empty
 284      */
 285     public void testTakeFromEmptyBlocksInterruptibly() {
 286         final BlockingQueue q = emptyCollection();
 287         final CountDownLatch threadStarted = new CountDownLatch(1);
 288         Thread t = newStartedThread(new CheckedRunnable() {
 289             public void realRun() {
 290                 threadStarted.countDown();
 291                 try {
 292                     q.take();
 293                     shouldThrow();
 294                 } catch (InterruptedException success) {}
 295                 assertFalse(Thread.interrupted());
 296             }});
 297 
 298         await(threadStarted);
 299         if (randomBoolean()) assertThreadBlocks(t, Thread.State.WAITING);
 300         t.interrupt();
 301         awaitTermination(t);
 302     }
 303 
 304     /**
 305      * take() throws InterruptedException immediately if interrupted
 306      * before waiting
 307      */
 308     public void testTakeFromEmptyAfterInterrupt() {
 309         final BlockingQueue q = emptyCollection();
 310         Thread t = newStartedThread(new CheckedRunnable() {
 311             public void realRun() {
 312                 Thread.currentThread().interrupt();
 313                 try {
 314                     q.take();
 315                     shouldThrow();
 316                 } catch (InterruptedException success) {}
 317                 assertFalse(Thread.interrupted());
 318             }});
 319 
 320         awaitTermination(t);
 321     }
 322 
 323     /**
 324      * timed poll() blocks interruptibly when empty
 325      */
 326     public void testTimedPollFromEmptyBlocksInterruptibly() {
 327         final BlockingQueue q = emptyCollection();
 328         final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
 329         Thread t = newStartedThread(new CheckedRunnable() {
 330             public void realRun() {
 331                 pleaseInterrupt.countDown();
 332                 try {
 333                     q.poll(LONGER_DELAY_MS, MILLISECONDS);
 334                     shouldThrow();
 335                 } catch (InterruptedException success) {}
 336                 assertFalse(Thread.interrupted());
 337             }});
 338 
 339         await(pleaseInterrupt);
 340         if (randomBoolean()) assertThreadBlocks(t, Thread.State.TIMED_WAITING);
 341         t.interrupt();
 342         awaitTermination(t);
 343     }
 344 
 345     /**
 346      * timed poll() throws InterruptedException immediately if
 347      * interrupted before waiting
 348      */
 349     public void testTimedPollFromEmptyAfterInterrupt() {
 350         final BlockingQueue q = emptyCollection();
 351         Thread t = newStartedThread(new CheckedRunnable() {
 352             public void realRun() {
 353                 Thread.currentThread().interrupt();
 354                 try {
 355                     q.poll(LONGER_DELAY_MS, MILLISECONDS);
 356                     shouldThrow();
 357                 } catch (InterruptedException success) {}
 358                 assertFalse(Thread.interrupted());
 359             }});
 360 
 361         awaitTermination(t);
 362     }
 363 
 364     /**
 365      * remove(x) removes x and returns true if present
 366      * TODO: move to superclass CollectionTest.java
 367      */
 368     public void testRemoveElement() {
 369         final BlockingQueue q = emptyCollection();
 370         final int size = Math.min(q.remainingCapacity(), SIZE);
 371         final Object[] elts = new Object[size];
 372         assertFalse(q.contains(makeElement(99)));
 373         assertFalse(q.remove(makeElement(99)));
 374         checkEmpty(q);
 375         for (int i = 0; i < size; i++)
 376             q.add(elts[i] = makeElement(i));
 377         for (int i = 1; i < size; i += 2) {
 378             for (int pass = 0; pass < 2; pass++) {
 379                 assertEquals((pass == 0), q.contains(elts[i]));
 380                 assertEquals((pass == 0), q.remove(elts[i]));
 381                 assertFalse(q.contains(elts[i]));
 382                 assertTrue(q.contains(elts[i - 1]));
 383                 if (i < size - 1)
 384                     assertTrue(q.contains(elts[i + 1]));
 385             }
 386         }
 387         if (size > 0)
 388             assertTrue(q.contains(elts[0]));
 389         for (int i = size - 2; i >= 0; i -= 2) {
 390             assertTrue(q.contains(elts[i]));
 391             assertFalse(q.contains(elts[i + 1]));
 392             assertTrue(q.remove(elts[i]));
 393             assertFalse(q.contains(elts[i]));
 394             assertFalse(q.remove(elts[i + 1]));
 395             assertFalse(q.contains(elts[i + 1]));
 396         }
 397         checkEmpty(q);
 398     }
 399 
 400     /** For debugging. */
 401     public void XXXXtestFails() {
 402         fail(emptyCollection().getClass().toString());
 403     }
 404 
 405 }