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 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<Integer> populatedSet(int n) {
64         CopyOnWriteArraySet<Integer> a = new CopyOnWriteArraySet<>();
65         assertTrue(a.isEmpty());
66         for (int i = 0; i < n; i++)
67             a.add(i);
68         assertEquals(n == 0, a.isEmpty());
69         assertEquals(n, a.size());
70         return a;
71     }
72 
populatedSet(Integer[] elements)73     static CopyOnWriteArraySet populatedSet(Integer[] elements) {
74         CopyOnWriteArraySet<Integer> a = new CopyOnWriteArraySet<>();
75         assertTrue(a.isEmpty());
76         for (int i = 0; i < elements.length; i++)
77             a.add(elements[i]);
78         assertFalse(a.isEmpty());
79         assertEquals(elements.length, a.size());
80         return a;
81     }
82 
83     /**
84      * Default-constructed set is empty
85      */
testConstructor()86     public void testConstructor() {
87         CopyOnWriteArraySet 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         Integer[] ints = new Integer[SIZE];
96         for (int i = 0; i < SIZE - 1; ++i)
97             ints[i] = new Integer(i);
98         CopyOnWriteArraySet a = new CopyOnWriteArraySet(Arrays.asList(ints));
99         for (int i = 0; i < SIZE; ++i)
100             assertTrue(a.contains(ints[i]));
101     }
102 
103     /**
104      * addAll adds each non-duplicate element from the given collection
105      */
testAddAll()106     public void testAddAll() {
107         Set full = populatedSet(3);
108         assertTrue(full.addAll(Arrays.asList(three, four, five)));
109         assertEquals(6, full.size());
110         assertFalse(full.addAll(Arrays.asList(three, four, five)));
111         assertEquals(6, full.size());
112     }
113 
114     /**
115      * addAll adds each non-duplicate element from the given collection
116      */
testAddAll2()117     public void testAddAll2() {
118         Set full = populatedSet(3);
119         // "one" is duplicate and will not be added
120         assertTrue(full.addAll(Arrays.asList(three, four, one)));
121         assertEquals(5, full.size());
122         assertFalse(full.addAll(Arrays.asList(three, four, one)));
123         assertEquals(5, full.size());
124     }
125 
126     /**
127      * add will not add the element if it already exists in the set
128      */
testAdd2()129     public void testAdd2() {
130         Set full = populatedSet(3);
131         full.add(one);
132         assertEquals(3, full.size());
133     }
134 
135     /**
136      * add adds the element when it does not exist in the set
137      */
testAdd3()138     public void testAdd3() {
139         Set full = populatedSet(3);
140         full.add(three);
141         assertTrue(full.contains(three));
142     }
143 
144     /**
145      * clear removes all elements from the set
146      */
testClear()147     public void testClear() {
148         Collection full = populatedSet(3);
149         full.clear();
150         assertEquals(0, full.size());
151         assertTrue(full.isEmpty());
152     }
153 
154     /**
155      * contains returns true for added elements
156      */
testContains()157     public void testContains() {
158         Collection full = populatedSet(3);
159         assertTrue(full.contains(one));
160         assertFalse(full.contains(five));
161     }
162 
163     /**
164      * Sets with equal elements are equal
165      */
testEquals()166     public void testEquals() {
167         CopyOnWriteArraySet a = populatedSet(3);
168         CopyOnWriteArraySet b = populatedSet(3);
169         assertTrue(a.equals(b));
170         assertTrue(b.equals(a));
171         assertTrue(a.containsAll(b));
172         assertTrue(b.containsAll(a));
173         assertEquals(a.hashCode(), b.hashCode());
174         assertEquals(a.size(), b.size());
175 
176         a.add(m1);
177         assertFalse(a.equals(b));
178         assertFalse(b.equals(a));
179         assertTrue(a.containsAll(b));
180         assertFalse(b.containsAll(a));
181         b.add(m1);
182         assertTrue(a.equals(b));
183         assertTrue(b.equals(a));
184         assertTrue(a.containsAll(b));
185         assertTrue(b.containsAll(a));
186         assertEquals(a.hashCode(), b.hashCode());
187 
188         Object x = a.iterator().next();
189         a.remove(x);
190         assertFalse(a.equals(b));
191         assertFalse(b.equals(a));
192         assertFalse(a.containsAll(b));
193         assertTrue(b.containsAll(a));
194         a.add(x);
195         assertTrue(a.equals(b));
196         assertTrue(b.equals(a));
197         assertTrue(a.containsAll(b));
198         assertTrue(b.containsAll(a));
199         assertEquals(a.hashCode(), b.hashCode());
200         assertEquals(a.size(), b.size());
201 
202         CopyOnWriteArraySet empty1 = new CopyOnWriteArraySet(Arrays.asList());
203         CopyOnWriteArraySet empty2 = new CopyOnWriteArraySet(Arrays.asList());
204         assertTrue(empty1.equals(empty1));
205         assertTrue(empty1.equals(empty2));
206 
207         assertFalse(empty1.equals(a));
208         assertFalse(a.equals(empty1));
209 
210         assertFalse(a.equals(null));
211     }
212 
213     /**
214      * containsAll returns true for collections with subset of elements
215      */
testContainsAll()216     public void testContainsAll() {
217         Collection full = populatedSet(3);
218         assertTrue(full.containsAll(full));
219         assertTrue(full.containsAll(Arrays.asList()));
220         assertTrue(full.containsAll(Arrays.asList(one)));
221         assertTrue(full.containsAll(Arrays.asList(one, two)));
222         assertFalse(full.containsAll(Arrays.asList(one, two, six)));
223         assertFalse(full.containsAll(Arrays.asList(six)));
224 
225         CopyOnWriteArraySet empty1 = new CopyOnWriteArraySet(Arrays.asList());
226         CopyOnWriteArraySet empty2 = new CopyOnWriteArraySet(Arrays.asList());
227         assertTrue(empty1.containsAll(empty2));
228         assertTrue(empty1.containsAll(empty1));
229         assertFalse(empty1.containsAll(full));
230         assertTrue(full.containsAll(empty1));
231 
232         try {
233             full.containsAll(null);
234             shouldThrow();
235         } catch (NullPointerException success) {}
236     }
237 
238     /**
239      * isEmpty is true when empty, else false
240      */
testIsEmpty()241     public void testIsEmpty() {
242         assertTrue(populatedSet(0).isEmpty());
243         assertFalse(populatedSet(3).isEmpty());
244     }
245 
246     /**
247      * iterator() returns an iterator containing the elements of the
248      * set in insertion order
249      */
testIterator()250     public void testIterator() {
251         Collection empty = new CopyOnWriteArraySet();
252         assertFalse(empty.iterator().hasNext());
253         try {
254             empty.iterator().next();
255             shouldThrow();
256         } catch (NoSuchElementException success) {}
257 
258         Integer[] elements = new Integer[SIZE];
259         for (int i = 0; i < SIZE; i++)
260             elements[i] = i;
261         shuffle(elements);
262         Collection<Integer> full = populatedSet(elements);
263 
264         Iterator it = full.iterator();
265         for (int j = 0; j < SIZE; j++) {
266             assertTrue(it.hasNext());
267             assertEquals(elements[j], it.next());
268         }
269         assertIteratorExhausted(it);
270     }
271 
272     /**
273      * iterator of empty collection has no elements
274      */
testEmptyIterator()275     public void testEmptyIterator() {
276         assertIteratorExhausted(new CopyOnWriteArraySet().iterator());
277     }
278 
279     /**
280      * iterator remove is unsupported
281      */
testIteratorRemove()282     public void testIteratorRemove() {
283         Collection full = populatedSet(3);
284         Iterator it = full.iterator();
285         it.next();
286         try {
287             it.remove();
288             shouldThrow();
289         } catch (UnsupportedOperationException success) {}
290     }
291 
292     /**
293      * toString holds toString of elements
294      */
testToString()295     public void testToString() {
296         assertEquals("[]", new CopyOnWriteArraySet().toString());
297         Collection full = populatedSet(3);
298         String s = full.toString();
299         for (int i = 0; i < 3; ++i)
300             assertTrue(s.contains(String.valueOf(i)));
301         assertEquals(new ArrayList(full).toString(),
302                      full.toString());
303     }
304 
305     /**
306      * removeAll removes all elements from the given collection
307      */
testRemoveAll()308     public void testRemoveAll() {
309         Set full = populatedSet(3);
310         assertTrue(full.removeAll(Arrays.asList(one, two)));
311         assertEquals(1, full.size());
312         assertFalse(full.removeAll(Arrays.asList(one, two)));
313         assertEquals(1, full.size());
314     }
315 
316     /**
317      * remove removes an element
318      */
testRemove()319     public void testRemove() {
320         Collection full = populatedSet(3);
321         full.remove(one);
322         assertFalse(full.contains(one));
323         assertEquals(2, full.size());
324     }
325 
326     /**
327      * size returns the number of elements
328      */
testSize()329     public void testSize() {
330         Collection empty = new CopyOnWriteArraySet();
331         Collection full = populatedSet(3);
332         assertEquals(3, full.size());
333         assertEquals(0, empty.size());
334     }
335 
336     /**
337      * toArray() returns an Object array containing all elements from
338      * the set in insertion order
339      */
testToArray()340     public void testToArray() {
341         Object[] a = new CopyOnWriteArraySet().toArray();
342         assertTrue(Arrays.equals(new Object[0], a));
343         assertSame(Object[].class, a.getClass());
344 
345         Integer[] elements = new Integer[SIZE];
346         for (int i = 0; i < SIZE; i++)
347             elements[i] = i;
348         shuffle(elements);
349         Collection<Integer> full = populatedSet(elements);
350 
351         assertTrue(Arrays.equals(elements, full.toArray()));
352         assertSame(Object[].class, full.toArray().getClass());
353     }
354 
355     /**
356      * toArray(Integer array) returns an Integer array containing all
357      * elements from the set in insertion order
358      */
testToArray2()359     public void testToArray2() {
360         Collection empty = new CopyOnWriteArraySet();
361         Integer[] a;
362 
363         a = new Integer[0];
364         assertSame(a, empty.toArray(a));
365 
366         a = new Integer[SIZE / 2];
367         Arrays.fill(a, 42);
368         assertSame(a, empty.toArray(a));
369         assertNull(a[0]);
370         for (int i = 1; i < a.length; i++)
371             assertEquals(42, (int) a[i]);
372 
373         Integer[] elements = new Integer[SIZE];
374         for (int i = 0; i < SIZE; i++)
375             elements[i] = i;
376         shuffle(elements);
377         Collection<Integer> full = populatedSet(elements);
378 
379         Arrays.fill(a, 42);
380         assertTrue(Arrays.equals(elements, full.toArray(a)));
381         for (int i = 0; i < a.length; i++)
382             assertEquals(42, (int) a[i]);
383         assertSame(Integer[].class, full.toArray(a).getClass());
384 
385         a = new Integer[SIZE];
386         Arrays.fill(a, 42);
387         assertSame(a, full.toArray(a));
388         assertTrue(Arrays.equals(elements, a));
389 
390         a = new Integer[2 * SIZE];
391         Arrays.fill(a, 42);
392         assertSame(a, full.toArray(a));
393         assertTrue(Arrays.equals(elements, Arrays.copyOf(a, SIZE)));
394         assertNull(a[SIZE]);
395         for (int i = SIZE + 1; i < a.length; i++)
396             assertEquals(42, (int) a[i]);
397     }
398 
399     /**
400      * toArray throws an ArrayStoreException when the given array can
401      * not store the objects inside the set
402      */
testToArray_ArrayStoreException()403     public void testToArray_ArrayStoreException() {
404         CopyOnWriteArraySet c = new CopyOnWriteArraySet();
405         c.add("zfasdfsdf");
406         c.add("asdadasd");
407         try {
408             c.toArray(new Long[5]);
409             shouldThrow();
410         } catch (ArrayStoreException success) {}
411     }
412 
413     /**
414      * A deserialized/reserialized set equals original
415      */
testSerialization()416     public void testSerialization() throws Exception {
417         Set x = populatedSet(SIZE);
418         Set y = serialClone(x);
419 
420         assertNotSame(y, x);
421         assertEquals(x.size(), y.size());
422         assertEquals(x.toString(), y.toString());
423         assertTrue(Arrays.equals(x.toArray(), y.toArray()));
424         assertEquals(x, y);
425         assertEquals(y, x);
426     }
427 
428     /**
429      * addAll is idempotent
430      */
testAddAll_idempotent()431     public void testAddAll_idempotent() throws Exception {
432         Set x = populatedSet(SIZE);
433         Set y = new CopyOnWriteArraySet(x);
434         y.addAll(x);
435         assertEquals(x, y);
436         assertEquals(y, x);
437     }
438 
439 }
440