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/licenses/publicdomain
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package tests.api.java.util.concurrent;
10
11import junit.framework.*;
12import java.util.*;
13import java.util.concurrent.*;
14import java.io.*;
15
16public class CopyOnWriteArrayListTest extends JSR166TestCase{
17
18    public static void main(String[] args) {
19        junit.textui.TestRunner.run (suite());
20    }
21
22    public static Test suite() {
23        return new TestSuite(CopyOnWriteArrayListTest.class);
24    }
25
26    static CopyOnWriteArrayList populatedArray(int n){
27        CopyOnWriteArrayList a = new CopyOnWriteArrayList();
28        assertTrue(a.isEmpty());
29        for (int i = 0; i < n; ++i)
30            a.add(new Integer(i));
31        assertFalse(a.isEmpty());
32        assertEquals(n, a.size());
33        return a;
34    }
35
36
37    /**
38     * a new list is empty
39     */
40    public void testConstructor() {
41        CopyOnWriteArrayList a = new CopyOnWriteArrayList();
42        assertTrue(a.isEmpty());
43    }
44
45    /**
46     * new list contains all elements of initializing array
47     */
48    public void testConstructor2() {
49        Integer[] ints = new Integer[SIZE];
50        for (int i = 0; i < SIZE-1; ++i)
51            ints[i] = new Integer(i);
52        CopyOnWriteArrayList a = new CopyOnWriteArrayList(ints);
53        for (int i = 0; i < SIZE; ++i)
54            assertEquals(ints[i], a.get(i));
55    }
56
57    /**
58     * new list contains all elements of initializing collection
59     */
60    public void testConstructor3() {
61        Integer[] ints = new Integer[SIZE];
62        for (int i = 0; i < SIZE-1; ++i)
63            ints[i] = new Integer(i);
64        CopyOnWriteArrayList a = new CopyOnWriteArrayList(Arrays.asList(ints));
65        for (int i = 0; i < SIZE; ++i)
66            assertEquals(ints[i], a.get(i));
67    }
68
69
70    /**
71     *   addAll  adds each element from the given collection
72     */
73    public void testAddAll() {
74        CopyOnWriteArrayList full = populatedArray(3);
75        Vector v = new Vector();
76        v.add(three);
77        v.add(four);
78        v.add(five);
79        full.addAll(v);
80        assertEquals(6, full.size());
81    }
82
83    /**
84     *   addAllAbsent adds each element from the given collection that did not
85     *  already exist in the List
86     */
87    public void testAddAllAbsent() {
88        CopyOnWriteArrayList full = populatedArray(3);
89        Vector v = new Vector();
90        v.add(three);
91        v.add(four);
92        v.add(one); // will not add this element
93        full.addAllAbsent(v);
94        assertEquals(5, full.size());
95    }
96
97    /**
98     *   addIfAbsent will not add the element if it already exists in the list
99     */
100    public void testAddIfAbsent() {
101        CopyOnWriteArrayList full = populatedArray(SIZE);
102        full.addIfAbsent(one);
103        assertEquals(SIZE, full.size());
104    }
105
106    /**
107     *   addIfAbsent adds the element when it does not exist in the list
108     */
109    public void testAddIfAbsent2() {
110        CopyOnWriteArrayList full = populatedArray(SIZE);
111        full.addIfAbsent(three);
112        assertTrue(full.contains(three));
113    }
114
115    /**
116     *   clear removes all elements from the list
117     */
118    public void testClear() {
119        CopyOnWriteArrayList full = populatedArray(SIZE);
120        full.clear();
121        assertEquals(0, full.size());
122    }
123
124
125    /**
126     *  Cloned list is equal
127     */
128    public void testClone() {
129        CopyOnWriteArrayList l1 = populatedArray(SIZE);
130        CopyOnWriteArrayList l2 = (CopyOnWriteArrayList)(l1.clone());
131        assertEquals(l1, l2);
132        l1.clear();
133        assertFalse(l1.equals(l2));
134    }
135
136    /**
137     *   contains is true for added elements
138     */
139    public void testContains() {
140        CopyOnWriteArrayList full = populatedArray(3);
141        assertTrue(full.contains(one));
142        assertFalse(full.contains(five));
143    }
144
145    /**
146     * adding at an index places it in the indicated index
147     */
148    public void testAddIndex() {
149        CopyOnWriteArrayList full = populatedArray(3);
150        full.add(0, m1);
151        assertEquals(4, full.size());
152        assertEquals(m1, full.get(0));
153        assertEquals(zero, full.get(1));
154
155        full.add(2, m2);
156        assertEquals(5, full.size());
157        assertEquals(m2, full.get(2));
158        assertEquals(two, full.get(4));
159    }
160
161    /**
162     * lists with same elements are equal and have same hashCode
163     */
164    public void testEquals() {
165        CopyOnWriteArrayList a = populatedArray(3);
166        CopyOnWriteArrayList b = populatedArray(3);
167        assertTrue(a.equals(b));
168        assertTrue(b.equals(a));
169        assertEquals(a.hashCode(), b.hashCode());
170        a.add(m1);
171        assertFalse(a.equals(b));
172        assertFalse(b.equals(a));
173        b.add(m1);
174        assertTrue(a.equals(b));
175        assertTrue(b.equals(a));
176        assertEquals(a.hashCode(), b.hashCode());
177    }
178
179
180    /**
181     *   containsAll returns true for collection with subset of elements
182     */
183    public void testContainsAll() {
184        CopyOnWriteArrayList full = populatedArray(3);
185        Vector v = new Vector();
186        v.add(one);
187        v.add(two);
188        assertTrue(full.containsAll(v));
189        v.add(six);
190        assertFalse(full.containsAll(v));
191    }
192
193    /**
194     *   get returns the  value at the given index
195     */
196    public void testGet() {
197        CopyOnWriteArrayList full = populatedArray(3);
198        assertEquals(0, ((Integer)full.get(0)).intValue());
199    }
200
201    /**
202     *   indexOf gives the index for the given object
203     */
204    public void testIndexOf() {
205        CopyOnWriteArrayList full = populatedArray(3);
206        assertEquals(1, full.indexOf(one));
207        assertEquals(-1, full.indexOf("puppies"));
208    }
209
210    /**
211     *   indexOf gives the index based on the given index
212     *  at which to start searching
213     */
214    public void testIndexOf2() {
215        CopyOnWriteArrayList full = populatedArray(3);
216        assertEquals(1, full.indexOf(one, 0));
217        assertEquals(-1, full.indexOf(one, 2));
218    }
219
220    /**
221     *   isEmpty returns true when empty, else false
222     */
223    public void testIsEmpty() {
224        CopyOnWriteArrayList empty = new CopyOnWriteArrayList();
225        CopyOnWriteArrayList full = populatedArray(SIZE);
226        assertTrue(empty.isEmpty());
227        assertFalse(full.isEmpty());
228    }
229
230    /**
231     *   iterator() returns an iterator containing the elements of the list
232     */
233    public void testIterator() {
234        CopyOnWriteArrayList full = populatedArray(SIZE);
235        Iterator i = full.iterator();
236        int j;
237        for(j = 0; i.hasNext(); j++)
238            assertEquals(j, ((Integer)i.next()).intValue());
239        assertEquals(SIZE, j);
240    }
241
242    /**
243     * iterator.remove throws UnsupportedOperationException
244     */
245    public void testIteratorRemove () {
246        CopyOnWriteArrayList full = populatedArray(SIZE);
247        Iterator it = full.iterator();
248        it.next();
249        try {
250            it.remove();
251            shouldThrow();
252        }
253        catch (UnsupportedOperationException success) {}
254    }
255
256    /**
257     * toString contains toString of elements
258     */
259    public void testToString() {
260        CopyOnWriteArrayList full = populatedArray(3);
261        String s = full.toString();
262        for (int i = 0; i < 3; ++i) {
263            assertTrue(s.indexOf(String.valueOf(i)) >= 0);
264        }
265    }
266
267    /**
268     *   lastIndexOf returns the index for the given object
269     */
270    public void testLastIndexOf1() {
271        CopyOnWriteArrayList full = populatedArray(3);
272        full.add(one);
273        full.add(three);
274        assertEquals(3, full.lastIndexOf(one));
275        assertEquals(-1, full.lastIndexOf(six));
276    }
277
278    /**
279     *   lastIndexOf returns the index from the given starting point
280     */
281    public void testlastIndexOf2() {
282        CopyOnWriteArrayList full = populatedArray(3);
283        full.add(one);
284        full.add(three);
285        assertEquals(3, full.lastIndexOf(one, 4));
286        assertEquals(-1, full.lastIndexOf(three, 3));
287    }
288
289    /**
290     *  listIterator traverses all elements
291     */
292    public void testListIterator1() {
293        CopyOnWriteArrayList full = populatedArray(SIZE);
294        ListIterator i = full.listIterator();
295        int j;
296        for(j = 0; i.hasNext(); j++)
297            assertEquals(j, ((Integer)i.next()).intValue());
298        assertEquals(SIZE, j);
299    }
300
301    /**
302     *  listIterator only returns those elements after the given index
303     */
304    public void testListIterator2() {
305        CopyOnWriteArrayList full = populatedArray(3);
306        ListIterator i = full.listIterator(1);
307        int j;
308        for(j = 0; i.hasNext(); j++)
309            assertEquals(j+1, ((Integer)i.next()).intValue());
310        assertEquals(2, j);
311    }
312
313    /**
314     *   remove  removes and returns the object at the given index
315     */
316    public void testRemove() {
317        CopyOnWriteArrayList full = populatedArray(3);
318        assertEquals(two, full.remove(2));
319        assertEquals(2, full.size());
320    }
321
322    /**
323     *   removeAll  removes all elements from the given collection
324     */
325    public void testRemoveAll() {
326        CopyOnWriteArrayList full = populatedArray(3);
327        Vector v = new Vector();
328        v.add(one);
329        v.add(two);
330        full.removeAll(v);
331        assertEquals(1, full.size());
332    }
333
334    /**
335     *   set  changes the element at the given index
336     */
337    public void testSet() {
338        CopyOnWriteArrayList full = populatedArray(3);
339        assertEquals(two, full.set(2, four));
340        assertEquals(4, ((Integer)full.get(2)).intValue());
341    }
342
343    /**
344     *   size returns the number of elements
345     */
346    public void testSize() {
347        CopyOnWriteArrayList empty = new CopyOnWriteArrayList();
348        CopyOnWriteArrayList full = populatedArray(SIZE);
349        assertEquals(SIZE, full.size());
350        assertEquals(0, empty.size());
351    }
352
353    /**
354     *   toArray returns an Object array containing all elements from the list
355     */
356    public void testToArray() {
357        CopyOnWriteArrayList full = populatedArray(3);
358        Object[] o = full.toArray();
359        assertEquals(3, o.length);
360        assertEquals(0, ((Integer)o[0]).intValue());
361        assertEquals(1, ((Integer)o[1]).intValue());
362        assertEquals(2, ((Integer)o[2]).intValue());
363    }
364
365    /**
366     *   toArray returns an Integer array containing all elements from
367     *   the list
368     */
369    public void testToArray2() {
370        CopyOnWriteArrayList full = populatedArray(3);
371        Integer[] i = new Integer[3];
372        i = (Integer[])full.toArray(i);
373        assertEquals(3, i.length);
374        assertEquals(0, i[0].intValue());
375        assertEquals(1, i[1].intValue());
376        assertEquals(2, i[2].intValue());
377    }
378
379
380    /**
381     * sublists contains elements at indexes offset from their base
382     */
383    public void testSubList() {
384        CopyOnWriteArrayList a = populatedArray(10);
385        assertTrue(a.subList(1,1).isEmpty());
386        for(int j = 0; j < 9; ++j) {
387            for(int i = j ; i < 10; ++i) {
388                List b = a.subList(j,i);
389                for(int k = j; k < i; ++k) {
390                    assertEquals(new Integer(k), b.get(k-j));
391                }
392            }
393        }
394
395        List s = a.subList(2, 5);
396        assertEquals(s.size(), 3);
397        s.set(2, m1);
398        assertEquals(a.get(4), m1);
399        s.clear();
400        assertEquals(a.size(), 7);
401    }
402
403    // Exception tests
404
405    /**
406     *   toArray throws an ArrayStoreException when the given array
407     *  can not store the objects inside the list
408     */
409    public void testToArray_ArrayStoreException() {
410        try {
411            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
412            c.add("zfasdfsdf");
413            c.add("asdadasd");
414            c.toArray(new Long[5]);
415            shouldThrow();
416        } catch(ArrayStoreException e){}
417    }
418
419    /**
420     *   get throws an IndexOutOfBoundsException on a negative index
421     */
422    public void testGet1_IndexOutOfBoundsException() {
423        try {
424            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
425            c.get(-1);
426            shouldThrow();
427        } catch(IndexOutOfBoundsException e){}
428    }
429
430    /**
431     *   get throws an IndexOutOfBoundsException on a too high index
432     */
433    public void testGet2_IndexOutOfBoundsException() {
434        try {
435            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
436            c.add("asdasd");
437            c.add("asdad");
438            c.get(100);
439            shouldThrow();
440        } catch(IndexOutOfBoundsException e){}
441    }
442
443    /**
444     *   set throws an IndexOutOfBoundsException on a negative index
445     */
446    public void testSet1_IndexOutOfBoundsException() {
447        try {
448            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
449            c.set(-1,"qwerty");
450            shouldThrow();
451        } catch(IndexOutOfBoundsException e){}
452    }
453
454    /**
455     *   set throws an IndexOutOfBoundsException on a too high index
456     */
457    public void testSet2() {
458        try {
459            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
460            c.add("asdasd");
461            c.add("asdad");
462            c.set(100, "qwerty");
463            shouldThrow();
464        } catch(IndexOutOfBoundsException e){}
465    }
466
467    /**
468     *   add throws an IndexOutOfBoundsException on a negative index
469     */
470    public void testAdd1_IndexOutOfBoundsException() {
471        try {
472            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
473            c.add(-1,"qwerty");
474            shouldThrow();
475        } catch(IndexOutOfBoundsException e){}
476    }
477
478    /**
479     *   add throws an IndexOutOfBoundsException on a too high index
480     */
481    public void testAdd2_IndexOutOfBoundsException() {
482        try {
483            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
484            c.add("asdasd");
485            c.add("asdasdasd");
486            c.add(100, "qwerty");
487            shouldThrow();
488        } catch(IndexOutOfBoundsException e){}
489    }
490
491    /**
492     *   remove throws an IndexOutOfBoundsException on a negative index
493     */
494    public void testRemove1_IndexOutOfBounds() {
495        try {
496            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
497            c.remove(-1);
498            shouldThrow();
499        } catch(IndexOutOfBoundsException e){}
500    }
501
502    /**
503     *   remove throws an IndexOutOfBoundsException on a too high index
504     */
505    public void testRemove2_IndexOutOfBounds() {
506        try {
507            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
508            c.add("asdasd");
509            c.add("adasdasd");
510            c.remove(100);
511            shouldThrow();
512        } catch(IndexOutOfBoundsException e){}
513    }
514
515    /**
516     *   addAll throws an IndexOutOfBoundsException on a negative index
517     */
518    public void testAddAll1_IndexOutOfBoundsException() {
519        try {
520            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
521            c.addAll(-1,new LinkedList());
522            shouldThrow();
523        } catch(IndexOutOfBoundsException e){}
524    }
525
526    /**
527     *   addAll throws an IndexOutOfBoundsException on a too high index
528     */
529    public void testAddAll2_IndexOutOfBoundsException() {
530        try {
531            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
532            c.add("asdasd");
533            c.add("asdasdasd");
534            c.addAll(100, new LinkedList());
535            shouldThrow();
536        } catch(IndexOutOfBoundsException e){}
537    }
538
539    /**
540     *   listIterator throws an IndexOutOfBoundsException on a negative index
541     */
542    public void testListIterator1_IndexOutOfBoundsException() {
543        try {
544            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
545            c.listIterator(-1);
546            shouldThrow();
547        } catch(IndexOutOfBoundsException e){}
548    }
549
550    /**
551     *   listIterator throws an IndexOutOfBoundsException on a too high index
552     */
553    public void testListIterator2_IndexOutOfBoundsException() {
554        try {
555            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
556            c.add("adasd");
557            c.add("asdasdas");
558            c.listIterator(100);
559            shouldThrow();
560        } catch(IndexOutOfBoundsException e){}
561    }
562
563    /**
564     *   subList throws an IndexOutOfBoundsException on a negative index
565     */
566    public void testSubList1_IndexOutOfBoundsException() {
567        try {
568            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
569            c.subList(-1,100);
570
571            shouldThrow();
572        } catch(IndexOutOfBoundsException e){}
573    }
574
575    /**
576     *   subList throws an IndexOutOfBoundsException on a too high index
577     */
578    public void testSubList2_IndexOutOfBoundsException() {
579        try {
580            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
581            c.add("asdasd");
582            c.subList(1,100);
583            shouldThrow();
584        } catch(IndexOutOfBoundsException e){}
585    }
586
587    /**
588     *   subList throws IndexOutOfBoundsException when the second index
589     *  is lower then the first
590     */
591    public void testSubList3_IndexOutOfBoundsException() {
592        try {
593            CopyOnWriteArrayList c = new CopyOnWriteArrayList();
594            c.subList(3,1);
595
596            shouldThrow();
597        } catch(IndexOutOfBoundsException e){}
598    }
599
600    /**
601     * a deserialized serialiszed list is equal
602     */
603    public void testSerialization() {
604        CopyOnWriteArrayList q = populatedArray(SIZE);
605
606        try {
607            ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
608            ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
609            out.writeObject(q);
610            out.close();
611
612            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
613            ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
614            CopyOnWriteArrayList r = (CopyOnWriteArrayList)in.readObject();
615            assertEquals(q.size(), r.size());
616            assertTrue(q.equals(r));
617            assertTrue(r.equals(q));
618        } catch(Exception e){
619            unexpectedException();
620        }
621    }
622
623}
624