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.ArrayList;
12import java.util.Arrays;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.Iterator;
16import java.util.NoSuchElementException;
17import java.util.Set;
18import java.util.concurrent.CopyOnWriteArraySet;
19
20import junit.framework.Test;
21import junit.framework.TestSuite;
22
23public 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
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
246    public void testEmptyIterator() {
247        assertIteratorExhausted(new CopyOnWriteArraySet().iterator());
248    }
249
250    /**
251     * iterator remove is unsupported
252     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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