1/*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package jsr166;
10
11import static java.util.concurrent.TimeUnit.MILLISECONDS;
12
13import java.util.ArrayList;
14import java.util.Arrays;
15import java.util.Collection;
16import java.util.Iterator;
17import java.util.NoSuchElementException;
18import java.util.Queue;
19import java.util.concurrent.BlockingQueue;
20import java.util.concurrent.CountDownLatch;
21import java.util.concurrent.Executors;
22import java.util.concurrent.ExecutorService;
23import java.util.concurrent.LinkedBlockingQueue;
24
25import junit.framework.Test;
26
27public class LinkedBlockingQueueTest extends JSR166TestCase {
28
29    // android-note: These tests have been moved into their own separate
30    // classes to work around CTS issues.
31    //
32    // public static class Unbounded extends BlockingQueueTest {
33    //     protected BlockingQueue emptyCollection() {
34    //         return new LinkedBlockingQueue();
35    //     }
36    // }
37
38    // public static class Bounded extends BlockingQueueTest {
39    //     protected BlockingQueue emptyCollection() {
40    //         return new LinkedBlockingQueue(SIZE);
41    //     }
42    // }
43
44    // android-note: Removed because the CTS runner does a bad job of
45    // retrying tests that have suite() declarations.
46    //
47    // public static void main(String[] args) {
48    //     main(suite(), args);
49    // }
50    // public static Test suite() {
51    //     return newTestSuite(LinkedBlockingQueueTest.class,
52    //                         new Unbounded().testSuite(),
53    //                         new Bounded().testSuite());
54    // }
55
56    /**
57     * Returns a new queue of given size containing consecutive
58     * Integers 0 ... n.
59     */
60    private LinkedBlockingQueue<Integer> populatedQueue(int n) {
61        LinkedBlockingQueue<Integer> q =
62            new LinkedBlockingQueue<Integer>(n);
63        assertTrue(q.isEmpty());
64        for (int i = 0; i < n; i++)
65            assertTrue(q.offer(new Integer(i)));
66        assertFalse(q.isEmpty());
67        assertEquals(0, q.remainingCapacity());
68        assertEquals(n, q.size());
69        return q;
70    }
71
72    /**
73     * A new queue has the indicated capacity, or Integer.MAX_VALUE if
74     * none given
75     */
76    public void testConstructor1() {
77        assertEquals(SIZE, new LinkedBlockingQueue(SIZE).remainingCapacity());
78        assertEquals(Integer.MAX_VALUE, new LinkedBlockingQueue().remainingCapacity());
79    }
80
81    /**
82     * Constructor throws IllegalArgumentException if capacity argument nonpositive
83     */
84    public void testConstructor2() {
85        try {
86            new LinkedBlockingQueue(0);
87            shouldThrow();
88        } catch (IllegalArgumentException success) {}
89    }
90
91    /**
92     * Initializing from null Collection throws NullPointerException
93     */
94    public void testConstructor3() {
95        try {
96            new LinkedBlockingQueue(null);
97            shouldThrow();
98        } catch (NullPointerException success) {}
99    }
100
101    /**
102     * Initializing from Collection of null elements throws NullPointerException
103     */
104    public void testConstructor4() {
105        Collection<Integer> elements = Arrays.asList(new Integer[SIZE]);
106        try {
107            new LinkedBlockingQueue(elements);
108            shouldThrow();
109        } catch (NullPointerException success) {}
110    }
111
112    /**
113     * Initializing from Collection with some null elements throws
114     * NullPointerException
115     */
116    public void testConstructor5() {
117        Integer[] ints = new Integer[SIZE];
118        for (int i = 0; i < SIZE - 1; ++i)
119            ints[i] = new Integer(i);
120        Collection<Integer> elements = Arrays.asList(ints);
121        try {
122            new LinkedBlockingQueue(elements);
123            shouldThrow();
124        } catch (NullPointerException success) {}
125    }
126
127    /**
128     * Queue contains all elements of collection used to initialize
129     */
130    public void testConstructor6() {
131        Integer[] ints = new Integer[SIZE];
132        for (int i = 0; i < SIZE; ++i)
133            ints[i] = new Integer(i);
134        LinkedBlockingQueue q = new LinkedBlockingQueue(Arrays.asList(ints));
135        for (int i = 0; i < SIZE; ++i)
136            assertEquals(ints[i], q.poll());
137    }
138
139    /**
140     * Queue transitions from empty to full when elements added
141     */
142    public void testEmptyFull() {
143        LinkedBlockingQueue q = new LinkedBlockingQueue(2);
144        assertTrue(q.isEmpty());
145        assertEquals("should have room for 2", 2, q.remainingCapacity());
146        q.add(one);
147        assertFalse(q.isEmpty());
148        q.add(two);
149        assertFalse(q.isEmpty());
150        assertEquals(0, q.remainingCapacity());
151        assertFalse(q.offer(three));
152    }
153
154    /**
155     * remainingCapacity decreases on add, increases on remove
156     */
157    public void testRemainingCapacity() {
158        BlockingQueue q = populatedQueue(SIZE);
159        for (int i = 0; i < SIZE; ++i) {
160            assertEquals(i, q.remainingCapacity());
161            assertEquals(SIZE, q.size() + q.remainingCapacity());
162            assertEquals(i, q.remove());
163        }
164        for (int i = 0; i < SIZE; ++i) {
165            assertEquals(SIZE - i, q.remainingCapacity());
166            assertEquals(SIZE, q.size() + q.remainingCapacity());
167            assertTrue(q.add(i));
168        }
169    }
170
171    /**
172     * Offer succeeds if not full; fails if full
173     */
174    public void testOffer() {
175        LinkedBlockingQueue q = new LinkedBlockingQueue(1);
176        assertTrue(q.offer(zero));
177        assertFalse(q.offer(one));
178    }
179
180    /**
181     * add succeeds if not full; throws IllegalStateException if full
182     */
183    public void testAdd() {
184        LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
185        for (int i = 0; i < SIZE; ++i)
186            assertTrue(q.add(new Integer(i)));
187        assertEquals(0, q.remainingCapacity());
188        try {
189            q.add(new Integer(SIZE));
190            shouldThrow();
191        } catch (IllegalStateException success) {}
192    }
193
194    /**
195     * addAll(this) throws IllegalArgumentException
196     */
197    public void testAddAllSelf() {
198        LinkedBlockingQueue q = populatedQueue(SIZE);
199        try {
200            q.addAll(q);
201            shouldThrow();
202        } catch (IllegalArgumentException success) {}
203    }
204
205    /**
206     * addAll of a collection with any null elements throws NPE after
207     * possibly adding some elements
208     */
209    public void testAddAll3() {
210        LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
211        Integer[] ints = new Integer[SIZE];
212        for (int i = 0; i < SIZE - 1; ++i)
213            ints[i] = new Integer(i);
214        Collection<Integer> elements = Arrays.asList(ints);
215        try {
216            q.addAll(elements);
217            shouldThrow();
218        } catch (NullPointerException success) {}
219    }
220
221    /**
222     * addAll throws IllegalStateException if not enough room
223     */
224    public void testAddAll4() {
225        LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE - 1);
226        Integer[] ints = new Integer[SIZE];
227        for (int i = 0; i < SIZE; ++i)
228            ints[i] = new Integer(i);
229        Collection<Integer> elements = Arrays.asList(ints);
230        try {
231            q.addAll(elements);
232            shouldThrow();
233        } catch (IllegalStateException success) {}
234    }
235
236    /**
237     * Queue contains all elements, in traversal order, of successful addAll
238     */
239    public void testAddAll5() {
240        Integer[] empty = new Integer[0];
241        Integer[] ints = new Integer[SIZE];
242        for (int i = 0; i < SIZE; ++i)
243            ints[i] = new Integer(i);
244        LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
245        assertFalse(q.addAll(Arrays.asList(empty)));
246        assertTrue(q.addAll(Arrays.asList(ints)));
247        for (int i = 0; i < SIZE; ++i)
248            assertEquals(ints[i], q.poll());
249    }
250
251    /**
252     * all elements successfully put are contained
253     */
254    public void testPut() throws InterruptedException {
255        LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
256        for (int i = 0; i < SIZE; ++i) {
257            Integer x = new Integer(i);
258            q.put(x);
259            assertTrue(q.contains(x));
260        }
261        assertEquals(0, q.remainingCapacity());
262    }
263
264    /**
265     * put blocks interruptibly if full
266     */
267    public void testBlockingPut() throws InterruptedException {
268        final LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
269        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
270        Thread t = newStartedThread(new CheckedRunnable() {
271            public void realRun() throws InterruptedException {
272                for (int i = 0; i < SIZE; ++i)
273                    q.put(i);
274                assertEquals(SIZE, q.size());
275                assertEquals(0, q.remainingCapacity());
276
277                Thread.currentThread().interrupt();
278                try {
279                    q.put(99);
280                    shouldThrow();
281                } catch (InterruptedException success) {}
282                assertFalse(Thread.interrupted());
283
284                pleaseInterrupt.countDown();
285                try {
286                    q.put(99);
287                    shouldThrow();
288                } catch (InterruptedException success) {}
289                assertFalse(Thread.interrupted());
290            }});
291
292        await(pleaseInterrupt);
293        assertThreadStaysAlive(t);
294        t.interrupt();
295        awaitTermination(t);
296        assertEquals(SIZE, q.size());
297        assertEquals(0, q.remainingCapacity());
298    }
299
300    /**
301     * put blocks interruptibly waiting for take when full
302     */
303    public void testPutWithTake() throws InterruptedException {
304        final int capacity = 2;
305        final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
306        final CountDownLatch pleaseTake = new CountDownLatch(1);
307        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
308        Thread t = newStartedThread(new CheckedRunnable() {
309            public void realRun() throws InterruptedException {
310                for (int i = 0; i < capacity; i++)
311                    q.put(i);
312                pleaseTake.countDown();
313                q.put(86);
314
315                pleaseInterrupt.countDown();
316                try {
317                    q.put(99);
318                    shouldThrow();
319                } catch (InterruptedException success) {}
320                assertFalse(Thread.interrupted());
321            }});
322
323        await(pleaseTake);
324        assertEquals(0, q.remainingCapacity());
325        assertEquals(0, q.take());
326
327        await(pleaseInterrupt);
328        assertThreadStaysAlive(t);
329        t.interrupt();
330        awaitTermination(t);
331        assertEquals(0, q.remainingCapacity());
332    }
333
334    /**
335     * timed offer times out if full and elements not taken
336     */
337    public void testTimedOffer() {
338        final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
339        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
340        Thread t = newStartedThread(new CheckedRunnable() {
341            public void realRun() throws InterruptedException {
342                q.put(new Object());
343                q.put(new Object());
344                long startTime = System.nanoTime();
345                assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS));
346                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
347                pleaseInterrupt.countDown();
348                try {
349                    q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
350                    shouldThrow();
351                } catch (InterruptedException success) {}
352            }});
353
354        await(pleaseInterrupt);
355        assertThreadStaysAlive(t);
356        t.interrupt();
357        awaitTermination(t);
358    }
359
360    /**
361     * take retrieves elements in FIFO order
362     */
363    public void testTake() throws InterruptedException {
364        LinkedBlockingQueue q = populatedQueue(SIZE);
365        for (int i = 0; i < SIZE; ++i) {
366            assertEquals(i, q.take());
367        }
368    }
369
370    /**
371     * Take removes existing elements until empty, then blocks interruptibly
372     */
373    public void testBlockingTake() throws InterruptedException {
374        final BlockingQueue q = populatedQueue(SIZE);
375        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
376        Thread t = newStartedThread(new CheckedRunnable() {
377            public void realRun() throws InterruptedException {
378                for (int i = 0; i < SIZE; ++i) {
379                    assertEquals(i, q.take());
380                }
381
382                Thread.currentThread().interrupt();
383                try {
384                    q.take();
385                    shouldThrow();
386                } catch (InterruptedException success) {}
387                assertFalse(Thread.interrupted());
388
389                pleaseInterrupt.countDown();
390                try {
391                    q.take();
392                    shouldThrow();
393                } catch (InterruptedException success) {}
394                assertFalse(Thread.interrupted());
395            }});
396
397        await(pleaseInterrupt);
398        assertThreadStaysAlive(t);
399        t.interrupt();
400        awaitTermination(t);
401    }
402
403    /**
404     * poll succeeds unless empty
405     */
406    public void testPoll() {
407        LinkedBlockingQueue q = populatedQueue(SIZE);
408        for (int i = 0; i < SIZE; ++i) {
409            assertEquals(i, q.poll());
410        }
411        assertNull(q.poll());
412    }
413
414    /**
415     * timed poll with zero timeout succeeds when non-empty, else times out
416     */
417    public void testTimedPoll0() throws InterruptedException {
418        LinkedBlockingQueue q = populatedQueue(SIZE);
419        for (int i = 0; i < SIZE; ++i) {
420            assertEquals(i, q.poll(0, MILLISECONDS));
421        }
422        assertNull(q.poll(0, MILLISECONDS));
423    }
424
425    /**
426     * timed poll with nonzero timeout succeeds when non-empty, else times out
427     */
428    public void testTimedPoll() throws InterruptedException {
429        LinkedBlockingQueue<Integer> q = populatedQueue(SIZE);
430        for (int i = 0; i < SIZE; ++i) {
431            long startTime = System.nanoTime();
432            assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
433            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
434        }
435        long startTime = System.nanoTime();
436        assertNull(q.poll(timeoutMillis(), MILLISECONDS));
437        assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
438        checkEmpty(q);
439    }
440
441    /**
442     * Interrupted timed poll throws InterruptedException instead of
443     * returning timeout status
444     */
445    public void testInterruptedTimedPoll() throws InterruptedException {
446        final BlockingQueue<Integer> q = populatedQueue(SIZE);
447        final CountDownLatch aboutToWait = new CountDownLatch(1);
448        Thread t = newStartedThread(new CheckedRunnable() {
449            public void realRun() throws InterruptedException {
450                long startTime = System.nanoTime();
451                for (int i = 0; i < SIZE; ++i) {
452                    assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
453                }
454                aboutToWait.countDown();
455                try {
456                    q.poll(LONG_DELAY_MS, MILLISECONDS);
457                    shouldThrow();
458                } catch (InterruptedException success) {
459                    assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
460                }
461            }});
462
463        await(aboutToWait);
464        waitForThreadToEnterWaitState(t, LONG_DELAY_MS);
465        t.interrupt();
466        awaitTermination(t);
467        checkEmpty(q);
468    }
469
470    /**
471     * peek returns next element, or null if empty
472     */
473    public void testPeek() {
474        LinkedBlockingQueue q = populatedQueue(SIZE);
475        for (int i = 0; i < SIZE; ++i) {
476            assertEquals(i, q.peek());
477            assertEquals(i, q.poll());
478            assertTrue(q.peek() == null ||
479                       !q.peek().equals(i));
480        }
481        assertNull(q.peek());
482    }
483
484    /**
485     * element returns next element, or throws NSEE if empty
486     */
487    public void testElement() {
488        LinkedBlockingQueue q = populatedQueue(SIZE);
489        for (int i = 0; i < SIZE; ++i) {
490            assertEquals(i, q.element());
491            assertEquals(i, q.poll());
492        }
493        try {
494            q.element();
495            shouldThrow();
496        } catch (NoSuchElementException success) {}
497    }
498
499    /**
500     * remove removes next element, or throws NSEE if empty
501     */
502    public void testRemove() {
503        LinkedBlockingQueue q = populatedQueue(SIZE);
504        for (int i = 0; i < SIZE; ++i) {
505            assertEquals(i, q.remove());
506        }
507        try {
508            q.remove();
509            shouldThrow();
510        } catch (NoSuchElementException success) {}
511    }
512
513    /**
514     * An add following remove(x) succeeds
515     */
516    public void testRemoveElementAndAdd() throws InterruptedException {
517        LinkedBlockingQueue q = new LinkedBlockingQueue();
518        assertTrue(q.add(new Integer(1)));
519        assertTrue(q.add(new Integer(2)));
520        assertTrue(q.remove(new Integer(1)));
521        assertTrue(q.remove(new Integer(2)));
522        assertTrue(q.add(new Integer(3)));
523        assertNotNull(q.take());
524    }
525
526    /**
527     * contains(x) reports true when elements added but not yet removed
528     */
529    public void testContains() {
530        LinkedBlockingQueue q = populatedQueue(SIZE);
531        for (int i = 0; i < SIZE; ++i) {
532            assertTrue(q.contains(new Integer(i)));
533            q.poll();
534            assertFalse(q.contains(new Integer(i)));
535        }
536    }
537
538    /**
539     * clear removes all elements
540     */
541    public void testClear() {
542        LinkedBlockingQueue q = populatedQueue(SIZE);
543        q.clear();
544        assertTrue(q.isEmpty());
545        assertEquals(0, q.size());
546        assertEquals(SIZE, q.remainingCapacity());
547        q.add(one);
548        assertFalse(q.isEmpty());
549        assertTrue(q.contains(one));
550        q.clear();
551        assertTrue(q.isEmpty());
552    }
553
554    /**
555     * containsAll(c) is true when c contains a subset of elements
556     */
557    public void testContainsAll() {
558        LinkedBlockingQueue q = populatedQueue(SIZE);
559        LinkedBlockingQueue p = new LinkedBlockingQueue(SIZE);
560        for (int i = 0; i < SIZE; ++i) {
561            assertTrue(q.containsAll(p));
562            assertFalse(p.containsAll(q));
563            p.add(new Integer(i));
564        }
565        assertTrue(p.containsAll(q));
566    }
567
568    /**
569     * retainAll(c) retains only those elements of c and reports true if changed
570     */
571    public void testRetainAll() {
572        LinkedBlockingQueue q = populatedQueue(SIZE);
573        LinkedBlockingQueue p = populatedQueue(SIZE);
574        for (int i = 0; i < SIZE; ++i) {
575            boolean changed = q.retainAll(p);
576            if (i == 0)
577                assertFalse(changed);
578            else
579                assertTrue(changed);
580
581            assertTrue(q.containsAll(p));
582            assertEquals(SIZE - i, q.size());
583            p.remove();
584        }
585    }
586
587    /**
588     * removeAll(c) removes only those elements of c and reports true if changed
589     */
590    public void testRemoveAll() {
591        for (int i = 1; i < SIZE; ++i) {
592            LinkedBlockingQueue q = populatedQueue(SIZE);
593            LinkedBlockingQueue p = populatedQueue(i);
594            assertTrue(q.removeAll(p));
595            assertEquals(SIZE - i, q.size());
596            for (int j = 0; j < i; ++j) {
597                Integer x = (Integer)(p.remove());
598                assertFalse(q.contains(x));
599            }
600        }
601    }
602
603    /**
604     * toArray contains all elements in FIFO order
605     */
606    public void testToArray() {
607        LinkedBlockingQueue q = populatedQueue(SIZE);
608        Object[] o = q.toArray();
609        for (int i = 0; i < o.length; i++)
610            assertSame(o[i], q.poll());
611    }
612
613    /**
614     * toArray(a) contains all elements in FIFO order
615     */
616    public void testToArray2() throws InterruptedException {
617        LinkedBlockingQueue<Integer> q = populatedQueue(SIZE);
618        Integer[] ints = new Integer[SIZE];
619        Integer[] array = q.toArray(ints);
620        assertSame(ints, array);
621        for (int i = 0; i < ints.length; i++)
622            assertSame(ints[i], q.poll());
623    }
624
625    /**
626     * toArray(incompatible array type) throws ArrayStoreException
627     */
628    public void testToArray1_BadArg() {
629        LinkedBlockingQueue q = populatedQueue(SIZE);
630        try {
631            q.toArray(new String[10]);
632            shouldThrow();
633        } catch (ArrayStoreException success) {}
634    }
635
636    /**
637     * iterator iterates through all elements
638     */
639    public void testIterator() throws InterruptedException {
640        LinkedBlockingQueue q = populatedQueue(SIZE);
641        Iterator it = q.iterator();
642        int i;
643        for (i = 0; it.hasNext(); i++)
644            assertTrue(q.contains(it.next()));
645        assertEquals(i, SIZE);
646        assertIteratorExhausted(it);
647
648        it = q.iterator();
649        for (i = 0; it.hasNext(); i++)
650            assertEquals(it.next(), q.take());
651        assertEquals(i, SIZE);
652        assertIteratorExhausted(it);
653    }
654
655    /**
656     * iterator of empty collection has no elements
657     */
658    public void testEmptyIterator() {
659        assertIteratorExhausted(new LinkedBlockingQueue().iterator());
660    }
661
662    /**
663     * iterator.remove removes current element
664     */
665    public void testIteratorRemove() {
666        final LinkedBlockingQueue q = new LinkedBlockingQueue(3);
667        q.add(two);
668        q.add(one);
669        q.add(three);
670
671        Iterator it = q.iterator();
672        it.next();
673        it.remove();
674
675        it = q.iterator();
676        assertSame(it.next(), one);
677        assertSame(it.next(), three);
678        assertFalse(it.hasNext());
679    }
680
681    /**
682     * iterator ordering is FIFO
683     */
684    public void testIteratorOrdering() {
685        final LinkedBlockingQueue q = new LinkedBlockingQueue(3);
686        q.add(one);
687        q.add(two);
688        q.add(three);
689        assertEquals(0, q.remainingCapacity());
690        int k = 0;
691        for (Iterator it = q.iterator(); it.hasNext();) {
692            assertEquals(++k, it.next());
693        }
694        assertEquals(3, k);
695    }
696
697    /**
698     * Modifications do not cause iterators to fail
699     */
700    public void testWeaklyConsistentIteration() {
701        final LinkedBlockingQueue q = new LinkedBlockingQueue(3);
702        q.add(one);
703        q.add(two);
704        q.add(three);
705        for (Iterator it = q.iterator(); it.hasNext();) {
706            q.remove();
707            it.next();
708        }
709        assertEquals(0, q.size());
710    }
711
712    /**
713     * toString contains toStrings of elements
714     */
715    public void testToString() {
716        LinkedBlockingQueue q = populatedQueue(SIZE);
717        String s = q.toString();
718        for (int i = 0; i < SIZE; ++i) {
719            assertTrue(s.contains(String.valueOf(i)));
720        }
721    }
722
723    /**
724     * offer transfers elements across Executor tasks
725     */
726    public void testOfferInExecutor() {
727        final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
728        q.add(one);
729        q.add(two);
730        final CheckedBarrier threadsStarted = new CheckedBarrier(2);
731        final ExecutorService executor = Executors.newFixedThreadPool(2);
732        try (PoolCleaner cleaner = cleaner(executor)) {
733            executor.execute(new CheckedRunnable() {
734                public void realRun() throws InterruptedException {
735                    assertFalse(q.offer(three));
736                    threadsStarted.await();
737                    assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS));
738                    assertEquals(0, q.remainingCapacity());
739                }});
740
741            executor.execute(new CheckedRunnable() {
742                public void realRun() throws InterruptedException {
743                    threadsStarted.await();
744                    assertSame(one, q.take());
745                }});
746        }
747    }
748
749    /**
750     * timed poll retrieves elements across Executor threads
751     */
752    public void testPollInExecutor() {
753        final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
754        final CheckedBarrier threadsStarted = new CheckedBarrier(2);
755        final ExecutorService executor = Executors.newFixedThreadPool(2);
756        try (PoolCleaner cleaner = cleaner(executor)) {
757            executor.execute(new CheckedRunnable() {
758                public void realRun() throws InterruptedException {
759                    assertNull(q.poll());
760                    threadsStarted.await();
761                    assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS));
762                    checkEmpty(q);
763                }});
764
765            executor.execute(new CheckedRunnable() {
766                public void realRun() throws InterruptedException {
767                    threadsStarted.await();
768                    q.put(one);
769                }});
770        }
771    }
772
773    /**
774     * A deserialized serialized queue has same elements in same order
775     */
776    public void testSerialization() throws Exception {
777        Queue x = populatedQueue(SIZE);
778        Queue y = serialClone(x);
779
780        assertNotSame(x, y);
781        assertEquals(x.size(), y.size());
782        assertEquals(x.toString(), y.toString());
783        assertTrue(Arrays.equals(x.toArray(), y.toArray()));
784        while (!x.isEmpty()) {
785            assertFalse(y.isEmpty());
786            assertEquals(x.remove(), y.remove());
787        }
788        assertTrue(y.isEmpty());
789    }
790
791    /**
792     * drainTo(c) empties queue into another collection c
793     */
794    public void testDrainTo() {
795        LinkedBlockingQueue q = populatedQueue(SIZE);
796        ArrayList l = new ArrayList();
797        q.drainTo(l);
798        assertEquals(0, q.size());
799        assertEquals(SIZE, l.size());
800        for (int i = 0; i < SIZE; ++i)
801            assertEquals(l.get(i), new Integer(i));
802        q.add(zero);
803        q.add(one);
804        assertFalse(q.isEmpty());
805        assertTrue(q.contains(zero));
806        assertTrue(q.contains(one));
807        l.clear();
808        q.drainTo(l);
809        assertEquals(0, q.size());
810        assertEquals(2, l.size());
811        for (int i = 0; i < 2; ++i)
812            assertEquals(l.get(i), new Integer(i));
813    }
814
815    /**
816     * drainTo empties full queue, unblocking a waiting put.
817     */
818    public void testDrainToWithActivePut() throws InterruptedException {
819        final LinkedBlockingQueue q = populatedQueue(SIZE);
820        Thread t = new Thread(new CheckedRunnable() {
821            public void realRun() throws InterruptedException {
822                q.put(new Integer(SIZE + 1));
823            }});
824
825        t.start();
826        ArrayList l = new ArrayList();
827        q.drainTo(l);
828        assertTrue(l.size() >= SIZE);
829        for (int i = 0; i < SIZE; ++i)
830            assertEquals(l.get(i), new Integer(i));
831        t.join();
832        assertTrue(q.size() + l.size() >= SIZE);
833    }
834
835    /**
836     * drainTo(c, n) empties first min(n, size) elements of queue into c
837     */
838    public void testDrainToN() {
839        LinkedBlockingQueue q = new LinkedBlockingQueue();
840        for (int i = 0; i < SIZE + 2; ++i) {
841            for (int j = 0; j < SIZE; j++)
842                assertTrue(q.offer(new Integer(j)));
843            ArrayList l = new ArrayList();
844            q.drainTo(l, i);
845            int k = (i < SIZE) ? i : SIZE;
846            assertEquals(k, l.size());
847            assertEquals(SIZE - k, q.size());
848            for (int j = 0; j < k; ++j)
849                assertEquals(l.get(j), new Integer(j));
850            do {} while (q.poll() != null);
851        }
852    }
853
854    /**
855     * remove(null), contains(null) always return false
856     */
857    public void testNeverContainsNull() {
858        Collection<?>[] qs = {
859            new LinkedBlockingQueue<Object>(),
860            populatedQueue(2),
861        };
862
863        for (Collection<?> q : qs) {
864            assertFalse(q.contains(null));
865            assertFalse(q.remove(null));
866        }
867    }
868
869}
870