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