BlockingQueueTest.java revision 8e9a0e92906742b17eb08d7fb83cca91965f9b8e
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
10package jsr166;
11
12import static java.util.concurrent.TimeUnit.MILLISECONDS;
13
14import java.util.ArrayList;
15import java.util.Arrays;
16import java.util.Collection;
17import java.util.Queue;
18import java.util.concurrent.BlockingQueue;
19import java.util.concurrent.CountDownLatch;
20
21import junit.framework.Test;
22import junit.framework.TestSuite;
23
24/**
25 * Contains "contract" tests applicable to all BlockingQueue implementations.
26 */
27public 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. */
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     */
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     */
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     */
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     */
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     */
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
244        barrier.await();
245        long startTime = System.nanoTime();
246        assertTrue(q.offer(zero, LONG_DELAY_MS, MILLISECONDS));
247        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
248
249        barrier.await();
250        assertThreadStaysAlive(t);
251        t.interrupt();
252        awaitTermination(t);
253    }
254
255    /**
256     * take() blocks interruptibly when empty
257     */
258    public void testTakeFromEmptyBlocksInterruptibly() {
259        final BlockingQueue q = emptyCollection();
260        final CountDownLatch threadStarted = new CountDownLatch(1);
261        Thread t = newStartedThread(new CheckedRunnable() {
262            public void realRun() {
263                threadStarted.countDown();
264                try {
265                    q.take();
266                    shouldThrow();
267                } catch (InterruptedException success) {}
268                assertFalse(Thread.interrupted());
269            }});
270
271        await(threadStarted);
272        assertThreadStaysAlive(t);
273        t.interrupt();
274        awaitTermination(t);
275    }
276
277    /**
278     * take() throws InterruptedException immediately if interrupted
279     * before waiting
280     */
281    public void testTakeFromEmptyAfterInterrupt() {
282        final BlockingQueue q = emptyCollection();
283        Thread t = newStartedThread(new CheckedRunnable() {
284            public void realRun() {
285                Thread.currentThread().interrupt();
286                try {
287                    q.take();
288                    shouldThrow();
289                } catch (InterruptedException success) {}
290                assertFalse(Thread.interrupted());
291            }});
292
293        awaitTermination(t);
294    }
295
296    /**
297     * timed poll() blocks interruptibly when empty
298     */
299    public void testTimedPollFromEmptyBlocksInterruptibly() {
300        final BlockingQueue q = emptyCollection();
301        final CountDownLatch threadStarted = new CountDownLatch(1);
302        Thread t = newStartedThread(new CheckedRunnable() {
303            public void realRun() {
304                threadStarted.countDown();
305                try {
306                    q.poll(2 * LONG_DELAY_MS, MILLISECONDS);
307                    shouldThrow();
308                } catch (InterruptedException success) {}
309                assertFalse(Thread.interrupted());
310            }});
311
312        await(threadStarted);
313        assertThreadStaysAlive(t);
314        t.interrupt();
315        awaitTermination(t);
316    }
317
318    /**
319     * timed poll() throws InterruptedException immediately if
320     * interrupted before waiting
321     */
322    public void testTimedPollFromEmptyAfterInterrupt() {
323        final BlockingQueue q = emptyCollection();
324        Thread t = newStartedThread(new CheckedRunnable() {
325            public void realRun() {
326                Thread.currentThread().interrupt();
327                try {
328                    q.poll(2 * LONG_DELAY_MS, MILLISECONDS);
329                    shouldThrow();
330                } catch (InterruptedException success) {}
331                assertFalse(Thread.interrupted());
332            }});
333
334        awaitTermination(t);
335    }
336
337    /**
338     * remove(x) removes x and returns true if present
339     * TODO: move to superclass CollectionTest.java
340     */
341    public void testRemoveElement() {
342        final BlockingQueue q = emptyCollection();
343        final int size = Math.min(q.remainingCapacity(), SIZE);
344        final Object[] elts = new Object[size];
345        assertFalse(q.contains(makeElement(99)));
346        assertFalse(q.remove(makeElement(99)));
347        checkEmpty(q);
348        for (int i = 0; i < size; i++)
349            q.add(elts[i] = makeElement(i));
350        for (int i = 1; i < size; i += 2) {
351            for (int pass = 0; pass < 2; pass++) {
352                assertEquals((pass == 0), q.contains(elts[i]));
353                assertEquals((pass == 0), q.remove(elts[i]));
354                assertFalse(q.contains(elts[i]));
355                assertTrue(q.contains(elts[i-1]));
356                if (i < size - 1)
357                    assertTrue(q.contains(elts[i+1]));
358            }
359        }
360        if (size > 0)
361            assertTrue(q.contains(elts[0]));
362        for (int i = size-2; i >= 0; i -= 2) {
363            assertTrue(q.contains(elts[i]));
364            assertFalse(q.contains(elts[i+1]));
365            assertTrue(q.remove(elts[i]));
366            assertFalse(q.contains(elts[i]));
367            assertFalse(q.remove(elts[i+1]));
368            assertFalse(q.contains(elts[i+1]));
369        }
370        checkEmpty(q);
371    }
372
373    /** For debugging. */
374    public void XXXXtestFails() {
375        fail(emptyCollection().getClass().toString());
376    }
377
378}
379