1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.
7  *
8  * This code is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * version 2 for more details (a copy is included in the LICENSE file that
12  * accompanied this code).
13  *
14  * You should have received a copy of the GNU General Public License version
15  * 2 along with this work; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19  * or visit www.oracle.com if you need additional information or have any
20  * questions.
21  */
22 
23 /*
24  * This file is available under and governed by the GNU General Public
25  * License version 2 only, as published by the Free Software Foundation.
26  * However, the following notice accompanied the original version of this
27  * file:
28  *
29  * Written by Doug Lea with assistance from members of JCP JSR-166
30  * Expert Group and released to the public domain, as explained at
31  * http://creativecommons.org/publicdomain/zero/1.0/
32  * Other contributors include Andrew Wright, Jeffrey Hayes,
33  * Pat Fisher, Mike Judd.
34  */
35 
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collection;
39 import java.util.Iterator;
40 import java.util.NoSuchElementException;
41 import java.util.Set;
42 import java.util.concurrent.CopyOnWriteArraySet;
43 
44 import junit.framework.Test;
45 
46 public class CopyOnWriteArraySetTest extends JSR166TestCase {
main(String[] args)47     public static void main(String[] args) {
48         main(suite(), args);
49     }
suite()50     public static Test suite() {
51         class Implementation implements CollectionImplementation {
52             public Class<?> klazz() { return CopyOnWriteArraySet.class; }
53             public Set emptyCollection() { return new CopyOnWriteArraySet(); }
54             public Object makeElement(int i) { return JSR166TestCase.itemFor(i); }
55             public boolean isConcurrent() { return true; }
56             public boolean permitsNulls() { return true; }
57         }
58         return newTestSuite(
59                 CopyOnWriteArraySetTest.class,
60                 CollectionTest.testSuite(new Implementation()));
61     }
62 
populatedSet(int n)63     static CopyOnWriteArraySet<Item> populatedSet(int n) {
64         CopyOnWriteArraySet<Item> a = new CopyOnWriteArraySet<>();
65         assertTrue(a.isEmpty());
66         for (int i = 0; i < n; i++)
67             mustAdd(a, i);
68         mustEqual(n == 0, a.isEmpty());
69         mustEqual(n, a.size());
70         return a;
71     }
72 
populatedSet(Item[] elements)73     static CopyOnWriteArraySet<Item> populatedSet(Item[] elements) {
74         CopyOnWriteArraySet<Item> a = new CopyOnWriteArraySet<>();
75         assertTrue(a.isEmpty());
76         for (int i = 0; i < elements.length; i++)
77             mustAdd(a, elements[i]);
78         assertFalse(a.isEmpty());
79         mustEqual(elements.length, a.size());
80         return a;
81     }
82 
83     /**
84      * Default-constructed set is empty
85      */
testConstructor()86     public void testConstructor() {
87         CopyOnWriteArraySet<Item> a = new CopyOnWriteArraySet<>();
88         assertTrue(a.isEmpty());
89     }
90 
91     /**
92      * Collection-constructed set holds all of its elements
93      */
testConstructor3()94     public void testConstructor3() {
95         Item[] items = defaultItems;
96         CopyOnWriteArraySet<Item> a = new CopyOnWriteArraySet<>(Arrays.asList(items));
97         for (int i = 0; i < SIZE; ++i)
98             mustContain(a, i);
99     }
100 
101     /**
102      * addAll adds each non-duplicate element from the given collection
103      */
testAddAll()104     public void testAddAll() {
105         Set<Item> full = populatedSet(3);
106         assertTrue(full.addAll(Arrays.asList(three, four, five)));
107         mustEqual(6, full.size());
108         assertFalse(full.addAll(Arrays.asList(three, four, five)));
109         mustEqual(6, full.size());
110     }
111 
112     /**
113      * addAll adds each non-duplicate element from the given collection
114      */
testAddAll2()115     public void testAddAll2() {
116         Set<Item> full = populatedSet(3);
117         // "one" is duplicate and will not be added
118         assertTrue(full.addAll(Arrays.asList(three, four, one)));
119         mustEqual(5, full.size());
120         assertFalse(full.addAll(Arrays.asList(three, four, one)));
121         mustEqual(5, full.size());
122     }
123 
124     /**
125      * add will not add the element if it already exists in the set
126      */
testAdd2()127     public void testAdd2() {
128         Set<Item> full = populatedSet(3);
129         full.add(one);
130         mustEqual(3, full.size());
131     }
132 
133     /**
134      * add adds the element when it does not exist in the set
135      */
testAdd3()136     public void testAdd3() {
137         Set<Item> full = populatedSet(3);
138         full.add(three);
139         mustContain(full, three);
140     }
141 
142     /**
143      * clear removes all elements from the set
144      */
testClear()145     public void testClear() {
146         Collection<Item> full = populatedSet(3);
147         full.clear();
148         mustEqual(0, full.size());
149         assertTrue(full.isEmpty());
150     }
151 
152     /**
153      * contains returns true for added elements
154      */
testContains()155     public void testContains() {
156         Collection<Item> full = populatedSet(3);
157         mustContain(full, one);
158         mustNotContain(full, five);
159     }
160 
161     /**
162      * Sets with equal elements are equal
163      */
testEquals()164     public void testEquals() {
165         CopyOnWriteArraySet<Item> a = populatedSet(3);
166         CopyOnWriteArraySet<Item> b = populatedSet(3);
167         assertTrue(a.equals(b));
168         assertTrue(b.equals(a));
169         assertTrue(a.containsAll(b));
170         assertTrue(b.containsAll(a));
171         mustEqual(a.hashCode(), b.hashCode());
172         mustEqual(a.size(), b.size());
173 
174         a.add(minusOne);
175         assertFalse(a.equals(b));
176         assertFalse(b.equals(a));
177         assertTrue(a.containsAll(b));
178         assertFalse(b.containsAll(a));
179         b.add(minusOne);
180         assertTrue(a.equals(b));
181         assertTrue(b.equals(a));
182         assertTrue(a.containsAll(b));
183         assertTrue(b.containsAll(a));
184         mustEqual(a.hashCode(), b.hashCode());
185 
186         Item x = a.iterator().next();
187         a.remove(x);
188         assertFalse(a.equals(b));
189         assertFalse(b.equals(a));
190         assertFalse(a.containsAll(b));
191         assertTrue(b.containsAll(a));
192         a.add(x);
193         assertTrue(a.equals(b));
194         assertTrue(b.equals(a));
195         assertTrue(a.containsAll(b));
196         assertTrue(b.containsAll(a));
197         mustEqual(a.hashCode(), b.hashCode());
198         mustEqual(a.size(), b.size());
199 
200         CopyOnWriteArraySet<Item> empty1 = new CopyOnWriteArraySet<>(Arrays.asList());
201         CopyOnWriteArraySet<Item> empty2 = new CopyOnWriteArraySet<>(Arrays.asList());
202         assertTrue(empty1.equals(empty1));
203         assertTrue(empty1.equals(empty2));
204 
205         assertFalse(empty1.equals(a));
206         assertFalse(a.equals(empty1));
207 
208         assertFalse(a.equals(null));
209     }
210 
211     /**
212      * containsAll returns true for collections with subset of elements
213      */
testContainsAll()214     public void testContainsAll() {
215         Collection<Item> full = populatedSet(3);
216         assertTrue(full.containsAll(full));
217         assertTrue(full.containsAll(Arrays.asList()));
218         assertTrue(full.containsAll(Arrays.asList(one)));
219         assertTrue(full.containsAll(Arrays.asList(one, two)));
220         assertFalse(full.containsAll(Arrays.asList(one, two, six)));
221         assertFalse(full.containsAll(Arrays.asList(six)));
222 
223         CopyOnWriteArraySet<Item> empty1 = new CopyOnWriteArraySet<>(Arrays.asList());
224         CopyOnWriteArraySet<Item> empty2 = new CopyOnWriteArraySet<>(Arrays.asList());
225         assertTrue(empty1.containsAll(empty2));
226         assertTrue(empty1.containsAll(empty1));
227         assertFalse(empty1.containsAll(full));
228         assertTrue(full.containsAll(empty1));
229 
230         try {
231             full.containsAll(null);
232             shouldThrow();
233         } catch (NullPointerException success) {}
234     }
235 
236     /**
237      * isEmpty is true when empty, else false
238      */
testIsEmpty()239     public void testIsEmpty() {
240         assertTrue(populatedSet(0).isEmpty());
241         assertFalse(populatedSet(3).isEmpty());
242     }
243 
244     /**
245      * iterator() returns an iterator containing the elements of the
246      * set in insertion order
247      */
testIterator()248     public void testIterator() {
249         Collection<Item> empty = new CopyOnWriteArraySet<>();
250         assertFalse(empty.iterator().hasNext());
251         try {
252             empty.iterator().next();
253             shouldThrow();
254         } catch (NoSuchElementException success) {}
255 
256         Item[] elements = seqItems(SIZE);
257         shuffle(elements);
258         Collection<Item> full = populatedSet(elements);
259 
260         Iterator<? extends Item> it = full.iterator();
261         for (int j = 0; j < SIZE; j++) {
262             assertTrue(it.hasNext());
263             mustEqual(elements[j], it.next());
264         }
265         assertIteratorExhausted(it);
266     }
267 
268     /**
269      * iterator of empty collection has no elements
270      */
testEmptyIterator()271     public void testEmptyIterator() {
272         assertIteratorExhausted(new CopyOnWriteArraySet<Item>().iterator());
273     }
274 
275     /**
276      * iterator remove is unsupported
277      */
testIteratorRemove()278     public void testIteratorRemove() {
279         Collection<Item> full = populatedSet(3);
280         Iterator<? extends Item> it = full.iterator();
281         it.next();
282         try {
283             it.remove();
284             shouldThrow();
285         } catch (UnsupportedOperationException success) {}
286     }
287 
288     /**
289      * toString holds toString of elements
290      */
testToString()291     public void testToString() {
292         mustEqual("[]", new CopyOnWriteArraySet<Item>().toString());
293         Collection<Item> full = populatedSet(3);
294         String s = full.toString();
295         for (int i = 0; i < 3; ++i)
296             assertTrue(s.contains(String.valueOf(i)));
297         mustEqual(new ArrayList<Item>(full).toString(),
298                      full.toString());
299     }
300 
301     /**
302      * removeAll removes all elements from the given collection
303      */
testRemoveAll()304     public void testRemoveAll() {
305         Set<Item> full = populatedSet(3);
306         assertTrue(full.removeAll(Arrays.asList(one, two)));
307         mustEqual(1, full.size());
308         assertFalse(full.removeAll(Arrays.asList(one, two)));
309         mustEqual(1, full.size());
310     }
311 
312     /**
313      * remove removes an element
314      */
testRemove()315     public void testRemove() {
316         Collection<Item> full = populatedSet(3);
317         full.remove(one);
318         mustNotContain(full, one);
319         mustEqual(2, full.size());
320     }
321 
322     /**
323      * size returns the number of elements
324      */
testSize()325     public void testSize() {
326         Collection<Item> empty = new CopyOnWriteArraySet<>();
327         Collection<Item> full = populatedSet(3);
328         mustEqual(3, full.size());
329         mustEqual(0, empty.size());
330     }
331 
332     /**
333      * toArray() returns an Object array containing all elements from
334      * the set in insertion order
335      */
testToArray()336     public void testToArray() {
337         Object[] a = new CopyOnWriteArraySet<>().toArray();
338         assertTrue(Arrays.equals(new Object[0], a));
339         assertSame(Object[].class, a.getClass());
340 
341         Item[] elements = seqItems(SIZE);
342         shuffle(elements);
343         Collection<Item> full = populatedSet(elements);
344 
345         assertTrue(Arrays.equals(elements, full.toArray()));
346         assertSame(Object[].class, full.toArray().getClass());
347     }
348 
349     /**
350      * toArray(Item array) returns an Item array containing all
351      * elements from the set in insertion order
352      */
testToArray2()353     public void testToArray2() {
354         Collection<Item> empty = new CopyOnWriteArraySet<>();
355         Item[] a;
356 
357         a = new Item[0];
358         assertSame(a, empty.toArray(a));
359 
360         a = new Item[SIZE / 2];
361         Arrays.fill(a, fortytwo);
362         assertSame(a, empty.toArray(a));
363         assertNull(a[0]);
364         for (int i = 1; i < a.length; i++)
365             mustEqual(42, a[i]);
366 
367         Item[] elements = seqItems(SIZE);
368         shuffle(elements);
369         Collection<Item> full = populatedSet(elements);
370 
371         Arrays.fill(a, fortytwo);
372         assertTrue(Arrays.equals(elements, full.toArray(a)));
373         for (int i = 0; i < a.length; i++)
374             mustEqual(42, a[i]);
375         assertSame(Item[].class, full.toArray(a).getClass());
376 
377         a = new Item[SIZE];
378         Arrays.fill(a, fortytwo);
379         assertSame(a, full.toArray(a));
380         assertTrue(Arrays.equals(elements, a));
381 
382         a = new Item[2 * SIZE];
383         Arrays.fill(a, fortytwo);
384         assertSame(a, full.toArray(a));
385         assertTrue(Arrays.equals(elements, Arrays.copyOf(a, SIZE)));
386         assertNull(a[SIZE]);
387         for (int i = SIZE + 1; i < a.length; i++)
388             mustEqual(42, a[i]);
389     }
390 
391     /**
392      * toArray throws an ArrayStoreException when the given array can
393      * not store the objects inside the set
394      */
395     @SuppressWarnings("CollectionToArraySafeParameter")
testToArray_ArrayStoreException()396     public void testToArray_ArrayStoreException() {
397         CopyOnWriteArraySet<Item> c = new CopyOnWriteArraySet<>();
398         c.add(one);
399         c.add(two);
400         try {
401             c.toArray(new Long[5]);
402             shouldThrow();
403         } catch (ArrayStoreException success) {}
404     }
405 
406     /**
407      * A deserialized/reserialized set equals original
408      */
testSerialization()409     public void testSerialization() throws Exception {
410         Set<Item> x = populatedSet(SIZE);
411         Set<Item> y = serialClone(x);
412 
413         assertNotSame(y, x);
414         mustEqual(x.size(), y.size());
415         mustEqual(x.toString(), y.toString());
416         assertTrue(Arrays.equals(x.toArray(), y.toArray()));
417         mustEqual(x, y);
418         mustEqual(y, x);
419     }
420 
421     /**
422      * addAll is idempotent
423      */
testAddAll_idempotent()424     public void testAddAll_idempotent() throws Exception {
425         Set<Item> x = populatedSet(SIZE);
426         Set<Item> y = new CopyOnWriteArraySet<>(x);
427         y.addAll(x);
428         mustEqual(x, y);
429         mustEqual(y, x);
430     }
431 
432 }
433