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 java.util.Arrays;
12import java.util.Collection;
13import java.util.Deque;
14import java.util.Iterator;
15import java.util.NoSuchElementException;
16import java.util.Queue;
17import java.util.Random;
18import java.util.concurrent.ConcurrentLinkedDeque;
19
20import junit.framework.Test;
21import junit.framework.TestSuite;
22
23public class ConcurrentLinkedDequeTest extends JSR166TestCase {
24
25    // android-note: Removed because the CTS runner does a bad job of
26    // retrying tests that have suite() declarations.
27    //
28    // public static void main(String[] args) {
29    //     main(suite(), args);
30    // }
31    // public static Test suite() {
32    //     return new TestSuite(ConcurrentLinkedDequeTest.class);
33    // }
34
35    /**
36     * Returns a new deque of given size containing consecutive
37     * Integers 0 ... n.
38     */
39    private ConcurrentLinkedDeque<Integer> populatedDeque(int n) {
40        ConcurrentLinkedDeque<Integer> q = new ConcurrentLinkedDeque<Integer>();
41        assertTrue(q.isEmpty());
42        for (int i = 0; i < n; ++i)
43            assertTrue(q.offer(new Integer(i)));
44        assertFalse(q.isEmpty());
45        assertEquals(n, q.size());
46        return q;
47    }
48
49    /**
50     * new deque is empty
51     */
52    public void testConstructor1() {
53        assertTrue(new ConcurrentLinkedDeque().isEmpty());
54        assertEquals(0, new ConcurrentLinkedDeque().size());
55    }
56
57    /**
58     * Initializing from null Collection throws NPE
59     */
60    public void testConstructor3() {
61        try {
62            new ConcurrentLinkedDeque((Collection)null);
63            shouldThrow();
64        } catch (NullPointerException success) {}
65    }
66
67    /**
68     * Initializing from Collection of null elements throws NPE
69     */
70    public void testConstructor4() {
71        try {
72            new ConcurrentLinkedDeque(Arrays.asList(new Integer[SIZE]));
73            shouldThrow();
74        } catch (NullPointerException success) {}
75    }
76
77    /**
78     * Initializing from Collection with some null elements throws NPE
79     */
80    public void testConstructor5() {
81        Integer[] ints = new Integer[SIZE];
82        for (int i = 0; i < SIZE - 1; ++i)
83            ints[i] = new Integer(i);
84        try {
85            new ConcurrentLinkedDeque(Arrays.asList(ints));
86            shouldThrow();
87        } catch (NullPointerException success) {}
88    }
89
90    /**
91     * Deque contains all elements of collection used to initialize
92     */
93    public void testConstructor6() {
94        Integer[] ints = new Integer[SIZE];
95        for (int i = 0; i < SIZE; ++i)
96            ints[i] = new Integer(i);
97        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(Arrays.asList(ints));
98        for (int i = 0; i < SIZE; ++i)
99            assertEquals(ints[i], q.poll());
100    }
101
102    /**
103     * isEmpty is true before add, false after
104     */
105    public void testEmpty() {
106        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
107        assertTrue(q.isEmpty());
108        q.add(one);
109        assertFalse(q.isEmpty());
110        q.add(two);
111        q.remove();
112        q.remove();
113        assertTrue(q.isEmpty());
114    }
115
116    /**
117     * size() changes when elements added and removed
118     */
119    public void testSize() {
120        ConcurrentLinkedDeque q = populatedDeque(SIZE);
121        for (int i = 0; i < SIZE; ++i) {
122            assertEquals(SIZE - i, q.size());
123            q.remove();
124        }
125        for (int i = 0; i < SIZE; ++i) {
126            assertEquals(i, q.size());
127            q.add(new Integer(i));
128        }
129    }
130
131    /**
132     * push(null) throws NPE
133     */
134    public void testPushNull() {
135        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
136        try {
137            q.push(null);
138            shouldThrow();
139        } catch (NullPointerException success) {}
140    }
141
142    /**
143     * peekFirst() returns element inserted with push
144     */
145    public void testPush() {
146        ConcurrentLinkedDeque q = populatedDeque(3);
147        q.pollLast();
148        q.push(four);
149        assertSame(four, q.peekFirst());
150    }
151
152    /**
153     * pop() removes first element, or throws NSEE if empty
154     */
155    public void testPop() {
156        ConcurrentLinkedDeque q = populatedDeque(SIZE);
157        for (int i = 0; i < SIZE; ++i) {
158            assertEquals(i, q.pop());
159        }
160        try {
161            q.pop();
162            shouldThrow();
163        } catch (NoSuchElementException success) {}
164    }
165
166    /**
167     * offer(null) throws NPE
168     */
169    public void testOfferNull() {
170        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
171        try {
172            q.offer(null);
173            shouldThrow();
174        } catch (NullPointerException success) {}
175    }
176
177    /**
178     * offerFirst(null) throws NPE
179     */
180    public void testOfferFirstNull() {
181        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
182        try {
183            q.offerFirst(null);
184            shouldThrow();
185        } catch (NullPointerException success) {}
186    }
187
188    /**
189     * offerLast(null) throws NPE
190     */
191    public void testOfferLastNull() {
192        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
193        try {
194            q.offerLast(null);
195            shouldThrow();
196        } catch (NullPointerException success) {}
197    }
198
199    /**
200     * offer(x) succeeds
201     */
202    public void testOffer() {
203        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
204        assertTrue(q.offer(zero));
205        assertTrue(q.offer(one));
206        assertSame(zero, q.peekFirst());
207        assertSame(one, q.peekLast());
208    }
209
210    /**
211     * offerFirst(x) succeeds
212     */
213    public void testOfferFirst() {
214        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
215        assertTrue(q.offerFirst(zero));
216        assertTrue(q.offerFirst(one));
217        assertSame(one, q.peekFirst());
218        assertSame(zero, q.peekLast());
219    }
220
221    /**
222     * offerLast(x) succeeds
223     */
224    public void testOfferLast() {
225        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
226        assertTrue(q.offerLast(zero));
227        assertTrue(q.offerLast(one));
228        assertSame(zero, q.peekFirst());
229        assertSame(one, q.peekLast());
230    }
231
232    /**
233     * add(null) throws NPE
234     */
235    public void testAddNull() {
236        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
237        try {
238            q.add(null);
239            shouldThrow();
240        } catch (NullPointerException success) {}
241    }
242
243    /**
244     * addFirst(null) throws NPE
245     */
246    public void testAddFirstNull() {
247        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
248        try {
249            q.addFirst(null);
250            shouldThrow();
251        } catch (NullPointerException success) {}
252    }
253
254    /**
255     * addLast(null) throws NPE
256     */
257    public void testAddLastNull() {
258        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
259        try {
260            q.addLast(null);
261            shouldThrow();
262        } catch (NullPointerException success) {}
263    }
264
265    /**
266     * add(x) succeeds
267     */
268    public void testAdd() {
269        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
270        assertTrue(q.add(zero));
271        assertTrue(q.add(one));
272        assertSame(zero, q.peekFirst());
273        assertSame(one, q.peekLast());
274    }
275
276    /**
277     * addFirst(x) succeeds
278     */
279    public void testAddFirst() {
280        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
281        q.addFirst(zero);
282        q.addFirst(one);
283        assertSame(one, q.peekFirst());
284        assertSame(zero, q.peekLast());
285    }
286
287    /**
288     * addLast(x) succeeds
289     */
290    public void testAddLast() {
291        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
292        q.addLast(zero);
293        q.addLast(one);
294        assertSame(zero, q.peekFirst());
295        assertSame(one, q.peekLast());
296    }
297
298    /**
299     * addAll(null) throws NPE
300     */
301    public void testAddAll1() {
302        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
303        try {
304            q.addAll(null);
305            shouldThrow();
306        } catch (NullPointerException success) {}
307    }
308
309    /**
310     * addAll(this) throws IAE
311     */
312    public void testAddAllSelf() {
313        ConcurrentLinkedDeque q = populatedDeque(SIZE);
314        try {
315            q.addAll(q);
316            shouldThrow();
317        } catch (IllegalArgumentException success) {}
318    }
319
320    /**
321     * addAll of a collection with null elements throws NPE
322     */
323    public void testAddAll2() {
324        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
325        try {
326            q.addAll(Arrays.asList(new Integer[SIZE]));
327            shouldThrow();
328        } catch (NullPointerException success) {}
329    }
330
331    /**
332     * addAll of a collection with any null elements throws NPE after
333     * possibly adding some elements
334     */
335    public void testAddAll3() {
336        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
337        Integer[] ints = new Integer[SIZE];
338        for (int i = 0; i < SIZE - 1; ++i)
339            ints[i] = new Integer(i);
340        try {
341            q.addAll(Arrays.asList(ints));
342            shouldThrow();
343        } catch (NullPointerException success) {}
344    }
345
346    /**
347     * Deque contains all elements, in traversal order, of successful addAll
348     */
349    public void testAddAll5() {
350        Integer[] empty = new Integer[0];
351        Integer[] ints = new Integer[SIZE];
352        for (int i = 0; i < SIZE; ++i)
353            ints[i] = new Integer(i);
354        ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
355        assertFalse(q.addAll(Arrays.asList(empty)));
356        assertTrue(q.addAll(Arrays.asList(ints)));
357        for (int i = 0; i < SIZE; ++i)
358            assertEquals(ints[i], q.poll());
359    }
360
361    /**
362     * pollFirst() succeeds unless empty
363     */
364    public void testPollFirst() {
365        ConcurrentLinkedDeque q = populatedDeque(SIZE);
366        for (int i = 0; i < SIZE; ++i) {
367            assertEquals(i, q.pollFirst());
368        }
369        assertNull(q.pollFirst());
370    }
371
372    /**
373     * pollLast() succeeds unless empty
374     */
375    public void testPollLast() {
376        ConcurrentLinkedDeque q = populatedDeque(SIZE);
377        for (int i = SIZE - 1; i >= 0; --i) {
378            assertEquals(i, q.pollLast());
379        }
380        assertNull(q.pollLast());
381    }
382
383    /**
384     * poll() succeeds unless empty
385     */
386    public void testPoll() {
387        ConcurrentLinkedDeque q = populatedDeque(SIZE);
388        for (int i = 0; i < SIZE; ++i) {
389            assertEquals(i, q.poll());
390        }
391        assertNull(q.poll());
392    }
393
394    /**
395     * peek() returns next element, or null if empty
396     */
397    public void testPeek() {
398        ConcurrentLinkedDeque q = populatedDeque(SIZE);
399        for (int i = 0; i < SIZE; ++i) {
400            assertEquals(i, q.peek());
401            assertEquals(i, q.poll());
402            assertTrue(q.peek() == null ||
403                       !q.peek().equals(i));
404        }
405        assertNull(q.peek());
406    }
407
408    /**
409     * element() returns first element, or throws NSEE if empty
410     */
411    public void testElement() {
412        ConcurrentLinkedDeque q = populatedDeque(SIZE);
413        for (int i = 0; i < SIZE; ++i) {
414            assertEquals(i, q.element());
415            assertEquals(i, q.poll());
416        }
417        try {
418            q.element();
419            shouldThrow();
420        } catch (NoSuchElementException success) {}
421    }
422
423    /**
424     * remove() removes next element, or throws NSEE if empty
425     */
426    public void testRemove() {
427        ConcurrentLinkedDeque q = populatedDeque(SIZE);
428        for (int i = 0; i < SIZE; ++i) {
429            assertEquals(i, q.remove());
430        }
431        try {
432            q.remove();
433            shouldThrow();
434        } catch (NoSuchElementException success) {}
435    }
436
437    /**
438     * remove(x) removes x and returns true if present
439     */
440    public void testRemoveElement() {
441        ConcurrentLinkedDeque q = populatedDeque(SIZE);
442        for (int i = 1; i < SIZE; i += 2) {
443            assertTrue(q.contains(i));
444            assertTrue(q.remove(i));
445            assertFalse(q.contains(i));
446            assertTrue(q.contains(i - 1));
447        }
448        for (int i = 0; i < SIZE; i += 2) {
449            assertTrue(q.contains(i));
450            assertTrue(q.remove(i));
451            assertFalse(q.contains(i));
452            assertFalse(q.remove(i + 1));
453            assertFalse(q.contains(i + 1));
454        }
455        assertTrue(q.isEmpty());
456    }
457
458    /**
459     * peekFirst() returns next element, or null if empty
460     */
461    public void testPeekFirst() {
462        ConcurrentLinkedDeque q = populatedDeque(SIZE);
463        for (int i = 0; i < SIZE; ++i) {
464            assertEquals(i, q.peekFirst());
465            assertEquals(i, q.pollFirst());
466            assertTrue(q.peekFirst() == null ||
467                       !q.peekFirst().equals(i));
468        }
469        assertNull(q.peekFirst());
470    }
471
472    /**
473     * peekLast() returns next element, or null if empty
474     */
475    public void testPeekLast() {
476        ConcurrentLinkedDeque q = populatedDeque(SIZE);
477        for (int i = SIZE - 1; i >= 0; --i) {
478            assertEquals(i, q.peekLast());
479            assertEquals(i, q.pollLast());
480            assertTrue(q.peekLast() == null ||
481                       !q.peekLast().equals(i));
482        }
483        assertNull(q.peekLast());
484    }
485
486    /**
487     * getFirst() returns first element, or throws NSEE if empty
488     */
489    public void testFirstElement() {
490        ConcurrentLinkedDeque q = populatedDeque(SIZE);
491        for (int i = 0; i < SIZE; ++i) {
492            assertEquals(i, q.getFirst());
493            assertEquals(i, q.pollFirst());
494        }
495        try {
496            q.getFirst();
497            shouldThrow();
498        } catch (NoSuchElementException success) {}
499    }
500
501    /**
502     * getLast() returns last element, or throws NSEE if empty
503     */
504    public void testLastElement() {
505        ConcurrentLinkedDeque q = populatedDeque(SIZE);
506        for (int i = SIZE - 1; i >= 0; --i) {
507            assertEquals(i, q.getLast());
508            assertEquals(i, q.pollLast());
509        }
510        try {
511            q.getLast();
512            shouldThrow();
513        } catch (NoSuchElementException success) {}
514        assertNull(q.peekLast());
515    }
516
517    /**
518     * removeFirst() removes first element, or throws NSEE if empty
519     */
520    public void testRemoveFirst() {
521        ConcurrentLinkedDeque q = populatedDeque(SIZE);
522        for (int i = 0; i < SIZE; ++i) {
523            assertEquals(i, q.removeFirst());
524        }
525        try {
526            q.removeFirst();
527            shouldThrow();
528        } catch (NoSuchElementException success) {}
529        assertNull(q.peekFirst());
530    }
531
532    /**
533     * removeLast() removes last element, or throws NSEE if empty
534     */
535    public void testRemoveLast() {
536        ConcurrentLinkedDeque q = populatedDeque(SIZE);
537        for (int i = SIZE - 1; i >= 0; --i) {
538            assertEquals(i, q.removeLast());
539        }
540        try {
541            q.removeLast();
542            shouldThrow();
543        } catch (NoSuchElementException success) {}
544        assertNull(q.peekLast());
545    }
546
547    /**
548     * removeFirstOccurrence(x) removes x and returns true if present
549     */
550    public void testRemoveFirstOccurrence() {
551        ConcurrentLinkedDeque q = populatedDeque(SIZE);
552        for (int i = 1; i < SIZE; i += 2) {
553            assertTrue(q.removeFirstOccurrence(new Integer(i)));
554        }
555        for (int i = 0; i < SIZE; i += 2) {
556            assertTrue(q.removeFirstOccurrence(new Integer(i)));
557            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
558        }
559        assertTrue(q.isEmpty());
560    }
561
562    /**
563     * removeLastOccurrence(x) removes x and returns true if present
564     */
565    public void testRemoveLastOccurrence() {
566        ConcurrentLinkedDeque q = populatedDeque(SIZE);
567        for (int i = 1; i < SIZE; i += 2) {
568            assertTrue(q.removeLastOccurrence(new Integer(i)));
569        }
570        for (int i = 0; i < SIZE; i += 2) {
571            assertTrue(q.removeLastOccurrence(new Integer(i)));
572            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
573        }
574        assertTrue(q.isEmpty());
575    }
576
577    /**
578     * contains(x) reports true when elements added but not yet removed
579     */
580    public void testContains() {
581        ConcurrentLinkedDeque q = populatedDeque(SIZE);
582        for (int i = 0; i < SIZE; ++i) {
583            assertTrue(q.contains(new Integer(i)));
584            q.poll();
585            assertFalse(q.contains(new Integer(i)));
586        }
587    }
588
589    /**
590     * clear() removes all elements
591     */
592    public void testClear() {
593        ConcurrentLinkedDeque q = populatedDeque(SIZE);
594        q.clear();
595        assertTrue(q.isEmpty());
596        assertEquals(0, q.size());
597        q.add(one);
598        assertFalse(q.isEmpty());
599        q.clear();
600        assertTrue(q.isEmpty());
601    }
602
603    /**
604     * containsAll(c) is true when c contains a subset of elements
605     */
606    public void testContainsAll() {
607        ConcurrentLinkedDeque q = populatedDeque(SIZE);
608        ConcurrentLinkedDeque p = new ConcurrentLinkedDeque();
609        for (int i = 0; i < SIZE; ++i) {
610            assertTrue(q.containsAll(p));
611            assertFalse(p.containsAll(q));
612            p.add(new Integer(i));
613        }
614        assertTrue(p.containsAll(q));
615    }
616
617    /**
618     * retainAll(c) retains only those elements of c and reports true if change
619     */
620    public void testRetainAll() {
621        ConcurrentLinkedDeque q = populatedDeque(SIZE);
622        ConcurrentLinkedDeque p = populatedDeque(SIZE);
623        for (int i = 0; i < SIZE; ++i) {
624            boolean changed = q.retainAll(p);
625            if (i == 0)
626                assertFalse(changed);
627            else
628                assertTrue(changed);
629
630            assertTrue(q.containsAll(p));
631            assertEquals(SIZE - i, q.size());
632            p.remove();
633        }
634    }
635
636    /**
637     * removeAll(c) removes only those elements of c and reports true if changed
638     */
639    public void testRemoveAll() {
640        for (int i = 1; i < SIZE; ++i) {
641            ConcurrentLinkedDeque q = populatedDeque(SIZE);
642            ConcurrentLinkedDeque p = populatedDeque(i);
643            assertTrue(q.removeAll(p));
644            assertEquals(SIZE - i, q.size());
645            for (int j = 0; j < i; ++j) {
646                Integer x = (Integer)(p.remove());
647                assertFalse(q.contains(x));
648            }
649        }
650    }
651
652    /**
653     * toArray() contains all elements in FIFO order
654     */
655    public void testToArray() {
656        ConcurrentLinkedDeque q = populatedDeque(SIZE);
657        Object[] o = q.toArray();
658        for (int i = 0; i < o.length; i++)
659            assertSame(o[i], q.poll());
660    }
661
662    /**
663     * toArray(a) contains all elements in FIFO order
664     */
665    public void testToArray2() {
666        ConcurrentLinkedDeque<Integer> q = populatedDeque(SIZE);
667        Integer[] ints = new Integer[SIZE];
668        Integer[] array = q.toArray(ints);
669        assertSame(ints, array);
670        for (int i = 0; i < ints.length; i++)
671            assertSame(ints[i], q.poll());
672    }
673
674    /**
675     * toArray(null) throws NullPointerException
676     */
677    public void testToArray_NullArg() {
678        ConcurrentLinkedDeque q = populatedDeque(SIZE);
679        try {
680            q.toArray(null);
681            shouldThrow();
682        } catch (NullPointerException success) {}
683    }
684
685    /**
686     * toArray(incompatible array type) throws ArrayStoreException
687     */
688    public void testToArray1_BadArg() {
689        ConcurrentLinkedDeque q = populatedDeque(SIZE);
690        try {
691            q.toArray(new String[10]);
692            shouldThrow();
693        } catch (ArrayStoreException success) {}
694    }
695
696    /**
697     * Iterator iterates through all elements
698     */
699    public void testIterator() {
700        ConcurrentLinkedDeque q = populatedDeque(SIZE);
701        Iterator it = q.iterator();
702        int i;
703        for (i = 0; it.hasNext(); i++)
704            assertTrue(q.contains(it.next()));
705        assertEquals(i, SIZE);
706        assertIteratorExhausted(it);
707    }
708
709    /**
710     * iterator of empty collection has no elements
711     */
712    public void testEmptyIterator() {
713        Deque c = new ConcurrentLinkedDeque();
714        assertIteratorExhausted(c.iterator());
715        assertIteratorExhausted(c.descendingIterator());
716    }
717
718    /**
719     * Iterator ordering is FIFO
720     */
721    public void testIteratorOrdering() {
722        final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
723        q.add(one);
724        q.add(two);
725        q.add(three);
726
727        int k = 0;
728        for (Iterator it = q.iterator(); it.hasNext();) {
729            assertEquals(++k, it.next());
730        }
731
732        assertEquals(3, k);
733    }
734
735    /**
736     * Modifications do not cause iterators to fail
737     */
738    public void testWeaklyConsistentIteration() {
739        final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
740        q.add(one);
741        q.add(two);
742        q.add(three);
743
744        for (Iterator it = q.iterator(); it.hasNext();) {
745            q.remove();
746            it.next();
747        }
748
749        assertEquals("deque should be empty again", 0, q.size());
750    }
751
752    /**
753     * iterator.remove() removes current element
754     */
755    public void testIteratorRemove() {
756        final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
757        final Random rng = new Random();
758        for (int iters = 0; iters < 100; ++iters) {
759            int max = rng.nextInt(5) + 2;
760            int split = rng.nextInt(max - 1) + 1;
761            for (int j = 1; j <= max; ++j)
762                q.add(new Integer(j));
763            Iterator it = q.iterator();
764            for (int j = 1; j <= split; ++j)
765                assertEquals(it.next(), new Integer(j));
766            it.remove();
767            assertEquals(it.next(), new Integer(split + 1));
768            for (int j = 1; j <= split; ++j)
769                q.remove(new Integer(j));
770            it = q.iterator();
771            for (int j = split + 1; j <= max; ++j) {
772                assertEquals(it.next(), new Integer(j));
773                it.remove();
774            }
775            assertFalse(it.hasNext());
776            assertTrue(q.isEmpty());
777        }
778    }
779
780    /**
781     * Descending iterator iterates through all elements
782     */
783    public void testDescendingIterator() {
784        ConcurrentLinkedDeque q = populatedDeque(SIZE);
785        int i = 0;
786        Iterator it = q.descendingIterator();
787        while (it.hasNext()) {
788            assertTrue(q.contains(it.next()));
789            ++i;
790        }
791        assertEquals(i, SIZE);
792        assertFalse(it.hasNext());
793        try {
794            it.next();
795            shouldThrow();
796        } catch (NoSuchElementException success) {}
797    }
798
799    /**
800     * Descending iterator ordering is reverse FIFO
801     */
802    public void testDescendingIteratorOrdering() {
803        final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
804        for (int iters = 0; iters < 100; ++iters) {
805            q.add(new Integer(3));
806            q.add(new Integer(2));
807            q.add(new Integer(1));
808            int k = 0;
809            for (Iterator it = q.descendingIterator(); it.hasNext();) {
810                assertEquals(++k, it.next());
811            }
812
813            assertEquals(3, k);
814            q.remove();
815            q.remove();
816            q.remove();
817        }
818    }
819
820    /**
821     * descendingIterator.remove() removes current element
822     */
823    public void testDescendingIteratorRemove() {
824        final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
825        final Random rng = new Random();
826        for (int iters = 0; iters < 100; ++iters) {
827            int max = rng.nextInt(5) + 2;
828            int split = rng.nextInt(max - 1) + 1;
829            for (int j = max; j >= 1; --j)
830                q.add(new Integer(j));
831            Iterator it = q.descendingIterator();
832            for (int j = 1; j <= split; ++j)
833                assertEquals(it.next(), new Integer(j));
834            it.remove();
835            assertEquals(it.next(), new Integer(split + 1));
836            for (int j = 1; j <= split; ++j)
837                q.remove(new Integer(j));
838            it = q.descendingIterator();
839            for (int j = split + 1; j <= max; ++j) {
840                assertEquals(it.next(), new Integer(j));
841                it.remove();
842            }
843            assertFalse(it.hasNext());
844            assertTrue(q.isEmpty());
845        }
846    }
847
848    /**
849     * toString() contains toStrings of elements
850     */
851    public void testToString() {
852        ConcurrentLinkedDeque q = populatedDeque(SIZE);
853        String s = q.toString();
854        for (int i = 0; i < SIZE; ++i) {
855            assertTrue(s.contains(String.valueOf(i)));
856        }
857    }
858
859    /**
860     * A deserialized serialized deque has same elements in same order
861     */
862    public void testSerialization() throws Exception {
863        Queue x = populatedDeque(SIZE);
864        Queue y = serialClone(x);
865
866        assertNotSame(x, y);
867        assertEquals(x.size(), y.size());
868        assertEquals(x.toString(), y.toString());
869        assertTrue(Arrays.equals(x.toArray(), y.toArray()));
870        while (!x.isEmpty()) {
871            assertFalse(y.isEmpty());
872            assertEquals(x.remove(), y.remove());
873        }
874        assertTrue(y.isEmpty());
875    }
876
877    /**
878     * contains(null) always return false.
879     * remove(null) always throws NullPointerException.
880     */
881    public void testNeverContainsNull() {
882        Deque<?>[] qs = {
883            new ConcurrentLinkedDeque<Object>(),
884            populatedDeque(2),
885        };
886
887        for (Deque<?> q : qs) {
888            assertFalse(q.contains(null));
889            try {
890                assertFalse(q.remove(null));
891                shouldThrow();
892            } catch (NullPointerException success) {}
893            try {
894                assertFalse(q.removeFirstOccurrence(null));
895                shouldThrow();
896            } catch (NullPointerException success) {}
897            try {
898                assertFalse(q.removeLastOccurrence(null));
899                shouldThrow();
900            } catch (NullPointerException success) {}
901        }
902    }
903}
904