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.Iterator;
14import java.util.NoSuchElementException;
15import java.util.Queue;
16import java.util.concurrent.ConcurrentLinkedQueue;
17
18import junit.framework.Test;
19import junit.framework.TestSuite;
20
21public class ConcurrentLinkedQueueTest extends JSR166TestCase {
22
23    // android-note: Removed because the CTS runner does a bad job of
24    // retrying tests that have suite() declarations.
25    //
26    // public static void main(String[] args) {
27    //     main(suite(), args);
28    // }
29    // public static Test suite() {
30    //     return new TestSuite(ConcurrentLinkedQueueTest.class);
31    // }
32
33    /**
34     * Returns a new queue of given size containing consecutive
35     * Integers 0 ... n.
36     */
37    private ConcurrentLinkedQueue<Integer> populatedQueue(int n) {
38        ConcurrentLinkedQueue<Integer> q = new ConcurrentLinkedQueue<Integer>();
39        assertTrue(q.isEmpty());
40        for (int i = 0; i < n; ++i)
41            assertTrue(q.offer(new Integer(i)));
42        assertFalse(q.isEmpty());
43        assertEquals(n, q.size());
44        return q;
45    }
46
47    /**
48     * new queue is empty
49     */
50    public void testConstructor1() {
51        assertEquals(0, new ConcurrentLinkedQueue().size());
52    }
53
54    /**
55     * Initializing from null Collection throws NPE
56     */
57    public void testConstructor3() {
58        try {
59            new ConcurrentLinkedQueue((Collection)null);
60            shouldThrow();
61        } catch (NullPointerException success) {}
62    }
63
64    /**
65     * Initializing from Collection of null elements throws NPE
66     */
67    public void testConstructor4() {
68        try {
69            new ConcurrentLinkedQueue(Arrays.asList(new Integer[SIZE]));
70            shouldThrow();
71        } catch (NullPointerException success) {}
72    }
73
74    /**
75     * Initializing from Collection with some null elements throws NPE
76     */
77    public void testConstructor5() {
78        Integer[] ints = new Integer[SIZE];
79        for (int i = 0; i < SIZE - 1; ++i)
80            ints[i] = new Integer(i);
81        try {
82            new ConcurrentLinkedQueue(Arrays.asList(ints));
83            shouldThrow();
84        } catch (NullPointerException success) {}
85    }
86
87    /**
88     * Queue contains all elements of collection used to initialize
89     */
90    public void testConstructor6() {
91        Integer[] ints = new Integer[SIZE];
92        for (int i = 0; i < SIZE; ++i)
93            ints[i] = new Integer(i);
94        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(Arrays.asList(ints));
95        for (int i = 0; i < SIZE; ++i)
96            assertEquals(ints[i], q.poll());
97    }
98
99    /**
100     * isEmpty is true before add, false after
101     */
102    public void testEmpty() {
103        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
104        assertTrue(q.isEmpty());
105        q.add(one);
106        assertFalse(q.isEmpty());
107        q.add(two);
108        q.remove();
109        q.remove();
110        assertTrue(q.isEmpty());
111    }
112
113    /**
114     * size changes when elements added and removed
115     */
116    public void testSize() {
117        ConcurrentLinkedQueue q = populatedQueue(SIZE);
118        for (int i = 0; i < SIZE; ++i) {
119            assertEquals(SIZE - i, q.size());
120            q.remove();
121        }
122        for (int i = 0; i < SIZE; ++i) {
123            assertEquals(i, q.size());
124            q.add(new Integer(i));
125        }
126    }
127
128    /**
129     * offer(null) throws NPE
130     */
131    public void testOfferNull() {
132        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
133        try {
134            q.offer(null);
135            shouldThrow();
136        } catch (NullPointerException success) {}
137    }
138
139    /**
140     * add(null) throws NPE
141     */
142    public void testAddNull() {
143        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
144        try {
145            q.add(null);
146            shouldThrow();
147        } catch (NullPointerException success) {}
148    }
149
150    /**
151     * Offer returns true
152     */
153    public void testOffer() {
154        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
155        assertTrue(q.offer(zero));
156        assertTrue(q.offer(one));
157    }
158
159    /**
160     * add returns true
161     */
162    public void testAdd() {
163        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
164        for (int i = 0; i < SIZE; ++i) {
165            assertEquals(i, q.size());
166            assertTrue(q.add(new Integer(i)));
167        }
168    }
169
170    /**
171     * addAll(null) throws NPE
172     */
173    public void testAddAll1() {
174        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
175        try {
176            q.addAll(null);
177            shouldThrow();
178        } catch (NullPointerException success) {}
179    }
180
181    /**
182     * addAll(this) throws IAE
183     */
184    public void testAddAllSelf() {
185        ConcurrentLinkedQueue q = populatedQueue(SIZE);
186        try {
187            q.addAll(q);
188            shouldThrow();
189        } catch (IllegalArgumentException success) {}
190    }
191
192    /**
193     * addAll of a collection with null elements throws NPE
194     */
195    public void testAddAll2() {
196        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
197        try {
198            q.addAll(Arrays.asList(new Integer[SIZE]));
199            shouldThrow();
200        } catch (NullPointerException success) {}
201    }
202
203    /**
204     * addAll of a collection with any null elements throws NPE after
205     * possibly adding some elements
206     */
207    public void testAddAll3() {
208        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
209        Integer[] ints = new Integer[SIZE];
210        for (int i = 0; i < SIZE - 1; ++i)
211            ints[i] = new Integer(i);
212        try {
213            q.addAll(Arrays.asList(ints));
214            shouldThrow();
215        } catch (NullPointerException success) {}
216    }
217
218    /**
219     * Queue contains all elements, in traversal order, of successful addAll
220     */
221    public void testAddAll5() {
222        Integer[] empty = new Integer[0];
223        Integer[] ints = new Integer[SIZE];
224        for (int i = 0; i < SIZE; ++i)
225            ints[i] = new Integer(i);
226        ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
227        assertFalse(q.addAll(Arrays.asList(empty)));
228        assertTrue(q.addAll(Arrays.asList(ints)));
229        for (int i = 0; i < SIZE; ++i)
230            assertEquals(ints[i], q.poll());
231    }
232
233    /**
234     * poll succeeds unless empty
235     */
236    public void testPoll() {
237        ConcurrentLinkedQueue q = populatedQueue(SIZE);
238        for (int i = 0; i < SIZE; ++i) {
239            assertEquals(i, q.poll());
240        }
241        assertNull(q.poll());
242    }
243
244    /**
245     * peek returns next element, or null if empty
246     */
247    public void testPeek() {
248        ConcurrentLinkedQueue q = populatedQueue(SIZE);
249        for (int i = 0; i < SIZE; ++i) {
250            assertEquals(i, q.peek());
251            assertEquals(i, q.poll());
252            assertTrue(q.peek() == null ||
253                       !q.peek().equals(i));
254        }
255        assertNull(q.peek());
256    }
257
258    /**
259     * element returns next element, or throws NSEE if empty
260     */
261    public void testElement() {
262        ConcurrentLinkedQueue q = populatedQueue(SIZE);
263        for (int i = 0; i < SIZE; ++i) {
264            assertEquals(i, q.element());
265            assertEquals(i, q.poll());
266        }
267        try {
268            q.element();
269            shouldThrow();
270        } catch (NoSuchElementException success) {}
271    }
272
273    /**
274     * remove removes next element, or throws NSEE if empty
275     */
276    public void testRemove() {
277        ConcurrentLinkedQueue q = populatedQueue(SIZE);
278        for (int i = 0; i < SIZE; ++i) {
279            assertEquals(i, q.remove());
280        }
281        try {
282            q.remove();
283            shouldThrow();
284        } catch (NoSuchElementException success) {}
285    }
286
287    /**
288     * remove(x) removes x and returns true if present
289     */
290    public void testRemoveElement() {
291        ConcurrentLinkedQueue q = populatedQueue(SIZE);
292        for (int i = 1; i < SIZE; i += 2) {
293            assertTrue(q.contains(i));
294            assertTrue(q.remove(i));
295            assertFalse(q.contains(i));
296            assertTrue(q.contains(i - 1));
297        }
298        for (int i = 0; i < SIZE; i += 2) {
299            assertTrue(q.contains(i));
300            assertTrue(q.remove(i));
301            assertFalse(q.contains(i));
302            assertFalse(q.remove(i + 1));
303            assertFalse(q.contains(i + 1));
304        }
305        assertTrue(q.isEmpty());
306    }
307
308    /**
309     * contains(x) reports true when elements added but not yet removed
310     */
311    public void testContains() {
312        ConcurrentLinkedQueue q = populatedQueue(SIZE);
313        for (int i = 0; i < SIZE; ++i) {
314            assertTrue(q.contains(new Integer(i)));
315            q.poll();
316            assertFalse(q.contains(new Integer(i)));
317        }
318    }
319
320    /**
321     * clear removes all elements
322     */
323    public void testClear() {
324        ConcurrentLinkedQueue q = populatedQueue(SIZE);
325        q.clear();
326        assertTrue(q.isEmpty());
327        assertEquals(0, q.size());
328        q.add(one);
329        assertFalse(q.isEmpty());
330        q.clear();
331        assertTrue(q.isEmpty());
332    }
333
334    /**
335     * containsAll(c) is true when c contains a subset of elements
336     */
337    public void testContainsAll() {
338        ConcurrentLinkedQueue q = populatedQueue(SIZE);
339        ConcurrentLinkedQueue p = new ConcurrentLinkedQueue();
340        for (int i = 0; i < SIZE; ++i) {
341            assertTrue(q.containsAll(p));
342            assertFalse(p.containsAll(q));
343            p.add(new Integer(i));
344        }
345        assertTrue(p.containsAll(q));
346    }
347
348    /**
349     * retainAll(c) retains only those elements of c and reports true if change
350     */
351    public void testRetainAll() {
352        ConcurrentLinkedQueue q = populatedQueue(SIZE);
353        ConcurrentLinkedQueue p = populatedQueue(SIZE);
354        for (int i = 0; i < SIZE; ++i) {
355            boolean changed = q.retainAll(p);
356            if (i == 0)
357                assertFalse(changed);
358            else
359                assertTrue(changed);
360
361            assertTrue(q.containsAll(p));
362            assertEquals(SIZE - i, q.size());
363            p.remove();
364        }
365    }
366
367    /**
368     * removeAll(c) removes only those elements of c and reports true if changed
369     */
370    public void testRemoveAll() {
371        for (int i = 1; i < SIZE; ++i) {
372            ConcurrentLinkedQueue q = populatedQueue(SIZE);
373            ConcurrentLinkedQueue p = populatedQueue(i);
374            assertTrue(q.removeAll(p));
375            assertEquals(SIZE - i, q.size());
376            for (int j = 0; j < i; ++j) {
377                Integer x = (Integer)(p.remove());
378                assertFalse(q.contains(x));
379            }
380        }
381    }
382
383    /**
384     * toArray contains all elements in FIFO order
385     */
386    public void testToArray() {
387        ConcurrentLinkedQueue q = populatedQueue(SIZE);
388        Object[] o = q.toArray();
389        for (int i = 0; i < o.length; i++)
390            assertSame(o[i], q.poll());
391    }
392
393    /**
394     * toArray(a) contains all elements in FIFO order
395     */
396    public void testToArray2() {
397        ConcurrentLinkedQueue<Integer> q = populatedQueue(SIZE);
398        Integer[] ints = new Integer[SIZE];
399        Integer[] array = q.toArray(ints);
400        assertSame(ints, array);
401        for (int i = 0; i < ints.length; i++)
402            assertSame(ints[i], q.poll());
403    }
404
405    /**
406     * toArray(null) throws NullPointerException
407     */
408    public void testToArray_NullArg() {
409        ConcurrentLinkedQueue q = populatedQueue(SIZE);
410        try {
411            q.toArray(null);
412            shouldThrow();
413        } catch (NullPointerException success) {}
414    }
415
416    /**
417     * toArray(incompatible array type) throws ArrayStoreException
418     */
419    public void testToArray1_BadArg() {
420        ConcurrentLinkedQueue q = populatedQueue(SIZE);
421        try {
422            q.toArray(new String[10]);
423            shouldThrow();
424        } catch (ArrayStoreException success) {}
425    }
426
427    /**
428     * iterator iterates through all elements
429     */
430    public void testIterator() {
431        ConcurrentLinkedQueue q = populatedQueue(SIZE);
432        Iterator it = q.iterator();
433        int i;
434        for (i = 0; it.hasNext(); i++)
435            assertTrue(q.contains(it.next()));
436        assertEquals(i, SIZE);
437        assertIteratorExhausted(it);
438    }
439
440    /**
441     * iterator of empty collection has no elements
442     */
443    public void testEmptyIterator() {
444        assertIteratorExhausted(new ConcurrentLinkedQueue().iterator());
445    }
446
447    /**
448     * iterator ordering is FIFO
449     */
450    public void testIteratorOrdering() {
451        final ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
452        q.add(one);
453        q.add(two);
454        q.add(three);
455
456        int k = 0;
457        for (Iterator it = q.iterator(); it.hasNext();) {
458            assertEquals(++k, it.next());
459        }
460
461        assertEquals(3, k);
462    }
463
464    /**
465     * Modifications do not cause iterators to fail
466     */
467    public void testWeaklyConsistentIteration() {
468        final ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
469        q.add(one);
470        q.add(two);
471        q.add(three);
472
473        for (Iterator it = q.iterator(); it.hasNext();) {
474            q.remove();
475            it.next();
476        }
477
478        assertEquals("queue should be empty again", 0, q.size());
479    }
480
481    /**
482     * iterator.remove removes current element
483     */
484    public void testIteratorRemove() {
485        final ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
486        q.add(one);
487        q.add(two);
488        q.add(three);
489        Iterator it = q.iterator();
490        it.next();
491        it.remove();
492        it = q.iterator();
493        assertSame(it.next(), two);
494        assertSame(it.next(), three);
495        assertFalse(it.hasNext());
496    }
497
498    /**
499     * toString contains toStrings of elements
500     */
501    public void testToString() {
502        ConcurrentLinkedQueue q = populatedQueue(SIZE);
503        String s = q.toString();
504        for (int i = 0; i < SIZE; ++i) {
505            assertTrue(s.contains(String.valueOf(i)));
506        }
507    }
508
509    /**
510     * A deserialized serialized queue has same elements in same order
511     */
512    public void testSerialization() throws Exception {
513        Queue x = populatedQueue(SIZE);
514        Queue y = serialClone(x);
515
516        assertNotSame(x, y);
517        assertEquals(x.size(), y.size());
518        assertEquals(x.toString(), y.toString());
519        assertTrue(Arrays.equals(x.toArray(), y.toArray()));
520        while (!x.isEmpty()) {
521            assertFalse(y.isEmpty());
522            assertEquals(x.remove(), y.remove());
523        }
524        assertTrue(y.isEmpty());
525    }
526
527    /**
528     * remove(null), contains(null) always return false
529     */
530    public void testNeverContainsNull() {
531        Collection<?>[] qs = {
532            new ConcurrentLinkedQueue<Object>(),
533            populatedQueue(2),
534        };
535
536        for (Collection<?> q : qs) {
537            assertFalse(q.contains(null));
538            assertFalse(q.remove(null));
539        }
540    }
541}
542