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