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
37import static java.util.concurrent.TimeUnit.MILLISECONDS;
38
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.Collection;
42import java.util.Queue;
43import java.util.concurrent.BlockingQueue;
44import java.util.concurrent.CountDownLatch;
45
46import junit.framework.Test;
47import junit.framework.TestSuite;
48
49/**
50 * Contains "contract" tests applicable to all BlockingQueue implementations.
51 */
52public 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     * put(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(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        for (int n : ns)
220            assertEquals(0, q.drainTo(new ArrayList(), n));
221        if (q.remainingCapacity() > 0) {
222            // Not SynchronousQueue, that is
223            Object one = makeElement(1);
224            q.add(one);
225            ArrayList c = new ArrayList();
226            for (int n : ns)
227                assertEquals(0, q.drainTo(new ArrayList(), n));
228            assertEquals(1, q.size());
229            assertSame(one, q.poll());
230            assertTrue(c.isEmpty());
231        }
232    }
233
234    /**
235     * timed poll before a delayed offer times out; after offer succeeds;
236     * on interruption throws
237     */
238    public void testTimedPollWithOffer() throws InterruptedException {
239        final BlockingQueue q = emptyCollection();
240        final CheckedBarrier barrier = new CheckedBarrier(2);
241        final Object zero = makeElement(0);
242        Thread t = newStartedThread(new CheckedRunnable() {
243            public void realRun() throws InterruptedException {
244                long startTime = System.nanoTime();
245                assertNull(q.poll(timeoutMillis(), MILLISECONDS));
246                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
247
248                barrier.await();
249
250                assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
251
252                Thread.currentThread().interrupt();
253                try {
254                    q.poll(LONG_DELAY_MS, MILLISECONDS);
255                    shouldThrow();
256                } catch (InterruptedException success) {}
257                assertFalse(Thread.interrupted());
258
259                barrier.await();
260                try {
261                    q.poll(LONG_DELAY_MS, MILLISECONDS);
262                    shouldThrow();
263                } catch (InterruptedException success) {}
264                assertFalse(Thread.interrupted());
265
266                assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
267            }});
268
269        barrier.await();
270        long startTime = System.nanoTime();
271        assertTrue(q.offer(zero, LONG_DELAY_MS, MILLISECONDS));
272        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
273
274        barrier.await();
275        assertThreadStaysAlive(t);
276        t.interrupt();
277        awaitTermination(t);
278    }
279
280    /**
281     * take() blocks interruptibly when empty
282     */
283    public void testTakeFromEmptyBlocksInterruptibly() {
284        final BlockingQueue q = emptyCollection();
285        final CountDownLatch threadStarted = new CountDownLatch(1);
286        Thread t = newStartedThread(new CheckedRunnable() {
287            public void realRun() {
288                threadStarted.countDown();
289                try {
290                    q.take();
291                    shouldThrow();
292                } catch (InterruptedException success) {}
293                assertFalse(Thread.interrupted());
294            }});
295
296        await(threadStarted);
297        assertThreadStaysAlive(t);
298        t.interrupt();
299        awaitTermination(t);
300    }
301
302    /**
303     * take() throws InterruptedException immediately if interrupted
304     * before waiting
305     */
306    public void testTakeFromEmptyAfterInterrupt() {
307        final BlockingQueue q = emptyCollection();
308        Thread t = newStartedThread(new CheckedRunnable() {
309            public void realRun() {
310                Thread.currentThread().interrupt();
311                try {
312                    q.take();
313                    shouldThrow();
314                } catch (InterruptedException success) {}
315                assertFalse(Thread.interrupted());
316            }});
317
318        awaitTermination(t);
319    }
320
321    /**
322     * timed poll() blocks interruptibly when empty
323     */
324    public void testTimedPollFromEmptyBlocksInterruptibly() {
325        final BlockingQueue q = emptyCollection();
326        final CountDownLatch threadStarted = new CountDownLatch(1);
327        Thread t = newStartedThread(new CheckedRunnable() {
328            public void realRun() {
329                threadStarted.countDown();
330                try {
331                    q.poll(2 * LONG_DELAY_MS, MILLISECONDS);
332                    shouldThrow();
333                } catch (InterruptedException success) {}
334                assertFalse(Thread.interrupted());
335            }});
336
337        await(threadStarted);
338        assertThreadStaysAlive(t);
339        t.interrupt();
340        awaitTermination(t);
341    }
342
343    /**
344     * timed poll() throws InterruptedException immediately if
345     * interrupted before waiting
346     */
347    public void testTimedPollFromEmptyAfterInterrupt() {
348        final BlockingQueue q = emptyCollection();
349        Thread t = newStartedThread(new CheckedRunnable() {
350            public void realRun() {
351                Thread.currentThread().interrupt();
352                try {
353                    q.poll(2 * LONG_DELAY_MS, MILLISECONDS);
354                    shouldThrow();
355                } catch (InterruptedException success) {}
356                assertFalse(Thread.interrupted());
357            }});
358
359        awaitTermination(t);
360    }
361
362    /**
363     * remove(x) removes x and returns true if present
364     * TODO: move to superclass CollectionTest.java
365     */
366    public void testRemoveElement() {
367        final BlockingQueue q = emptyCollection();
368        final int size = Math.min(q.remainingCapacity(), SIZE);
369        final Object[] elts = new Object[size];
370        assertFalse(q.contains(makeElement(99)));
371        assertFalse(q.remove(makeElement(99)));
372        checkEmpty(q);
373        for (int i = 0; i < size; i++)
374            q.add(elts[i] = makeElement(i));
375        for (int i = 1; i < size; i += 2) {
376            for (int pass = 0; pass < 2; pass++) {
377                assertEquals((pass == 0), q.contains(elts[i]));
378                assertEquals((pass == 0), q.remove(elts[i]));
379                assertFalse(q.contains(elts[i]));
380                assertTrue(q.contains(elts[i - 1]));
381                if (i < size - 1)
382                    assertTrue(q.contains(elts[i + 1]));
383            }
384        }
385        if (size > 0)
386            assertTrue(q.contains(elts[0]));
387        for (int i = size - 2; i >= 0; i -= 2) {
388            assertTrue(q.contains(elts[i]));
389            assertFalse(q.contains(elts[i + 1]));
390            assertTrue(q.remove(elts[i]));
391            assertFalse(q.contains(elts[i]));
392            assertFalse(q.remove(elts[i + 1]));
393            assertFalse(q.contains(elts[i + 1]));
394        }
395        checkEmpty(q);
396    }
397
398    /** For debugging. */
399    public void XXXXtestFails() {
400        fail(emptyCollection().getClass().toString());
401    }
402
403}
404