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