ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/CopyOnWriteArrayListTest.java
Revision: 1.49
Committed: Tue Apr 3 05:49:43 2018 UTC (6 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.48: +6 -1 lines
Log Message:
add more randomness to sublist testing

File Contents

# Content
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 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.ListIterator;
16 import java.util.NoSuchElementException;
17 import java.util.concurrent.CopyOnWriteArrayList;
18 import java.util.concurrent.ThreadLocalRandom;
19
20 import junit.framework.Test;
21
22 public class CopyOnWriteArrayListTest extends JSR166TestCase {
23
24 public static void main(String[] args) {
25 main(suite(), args);
26 }
27
28 public static Test suite() {
29 class Implementation implements CollectionImplementation {
30 public Class<?> klazz() { return CopyOnWriteArrayList.class; }
31 public List emptyCollection() { return new CopyOnWriteArrayList(); }
32 public Object makeElement(int i) { return i; }
33 public boolean isConcurrent() { return true; }
34 public boolean permitsNulls() { return true; }
35 }
36 class SubListImplementation extends Implementation {
37 public List emptyCollection() {
38 List list = super.emptyCollection();
39 ThreadLocalRandom rnd = ThreadLocalRandom.current();
40 if (rnd.nextBoolean())
41 list.add(makeElement(rnd.nextInt()));
42 int i = rnd.nextInt(list.size() + 1);
43 return list.subList(i, i);
44 }
45 }
46 return newTestSuite(
47 CopyOnWriteArrayListTest.class,
48 CollectionTest.testSuite(new Implementation()),
49 CollectionTest.testSuite(new SubListImplementation()));
50 }
51
52 static CopyOnWriteArrayList<Integer> populatedList(int n) {
53 CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
54 assertTrue(list.isEmpty());
55 for (int i = 0; i < n; i++)
56 list.add(i);
57 assertEquals(n <= 0, list.isEmpty());
58 assertEquals(n, list.size());
59 return list;
60 }
61
62 static CopyOnWriteArrayList<Integer> populatedList(Integer[] elements) {
63 CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
64 assertTrue(list.isEmpty());
65 for (Integer element : elements)
66 list.add(element);
67 assertFalse(list.isEmpty());
68 assertEquals(elements.length, list.size());
69 return list;
70 }
71
72 /**
73 * a new list is empty
74 */
75 public void testConstructor() {
76 List list = new CopyOnWriteArrayList();
77 assertTrue(list.isEmpty());
78 }
79
80 /**
81 * new list contains all elements of initializing array
82 */
83 public void testConstructor2() {
84 Integer[] elts = new Integer[SIZE];
85 for (int i = 0; i < SIZE - 1; ++i)
86 elts[i] = i;
87 List list = new CopyOnWriteArrayList(elts);
88 for (int i = 0; i < SIZE; ++i)
89 assertEquals(elts[i], list.get(i));
90 }
91
92 /**
93 * new list contains all elements of initializing collection
94 */
95 public void testConstructor3() {
96 Integer[] elts = new Integer[SIZE];
97 for (int i = 0; i < SIZE - 1; ++i)
98 elts[i] = i;
99 List list = new CopyOnWriteArrayList(Arrays.asList(elts));
100 for (int i = 0; i < SIZE; ++i)
101 assertEquals(elts[i], list.get(i));
102 }
103
104 /**
105 * addAll adds each element from the given collection, including duplicates
106 */
107 public void testAddAll() {
108 List list = populatedList(3);
109 assertTrue(list.addAll(Arrays.asList(three, four, five)));
110 assertEquals(6, list.size());
111 assertTrue(list.addAll(Arrays.asList(three, four, five)));
112 assertEquals(9, list.size());
113 }
114
115 /**
116 * addAllAbsent adds each element from the given collection that did not
117 * already exist in the List
118 */
119 public void testAddAllAbsent() {
120 CopyOnWriteArrayList list = populatedList(3);
121 // "one" is duplicate and will not be added
122 assertEquals(2, list.addAllAbsent(Arrays.asList(three, four, one)));
123 assertEquals(5, list.size());
124 assertEquals(0, list.addAllAbsent(Arrays.asList(three, four, one)));
125 assertEquals(5, list.size());
126 }
127
128 /**
129 * addIfAbsent will not add the element if it already exists in the list
130 */
131 public void testAddIfAbsent() {
132 CopyOnWriteArrayList list = populatedList(SIZE);
133 list.addIfAbsent(one);
134 assertEquals(SIZE, list.size());
135 }
136
137 /**
138 * addIfAbsent adds the element when it does not exist in the list
139 */
140 public void testAddIfAbsent2() {
141 CopyOnWriteArrayList list = populatedList(SIZE);
142 list.addIfAbsent(three);
143 assertTrue(list.contains(three));
144 }
145
146 /**
147 * clear removes all elements from the list
148 */
149 public void testClear() {
150 List list = populatedList(SIZE);
151 list.clear();
152 assertEquals(0, list.size());
153 }
154
155 /**
156 * Cloned list is equal
157 */
158 public void testClone() {
159 CopyOnWriteArrayList l1 = populatedList(SIZE);
160 CopyOnWriteArrayList l2 = (CopyOnWriteArrayList)(l1.clone());
161 assertEquals(l1, l2);
162 l1.clear();
163 assertFalse(l1.equals(l2));
164 }
165
166 /**
167 * contains is true for added elements
168 */
169 public void testContains() {
170 List list = populatedList(3);
171 assertTrue(list.contains(one));
172 assertFalse(list.contains(five));
173 }
174
175 /**
176 * adding at an index places it in the indicated index
177 */
178 public void testAddIndex() {
179 List list = populatedList(3);
180 list.add(0, m1);
181 assertEquals(4, list.size());
182 assertEquals(m1, list.get(0));
183 assertEquals(zero, list.get(1));
184
185 list.add(2, m2);
186 assertEquals(5, list.size());
187 assertEquals(m2, list.get(2));
188 assertEquals(two, list.get(4));
189 }
190
191 /**
192 * lists with same elements are equal and have same hashCode
193 */
194 public void testEquals() {
195 List a = populatedList(3);
196 List b = populatedList(3);
197 assertTrue(a.equals(b));
198 assertTrue(b.equals(a));
199 assertTrue(a.containsAll(b));
200 assertTrue(b.containsAll(a));
201 assertEquals(a.hashCode(), b.hashCode());
202 a.add(m1);
203 assertFalse(a.equals(b));
204 assertFalse(b.equals(a));
205 assertTrue(a.containsAll(b));
206 assertFalse(b.containsAll(a));
207 b.add(m1);
208 assertTrue(a.equals(b));
209 assertTrue(b.equals(a));
210 assertTrue(a.containsAll(b));
211 assertTrue(b.containsAll(a));
212 assertEquals(a.hashCode(), b.hashCode());
213
214 assertFalse(a.equals(null));
215 }
216
217 /**
218 * containsAll returns true for collections with subset of elements
219 */
220 public void testContainsAll() {
221 List list = populatedList(3);
222 assertTrue(list.containsAll(Arrays.asList()));
223 assertTrue(list.containsAll(Arrays.asList(one)));
224 assertTrue(list.containsAll(Arrays.asList(one, two)));
225 assertFalse(list.containsAll(Arrays.asList(one, two, six)));
226 assertFalse(list.containsAll(Arrays.asList(six)));
227
228 try {
229 list.containsAll(null);
230 shouldThrow();
231 } catch (NullPointerException success) {}
232 }
233
234 /**
235 * get returns the value at the given index
236 */
237 public void testGet() {
238 List list = populatedList(3);
239 assertEquals(0, list.get(0));
240 }
241
242 /**
243 * indexOf(Object) returns the index of the first occurrence of the
244 * specified element in this list, or -1 if this list does not
245 * contain the element
246 */
247 public void testIndexOf() {
248 List list = populatedList(3);
249 assertEquals(-1, list.indexOf(-42));
250 int size = list.size();
251 for (int i = 0; i < size; i++) {
252 assertEquals(i, list.indexOf(i));
253 assertEquals(i, list.subList(0, size).indexOf(i));
254 assertEquals(i, list.subList(0, i + 1).indexOf(i));
255 assertEquals(-1, list.subList(0, i).indexOf(i));
256 assertEquals(0, list.subList(i, size).indexOf(i));
257 assertEquals(-1, list.subList(i + 1, size).indexOf(i));
258 }
259
260 list.add(1);
261 assertEquals(1, list.indexOf(1));
262 assertEquals(1, list.subList(0, size + 1).indexOf(1));
263 assertEquals(0, list.subList(1, size + 1).indexOf(1));
264 assertEquals(size - 2, list.subList(2, size + 1).indexOf(1));
265 assertEquals(0, list.subList(size, size + 1).indexOf(1));
266 assertEquals(-1, list.subList(size + 1, size + 1).indexOf(1));
267 }
268
269 /**
270 * indexOf(E, int) returns the index of the first occurrence of the
271 * specified element in this list, searching forwards from index,
272 * or returns -1 if the element is not found
273 */
274 public void testIndexOf2() {
275 CopyOnWriteArrayList list = populatedList(3);
276 int size = list.size();
277 assertEquals(-1, list.indexOf(-42, 0));
278
279 // we might expect IOOBE, but spec says otherwise
280 assertEquals(-1, list.indexOf(0, size));
281 assertEquals(-1, list.indexOf(0, Integer.MAX_VALUE));
282
283 assertThrows(
284 IndexOutOfBoundsException.class,
285 () -> list.indexOf(0, -1),
286 () -> list.indexOf(0, Integer.MIN_VALUE));
287
288 for (int i = 0; i < size; i++) {
289 assertEquals(i, list.indexOf(i, 0));
290 assertEquals(i, list.indexOf(i, i));
291 assertEquals(-1, list.indexOf(i, i + 1));
292 }
293
294 list.add(1);
295 assertEquals(1, list.indexOf(1, 0));
296 assertEquals(1, list.indexOf(1, 1));
297 assertEquals(size, list.indexOf(1, 2));
298 assertEquals(size, list.indexOf(1, size));
299 }
300
301 /**
302 * isEmpty returns true when empty, else false
303 */
304 public void testIsEmpty() {
305 List empty = new CopyOnWriteArrayList();
306 assertTrue(empty.isEmpty());
307 assertTrue(empty.subList(0, 0).isEmpty());
308
309 List full = populatedList(SIZE);
310 assertFalse(full.isEmpty());
311 assertTrue(full.subList(0, 0).isEmpty());
312 assertTrue(full.subList(SIZE, SIZE).isEmpty());
313 }
314
315 /**
316 * iterator() returns an iterator containing the elements of the
317 * list in insertion order
318 */
319 public void testIterator() {
320 Collection empty = new CopyOnWriteArrayList();
321 assertFalse(empty.iterator().hasNext());
322 try {
323 empty.iterator().next();
324 shouldThrow();
325 } catch (NoSuchElementException success) {}
326
327 Integer[] elements = new Integer[SIZE];
328 for (int i = 0; i < SIZE; i++)
329 elements[i] = i;
330 shuffle(elements);
331 Collection<Integer> full = populatedList(elements);
332
333 Iterator it = full.iterator();
334 for (int j = 0; j < SIZE; j++) {
335 assertTrue(it.hasNext());
336 assertEquals(elements[j], it.next());
337 }
338 assertIteratorExhausted(it);
339 }
340
341 /**
342 * iterator of empty collection has no elements
343 */
344 public void testEmptyIterator() {
345 Collection c = new CopyOnWriteArrayList();
346 assertIteratorExhausted(c.iterator());
347 }
348
349 /**
350 * iterator.remove throws UnsupportedOperationException
351 */
352 public void testIteratorRemove() {
353 CopyOnWriteArrayList list = populatedList(SIZE);
354 Iterator it = list.iterator();
355 it.next();
356 try {
357 it.remove();
358 shouldThrow();
359 } catch (UnsupportedOperationException success) {}
360 }
361
362 /**
363 * toString contains toString of elements
364 */
365 public void testToString() {
366 assertEquals("[]", new CopyOnWriteArrayList().toString());
367 List list = populatedList(3);
368 String s = list.toString();
369 for (int i = 0; i < 3; ++i)
370 assertTrue(s.contains(String.valueOf(i)));
371 assertEquals(new ArrayList(list).toString(),
372 list.toString());
373 }
374
375 /**
376 * lastIndexOf(Object) returns the index of the last occurrence of
377 * the specified element in this list, or -1 if this list does not
378 * contain the element
379 */
380 public void testLastIndexOf1() {
381 List list = populatedList(3);
382 assertEquals(-1, list.lastIndexOf(-42));
383 int size = list.size();
384 for (int i = 0; i < size; i++) {
385 assertEquals(i, list.lastIndexOf(i));
386 assertEquals(i, list.subList(0, size).lastIndexOf(i));
387 assertEquals(i, list.subList(0, i + 1).lastIndexOf(i));
388 assertEquals(-1, list.subList(0, i).lastIndexOf(i));
389 assertEquals(0, list.subList(i, size).lastIndexOf(i));
390 assertEquals(-1, list.subList(i + 1, size).lastIndexOf(i));
391 }
392
393 list.add(1);
394 assertEquals(size, list.lastIndexOf(1));
395 assertEquals(size, list.subList(0, size + 1).lastIndexOf(1));
396 assertEquals(1, list.subList(0, size).lastIndexOf(1));
397 assertEquals(0, list.subList(1, 2).lastIndexOf(1));
398 assertEquals(-1, list.subList(0, 1).indexOf(1));
399 }
400
401 /**
402 * lastIndexOf(E, int) returns the index of the last occurrence of the
403 * specified element in this list, searching backwards from index, or
404 * returns -1 if the element is not found
405 */
406 public void testLastIndexOf2() {
407 CopyOnWriteArrayList list = populatedList(3);
408
409 // we might expect IOOBE, but spec says otherwise
410 assertEquals(-1, list.lastIndexOf(0, -1));
411
412 int size = list.size();
413 assertThrows(
414 IndexOutOfBoundsException.class,
415 () -> list.lastIndexOf(0, size),
416 () -> list.lastIndexOf(0, Integer.MAX_VALUE));
417
418 for (int i = 0; i < size; i++) {
419 assertEquals(i, list.lastIndexOf(i, i));
420 assertEquals(list.indexOf(i), list.lastIndexOf(i, i));
421 if (i > 0)
422 assertEquals(-1, list.lastIndexOf(i, i - 1));
423 }
424 list.add(one);
425 list.add(three);
426 assertEquals(1, list.lastIndexOf(one, 1));
427 assertEquals(1, list.lastIndexOf(one, 2));
428 assertEquals(3, list.lastIndexOf(one, 3));
429 assertEquals(3, list.lastIndexOf(one, 4));
430 assertEquals(-1, list.lastIndexOf(three, 3));
431 }
432
433 /**
434 * listIterator traverses all elements
435 */
436 public void testListIterator1() {
437 List list = populatedList(SIZE);
438 ListIterator i = list.listIterator();
439 int j;
440 for (j = 0; i.hasNext(); j++)
441 assertEquals(j, i.next());
442 assertEquals(SIZE, j);
443 }
444
445 /**
446 * listIterator only returns those elements after the given index
447 */
448 public void testListIterator2() {
449 List list = populatedList(3);
450 ListIterator i = list.listIterator(1);
451 int j;
452 for (j = 0; i.hasNext(); j++)
453 assertEquals(j + 1, i.next());
454 assertEquals(2, j);
455 }
456
457 /**
458 * remove(int) removes and returns the object at the given index
459 */
460 public void testRemove_int() {
461 int SIZE = 3;
462 for (int i = 0; i < SIZE; i++) {
463 List list = populatedList(SIZE);
464 assertEquals(i, list.remove(i));
465 assertEquals(SIZE - 1, list.size());
466 assertFalse(list.contains(new Integer(i)));
467 }
468 }
469
470 /**
471 * remove(Object) removes the object if found and returns true
472 */
473 public void testRemove_Object() {
474 int SIZE = 3;
475 for (int i = 0; i < SIZE; i++) {
476 List list = populatedList(SIZE);
477 assertFalse(list.remove(new Integer(-42)));
478 assertTrue(list.remove(new Integer(i)));
479 assertEquals(SIZE - 1, list.size());
480 assertFalse(list.contains(new Integer(i)));
481 }
482 CopyOnWriteArrayList x = new CopyOnWriteArrayList(Arrays.asList(4, 5, 6));
483 assertTrue(x.remove(new Integer(6)));
484 assertEquals(x, Arrays.asList(4, 5));
485 assertTrue(x.remove(new Integer(4)));
486 assertEquals(x, Arrays.asList(5));
487 assertTrue(x.remove(new Integer(5)));
488 assertEquals(x, Arrays.asList());
489 assertFalse(x.remove(new Integer(5)));
490 }
491
492 /**
493 * removeAll removes all elements from the given collection
494 */
495 public void testRemoveAll() {
496 List list = populatedList(3);
497 assertTrue(list.removeAll(Arrays.asList(one, two)));
498 assertEquals(1, list.size());
499 assertFalse(list.removeAll(Arrays.asList(one, two)));
500 assertEquals(1, list.size());
501 }
502
503 /**
504 * set changes the element at the given index
505 */
506 public void testSet() {
507 List list = populatedList(3);
508 assertEquals(2, list.set(2, four));
509 assertEquals(4, list.get(2));
510 }
511
512 /**
513 * size returns the number of elements
514 */
515 public void testSize() {
516 List empty = new CopyOnWriteArrayList();
517 assertEquals(0, empty.size());
518 assertEquals(0, empty.subList(0, 0).size());
519
520 List full = populatedList(SIZE);
521 assertEquals(SIZE, full.size());
522 assertEquals(0, full.subList(0, 0).size());
523 assertEquals(0, full.subList(SIZE, SIZE).size());
524 }
525
526 /**
527 * toArray() returns an Object array containing all elements from
528 * the list in insertion order
529 */
530 public void testToArray() {
531 Object[] a = new CopyOnWriteArrayList().toArray();
532 assertTrue(Arrays.equals(new Object[0], a));
533 assertSame(Object[].class, a.getClass());
534
535 Integer[] elements = new Integer[SIZE];
536 for (int i = 0; i < SIZE; i++)
537 elements[i] = i;
538 shuffle(elements);
539 Collection<Integer> full = populatedList(elements);
540
541 assertTrue(Arrays.equals(elements, full.toArray()));
542 assertSame(Object[].class, full.toArray().getClass());
543 }
544
545 /**
546 * toArray(Integer array) returns an Integer array containing all
547 * elements from the list in insertion order
548 */
549 public void testToArray2() {
550 Collection empty = new CopyOnWriteArrayList();
551 Integer[] a;
552
553 a = new Integer[0];
554 assertSame(a, empty.toArray(a));
555
556 a = new Integer[SIZE / 2];
557 Arrays.fill(a, 42);
558 assertSame(a, empty.toArray(a));
559 assertNull(a[0]);
560 for (int i = 1; i < a.length; i++)
561 assertEquals(42, (int) a[i]);
562
563 Integer[] elements = new Integer[SIZE];
564 for (int i = 0; i < SIZE; i++)
565 elements[i] = i;
566 shuffle(elements);
567 Collection<Integer> full = populatedList(elements);
568
569 Arrays.fill(a, 42);
570 assertTrue(Arrays.equals(elements, full.toArray(a)));
571 for (int i = 0; i < a.length; i++)
572 assertEquals(42, (int) a[i]);
573 assertSame(Integer[].class, full.toArray(a).getClass());
574
575 a = new Integer[SIZE];
576 Arrays.fill(a, 42);
577 assertSame(a, full.toArray(a));
578 assertTrue(Arrays.equals(elements, a));
579
580 a = new Integer[2 * SIZE];
581 Arrays.fill(a, 42);
582 assertSame(a, full.toArray(a));
583 assertTrue(Arrays.equals(elements, Arrays.copyOf(a, SIZE)));
584 assertNull(a[SIZE]);
585 for (int i = SIZE + 1; i < a.length; i++)
586 assertEquals(42, (int) a[i]);
587 }
588
589 /**
590 * sublists contains elements at indexes offset from their base
591 */
592 public void testSubList() {
593 List a = populatedList(10);
594 assertTrue(a.subList(1,1).isEmpty());
595 for (int j = 0; j < 9; ++j) {
596 for (int i = j ; i < 10; ++i) {
597 List b = a.subList(j,i);
598 for (int k = j; k < i; ++k) {
599 assertEquals(new Integer(k), b.get(k-j));
600 }
601 }
602 }
603
604 List s = a.subList(2, 5);
605 assertEquals(3, s.size());
606 s.set(2, m1);
607 assertEquals(a.get(4), m1);
608 s.clear();
609 assertEquals(7, a.size());
610
611 assertThrows(
612 IndexOutOfBoundsException.class,
613 () -> s.get(0),
614 () -> s.set(0, 42));
615 }
616
617 // Exception tests
618
619 /**
620 * toArray throws an ArrayStoreException when the given array
621 * can not store the objects inside the list
622 */
623 public void testToArray_ArrayStoreException() {
624 List list = new CopyOnWriteArrayList();
625 // Integers are not auto-converted to Longs
626 list.add(86);
627 list.add(99);
628 assertThrows(
629 ArrayStoreException.class,
630 () -> list.toArray(new Long[0]),
631 () -> list.toArray(new Long[5]));
632 }
633
634 void testIndexOutOfBoundsException(List list) {
635 int size = list.size();
636 assertThrows(
637 IndexOutOfBoundsException.class,
638 () -> list.get(-1),
639 () -> list.get(size),
640 () -> list.set(-1, "qwerty"),
641 () -> list.set(size, "qwerty"),
642 () -> list.add(-1, "qwerty"),
643 () -> list.add(size + 1, "qwerty"),
644 () -> list.remove(-1),
645 () -> list.remove(size),
646 () -> list.addAll(-1, Collections.emptyList()),
647 () -> list.addAll(size + 1, Collections.emptyList()),
648 () -> list.listIterator(-1),
649 () -> list.listIterator(size + 1),
650 () -> list.subList(-1, size),
651 () -> list.subList(0, size + 1));
652
653 // Conversely, operations that must not throw
654 list.addAll(0, Collections.emptyList());
655 list.addAll(size, Collections.emptyList());
656 list.add(0, "qwerty");
657 list.add(list.size(), "qwerty");
658 list.get(0);
659 list.get(list.size() - 1);
660 list.set(0, "azerty");
661 list.set(list.size() - 1, "azerty");
662 list.listIterator(0);
663 list.listIterator(list.size());
664 list.subList(0, list.size());
665 list.remove(list.size() - 1);
666 }
667
668 /**
669 * IndexOutOfBoundsException is thrown when specified
670 */
671 public void testIndexOutOfBoundsException() {
672 ThreadLocalRandom rnd = ThreadLocalRandom.current();
673 List x = populatedList(rnd.nextInt(5));
674 testIndexOutOfBoundsException(x);
675
676 int start = rnd.nextInt(x.size() + 1);
677 int end = rnd.nextInt(start, x.size() + 1);
678 assertThrows(
679 IndexOutOfBoundsException.class,
680 () -> x.subList(start, start - 1));
681 List subList = x.subList(start, end);
682 testIndexOutOfBoundsException(x);
683 }
684
685 /**
686 * a deserialized/reserialized list equals original
687 */
688 public void testSerialization() throws Exception {
689 List x = populatedList(SIZE);
690 List y = serialClone(x);
691
692 assertNotSame(x, y);
693 assertEquals(x.size(), y.size());
694 assertEquals(x.toString(), y.toString());
695 assertTrue(Arrays.equals(x.toArray(), y.toArray()));
696 assertEquals(x, y);
697 assertEquals(y, x);
698 while (!x.isEmpty()) {
699 assertFalse(y.isEmpty());
700 assertEquals(x.remove(0), y.remove(0));
701 }
702 assertTrue(y.isEmpty());
703 }
704
705 }