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