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 
9 package jsr166;
10 
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.Iterator;
14 import java.util.NoSuchElementException;
15 import java.util.Queue;
16 import java.util.concurrent.ConcurrentLinkedQueue;
17 
18 import junit.framework.Test;
19 import junit.framework.TestSuite;
20 
21 public 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      */
populatedQueue(int n)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      */
testConstructor1()50     public void testConstructor1() {
51         assertEquals(0, new ConcurrentLinkedQueue().size());
52     }
53 
54     /**
55      * Initializing from null Collection throws NPE
56      */
testConstructor3()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      */
testConstructor4()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      */
testConstructor5()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      */
testConstructor6()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      */
testEmpty()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      */
testSize()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      */
testOfferNull()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      */
testAddNull()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      */
testOffer()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      */
testAdd()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      */
testAddAll1()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      */
testAddAllSelf()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      */
testAddAll2()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      */
testAddAll3()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      */
testAddAll5()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      */
testPoll()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      */
testPeek()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      */
testElement()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      */
testRemove()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      */
testRemoveElement()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      */
testContains()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      */
testClear()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      */
testContainsAll()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      */
testRetainAll()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      */
testRemoveAll()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      */
testToArray()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      */
testToArray2()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      */
testToArray_NullArg()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      */
testToArray1_BadArg()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      */
testIterator()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      */
testEmptyIterator()443     public void testEmptyIterator() {
444         assertIteratorExhausted(new ConcurrentLinkedQueue().iterator());
445     }
446 
447     /**
448      * iterator ordering is FIFO
449      */
testIteratorOrdering()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      */
testWeaklyConsistentIteration()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      */
testIteratorRemove()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      */
testToString()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      */
testSerialization()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      */
testNeverContainsNull()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