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