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