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