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